[llvm] [X86, SimplifyCFG] Support hoisting load/store with conditional faulting (Part II) (PR #108812)

Phoebe Wang via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 23 06:46:23 PDT 2024


================
@@ -1771,6 +1782,25 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(Instruction *TI,
     if (Succ->hasAddressTaken() || !Succ->getSinglePredecessor())
       return false;
 
+  auto *BI = dyn_cast<BranchInst>(TI);
+  if (BI && HoistLoadsStoresWithCondFaulting &&
+      Options.HoistLoadsStoresWithCondFaulting) {
+    SmallVector<Instruction *, 2> SpeculatedConditionalLoadsStores;
+    for (auto *Succ : successors(BB)) {
+      for (Instruction &I : drop_end(*Succ)) {
+        if (!isSafeCheapLoadStore(&I, TTI) ||
+            SpeculatedConditionalLoadsStores.size() ==
+                HoistLoadsStoresWithCondFaultingThreshold)
+          return false;
+        SpeculatedConditionalLoadsStores.push_back(&I);
+      }
+    }
+
+    if (!SpeculatedConditionalLoadsStores.empty())
----------------
phoebewang wrote:

The assumption here is prior passes have moved common instructions out of branches. It works in a pipeline, e.g.,
```
$ cat single_predecessor.ll
define i32 @single_predecessor(ptr %p, ptr %q, i32 %x, i32 %a, i32 %b) {
entry:
  %tobool = icmp ne i32 %x, 0
  br i1 %tobool, label %if.end, label %if.then
if.end:
  store i32 1, ptr %q
  %c = add i32 %a, %b ; <== common instruction
  ret i32 %c
if.then:
  %0 = load i32, ptr %q
  store i32 %0, ptr %p
  %d = add i32 %a, %b ; <== common instruction
  ret i32 %d
}

$ opt -passes=simplifycfg,'instcombine<no-verify-fixpoint>','simplifycfg<hoist-loads-stores-with-cond-faulting>' -mtriple=x86_64 -mattr=+cf single_predecessor.ll -S -o -
; ModuleID = 'single_predecessor.ll'
source_filename = "single_predecessor.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64"

define i32 @single_predecessor(ptr %p, ptr %q, i32 %x, i32 %a, i32 %b) #0 {
entry:
  %tobool.not = icmp eq i32 %x, 0
  %0 = xor i1 %tobool.not, true
  %1 = bitcast i1 %0 to <1 x i1>
  %2 = bitcast i1 %tobool.not to <1 x i1>
  %3 = call <1 x i32> @llvm.masked.load.v1i32.p0(ptr %q, i32 4, <1 x i1> %2, <1 x i32> poison)
  %4 = bitcast <1 x i32> %3 to i32
  call void @llvm.masked.store.v1i32.p0(<1 x i32> %3, ptr %p, i32 4, <1 x i1> %2)
  call void @llvm.masked.store.v1i32.p0(<1 x i32> <i32 1>, ptr %q, i32 4, <1 x i1> %2)
  %common.ret.op = add i32 %a, %b
  ret i32 %common.ret.op
}

```

https://github.com/llvm/llvm-project/pull/108812


More information about the llvm-commits mailing list