[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