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 @@ -4016,6 +4016,9 @@ if (match(Op0, m_Undef())) { for (const auto *U : I.users()) { + // Don't fold freeze(undef/poison) if it's used has the second vector in a shuffle. + // This is necessary for the backend to generate efficient assembly for + // mm*_cast* intel intrinsics. if (match(U, m_Shuffle(m_Value(), m_Specific(&I)))) return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/shufflevector_freezepoison.ll b/llvm/test/Transforms/InstCombine/shufflevector_freezepoison.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/shufflevector_freezepoison.ll @@ -0,0 +1,50 @@ +; RUN: opt -passes='instcombine' -S %s | FileCheck %s + +define <4 x double> @shuffle_op1_freeze_poison(<2 x double> %a) { +; CHECK-LABEL: @shuffle_op1_freeze_poison( +; CHECK-NEXT: call void @use(<2 x double> zeroinitializer) +; CHECK-NEXT: [[SV:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> %{{.*}}, <4 x i32> +; CHECK-NEXT: ret <4 x double> [[SV]] + %b = freeze <2 x double> poison + call void @use(<2 x double> %b) + %shuffle = shufflevector <2 x double> %b, <2 x double> %a, <4 x i32> + ret <4 x double> %shuffle +} + +define <4 x double> @shuffle_op2_freeze_poison(<2 x double> %a) { +; CHECK-LABEL: @shuffle_op2_freeze_poison( +; CHECK-NEXT: [[FR:%.*]] = freeze <2 x double> poison +; CHECK-NEXT: call void @use(<2 x double> [[FR]]) +; CHECK-NEXT: [[SV:%.*]] = shufflevector <2 x double> %{{.*}}, <2 x double> [[FR]], <4 x i32> +; CHECK-NEXT: ret <4 x double> [[SV]] + %b = freeze <2 x double> poison + call void @use(<2 x double> %b) + %shuffle = shufflevector <2 x double> %a, <2 x double> %b, <4 x i32> + ret <4 x double> %shuffle +} + +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: [[SV:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> %{{.*}}, <4 x i32> +; CHECK-NEXT: ret <4 x double> [[SV]] + %b = freeze <2 x double> undef + call void @use(<2 x double> %b) + %shuffle = shufflevector <2 x double> %b, <2 x double> %a, <4 x i32> + ret <4 x double> %shuffle +} + +define <4 x double> @shuffle_op2_freeze_undef(<2 x double> %a) { +; CHECK-LABEL: @shuffle_op2_freeze_undef( +; CHECK-NEXT: [[FR:%.*]] = freeze <2 x double> undef +; CHECK-NEXT: call void @use(<2 x double> [[FR]]) +; CHECK-NEXT: [[SV:%.*]] = shufflevector <2 x double> %{{.*}}, <2 x double> [[FR]], <4 x i32> +; CHECK-NEXT: ret <4 x double> [[SV]] + %b = freeze <2 x double> undef + call void @use(<2 x double> %b) + %shuffle = shufflevector <2 x double> %a, <2 x double> %b, <4 x i32> + ret <4 x double> %shuffle +} + +declare void @use(<2 x double>) +