[llvm] [SimplifyCFG] Treat umul + extract pattern as cheap single instruction. (PR #124933)

Gábor Spaits via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 20 04:10:05 PST 2025


https://github.com/spaits updated https://github.com/llvm/llvm-project/pull/124933

>From 838e617069e555468753bf902eb2bfdba3fe6309 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Tue, 4 Feb 2025 16:38:32 +0100
Subject: [PATCH 1/8] [Transform] Treat umul + extract pattern as cheap single
 instruction.

---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp     | 37 ++++++++++--
 .../X86/unsigned-multiply-overflow-check.ll   | 34 +++--------
 .../SimplifyCFG/umul-extract-pattern.ll       | 59 +++++++++++++++++++
 3 files changed, 98 insertions(+), 32 deletions(-)
 create mode 100644 llvm/test/Transforms/SimplifyCFG/umul-extract-pattern.ll

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 12dd49da279b9..63f7029885fa6 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3286,7 +3286,21 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
 
   SmallVector<Instruction *, 4> SpeculatedDbgIntrinsics;
 
+  // The number of already examined instructions. Debug instructions don't
+  // count!
   unsigned SpeculatedInstructions = 0;
+  // By default the number of instructions that may be speculatevly executed is
+  // one. Whenever a pattern is found in the basic block, that is cheap for sure
+  // we increase this number to the size of the pattern (how many instructions
+  // are there in that pattern).
+  unsigned MaxSpeculatedInstructionsToHoist = 1;
+  // In case we have found a cheap pattern, we don't want to do cost checking
+  // anymore. We are sure we want to hoist the pattern. To know, that we are
+  // only hoisting the cheap pattern only and not other expensive instructions
+  // too, we have the `MaxSpeculatedInstructionsToHoist` variable to track that
+  // the basic block truly only contains that pattern.
+  bool PartialInst = false;
+
   bool HoistLoadsStores = HoistLoadsStoresWithCondFaulting &&
                           Options.HoistLoadsStoresWithCondFaulting;
   SmallVector<Instruction *, 2> SpeculatedConditionalLoadsStores;
@@ -3316,12 +3330,20 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
     if (EphTracker.track(&I))
       continue;
 
-    // Only speculatively execute a single instruction (not counting the
-    // terminator) for now.
     bool IsSafeCheapLoadStore = HoistLoadsStores &&
                                 isSafeCheapLoadStore(&I, TTI) &&
                                 SpeculatedConditionalLoadsStores.size() <
                                     HoistLoadsStoresWithCondFaultingThreshold;
+
+    // Overflow arithmetic instruction plus extract value are usually generated
+    // when a division is being replaced, but the zero check may still be there.
+    // In that case hoist these two instructions out of this basic block, and
+    // let later optimizations take care of the unnecessary zero checks.
+    WithOverflowInst *OverflowI;
+    if (match(&I, m_ExtractValue<1>(m_OneUse(m_WithOverflowInst(OverflowI))))) {
+      MaxSpeculatedInstructionsToHoist = 2;
+      PartialInst = true;
+    }
     // Not count load/store into cost if target supports conditional faulting
     // b/c it's cheap to speculate it.
     if (IsSafeCheapLoadStore)
@@ -3329,9 +3351,6 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
     else
       ++SpeculatedInstructions;
 
-    if (SpeculatedInstructions > 1)
-      return false;
-
     // Don't hoist the instruction if it's unsafe or expensive.
     if (!IsSafeCheapLoadStore &&
         !isSafeToSpeculativelyExecute(&I, BI, Options.AC) &&
@@ -3339,11 +3358,17 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
           (SpeculatedStoreValue =
                isSafeToSpeculateStore(&I, BB, ThenBB, EndBB))))
       return false;
