static bool getShuffleDemandedElts(const ShuffleVectorInst *Shuf,
const APInt &DemandedElts,
APInt &DemandedLHS, APInt &DemandedRHS) {
- // The length of scalable vectors is unknown at compile time, thus we
- // cannot check their values
- if (isa<ScalableVectorType>(Shuf->getType()))
- return false;
+ if (isa<ScalableVectorType>(Shuf->getType())) {
+ assert(DemandedElts == APInt(1,1));
+ DemandedLHS = DemandedRHS = DemandedElts;
+ return true;
+ }
int NumElts =
cast<FixedVectorType>(Shuf->getOperand(0)->getType())->getNumElements();
static void computeKnownBits(const Value *V, KnownBits &Known, unsigned Depth,
const Query &Q) {
- // FIXME: We currently have no way to represent the DemandedElts of a scalable
- // vector
- if (isa<ScalableVectorType>(V->getType())) {
- Known.resetAll();
- return;
- }
-
+ // Since the number of lanes in a scalable vector is unknown at compile time,
+ // we track one bit which is implicitly broadcast to all lanes. This means
+ // that all lanes in a scalable vector are considered demanded.
auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
APInt DemandedElts =
FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
// Look through a cast from narrow vector elements to wider type.
// Examples: v4i32 -> v2i64, v3i8 -> v24
unsigned SubBitWidth = SrcVecTy->getScalarSizeInBits();
- if (BitWidth % SubBitWidth == 0) {
+ if (BitWidth % SubBitWidth == 0 && !isa<ScalableVectorType>(I->getType())) {
// Known bits are automatically intersected across demanded elements of a
// vector. So for example, if a bit is computed as known zero, it must be
// zero across all demanded elements of the vector.
break;
}
case Instruction::InsertElement: {
+ if (isa<ScalableVectorType>(I->getType())) {
+ Known.resetAll();
+ return;
+ }
const Value *Vec = I->getOperand(0);
const Value *Elt = I->getOperand(1);
auto *CIdx = dyn_cast<ConstantInt>(I->getOperand(2));
/// for all of the demanded elements in the vector specified by DemandedElts.
void computeKnownBits(const Value *V, const APInt &DemandedElts,
KnownBits &Known, unsigned Depth, const Query &Q) {
- if (!DemandedElts || isa<ScalableVectorType>(V->getType())) {
- // No demanded elts or V is a scalable vector, better to assume we don't
- // know anything.
+ if (!DemandedElts) {
+ // No demanded elts, better to assume we don't know anything.
Known.resetAll();
return;
}
"DemandedElt width should equal the fixed vector number of elements");
} else {
assert(DemandedElts == APInt(1, 1) &&
- "DemandedElt width should be 1 for scalars");
+ "DemandedElt width should be 1 for scalars or scalable vectors");
}
Type *ScalarTy = Ty->getScalarType();
// Handle a constant vector by taking the intersection of the known bits of
// each element.
if (const ConstantDataVector *CDV = dyn_cast<ConstantDataVector>(V)) {
+ assert(!isa<ScalableVectorType>(V->getType()));
// We know that CDV must be a vector of integers. Take the intersection of
// each element.
Known.Zero.setAllBits(); Known.One.setAllBits();
}
if (const auto *CV = dyn_cast<ConstantVector>(V)) {
+ assert(!isa<ScalableVectorType>(V->getType()));
// We know that CV must be a vector of integers. Take the intersection of
// each element.
Known.Zero.setAllBits(); Known.One.setAllBits();
define <vscale x 1 x i32> @add_to_or_scalable(<vscale x 1 x i32> %in) {
; CHECK-LABEL: @add_to_or_scalable(
; CHECK-NEXT: [[SHL:%.*]] = shl <vscale x 1 x i32> [[IN:%.*]], shufflevector (<vscale x 1 x i32> insertelement (<vscale x 1 x i32> poison, i32 1, i32 0), <vscale x 1 x i32> poison, <vscale x 1 x i32> zeroinitializer)
-; CHECK-NEXT: [[ADD:%.*]] = add <vscale x 1 x i32> [[SHL]], shufflevector (<vscale x 1 x i32> insertelement (<vscale x 1 x i32> poison, i32 1, i32 0), <vscale x 1 x i32> poison, <vscale x 1 x i32> zeroinitializer)
+; CHECK-NEXT: [[ADD:%.*]] = or <vscale x 1 x i32> [[SHL]], shufflevector (<vscale x 1 x i32> insertelement (<vscale x 1 x i32> poison, i32 1, i32 0), <vscale x 1 x i32> poison, <vscale x 1 x i32> zeroinitializer)
; CHECK-NEXT: ret <vscale x 1 x i32> [[ADD]]
;
%shl = shl <vscale x 1 x i32> %in, shufflevector (<vscale x 1 x i32> insertelement (<vscale x 1 x i32> poison, i32 1, i32 0), <vscale x 1 x i32> poison, <vscale x 1 x i32> zeroinitializer)
define <vscale x 1 x i1> @cttz_knownbits_scalable_vec(<vscale x 1 x i32> %arg) {
; CHECK-LABEL: @cttz_knownbits_scalable_vec(
-; CHECK-NEXT: [[OR:%.*]] = and <vscale x 1 x i32> [[ARG:%.*]], shufflevector (<vscale x 1 x i32> insertelement (<vscale x 1 x i32> poison, i32 27, i32 0), <vscale x 1 x i32> poison, <vscale x 1 x i32> zeroinitializer)
-; CHECK-NEXT: [[RES:%.*]] = icmp eq <vscale x 1 x i32> [[OR]], shufflevector (<vscale x 1 x i32> insertelement (<vscale x 1 x i32> poison, i32 20, i32 0), <vscale x 1 x i32> poison, <vscale x 1 x i32> zeroinitializer)
-; CHECK-NEXT: ret <vscale x 1 x i1> [[RES]]
+; CHECK-NEXT: ret <vscale x 1 x i1> zeroinitializer
;
%or = or <vscale x 1 x i32> %arg, shufflevector (<vscale x 1 x i32> insertelement (<vscale x 1 x i32> poison, i32 4, i32 0), <vscale x 1 x i32> poison, <vscale x 1 x i32> zeroinitializer)
%cnt = call <vscale x 1 x i32> @llvm.cttz.nxv1i32(<vscale x 1 x i32> %or, i1 true) nounwind readnone