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 @@ -3525,6 +3525,25 @@ return NV; } + // v = load ptr + // freeze(icmp (and v, const), const') + // => + // v = load ptr + // v' = freeze v + // icmp (and v', const), const' + ICmpInst::Predicate Pred; + Value *W; + if (match(Op0, m_ICmp(Pred, m_And(m_Value(W), m_ConstantInt()), + m_ConstantInt()))) { + if (auto *LI = dyn_cast(W)) { + auto *FI = new FreezeInst(LI, LI->getName() + ".fr"); + FI->insertAfter(LI); + LI->replaceUsesWithIf( + FI, [&](Use &U) { return !isa(U.getUser()); }); + return replaceInstUsesWith(I, Op0); + } + } + if (match(Op0, m_Undef())) { // If I is freeze(undef), see its uses and fold it to the best constant. // - or: pick -1 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 @@ -86,3 +86,20 @@ call void @use_i32_i1(i32 %a, i1 %b) ret void } + +; Add freeze immediately after load. It prevents the poison from being propagated. + +define i1 @freeze_icmp_and_load(i32* %ptr) { +; CHECK-LABEL: @freeze_icmp_and_load( +; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[PTR:%.*]], align 4 +; CHECK-NEXT: [[V_FR:%.*]] = freeze i32 [[V]] +; CHECK-NEXT: [[W:%.*]] = and i32 [[V_FR]], 1 +; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[W]], 0 +; CHECK-NEXT: ret i1 [[COND]] +; + %v = load i32, i32* %ptr + %w = and i32 %v, 1 + %cond = icmp eq i32 %w, 0 + %cond.fr = freeze i1 %cond + ret i1 %cond.fr +}