-    if (!IsSafeCheapLoadStore && !SpeculatedStoreValue &&
+
+    if (!PartialInst && !IsSafeCheapLoadStore && !SpeculatedStoreValue &&
         computeSpeculationCost(&I, TTI) >
             PHINodeFoldingThreshold * TargetTransformInfo::TCC_Basic)
       return false;
 
+    // The number of instrcutions to be speculatively executed is limited.
+    // This limit is dependent on the found patterns.
+    if (SpeculatedInstructions > MaxSpeculatedInstructionsToHoist)
+      return false;
+
     // Store the store speculation candidate.
     if (!SpeculatedStore && SpeculatedStoreValue)
       SpeculatedStore = cast<StoreInst>(&I);
diff --git a/llvm/test/Transforms/PhaseOrdering/X86/unsigned-multiply-overflow-check.ll b/llvm/test/Transforms/PhaseOrdering/X86/unsigned-multiply-overflow-check.ll
index 7bcb6ce17df0e..9858591dfc700 100644
--- a/llvm/test/Transforms/PhaseOrdering/X86/unsigned-multiply-overflow-check.ll
+++ b/llvm/test/Transforms/PhaseOrdering/X86/unsigned-multiply-overflow-check.ll
@@ -45,26 +45,17 @@ define i1 @will_not_overflow(i64 %arg, i64 %arg1) {
 ; INSTCOMBINESIMPLIFYCFGONLY-LABEL: @will_not_overflow(
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:  bb:
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[T0:%.*]] = icmp eq i64 [[ARG:%.*]], 0
-; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    br i1 [[T0]], label [[BB5:%.*]], label [[BB2:%.*]]
-; INSTCOMBINESIMPLIFYCFGONLY:       bb2:
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG]], i64 [[ARG1:%.*]])
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[MUL_OV:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
-; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    br label [[BB5]]
-; INSTCOMBINESIMPLIFYCFGONLY:       bb5:
-; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[T6:%.*]] = phi i1 [ false, [[BB:%.*]] ], [ [[MUL_OV]], [[BB2]] ]
+; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[T6:%.*]] = select i1 [[T0]], i1 false, i1 [[MUL_OV]]
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    ret i1 [[T6]]
 ;
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-LABEL: @will_not_overflow(
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:  bb:
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[T0:%.*]] = icmp eq i64 [[ARG:%.*]], 0
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    br i1 [[T0]], label [[BB5:%.*]], label [[BB2:%.*]]
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE:       bb2:
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG]], i64 [[ARG1:%.*]])
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[ARG1:%.*]] = freeze i64 [[ARG2:%.*]]
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG:%.*]], i64 [[ARG1]])
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[MUL_OV:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    br label [[BB5]]
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE:       bb5:
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[T6:%.*]] = phi i1 [ false, [[BB:%.*]] ], [ [[MUL_OV]], [[BB2]] ]
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    ret i1 [[T6]]
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    ret i1 [[MUL_OV]]
 ;
 bb:
   %t0 = icmp eq i64 %arg, 0
@@ -112,28 +103,19 @@ define i1 @will_overflow(i64 %arg, i64 %arg1) {
 ; INSTCOMBINESIMPLIFYCFGONLY-LABEL: @will_overflow(
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:  bb:
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[T0:%.*]] = icmp eq i64 [[ARG:%.*]], 0
-; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    br i1 [[T0]], label [[BB5:%.*]], label [[BB2:%.*]]
-; INSTCOMBINESIMPLIFYCFGONLY:       bb2:
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG]], i64 [[ARG1:%.*]])
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[MUL_OV:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[PHI_BO:%.*]] = xor i1 [[MUL_OV]], true
-; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    br label [[BB5]]
-; INSTCOMBINESIMPLIFYCFGONLY:       bb5:
-; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[T6:%.*]] = phi i1 [ true, [[BB:%.*]] ], [ [[PHI_BO]], [[BB2]] ]
+; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[T6:%.*]] = select i1 [[T0]], i1 true, i1 [[PHI_BO]]
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    ret i1 [[T6]]
 ;
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-LABEL: @will_overflow(
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:  bb:
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[T0:%.*]] = icmp eq i64 [[ARG:%.*]], 0
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    br i1 [[T0]], label [[BB5:%.*]], label [[BB2:%.*]]
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE:       bb2:
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG]], i64 [[ARG1:%.*]])
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[ARG1:%.*]] = freeze i64 [[ARG2:%.*]]
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG:%.*]], i64 [[ARG1]])
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[MUL_OV:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[PHI_BO:%.*]] = xor i1 [[MUL_OV]], true
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    br label [[BB5]]
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE:       bb5:
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[T6:%.*]] = phi i1 [ true, [[BB:%.*]] ], [ [[PHI_BO]], [[BB2]] ]
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    ret i1 [[T6]]
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    ret i1 [[PHI_BO]]
 ;
 bb:
   %t0 = icmp eq i64 %arg, 0
