diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp --- a/llvm/lib/Analysis/VectorUtils.cpp +++ b/llvm/lib/Analysis/VectorUtils.cpp @@ -301,16 +301,18 @@ } ShuffleVectorInst *SVI = dyn_cast(V); - // Restrict the following transformation to fixed-length vector. - if (SVI && isa(SVI->getType())) { - unsigned LHSWidth = - cast(SVI->getOperand(0)->getType())->getNumElements(); - int InEl = SVI->getMaskValue(EltNo); - if (InEl < 0) - return UndefValue::get(VTy->getElementType()); - if (InEl < (int)LHSWidth) - return findScalarElement(SVI->getOperand(0), InEl); - return findScalarElement(SVI->getOperand(1), InEl - LHSWidth); + if (SVI && isa(SVI->getType())) { + ElementCount LHS = + cast(SVI->getOperand(0)->getType())->getElementCount(); + unsigned LHSWidth = LHS.getKnownMinValue(); + if ((EltNo < LHSWidth && LHS.isScalable()) || !LHS.isScalable()) { + int InEl = SVI->getMaskValue(EltNo); + if (InEl < 0) + return UndefValue::get(VTy->getElementType()); + if (InEl < (int)LHSWidth) + return findScalarElement(SVI->getOperand(0), InEl); + return findScalarElement(SVI->getOperand(1), InEl - LHSWidth); + } } // Extract a value from a vector add operation with a constant zero. diff --git a/llvm/test/Transforms/InstCombine/vscale_extractelement-inseltpoison.ll b/llvm/test/Transforms/InstCombine/vscale_extractelement-inseltpoison.ll --- a/llvm/test/Transforms/InstCombine/vscale_extractelement-inseltpoison.ll +++ b/llvm/test/Transforms/InstCombine/vscale_extractelement-inseltpoison.ll @@ -55,13 +55,9 @@ ret i8 %r } -; TODO: Instcombine could optimize to return %v. define i32 @extractelement_shuffle_in_range(i32 %v) { ; CHECK-LABEL: @extractelement_shuffle_in_range( -; CHECK-NEXT: [[IN:%.*]] = insertelement poison, i32 [[V:%.*]], i32 0 -; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector [[IN]], poison, zeroinitializer -; CHECK-NEXT: [[R:%.*]] = extractelement [[SPLAT]], i32 1 -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: ret i32 %v ; %in = insertelement poison, i32 %v, i32 0 %splat = shufflevector %in, poison, zeroinitializer diff --git a/llvm/test/Transforms/InstCombine/vscale_extractelement.ll b/llvm/test/Transforms/InstCombine/vscale_extractelement.ll --- a/llvm/test/Transforms/InstCombine/vscale_extractelement.ll +++ b/llvm/test/Transforms/InstCombine/vscale_extractelement.ll @@ -55,13 +55,9 @@ ret i8 %r } -; TODO: Instcombine could optimize to return %v. define i32 @extractelement_shuffle_in_range(i32 %v) { ; CHECK-LABEL: @extractelement_shuffle_in_range( -; CHECK-NEXT: [[IN:%.*]] = insertelement undef, i32 [[V:%.*]], i32 0 -; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector [[IN]], undef, zeroinitializer -; CHECK-NEXT: [[R:%.*]] = extractelement [[SPLAT]], i32 1 -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: ret i32 %v ; %in = insertelement undef, i32 %v, i32 0 %splat = shufflevector %in, undef, zeroinitializer