[llvm] ARM: Avoid relying on kill flags for determining CPSR liveness (PR #222873)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 11 00:53:55 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-arm
Author: Matt Arsenault (arsenm)
<details>
<summary>Changes</summary>
When forming CBZ/CBNZ in ARMConstantIslands, check if CPSR is live-out
of the block instead of relying on the kill flag. Kill flags have been
soft deprecated for over a decade.
Co-authored-by: Claude claude-opus-4.8 <noreply@<!-- -->anthropic.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/222873.diff
2 Files Affected:
- (modified) llvm/lib/Target/ARM/ARMConstantIslandPass.cpp (+8-4)
- (added) llvm/test/CodeGen/ARM/cbz-no-kill-flag.mir (+132)
``````````diff
diff --git a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
index 97db51129cff2..f3961ba260d7b 100644
--- a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
+++ b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
@@ -1908,10 +1908,14 @@ bool ARMConstantIslands::optimizeThumb2Branches() {
ImmCmp.MI = nullptr;
ImmCmp.NewOpc = 0;
- // If the conditional branch doesn't kill CPSR, then CPSR can be liveout
- // so this transformation is not safe.
- if (!Br.MI->killsRegister(ARM::CPSR, /*TRI=*/nullptr))
- return false;
+ // Folding the compare into a CBZ/CBNZ clobbers the comparison, so it is not
+ // safe if CPSR is live past the branch.
+ //
+ // TODO: This could be safe if it's only live into this branch's target.
+ for (const MachineBasicBlock *Succ : Br.MI->getParent()->successors()) {
+ if (Succ->isLiveIn(ARM::CPSR))
+ return false;
+ }
Register PredReg;
unsigned NewOpc = 0;
diff --git a/llvm/test/CodeGen/ARM/cbz-no-kill-flag.mir b/llvm/test/CodeGen/ARM/cbz-no-kill-flag.mir
new file mode 100644
index 0000000000000..2957d9c642694
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/cbz-no-kill-flag.mir
@@ -0,0 +1,132 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=thumbv8m.base -run-pass=arm-cp-islands -o - %s | FileCheck %s
+
+# ARMConstantIslands forms a CBZ/CBNZ from a tCMPi8 + conditional
+# branch only when CPSR is not live past the branch. Determine this
+# from block liveness rather than a kill flag on the branch
+
+---
+name: cbz_no_kill_flag
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: cbz_no_kill_flag
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: liveins: $r0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: tCBZ renamable $r0, %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.2(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $r0, dead $cpsr = tMOVi8 3, 14 /* CC::al */, $noreg
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2.entry:
+ ; CHECK-NEXT: liveins: $r0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg, implicit $r0
+ bb.0.entry:
+ successors: %bb.2, %bb.1
+ liveins: $r0
+
+ tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
+ tBcc %bb.2, 0 /* CC::eq */, $cpsr
+
+ bb.1:
+ successors: %bb.2
+
+ renamable $r0, dead $cpsr = tMOVi8 3, 14 /* CC::al */, $noreg
+
+ bb.2.entry:
+ liveins: $r0
+
+ tBX_RET 14 /* CC::al */, $noreg, implicit $r0
+...
+
+# Negative test: CPSR is live out of the branch's block so the compare
+# must not be folded into a CBZ/CBNZ.
+---
+name: cpsr_live_out
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: cpsr_live_out
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: liveins: $r0, $r1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
+ ; CHECK-NEXT: tBcc %bb.2, 0 /* CC::eq */, $cpsr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.2(0x80000000)
+ ; CHECK-NEXT: liveins: $r0, $r1, $cpsr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $r0, dead $cpsr = tADC renamable $r0, renamable $r1, 14 /* CC::al */, $noreg, implicit $cpsr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2.entry:
+ ; CHECK-NEXT: liveins: $r0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg, implicit $r0
+ bb.0.entry:
+ successors: %bb.2, %bb.1
+ liveins: $r0, $r1
+
+ tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
+ tBcc %bb.2, 0 /* CC::eq */, $cpsr
+
+ bb.1:
+ successors: %bb.2
+ liveins: $r0, $r1, $cpsr
+
+ renamable $r0, dead $cpsr = tADC renamable $r0, renamable $r1, 14 /* CC::al */, $noreg, implicit $cpsr
+
+ bb.2.entry:
+ liveins: $r0
+
+ tBX_RET 14 /* CC::al */, $noreg, implicit $r0
+...
+
+# Negative test: CPSR is live out through the tBcc's branch, but not
+# the other successor.
+#
+# TODO: This is a missed optimization.
+---
+name: cpsr_live_out_branch_target
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: cpsr_live_out_branch_target
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: liveins: $r0, $r1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
+ ; CHECK-NEXT: tBcc %bb.2, 0 /* CC::eq */, $cpsr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: liveins: $r0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg, implicit $r0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2.entry:
+ ; CHECK-NEXT: liveins: $r0, $r1, $cpsr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $r0, dead $cpsr = tADC renamable $r0, renamable $r1, 14 /* CC::al */, $noreg, implicit $cpsr
+ ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg, implicit $r0
+ bb.0.entry:
+ successors: %bb.2, %bb.1
+ liveins: $r0, $r1
+
+ tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
+ tBcc %bb.2, 0 /* CC::eq */, $cpsr
+
+ bb.1:
+ liveins: $r0
+
+ tBX_RET 14 /* CC::al */, $noreg, implicit $r0
+
+ bb.2.entry:
+ liveins: $r0, $r1, $cpsr
+
+ renamable $r0, dead $cpsr = tADC renamable $r0, renamable $r1, 14 /* CC::al */, $noreg, implicit $cpsr
+ tBX_RET 14 /* CC::al */, $noreg, implicit $r0
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/222873
More information about the llvm-commits
mailing list