diff --git a/llvm/test/Transforms/SimplifyCFG/umul-extract-pattern.ll b/llvm/test/Transforms/SimplifyCFG/umul-extract-pattern.ll
new file mode 100644
index 0000000000000..db3c0fdf1d537
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/umul-extract-pattern.ll
@@ -0,0 +1,59 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
+target triple = "riscv64-unknown-unknown-elf"
+
+define i16 @func2(i64 %x, i64 %y) {
+; CHECK-LABEL: @func2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i64 [[Y:%.*]], 0
+; CHECK-NEXT:    [[MUL:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[Y]], i64 [[X:%.*]])
+; CHECK-NEXT:    [[MUL_OV:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP_NOT]], i1 false, i1 [[MUL_OV]]
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[SPEC_SELECT]] to i16
+; CHECK-NEXT:    ret i16 [[CONV]]
+;
+entry:
+  %cmp.not = icmp eq i64 %y, 0
+  br i1 %cmp.not, label %land.end, label %land.rhs
+
+land.rhs:                                         ; preds = %entry
+  %mul = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %y, i64 %x)
+  %mul.ov = extractvalue { i64, i1 } %mul, 1
+  br label %land.end
+
+land.end:                                         ; preds = %land.rhs, %entry
+  %0 = phi i1 [ false, %entry ], [ %mul.ov, %land.rhs ]
+  %conv = zext i1 %0 to i16
+  ret i16 %conv
+}
+
+define i16 @noHoist(i64 %x, i64 %y) {
+; CHECK-LABEL: @noHoist(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i64 [[Y:%.*]], 0
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[LAND_END:%.*]], label [[LAND_RHS:%.*]]
+; CHECK:       land.rhs:
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i64 [[Y]], [[X:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ADD2]], i64 [[X]])
+; CHECK-NEXT:    [[MUL_OV:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
+; CHECK-NEXT:    br label [[LAND_END]]
+; CHECK:       land.end:
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[MUL_OV]], [[LAND_RHS]] ]
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[SPEC_SELECT]] to i16
+; CHECK-NEXT:    ret i16 [[CONV]]
+;
+entry:
+  %cmp.not = icmp eq i64 %y, 0
+  br i1 %cmp.not, label %land.end, label %land.rhs
+
+land.rhs:                                   ; preds = %entry
+  %add = add nsw i64 %y, %x
+  %mul = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %add, i64 %x)
+  %mul.ov = extractvalue { i64, i1 } %mul, 1
+  br label %land.end
+
+land.end:                                         ; preds = %land.rhs, %entry
+  %0 = phi i1 [ false, %entry ], [ %mul.ov, %land.rhs ]
+  %conv = zext i1 %0 to i16
+  ret i16 %conv
+}

>From 31dcf40e5602cb5db52c607b52df235aae092237 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?= <gaborspaits1 at gmail.com>
Date: Wed, 12 Feb 2025 12:47:58 +0100
Subject: [PATCH 2/8] Fix typo

Co-authored-by: Antonio Frighetto <me at antoniofrighetto.com>
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 63f7029885fa6..d3f95985ffe64 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3364,7 +3364,7 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
             PHINodeFoldingThreshold * TargetTransformInfo::TCC_Basic)
       return false;
 
-    // The number of instrcutions to be speculatively executed is limited.
+    // The number of instructions to be speculatively executed is limited.
     // This limit is dependent on the found patterns.
     if (SpeculatedInstructions > MaxSpeculatedInstructionsToHoist)
       return false;

