[llvm] a290bf9 - [SimplifyCFG] Remove conservative fcmp guard from speculativelyExecuteBB (#211611)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 28 05:55:19 PDT 2026


Author: Guy David
Date: 2026-08-28T15:55:14+03:00
New Revision: a290bf939154bbbed3c00598ff29845f958317bf

URL: https://github.com/llvm/llvm-project/commit/a290bf939154bbbed3c00598ff29845f958317bf
DIFF: https://github.com/llvm/llvm-project/commit/a290bf939154bbbed3c00598ff29845f958317bf.diff

LOG: [SimplifyCFG] Remove conservative fcmp guard from speculativelyExecuteBB (#211611)

Previously it rejected to perform if conversion when the condition was
an FCmpInst. That guard predated the current cost model which now takes
into consideration target-dependent knobs such as getCmpSelInstrCost()
via validateAndCostRequiredSelects.
    
Also propagate fast-math flags from the phi to the replacement select
using CreateSelectFMF instead of CreateSelect (which technically works
but I am not sure whether it's intended to be used for both types of
selects).

Added: 
    llvm/test/Transforms/SimplifyCFG/X86/fcmp-branch-phi-to-select.ll
    llvm/test/Transforms/SimplifyCFG/fcmp-branch-phi-to-select.ll

Modified: 
    llvm/lib/Transforms/Utils/SimplifyCFG.cpp
    llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-phis.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 2f9a4819f9984..c5fb8eebdc734 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3239,11 +3239,6 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(CondBrInst *BI,
   if (!Options.SpeculateBlocks)
     return false;
 
-  // Be conservative for now. FP select instruction can often be expensive.
-  Value *BrCond = BI->getCondition();
-  if (isa<FCmpInst>(BrCond))
-    return false;
-
   BasicBlock *BB = BI->getParent();
   BasicBlock *EndBB = ThenBB->getTerminator()->getSuccessor(0);
   InstructionCost Budget =
@@ -3361,6 +3356,7 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(CondBrInst *BI,
   LLVM_DEBUG(dbgs() << "SPECULATIVELY EXECUTING BB" << *ThenBB << "\n";);
 
   Instruction *Sel = nullptr;
+  Value *BrCond = BI->getCondition();
   // Insert a select of the value of the speculated store.
   if (SpeculatedStoreValue) {
     IRBuilder<NoFolder> Builder(BI);
@@ -3459,7 +3455,9 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(CondBrInst *BI,
     Value *TrueV = ThenV, *FalseV = OrigV;
     if (Invert)
       std::swap(TrueV, FalseV);
-    Value *V = Builder.CreateSelect(BrCond, TrueV, FalseV, "spec.select", BI);
+    // Propagate fast-math flags from the phi node to the replacement select.
+    Value *V = Builder.CreateSelectFMF(
+        BrCond, TrueV, FalseV, PN.getFastMathFlagsOrNone(), "spec.select", BI);
     PN.setIncomingValue(OrigI, V);
     PN.setIncomingValue(ThenI, V);
   }

diff  --git a/llvm/test/Transforms/SimplifyCFG/X86/fcmp-branch-phi-to-select.ll b/llvm/test/Transforms/SimplifyCFG/X86/fcmp-branch-phi-to-select.ll
new file mode 100644
index 0000000000000..4cf5913aba769
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/X86/fcmp-branch-phi-to-select.ll
@@ -0,0 +1,59 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -mtriple=x86_64-unknown-linux-gnu -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
+
+define double @no_fold_expensive_fp_select(double %x, double %scale, i1 %other) {
+; CHECK-LABEL: define double @no_fold_expensive_fp_select(
+; CHECK-SAME: double [[X:%.*]], double [[SCALE:%.*]], i1 [[OTHER:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[OTHER]], label %[[MERGE:.*]], label %[[CHECK:.*]]
+; CHECK:       [[CHECK]]:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt double [[X]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[CMP]], label %[[THEN:.*]], label %[[MERGE]]
+; CHECK:       [[THEN]]:
+; CHECK-NEXT:    [[SCALED:%.*]] = fmul double [[X]], [[SCALE]]
+; CHECK-NEXT:    br label %[[MERGE]]
+; CHECK:       [[MERGE]]:
+; CHECK-NEXT:    [[R:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[SCALED]], %[[THEN]] ], [ 1.000000e+00, %[[CHECK]] ]
+; CHECK-NEXT:    ret double [[R]]
+;
+entry:
+  br i1 %other, label %merge, label %check
+
+check:
+  %cmp = fcmp ogt double %x, 0.0
+  br i1 %cmp, label %then, label %merge
+
+then:
+  %scaled = fmul double %x, %scale
+  br label %merge
+
+merge:
+  %r = phi double [ 0.0, %entry ], [ %scaled, %then ], [ 1.0, %check ]
+  ret double %r
+}
+
+define i64 @fold_cheap_int_select(double %x, i64 %a, i64 %b, i1 %other) {
+; CHECK-LABEL: define i64 @fold_cheap_int_select(
+; CHECK-SAME: double [[X:%.*]], i64 [[A:%.*]], i64 [[B:%.*]], i1 [[OTHER:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt double [[X]], 0.000000e+00
+; CHECK-NEXT:    [[SCALED:%.*]] = mul i64 [[A]], [[B]]
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i64 [[SCALED]], i64 1
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[OTHER]], i64 0, i64 [[SPEC_SELECT]]
+; CHECK-NEXT:    ret i64 [[R]]
+;
+entry:
+  br i1 %other, label %merge, label %check
+
+check:
+  %cmp = fcmp ogt double %x, 0.0
+  br i1 %cmp, label %then, label %merge
+
+then:
+  %scaled = mul i64 %a, %b
+  br label %merge
+
+merge:
+  %r = phi i64 [ 0, %entry ], [ %scaled, %then ], [ 1, %check ]
+  ret i64 %r
+}

diff  --git a/llvm/test/Transforms/SimplifyCFG/fcmp-branch-phi-to-select.ll b/llvm/test/Transforms/SimplifyCFG/fcmp-branch-phi-to-select.ll
new file mode 100644
index 0000000000000..43a721c55bb28
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/fcmp-branch-phi-to-select.ll
@@ -0,0 +1,139 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
+
+define float @spec_fcmp_multi_pred(float %x, float %scale, i1 %other) {
+; CHECK-LABEL: define float @spec_fcmp_multi_pred(
+; CHECK-SAME: float [[X:%.*]], float [[SCALE:%.*]], i1 [[OTHER:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[X]], 0.000000e+00
+; CHECK-NEXT:    [[SCALED:%.*]] = fmul float [[X]], [[SCALE]]
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], float [[SCALED]], float 1.000000e+00
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[OTHER]], float 0.000000e+00, float [[SPEC_SELECT]]
+; CHECK-NEXT:    ret float [[R]]
+;
+entry:
+  br i1 %other, label %merge, label %check
+
+check:
+  %cmp = fcmp ogt float %x, 0.0
+  br i1 %cmp, label %then, label %merge
+
+then:
+  %scaled = fmul float %x, %scale
+  br label %merge
+
+merge:
+  %r = phi float [ 0.0, %entry ], [ %scaled, %then ], [ 1.0, %check ]
+  ret float %r
+}
+
+define float @spec_fcmp_multi_pred_fmf(float %x, float %scale, i1 %other) {
+; CHECK-LABEL: define float @spec_fcmp_multi_pred_fmf(
+; CHECK-SAME: float [[X:%.*]], float [[SCALE:%.*]], i1 [[OTHER:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[X]], 0.000000e+00
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[X]], [[SCALE]]
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select nsz i1 [[CMP]], float [[ADD]], float 1.000000e+00
+; CHECK-NEXT:    [[R:%.*]] = select nsz i1 [[OTHER]], float 0.000000e+00, float [[SPEC_SELECT]]
+; CHECK-NEXT:    ret float [[R]]
+;
+entry:
+  br i1 %other, label %merge, label %check
+
+check:
+  %cmp = fcmp ogt float %x, 0.0
+  br i1 %cmp, label %then, label %merge
+
+then:
+  %add = fadd float %x, %scale
+  br label %merge
+
+merge:
+  %r = phi nsz float [ 0.0, %entry ], [ %add, %then ], [ 1.0, %check ]
+  ret float %r
+}
+
+define double @spec_fcmp_double(double %x, double %scale, i1 %other) {
+; CHECK-LABEL: define double @spec_fcmp_double(
+; CHECK-SAME: double [[X:%.*]], double [[SCALE:%.*]], i1 [[OTHER:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt double [[X]], 0.000000e+00
+; CHECK-NEXT:    [[SCALED:%.*]] = fmul double [[X]], [[SCALE]]
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], double [[SCALED]], double 1.000000e+00
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[OTHER]], double 0.000000e+00, double [[SPEC_SELECT]]
+; CHECK-NEXT:    ret double [[R]]
+;
+entry:
+  br i1 %other, label %merge, label %check
+
+check:
+  %cmp = fcmp ogt double %x, 0.0
+  br i1 %cmp, label %then, label %merge
+
+then:
+  %scaled = fmul double %x, %scale
+  br label %merge
+
+merge:
+  %r = phi double [ 0.0, %entry ], [ %scaled, %then ], [ 1.0, %check ]
+  ret double %r
+}
+
+define float @spec_fcmp_inverted(float %x, float %scale, i1 %other) {
+; CHECK-LABEL: define float @spec_fcmp_inverted(
+; CHECK-SAME: float [[X:%.*]], float [[SCALE:%.*]], i1 [[OTHER:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[X]], 0.000000e+00
+; CHECK-NEXT:    [[SCALED:%.*]] = fmul float [[X]], [[SCALE]]
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[SCALED]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[OTHER]], float 0.000000e+00, float [[SPEC_SELECT]]
+; CHECK-NEXT:    ret float [[R]]
+;
+entry:
+  br i1 %other, label %merge, label %check
+
+check:
+  %cmp = fcmp ogt float %x, 0.0
+  br i1 %cmp, label %merge, label %then
+
+then:
+  %scaled = fmul float %x, %scale
+  br label %merge
+
+merge:
+  %r = phi float [ 0.0, %entry ], [ %scaled, %then ], [ 1.0, %check ]
+  ret float %r
+}
+
+define float @no_fold_too_many_insts(float %x, float %scale, i1 %other) {
+; CHECK-LABEL: define float @no_fold_too_many_insts(
+; CHECK-SAME: float [[X:%.*]], float [[SCALE:%.*]], i1 [[OTHER:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[OTHER]], label %[[MERGE:.*]], label %[[CHECK:.*]]
+; CHECK:       [[CHECK]]:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[X]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[CMP]], label %[[THEN:.*]], label %[[MERGE]]
+; CHECK:       [[THEN]]:
+; CHECK-NEXT:    [[A:%.*]] = fmul float [[X]], [[SCALE]]
+; CHECK-NEXT:    [[B:%.*]] = fmul float [[A]], [[SCALE]]
+; CHECK-NEXT:    br label %[[MERGE]]
+; CHECK:       [[MERGE]]:
+; CHECK-NEXT:    [[R:%.*]] = phi float [ 0.000000e+00, %[[ENTRY]] ], [ [[B]], %[[THEN]] ], [ 1.000000e+00, %[[CHECK]] ]
+; CHECK-NEXT:    ret float [[R]]
+;
+entry:
+  br i1 %other, label %merge, label %check
+
+check:
+  %cmp = fcmp ogt float %x, 0.0
+  br i1 %cmp, label %then, label %merge
+
+then:
+  %a = fmul float %x, %scale
+  %b = fmul float %a, %scale
+  br label %merge
+
+merge:
+  %r = phi float [ 0.0, %entry ], [ %b, %then ], [ 1.0, %check ]
+  ret float %r
+}

diff  --git a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-phis.ll b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-phis.ll
index e281e9bcc5e4d..eaad45ceeb17f 100644
--- a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-phis.ll
+++ b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-phis.ll
@@ -465,12 +465,11 @@ define float @D139275_c4001580(float %val) {
 ; ALL-NEXT:    br i1 [[CMP1]], label [[IF_END3:%.*]], label [[RETURN]]
 ; ALL:       if.end3:
 ; ALL-NEXT:    [[CMP4:%.*]] = fcmp olt float [[VAL]], 2.000000e-01
-; ALL-NEXT:    br i1 [[CMP4]], label [[RETURN]], label [[IF_END6:%.*]]
-; ALL:       if.end6:
 ; ALL-NEXT:    [[SUB:%.*]] = fadd float [[VAL]], -1.000000e-01
+; ALL-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP4]], float 0.000000e+00, float [[SUB]]
 ; ALL-NEXT:    br label [[RETURN]]
 ; ALL:       return:
-; ALL-NEXT:    [[RETVAL_0:%.*]] = phi float [ [[SUB]], [[IF_END6]] ], [ 0.000000e+00, [[ENTRY:%.*]] ], [ 1.000000e-01, [[IF_END]] ], [ 0.000000e+00, [[IF_END3]] ]
+; ALL-NEXT:    [[RETVAL_0:%.*]] = phi float [ [[SPEC_SELECT]], [[IF_END3]] ], [ 0.000000e+00, [[ENTRY:%.*]] ], [ 1.000000e-01, [[IF_END]] ]
 ; ALL-NEXT:    ret float [[RETVAL_0]]
 ;
 entry:


        


More information about the llvm-commits mailing list