[llvm] [EarlyIfConversion] Extend data dependent analysis across multiple blocks (PR #180623)

via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 30 04:08:05 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Jonathan Cohen (jcohen-apple)

<details>
<summary>Changes</summary>

This extends the new data dependent analysis for branches to cover loads which feed conditions which are not within the same Machine Basic Block. To still try to catch loads which are "close in program time" we still keep the limit on the number of instructions between the branch and the load, and that there must not be any intervening function calls. 

---

Patch is 33.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/180623.diff


2 Files Affected:

- (modified) llvm/lib/CodeGen/EarlyIfConversion.cpp (+101-22) 
- (modified) llvm/test/CodeGen/AArch64/early-ifcvt-load-to-cond-br.mir (+566-38) 


``````````diff
diff --git a/llvm/lib/CodeGen/EarlyIfConversion.cpp b/llvm/lib/CodeGen/EarlyIfConversion.cpp
index f178923070656..28be3876c59d0 100644
--- a/llvm/lib/CodeGen/EarlyIfConversion.cpp
+++ b/llvm/lib/CodeGen/EarlyIfConversion.cpp
@@ -23,6 +23,7 @@
 #include "llvm/ADT/SparseSet.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
 #include "llvm/CodeGen/MachineDominators.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -42,6 +43,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
+#include <cstddef>
 
 using namespace llvm;
 
@@ -829,6 +831,9 @@ class EarlyIfConverter {
   MachineBranchProbabilityInfo *MBPI = nullptr;
   SSAIfConv IfConv;
 
+  /// Cache of basic blocks verified to contain no call instructions.
+  SmallPtrSet<const MachineBasicBlock *, 16> NoCallBlocksCache;
+
 public:
   EarlyIfConverter(MachineDominatorTree &DT, MachineLoopInfo &LI,
                    MachineTraceMetrics &MTM, MachineBranchProbabilityInfo *MBPI)
@@ -842,7 +847,11 @@ class EarlyIfConverter {
   void invalidateTraces();
   bool shouldConvertIf();
   bool isConditionDataDependent();
-  bool doOperandsComeFromMemory(Register Reg);
+  bool doOperandsComeFromMemory(Register Reg, const MachineInstr *ConditionDef);
+  bool callInPath(
+      const MachineInstr *From, const MachineInstr *To,
+      const SmallPtrSetImpl<const MachineBasicBlock *> &IntermediateBlocks,
+      unsigned MaxInstructions = 64);
 };
 
 class EarlyIfConverterLegacy : public MachineFunctionPass {
@@ -923,15 +932,62 @@ static bool isConstantPoolLoad(const MachineInstr *MI) {
          });
 }
 
-/// Check if there are any calls in the range (From, To].
-static bool callInRange(const MachineInstr *From, const MachineInstr *To) {
-  constexpr int MaxInstructionsToCheck = 64;
-  int Count = 0;
-  auto InstrRange =
-      make_range(std::next(From->getIterator()), To->getIterator());
-  return any_of(InstrRange, [&](const MachineInstr &MI) {
-    return ++Count > MaxInstructionsToCheck || MI.isCall();
-  });
+/// Check if there are any calls in the path from From to To, potentially
+/// spanning multiple basic blocks. The IntermediateBlocks set contains
+/// blocks that are between From's block and To's block in the control flow.
+///
+/// Checks:
+/// - If same block: (From, To)
+/// - If different blocks:
+///   - (From, end of From's block]
+///   - All instructions in IntermediateBlocks
+///   - [start of To's block, To)
+///
+/// Returns true if a call is found or if the path exceeds MaxInstructions.
+/// Uses NoCallBlocksCache to skip blocks already verified to have no calls.
+bool EarlyIfConverter::callInPath(
+    const MachineInstr *From, const MachineInstr *To,
+    const SmallPtrSetImpl<const MachineBasicBlock *> &IntermediateBlocks,
+    unsigned MaxInstructions /* = 64 */) {
+  if (From == To)
+    return false;
+
+  unsigned Count = 0;
+  const MachineBasicBlock *FromBB = From->getParent();
+  const MachineBasicBlock *ToBB = To->getParent();
+
+  // Helper to check if instruction limit exceeded or call found.
+  auto CheckInstrIsCall = [&](const MachineInstr &MI) {
+    return ++Count > MaxInstructions || MI.isCall();
+  };
+
+  // If From and To are in the same block, just check (From, To).
+  if (FromBB == ToBB)
+    return llvm::any_of(
+        llvm::make_range(std::next(From->getIterator()), To->getIterator()),
+        CheckInstrIsCall);
+
+  // Check (From, end of From's block].
+  if (any_of(
+          llvm::make_range(std::next(From->getIterator()), FromBB->instr_end()),
+          CheckInstrIsCall))
+    return true;
+
+  // Check all intermediate blocks entirely.
+  // Use cache to skip blocks already verified to have no calls.
+  for (const MachineBasicBlock *BB : IntermediateBlocks) {
+    if (BB == FromBB || BB == ToBB)
+      continue;
+    if (NoCallBlocksCache.contains(BB))
+      continue;
+    if (any_of(*BB, CheckInstrIsCall))
+      return true;
+    NoCallBlocksCache.insert(BB);
+  }
+
+  // Check [start of To's block, To).
+  return any_of(llvm::make_range(ToBB->instr_begin(), To->getIterator()),
+                CheckInstrIsCall);
 }
 
 /// Check if a register's value comes from a memory load by walking the
@@ -940,14 +996,18 @@ static bool callInRange(const MachineInstr *From, const MachineInstr *To) {
 /// or come from a constant pool). Only consider loads that are in the
 /// same basic block as the branch to ensure the load is "immediately"
 /// before the branch in program time.
-bool EarlyIfConverter::doOperandsComeFromMemory(Register Reg) {
+bool EarlyIfConverter::doOperandsComeFromMemory(
+    Register Reg, const MachineInstr *ConditionDef) {
   if (!Reg.isVirtual())
     return false;
 
+  LLVM_DEBUG(dbgs() << "  doOperandsComeFromMemory starting from reg "
+                    << printReg(Reg) << "\n");
+
   // Walk the def-use chain.
   SmallPtrSet<const MachineInstr *, 8> VisitedInstrs;
+  SmallPtrSet<const MachineBasicBlock *, 8> VisitedBlocks;
   SmallVector<const MachineInstr *> Worklist;
-  SmallVector<Register, 16> VisitedRegs;
 
   MachineInstr *DefMI = MRI->getVRegDef(Reg);
   // The operand is defined outside of the function - it does not
@@ -956,24 +1016,41 @@ bool EarlyIfConverter::doOperandsComeFromMemory(Register Reg) {
     return false;
 
   Worklist.push_back(DefMI);
-  VisitedRegs.push_back(Reg);
 
   while (!Worklist.empty() && VisitedInstrs.size() < MaxNumSteps) {
     const MachineInstr *MI = Worklist.pop_back_val();
     if (!VisitedInstrs.insert(MI).second)
       continue;
 
-    // Stop walking if we encounter an instruction outside the head block.
-    if (MI->getParent() != IfConv.Head)
-      break;
+    // Stop walking if we encounter an instruction outside the loop.
+    // For blocks in the same loop, we continue to walk the def-use chain
+    // to find loads, regardless of whether they're immediate predecessors.
+    const MachineBasicBlock *Parent = MI->getParent();
+    MachineLoop *IfConvLoop = Loops->getLoopFor(IfConv.Head);
+    MachineLoop *ParentLoop = Loops->getLoopFor(Parent);
+
+    // If the instruction is outside the loop, skip it (loop-invariant).
+    if (IfConvLoop && ParentLoop != IfConvLoop)
+      continue;
+
+    // Track visited blocks for call checking later.
+    VisitedBlocks.insert(Parent);
 
     // Check if this instruction is a load, and there are no calls between
-    // the load and the branch (which would break the "close in time"
+    // the load and the condition (which would break the "close in time"
     // assumption).
     if (MI->mayLoad() && !isConstantPoolLoad(MI) &&
-        !MI->isDereferenceableInvariantLoad() &&
-        !callInRange(MI, &*IfConv.Head->getFirstTerminator()))
+        !MI->isDereferenceableInvariantLoad()) {
+      // If the load doesn't dominate the condition (e.g., comes after it in
+      // the same block via a loop back-edge), it can't affect this iteration.
+      // If not - check if there is a call between the load instruction and
+      // ConditionDef.
+      if (!DomTree->dominates(MI, ConditionDef) ||
+          callInPath(MI, ConditionDef, VisitedBlocks))
+        continue;
+
       return true;
+    }
 
     // Walk through all register use operands and find their definitions.
     for (const MachineOperand &MO : MI->operands()) {
@@ -986,7 +1063,6 @@ bool EarlyIfConverter::doOperandsComeFromMemory(Register Reg) {
       if (MachineInstr *UseDef = MRI->getVRegDef(UseReg)) {
         if (!VisitedInstrs.count(UseDef)) {
           Worklist.push_back(UseDef);
-          VisitedRegs.push_back(UseReg);
         }
       }
     }
@@ -1017,7 +1093,8 @@ bool EarlyIfConverter::isConditionDataDependent() {
   // Check if operands used to compute the branch condition were loaded recently
   // from memory, starting by the ConditionDef itself and walking up the use-def
   // chain.
-  if (doOperandsComeFromMemory(MBP.ConditionDef->getOperand(0).getReg())) {
+  if (doOperandsComeFromMemory(MBP.ConditionDef->getOperand(0).getReg(),
+                               MBP.ConditionDef)) {
     ++NumDataDependant;
     return true;
   }
@@ -1268,8 +1345,10 @@ bool EarlyIfConverter::tryConvertIf(MachineBasicBlock *MBB) {
     Changed = true;
     updateDomTree(DomTree, IfConv, RemoveBlocks);
     updateLoops(Loops, RemoveBlocks);
-    for (MachineBasicBlock *MBB : RemoveBlocks)
+    for (MachineBasicBlock *MBB : RemoveBlocks) {
+      NoCallBlocksCache.erase(MBB);
       MBB->eraseFromParent();
+    }
   }
   return Changed;
 }
diff --git a/llvm/test/CodeGen/AArch64/early-ifcvt-load-to-cond-br.mir b/llvm/test/CodeGen/AArch64/early-ifcvt-load-to-cond-br.mir
index ba37de47e6b64..cd29ca1b12010 100644
--- a/llvm/test/CodeGen/AArch64/early-ifcvt-load-to-cond-br.mir
+++ b/llvm/test/CodeGen/AArch64/early-ifcvt-load-to-cond-br.mir
@@ -48,6 +48,24 @@
   define i32 @call_between_load_and_branch(ptr %p, i32 %x, i32 %y) {
     ret i32 0
   }
+  define i32 @load_cond_and_branch_pred_bb(ptr %p, i32 %x, i32 %y) {
+    ret i32 0
+  }
+  define i32 @load_cond_and_branch_pred_bb_with_call(ptr %p, i32%x, i32 %y) {
+    ret i32 0
+  }
+  define i32 @load_in_pred_call_in_head(ptr %p, i32 %x, i32 %y) {
+    ret i32 0
+  }
+  define i32 @load_in_loop_not_immediate_pred(ptr %p, i32 %x, i32 %y) {
+    ret i32 0
+  }
+  define i32 @load_in_loop_call_in_intermediate_block(ptr %p, i32 %x, i32 %y) {
+    ret i32 0
+  }
+  define i32 @load_to_cond_in_backedge(ptr %p) {
+    ret i32 0
+  }
   declare void @foo()
 ...
 ---
@@ -853,44 +871,73 @@ name:            load_branch_separate_bbs_in_loop
 alignment:       4
 tracksRegLiveness: true
 body:             |
-  ; CHECK-COMMON-LABEL: name: load_branch_separate_bbs_in_loop
-  ; CHECK-COMMON: bb.0:
-  ; CHECK-COMMON-NEXT:   successors: %bb.1(0x80000000)
-  ; CHECK-COMMON-NEXT:   liveins: $x0, $w1, $w2
-  ; CHECK-COMMON-NEXT: {{  $}}
-  ; CHECK-COMMON-NEXT:   [[COPY:%[0-9]+]]:gpr64common = COPY $x0
-  ; CHECK-COMMON-NEXT:   [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
-  ; CHECK-COMMON-NEXT:   [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
-  ; CHECK-COMMON-NEXT: {{  $}}
-  ; CHECK-COMMON-NEXT: bb.1:
-  ; CHECK-COMMON-NEXT:   successors: %bb.2(0x80000000)
-  ; CHECK-COMMON-NEXT: {{  $}}
-  ; CHECK-COMMON-NEXT:   [[LDRWui:%[0-9]+]]:gpr32common = LDRWui [[COPY]], 0 :: (load (s32))
-  ; CHECK-COMMON-NEXT: {{  $}}
-  ; CHECK-COMMON-NEXT: bb.2:
-  ; CHECK-COMMON-NEXT:   successors: %bb.3(0x40000000), %bb.4(0x40000000)
-  ; CHECK-COMMON-NEXT: {{  $}}
-  ; CHECK-COMMON-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[LDRWui]], 100, 0, implicit-def $nzcv
-  ; CHECK-COMMON-NEXT:   Bcc 12, %bb.4, implicit $nzcv
-  ; CHECK-COMMON-NEXT:   B %bb.3
-  ; CHECK-COMMON-NEXT: {{  $}}
-  ; CHECK-COMMON-NEXT: bb.3:
-  ; CHECK-COMMON-NEXT:   successors: %bb.4(0x80000000)
-  ; CHECK-COMMON-NEXT: {{  $}}
-  ; CHECK-COMMON-NEXT:   [[MADDWrrr:%[0-9]+]]:gpr32 = MADDWrrr [[COPY1]], [[COPY2]], $wzr
-  ; CHECK-COMMON-NEXT:   [[MADDWrrr1:%[0-9]+]]:gpr32 = MADDWrrr [[MADDWrrr]], [[COPY1]], $wzr
-  ; CHECK-COMMON-NEXT: {{  $}}
-  ; CHECK-COMMON-NEXT: bb.4:
-  ; CHECK-COMMON-NEXT:   successors: %bb.1(0x7c000000), %bb.5(0x04000000)
-  ; CHECK-COMMON-NEXT: {{  $}}
-  ; CHECK-COMMON-NEXT:   [[PHI:%[0-9]+]]:gpr32sp = PHI [[COPY1]], %bb.2, [[MADDWrrr1]], %bb.3
-  ; CHECK-COMMON-NEXT:   [[SUBSWri1:%[0-9]+]]:gpr32 = SUBSWri [[PHI]], 0, 0, implicit-def $nzcv
-  ; CHECK-COMMON-NEXT:   Bcc 12, %bb.1, implicit $nzcv
-  ; CHECK-COMMON-NEXT:   B %bb.5
-  ; CHECK-COMMON-NEXT: {{  $}}
-  ; CHECK-COMMON-NEXT: bb.5:
-  ; CHECK-COMMON-NEXT:   $w0 = COPY [[PHI]]
-  ; CHECK-COMMON-NEXT:   RET_ReallyLR implicit $w0
+  ; CHECK-DEFAULT-LABEL: name: load_branch_separate_bbs_in_loop
+  ; CHECK-DEFAULT: bb.0:
+  ; CHECK-DEFAULT-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-DEFAULT-NEXT:   liveins: $x0, $w1, $w2
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT:   [[COPY:%[0-9]+]]:gpr64common = COPY $x0
+  ; CHECK-DEFAULT-NEXT:   [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+  ; CHECK-DEFAULT-NEXT:   [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT: bb.1:
+  ; CHECK-DEFAULT-NEXT:   successors: %bb.2(0x80000000)
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT:   [[LDRWui:%[0-9]+]]:gpr32common = LDRWui [[COPY]], 0 :: (load (s32))
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT: bb.2:
+  ; CHECK-DEFAULT-NEXT:   successors: %bb.3(0x40000000), %bb.4(0x40000000)
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[LDRWui]], 100, 0, implicit-def $nzcv
+  ; CHECK-DEFAULT-NEXT:   Bcc 12, %bb.4, implicit $nzcv
+  ; CHECK-DEFAULT-NEXT:   B %bb.3
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT: bb.3:
+  ; CHECK-DEFAULT-NEXT:   successors: %bb.4(0x80000000)
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT:   [[MADDWrrr:%[0-9]+]]:gpr32 = MADDWrrr [[COPY1]], [[COPY2]], $wzr
+  ; CHECK-DEFAULT-NEXT:   [[MADDWrrr1:%[0-9]+]]:gpr32 = MADDWrrr [[MADDWrrr]], [[COPY1]], $wzr
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT: bb.4:
+  ; CHECK-DEFAULT-NEXT:   successors: %bb.1(0x7c000000), %bb.5(0x04000000)
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT:   [[PHI:%[0-9]+]]:gpr32sp = PHI [[COPY1]], %bb.2, [[MADDWrrr1]], %bb.3
+  ; CHECK-DEFAULT-NEXT:   [[SUBSWri1:%[0-9]+]]:gpr32 = SUBSWri [[PHI]], 0, 0, implicit-def $nzcv
+  ; CHECK-DEFAULT-NEXT:   Bcc 12, %bb.1, implicit $nzcv
+  ; CHECK-DEFAULT-NEXT:   B %bb.5
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT: bb.5:
+  ; CHECK-DEFAULT-NEXT:   $w0 = COPY [[PHI]]
+  ; CHECK-DEFAULT-NEXT:   RET_ReallyLR implicit $w0
+  ;
+  ; CHECK-DATA-DEPENDENT-LABEL: name: load_branch_separate_bbs_in_loop
+  ; CHECK-DATA-DEPENDENT: bb.0:
+  ; CHECK-DATA-DEPENDENT-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-DATA-DEPENDENT-NEXT:   liveins: $x0, $w1, $w2
+  ; CHECK-DATA-DEPENDENT-NEXT: {{  $}}
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[COPY:%[0-9]+]]:gpr64common = COPY $x0
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+  ; CHECK-DATA-DEPENDENT-NEXT: {{  $}}
+  ; CHECK-DATA-DEPENDENT-NEXT: bb.1:
+  ; CHECK-DATA-DEPENDENT-NEXT:   successors: %bb.2(0x80000000)
+  ; CHECK-DATA-DEPENDENT-NEXT: {{  $}}
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[LDRWui:%[0-9]+]]:gpr32common = LDRWui [[COPY]], 0 :: (load (s32))
+  ; CHECK-DATA-DEPENDENT-NEXT: {{  $}}
+  ; CHECK-DATA-DEPENDENT-NEXT: bb.2:
+  ; CHECK-DATA-DEPENDENT-NEXT:   successors: %bb.1(0x7c000000), %bb.5(0x04000000)
+  ; CHECK-DATA-DEPENDENT-NEXT: {{  $}}
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[LDRWui]], 100, 0, implicit-def $nzcv
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[MADDWrrr:%[0-9]+]]:gpr32 = MADDWrrr [[COPY1]], [[COPY2]], $wzr
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[MADDWrrr1:%[0-9]+]]:gpr32 = MADDWrrr [[MADDWrrr]], [[COPY1]], $wzr
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[CSELWr:%[0-9]+]]:gpr32common = CSELWr [[COPY1]], [[MADDWrrr1]], 12, implicit $nzcv
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[SUBSWri1:%[0-9]+]]:gpr32 = SUBSWri [[CSELWr]], 0, 0, implicit-def $nzcv
+  ; CHECK-DATA-DEPENDENT-NEXT:   Bcc 12, %bb.1, implicit $nzcv
+  ; CHECK-DATA-DEPENDENT-NEXT:   B %bb.5
+  ; CHECK-DATA-DEPENDENT-NEXT: {{  $}}
+  ; CHECK-DATA-DEPENDENT-NEXT: bb.5:
+  ; CHECK-DATA-DEPENDENT-NEXT:   $w0 = COPY [[CSELWr]]
+  ; CHECK-DATA-DEPENDENT-NEXT:   RET_ReallyLR implicit $w0
   bb.0:
     successors: %bb.1(0x80000000)
     liveins: $x0, $w1, $w2
@@ -981,3 +1028,484 @@ body:             |
     %7:gpr32 = PHI %1, %bb.0, %6, %bb.1
     $w0 = COPY %7
     RET_ReallyLR implicit $w0
+...
+---
+name:            load_cond_and_branch_pred_bb
+alignment:       4
+tracksRegLiveness: true
+body:             |
+  ; CHECK-DEFAULT-LABEL: name: load_cond_and_branch_pred_bb
+  ; CHECK-DEFAULT: bb.0:
+  ; CHECK-DEFAULT-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-DEFAULT-NEXT:   liveins: $x0, $w1, $w2
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT:   [[COPY:%[0-9]+]]:gpr64common = COPY $x0
+  ; CHECK-DEFAULT-NEXT:   [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+  ; CHECK-DEFAULT-NEXT:   [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+  ; CHECK-DEFAULT-NEXT:   [[LDRWui:%[0-9]+]]:gpr32common = LDRWui [[COPY]], 0 :: (load (s32))
+  ; CHECK-DEFAULT-NEXT:   B %bb.1
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT: bb.1:
+  ; CHECK-DEFAULT-NEXT:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[LDRWui]], 100, 0, implicit-def $nzcv
+  ; CHECK-DEFAULT-NEXT:   Bcc 12, %bb.3, implicit $nzcv
+  ; CHECK-DEFAULT-NEXT:   B %bb.2
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT: bb.2:
+  ; CHECK-DEFAULT-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT:   [[MADDWrrr:%[0-9]+]]:gpr32 = MADDWrrr [[COPY1]], [[COPY2]], $wzr
+  ; CHECK-DEFAULT-NEXT:   [[MADDWrrr1:%[0-9]+]]:gpr32 = MADDWrrr [[MADDWrrr]], [[COPY1]], $wzr
+  ; CHECK-DEFAULT-NEXT: {{  $}}
+  ; CHECK-DEFAULT-NEXT: bb.3:
+  ; CHECK-DEFAULT-NEXT:   [[PHI:%[0-9]+]]:gpr32 = PHI [[COPY1]], %bb.1, [[MADDWrrr1]], %bb.2
+  ; CHECK-DEFAULT-NEXT:   $w0 = COPY [[PHI]]
+  ; CHECK-DEFAULT-NEXT:   RET_ReallyLR implicit $w0
+  ;
+  ; CHECK-DATA-DEPENDENT-LABEL: name: load_cond_and_branch_pred_bb
+  ; CHECK-DATA-DEPENDENT: bb.0:
+  ; CHECK-DATA-DEPENDENT-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-DATA-DEPENDENT-NEXT:   liveins: $x0, $w1, $w2
+  ; CHECK-DATA-DEPENDENT-NEXT: {{  $}}
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[COPY:%[0-9]+]]:gpr64common = COPY $x0
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[LDRWui:%[0-9]+]]:gpr32common = LDRWui [[COPY]], 0 :: (load (s32))
+  ; CHECK-DATA-DEPENDENT-NEXT:   B %bb.1
+  ; CHECK-DATA-DEPENDENT-NEXT: {{  $}}
+  ; CHECK-DATA-DEPENDENT-NEXT: bb.1:
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[LDRWui]], 100, 0, implicit-def $nzcv
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[MADDWrrr:%[0-9]+]]:gpr32 = MADDWrrr [[COPY1]], [[COPY2]], $wzr
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[MADDWrrr1:%[0-9]+]]:gpr32 = MADDWrrr [[MADDWrrr]], [[COPY1]], $wzr
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[CSELWr:%[0-9]+]]:gpr32 = CSELWr [[COPY1]], [[MADDWrrr1]], 12, implicit $nzcv
+  ; CHECK-DATA-DEPENDENT-NEXT:   $w0 = COPY [[CSELWr]]
+  ; CHECK-DATA-DEPENDENT-NEXT:   RET_ReallyLR implicit $w0
+  bb.0:
+    successors: %bb.1(0x80000000)
+    liveins: $x0, $w1, $w2
+
+    %0:gpr64common = COPY $x0
+    %1:gpr32 = COPY $w1
+    %2:gpr32 = COPY $w2
+    %3:gpr32common = LDRWui %0, 0 :: (load (s32))
+    B %bb.1
+
+  bb.1:
+    successors: %bb.2(0x40000000), %bb.3(0x40000000)
+
+    %4:gpr32 = SUBSWri %3, 100, 0, implicit-def $nzcv
+    Bcc 12, %bb.3, implicit $nzcv
+    B %bb.2
+
+  bb.2:
+    successors: %bb.3(0x80000000)
+
+    %5:gpr32 = MADDWrrr %1, %2, $wzr
+    %6:gpr32 = MADDWrrr %5, %1, $wzr
+
+  bb.3:
+    %7:gpr32 = PHI %1, %bb.1, %6, %bb.2
+    $w0 = COPY %7
+    RET_ReallyLR implicit $w0
+...
+---
+name:            load_cond_and_branch_pred_bb_with_call
+alignment:       4
+tracksRegLiveness: true
+body:             |
+  ; CHECK-COMMON-LABEL: name: load_cond_and_branch_pred_bb_with_call
+  ; CHECK-COMMON: bb.0:
+  ; CHECK-COMMON-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-COMMON-NEXT:   liveins: $x0, $w1, $w2
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT:   [[COPY:%[0-9]+]]:gpr64common = COPY $x0
+  ; CHECK-COMMON-NEXT:   [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+  ; CHECK-COMMON-NEXT:   [[COPY2:%[0-9]+]]:gpr32 = COPY $w2
+  ; CHECK-COMMON-NEXT:   [[LDRWui:%[0-9]+]]:gpr32common = LDRWui [[COPY]], 0 :: (load (s32))
+  ; CHECK-COMMON-NEXT:   BL @foo, implicit-def $lr
+  ; CHECK-COMMON-NEXT:   B %bb.1
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT: bb.1:
+  ; CHECK-COMMON-NEXT:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[LDRWui]], 100, 0, implicit-def $nzcv
+  ; CHECK-COMMON-NEXT:   Bcc 12, %bb.3, implicit $nzcv
+  ; CHECK-COMMON-NEXT:   B %bb.2
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT: bb.2:
+  ; CHECK-COMMON-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-COMM...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list