Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -4118,6 +4118,11 @@ if (Op0Const && Op1Const) return ConstantFoldShuffleVectorInstruction(Op0Const, Op1Const, Mask); + // A shuffle of a splat is always the splat itself + if (auto Op0Shuf = dyn_cast(Op0)) + if (isa(Op1) && Op0Shuf->getMask()->getSplatValue()) + return Op0; + return nullptr; } Index: test/Transforms/InstSimplify/shufflevector.ll =================================================================== --- test/Transforms/InstSimplify/shufflevector.ll +++ test/Transforms/InstSimplify/shufflevector.ll @@ -4,14 +4,23 @@ define <4 x i32> @splat_operand(<4 x i32> %x) { ; CHECK-LABEL: @splat_operand( ; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer -; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[SPLAT]], <4 x i32> undef, <4 x i32> -; CHECK-NEXT: ret <4 x i32> [[SHUF]] +; CHECK-NEXT: ret <4 x i32> [[SPLAT]] ; %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <4 x i32> ret <4 x i32> %shuf } +define <4 x i32> @splat_operand1(<4 x i32> %x, <4 x i32> %y) { +; CHECK-LABEL: @splat_operand1( +; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> zeroinitializer +; CHECK-NEXT: ret <4 x i32> [[SPLAT]] +; + %splat = shufflevector <4 x i32> %x, <4 x i32> %y, <4 x i32> zeroinitializer + %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <4 x i32> + ret <4 x i32> %shuf +} + define <4 x i32> @undef_mask(<4 x i32> %x) { ; CHECK-LABEL: @undef_mask( ; CHECK-NEXT: ret <4 x i32> undef