Index: lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCasts.cpp +++ lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -463,6 +463,41 @@ return BinaryOperator::Create(LogicOp->getOpcode(), NarrowOp0, NarrowC); } +static Instruction *shrinkInsertElt(CastInst &Trunc, + InstCombiner::BuilderTy &Builder) { + Instruction::CastOps Opcode = Trunc.getOpcode(); + assert((Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) && + "Unexpected instruction for shrinking"); + + auto *InsElt = dyn_cast(Trunc.getOperand(0)); + if (!InsElt || !InsElt->hasOneUse()) + return nullptr; + + Type *DestTy = Trunc.getType(); + Type *DestScalarTy = DestTy->getScalarType(); + Value *VecOp = InsElt->getOperand(0); + Value *ScalarOp = InsElt->getOperand(1); + Value *Index = InsElt->getOperand(2); + + if (auto *C = dyn_cast(VecOp)) { + // trunc (inselt C, X, Index) --> inselt C, (trunc X), Index + // fptrunc (inselt C, X, Index) --> inselt C, (fptrunc X), Index + Constant *NarrowC = ConstantExpr::getCast(Opcode, C, DestTy); + Value *NarrowOp = Builder.CreateCast(Opcode, ScalarOp, DestScalarTy); + return InsertElementInst::Create(NarrowC, NarrowOp, Index); + } + + if (auto *C = dyn_cast(ScalarOp)) { + // trunc (inselt X, C, Index) --> inselt (trunc X), C', Index + // fptrunc (inselt X, C, Index) --> inselt (fptrunc X), C', Index + Constant *NarrowC = ConstantExpr::getCast(Opcode, C, DestScalarTy); + Value *NarrowOp = Builder.CreateCast(Opcode, VecOp, DestTy); + return InsertElementInst::Create(NarrowOp, NarrowC, Index); + } + + return nullptr; +} + Instruction *InstCombiner::visitTrunc(TruncInst &CI) { if (Instruction *Result = commonCastTransforms(CI)) return Result; @@ -554,6 +589,9 @@ if (Instruction *I = shrinkBitwiseLogic(CI)) return I; + if (Instruction *I = shrinkInsertElt(CI, *Builder)) + return I; + if (Src->hasOneUse() && isa(SrcTy) && shouldChangeType(SrcTy, DestTy)) { // Transform "trunc (shl X, cst)" -> "shl (trunc X), cst" so long as the @@ -1420,6 +1458,9 @@ } } + if (Instruction *I = shrinkInsertElt(CI, *Builder)) + return I; + return nullptr; } Index: test/Transforms/InstCombine/vector-casts.ll =================================================================== --- test/Transforms/InstCombine/vector-casts.ll +++ test/Transforms/InstCombine/vector-casts.ll @@ -221,8 +221,8 @@ define <3 x i16> @trunc_inselt1(i32 %x) { ; CHECK-LABEL: @trunc_inselt1( -; CHECK-NEXT: [[VEC:%.*]] = insertelement <3 x i32> , i32 %x, i32 1 -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <3 x i32> [[VEC]] to <3 x i16> +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %x to i16 +; CHECK-NEXT: [[TRUNC:%.*]] = insertelement <3 x i16> , i16 [[TMP1]], i32 1 ; CHECK-NEXT: ret <3 x i16> [[TRUNC]] ; %vec = insertelement <3 x i32> , i32 %x, i32 1 @@ -235,8 +235,8 @@ define <2 x float> @fptrunc_inselt1(double %x, i32 %index) { ; CHECK-LABEL: @fptrunc_inselt1( -; CHECK-NEXT: [[VEC:%.*]] = insertelement <2 x double> , double %x, i32 %index -; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc <2 x double> [[VEC]] to <2 x float> +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double %x to float +; CHECK-NEXT: [[TRUNC:%.*]] = insertelement <2 x float> , float [[TMP1]], i32 %index ; CHECK-NEXT: ret <2 x float> [[TRUNC]] ; %vec = insertelement <2 x double> , double %x, i32 %index @@ -249,8 +249,8 @@ define <8 x i16> @trunc_inselt2(<8 x i32> %x, i32 %index) { ; CHECK-LABEL: @trunc_inselt2( -; CHECK-NEXT: [[VEC:%.*]] = insertelement <8 x i32> %x, i32 1048576, i32 %index -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <8 x i32> [[VEC]] to <8 x i16> +; CHECK-NEXT: [[TMP1:%.*]] = trunc <8 x i32> %x to <8 x i16> +; CHECK-NEXT: [[TRUNC:%.*]] = insertelement <8 x i16> [[TMP1]], i16 0, i32 %index ; CHECK-NEXT: ret <8 x i16> [[TRUNC]] ; %vec = insertelement <8 x i32> %x, i32 1048576, i32 %index @@ -263,8 +263,8 @@ define <3 x float> @fptrunc_inselt2(<3 x double> %x) { ; CHECK-LABEL: @fptrunc_inselt2( -; CHECK-NEXT: [[VEC:%.*]] = insertelement <3 x double> %x, double 4.000000e+00, i32 2 -; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc <3 x double> [[VEC]] to <3 x float> +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc <3 x double> %x to <3 x float> +; CHECK-NEXT: [[TRUNC:%.*]] = insertelement <3 x float> [[TMP1]], float 4.000000e+00, i32 2 ; CHECK-NEXT: ret <3 x float> [[TRUNC]] ; %vec = insertelement <3 x double> %x, double 4.0, i32 2