diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -7191,6 +7191,28 @@ return false; } + if (FreezeInst *FI = dyn_cast(I)) { + // br(freeze(icmp a, const)) -> br(icmp (freeze a), const) + // This helps generate efficient conditional jumps. + bool AllUsesAreBr = llvm::all_of( + FI->users(), [](const User *U) { return isa(U); }); + auto II = dyn_cast(FI->getOperand(0)); + if (AllUsesAreBr && II && II->hasOneUse()) { + auto Op0 = II->getOperand(0), Op1 = II->getOperand(1); + bool Const0 = isa(Op0), Const1 = isa(Op1); + if (Const0 || Const1) { + FI->replaceAllUsesWith(II); + FI->eraseFromParent(); + if (!Const0 || !Const1) { + Instruction *F = new FreezeInst(Const0 ? Op1 : Op0, "fr", II); + II->setOperand(Const0 ? 1 : 0, F); + } + return true; + } + } + return false; + } + if (tryToSinkFreeOperands(I)) return true; diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/freeze-icmp.ll b/llvm/test/Transforms/CodeGenPrepare/X86/freeze-icmp.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/CodeGenPrepare/X86/freeze-icmp.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -codegenprepare < %s | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" + +define void @f(i32 %a) { +; CHECK-LABEL: @f( +; CHECK-NEXT: [[FR:%.*]] = freeze i32 [[A:%.*]] +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[FR]], 0 +; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] +; CHECK: A: +; CHECK-NEXT: call void @g1() +; CHECK-NEXT: ret void +; CHECK: B: +; CHECK-NEXT: call void @g2() +; CHECK-NEXT: ret void +; + %c = icmp eq i32 %a, 0 + %fr = freeze i1 %c + br i1 %fr, label %A, label %B +A: + call void @g1() + ret void +B: + call void @g2() + ret void +} + +declare void @g1() +declare void @g2()