>From 134ad7bb828d041e3d4cd6b544e1cbac02eed552 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?= <gaborspaits1 at gmail.com>
Date: Wed, 12 Feb 2025 12:48:29 +0100
Subject: [PATCH 3/8] Fix typo

Co-authored-by: Antonio Frighetto <me at antoniofrighetto.com>
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index d3f95985ffe64..6ffc9f6badf3c 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3289,7 +3289,7 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
   // The number of already examined instructions. Debug instructions don't
   // count!
   unsigned SpeculatedInstructions = 0;
-  // By default the number of instructions that may be speculatevly executed is
+  // By default the number of instructions that may be speculatively executed is
   // one. Whenever a pattern is found in the basic block, that is cheap for sure
   // we increase this number to the size of the pattern (how many instructions
   // are there in that pattern).

>From 3fb1a07656144ef3e69ad7de0a21e8a5f9684826 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?= <gaborspaits1 at gmail.com>
Date: Wed, 12 Feb 2025 12:49:00 +0100
Subject: [PATCH 4/8] Update llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Co-authored-by: Antonio Frighetto <me at antoniofrighetto.com>
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 6ffc9f6badf3c..b2508bd019554 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3287,7 +3287,7 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
   SmallVector<Instruction *, 4> SpeculatedDbgIntrinsics;
 
   // The number of already examined instructions. Debug instructions don't
-  // count!
+  // count.
   unsigned SpeculatedInstructions = 0;
   // By default the number of instructions that may be speculatively executed is
   // one. Whenever a pattern is found in the basic block, that is cheap for sure

>From 563416928ee80d436c8db32234641b62ee294033 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=A1bor=20Spaits?= <gaborspaits1 at gmail.com>
Date: Wed, 12 Feb 2025 12:50:16 +0100
Subject: [PATCH 5/8] Update llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Co-authored-by: Antonio Frighetto <me at antoniofrighetto.com>
---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index b2508bd019554..6b595fcbaf9bf 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3290,8 +3290,8 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
   // count.
   unsigned SpeculatedInstructions = 0;
   // By default the number of instructions that may be speculatively executed is
-  // one. Whenever a pattern is found in the basic block, that is cheap for sure
-  // we increase this number to the size of the pattern (how many instructions
+  // one. Whenever `extract oneuse(op.with.overflow),1` pattern is found,
+  // we increase this threshold to the size of the pattern (how many instructions
   // are there in that pattern).
   unsigned MaxSpeculatedInstructionsToHoist = 1;
   // In case we have found a cheap pattern, we don't want to do cost checking

>From 3ed35731bacdbeaff0365c85e6010826584e003f Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Wed, 12 Feb 2025 17:44:49 +0100
Subject: [PATCH 6/8] Proper spacing for fields

---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 6b595fcbaf9bf..5568b9d8825c1 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3289,11 +3289,14 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
   // The number of already examined instructions. Debug instructions don't
   // count.
   unsigned SpeculatedInstructions = 0;
+
   // By default the number of instructions that may be speculatively executed is
   // one. Whenever `extract oneuse(op.with.overflow),1` pattern is found,
   // we increase this threshold to the size of the pattern (how many instructions
   // are there in that pattern).
+
   unsigned MaxSpeculatedInstructionsToHoist = 1;
+
   // In case we have found a cheap pattern, we don't want to do cost checking
   // anymore. We are sure we want to hoist the pattern. To know, that we are
   // only hoisting the cheap pattern only and not other expensive instructions

>From 63a31257ab3612dac6e1932db4fcf6323211f1c2 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Tue, 18 Feb 2025 22:42:34 +0100
Subject: [PATCH 7/8] Get rid of MaxSpeculatedInstructionsToHoist

---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 5568b9d8825c1..4604384abfdf5 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3290,13 +3290,6 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
   // count.
   unsigned SpeculatedInstructions = 0;
 
