[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