[llvm] [AArch64][SME] Exclude runtime defined liveins when computing liveouts (PR #154325)
Benjamin Maxwell via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 19 05:56:29 PDT 2025
https://github.com/MacDue created https://github.com/llvm/llvm-project/pull/154325
These liveins are not defined by predecessors, so attempting to preserve them results in generating invalid MIR (as the registers may not be defined). This takes a similar approach to: https://github.com/llvm/llvm-project/commit/c1dc267258e06bb69e1ca217d1d8ce2d15b8757f
This resolves:
- https://github.com/llvm/llvm-project/pull/149062#discussion_r2285072001
- https://github.com/llvm/llvm-project/pull/153417#issuecomment-3199972351
>From ea2e249d5b76b191d84c6127387862ffeb8882cd Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Tue, 19 Aug 2025 12:47:30 +0000
Subject: [PATCH] [AArch64][SME] Exclude runtime defined liveins when computing
liveouts
These liveins are not defined by predecessors, so attempting to preserve
them results in generating invalid MIR (as the registers may not be
defined). This takes a similar approach to: https://github.com/llvm/llvm-project/commit/c1dc267258e06bb69e1ca217d1d8ce2d15b8757f
---
llvm/include/llvm/CodeGen/LiveRegUnits.h | 8 +-
llvm/lib/CodeGen/LiveRegUnits.cpp | 26 +++++-
llvm/lib/Target/AArch64/MachineSMEABIPass.cpp | 2 +-
.../CodeGen/AArch64/sme-abi-eh-liveins.mir | 82 +++++++++++++++++++
.../test/CodeGen/AArch64/sme-za-exceptions.ll | 8 +-
5 files changed, 114 insertions(+), 12 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/sme-abi-eh-liveins.mir
diff --git a/llvm/include/llvm/CodeGen/LiveRegUnits.h b/llvm/include/llvm/CodeGen/LiveRegUnits.h
index 37c31cc6f4ac5..f58188377b520 100644
--- a/llvm/include/llvm/CodeGen/LiveRegUnits.h
+++ b/llvm/include/llvm/CodeGen/LiveRegUnits.h
@@ -26,6 +26,7 @@ namespace llvm {
class MachineInstr;
class MachineBasicBlock;
+class TargetLowering;
/// A set of register units used to track register liveness.
class LiveRegUnits {
@@ -135,8 +136,11 @@ class LiveRegUnits {
/// Adds registers living out of block \p MBB.
/// Live out registers are the union of the live-in registers of the successor
/// blocks and pristine registers. Live out registers of the end block are the
- /// callee saved registers.
- LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB);
+ /// callee saved registers. If the target lowering information \p TLI is
+ /// provided, runtime-defined live ins of successors will be excluded from the
+ /// live outs.
+ LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB,
+ const TargetLowering *TLI = nullptr);
/// Adds registers living into block \p MBB.
LLVM_ABI void addLiveIns(const MachineBasicBlock &MBB);
diff --git a/llvm/lib/CodeGen/LiveRegUnits.cpp b/llvm/lib/CodeGen/LiveRegUnits.cpp
index 34de09dd2944b..c034d5f3925fc 100644
--- a/llvm/lib/CodeGen/LiveRegUnits.cpp
+++ b/llvm/lib/CodeGen/LiveRegUnits.cpp
@@ -16,6 +16,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
using namespace llvm;
@@ -86,9 +87,15 @@ void LiveRegUnits::accumulate(const MachineInstr &MI) {
/// Add live-in registers of basic block \p MBB to \p LiveUnits.
static void addBlockLiveIns(LiveRegUnits &LiveUnits,
- const MachineBasicBlock &MBB) {
- for (const auto &LI : MBB.liveins())
+ const MachineBasicBlock &MBB,
+ MCPhysReg ExceptionPointer = {},
+ MCPhysReg ExceptionSelector = {}) {
+ for (const auto &LI : MBB.liveins()) {
+ if (MBB.isEHPad() &&
+ (LI.PhysReg == ExceptionPointer || LI.PhysReg == ExceptionSelector))
+ continue;
LiveUnits.addRegMasked(LI.PhysReg, LI.LaneMask);
+ }
}
/// Adds all callee saved registers to \p LiveUnits.
@@ -135,14 +142,25 @@ void LiveRegUnits::addPristines(const MachineFunction &MF) {
addUnits(Pristine.getBitVector());
}
-void LiveRegUnits::addLiveOuts(const MachineBasicBlock &MBB) {
+void LiveRegUnits::addLiveOuts(const MachineBasicBlock &MBB,
+ const TargetLowering *TLI) {
const MachineFunction &MF = *MBB.getParent();
addPristines(MF);
+ MCPhysReg ExceptionPointer;
+ MCPhysReg ExceptionSelector;
+
+ // Remove live-ins from successors that are defined by the runtime.
+ if (TLI && MF.getFunction().hasPersonalityFn()) {
+ auto PersonalityFn = MF.getFunction().getPersonalityFn();
+ ExceptionPointer = TLI->getExceptionPointerRegister(PersonalityFn);
+ ExceptionSelector = TLI->getExceptionSelectorRegister(PersonalityFn);
+ }
+
// To get the live-outs we simply merge the live-ins of all successors.
for (const MachineBasicBlock *Succ : MBB.successors())
- addBlockLiveIns(*this, *Succ);
+ addBlockLiveIns(*this, *Succ, ExceptionPointer, ExceptionSelector);
// For the return block: Add all callee saved registers.
if (MBB.isReturnBlock()) {
diff --git a/llvm/lib/Target/AArch64/MachineSMEABIPass.cpp b/llvm/lib/Target/AArch64/MachineSMEABIPass.cpp
index b58dfdf32e4ab..2f00977e9a1cc 100644
--- a/llvm/lib/Target/AArch64/MachineSMEABIPass.cpp
+++ b/llvm/lib/Target/AArch64/MachineSMEABIPass.cpp
@@ -277,7 +277,7 @@ void MachineSMEABI::collectNeededZAStates(SMEAttrs SMEFnAttrs) {
}
LiveRegUnits LiveUnits(*TRI);
- LiveUnits.addLiveOuts(MBB);
+ LiveUnits.addLiveOuts(MBB, Subtarget->getTargetLowering());
auto GetPhysLiveRegs = [&] {
LiveRegs PhysLiveRegs = LiveRegs::None;
diff --git a/llvm/test/CodeGen/AArch64/sme-abi-eh-liveins.mir b/llvm/test/CodeGen/AArch64/sme-abi-eh-liveins.mir
new file mode 100644
index 0000000000000..711745e528bbf
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sme-abi-eh-liveins.mir
@@ -0,0 +1,82 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple=aarch64 -mattr=+sve -mattr=+sme -run-pass=aarch64-machine-sme-abi -verify-machineinstrs %s -o - | FileCheck %s
+
+# This test verifies that runtime defined live-ins are not included in the live
+# outs of predecessors in the MachineSMEABIPass, as including them would result
+# in copies of undefined registers.
+
+--- |
+ define void @sme_abi_eh_liveins() "aarch64_inout_za" personality ptr @__gxx_personality_v0 { entry: unreachable }
+
+ declare i32 @__gxx_personality_v0(...)
+...
+---
+name: sme_abi_eh_liveins
+tracksRegLiveness: true
+isSSA: true
+noVRegs: false
+
+body: |
+ ; CHECK-LABEL: name: sme_abi_eh_liveins
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.2(0x00000000), %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[RDSVLI_XI:%[0-9]+]]:gpr64 = RDSVLI_XI 1, implicit $vg
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $sp
+ ; CHECK-NEXT: [[MSUBXrrr:%[0-9]+]]:gpr64 = MSUBXrrr [[RDSVLI_XI]], [[RDSVLI_XI]], [[COPY]]
+ ; CHECK-NEXT: $sp = COPY [[MSUBXrrr]]
+ ; CHECK-NEXT: STPXi [[MSUBXrrr]], [[RDSVLI_XI]], %stack.0, 0
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
+ ; CHECK-NEXT: InOutZAUsePseudo
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
+ ; CHECK-NEXT: [[ADDXri:%[0-9]+]]:gpr64sp = ADDXri %stack.0, 0, 0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY [[ADDXri]]
+ ; CHECK-NEXT: MSR 56965, [[COPY1]]
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
+ ; CHECK-NEXT: RequiresZASavePseudo
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
+ ; CHECK-NEXT: MSRpstatesvcrImm1 2, 1, implicit-def $nzcv
+ ; CHECK-NEXT: [[MRS:%[0-9]+]]:gpr64 = MRS 56965, implicit-def $nzcv
+ ; CHECK-NEXT: $x0 = ADDXri %stack.0, 0, 0
+ ; CHECK-NEXT: RestoreZAPseudo [[MRS]], $x0, &__arm_tpidr2_restore, csr_aarch64_sme_abi_support_routines_preservemost_from_x0
+ ; CHECK-NEXT: MSR 56965, $xzr
+ ; CHECK-NEXT: B %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1 (landing-pad):
+ ; CHECK-NEXT: successors: %bb.2(0x80000000)
+ ; CHECK-NEXT: liveins: $x0, $x1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: MSRpstatesvcrImm1 2, 1, implicit-def $nzcv
+ ; CHECK-NEXT: [[MRS1:%[0-9]+]]:gpr64 = MRS 56965, implicit-def $nzcv
+ ; CHECK-NEXT: $x0 = ADDXri %stack.0, 0, 0
+ ; CHECK-NEXT: RestoreZAPseudo [[MRS1]], $x0, &__arm_tpidr2_restore, csr_aarch64_sme_abi_support_routines_preservemost_from_x0
+ ; CHECK-NEXT: MSR 56965, $xzr
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
+ ; CHECK-NEXT: InOutZAUsePseudo
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ bb.0:
+ successors: %bb.2(0x00000000), %bb.1(0x80000000)
+
+ ; Simulate shared ZA call
+ ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
+ InOutZAUsePseudo
+ ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
+
+ ; Simulate private ZA call at the end of the block
+ ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
+ RequiresZASavePseudo
+ ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
+
+ B %bb.2
+
+ bb.1 (landing-pad):
+ liveins: $x0, $x1
+
+ ; Simulate shared ZA call
+ ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
+ InOutZAUsePseudo
+ ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
+
+ bb.2:
diff --git a/llvm/test/CodeGen/AArch64/sme-za-exceptions.ll b/llvm/test/CodeGen/AArch64/sme-za-exceptions.ll
index c497a95a58c8a..bb88142efa592 100644
--- a/llvm/test/CodeGen/AArch64/sme-za-exceptions.ll
+++ b/llvm/test/CodeGen/AArch64/sme-za-exceptions.ll
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme -aarch64-new-sme-abi < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme -aarch64-new-sme-abi -verify-machineinstrs < %s | FileCheck %s
; A simple EH test case that corresponds to the following C++ source:
;
@@ -62,16 +62,14 @@ define void @za_with_raii(i1 %fail) "aarch64_inout_za" personality ptr @__gxx_pe
; CHECK-NEXT: ldr x1, [x1, :got_lo12:typeinfo_for_char_const_ptr]
; CHECK-NEXT: bl __cxa_throw
; CHECK-NEXT: .Ltmp1:
-; CHECK-NEXT: mov x8, x0
; CHECK-NEXT: smstart za
-; CHECK-NEXT: mrs x9, TPIDR2_EL0
+; CHECK-NEXT: mrs x8, TPIDR2_EL0
; CHECK-NEXT: sub x0, x29, #16
-; CHECK-NEXT: cbnz x9, .LBB0_4
+; CHECK-NEXT: cbnz x8, .LBB0_4
; CHECK-NEXT: // %bb.3: // %throw_exception
; CHECK-NEXT: bl __arm_tpidr2_restore
; CHECK-NEXT: .LBB0_4: // %throw_exception
; CHECK-NEXT: msr TPIDR2_EL0, xzr
-; CHECK-NEXT: // kill: def $x0 killed $x8
; CHECK-NEXT: // %bb.5: // %throw_fail
; CHECK-NEXT: .LBB0_6: // %unwind_dtors
; CHECK-NEXT: .Ltmp2:
More information about the llvm-commits
mailing list