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

Jonathan Cohen via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 16 00:13:11 PDT 2026


https://github.com/jcohen-apple updated https://github.com/llvm/llvm-project/pull/180623

>From 1d1187b695766b918e06c02791cfbfe897f6ec41 Mon Sep 17 00:00:00 2001
From: Jonathan Cohen <joncoh at apple.com>
Date: Sun, 8 Feb 2026 21:17:56 +0200
Subject: [PATCH 1/2] Unit tests demonstrating current behavior

---
 .../AArch64/early-ifcvt-load-to-cond-br.mir   | 378 ++++++++++++++++++
 1 file changed, 378 insertions(+)

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..04c3bc03cbbdb 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,21 @@
   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
+  }
   declare void @foo()
 ...
 ---
@@ -981,3 +996,366 @@ 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-COMMON-LABEL: name: load_cond_and_branch_pred_bb
+  ; 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:   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-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.3:
+  ; CHECK-COMMON-NEXT:   [[PHI:%[0-9]+]]:gpr32 = PHI [[COPY1]], %bb.1, [[MADDWrrr1]], %bb.2
+  ; CHECK-COMMON-NEXT:   $w0 = COPY [[PHI]]
+  ; CHECK-COMMON-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-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.3:
+  ; CHECK-COMMON-NEXT:   [[PHI:%[0-9]+]]:gpr32 = PHI [[COPY1]], %bb.1, [[MADDWrrr1]], %bb.2
+  ; CHECK-COMMON-NEXT:   $w0 = COPY [[PHI]]
+  ; CHECK-COMMON-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))
+    BL @foo, implicit-def $lr
+    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_in_pred_call_in_head
+alignment:       4
+tracksRegLiveness: true
+body:             |
+  ; CHECK-COMMON-LABEL: name: load_in_pred_call_in_head
+  ; 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:   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:   BL @foo, implicit-def $lr
+  ; 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-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.3:
+  ; CHECK-COMMON-NEXT:   [[PHI:%[0-9]+]]:gpr32 = PHI [[COPY1]], %bb.1, [[MADDWrrr1]], %bb.2
+  ; CHECK-COMMON-NEXT:   $w0 = COPY [[PHI]]
+  ; CHECK-COMMON-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)
+
+    BL @foo, implicit-def $lr
+    %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_in_loop_not_immediate_pred
+alignment:       4
+tracksRegLiveness: true
+body:             |
+  ; CHECK-COMMON-LABEL: name: load_in_loop_not_immediate_pred
+  ; 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:   [[ADDWri:%[0-9]+]]:gpr32common = ADDWri [[LDRWui]], 1, 0
+  ; CHECK-COMMON-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[ADDWri]], 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
+  bb.0:
+    successors: %bb.1(0x80000000)
+    liveins: $x0, $w1, $w2
+
+    %0:gpr64common = COPY $x0
+    %1:gpr32 = COPY $w1
+    %2:gpr32 = COPY $w2
+
+  bb.1:
+    successors: %bb.2(0x80000000)
+
+    %3:gpr32common = LDRWui %0, 0 :: (load (s32))
+
+  bb.2:
+    successors: %bb.3(0x40000000), %bb.4(0x40000000)
+
+    %4:gpr32common = ADDWri %3, 1, 0
+    %5:gpr32 = SUBSWri %4, 100, 0, implicit-def $nzcv
+    Bcc 12, %bb.4, implicit $nzcv
+    B %bb.3
+
+  bb.3:
+    successors: %bb.4(0x80000000)
+
+    %6:gpr32 = MADDWrrr %1, %2, $wzr
+    %7:gpr32 = MADDWrrr %6, %1, $wzr
+
+  bb.4:
+    successors: %bb.1(0x7c000000), %bb.5(0x04000000)
+
+    %8:gpr32sp = PHI %1, %bb.2, %7, %bb.3
+    %9:gpr32 = SUBSWri %8, 0, 0, implicit-def $nzcv
+    Bcc 12, %bb.1, implicit $nzcv
+    B %bb.5
+
+  bb.5:
+    $w0 = COPY %8
+    RET_ReallyLR implicit $w0
+...
+---
+name:            load_in_loop_call_in_intermediate_block
+alignment:       4
+tracksRegLiveness: true
+body:             |
+  ; CHECK-COMMON-LABEL: name: load_in_loop_call_in_intermediate_block
+  ; 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(0x80000000)
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT:   BL @foo, implicit-def $lr
+  ; CHECK-COMMON-NEXT:   [[ADDWri:%[0-9]+]]:gpr32common = ADDWri [[LDRWui]], 1, 0
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT: bb.3:
+  ; CHECK-COMMON-NEXT:   successors: %bb.4(0x40000000), %bb.5(0x40000000)
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[ADDWri]], 100, 0, implicit-def $nzcv
+  ; CHECK-COMMON-NEXT:   Bcc 12, %bb.5, implicit $nzcv
+  ; CHECK-COMMON-NEXT:   B %bb.4
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT: bb.4:
+  ; CHECK-COMMON-NEXT:   successors: %bb.5(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.5:
+  ; CHECK-COMMON-NEXT:   successors: %bb.1(0x7c000000), %bb.6(0x04000000)
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT:   [[PHI:%[0-9]+]]:gpr32sp = PHI [[COPY1]], %bb.3, [[MADDWrrr1]], %bb.4
+  ; 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.6
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT: bb.6:
+  ; CHECK-COMMON-NEXT:   $w0 = COPY [[PHI]]
+  ; CHECK-COMMON-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
+
+  bb.1:
+    successors: %bb.2(0x80000000)
+
+    %3:gpr32common = LDRWui %0, 0 :: (load (s32))
+
+  bb.2:
+    successors: %bb.3(0x80000000)
+
+    BL @foo, implicit-def $lr
+    %4:gpr32common = ADDWri %3, 1, 0
+
+  bb.3:
+    successors: %bb.4(0x40000000), %bb.5(0x40000000)
+
+    %5:gpr32 = SUBSWri %4, 100, 0, implicit-def $nzcv
+    Bcc 12, %bb.5, implicit $nzcv
+    B %bb.4
+
+  bb.4:
+    successors: %bb.5(0x80000000)
+
+    %6:gpr32 = MADDWrrr %1, %2, $wzr
+    %7:gpr32 = MADDWrrr %6, %1, $wzr
+
+  bb.5:
+    successors: %bb.1(0x7c000000), %bb.6(0x04000000)
+
+    %8:gpr32sp = PHI %1, %bb.3, %7, %bb.4
+    %9:gpr32 = SUBSWri %8, 0, 0, implicit-def $nzcv
+    Bcc 12, %bb.1, implicit $nzcv
+    B %bb.6
+
+  bb.6:
+    $w0 = COPY %8
+    RET_ReallyLR implicit $w0

>From bf29a547b2138882213d63366af0c04d58691cd3 Mon Sep 17 00:00:00 2001
From: Jonathan Cohen <joncoh at apple.com>
Date: Mon, 16 Mar 2026 10:20:08 +0200
Subject: [PATCH 2/2] [EarlyIfConversion] Extend data dependent analysis to
 multiple blocks

---
 llvm/lib/CodeGen/EarlyIfConversion.cpp        | 123 ++++--
 .../AArch64/early-ifcvt-load-to-cond-br.mir   | 360 +++++++++++++-----
 2 files changed, 356 insertions(+), 127 deletions(-)

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 04c3bc03cbbdb..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
@@ -63,6 +63,9 @@
   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()
 ...
 ---
@@ -868,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
@@ -1002,34 +1034,53 @@ name:            load_cond_and_branch_pred_bb
 alignment:       4
 tracksRegLiveness: true
 body:             |
-  ; CHECK-COMMON-LABEL: name: load_cond_and_branch_pred_bb
-  ; 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:   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-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.3:
-  ; CHECK-COMMON-NEXT:   [[PHI:%[0-9]+]]:gpr32 = PHI [[COPY1]], %bb.1, [[MADDWrrr1]], %bb.2
-  ; CHECK-COMMON-NEXT:   $w0 = COPY [[PHI]]
-  ; CHECK-COMMON-NEXT:   RET_ReallyLR implicit $w0
+  ; 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
@@ -1189,45 +1240,75 @@ name:            load_in_loop_not_immediate_pred
 alignment:       4
 tracksRegLiveness: true
 body:             |
-  ; CHECK-COMMON-LABEL: name: load_in_loop_not_immediate_pred
-  ; 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:   [[ADDWri:%[0-9]+]]:gpr32common = ADDWri [[LDRWui]], 1, 0
-  ; CHECK-COMMON-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[ADDWri]], 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_in_loop_not_immediate_pred
+  ; 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:   [[ADDWri:%[0-9]+]]:gpr32common = ADDWri [[LDRWui]], 1, 0
+  ; CHECK-DEFAULT-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[ADDWri]], 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_in_loop_not_immediate_pred
+  ; 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:   [[ADDWri:%[0-9]+]]:gpr32common = ADDWri [[LDRWui]], 1, 0
+  ; CHECK-DATA-DEPENDENT-NEXT:   [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[ADDWri]], 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
@@ -1359,3 +1440,72 @@ body:             |
   bb.6:
     $w0 = COPY %8
     RET_ReallyLR implicit $w0
