diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3959,6 +3959,17 @@ return Changed; } +// Check if any direct or bitcast user of this value is a shuffle instruction. +static bool isUsedWithinShuffleVector(Value *V) { + for (auto *U : V->users()) { + if (isa(U)) + return true; + else if (match(U, m_BitCast(m_Specific(V))) && isUsedWithinShuffleVector(U)) + return true; + } + return false; +} + Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) { Value *Op0 = I.getOperand(0); @@ -4008,8 +4019,14 @@ return BestValue; }; - if (match(Op0, m_Undef())) + if (match(Op0, m_Undef())) { + // Don't fold freeze(undef/poison) if it's used as a vector operand in + // a shuffle. This may improve codegen for shuffles that allow + // unspecified inputs. + if (isUsedWithinShuffleVector(&I)) + return nullptr; return replaceInstUsesWith(I, getUndefReplacement(I.getType())); + } Constant *C; if (match(Op0, m_Constant(C)) && C->containsUndefOrPoisonElement()) { diff --git a/llvm/test/Transforms/InstCombine/shufflevector_freezepoison.ll b/llvm/test/Transforms/InstCombine/shufflevector_freezepoison.ll --- a/llvm/test/Transforms/InstCombine/shufflevector_freezepoison.ll +++ b/llvm/test/Transforms/InstCombine/shufflevector_freezepoison.ll @@ -4,7 +4,8 @@ define <4 x double> @shuffle_op0_freeze_poison(<2 x double> %a) { ; CHECK-LABEL: @shuffle_op0_freeze_poison( -; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[A:%.*]], <4 x i32> +; CHECK-NEXT: [[B:%.*]] = freeze <2 x double> poison +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[B]], <2 x double> [[A:%.*]], <4 x i32> ; CHECK-NEXT: ret <4 x double> [[SHUFFLE]] ; %b = freeze <2 x double> poison @@ -14,7 +15,8 @@ define <4 x double> @shuffle_op1_freeze_poison(<2 x double> %a) { ; CHECK-LABEL: @shuffle_op1_freeze_poison( -; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> zeroinitializer, <4 x i32> +; CHECK-NEXT: [[B:%.*]] = freeze <2 x double> poison +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> [[B]], <4 x i32> ; CHECK-NEXT: ret <4 x double> [[SHUFFLE]] ; %b = freeze <2 x double> poison @@ -24,8 +26,9 @@ define <4 x double> @shuffle_op0_freeze_poison_use(<2 x double> %a) { ; CHECK-LABEL: @shuffle_op0_freeze_poison_use( -; CHECK-NEXT: call void @use(<2 x double> zeroinitializer) -; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[A:%.*]], <4 x i32> +; CHECK-NEXT: [[B:%.*]] = freeze <2 x double> poison +; CHECK-NEXT: call void @use(<2 x double> [[B]]) +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[B]], <2 x double> [[A:%.*]], <4 x i32> ; CHECK-NEXT: ret <4 x double> [[SHUFFLE]] ; %b = freeze <2 x double> poison @@ -36,8 +39,9 @@ define <4 x double> @shuffle_op1_freeze_poison_use(<2 x double> %a) { ; CHECK-LABEL: @shuffle_op1_freeze_poison_use( -; CHECK-NEXT: call void @use(<2 x double> zeroinitializer) -; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> zeroinitializer, <4 x i32> +; CHECK-NEXT: [[B:%.*]] = freeze <2 x double> poison +; CHECK-NEXT: call void @use(<2 x double> [[B]]) +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> [[B]], <4 x i32> ; CHECK-NEXT: ret <4 x double> [[SHUFFLE]] ; %b = freeze <2 x double> poison @@ -48,8 +52,9 @@ define <4 x double> @shuffle_op0_freeze_undef(<2 x double> %a) { ; CHECK-LABEL: @shuffle_op0_freeze_undef( -; CHECK-NEXT: call void @use(<2 x double> zeroinitializer) -; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[A:%.*]], <4 x i32> +; CHECK-NEXT: [[B:%.*]] = freeze <2 x double> undef +; CHECK-NEXT: call void @use(<2 x double> [[B]]) +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[B]], <2 x double> [[A:%.*]], <4 x i32> ; CHECK-NEXT: ret <4 x double> [[SHUFFLE]] ; %b = freeze <2 x double> undef @@ -60,8 +65,9 @@ define <4 x double> @shuffle_op1_freeze_undef(<2 x double> %a) { ; CHECK-LABEL: @shuffle_op1_freeze_undef( -; CHECK-NEXT: call void @use(<2 x double> zeroinitializer) -; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> zeroinitializer, <4 x i32> +; CHECK-NEXT: [[B:%.*]] = freeze <2 x double> undef +; CHECK-NEXT: call void @use(<2 x double> [[B]]) +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> [[B]], <4 x i32> ; CHECK-NEXT: ret <4 x double> [[SHUFFLE]] ; %b = freeze <2 x double> undef @@ -70,5 +76,34 @@ ret <4 x double> %shuffle } +define <4 x double> @shuffle_bc1(<2 x double> %a) { +; CHECK-LABEL: @shuffle_bc1( +; CHECK-NEXT: [[B:%.*]] = freeze <4 x float> poison +; CHECK-NEXT: [[B1:%.*]] = bitcast <4 x float> [[B]] to <2 x double> +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> [[B1]], <4 x i32> +; CHECK-NEXT: ret <4 x double> [[SHUFFLE]] +; + %b = freeze <4 x float> poison + %b1 = bitcast <4 x float> %b to <2 x double> + %shuffle = shufflevector <2 x double> %a, <2 x double> %b1, <4 x i32> + ret <4 x double> %shuffle +} + +define <8 x float> @shuffle_bc2(<4 x float> %a) { +; CHECK-LABEL: @shuffle_bc2( +; CHECK-NEXT: [[B:%.*]] = freeze <4 x float> poison +; CHECK-NEXT: [[B1:%.*]] = bitcast <4 x float> [[B]] to <2 x double> +; CHECK-NEXT: call void @use(<2 x double> [[B1]]) +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x float> [[A:%.*]], <4 x float> [[B]], <8 x i32> +; CHECK-NEXT: ret <8 x float> [[SHUFFLE]] +; + %b = freeze <4 x float> poison + %b1 = bitcast <4 x float> %b to <2 x double> + call void @use(<2 x double> %b1) + %b2 = bitcast <2 x double> %b1 to <4 x float> + %shuffle = shufflevector <4 x float> %a, <4 x float> %b2, <8 x i32> + ret <8 x float> %shuffle +} + declare void @use(<2 x double>)