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 @@ -3387,6 +3387,34 @@ return NV; } + if (match(Op0, m_Undef())) { + // If I is freeze(undef), see its uses and fold it to the best constant. + // - or: pick -1 + // - select's condition: pick the value that leads to choosing a constant + // - other ops: pick 0 + Constant *BestValue = nullptr; + Constant *NullValue = Constant::getNullValue(I.getType()); + for (const auto *U : I.users()) { + Constant *C = NullValue; + + if (match(U, m_Or(m_Value(), m_Value()))) + C = Constant::getAllOnesValue(I.getType()); + else if (const auto *SI = dyn_cast(U)) { + if (SI->getCondition() == &I) { + APInt CondVal(1, isa(SI->getFalseValue()) ? 0 : 1); + C = Constant::getIntegerValue(I.getType(), CondVal); + } + } + + if (!BestValue) + BestValue = C; + else if (BestValue != C) + BestValue = NullValue; + } + + return replaceInstUsesWith(I, BestValue); + } + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/freeze-phi.ll b/llvm/test/Transforms/InstCombine/freeze-phi.ll --- a/llvm/test/Transforms/InstCombine/freeze-phi.ll +++ b/llvm/test/Transforms/InstCombine/freeze-phi.ll @@ -154,14 +154,13 @@ ; CHECK-NEXT: i8 1, label [[C:%.*]] ; CHECK-NEXT: ] ; CHECK: A: -; CHECK-NEXT: [[PHI_FR:%.*]] = freeze i32 undef ; CHECK-NEXT: br label [[D:%.*]] ; CHECK: B: ; CHECK-NEXT: br label [[D]] ; CHECK: C: ; CHECK-NEXT: br label [[D]] ; CHECK: D: -; CHECK-NEXT: [[Y:%.*]] = phi i32 [ [[PHI_FR]], [[A]] ], [ 32, [[B]] ], [ 0, [[C]] ] +; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 0, [[A]] ], [ 32, [[B]] ], [ 0, [[C]] ] ; CHECK-NEXT: ret i32 [[Y]] ; switch i8 %cond, label %A [ diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll --- a/llvm/test/Transforms/InstCombine/freeze.ll +++ b/llvm/test/Transforms/InstCombine/freeze.ll @@ -21,9 +21,7 @@ define i32 @and_freeze_undef(i32 %x) { ; CHECK-LABEL: @and_freeze_undef( -; CHECK-NEXT: [[F:%.*]] = freeze i32 undef -; CHECK-NEXT: [[RES:%.*]] = and i32 [[F]], [[X:%.*]] -; CHECK-NEXT: ret i32 [[RES]] +; CHECK-NEXT: ret i32 0 ; %f = freeze i32 undef %res = and i32 %x, %f @@ -34,10 +32,8 @@ define i32 @and_freeze_undef_multipleuses(i32 %x) { ; CHECK-LABEL: @and_freeze_undef_multipleuses( -; CHECK-NEXT: [[F:%.*]] = freeze i32 undef -; CHECK-NEXT: [[RES:%.*]] = and i32 [[F]], [[X:%.*]] -; CHECK-NEXT: call void @use_i32(i32 [[F]]) -; CHECK-NEXT: ret i32 [[RES]] +; CHECK-NEXT: call void @use_i32(i32 0) +; CHECK-NEXT: ret i32 0 ; %f = freeze i32 undef %res = and i32 %x, %f @@ -47,9 +43,7 @@ define i32 @or_freeze_undef(i32 %x) { ; CHECK-LABEL: @or_freeze_undef( -; CHECK-NEXT: [[F:%.*]] = freeze i32 undef -; CHECK-NEXT: [[RES:%.*]] = or i32 [[F]], [[X:%.*]] -; CHECK-NEXT: ret i32 [[RES]] +; CHECK-NEXT: ret i32 -1 ; %f = freeze i32 undef %res = or i32 %x, %f @@ -58,10 +52,8 @@ define i32 @or_freeze_undef_multipleuses(i32 %x) { ; CHECK-LABEL: @or_freeze_undef_multipleuses( -; CHECK-NEXT: [[F:%.*]] = freeze i32 undef -; CHECK-NEXT: [[RES:%.*]] = or i32 [[F]], [[X:%.*]] -; CHECK-NEXT: call void @use_i32(i32 [[F]]) -; CHECK-NEXT: ret i32 [[RES]] +; CHECK-NEXT: call void @use_i32(i32 0) +; CHECK-NEXT: ret i32 [[X:%.*]] ; %f = freeze i32 undef %res = or i32 %x, %f @@ -73,10 +65,7 @@ define void @or_select_multipleuses(i32 %x, i1 %y) { ; CHECK-LABEL: @or_select_multipleuses( -; CHECK-NEXT: [[F:%.*]] = freeze i1 undef -; CHECK-NEXT: [[A:%.*]] = select i1 [[F]], i32 [[X:%.*]], i32 32 -; CHECK-NEXT: [[B:%.*]] = or i1 [[F]], [[Y:%.*]] -; CHECK-NEXT: call void @use_i32_i1(i32 [[A]], i1 [[B]]) +; CHECK-NEXT: call void @use_i32_i1(i32 32, i1 [[Y:%.*]]) ; CHECK-NEXT: ret void ; %f = freeze i1 undef diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll --- a/llvm/test/Transforms/InstCombine/select.ll +++ b/llvm/test/Transforms/InstCombine/select.ll @@ -2490,9 +2490,7 @@ define i8 @cond_freeze(i8 %x, i8 %y) { ; CHECK-LABEL: @cond_freeze( -; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 undef -; CHECK-NEXT: [[S:%.*]] = select i1 [[COND_FR]], i8 [[X:%.*]], i8 [[Y:%.*]] -; CHECK-NEXT: ret i8 [[S]] +; CHECK-NEXT: ret i8 [[X:%.*]] ; %cond.fr = freeze i1 undef %s = select i1 %cond.fr, i8 %x, i8 %y @@ -2501,9 +2499,7 @@ define i8 @cond_freeze2(i8 %x, i8 %y) { ; CHECK-LABEL: @cond_freeze2( -; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 undef -; CHECK-NEXT: [[S:%.*]] = select i1 [[COND_FR]], i8 [[X:%.*]], i8 1 -; CHECK-NEXT: ret i8 [[S]] +; CHECK-NEXT: ret i8 1 ; %cond.fr = freeze i1 undef %s = select i1 %cond.fr, i8 %x, i8 1 @@ -2512,9 +2508,7 @@ define i8 @cond_freeze3(i8 %x) { ; CHECK-LABEL: @cond_freeze3( -; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 undef -; CHECK-NEXT: [[S:%.*]] = select i1 [[COND_FR]], i8 1, i8 [[X:%.*]] -; CHECK-NEXT: ret i8 [[S]] +; CHECK-NEXT: ret i8 1 ; %cond.fr = freeze i1 undef %s = select i1 %cond.fr, i8 1, i8 %x @@ -2523,9 +2517,7 @@ define <2 x i8> @cond_freeze_vec(<2 x i8> %x) { ; CHECK-LABEL: @cond_freeze_vec( -; CHECK-NEXT: [[COND_FR:%.*]] = freeze <2 x i1> undef -; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[COND_FR]], <2 x i8> , <2 x i8> [[X:%.*]] -; CHECK-NEXT: ret <2 x i8> [[S]] +; CHECK-NEXT: ret <2 x i8> ; %cond.fr = freeze <2 x i1> %s = select <2 x i1> %cond.fr, <2 x i8> , <2 x i8> %x @@ -2536,10 +2528,7 @@ define void @cond_freeze_multipleuses(i8 %x, i8 %y) { ; CHECK-LABEL: @cond_freeze_multipleuses( -; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 undef -; CHECK-NEXT: [[S:%.*]] = select i1 [[COND_FR]], i8 [[X:%.*]], i8 [[Y:%.*]] -; CHECK-NEXT: [[S2:%.*]] = select i1 [[COND_FR]], i8 [[Y]], i8 [[X]] -; CHECK-NEXT: call void @foo2(i8 [[S]], i8 [[S2]]) +; CHECK-NEXT: call void @foo2(i8 [[X:%.*]], i8 [[Y:%.*]]) ; CHECK-NEXT: ret void ; %cond.fr = freeze i1 undef