diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -228,8 +228,9 @@ // truncate a subset of scalar bits of an insert op. if (NumSrcElts.getKnownMinValue() < NumElts.getKnownMinValue()) { Value *Scalar; + Value *Vec; uint64_t InsIndexC; - if (!match(X, m_InsertElt(m_Value(), m_Value(Scalar), + if (!match(X, m_InsertElt(m_Value(Vec), m_Value(Scalar), m_ConstantInt(InsIndexC)))) return nullptr; @@ -239,8 +240,17 @@ // of elements 4-7 of the bitcasted vector. unsigned NarrowingRatio = NumElts.getKnownMinValue() / NumSrcElts.getKnownMinValue(); - if (ExtIndexC / NarrowingRatio != InsIndexC) + + if (ExtIndexC / NarrowingRatio != InsIndexC) { + // Remove insertelement, if we don't use the inserted element. + // extractelement (bitcast (insertelement (Vec, b)), a) -> + // extractelement (bitcast (Vec), a) + if (X->hasOneUse() && Ext.getVectorOperand()->hasOneUse()) { + Value *NewBC = Builder.CreateBitCast(Vec, Ext.getVectorOperandType()); + return ExtractElementInst::Create(NewBC, Ext.getIndexOperand()); + } return nullptr; + } // We are extracting part of the original scalar. How that scalar is // inserted into the vector depends on the endian-ness. Example: 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 @@ -41,12 +41,10 @@ ret i8 %r } -; TODO: Instcombine could remove the insert. define i8 @extractelement_bitcast_wrong_insert( %a, i32 %x) { ; CHECK-LABEL: @extractelement_bitcast_wrong_insert( -; CHECK-NEXT: [[VEC:%.*]] = insertelement [[A:%.*]], i32 [[X:%.*]], i64 1 -; CHECK-NEXT: [[VEC_CAST:%.*]] = bitcast [[VEC]] to -; CHECK-NEXT: [[R:%.*]] = extractelement [[VEC_CAST]], i64 2 +; CHECK-NEXT: [[TMP1:%.*]] = bitcast [[A:%.*]] to +; CHECK-NEXT: [[R:%.*]] = extractelement [[TMP1]], i64 2 ; CHECK-NEXT: ret i8 [[R]] ; %vec = insertelement %a, i32 %x, i32 1 ; <- This insert could be removed. 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 @@ -41,12 +41,10 @@ ret i8 %r } -; TODO: Instcombine could remove the insert. define i8 @extractelement_bitcast_wrong_insert( %a, i32 %x) { ; CHECK-LABEL: @extractelement_bitcast_wrong_insert( -; CHECK-NEXT: [[VEC:%.*]] = insertelement [[A:%.*]], i32 [[X:%.*]], i64 1 -; CHECK-NEXT: [[VEC_CAST:%.*]] = bitcast [[VEC]] to -; CHECK-NEXT: [[R:%.*]] = extractelement [[VEC_CAST]], i64 2 +; CHECK-NEXT: [[TMP1:%.*]] = bitcast [[A:%.*]] to +; CHECK-NEXT: [[R:%.*]] = extractelement [[TMP1]], i64 2 ; CHECK-NEXT: ret i8 [[R]] ; %vec = insertelement %a, i32 %x, i32 1 ; <- This insert could be removed.