-  // By default the number of instructions that may be speculatively executed is
-  // one. Whenever `extract oneuse(op.with.overflow),1` pattern is found,
-  // we increase this threshold to the size of the pattern (how many instructions
-  // are there in that pattern).
-
-  unsigned MaxSpeculatedInstructionsToHoist = 1;
-
   // In case we have found a cheap pattern, we don't want to do cost checking
   // anymore. We are sure we want to hoist the pattern. To know, that we are
   // only hoisting the cheap pattern only and not other expensive instructions
@@ -3343,10 +3336,8 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
     // In that case hoist these two instructions out of this basic block, and
     // let later optimizations take care of the unnecessary zero checks.
     WithOverflowInst *OverflowI;
-    if (match(&I, m_ExtractValue<1>(m_OneUse(m_WithOverflowInst(OverflowI))))) {
-      MaxSpeculatedInstructionsToHoist = 2;
+    if (match(&I, m_ExtractValue<1>(m_OneUse(m_WithOverflowInst(OverflowI)))))
       PartialInst = true;
-    }
     // Not count load/store into cost if target supports conditional faulting
     // b/c it's cheap to speculate it.
     if (IsSafeCheapLoadStore)
@@ -3369,7 +3360,7 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
 
     // The number of instructions to be speculatively executed is limited.
     // This limit is dependent on the found patterns.
-    if (SpeculatedInstructions > MaxSpeculatedInstructionsToHoist)
+    if (SpeculatedInstructions > (PartialInst ? 2 : 1))
       return false;
 
     // Store the store speculation candidate.

>From 4d014d58531732696fe8846dbf61b41a80ace079 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Thu, 20 Feb 2025 13:09:46 +0100
Subject: [PATCH 8/8] Fix failing test case

---
 .../X86/unsigned-multiply-overflow-check.ll     | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/llvm/test/Transforms/PhaseOrdering/X86/unsigned-multiply-overflow-check.ll b/llvm/test/Transforms/PhaseOrdering/X86/unsigned-multiply-overflow-check.ll
index 9858591dfc700..f6d668d282603 100644
--- a/llvm/test/Transforms/PhaseOrdering/X86/unsigned-multiply-overflow-check.ll
+++ b/llvm/test/Transforms/PhaseOrdering/X86/unsigned-multiply-overflow-check.ll
@@ -103,19 +103,28 @@ define i1 @will_overflow(i64 %arg, i64 %arg1) {
 ; INSTCOMBINESIMPLIFYCFGONLY-LABEL: @will_overflow(
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:  bb:
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[T0:%.*]] = icmp eq i64 [[ARG:%.*]], 0
+; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    br i1 [[T0]], label [[BB5:%.*]], label [[BB2:%.*]]
+; INSTCOMBINESIMPLIFYCFGONLY:       bb2:
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG]], i64 [[ARG1:%.*]])
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[MUL_OV:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[PHI_BO:%.*]] = xor i1 [[MUL_OV]], true
-; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[T6:%.*]] = select i1 [[T0]], i1 true, i1 [[PHI_BO]]
+; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    br label [[BB5]]
+; INSTCOMBINESIMPLIFYCFGONLY:       bb5:
+; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    [[T6:%.*]] = phi i1 [ true, [[BB:%.*]] ], [ [[PHI_BO]], [[BB2]] ]
 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT:    ret i1 [[T6]]
 ;
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-LABEL: @will_overflow(
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:  bb:
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[ARG1:%.*]] = freeze i64 [[ARG2:%.*]]
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG:%.*]], i64 [[ARG1]])
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[T0:%.*]] = icmp eq i64 [[ARG:%.*]], 0
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    br i1 [[T0]], label [[BB5:%.*]], label [[BB2:%.*]]
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE:       bb2:
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG]], i64 [[ARG1:%.*]])
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[MUL_OV:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
 ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[PHI_BO:%.*]] = xor i1 [[MUL_OV]], true
-; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    ret i1 [[PHI_BO]]
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    br label [[BB5]]
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE:       bb5:
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    [[T6:%.*]] = phi i1 [ true, [[BB:%.*]] ], [ [[PHI_BO]], [[BB2]] ]
+; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT:    ret i1 [[T6]]
 ;
 bb:
   %t0 = icmp eq i64 %arg, 0



More information about the llvm-commits mailing list