+...
+---
+name:            load_to_cond_in_backedge
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gpr64sp }
+  - { id: 1, class: gpr32 }
+  - { id: 2, class: gpr32 }
+  - { id: 3, class: gpr64 }
+  - { id: 4, class: gpr32 }
+  - { id: 5, class: gpr32all }
+  - { id: 6, class: gpr32 }
+body:             |
+  ; CHECK-COMMON-LABEL: name: load_to_cond_in_backedge
+  ; CHECK-COMMON: bb.0:
+  ; CHECK-COMMON-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-COMMON-NEXT:   liveins: $x0
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT:   [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
+  ; CHECK-COMMON-NEXT:   [[DEF:%[0-9]+]]:gpr32 = IMPLICIT_DEF
+  ; CHECK-COMMON-NEXT:   B %bb.1
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT: bb.1:
+  ; CHECK-COMMON-NEXT:   successors: %bb.5(0x04000000), %bb.1(0x7c000000)
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT:   [[PHI:%[0-9]+]]:gpr32 = PHI undef [[DEF]], %bb.0, %5, %bb.1
+  ; CHECK-COMMON-NEXT:   [[LDRHHroW:%[0-9]+]]:gpr32 = LDRHHroW undef [[COPY]], undef [[PHI]], 0, 1 :: (load (s16))
+  ; CHECK-COMMON-NEXT:   [[COPY1:%[0-9]+]]:gpr32all = COPY [[LDRHHroW]]
+  ; CHECK-COMMON-NEXT:   [[COPY2:%[0-9]+]]:gpr32 = COPY [[COPY1]]
+  ; CHECK-COMMON-NEXT:   Bcc 1, %bb.1, implicit undef $nzcv
+  ; CHECK-COMMON-NEXT:   B %bb.5
+  ; CHECK-COMMON-NEXT: {{  $}}
+  ; CHECK-COMMON-NEXT: bb.5:
+  ; CHECK-COMMON-NEXT:   RET_ReallyLR
+  bb.0:
+    successors: %bb.1(0x80000000)
+    liveins: $x0
+
+    %0:gpr64sp = COPY $x0
+    %1:gpr32 = IMPLICIT_DEF
+    B %bb.1
+
+  bb.1:
+    successors: %bb.2(0x40000000), %bb.3(0x40000000)
+
+    %2:gpr32 = PHI undef %1, %bb.0, %5, %bb.4
+    %4:gpr32 = LDRHHroW undef %0, undef %2, 0, 1 :: (load (s16))
+    %5:gpr32all = COPY %4
+    TBNZW undef %2, 0, %bb.3
+    B %bb.2
+
+  bb.2:
+    successors: %bb.4(0x80000000)
+
+    B %bb.4
+
+  bb.3:
+    successors: %bb.4(0x80000000)
+
+  bb.4:
+    successors: %bb.5(0x04000000), %bb.1(0x7c000000)
+
+    %6:gpr32 = PHI undef %5, %bb.3, undef %5, %bb.2
+    Bcc 1, %bb.1, implicit undef $nzcv
+    B %bb.5
+
+  bb.5:
+    RET_ReallyLR



More information about the llvm-commits mailing list