diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2359,6 +2359,28 @@ return nullptr; } +// Optimize bitcast(insertelt(undef,trunc(X))) --> bitcast(X) +static Value *foldBitCastUndefInsElem(BitCastInst &BitCast, + InstCombiner::BuilderTy &Builder) { + Value *OrigVal; + uint64_t Idx = ~0U; + if (!match(BitCast.getOperand(0), + m_OneUse(m_InsertElt(m_Undef(), m_Trunc(m_Value(OrigVal)), + m_ConstantInt(Idx))))) { + return nullptr; + } + + if (Idx != 0) + return nullptr; + + if (OrigVal->getType()->getScalarSizeInBits() != + BitCast.getType()->getScalarSizeInBits()) { + return nullptr; + } + + return Builder.CreateBitCast(OrigVal, BitCast.getType()); +} + /// Check if all users of CI are StoreInsts. static bool hasStoreUsersOnly(CastInst &CI) { for (User *U : CI.users()) { @@ -2720,6 +2742,9 @@ if (Instruction *I = foldBitCastSelect(CI, Builder)) return I; + if (Value *V = foldBitCastUndefInsElem(CI, Builder)) + return replaceInstUsesWith(CI, V); + if (SrcTy->isPointerTy()) return commonPointerCastTransforms(CI); return commonCastTransforms(CI); diff --git a/llvm/test/Transforms/InstCombine/bitcast.ll b/llvm/test/Transforms/InstCombine/bitcast.ll --- a/llvm/test/Transforms/InstCombine/bitcast.ll +++ b/llvm/test/Transforms/InstCombine/bitcast.ll @@ -571,3 +571,28 @@ %ptr = bitcast <1 x i8*> %ptrvec to i8* ret i8* %ptr } + +define i64 @bitcast_from_undef_insert_elem(i64 %val) { +; CHECK-LABEL: @bitcast_from_undef_insert_elem +; CHECK-SAME: (i64 %[[VAL:.*]]) +; CHECK-NEXT: ret i64 %[[VAL]] +; + %coerce.val.ii = trunc i64 %val to i32 + %coerce.val.vec = insertelement <2 x i32> undef, i32 %coerce.val.ii, i8 0 + %coerce.val.vec.ii = bitcast <2 x i32> %coerce.val.vec to i64 + ret i64 %coerce.val.vec.ii +} + +define i64 @bitcast_from_undef_insert_elem_incompatible_size(i32 %val) { +; CHECK-LABEL: @bitcast_from_undef_insert_elem +; CHECK-SAME: (i32 %[[VAL:.*]]) +; CHECK-NEXT: %[[COERCE:.*]] = trunc i32 %[[VAL]] to i16 +; CHECK-NEXT: %[[VEC:.*]] = insertelement <4 x i16> undef, i16 %[[COERCE]], i8 0 +; CHECK-NEXT: %[[BITCAST:.*]] = bitcast <4 x i16> %[[VEC]] to i64 +; CHECK-NEXT: ret i64 %[[BITCAST]] +; + %coerce.val.ii = trunc i32 %val to i16 + %coerce.val.vec = insertelement <4 x i16> undef, i16 %coerce.val.ii, i8 0 + %coerce.val.vec.ii = bitcast <4 x i16> %coerce.val.vec to i64 + ret i64 %coerce.val.vec.ii +}