Index: lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCasts.cpp +++ lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -463,6 +463,31 @@ return BinaryOperator::Create(LogicOp->getOpcode(), NarrowOp0, NarrowC); } +static Instruction *shrinkShuffle(TruncInst &Trunc, + InstCombiner::BuilderTy &Builder) { + auto *Shuf = dyn_cast(Trunc.getOperand(0)); + if (!Shuf || !Shuf->hasOneUse()) + return nullptr; + + Type *DestTy = Trunc.getType(); + if (auto *C = dyn_cast(Shuf->getOperand(1))) { + // trunc (shuffle X, C, Mask) --> shuffle (trunc X), C', Mask + Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy); + Value *NarrowOp = Builder.CreateTrunc(Shuf->getOperand(0), DestTy); + return new ShuffleVectorInst(NarrowOp, NarrowC, Shuf->getMask()); + } + // TODO: Canonicalize constant to operand 1, so we don't need to match this + // pattern? + if (auto *C = dyn_cast(Shuf->getOperand(0))) { + // trunc (shuffle C, X, Mask) --> shuffle C', (trunc X), Mask + Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy); + Value *NarrowOp = Builder.CreateTrunc(Shuf->getOperand(1), DestTy); + return new ShuffleVectorInst(NarrowC, NarrowOp, Shuf->getMask()); + } + + return nullptr; +} + Instruction *InstCombiner::visitTrunc(TruncInst &CI) { if (Instruction *Result = commonCastTransforms(CI)) return Result; @@ -554,6 +579,9 @@ if (Instruction *I = shrinkBitwiseLogic(CI)) return I; + if (Instruction *I = shrinkShuffle(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 Index: test/Transforms/InstCombine/trunc.ll =================================================================== --- test/Transforms/InstCombine/trunc.ll +++ test/Transforms/InstCombine/trunc.ll @@ -468,8 +468,8 @@ define <4 x i8> @shuf1(<4 x i32> %x) { ; CHECK-LABEL: @shuf1( -; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> %x, <4 x i32> , <4 x i32> -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <4 x i32> [[SHUF]] to <4 x i8> +; CHECK-NEXT: [[TMP1:%.*]] = trunc <4 x i32> %x to <4 x i8> +; CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> , <4 x i32> ; CHECK-NEXT: ret <4 x i8> [[TRUNC]] ; %shuf = shufflevector <4 x i32> %x, <4 x i32> , <4 x i32> @@ -482,8 +482,8 @@ define <4 x i8> @shuf2(<4 x i32> %x) { ; CHECK-LABEL: @shuf2( -; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> , <4 x i32> %x, <4 x i32> -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <4 x i32> [[SHUF]] to <4 x i8> +; CHECK-NEXT: [[TMP1:%.*]] = trunc <4 x i32> %x to <4 x i8> +; CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <4 x i8> , <4 x i8> [[TMP1]], <4 x i32> ; CHECK-NEXT: ret <4 x i8> [[TRUNC]] ; %shuf = shufflevector <4 x i32> , <4 x i32> %x, <4 x i32>