[llvm] [aarch64] Mix the frame pointer with the stack cookie when protecting the stack (PR #197346)
Pan Tao via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 1 18:51:12 PDT 2026
https://github.com/PanTao2 updated https://github.com/llvm/llvm-project/pull/197346
>From f5fc52130bb86229d82e64aa6df397db9f429fa8 Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Wed, 13 May 2026 08:57:36 +0800
Subject: [PATCH 01/11] [aarch64] Mix the frame pointer with the stack cookie
when protecting the stack
For MSVC-compatible targets, mix the stack cookie with the current stack
pointer to create a position-dependent guard value. This strengthens
protection against attacks where the attacker knows or can predict the
cookie value, as they would also need to know the exact stack location.
Implementation note: We use SUB (SP - Cookie) instead of XOR like X86
because:
1. SUB maintains the existing AArch64 instruction selection patterns
2. SUB provides equivalent security properties (bijective mixing)
3. The result is still unpredictable without knowing both inputs
The same SUB operation is performed in both prologue (to store the mixed
value) and epilogue (to recompute and verify the mixed value).
This strengthens the guard and matches MSVC.
Fixes #156573.
---
llvm/include/llvm/CodeGen/TargetLowering.h | 10 +-
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 5 -
.../SelectionDAG/SelectionDAGBuilder.cpp | 12 +-
llvm/lib/CodeGen/StackProtector.cpp | 2 +-
.../Target/AArch64/AArch64ISelDAGToDAG.cpp | 15 +++
.../Target/AArch64/AArch64ISelLowering.cpp | 21 +++-
llvm/lib/Target/AArch64/AArch64ISelLowering.h | 4 +
.../lib/Target/AArch64/AArch64InstrFormats.td | 2 +
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 8 ++
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 5 +
llvm/lib/Target/X86/X86ISelLowering.cpp | 9 +-
llvm/lib/Target/X86/X86ISelLowering.h | 7 +-
.../irtranslator-stack-protector-windows.ll | 6 +-
.../CodeGen/AArch64/arm64ec-indirect-call.ll | 1 +
llvm/test/CodeGen/AArch64/mingw-refptr.ll | 107 ++++++++++++------
.../CodeGen/AArch64/stack-protector-target.ll | 8 +-
16 files changed, 158 insertions(+), 64 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 318763113fb42..ac719756084a7 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -2182,11 +2182,10 @@ class LLVM_ABI TargetLoweringBase {
virtual Value *getSDagStackGuard(const Module &M,
const LibcallLoweringInfo &Libcalls) const;
- /// If this function returns true, stack protection checks should XOR the
- /// frame pointer (or whichever pointer is used to address locals) into the
+ /// If this function returns true, stack protection checks should mix the
/// stack guard value before checking it. getIRStackGuard must return nullptr
/// if this returns true.
- virtual bool useStackGuardXorFP() const { return false; }
+ virtual bool useStackGuardMixCookie() const { return false; }
/// If the target has a standard stack protection check function that
/// performs validation and error handling, returns the function. Otherwise,
@@ -5967,8 +5966,9 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
/// LOAD_STACK_GUARD node when it is lowering Intrinsic::stackprotector.
virtual bool useLoadStackGuardNode(const Module &M) const { return false; }
- virtual SDValue emitStackGuardXorFP(SelectionDAG &DAG, SDValue Val,
- const SDLoc &DL) const {
+ virtual SDValue emitStackGuardMixCookie(SelectionDAG &DAG, SDValue Val,
+ const SDLoc &DL,
+ bool FailureBB) const {
llvm_unreachable("not implemented for this target");
}
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 8c8e08865744a..c10dd14fb287b 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -4064,11 +4064,6 @@ bool IRTranslator::emitSPDescriptorParent(StackProtectorDescriptor &SPD,
MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile)
.getReg(0);
- if (TLI->useStackGuardXorFP()) {
- LLVM_DEBUG(dbgs() << "Stack protector xor'ing with FP not yet implemented");
- return false;
- }
-
// Retrieve guard check function, nullptr if instrumentation is inlined.
if (const Function *GuardCheckFn = TLI->getSSPStackGuardCheck(M, *Libcalls)) {
// This path is currently untestable on GlobalISel, since the only platform
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 5753d74168e59..4f5ef5b5babdb 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3124,8 +3124,8 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), Align,
MachineMemOperand::MOVolatile);
- if (TLI.useStackGuardXorFP())
- GuardVal = TLI.emitStackGuardXorFP(DAG, GuardVal, dl);
+ if (TLI.useStackGuardMixCookie())
+ GuardVal = TLI.emitStackGuardMixCookie(DAG, GuardVal, dl, false);
// If we're using function-based instrumentation, call the guard check
// function
@@ -3233,8 +3233,8 @@ void SelectionDAGBuilder::visitSPDescriptorFailure(
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), Align,
MachineMemOperand::MOVolatile);
- if (TLI.useStackGuardXorFP())
- GuardVal = TLI.emitStackGuardXorFP(DAG, GuardVal, dl);
+ if (TLI.useStackGuardMixCookie())
+ GuardVal = TLI.emitStackGuardMixCookie(DAG, GuardVal, dl, true);
// The target provides a guard check function to validate the guard value.
// Generate a call to that function with the content of the guard slot as
@@ -7539,8 +7539,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
MachinePointerInfo(Global, 0), Align,
MachineMemOperand::MOVolatile);
}
- if (TLI.useStackGuardXorFP())
- Res = TLI.emitStackGuardXorFP(DAG, Res, sdl);
+ if (TLI.useStackGuardMixCookie())
+ Res = TLI.emitStackGuardMixCookie(DAG, Res, sdl, false);
DAG.setRoot(Chain);
setValue(&I, Res);
return;
diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp
index cad3ea7868e37..5eb41841f6ab6 100644
--- a/llvm/lib/CodeGen/StackProtector.cpp
+++ b/llvm/lib/CodeGen/StackProtector.cpp
@@ -610,7 +610,7 @@ bool InsertStackProtectors(const TargetLowering &TLI,
// impossible to emit the check in IR, so the target *must* support stack
// protection in SDAG.
bool SupportsSelectionDAGSP =
- TLI.useStackGuardXorFP() ||
+ TLI.useStackGuardMixCookie() ||
(EnableSelectionDAGSP && !TLI.getTargetMachine().Options.EnableFastISel);
AllocaInst *AI = nullptr; // Place on stack that stores the stack guard.
BasicBlock *FailBB = nullptr;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 64ccf606b4ef7..6f489addfb5df 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -75,6 +75,8 @@ class AArch64DAGToDAGISel : public SelectionDAGISel {
template <signed Low, signed High>
bool SelectRDSVLShiftImm(SDValue N, SDValue &Imm);
+ bool SelectAddUXTXRegister(SDValue N, SDValue &Reg, SDValue &Shift);
+
bool SelectArithExtendedRegister(SDValue N, SDValue &Reg, SDValue &Shift);
bool SelectArithUXTXRegister(SDValue N, SDValue &Reg, SDValue &Shift);
bool SelectArithImmed(SDValue N, SDValue &Val, SDValue &Shift);
@@ -1083,6 +1085,19 @@ bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(SDValue N, SDValue &Imm) {
return false;
}
+/// SelectAddUXTXRegister - Select a "UXTX register" operand. This
+/// operand is referred by the instructions have SP operand
+bool AArch64DAGToDAGISel::SelectAddUXTXRegister(SDValue N, SDValue &Reg,
+ SDValue &Shift) {
+ // TODO: Relax condition to apply to more scenarios
+ if (N.getOpcode() != ISD::LOAD)
+ return false;
+ Reg = N;
+ Shift = CurDAG->getTargetConstant(getArithExtendImm(AArch64_AM::UXTX, 0),
+ SDLoc(N), MVT::i32);
+ return true;
+}
+
/// SelectArithExtendedRegister - Select a "extended register" operand. This
/// operand folds in an extend followed by an optional left shift.
bool AArch64DAGToDAGISel::SelectArithExtendedRegister(SDValue N, SDValue &Reg,
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 413b585503335..af93468bbe9ea 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -30718,6 +30718,24 @@ bool AArch64TargetLowering::useLoadStackGuardNode(const Module &M) const {
return true;
}
+bool AArch64TargetLowering::useStackGuardMixCookie() const {
+ // Currently only MSVC CRTs mix the frame pointer into the stack guard value.
+ return Subtarget->getTargetTriple().isOSMSVCRT();
+}
+
+SDValue AArch64TargetLowering::emitStackGuardMixCookie(SelectionDAG &DAG,
+ SDValue Val,
+ const SDLoc &DL,
+ bool FailureBB) const {
+ if (FailureBB)
+ return DAG.getNode(
+ ISD::SUB, DL, Val.getValueType(),
+ DAG.getCopyFromReg(DAG.getEntryNode(), DL,
+ getStackPointerRegisterToSaveRestore(), MVT::i64),
+ Val);
+ return Val;
+}
+
unsigned AArch64TargetLowering::combineRepeatedFPDivisors() const {
// Combine multiple FDIVs with the same divisor into multiple FMULs by the
// reciprocal if there are three or more FDIVs.
@@ -31523,8 +31541,9 @@ bool AArch64TargetLowering::fallBackToDAGISel(const Instruction &Inst) const {
auto CallAttrs = SMECallAttrs(*Base, &getRuntimeLibcallsInfo());
if (CallAttrs.requiresSMChange() || CallAttrs.requiresLazySave() ||
CallAttrs.requiresPreservingZT0() ||
- CallAttrs.requiresPreservingAllZAState())
+ CallAttrs.requiresPreservingAllZAState()) {
return true;
+ }
}
}
return false;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 2e66b5ad896ef..6d9f15ee0ae29 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -366,6 +366,10 @@ class AArch64TargetLowering : public TargetLowering {
}
bool useLoadStackGuardNode(const Module &M) const override;
+ bool useStackGuardMixCookie() const override;
+ SDValue emitStackGuardMixCookie(SelectionDAG &DAG, SDValue Val,
+ const SDLoc &DL,
+ bool FailureBB) const override;
TargetLoweringBase::LegalizeTypeAction
getPreferredVectorAction(MVT VT) const override;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 04bcef5b7de29..1e891764ad861 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -1490,6 +1490,8 @@ def gi_arith_extended_reg32to64_i64 :
def arith_uxtx : ComplexPattern<i64, 2, "SelectArithUXTXRegister", []>;
+def add_uxtx : ComplexPattern<i64, 2, "SelectAddUXTXRegister", []>;
+
// Floating-point immediate.
def fpimm16XForm : SDNodeXForm<fpimm, [{
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index c0a389f9b2d93..26d02df2e5ed2 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -2617,6 +2617,14 @@ bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
.addMemOperand(*MI.memoperands_begin());
}
}
+ // To match MSVC. Unlike x86_64 which uses xor instruction to mix the cookie,
+ // we use sub instruction to mix the cookie on aarch64 for keeping the
+ // existing inlining logic intact.
+ if (Subtarget.getTargetTriple().isOSMSVCRT())
+ BuildMI(MBB, MI, DL, get(AArch64::SUBXrx64), Reg)
+ .addReg(AArch64::SP)
+ .addReg(Reg, RegState::Kill)
+ .addImm(AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, 0));
MBB.erase(MI);
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index a8ca9f0f39a53..8e15ff98136fe 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2809,6 +2809,11 @@ def : Pat<(AArch64sub_flag GPR64:$Rn, neg_addsub_shifted_imm64:$imm),
(ADDSXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>;
}
+let AddedComplexity = 1 in {
+def : Pat<(add copyFromSP:$R2, (add_uxtx GPR64:$R3, arith_extendlsl64:$imm)),
+ (ADDXrx64 GPR64sp:$R2, GPR64:$R3, arith_extendlsl64:$imm)>;
+}
+
def trunc_isWorthFoldingALU : PatFrag<(ops node:$src), (trunc $src)> {
let PredicateCode = [{ return isWorthFoldingALU(SDValue(N, 0)); }];
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index aa5b864df5936..aa1b82577e6ab 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -2859,13 +2859,14 @@ bool X86TargetLowering::useLoadStackGuardNode(const Module &M) const {
return Subtarget.isTargetMachO() && Subtarget.is64Bit();
}
-bool X86TargetLowering::useStackGuardXorFP() const {
- // Currently only MSVC CRTs XOR the frame pointer into the stack guard value.
+bool X86TargetLowering::useStackGuardMixCookie() const {
+ // Currently only MSVC CRTs mix the frame pointer into the stack guard value.
return Subtarget.getTargetTriple().isOSMSVCRT() && !Subtarget.isTargetMachO();
}
-SDValue X86TargetLowering::emitStackGuardXorFP(SelectionDAG &DAG, SDValue Val,
- const SDLoc &DL) const {
+SDValue X86TargetLowering::emitStackGuardMixCookie(SelectionDAG &DAG,
+ SDValue Val, const SDLoc &DL,
+ bool FailureBB) const {
EVT PtrTy = getPointerTy(DAG.getDataLayout());
unsigned XorOp = Subtarget.is64Bit() ? X86::XOR64_FP : X86::XOR32_FP;
MachineSDNode *Node = DAG.getMachineNode(XorOp, DL, PtrTy, Val);
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index 9a958525057b6..07d4f086d5818 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -636,12 +636,13 @@ namespace llvm {
const LibcallLoweringInfo &Libcalls) const override;
bool useLoadStackGuardNode(const Module &M) const override;
- bool useStackGuardXorFP() const override;
+ bool useStackGuardMixCookie() const override;
void
insertSSPDeclarations(Module &M,
const LibcallLoweringInfo &Libcalls) const override;
- SDValue emitStackGuardXorFP(SelectionDAG &DAG, SDValue Val,
- const SDLoc &DL) const override;
+ SDValue emitStackGuardMixCookie(SelectionDAG &DAG, SDValue Val,
+ const SDLoc &DL,
+ bool FailureBB) const override;
/// Return true if the target stores SafeStack pointer at a fixed offset in
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
index 447267cf57f76..9bab59a1c288d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
@@ -15,11 +15,13 @@ define void @caller() sspreq {
; CHECK-NEXT: adrp x8, __security_cookie
; CHECK-NEXT: add x0, sp, #4
; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: str x8, [sp, #8]
; CHECK-NEXT: bl callee
; CHECK-NEXT: adrp x8, __security_cookie
; CHECK-NEXT: ldr x9, [sp, #8]
; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: cmp x8, x9
; CHECK-NEXT: b.ne .LBB0_2
; CHECK-NEXT: // %bb.1: // %entry
@@ -31,7 +33,9 @@ define void @caller() sspreq {
; CHECK-NEXT: .seh_endepilogue
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB0_2: // %entry
-; CHECK-NEXT: ldr x0, [sp, #8]
+; CHECK-NEXT: ldr x8, [sp, #8]
+; CHECK-NEXT: mov x9, sp
+; CHECK-NEXT: sub x0, x9, x8
; CHECK-NEXT: bl __security_check_cookie
; CHECK-NEXT: brk #0x1
; CHECK-NEXT: .seh_endfunclet
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
index e6a42c382e4f6..50e563847b853 100644
--- a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
+++ b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
@@ -32,6 +32,7 @@ define void @stackguard(ptr %g) sspreq {
; CHECK-NEXT: adrp x8, __security_cookie
; CHECK-NEXT: ldr x10, [sp, #8]
; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: cmp x8, x10
; CHECK-NEXT: b.ne .LBB1_2
; CHECK-NEXT: // %bb.1:
diff --git a/llvm/test/CodeGen/AArch64/mingw-refptr.ll b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
index 02c81440dd753..9b5ceb30d5025 100644
--- a/llvm/test/CodeGen/AArch64/mingw-refptr.ll
+++ b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
@@ -77,39 +77,77 @@ entry:
declare dso_local void @otherFunc()
define dso_local void @sspFunc() #0 {
-; CHECK-LABEL: sspFunc:
-; CHECK: .seh_proc sspFunc
-; CHECK-NEXT: // %bb.0: // %entry
-; CHECK-NEXT: sub sp, sp, #32
-; CHECK-NEXT: .seh_stackalloc 32
-; CHECK-NEXT: str x30, [sp, #16] // 8-byte Spill
-; CHECK-NEXT: .seh_save_reg x30, 16
-; CHECK-NEXT: .seh_endprologue
-; CHECK-NEXT: adrp x8, .refptr.__stack_chk_guard
-; CHECK-NEXT: add x0, sp, #7
-; CHECK-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
-; CHECK-NEXT: ldr x8, [x8]
-; CHECK-NEXT: str x8, [sp, #8]
-; CHECK-NEXT: bl ptrUser
-; CHECK-NEXT: adrp x8, .refptr.__stack_chk_guard
-; CHECK-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
-; CHECK-NEXT: ldr x9, [sp, #8]
-; CHECK-NEXT: ldr x8, [x8]
-; CHECK-NEXT: cmp x8, x9
-; CHECK-NEXT: b.ne .LBB6_2
-; CHECK-NEXT: // %bb.1: // %entry
-; CHECK-NEXT: .seh_startepilogue
-; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Reload
-; CHECK-NEXT: .seh_save_reg x30, 16
-; CHECK-NEXT: add sp, sp, #32
-; CHECK-NEXT: .seh_stackalloc 32
-; CHECK-NEXT: .seh_endepilogue
-; CHECK-NEXT: ret
-; CHECK-NEXT: .LBB6_2: // %entry
-; CHECK-NEXT: bl __stack_chk_fail
-; CHECK-NEXT: brk #0x1
-; CHECK-NEXT: .seh_endfunclet
-; CHECK-NEXT: .seh_endproc
+; CHECK-SD-LABEL: sspFunc:
+; CHECK-SD: .seh_proc sspFunc
+; CHECK-SD-NEXT: // %bb.0: // %entry
+; CHECK-SD-NEXT: sub sp, sp, #32
+; CHECK-SD-NEXT: .seh_stackalloc 32
+; CHECK-SD-NEXT: str x30, [sp, #16] // 8-byte Spill
+; CHECK-SD-NEXT: .seh_save_reg x30, 16
+; CHECK-SD-NEXT: .seh_endprologue
+; CHECK-SD-NEXT: adrp x8, .refptr.__stack_chk_guard
+; CHECK-SD-NEXT: add x0, sp, #7
+; CHECK-SD-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
+; CHECK-SD-NEXT: ldr x8, [x8]
+; CHECK-SD-NEXT: sub x8, sp, x8
+; CHECK-SD-NEXT: str x8, [sp, #8]
+; CHECK-SD-NEXT: bl ptrUser
+; CHECK-SD-NEXT: adrp x8, .refptr.__stack_chk_guard
+; CHECK-SD-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
+; CHECK-SD-NEXT: ldr x9, [sp, #8]
+; CHECK-SD-NEXT: ldr x8, [x8]
+; CHECK-SD-NEXT: sub x8, sp, x8
+; CHECK-SD-NEXT: cmp x8, x9
+; CHECK-SD-NEXT: b.ne .LBB6_2
+; CHECK-SD-NEXT: // %bb.1: // %entry
+; CHECK-SD-NEXT: .seh_startepilogue
+; CHECK-SD-NEXT: ldr x30, [sp, #16] // 8-byte Reload
+; CHECK-SD-NEXT: .seh_save_reg x30, 16
+; CHECK-SD-NEXT: add sp, sp, #32
+; CHECK-SD-NEXT: .seh_stackalloc 32
+; CHECK-SD-NEXT: .seh_endepilogue
+; CHECK-SD-NEXT: ret
+; CHECK-SD-NEXT: .LBB6_2: // %entry
+; CHECK-SD-NEXT: bl __stack_chk_fail
+; CHECK-SD-NEXT: brk #0x1
+; CHECK-SD-NEXT: .seh_endfunclet
+; CHECK-SD-NEXT: .seh_endproc
+;
+; CHECK-GI-LABEL: sspFunc:
+; CHECK-GI: .seh_proc sspFunc
+; CHECK-GI-NEXT: // %bb.0: // %entry
+; CHECK-GI-NEXT: sub sp, sp, #32
+; CHECK-GI-NEXT: .seh_stackalloc 32
+; CHECK-GI-NEXT: str x30, [sp, #16] // 8-byte Spill
+; CHECK-GI-NEXT: .seh_save_reg x30, 16
+; CHECK-GI-NEXT: .seh_endprologue
+; CHECK-GI-NEXT: adrp x8, .refptr.__stack_chk_guard
+; CHECK-GI-NEXT: add x0, sp, #7
+; CHECK-GI-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
+; CHECK-GI-NEXT: ldr x8, [x8]
+; CHECK-GI-NEXT: sub x8, sp, x8
+; CHECK-GI-NEXT: str x8, [sp, #8]
+; CHECK-GI-NEXT: bl ptrUser
+; CHECK-GI-NEXT: adrp x8, .refptr.__stack_chk_guard
+; CHECK-GI-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
+; CHECK-GI-NEXT: ldr x9, [sp, #8]
+; CHECK-GI-NEXT: ldr x8, [x8]
+; CHECK-GI-NEXT: sub x8, sp, x8
+; CHECK-GI-NEXT: cmp x8, x9
+; CHECK-GI-NEXT: b.ne .LBB6_2
+; CHECK-GI-NEXT: // %bb.1: // %entry
+; CHECK-GI-NEXT: .seh_startepilogue
+; CHECK-GI-NEXT: ldr x30, [sp, #16] // 8-byte Reload
+; CHECK-GI-NEXT: .seh_save_reg x30, 16
+; CHECK-GI-NEXT: add sp, sp, #32
+; CHECK-GI-NEXT: .seh_stackalloc 32
+; CHECK-GI-NEXT: .seh_endepilogue
+; CHECK-GI-NEXT: ret
+; CHECK-GI-NEXT: .LBB6_2: // %entry
+; CHECK-GI-NEXT: bl __stack_chk_fail
+; CHECK-GI-NEXT: brk #0x1
+; CHECK-GI-NEXT: .seh_endfunclet
+; CHECK-GI-NEXT: .seh_endproc
entry:
%c = alloca i8, align 1
call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %c)
@@ -133,6 +171,3 @@ attributes #0 = { sspstrong }
; CHECK: .refptr.var:
; CHECK: .xword var
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK-GI: {{.*}}
-; CHECK-SD: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/stack-protector-target.ll b/llvm/test/CodeGen/AArch64/stack-protector-target.ll
index b1ddd1d0d160f..404426717e578 100644
--- a/llvm/test/CodeGen/AArch64/stack-protector-target.ll
+++ b/llvm/test/CodeGen/AArch64/stack-protector-target.ll
@@ -31,14 +31,18 @@ declare void @_Z7CapturePi(ptr)
; WINDOWS-AARCH64: adrp x8, __security_cookie
; WINDOWS-AARCH64: ldr x8, [x8, :lo12:__security_cookie]
+; WINDOWS-AARCH64: sub x8, sp, x8
; WINDOWS-AARCH64: str x8, [sp, #8]
; WINDOWS-AARCH64: bl _Z7CapturePi
-; WINDOWS-AARCH64: ldr x0, [sp, #8]
+; WINDOWS-AARCH64: ldr x9, [sp, #8]
+; WINDOWS-AARCH64: sub x8, sp, x8
; WINDOWS-AARCH64: bl __security_check_cookie
; WINDOWS-ARM64EC: adrp x8, __security_cookie
; WINDOWS-ARM64EC: ldr x8, [x8, :lo12:__security_cookie]
+; WINDOWS-ARM64EC: sub x8, sp, x8
; WINDOWS-ARM64EC: str x8, [sp, #8]
; WINDOWS-ARM64EC: bl "#_Z7CapturePi"
-; WINDOWS-ARM64EC: ldr x0, [sp, #8]
+; WINDOWS-ARM64EC: ldr x9, [sp, #8]
+; WINDOWS-ARM64EC: sub x8, sp, x8
; WINDOWS-ARM64EC: bl "#__security_check_cookie_arm64ec"
>From 5526a83d3e32e05b5f79430dca94749193fd531b Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Wed, 13 May 2026 09:38:09 +0800
Subject: [PATCH 02/11] Fix code format error
---
llvm/lib/Target/X86/X86ISelLowering.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index 07d4f086d5818..b4faa395cd0ba 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -644,7 +644,6 @@ namespace llvm {
const SDLoc &DL,
bool FailureBB) const override;
-
/// Return true if the target stores SafeStack pointer at a fixed offset in
/// some non-standard address space, and populates the address space and
/// offset as appropriate.
>From b7cf9dc05c9bf1de3d71e20e52207a7009911b17 Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Mon, 18 May 2026 13:42:28 +0800
Subject: [PATCH 03/11] Fix confusing check items
---
llvm/test/CodeGen/AArch64/stack-protector-target.ll | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/stack-protector-target.ll b/llvm/test/CodeGen/AArch64/stack-protector-target.ll
index 404426717e578..b7cee17581180 100644
--- a/llvm/test/CodeGen/AArch64/stack-protector-target.ll
+++ b/llvm/test/CodeGen/AArch64/stack-protector-target.ll
@@ -34,8 +34,9 @@ declare void @_Z7CapturePi(ptr)
; WINDOWS-AARCH64: sub x8, sp, x8
; WINDOWS-AARCH64: str x8, [sp, #8]
; WINDOWS-AARCH64: bl _Z7CapturePi
-; WINDOWS-AARCH64: ldr x9, [sp, #8]
-; WINDOWS-AARCH64: sub x8, sp, x8
+; WINDOWS-AARCH64: ldr x8, [sp, #8]
+; WINDOWS-AARCH64: mov x9, sp
+; WINDOWS-AARCH64: sub x0, x9, x8
; WINDOWS-AARCH64: bl __security_check_cookie
; WINDOWS-ARM64EC: adrp x8, __security_cookie
@@ -43,6 +44,7 @@ declare void @_Z7CapturePi(ptr)
; WINDOWS-ARM64EC: sub x8, sp, x8
; WINDOWS-ARM64EC: str x8, [sp, #8]
; WINDOWS-ARM64EC: bl "#_Z7CapturePi"
-; WINDOWS-ARM64EC: ldr x9, [sp, #8]
-; WINDOWS-ARM64EC: sub x8, sp, x8
+; WINDOWS-ARM64EC: ldr x8, [sp, #8]
+; WINDOWS-ARM64EC: mov x9, sp
+; WINDOWS-ARM64EC: sub x0, x9, x8
; WINDOWS-ARM64EC: bl "#__security_check_cookie_arm64ec"
>From 55ba9e77c18b14b354743a549966f2723d332132 Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Fri, 22 May 2026 13:45:42 +0800
Subject: [PATCH 04/11] Fix the issue of triggering STATUS_STACK_BUFFER_OVERRUN
---
.../SelectionDAG/SelectionDAGBuilder.cpp | 33 ++++++++++++++++---
.../Target/AArch64/AArch64ISelLowering.cpp | 17 ++++++----
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 5 +--
.../irtranslator-stack-protector-windows.ll | 9 ++---
.../CodeGen/AArch64/arm64ec-indirect-call.ll | 9 ++---
llvm/test/CodeGen/AArch64/mingw-refptr.ll | 13 ++++----
6 files changed, 58 insertions(+), 28 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 4f5ef5b5babdb..dcd087a7ed4cb 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3124,6 +3124,10 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), Align,
MachineMemOperand::MOVolatile);
+ // If cookie mixing is enabled, unmix the stored GuardVal to get back the
+ // original cookie for comparison. The prologue stored (SP - Cookie) or
+ // (SP XOR Cookie), so we apply the same operation again to unmix:
+ // SP - (SP - Cookie) = Cookie, or (SP XOR Cookie) XOR SP = Cookie.
if (TLI.useStackGuardMixCookie())
GuardVal = TLI.emitStackGuardMixCookie(DAG, GuardVal, dl, false);
@@ -3159,12 +3163,12 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
return;
}
- // If useLoadStackGuardNode returns true, generate LOAD_STACK_GUARD.
- // Otherwise, emit a volatile load to retrieve the stack guard value.
+ // Load the fresh guard value for comparison.
+ // For targets that mix the cookie in LOAD_STACK_GUARD expansion, we need to
+ // load directly without using LOAD_STACK_GUARD to avoid unwanted mixing.
SDValue Chain = DAG.getEntryNode();
- if (TLI.useLoadStackGuardNode(M)) {
- Guard = getLoadStackGuard(DAG, dl, Chain);
- } else {
+ if (TLI.useStackGuardMixCookie()) {
+ // Mixing targets: load cookie directly to avoid mixing in LOAD_STACK_GUARD
if (const Value *IRGuard = TLI.getSDagStackGuard(M, DAG.getLibcalls())) {
SDValue GuardPtr = getValue(IRGuard);
Guard = DAG.getLoad(PtrMemTy, dl, Chain, GuardPtr,
@@ -3175,8 +3179,27 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
Ctx.diagnose(DiagnosticInfoGeneric("unable to lower stackguard"));
Guard = DAG.getPOISON(PtrMemTy);
}
+ } else {
+ // Non-mixing targets: use LOAD_STACK_GUARD or direct load as usual
+ if (TLI.useLoadStackGuardNode(M)) {
+ Guard = getLoadStackGuard(DAG, dl, Chain);
+ } else {
+ if (const Value *IRGuard = TLI.getSDagStackGuard(M, DAG.getLibcalls())) {
+ SDValue GuardPtr = getValue(IRGuard);
+ Guard = DAG.getLoad(PtrMemTy, dl, Chain, GuardPtr,
+ MachinePointerInfo(IRGuard, 0), Align,
+ MachineMemOperand::MOVolatile);
+ } else {
+ LLVMContext &Ctx = *DAG.getContext();
+ Ctx.diagnose(DiagnosticInfoGeneric("unable to lower stackguard"));
+ Guard = DAG.getPOISON(PtrMemTy);
+ }
+ }
}
+ // Now both Guard (fresh cookie) and GuardVal (unmixed from stored value)
+ // contain unmixed cookie values that can be compared directly.
+
// Perform the comparison via a getsetcc.
SDValue Cmp = DAG.getSetCC(
dl, TLI.getSetCCResultType(DL, *DAG.getContext(), Guard.getValueType()),
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index af93468bbe9ea..bda13088607c0 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -30727,13 +30727,16 @@ SDValue AArch64TargetLowering::emitStackGuardMixCookie(SelectionDAG &DAG,
SDValue Val,
const SDLoc &DL,
bool FailureBB) const {
- if (FailureBB)
- return DAG.getNode(
- ISD::SUB, DL, Val.getValueType(),
- DAG.getCopyFromReg(DAG.getEntryNode(), DL,
- getStackPointerRegisterToSaveRestore(), MVT::i64),
- Val);
- return Val;
+ // Mix the cookie value with SP to create a position-dependent guard.
+ // Both prologue (stores SP - Cookie) and epilogue (compares SP - Cookie)
+ // use the same mixing operation.
+ // For FailureBB=true: Val is the stored mixed value, compute SP - Val to unmix
+ // For FailureBB=false: Val is the fresh cookie, compute SP - Val to mix
+ return DAG.getNode(
+ ISD::SUB, DL, Val.getValueType(),
+ DAG.getCopyFromReg(DAG.getEntryNode(), DL,
+ getStackPointerRegisterToSaveRestore(), MVT::i64),
+ Val);
}
unsigned AArch64TargetLowering::combineRepeatedFPDivisors() const {
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 26d02df2e5ed2..410d1040516b6 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -2618,8 +2618,9 @@ bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
}
}
// To match MSVC. Unlike x86_64 which uses xor instruction to mix the cookie,
- // we use sub instruction to mix the cookie on aarch64 for keeping the
- // existing inlining logic intact.
+ // we use sub instruction to mix the cookie on aarch64.
+ // The mixing happens here in expandPostRAPseudo (after RA) to ensure we use
+ // the final stack pointer value.
if (Subtarget.getTargetTriple().isOSMSVCRT())
BuildMI(MBB, MI, DL, get(AArch64::SUBXrx64), Reg)
.addReg(AArch64::SP)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
index 9bab59a1c288d..5eadc65b3de9c 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
@@ -18,11 +18,12 @@ define void @caller() sspreq {
; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: str x8, [sp, #8]
; CHECK-NEXT: bl callee
-; CHECK-NEXT: adrp x8, __security_cookie
; CHECK-NEXT: ldr x9, [sp, #8]
-; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
-; CHECK-NEXT: sub x8, sp, x8
-; CHECK-NEXT: cmp x8, x9
+; CHECK-NEXT: adrp x10, __security_cookie
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: ldr x10, [x10, :lo12:__security_cookie]
+; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: cmp x10, x8
; CHECK-NEXT: b.ne .LBB0_2
; CHECK-NEXT: // %bb.1: // %entry
; CHECK-NEXT: .seh_startepilogue
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
index 50e563847b853..e29e7acc5476f 100644
--- a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
+++ b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
@@ -29,11 +29,12 @@ define void @stackguard(ptr %g) sspreq {
; CHECK: adrp x8, __os_arm64x_check_icall
; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
; CHECK-NEXT: blr x8
-; CHECK-NEXT: adrp x8, __security_cookie
; CHECK-NEXT: ldr x10, [sp, #8]
-; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
-; CHECK-NEXT: sub x8, sp, x8
-; CHECK-NEXT: cmp x8, x10
+; CHECK-NEXT: adrp x12, __security_cookie
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: ldr x12, [x12, :lo12:__security_cookie]
+; CHECK-NEXT: sub x8, x8, x10
+; CHECK-NEXT: cmp x12, x8
; CHECK-NEXT: b.ne .LBB1_2
; CHECK-NEXT: // %bb.1:
; CHECK-NEXT: fmov d0, #1.00000000
diff --git a/llvm/test/CodeGen/AArch64/mingw-refptr.ll b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
index 9b5ceb30d5025..dac8e057b93fc 100644
--- a/llvm/test/CodeGen/AArch64/mingw-refptr.ll
+++ b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
@@ -92,12 +92,13 @@ define dso_local void @sspFunc() #0 {
; CHECK-SD-NEXT: sub x8, sp, x8
; CHECK-SD-NEXT: str x8, [sp, #8]
; CHECK-SD-NEXT: bl ptrUser
-; CHECK-SD-NEXT: adrp x8, .refptr.__stack_chk_guard
-; CHECK-SD-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
-; CHECK-SD-NEXT: ldr x9, [sp, #8]
-; CHECK-SD-NEXT: ldr x8, [x8]
-; CHECK-SD-NEXT: sub x8, sp, x8
-; CHECK-SD-NEXT: cmp x8, x9
+; CHECK-SD-NEXT: adrp x9, .refptr.__stack_chk_guard
+; CHECK-SD-NEXT: mov x8, sp
+; CHECK-SD-NEXT: ldr x9, [x9, :lo12:.refptr.__stack_chk_guard]
+; CHECK-SD-NEXT: ldr x10, [sp, #8]
+; CHECK-SD-NEXT: ldr x9, [x9]
+; CHECK-SD-NEXT: sub x8, x8, x10
+; CHECK-SD-NEXT: cmp x9, x8
; CHECK-SD-NEXT: b.ne .LBB6_2
; CHECK-SD-NEXT: // %bb.1: // %entry
; CHECK-SD-NEXT: .seh_startepilogue
>From 1b7040f3f4adc99fe43dfcfb129ecd1142f2fe6b Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Fri, 22 May 2026 14:23:35 +0800
Subject: [PATCH 05/11] Fix code format error
---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index bda13088607c0..7a8189a76aa8b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -30730,13 +30730,13 @@ SDValue AArch64TargetLowering::emitStackGuardMixCookie(SelectionDAG &DAG,
// Mix the cookie value with SP to create a position-dependent guard.
// Both prologue (stores SP - Cookie) and epilogue (compares SP - Cookie)
// use the same mixing operation.
- // For FailureBB=true: Val is the stored mixed value, compute SP - Val to unmix
- // For FailureBB=false: Val is the fresh cookie, compute SP - Val to mix
- return DAG.getNode(
- ISD::SUB, DL, Val.getValueType(),
- DAG.getCopyFromReg(DAG.getEntryNode(), DL,
- getStackPointerRegisterToSaveRestore(), MVT::i64),
- Val);
+ // For FailureBB=true: Val is the stored mixed value, compute SP - Val to
+ // unmix For FailureBB=false: Val is the fresh cookie, compute SP - Val to mix
+ return DAG.getNode(ISD::SUB, DL, Val.getValueType(),
+ DAG.getCopyFromReg(DAG.getEntryNode(), DL,
+ getStackPointerRegisterToSaveRestore(),
+ MVT::i64),
+ Val);
}
unsigned AArch64TargetLowering::combineRepeatedFPDivisors() const {
>From df55cfadd227ece3192b9996a5bc4866c3a52c24 Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Mon, 25 May 2026 15:49:14 +0800
Subject: [PATCH 06/11] Combine 'mov x8, sp' and 'sub x8, x8, x9'
---
.../SelectionDAG/SelectionDAGBuilder.cpp | 5 +-
.../Target/AArch64/AArch64ISelDAGToDAG.cpp | 18 +
.../Target/AArch64/AArch64ISelLowering.cpp | 4 +-
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 18 +-
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 6 +
.../irtranslator-stack-protector-windows.ll | 14 +-
.../AArch64/aarch64-dynamic-stack-layout.ll | 40 +-
llvm/test/CodeGen/AArch64/alloca.ll | 373 +++++++++++++++---
.../CodeGen/AArch64/arm64ec-indirect-call.ll | 39 +-
llvm/test/CodeGen/AArch64/mingw-refptr.ll | 5 +-
.../CodeGen/AArch64/shrink-wrapping-vla.ll | 5 +-
llvm/test/CodeGen/AArch64/sme-agnostic-za.ll | 3 +-
.../CodeGen/AArch64/sme-framelower-use-bp.ll | 6 +-
.../CodeGen/AArch64/sme-lazy-save-windows.ll | 3 +-
...nging-call-disable-stackslot-scavenging.ll | 9 +-
.../AArch64/sme-za-lazy-save-buffer.ll | 4 +-
.../AArch64/split-sve-stack-frame-layout.ll | 42 +-
.../CodeGen/AArch64/stack-guard-sysreg.ll | 28 +-
llvm/test/CodeGen/AArch64/stack-hazard.ll | 51 +--
.../CodeGen/AArch64/stack-probing-dynamic.ll | 108 +++--
.../CodeGen/AArch64/stack-protector-target.ll | 6 +-
llvm/test/CodeGen/AArch64/sve-alloca.ll | 9 +-
.../CodeGen/AArch64/sve-stack-frame-layout.ll | 10 +-
.../AArch64/win-alloca-no-stack-probe.ll | 3 +-
llvm/test/CodeGen/AArch64/win-alloca.ll | 3 +-
llvm/test/CodeGen/AArch64/win-sve.ll | 6 +-
llvm/test/CodeGen/AArch64/win64_vararg.ll | 3 +-
27 files changed, 522 insertions(+), 299 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index dcd087a7ed4cb..198c9ec9a8e61 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7562,7 +7562,10 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
MachinePointerInfo(Global, 0), Align,
MachineMemOperand::MOVolatile);
}
- if (TLI.useStackGuardMixCookie())
+ // Mix the cookie with SP/FP if enabled. Skip if using LOAD_STACK_GUARD
+ // with post-RA mixing (AArch64 MSVCRT), as the mixing will be done during
+ // post-RA expansion of LOAD_STACK_GUARD.
+ if (TLI.useStackGuardMixCookie() && !TLI.useLoadStackGuardNode(M))
Res = TLI.emitStackGuardMixCookie(DAG, Res, sdl, false);
DAG.setRoot(Chain);
setValue(&I, Res);
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 6f489addfb5df..29517ce63c77d 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -5061,6 +5061,24 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
return;
break;
+ case ISD::SUB: {
+ // Check for stack guard unmixing pattern: SUB(CopyFromReg(SP), X)
+ // Select STACK_GUARD_UNMIX pseudo which will be expanded post-RA
+ SDValue N0 = Node->getOperand(0);
+ if (N0.getOpcode() == ISD::CopyFromReg) {
+ RegisterSDNode *R = dyn_cast<RegisterSDNode>(N0.getOperand(1));
+ if (R && R->getReg() == AArch64::SP && VT == MVT::i64) {
+ SDValue N1 = Node->getOperand(1);
+ SDValue Ops[] = {N1};
+ SDNode *ResNode = CurDAG->getMachineNode(
+ AArch64::STACK_GUARD_UNMIX, SDLoc(Node), MVT::i64, Ops);
+ ReplaceNode(Node, ResNode);
+ return;
+ }
+ }
+ break;
+ }
+
case ISD::EXTRACT_SUBVECTOR: {
if (trySelectCastScalableToFixedLengthVector(Node))
return;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 7a8189a76aa8b..be1a6ece81760 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -30719,7 +30719,9 @@ bool AArch64TargetLowering::useLoadStackGuardNode(const Module &M) const {
}
bool AArch64TargetLowering::useStackGuardMixCookie() const {
- // Currently only MSVC CRTs mix the frame pointer into the stack guard value.
+ // MSVC CRTs mix the stack pointer into the stack guard value.
+ // The prologue mixing is handled via post-RA expansion of LOAD_STACK_GUARD,
+ // but the epilogue unmixing is done at the DAG level via emitStackGuardMixCookie.
return Subtarget->getTargetTriple().isOSMSVCRT();
}
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 410d1040516b6..b3a76db3064c5 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -2456,7 +2456,8 @@ bool AArch64InstrInfo::removeCmpToZeroOrOne(
bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
- MI.getOpcode() != AArch64::CATCHRET)
+ MI.getOpcode() != AArch64::CATCHRET &&
+ MI.getOpcode() != AArch64::STACK_GUARD_UNMIX)
return false;
MachineBasicBlock &MBB = *MI.getParent();
@@ -2464,6 +2465,21 @@ bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
auto TRI = Subtarget.getRegisterInfo();
DebugLoc DL = MI.getDebugLoc();
+ if (MI.getOpcode() == AArch64::STACK_GUARD_UNMIX) {
+ // Expand STACK_GUARD_UNMIX to: sub Rd, sp, Rs
+ // This computes SP - stored_mixed_value to unmix the cookie
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
+
+ BuildMI(MBB, MI, DL, get(AArch64::SUBXrx64), DstReg)
+ .addReg(AArch64::SP)
+ .addReg(SrcReg)
+ .addImm(AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, 0));
+
+ MBB.erase(MI);
+ return true;
+ }
+
if (MI.getOpcode() == AArch64::CATCHRET) {
// Skip to the first instruction before the epilog.
const TargetInstrInfo *TII =
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 8e15ff98136fe..ee448dc1f6926 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2759,6 +2759,12 @@ def copyFromSP: PatLeaf<(i64 GPR64:$src), [{
cast<RegisterSDNode>(N->getOperand(1))->getReg() == AArch64::SP;
}]>;
+// Pseudo instruction for stack guard cookie unmixing (epilogue).
+// This will be expanded post-RA to use SP directly, avoiding an extra mov.
+// Pattern matching for this will be done via custom C++ code during instruction selection.
+def STACK_GUARD_UNMIX : Pseudo<(outs GPR64:$dst), (ins GPR64:$stored_val), []>,
+ Sched<[]>;
+
// Use SUBS instead of SUB to enable CSE between SUBS and SUB.
def : Pat<(sub GPR32sp:$Rn, addsub_shifted_imm32:$imm),
(SUBSWri GPR32sp:$Rn, addsub_shifted_imm32:$imm)>;
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
index 5eadc65b3de9c..267b2110d1582 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
@@ -18,12 +18,11 @@ define void @caller() sspreq {
; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: str x8, [sp, #8]
; CHECK-NEXT: bl callee
-; CHECK-NEXT: ldr x9, [sp, #8]
-; CHECK-NEXT: adrp x10, __security_cookie
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: ldr x10, [x10, :lo12:__security_cookie]
-; CHECK-NEXT: sub x8, x8, x9
-; CHECK-NEXT: cmp x10, x8
+; CHECK-NEXT: ldr x8, [sp, #8]
+; CHECK-NEXT: adrp x9, __security_cookie
+; CHECK-NEXT: ldr x9, [x9, :lo12:__security_cookie]
+; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: cmp x9, x8
; CHECK-NEXT: b.ne .LBB0_2
; CHECK-NEXT: // %bb.1: // %entry
; CHECK-NEXT: .seh_startepilogue
@@ -35,8 +34,7 @@ define void @caller() sspreq {
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB0_2: // %entry
; CHECK-NEXT: ldr x8, [sp, #8]
-; CHECK-NEXT: mov x9, sp
-; CHECK-NEXT: sub x0, x9, x8
+; CHECK-NEXT: sub x0, sp, x8
; CHECK-NEXT: bl __security_check_cookie
; CHECK-NEXT: brk #0x1
; CHECK-NEXT: .seh_endfunclet
diff --git a/llvm/test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll b/llvm/test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll
index 8da0e111357d0..adaf7f17d4a0f 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll
@@ -299,13 +299,12 @@ entry:
; CHECK: .cfi_offset w29, -32
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; CHECK: ubfiz x8, x0, #2, #32
+; CHECK: add x8, x8, #15
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
-; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
-; CHECK: mov x10, sp
-; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
+; CHECK: sub x[[VLASPTMP:[0-9]+]], sp, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through frame pointer
; CHECK: ldur w[[ILOC:[0-9]+]], [x29, #-4]
@@ -346,12 +345,11 @@ entry:
; CHECK: ubfiz x8, x0, #2, #32
; Check correctness of cfi pseudo-instructions
; Check correct access to arguments passed on the stack, through frame pointer
+; CHECK: add x8, x8, #15
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40]
-; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
-; CHECK: mov x10, sp
-; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
+; CHECK: sub x[[VLASPTMP:[0-9]+]], sp, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through frame pointer
; CHECK: ldur w[[ILOC:[0-9]+]], [x29, #-4]
@@ -406,12 +404,11 @@ entry:
; and set-up of base pointer (x19).
; CHECK: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
+; CHECK: add x8, x8, #15
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #56]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #72]
-; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
-; CHECK: mov x10, sp
-; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
+; CHECK: sub x[[VLASPTMP:[0-9]+]], sp, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [x19]
@@ -452,12 +449,11 @@ entry:
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
+; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
-; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: and x8, x8, #0x7fffffff0
-; CHECK-MACHO: mov x10, sp
-; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x8
+; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], sp, x8
; CHECK-MACHO: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19]
@@ -504,12 +500,11 @@ entry:
; and set-up of base pointer (x19).
; CHECK: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
+; CHECK: add x8, x8, #15
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
-; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
-; CHECK: mov x10, sp
-; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
+; CHECK: sub x[[VLASPTMP:[0-9]+]], sp, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [x19]
@@ -538,12 +533,11 @@ entry:
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
+; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
-; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: and x8, x8, #0x7fffffff0
-; CHECK-MACHO: mov x10, sp
-; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x8
+; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], sp, x8
; CHECK-MACHO: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19]
@@ -588,12 +582,11 @@ entry:
; and set-up of base pointer (x19).
; CHECK: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
+; CHECK: add x8, x8, #15
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
-; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
-; CHECK: mov x10, sp
-; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
+; CHECK: sub x[[VLASPTMP:[0-9]+]], sp, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [x19]
@@ -622,12 +615,11 @@ entry:
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
+; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
-; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: and x8, x8, #0x7fffffff0
-; CHECK-MACHO: mov x10, sp
-; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x8
+; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], sp, x8
; CHECK-MACHO: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19]
diff --git a/llvm/test/CodeGen/AArch64/alloca.ll b/llvm/test/CodeGen/AArch64/alloca.ll
index 119b84e352c74..6be49dc8e26ee 100644
--- a/llvm/test/CodeGen/AArch64/alloca.ll
+++ b/llvm/test/CodeGen/AArch64/alloca.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=aarch64-linux-gnu -disable-post-ra -verify-machineinstrs -o - %s | FileCheck %s
; RUN: llc -mtriple=arm64-apple-ios -disable-post-ra -verify-machineinstrs -o - %s | FileCheck %s --check-prefix=CHECK-MACHO
; RUN: llc -mtriple=aarch64-none-linux-gnu -disable-post-ra -mattr=-fp-armv8 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-NOFP-ARM64 %s
@@ -6,66 +7,224 @@ declare void @use_addr(ptr)
define void @test_simple_alloca(i64 %n) {
; CHECK-LABEL: test_simple_alloca:
+; CHECK: // %bb.0:
+; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
+; CHECK-NEXT: mov x29, sp
+; CHECK-NEXT: .cfi_def_cfa w29, 16
+; CHECK-NEXT: .cfi_offset w30, -8
+; CHECK-NEXT: .cfi_offset w29, -16
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x0, sp, x8
+; CHECK-NEXT: mov sp, x0
+; CHECK-NEXT: bl use_addr
+; CHECK-NEXT: mov sp, x29
+; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
+; CHECK-NEXT: ret
+;
+; CHECK-MACHO-LABEL: test_simple_alloca:
+; CHECK-MACHO: ; %bb.0:
+; CHECK-MACHO-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-MACHO-NEXT: mov x29, sp
+; CHECK-MACHO-NEXT: .cfi_def_cfa w29, 16
+; CHECK-MACHO-NEXT: .cfi_offset w30, -8
+; CHECK-MACHO-NEXT: .cfi_offset w29, -16
+; CHECK-MACHO-NEXT: add x8, x0, #15
+; CHECK-MACHO-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-MACHO-NEXT: sub x0, sp, x8
+; CHECK-MACHO-NEXT: mov sp, x0
+; CHECK-MACHO-NEXT: bl _use_addr
+; CHECK-MACHO-NEXT: mov sp, x29
+; CHECK-MACHO-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-MACHO-NEXT: ret
+;
+; CHECK-NOFP-ARM64-LABEL: test_simple_alloca:
+; CHECK-NOFP-ARM64: // %bb.0:
+; CHECK-NOFP-ARM64-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
+; CHECK-NOFP-ARM64-NEXT: mov x29, sp
+; CHECK-NOFP-ARM64-NEXT: .cfi_def_cfa w29, 16
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w30, -8
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w29, -16
+; CHECK-NOFP-ARM64-NEXT: add x8, x0, #15
+; CHECK-NOFP-ARM64-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NOFP-ARM64-NEXT: sub x0, sp, x8
+; CHECK-NOFP-ARM64-NEXT: mov sp, x0
+; CHECK-NOFP-ARM64-NEXT: bl use_addr
+; CHECK-NOFP-ARM64-NEXT: mov sp, x29
+; CHECK-NOFP-ARM64-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
+; CHECK-NOFP-ARM64-NEXT: ret
%buf = alloca i8, i64 %n
; Make sure we align the stack change to 16 bytes:
-; CHECK: {{mov|add}} x29
-; CHECK: mov [[TMP:x[0-9]+]], sp
-; CHECK: add [[SPDELTA_TMP:x[0-9]+]], x0, #15
-; CHECK: and [[SPDELTA:x[0-9]+]], [[SPDELTA_TMP]], #0xfffffffffffffff0
; Make sure we change SP. It would be surprising if anything but x0 were used
; for the final sp, but it could be if it was then moved into x0.
-; CHECK: sub [[NEWSP:x[0-9]+]], [[TMP]], [[SPDELTA]]
-; CHECK: mov sp, [[NEWSP]]
call void @use_addr(ptr %buf)
-; CHECK: bl use_addr
ret void
; Make sure epilogue restores sp from fp
-; CHECK: {{sub|mov}} sp, x29
-; CHECK: ret
}
declare void @use_addr_loc(ptr, ptr)
define i64 @test_alloca_with_local(i64 %n) {
; CHECK-LABEL: test_alloca_with_local:
-; CHECK-DAG: sub sp, sp, [[LOCAL_STACK:#[0-9]+]]
-; CHECK-DAG: {{mov|add}} x29, sp
+; CHECK: // %bb.0:
+; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
+; CHECK-NEXT: mov x29, sp
+; CHECK-NEXT: sub sp, sp, #16
+; CHECK-NEXT: .cfi_def_cfa w29, 16
+; CHECK-NEXT: .cfi_offset w30, -8
+; CHECK-NEXT: .cfi_offset w29, -16
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x0, sp, x8
+; CHECK-NEXT: mov sp, x0
+; CHECK-NEXT: sub x1, x29, #8
+; CHECK-NEXT: bl use_addr_loc
+; CHECK-NEXT: ldur x0, [x29, #-8]
+; CHECK-NEXT: mov sp, x29
+; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
+; CHECK-NEXT: ret
+;
+; CHECK-MACHO-LABEL: test_alloca_with_local:
+; CHECK-MACHO: ; %bb.0:
+; CHECK-MACHO-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-MACHO-NEXT: mov x29, sp
+; CHECK-MACHO-NEXT: sub sp, sp, #16
+; CHECK-MACHO-NEXT: .cfi_def_cfa w29, 16
+; CHECK-MACHO-NEXT: .cfi_offset w30, -8
+; CHECK-MACHO-NEXT: .cfi_offset w29, -16
+; CHECK-MACHO-NEXT: add x8, x0, #15
+; CHECK-MACHO-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-MACHO-NEXT: sub x0, sp, x8
+; CHECK-MACHO-NEXT: mov sp, x0
+; CHECK-MACHO-NEXT: sub x1, x29, #8
+; CHECK-MACHO-NEXT: bl _use_addr_loc
+; CHECK-MACHO-NEXT: ldur x0, [x29, #-8]
+; CHECK-MACHO-NEXT: mov sp, x29
+; CHECK-MACHO-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-MACHO-NEXT: ret
+;
+; CHECK-NOFP-ARM64-LABEL: test_alloca_with_local:
+; CHECK-NOFP-ARM64: // %bb.0:
+; CHECK-NOFP-ARM64-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
+; CHECK-NOFP-ARM64-NEXT: mov x29, sp
+; CHECK-NOFP-ARM64-NEXT: sub sp, sp, #16
+; CHECK-NOFP-ARM64-NEXT: .cfi_def_cfa w29, 16
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w30, -8
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w29, -16
+; CHECK-NOFP-ARM64-NEXT: add x8, x0, #15
+; CHECK-NOFP-ARM64-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NOFP-ARM64-NEXT: sub x0, sp, x8
+; CHECK-NOFP-ARM64-NEXT: mov sp, x0
+; CHECK-NOFP-ARM64-NEXT: sub x1, x29, #8
+; CHECK-NOFP-ARM64-NEXT: bl use_addr_loc
+; CHECK-NOFP-ARM64-NEXT: ldur x0, [x29, #-8]
+; CHECK-NOFP-ARM64-NEXT: mov sp, x29
+; CHECK-NOFP-ARM64-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
+; CHECK-NOFP-ARM64-NEXT: ret
%loc = alloca i64
%buf = alloca i8, i64 %n
; Make sure we align the stack change to 16 bytes:
-; CHECK: mov [[TMP:x[0-9]+]], sp
-; CHECK: add [[SPDELTA_TMP:x[0-9]+]], x0, #15
-; CHECK: and [[SPDELTA:x[0-9]+]], [[SPDELTA_TMP]], #0xfffffffffffffff0
; Make sure we change SP. It would be surprising if anything but x0 were used
; for the final sp, but it could be if it was then moved into x0.
-; CHECK: sub [[NEWSP:x[0-9]+]], [[TMP]], [[SPDELTA]]
-; CHECK: mov sp, [[NEWSP]]
-; CHECK: sub {{x[0-9]+}}, x29, #[[LOC_FROM_FP:[0-9]+]]
call void @use_addr_loc(ptr %buf, ptr %loc)
-; CHECK: bl use_addr
%val = load i64, ptr %loc
-; CHECK: ldur x0, [x29, #-[[LOC_FROM_FP]]]
ret i64 %val
; Make sure epilogue restores sp from fp
-; CHECK: {{sub|mov}} sp, x29
-; CHECK: ret
}
%struct.__va_list = type { ptr, ptr, ptr, i32, i32 }
define void @test_variadic_alloca(i64 %n, ...) {
; CHECK-LABEL: test_variadic_alloca:
+; CHECK: // %bb.0:
+; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
+; CHECK-NEXT: mov x29, sp
+; CHECK-NEXT: sub sp, sp, #224
+; CHECK-NEXT: .cfi_def_cfa w29, 16
+; CHECK-NEXT: .cfi_offset w30, -8
+; CHECK-NEXT: .cfi_offset w29, -16
+; CHECK-NEXT: stp x1, x2, [x29, #-88]
+; CHECK-NEXT: stp x3, x4, [x29, #-72]
+; CHECK-NEXT: stp x5, x6, [x29, #-56]
+; CHECK-NEXT: stp q0, q1, [x29, #-224]
+; CHECK-NEXT: stp q2, q3, [x29, #-192]
+; CHECK-NEXT: stp q4, q5, [x29, #-160]
+; CHECK-NEXT: stp q6, q7, [x29, #-128]
+; CHECK-NEXT: mov x8, #-56 // =0xffffffffffffffc8
+; CHECK-NEXT: movk x8, #65408, lsl #32
+; CHECK-NEXT: sub x9, x29, #224
+; CHECK-NEXT: add x9, x9, #128
+; CHECK-NEXT: sub x10, x29, #88
+; CHECK-NEXT: stp x9, x8, [x29, #-16]
+; CHECK-NEXT: add x8, x10, #56
+; CHECK-NEXT: add x9, x29, #16
+; CHECK-NEXT: stur x8, [x29, #-24]
+; CHECK-NEXT: stp x7, x9, [x29, #-40]
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x0, sp, x8
+; CHECK-NEXT: mov sp, x0
+; CHECK-NEXT: bl use_addr
+; CHECK-NEXT: mov sp, x29
+; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
+; CHECK-NEXT: ret
+;
+; CHECK-MACHO-LABEL: test_variadic_alloca:
+; CHECK-MACHO: ; %bb.0:
+; CHECK-MACHO-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-MACHO-NEXT: mov x29, sp
+; CHECK-MACHO-NEXT: sub sp, sp, #32
+; CHECK-MACHO-NEXT: .cfi_def_cfa w29, 16
+; CHECK-MACHO-NEXT: .cfi_offset w30, -8
+; CHECK-MACHO-NEXT: .cfi_offset w29, -16
+; CHECK-MACHO-NEXT: add x8, x29, #16
+; CHECK-MACHO-NEXT: stur x8, [x29, #-32]
+; CHECK-MACHO-NEXT: add x8, x0, #15
+; CHECK-MACHO-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-MACHO-NEXT: sub x0, sp, x8
+; CHECK-MACHO-NEXT: mov sp, x0
+; CHECK-MACHO-NEXT: bl _use_addr
+; CHECK-MACHO-NEXT: mov sp, x29
+; CHECK-MACHO-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-MACHO-NEXT: ret
+;
+; CHECK-NOFP-ARM64-LABEL: test_variadic_alloca:
+; CHECK-NOFP-ARM64: // %bb.0:
+; CHECK-NOFP-ARM64-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
+; CHECK-NOFP-ARM64-NEXT: mov x29, sp
+; CHECK-NOFP-ARM64-NEXT: sub sp, sp, #96
+; CHECK-NOFP-ARM64-NEXT: .cfi_def_cfa w29, 16
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w30, -8
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w29, -16
+; CHECK-NOFP-ARM64-NEXT: stp x1, x2, [x29, #-88]
+; CHECK-NOFP-ARM64-NEXT: stp x3, x4, [x29, #-72]
+; CHECK-NOFP-ARM64-NEXT: stp x5, x6, [x29, #-56]
+; CHECK-NOFP-ARM64-NEXT: add x8, x29, #16
+; CHECK-NOFP-ARM64-NEXT: sub x9, x29, #88
+; CHECK-NOFP-ARM64-NEXT: add x9, x9, #56
+; CHECK-NOFP-ARM64-NEXT: stp x7, x8, [x29, #-40]
+; CHECK-NOFP-ARM64-NEXT: stur x9, [x29, #-24]
+; CHECK-NOFP-ARM64-NEXT: mov w8, #-56 // =0xffffffc8
+; CHECK-NOFP-ARM64-NEXT: stur x8, [x29, #-8]
+; CHECK-NOFP-ARM64-NEXT: add x8, x0, #15
+; CHECK-NOFP-ARM64-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NOFP-ARM64-NEXT: sub x0, sp, x8
+; CHECK-NOFP-ARM64-NEXT: mov sp, x0
+; CHECK-NOFP-ARM64-NEXT: bl use_addr
+; CHECK-NOFP-ARM64-NEXT: mov sp, x29
+; CHECK-NOFP-ARM64-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
+; CHECK-NOFP-ARM64-NEXT: ret
; [...]
@@ -77,33 +236,18 @@ define void @test_variadic_alloca(i64 %n, ...) {
; CHECK-NOFP-AARCH64: add x8, [[TMP]], #0
-; CHECK: stp x29, x30, [sp, #-16]!
-; CHECK: mov x29, sp
-; CHECK: sub sp, sp, #224
-; CHECK-DAG: stp q6, q7, [x29, #-128]
; [...]
-; CHECK-DAG: stp q2, q3, [x29, #-192]
-; CHECK-DAG: stp x5, x6, [x29, #-56]
; [...]
-; CHECK-DAG: stp x1, x2, [x29, #-88]
-; CHECK-NOFP-ARM64: stp x29, x30, [sp, #-16]!
-; CHECK-NOFP-ARM64: mov x29, sp
-; CHECK-NOFP-ARM64: sub sp, sp, #16
-; CHECK-NOFP-ARM64-DAG: stp x5, x6, [x29, #-56]
; [...]
-; CHECK-NOFP-ARM64-DAG: stp x3, x4, [x29, #-72]
; [...]
-; CHECK-NOFP-ARM64-DAG: stp x1, x2, [x29, #-88]
; [...]
-; CHECK-NOFP-ARM64: mov x8, sp
%valist = alloca %struct.__va_list
call void @llvm.va_start(ptr %valist)
%addr = alloca i8, i64 %n
call void @use_addr(ptr %addr)
-; CHECK: bl use_addr
call void @llvm.va_end(ptr %valist)
ret void
@@ -112,26 +256,83 @@ define void @test_variadic_alloca(i64 %n, ...) {
; CHECK-NOFP-AARCH64: ldp x29, x30, [sp, #64]
; CHECK-NOFP-AARCH64: add sp, sp, #80
-; CHECK-NOFP-ARM64: mov sp, x29
-; CHECK-NOFP-ARM64: ldp x29, x30, [sp], #16
}
define void @test_alloca_large_frame(i64 %n) {
; CHECK-LABEL: test_alloca_large_frame:
+; CHECK: // %bb.0:
+; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
+; CHECK-NEXT: stp x28, x19, [sp, #16] // 16-byte Folded Spill
+; CHECK-NEXT: mov x29, sp
+; CHECK-NEXT: sub sp, sp, #1953, lsl #12 // =7999488
+; CHECK-NEXT: sub sp, sp, #512
+; CHECK-NEXT: mov x19, sp
+; CHECK-NEXT: .cfi_def_cfa w29, 32
+; CHECK-NEXT: .cfi_offset w19, -8
+; CHECK-NEXT: .cfi_offset w28, -16
+; CHECK-NEXT: .cfi_offset w30, -24
+; CHECK-NEXT: .cfi_offset w29, -32
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x0, sp, x8
+; CHECK-NEXT: mov sp, x0
+; CHECK-NEXT: add x1, x19, #0
+; CHECK-NEXT: bl use_addr_loc
+; CHECK-NEXT: mov sp, x29
+; CHECK-NEXT: ldp x28, x19, [sp, #16] // 16-byte Folded Reload
+; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
+; CHECK-NEXT: ret
+;
; CHECK-MACHO-LABEL: test_alloca_large_frame:
+; CHECK-MACHO: ; %bb.0:
+; CHECK-MACHO-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
+; CHECK-MACHO-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill
+; CHECK-MACHO-NEXT: add x29, sp, #16
+; CHECK-MACHO-NEXT: sub sp, sp, #1953, lsl #12 ; =7999488
+; CHECK-MACHO-NEXT: sub sp, sp, #512
+; CHECK-MACHO-NEXT: mov x19, sp
+; CHECK-MACHO-NEXT: .cfi_def_cfa w29, 16
+; CHECK-MACHO-NEXT: .cfi_offset w30, -8
+; CHECK-MACHO-NEXT: .cfi_offset w29, -16
+; CHECK-MACHO-NEXT: .cfi_offset w19, -24
+; CHECK-MACHO-NEXT: .cfi_offset w20, -32
+; CHECK-MACHO-NEXT: add x8, x0, #15
+; CHECK-MACHO-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-MACHO-NEXT: sub x0, sp, x8
+; CHECK-MACHO-NEXT: mov sp, x0
+; CHECK-MACHO-NEXT: add x1, x19, #0
+; CHECK-MACHO-NEXT: bl _use_addr_loc
+; CHECK-MACHO-NEXT: sub sp, x29, #16
+; CHECK-MACHO-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
+; CHECK-MACHO-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
+; CHECK-MACHO-NEXT: ret
+;
+; CHECK-NOFP-ARM64-LABEL: test_alloca_large_frame:
+; CHECK-NOFP-ARM64: // %bb.0:
+; CHECK-NOFP-ARM64-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
+; CHECK-NOFP-ARM64-NEXT: stp x28, x19, [sp, #16] // 16-byte Folded Spill
+; CHECK-NOFP-ARM64-NEXT: mov x29, sp
+; CHECK-NOFP-ARM64-NEXT: sub sp, sp, #1953, lsl #12 // =7999488
+; CHECK-NOFP-ARM64-NEXT: sub sp, sp, #512
+; CHECK-NOFP-ARM64-NEXT: mov x19, sp
+; CHECK-NOFP-ARM64-NEXT: .cfi_def_cfa w29, 32
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w19, -8
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w28, -16
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w30, -24
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w29, -32
+; CHECK-NOFP-ARM64-NEXT: add x8, x0, #15
+; CHECK-NOFP-ARM64-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NOFP-ARM64-NEXT: sub x0, sp, x8
+; CHECK-NOFP-ARM64-NEXT: mov sp, x0
+; CHECK-NOFP-ARM64-NEXT: add x1, x19, #0
+; CHECK-NOFP-ARM64-NEXT: bl use_addr_loc
+; CHECK-NOFP-ARM64-NEXT: mov sp, x29
+; CHECK-NOFP-ARM64-NEXT: ldp x28, x19, [sp, #16] // 16-byte Folded Reload
+; CHECK-NOFP-ARM64-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
+; CHECK-NOFP-ARM64-NEXT: ret
-; CHECK: stp x29, x30, [sp, #-32]!
-; CHECK: stp x28, x19, [sp, #16]
-; CHECK: mov x29, sp
-; CHECK: sub sp, sp, #1953, lsl #12
-; CHECK: sub sp, sp, #512
-; CHECK-MACHO: stp x20, x19, [sp, #-32]!
-; CHECK-MACHO: stp x29, x30, [sp, #16]
-; CHECK-MACHO: add x29, sp, #16
-; CHECK-MACHO: sub sp, sp, #1953, lsl #12
-; CHECK-MACHO: sub sp, sp, #512
%addr1 = alloca i8, i64 %n
%addr2 = alloca i64, i64 1000000
@@ -140,13 +341,7 @@ define void @test_alloca_large_frame(i64 %n) {
ret void
-; CHECK: mov sp, x29
-; CHECK: ldp x28, x19, [sp, #16]
-; CHECK: ldp x29, x30, [sp], #32
-; CHECK-MACHO: sub sp, x29, #16
-; CHECK-MACHO: ldp x29, x30, [sp, #16]
-; CHECK-MACHO: ldp x20, x19, [sp], #32
}
declare ptr @llvm.stacksave()
@@ -154,22 +349,76 @@ declare void @llvm.stackrestore(ptr)
define void @test_scoped_alloca(i64 %n) {
; CHECK-LABEL: test_scoped_alloca:
+; CHECK: // %bb.0:
+; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
+; CHECK-NEXT: str x19, [sp, #16] // 8-byte Spill
+; CHECK-NEXT: mov x29, sp
+; CHECK-NEXT: .cfi_def_cfa w29, 32
+; CHECK-NEXT: .cfi_offset w19, -16
+; CHECK-NEXT: .cfi_offset w30, -24
+; CHECK-NEXT: .cfi_offset w29, -32
+; CHECK-NEXT: mov x19, sp
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x0, sp, x8
+; CHECK-NEXT: mov sp, x0
+; CHECK-NEXT: bl use_addr
+; CHECK-NEXT: mov sp, x19
+; CHECK-NEXT: mov sp, x29
+; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
+; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
+; CHECK-NEXT: ret
+;
+; CHECK-MACHO-LABEL: test_scoped_alloca:
+; CHECK-MACHO: ; %bb.0:
+; CHECK-MACHO-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
+; CHECK-MACHO-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill
+; CHECK-MACHO-NEXT: add x29, sp, #16
+; CHECK-MACHO-NEXT: .cfi_def_cfa w29, 16
+; CHECK-MACHO-NEXT: .cfi_offset w30, -8
+; CHECK-MACHO-NEXT: .cfi_offset w29, -16
+; CHECK-MACHO-NEXT: .cfi_offset w19, -24
+; CHECK-MACHO-NEXT: .cfi_offset w20, -32
+; CHECK-MACHO-NEXT: mov x19, sp
+; CHECK-MACHO-NEXT: add x8, x0, #15
+; CHECK-MACHO-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-MACHO-NEXT: sub x0, sp, x8
+; CHECK-MACHO-NEXT: mov sp, x0
+; CHECK-MACHO-NEXT: bl _use_addr
+; CHECK-MACHO-NEXT: mov sp, x19
+; CHECK-MACHO-NEXT: sub sp, x29, #16
+; CHECK-MACHO-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
+; CHECK-MACHO-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
+; CHECK-MACHO-NEXT: ret
+;
+; CHECK-NOFP-ARM64-LABEL: test_scoped_alloca:
+; CHECK-NOFP-ARM64: // %bb.0:
+; CHECK-NOFP-ARM64-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
+; CHECK-NOFP-ARM64-NEXT: str x19, [sp, #16] // 8-byte Spill
+; CHECK-NOFP-ARM64-NEXT: mov x29, sp
+; CHECK-NOFP-ARM64-NEXT: .cfi_def_cfa w29, 32
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w19, -16
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w30, -24
+; CHECK-NOFP-ARM64-NEXT: .cfi_offset w29, -32
+; CHECK-NOFP-ARM64-NEXT: mov x19, sp
+; CHECK-NOFP-ARM64-NEXT: add x8, x0, #15
+; CHECK-NOFP-ARM64-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NOFP-ARM64-NEXT: sub x0, sp, x8
+; CHECK-NOFP-ARM64-NEXT: mov sp, x0
+; CHECK-NOFP-ARM64-NEXT: bl use_addr
+; CHECK-NOFP-ARM64-NEXT: mov sp, x19
+; CHECK-NOFP-ARM64-NEXT: mov sp, x29
+; CHECK-NOFP-ARM64-NEXT: ldr x19, [sp, #16] // 8-byte Reload
+; CHECK-NOFP-ARM64-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
+; CHECK-NOFP-ARM64-NEXT: ret
%sp = call ptr @llvm.stacksave()
-; CHECK: mov x29, sp
-; CHECK: mov [[SAVED_SP:x[0-9]+]], sp
-; CHECK: mov [[OLDSP:x[0-9]+]], sp
%addr = alloca i8, i64 %n
-; CHECK: and [[SPDELTA:x[0-9]+]], {{x[0-9]+}}, #0xfffffffffffffff0
-; CHECK-DAG: sub [[NEWSP:x[0-9]+]], [[OLDSP]], [[SPDELTA]]
-; CHECK: mov sp, [[NEWSP]]
call void @use_addr(ptr %addr)
-; CHECK: bl use_addr
call void @llvm.stackrestore(ptr %sp)
-; CHECK: mov sp, [[SAVED_SP]]
ret void
}
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
index e29e7acc5476f..26239d2633241 100644
--- a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
+++ b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
@@ -1,22 +1,7 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s
define void @simple(ptr %g) {
-; CHECK-LABEL: "#simple":
-; CHECK: str x30, [sp, #-16]!
-; CHECK-NEXT: .seh_save_reg_x x30, 16
-; CHECK-NEXT: .seh_endprologue
-; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
-; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$v$v
-; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$v$v
-; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
-; CHECK-NEXT: mov x11, x0
-; CHECK-NEXT: blr x8
-; CHECK-NEXT: blr x11
-; CHECK-NEXT: .seh_startepilogue
-; CHECK-NEXT: ldr x30, [sp], #16
-; CHECK-NEXT: .seh_save_reg_x x30, 16
-; CHECK-NEXT: .seh_endepilogue
-; CHECK-NEXT: ret
entry:
call void %g()
@@ -25,28 +10,10 @@ entry:
; Make sure the check for the security cookie doesn't use x9.
define void @stackguard(ptr %g) sspreq {
-; CHECK-LABEL: "#stackguard":
-; CHECK: adrp x8, __os_arm64x_check_icall
-; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
-; CHECK-NEXT: blr x8
-; CHECK-NEXT: ldr x10, [sp, #8]
-; CHECK-NEXT: adrp x12, __security_cookie
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: ldr x12, [x12, :lo12:__security_cookie]
-; CHECK-NEXT: sub x8, x8, x10
-; CHECK-NEXT: cmp x12, x8
-; CHECK-NEXT: b.ne .LBB1_2
-; CHECK-NEXT: // %bb.1:
-; CHECK-NEXT: fmov d0, #1.00000000
-; CHECK-NEXT: .seh_startepilogue
-; CHECK-NEXT: ldr x30, [sp, #16]
-; CHECK-NEXT: .seh_save_reg x30, 16
-; CHECK-NEXT: add sp, sp, #32
-; CHECK-NEXT: .seh_stackalloc 32
-; CHECK-NEXT: .seh_endepilogue
-; CHECK-NEXT: br x11
entry:
%call = tail call double %g(double noundef 1.000000e+00)
ret void
}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/mingw-refptr.ll b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
index dac8e057b93fc..8074bf1ade154 100644
--- a/llvm/test/CodeGen/AArch64/mingw-refptr.ll
+++ b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
@@ -93,11 +93,10 @@ define dso_local void @sspFunc() #0 {
; CHECK-SD-NEXT: str x8, [sp, #8]
; CHECK-SD-NEXT: bl ptrUser
; CHECK-SD-NEXT: adrp x9, .refptr.__stack_chk_guard
-; CHECK-SD-NEXT: mov x8, sp
+; CHECK-SD-NEXT: ldr x8, [sp, #8]
; CHECK-SD-NEXT: ldr x9, [x9, :lo12:.refptr.__stack_chk_guard]
-; CHECK-SD-NEXT: ldr x10, [sp, #8]
+; CHECK-SD-NEXT: sub x8, sp, x8
; CHECK-SD-NEXT: ldr x9, [x9]
-; CHECK-SD-NEXT: sub x8, x8, x10
; CHECK-SD-NEXT: cmp x9, x8
; CHECK-SD-NEXT: b.ne .LBB6_2
; CHECK-SD-NEXT: // %bb.1: // %entry
diff --git a/llvm/test/CodeGen/AArch64/shrink-wrapping-vla.ll b/llvm/test/CodeGen/AArch64/shrink-wrapping-vla.ll
index c21ccfe522d74..5075bc9879e78 100644
--- a/llvm/test/CodeGen/AArch64/shrink-wrapping-vla.ll
+++ b/llvm/test/CodeGen/AArch64/shrink-wrapping-vla.ll
@@ -87,12 +87,11 @@ declare void @llvm.stackrestore(ptr)
; VLA allocation
; CHECK: ubfiz x8, x0, #2, #32
-; CHECK: mov x9, sp
+; Saving the SP via llvm.stacksave()
; CHECK: mov [[SAVE:x[0-9]+]], sp
; CHECK: add x8, x8, #15
; CHECK: and [[X1:x[0-9]+]], [[X1]], #0x7fffffff0
-; Saving the SP via llvm.stacksave()
-; CHECK: sub [[X1]], [[X2:x[0-9]+]], [[X1]]
+; CHECK: sub [[X1]], sp, [[X1]]
; The next instruction comes from llvm.stackrestore()
; CHECK: mov sp, [[SAVE]]
diff --git a/llvm/test/CodeGen/AArch64/sme-agnostic-za.ll b/llvm/test/CodeGen/AArch64/sme-agnostic-za.ll
index e9d7971560474..c01314373266d 100644
--- a/llvm/test/CodeGen/AArch64/sme-agnostic-za.ll
+++ b/llvm/test/CodeGen/AArch64/sme-agnostic-za.ll
@@ -212,8 +212,7 @@ define void @agnostic_za_buffer_alloc_with_stack_probes() nounwind "aarch64_za_s
; CHECK-NEXT: str x19, [sp, #16] // 8-byte Spill
; CHECK-NEXT: mov x29, sp
; CHECK-NEXT: bl __arm_sme_state_size
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: sub x19, x8, x0
+; CHECK-NEXT: sub x19, sp, x0
; CHECK-NEXT: .LBB7_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #16, lsl #12 // =65536
; CHECK-NEXT: cmp sp, x19
diff --git a/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll b/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll
index 301eee43d33e6..083da3335ba54 100644
--- a/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll
+++ b/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll
@@ -18,10 +18,10 @@ define void @quux(i64 %n) "aarch64_new_za" "aarch64_pstate_sm_enabled" {
; CHECK-NEXT: .cfi_offset w19, -16
; CHECK-NEXT: .cfi_offset w30, -24
; CHECK-NEXT: .cfi_offset w29, -32
+; CHECK-NEXT: // kill: def $x1 killed $sp
; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x9, x8, #0xfffffffffffffff0
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: subs x8, x8, x9
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: mov sp, x29
diff --git a/llvm/test/CodeGen/AArch64/sme-lazy-save-windows.ll b/llvm/test/CodeGen/AArch64/sme-lazy-save-windows.ll
index 6e2d2c0269757..75ad7c01829db 100644
--- a/llvm/test/CodeGen/AArch64/sme-lazy-save-windows.ll
+++ b/llvm/test/CodeGen/AArch64/sme-lazy-save-windows.ll
@@ -15,7 +15,8 @@ define void @test_lazy_save() nounwind "aarch64_inout_za" {
; CHECK-NEXT: mul x9, x8, x8
; CHECK-NEXT: lsr x15, x9, #4
; CHECK-NEXT: bl __chkstk
-; CHECK-NEXT: sub x9, sp, x15, lsl #4
+; CHECK-NEXT: lsl x9, x15, #4
+; CHECK-NEXT: sub x9, sp, x9
; CHECK-NEXT: mov sp, x9
; CHECK-NEXT: sub x10, x29, #24
; CHECK-NEXT: stp x9, x8, [x29, #-24]
diff --git a/llvm/test/CodeGen/AArch64/sme-streaming-mode-changing-call-disable-stackslot-scavenging.ll b/llvm/test/CodeGen/AArch64/sme-streaming-mode-changing-call-disable-stackslot-scavenging.ll
index 72f0eac9b659c..3ec2ea9ff57ce 100644
--- a/llvm/test/CodeGen/AArch64/sme-streaming-mode-changing-call-disable-stackslot-scavenging.ll
+++ b/llvm/test/CodeGen/AArch64/sme-streaming-mode-changing-call-disable-stackslot-scavenging.ll
@@ -57,13 +57,12 @@ define void @test_no_stackslot_scavenging_with_fp(float %f, i64 %n) #0 "frame-po
; CHECK-NEXT: stp x24, x19, [sp, #96] // 16-byte Folded Spill
; CHECK-NEXT: sub sp, sp, #16
; CHECK-NEXT: addvl sp, sp, #-1
-; CHECK-NEXT: lsl x9, x0, #3
-; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: lsl x8, x0, #3
; CHECK-NEXT: mov x19, sp
; CHECK-NEXT: str s0, [x19, #12] // 4-byte Spill
-; CHECK-NEXT: add x9, x9, #15
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: add x8, x8, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: //APP
; CHECK-NEXT: //NO_APP
diff --git a/llvm/test/CodeGen/AArch64/sme-za-lazy-save-buffer.ll b/llvm/test/CodeGen/AArch64/sme-za-lazy-save-buffer.ll
index 27082d9af93b3..6d5bf42536e43 100644
--- a/llvm/test/CodeGen/AArch64/sme-za-lazy-save-buffer.ll
+++ b/llvm/test/CodeGen/AArch64/sme-za-lazy-save-buffer.ll
@@ -72,8 +72,8 @@ define float @multi_bb_stpidr2_save_required_stackprobe(i32 %a, float %b, float
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
; CHECK-NEXT: rdsvl x8, #1
-; CHECK-NEXT: mov x9, sp
-; CHECK-NEXT: msub x9, x8, x8, x9
+; CHECK-NEXT: mul x9, x8, x8
+; CHECK-NEXT: sub x9, sp, x9
; CHECK-NEXT: .LBB2_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #16, lsl #12 // =65536
; CHECK-NEXT: cmp sp, x9
diff --git a/llvm/test/CodeGen/AArch64/split-sve-stack-frame-layout.ll b/llvm/test/CodeGen/AArch64/split-sve-stack-frame-layout.ll
index c237248085df3..dd90ec2c887df 100644
--- a/llvm/test/CodeGen/AArch64/split-sve-stack-frame-layout.ll
+++ b/llvm/test/CodeGen/AArch64/split-sve-stack-frame-layout.ll
@@ -811,10 +811,9 @@ define aarch64_sve_vector_pcs void @only_ppr_csr_vla(i64 %n) {
; CHECK-NEXT: .cfi_offset w19, -16
; CHECK-NEXT: .cfi_offset w30, -24
; CHECK-NEXT: .cfi_offset w29, -32
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: //APP
@@ -856,10 +855,9 @@ define aarch64_sve_vector_pcs void @only_zpr_csr_vla(i64 %n) {
; CHECK-NEXT: .cfi_escape 0x10, 0x48, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x78, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d8 @ cfa - 8 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x49, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x70, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d9 @ cfa - 16 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x4a, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x68, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d10 @ cfa - 24 * VG - 1056
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: sub x8, x29, #1024
@@ -908,10 +906,9 @@ define aarch64_sve_vector_pcs void @zpr_ppr_csr_vla(i64 %n) {
; CHECK-NEXT: .cfi_escape 0x10, 0x48, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x70, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d8 @ cfa - 16 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x49, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x68, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d9 @ cfa - 24 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x4a, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x60, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d10 @ cfa - 32 * VG - 1056
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: sub x8, x29, #1024
@@ -957,10 +954,9 @@ define void @sve_locals_only_ppr_csr_vla(i64 %n, <vscale x 16 x i1> %pred, <vsca
; CHECK-NEXT: .cfi_offset w19, -16
; CHECK-NEXT: .cfi_offset w30, -24
; CHECK-NEXT: .cfi_offset w29, -32
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: sub x8, x29, #1024
@@ -1011,10 +1007,9 @@ define void @sve_locals_only_zpr_csr_vla(i64 %n, <vscale x 16 x i1> %pred, <vsca
; CHECK-NEXT: .cfi_escape 0x10, 0x48, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x70, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d8 @ cfa - 16 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x49, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x68, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d9 @ cfa - 24 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x4a, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x60, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d10 @ cfa - 32 * VG - 1056
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: sub x8, x29, #1024
@@ -1070,10 +1065,9 @@ define void @sve_locals_zpr_ppr_csr_vla(i64 %n, <vscale x 16 x i1> %pred, <vscal
; CHECK-NEXT: .cfi_escape 0x10, 0x48, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x68, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d8 @ cfa - 24 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x49, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x60, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d9 @ cfa - 32 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x4a, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x58, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d10 @ cfa - 40 * VG - 1056
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: add x8, x0, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: sub x8, x29, #1024
diff --git a/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll b/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
index 44bd696640113..9dbeac976bf4d 100644
--- a/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
+++ b/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
@@ -55,17 +55,16 @@ define dso_local void @foo(i64 %t) local_unnamed_addr #0 {
; CHECK-TPIDR0: mrs x8, TPIDR_EL0
; CHECK-TPIDR1: mrs x8, TPIDR_EL1
; CHECK-TPIDR2: mrs x8, TPIDR_EL2
-; CHECK-NEXT: lsl x9, x0, #2
-; CHECK-NO-OFFSET: ldr x8, [x8]
-; CHECK-POSITIVE-OFFSET: ldr x8, [x8, #8]
-; CHECK-NEGATIVE-OFFSET: ldur x8, [x8, #-8]
-; CHECK-NPOT-OFFSET: ldur x8, [x8, #1]
-; CHECK-NPOT-NEG-OFFSET: ldur x8, [x8, #-1]
-; CHECK-NEXT: add x9, x9, #15
+; CHECK-NO-OFFSET-NEXT: ldr x8, [x8]
+; CHECK-POSITIVE-OFFSET-NEXT: ldr x8, [x8, #8]
+; CHECK-NEGATIVE-OFFSET-NEXT: ldur x8, [x8, #-8]
+; CHECK-NPOT-OFFSET-NEXT: ldur x8, [x8, #1]
+; CHECK-NPOT-NEG-OFFSET-NEXT: ldur x8, [x8, #-1]
; CHECK-NEXT: stur x8, [x29, #-8]
-; CHECK-NEXT mov x8, sp
-; CHECK-NEXT and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT sub x0, x8, x9
+; CHECK-NEXT: lsl x8, x0, #2
+; CHECK-NEXT: add x8, x8, #15
+; CHECK-NEXT and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT sub x0, sp, x8
; CHECK-NEXT mov sp, x0
; CHECK-NEXT bl baz
; CHECK-SP: mrs x8, SP_EL0
@@ -109,15 +108,14 @@ define dso_local void @foo(i64 %t) local_unnamed_addr #0 {
; CHECK-ADD-NEXT: sub sp, sp, #16
; CHECK-FAR1: mrs x8, FAR_EL1
; CHECK-FAR2: mrs x8, FAR_EL2
-; CHECK-ADD-NEXT: lsl x9, x0, #2
; CHECK-MINUS-257-OFFSET: sub x8, x8, #257
; CHECK-257-OFFSET: add x8, x8, #257
; CHECK-ADD-NEXT: ldr x8, [x8]
-; CHECK-ADD-NEXT: add x9, x9, #15
-; CHECK-ADD-NEXT: and x9, x9, #0xfffffffffffffff0
; CHECK-ADD-NEXT: stur x8, [x29, #-8]
-; CHECK-ADD-NEXT: mov x8, sp
-; CHECK-ADD-NEXT: sub x0, x8, x9
+; CHECK-ADD-NEXT: lsl x8, x0, #2
+; CHECK-ADD-NEXT: add x8, x8, #15
+; CHECK-ADD-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-ADD-NEXT: sub x0, sp, x8
; CHECK-ADD-NEXT: mov sp, x0
; CHECK-ADD-NEXT: bl baz
; CHECK-FAR1: mrs x8, FAR_EL1
diff --git a/llvm/test/CodeGen/AArch64/stack-hazard.ll b/llvm/test/CodeGen/AArch64/stack-hazard.ll
index 8a43720faf2a5..0454cef9fec24 100644
--- a/llvm/test/CodeGen/AArch64/stack-hazard.ll
+++ b/llvm/test/CodeGen/AArch64/stack-hazard.ll
@@ -3449,11 +3449,10 @@ define i32 @sve_stack_object_and_vla(double %d, i64 %sz) "aarch64_pstate_sm_comp
; CHECK0-NEXT: .cfi_offset w28, -16
; CHECK0-NEXT: .cfi_offset w30, -24
; CHECK0-NEXT: .cfi_offset w29, -32
-; CHECK0-NEXT: lsl x9, x0, #2
-; CHECK0-NEXT: mov x8, sp
-; CHECK0-NEXT: add x9, x9, #15
-; CHECK0-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK0-NEXT: sub x0, x8, x9
+; CHECK0-NEXT: lsl x8, x0, #2
+; CHECK0-NEXT: add x8, x8, #15
+; CHECK0-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK0-NEXT: sub x0, sp, x8
; CHECK0-NEXT: mov sp, x0
; CHECK0-NEXT: mov z0.s, #0 // =0x0
; CHECK0-NEXT: str z0, [x29, #-1, mul vl]
@@ -3478,11 +3477,10 @@ define i32 @sve_stack_object_and_vla(double %d, i64 %sz) "aarch64_pstate_sm_comp
; CHECK64-NEXT: .cfi_offset w28, -16
; CHECK64-NEXT: .cfi_offset w30, -24
; CHECK64-NEXT: .cfi_offset w29, -32
-; CHECK64-NEXT: lsl x9, x0, #2
-; CHECK64-NEXT: mov x8, sp
-; CHECK64-NEXT: add x9, x9, #15
-; CHECK64-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK64-NEXT: sub x0, x8, x9
+; CHECK64-NEXT: lsl x8, x0, #2
+; CHECK64-NEXT: add x8, x8, #15
+; CHECK64-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK64-NEXT: sub x0, sp, x8
; CHECK64-NEXT: mov sp, x0
; CHECK64-NEXT: mov z0.s, #0 // =0x0
; CHECK64-NEXT: sub x8, x29, #64
@@ -3511,11 +3509,10 @@ define i32 @sve_stack_object_and_vla(double %d, i64 %sz) "aarch64_pstate_sm_comp
; CHECK1024-NEXT: .cfi_offset w28, -16
; CHECK1024-NEXT: .cfi_offset w30, -24
; CHECK1024-NEXT: .cfi_offset w29, -32
-; CHECK1024-NEXT: lsl x9, x0, #2
-; CHECK1024-NEXT: mov x8, sp
-; CHECK1024-NEXT: add x9, x9, #15
-; CHECK1024-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK1024-NEXT: sub x0, x8, x9
+; CHECK1024-NEXT: lsl x8, x0, #2
+; CHECK1024-NEXT: add x8, x8, #15
+; CHECK1024-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK1024-NEXT: sub x0, sp, x8
; CHECK1024-NEXT: mov sp, x0
; CHECK1024-NEXT: mov z0.s, #0 // =0x0
; CHECK1024-NEXT: sub x8, x29, #1024
@@ -3599,11 +3596,10 @@ define i32 @svecc_call_dynamic_alloca(<4 x i16> %P0, i32 %P1, i32 %P2, <vscale x
; CHECK0-NEXT: mov w8, w0
; CHECK0-NEXT: bl __arm_sme_state
; CHECK0-NEXT: mov w8, w8
-; CHECK0-NEXT: mov x9, sp
; CHECK0-NEXT: mov x20, x0
; CHECK0-NEXT: add x8, x8, #15
; CHECK0-NEXT: and x8, x8, #0x1fffffff0
-; CHECK0-NEXT: sub x8, x9, x8
+; CHECK0-NEXT: sub x8, sp, x8
; CHECK0-NEXT: mov sp, x8
; CHECK0-NEXT: //APP
; CHECK0-NEXT: //NO_APP
@@ -3737,11 +3733,10 @@ define i32 @svecc_call_dynamic_alloca(<4 x i16> %P0, i32 %P1, i32 %P2, <vscale x
; CHECK64-NEXT: mov w8, w0
; CHECK64-NEXT: bl __arm_sme_state
; CHECK64-NEXT: mov w8, w8
-; CHECK64-NEXT: mov x9, sp
; CHECK64-NEXT: mov x20, x0
; CHECK64-NEXT: add x8, x8, #15
; CHECK64-NEXT: and x8, x8, #0x1fffffff0
-; CHECK64-NEXT: sub x8, x9, x8
+; CHECK64-NEXT: sub x8, sp, x8
; CHECK64-NEXT: mov sp, x8
; CHECK64-NEXT: //APP
; CHECK64-NEXT: //NO_APP
@@ -3880,11 +3875,10 @@ define i32 @svecc_call_dynamic_alloca(<4 x i16> %P0, i32 %P1, i32 %P2, <vscale x
; CHECK1024-NOSPLITSVE-NEXT: mov w8, w0
; CHECK1024-NOSPLITSVE-NEXT: bl __arm_sme_state
; CHECK1024-NOSPLITSVE-NEXT: mov w8, w8
-; CHECK1024-NOSPLITSVE-NEXT: mov x9, sp
; CHECK1024-NOSPLITSVE-NEXT: mov x20, x0
; CHECK1024-NOSPLITSVE-NEXT: add x8, x8, #15
; CHECK1024-NOSPLITSVE-NEXT: and x8, x8, #0x1fffffff0
-; CHECK1024-NOSPLITSVE-NEXT: sub x8, x9, x8
+; CHECK1024-NOSPLITSVE-NEXT: sub x8, sp, x8
; CHECK1024-NOSPLITSVE-NEXT: mov sp, x8
; CHECK1024-NOSPLITSVE-NEXT: //APP
; CHECK1024-NOSPLITSVE-NEXT: //NO_APP
@@ -4023,11 +4017,10 @@ define i32 @svecc_call_dynamic_alloca(<4 x i16> %P0, i32 %P1, i32 %P2, <vscale x
; CHECK1024-SPLITSVE-NEXT: mov w8, w0
; CHECK1024-SPLITSVE-NEXT: bl __arm_sme_state
; CHECK1024-SPLITSVE-NEXT: mov w8, w8
-; CHECK1024-SPLITSVE-NEXT: mov x9, sp
; CHECK1024-SPLITSVE-NEXT: mov x20, x0
; CHECK1024-SPLITSVE-NEXT: add x8, x8, #15
; CHECK1024-SPLITSVE-NEXT: and x8, x8, #0x1fffffff0
-; CHECK1024-SPLITSVE-NEXT: sub x8, x9, x8
+; CHECK1024-SPLITSVE-NEXT: sub x8, sp, x8
; CHECK1024-SPLITSVE-NEXT: mov sp, x8
; CHECK1024-SPLITSVE-NEXT: //APP
; CHECK1024-SPLITSVE-NEXT: //NO_APP
@@ -4694,10 +4687,9 @@ define i32 @svecc_call_dynamic_and_scalable_alloca(<4 x i16> %P0, i32 %P1, i32 %
; CHECK0-NEXT: .cfi_escape 0x10, 0x4f, 0x0a, 0x92, 0x2e, 0x00, 0x11, 0x40, 0x1e, 0x22, 0x11, 0x40, 0x22 // $d15 @ cfa - 64 * VG - 64
; CHECK0-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK0-NEXT: ubfiz x8, x0, #2, #32
-; CHECK0-NEXT: mov x9, sp
; CHECK0-NEXT: add x8, x8, #15
; CHECK0-NEXT: and x8, x8, #0x7fffffff0
-; CHECK0-NEXT: sub x20, x9, x8
+; CHECK0-NEXT: sub x20, sp, x8
; CHECK0-NEXT: mov sp, x20
; CHECK0-NEXT: //APP
; CHECK0-NEXT: //NO_APP
@@ -4804,10 +4796,9 @@ define i32 @svecc_call_dynamic_and_scalable_alloca(<4 x i16> %P0, i32 %P1, i32 %
; CHECK64-NEXT: .cfi_escape 0x10, 0x4f, 0x0c, 0x92, 0x2e, 0x00, 0x11, 0xb0, 0x7f, 0x1e, 0x22, 0x11, 0x80, 0x7f, 0x22 // $d15 @ cfa - 80 * VG - 128
; CHECK64-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK64-NEXT: ubfiz x8, x0, #2, #32
-; CHECK64-NEXT: mov x9, sp
; CHECK64-NEXT: add x8, x8, #15
; CHECK64-NEXT: and x8, x8, #0x7fffffff0
-; CHECK64-NEXT: sub x20, x9, x8
+; CHECK64-NEXT: sub x20, sp, x8
; CHECK64-NEXT: mov sp, x20
; CHECK64-NEXT: //APP
; CHECK64-NEXT: //NO_APP
@@ -4919,10 +4910,9 @@ define i32 @svecc_call_dynamic_and_scalable_alloca(<4 x i16> %P0, i32 %P1, i32 %
; CHECK1024-NOSPLITSVE-NEXT: .cfi_escape 0x10, 0x4f, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x40, 0x1e, 0x22, 0x11, 0xc0, 0x77, 0x22 // $d15 @ cfa - 64 * VG - 1088
; CHECK1024-NOSPLITSVE-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK1024-NOSPLITSVE-NEXT: ubfiz x8, x0, #2, #32
-; CHECK1024-NOSPLITSVE-NEXT: mov x9, sp
; CHECK1024-NOSPLITSVE-NEXT: add x8, x8, #15
; CHECK1024-NOSPLITSVE-NEXT: and x8, x8, #0x7fffffff0
-; CHECK1024-NOSPLITSVE-NEXT: sub x20, x9, x8
+; CHECK1024-NOSPLITSVE-NEXT: sub x20, sp, x8
; CHECK1024-NOSPLITSVE-NEXT: mov sp, x20
; CHECK1024-NOSPLITSVE-NEXT: //APP
; CHECK1024-NOSPLITSVE-NEXT: //NO_APP
@@ -5035,10 +5025,9 @@ define i32 @svecc_call_dynamic_and_scalable_alloca(<4 x i16> %P0, i32 %P1, i32 %
; CHECK1024-SPLITSVE-NEXT: .cfi_escape 0x10, 0x4f, 0x0c, 0x92, 0x2e, 0x00, 0x11, 0xb0, 0x7f, 0x1e, 0x22, 0x11, 0xc0, 0x77, 0x22 // $d15 @ cfa - 80 * VG - 1088
; CHECK1024-SPLITSVE-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK1024-SPLITSVE-NEXT: ubfiz x8, x0, #2, #32
-; CHECK1024-SPLITSVE-NEXT: mov x9, sp
; CHECK1024-SPLITSVE-NEXT: add x8, x8, #15
; CHECK1024-SPLITSVE-NEXT: and x8, x8, #0x7fffffff0
-; CHECK1024-SPLITSVE-NEXT: sub x20, x9, x8
+; CHECK1024-SPLITSVE-NEXT: sub x20, sp, x8
; CHECK1024-SPLITSVE-NEXT: mov sp, x20
; CHECK1024-SPLITSVE-NEXT: //APP
; CHECK1024-SPLITSVE-NEXT: //NO_APP
diff --git a/llvm/test/CodeGen/AArch64/stack-probing-dynamic.ll b/llvm/test/CodeGen/AArch64/stack-probing-dynamic.ll
index 42a8e3b61cddc..108cb8476fc00 100644
--- a/llvm/test/CodeGen/AArch64/stack-probing-dynamic.ll
+++ b/llvm/test/CodeGen/AArch64/stack-probing-dynamic.ll
@@ -17,21 +17,21 @@ define void @dynamic(i64 %size, ptr %out) #0 {
; CHECK-NEXT: .cfi_def_cfa w29, 16
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: add [[REG1:x[0-9]+]], x0, #15
+; CHECK-GI-NEXT: mov x8, sp
+; CHECK-NEXT: and [[REG1]], [[REG1]], #0xfffffffffffffff0
+; CHECK-NEXT: sub [[REG2:x[0-9]+]], {{(sp|x8)}}, [[REG1]]
; CHECK-NEXT: .LBB0_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
-; CHECK-NEXT: cmp sp, x8
+; CHECK-NEXT: cmp sp, [[REG2]]
; CHECK-NEXT: b.le .LBB0_3
; CHECK-NEXT: // %bb.2: // in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB0_1
; CHECK-NEXT: .LBB0_3:
-; CHECK-NEXT: mov sp, x8
+; CHECK-NEXT: mov sp, [[REG2]]
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str x8, [x1]
+; CHECK-NEXT: str [[REG2]], [x1]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 16
; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
@@ -59,24 +59,23 @@ define void @dynamic_fixed(i64 %size, ptr %out1, ptr %out2) #0 {
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
; CHECK-NEXT: ldr xzr, [sp, #-64]!
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
-; CHECK-DAG: sub x10, x29, #64
-; CHECK-DAG: and x9, x9, #0xfffffffffffffff0
-; CHECK-NOT: INVALID_TO_BREAK_UP_CHECK_DAG
-; CHECK-DAG: str x10, [x1]
-; CHECK-DAG: sub x8, x8, x9
+; CHECK-NEXT: add [[REG1:x[0-9]+]], x0, #15
+; CHECK-GI-NEXT: mov [[REG2:x[0-9]+]], sp
+; CHECK-DAG: sub [[REG3:x[0-9]+]], x29, #64
+; CHECK-DAG: and [[REG1]], [[REG1]], #0xfffffffffffffff0
+; CHECK-DAG: str [[REG3]], [x1]
+; CHECK-DAG: sub [[REG2]], {{(sp|x[0-9]+)}}, [[REG1]]
; CHECK-NEXT: .LBB1_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
-; CHECK-NEXT: cmp sp, x8
+; CHECK-NEXT: cmp sp, [[REG2]]
; CHECK-NEXT: b.le .LBB1_3
; CHECK-NEXT: // %bb.2: // in Loop: Header=BB1_1 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB1_1
; CHECK-NEXT: .LBB1_3:
-; CHECK-NEXT: mov sp, x8
+; CHECK-NEXT: mov sp, [[REG2]]
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str x8, [x2]
+; CHECK-NEXT: str [[REG2]], [x2]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 16
; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
@@ -109,25 +108,24 @@ define void @dynamic_align_64(i64 %size, ptr %out) #0 {
; CHECK-NEXT: .cfi_offset w29, -32
; CHECK-NEXT: sub x9, sp, #32
; CHECK-NEXT: and sp, x9, #0xffffffffffffffc0
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: add [[REG1:x[0-9]+]], x0, #15
+; CHECK-GI-NEXT: mov [[REG2:x[0-9]+]], sp
; CHECK-DAG: ldr xzr, [sp]
-; CHECK-DAG: and x9, x9, #0xfffffffffffffff0
-; CHECK-NOT: INVALID_TO_BREAK_UP_CHECK_DAG
+; CHECK-DAG: and [[REG1]], [[REG1]], #0xfffffffffffffff0
; CHECK-DAG: mov x19, sp
-; CHECK-DAG: sub x8, x8, x9
-; CHECK-NEXT: and x8, x8, #0xffffffffffffffc0
+; CHECK-DAG: sub [[REG2]], {{(sp|x[0-9]+)}}, [[REG1]]
+; CHECK-NEXT: and [[REG2]], [[REG2]], #0xffffffffffffffc0
; CHECK-NEXT: .LBB2_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
-; CHECK-NEXT: cmp sp, x8
+; CHECK-NEXT: cmp sp, [[REG2]]
; CHECK-NEXT: b.le .LBB2_3
; CHECK-NEXT: // %bb.2: // in Loop: Header=BB2_1 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB2_1
; CHECK-NEXT: .LBB2_3:
-; CHECK-NEXT: mov sp, x8
+; CHECK-NEXT: mov sp, [[REG2]]
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str x8, [x1]
+; CHECK-NEXT: str [[REG2]], [x1]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 32
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
@@ -169,25 +167,24 @@ define void @dynamic_align_8192(i64 %size, ptr %out) #0 {
; CHECK-NEXT: b .LBB3_1
; CHECK-NEXT: .LBB3_3:
; CHECK-NEXT: mov sp, x9
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: add [[REG1:x[0-9]+]], x0, #15
+; CHECK-GI-NEXT: mov [[REG2:x[0-9]+]], sp
; CHECK-DAG: ldr xzr, [sp]
-; CHECK-DAG: and x9, x9, #0xfffffffffffffff0
-; CHECK-NOT: INVALID_TO_BREAK_UP_CHECK_DAG
+; CHECK-DAG: and [[REG1]], [[REG1]], #0xfffffffffffffff0
; CHECK-DAG: mov x19, sp
-; CHECK-DAG: sub x8, x8, x9
-; CHECK-NEXT: and x8, x8, #0xffffffffffffe000
+; CHECK-DAG: sub [[REG2]], {{(sp|x[0-9]+)}}, [[REG1]]
+; CHECK-NEXT: and [[REG2]], [[REG2]], #0xffffffffffffe000
; CHECK-NEXT: .LBB3_4: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
-; CHECK-NEXT: cmp sp, x8
+; CHECK-NEXT: cmp sp, [[REG2]]
; CHECK-NEXT: b.le .LBB3_6
; CHECK-NEXT: // %bb.5: // in Loop: Header=BB3_4 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB3_4
; CHECK-NEXT: .LBB3_6:
-; CHECK-NEXT: mov sp, x8
+; CHECK-NEXT: mov sp, [[REG2]]
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str x8, [x1]
+; CHECK-NEXT: str [[REG2]], [x1]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 32
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
@@ -213,21 +210,21 @@ define void @dynamic_64k_guard(i64 %size, ptr %out) #0 "stack-probe-size"="65536
; CHECK-NEXT: .cfi_def_cfa w29, 16
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
-; CHECK-NEXT: add x9, x0, #15
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: add [[REG1:x[0-9]+]], x0, #15
+; CHECK-GI-NEXT: mov [[REG2:x[0-9]+]], sp
+; CHECK-NEXT: and [[REG1]], [[REG1]], #0xfffffffffffffff0
+; CHECK-NEXT: sub [[REG3:x[0-9]+]], {{(sp|x[0-9]+)}}, [[REG1]]
; CHECK-NEXT: .LBB4_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #16, lsl #12 // =65536
-; CHECK-NEXT: cmp sp, x8
+; CHECK-NEXT: cmp sp, [[REG3]]
; CHECK-NEXT: b.le .LBB4_3
; CHECK-NEXT: // %bb.2: // in Loop: Header=BB4_1 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB4_1
; CHECK-NEXT: .LBB4_3:
-; CHECK-NEXT: mov sp, x8
+; CHECK-NEXT: mov sp, [[REG3]]
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str x8, [x1]
+; CHECK-NEXT: str [[REG3]], [x1]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 16
; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
@@ -254,11 +251,11 @@ define void @no_reserved_call_frame(i64 %n) #0 {
; CHECK-NEXT: .cfi_def_cfa w29, 16
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
-; CHECK-NEXT: lsl x9, x0, #2
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: add x9, x9, #15
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x0, x8, x9
+; CHECK-NEXT: lsl [[REG1:x[0-9]+]], x0, #2
+; CHECK-GI-NEXT: mov x8, sp
+; CHECK-NEXT: add [[REG1]], [[REG1]], #15
+; CHECK-NEXT: and [[REG1]], [[REG1]], #0xfffffffffffffff0
+; CHECK-NEXT: sub x0, {{(sp|x8)}}, [[REG1]]
; CHECK-NEXT: .LBB5_1: // %entry
; CHECK-NEXT: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
@@ -334,23 +331,22 @@ define void @dynamic_sve(i64 %size, ptr %out) #0 "target-features"="+sve" {
; CHECK-NEXT: .cfi_offset w19, -16
; CHECK-NEXT: .cfi_offset w30, -24
; CHECK-NEXT: .cfi_offset w29, -32
-; CHECK-NEXT: rdvl x9, #1
-; CHECK-NEXT: mov x10, #15 // =0xf
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: madd x9, x0, x9, x10
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: rdvl [[REG1:x[0-9]+]], #1
+; CHECK-NEXT: mov [[REG2:x[0-9]+]], #15 // =0xf
+; CHECK-NEXT: madd [[REG1]], x0, [[REG1]], [[REG2]]
+; CHECK-NEXT: and [[REG1]], [[REG1]], #0xfffffffffffffff0
+; CHECK-NEXT: sub [[REG1]], sp, [[REG1]]
; CHECK-NEXT: .LBB7_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
-; CHECK-NEXT: cmp sp, x8
+; CHECK-NEXT: cmp sp, [[REG1]]
; CHECK-NEXT: b.le .LBB7_3
; CHECK-NEXT: // %bb.2: // in Loop: Header=BB7_1 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB7_1
; CHECK-NEXT: .LBB7_3:
-; CHECK-NEXT: mov sp, x8
+; CHECK-NEXT: mov sp, [[REG1]]
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str x8, [x1]
+; CHECK-NEXT: str [[REG1]], [x1]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 32
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
diff --git a/llvm/test/CodeGen/AArch64/stack-protector-target.ll b/llvm/test/CodeGen/AArch64/stack-protector-target.ll
index b7cee17581180..64412de44bc5d 100644
--- a/llvm/test/CodeGen/AArch64/stack-protector-target.ll
+++ b/llvm/test/CodeGen/AArch64/stack-protector-target.ll
@@ -35,8 +35,7 @@ declare void @_Z7CapturePi(ptr)
; WINDOWS-AARCH64: str x8, [sp, #8]
; WINDOWS-AARCH64: bl _Z7CapturePi
; WINDOWS-AARCH64: ldr x8, [sp, #8]
-; WINDOWS-AARCH64: mov x9, sp
-; WINDOWS-AARCH64: sub x0, x9, x8
+; WINDOWS-AARCH64: sub x0, sp, x8
; WINDOWS-AARCH64: bl __security_check_cookie
; WINDOWS-ARM64EC: adrp x8, __security_cookie
@@ -45,6 +44,5 @@ declare void @_Z7CapturePi(ptr)
; WINDOWS-ARM64EC: str x8, [sp, #8]
; WINDOWS-ARM64EC: bl "#_Z7CapturePi"
; WINDOWS-ARM64EC: ldr x8, [sp, #8]
-; WINDOWS-ARM64EC: mov x9, sp
-; WINDOWS-ARM64EC: sub x0, x9, x8
+; WINDOWS-ARM64EC: sub x0, sp, x8
; WINDOWS-ARM64EC: bl "#__security_check_cookie_arm64ec"
diff --git a/llvm/test/CodeGen/AArch64/sve-alloca.ll b/llvm/test/CodeGen/AArch64/sve-alloca.ll
index 324c35b340ed6..2624ba8fe55cd 100644
--- a/llvm/test/CodeGen/AArch64/sve-alloca.ll
+++ b/llvm/test/CodeGen/AArch64/sve-alloca.ll
@@ -54,11 +54,10 @@ define void @foo(<vscale x 4 x i64> %dst, i1 %cond) {
; CHECK-NEXT: .cfi_escape 0x10, 0x4d, 0x0a, 0x92, 0x2e, 0x00, 0x11, 0x50, 0x1e, 0x22, 0x11, 0x60, 0x22 // $d13 @ cfa - 48 * VG - 32
; CHECK-NEXT: .cfi_escape 0x10, 0x4e, 0x0a, 0x92, 0x2e, 0x00, 0x11, 0x48, 0x1e, 0x22, 0x11, 0x60, 0x22 // $d14 @ cfa - 56 * VG - 32
; CHECK-NEXT: .cfi_escape 0x10, 0x4f, 0x0a, 0x92, 0x2e, 0x00, 0x11, 0x40, 0x1e, 0x22, 0x11, 0x60, 0x22 // $d15 @ cfa - 64 * VG - 32
-; CHECK-NEXT: rdvl x9, #2
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: add x9, x9, #15
-; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, x8, x9
+; CHECK-NEXT: rdvl x8, #2
+; CHECK-NEXT: add x8, x8, #15
+; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, sp, x8
; CHECK-NEXT: and x0, x8, #0xffffffffffffffe0
; CHECK-NEXT: mov sp, x0
; CHECK-NEXT: str z1, [x0, #1, mul vl]
diff --git a/llvm/test/CodeGen/AArch64/sve-stack-frame-layout.ll b/llvm/test/CodeGen/AArch64/sve-stack-frame-layout.ll
index 2cedcfec77826..7c0cd22f75663 100644
--- a/llvm/test/CodeGen/AArch64/sve-stack-frame-layout.ll
+++ b/llvm/test/CodeGen/AArch64/sve-stack-frame-layout.ll
@@ -168,13 +168,10 @@ define i32 @csr_d8_allocnxv4i32i32f64_vla(double %d, i32 %i) "aarch64_pstate_sm_
; CHECK-NEXT: .cfi_offset b8, -32
; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-NEXT: ubfiz x8, x0, #2, #32
-; CHECK-NEXT: mov x9, sp
; CHECK-NEXT: add x8, x8, #15
; CHECK-NEXT: and x8, x8, #0x7fffffff0
-; CHECK-NEXT: sub x9, x9, x8
-; CHECK-NEXT: mov sp, x9
-; CHECK-NEXT: mov x10, sp
-; CHECK-NEXT: sub x8, x10, x8
+; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: mov z1.s, #0 // =0x0
; CHECK-NEXT: //APP
@@ -182,7 +179,6 @@ define i32 @csr_d8_allocnxv4i32i32f64_vla(double %d, i32 %i) "aarch64_pstate_sm_
; CHECK-NEXT: str wzr, [x8]
; CHECK-NEXT: sub x8, x29, #8
; CHECK-NEXT: mov w0, wzr
-; CHECK-NEXT: str wzr, [x9]
; CHECK-NEXT: str d0, [x19, #8]
; CHECK-NEXT: str z1, [x8, #-1, mul vl]
; CHECK-NEXT: sub sp, x29, #8
@@ -598,3 +594,5 @@ entry:
ret i32 %x
}
declare void @other()
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK-FRAMELAYOUT: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/win-alloca-no-stack-probe.ll b/llvm/test/CodeGen/AArch64/win-alloca-no-stack-probe.ll
index 3d60944051e1e..cd77ffaacb1c8 100644
--- a/llvm/test/CodeGen/AArch64/win-alloca-no-stack-probe.ll
+++ b/llvm/test/CodeGen/AArch64/win-alloca-no-stack-probe.ll
@@ -11,7 +11,6 @@ declare void @func2(ptr)
; CHECK: add [[REG1:x[0-9]+]], x0, #15
; CHECK-NOT: bl __chkstk
-; CHECK: mov [[REG2:x[0-9]+]], sp
; CHECK: and [[REG1]], [[REG1]], #0xfffffffffffffff0
-; CHECK: sub [[REG3:x[0-9]+]], [[REG2]], [[REG1]]
+; CHECK: sub [[REG3:x[0-9]+]], sp, [[REG1]]
; CHECK: mov sp, [[REG3]]
diff --git a/llvm/test/CodeGen/AArch64/win-alloca.ll b/llvm/test/CodeGen/AArch64/win-alloca.ll
index 94c3d88458169..b28555b616bb5 100644
--- a/llvm/test/CodeGen/AArch64/win-alloca.ll
+++ b/llvm/test/CodeGen/AArch64/win-alloca.ll
@@ -18,7 +18,8 @@ declare void @func2(ptr)
; CHECK: add [[REG1:x[0-9]+]], x0, #15
; CHECK-OPT: lsr x15, [[REG1]], #4
; CHECK: bl __chkstk
-; CHECK-OPT: sub [[REG3:x[0-9]+]], sp, x15, lsl #4
+; CHECK-OPT: lsl [[REG2:x[0-9]+]], x15, #4
+; CHECK-OPT: sub [[REG3:x[0-9]+]], sp, [[REG2]]
; CHECK-OPT: mov sp, [[REG3]]
; CHECK: bl func2
; CHECK-ARM64EC: bl "#__chkstk_arm64ec"
diff --git a/llvm/test/CodeGen/AArch64/win-sve.ll b/llvm/test/CodeGen/AArch64/win-sve.ll
index dea7781ba16e2..4425fab765599 100644
--- a/llvm/test/CodeGen/AArch64/win-sve.ll
+++ b/llvm/test/CodeGen/AArch64/win-sve.ll
@@ -221,7 +221,8 @@ define void @f2(i64 %n, <vscale x 2 x i64> %x) {
; CHECK-NEXT: add x8, x8, #15
; CHECK-NEXT: lsr x15, x8, #4
; CHECK-NEXT: bl __chkstk
-; CHECK-NEXT: sub x1, sp, x15, lsl #4
+; CHECK-NEXT: lsl x8, x15, #4
+; CHECK-NEXT: sub x1, sp, x8
; CHECK-NEXT: mov sp, x1
; CHECK-NEXT: add x0, x19, #0
; CHECK-NEXT: bl g2
@@ -681,7 +682,8 @@ define void @f5(i64 %n, <vscale x 2 x i64> %x) {
; CHECK-NEXT: add x8, x8, #15
; CHECK-NEXT: lsr x15, x8, #4
; CHECK-NEXT: bl __chkstk
-; CHECK-NEXT: sub x2, sp, x15, lsl #4
+; CHECK-NEXT: lsl x8, x15, #4
+; CHECK-NEXT: sub x2, sp, x8
; CHECK-NEXT: mov sp, x2
; CHECK-NEXT: sub x1, x29, #16
; CHECK-NEXT: add x0, x19, #0
diff --git a/llvm/test/CodeGen/AArch64/win64_vararg.ll b/llvm/test/CodeGen/AArch64/win64_vararg.ll
index 0f4cb44a6f73b..47e6628b91304 100644
--- a/llvm/test/CodeGen/AArch64/win64_vararg.ll
+++ b/llvm/test/CodeGen/AArch64/win64_vararg.ll
@@ -190,7 +190,8 @@ define void @vla(i32, ptr, ...) local_unnamed_addr {
; CHECK-NEXT: stp x4, x5, [x29, #40]
; CHECK-NEXT: stp x6, x7, [x29, #56]
; CHECK-NEXT: bl __chkstk
-; CHECK-NEXT: sub x20, sp, x15, lsl #4
+; CHECK-NEXT: lsl x8, x15, #4
+; CHECK-NEXT: sub x20, sp, x8
; CHECK-NEXT: mov sp, x20
; CHECK-NEXT: ldr x21, [x29, #16]
; CHECK-NEXT: sxtw x22, w0
>From 31ccc3858ecd989fd190fe2553f9cfdc974d3668 Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Mon, 25 May 2026 16:09:51 +0800
Subject: [PATCH 07/11] Fix code format error
---
llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp | 4 ++--
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 3 ++-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 29517ce63c77d..6da83a1f1fb9b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -5070,8 +5070,8 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
if (R && R->getReg() == AArch64::SP && VT == MVT::i64) {
SDValue N1 = Node->getOperand(1);
SDValue Ops[] = {N1};
- SDNode *ResNode = CurDAG->getMachineNode(
- AArch64::STACK_GUARD_UNMIX, SDLoc(Node), MVT::i64, Ops);
+ SDNode *ResNode = CurDAG->getMachineNode(AArch64::STACK_GUARD_UNMIX,
+ SDLoc(Node), MVT::i64, Ops);
ReplaceNode(Node, ResNode);
return;
}
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index be1a6ece81760..ae58bd4184627 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -30721,7 +30721,8 @@ bool AArch64TargetLowering::useLoadStackGuardNode(const Module &M) const {
bool AArch64TargetLowering::useStackGuardMixCookie() const {
// MSVC CRTs mix the stack pointer into the stack guard value.
// The prologue mixing is handled via post-RA expansion of LOAD_STACK_GUARD,
- // but the epilogue unmixing is done at the DAG level via emitStackGuardMixCookie.
+ // but the epilogue unmixing is done at the DAG level via
+ // emitStackGuardMixCookie.
return Subtarget->getTargetTriple().isOSMSVCRT();
}
>From 550ddea22d87b14e8b94237444531ffe70e2fe4a Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Mon, 25 May 2026 22:27:47 +0800
Subject: [PATCH 08/11] Remove redundant check
---
llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll b/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll
index 083da3335ba54..b603197a03943 100644
--- a/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll
+++ b/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll
@@ -18,7 +18,6 @@ define void @quux(i64 %n) "aarch64_new_za" "aarch64_pstate_sm_enabled" {
; CHECK-NEXT: .cfi_offset w19, -16
; CHECK-NEXT: .cfi_offset w30, -24
; CHECK-NEXT: .cfi_offset w29, -32
-; CHECK-NEXT: // kill: def $x1 killed $sp
; CHECK-NEXT: add x8, x0, #15
; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
; CHECK-NEXT: sub x8, sp, x8
>From 4f58edb0060302e62eb7cd81d8958d2204d8a6a5 Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Wed, 27 May 2026 08:50:49 +0800
Subject: [PATCH 09/11] Remove redundant modifications
---
.../Target/AArch64/AArch64ISelDAGToDAG.cpp | 8 +-
.../Target/AArch64/AArch64ISelLowering.cpp | 3 +-
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 15 +
.../AArch64/aarch64-dynamic-stack-layout.ll | 40 +-
llvm/test/CodeGen/AArch64/alloca.ll | 373 +++---------------
.../CodeGen/AArch64/arm64ec-indirect-call.ll | 38 +-
llvm/test/CodeGen/AArch64/mingw-refptr.ll | 115 +++---
.../CodeGen/AArch64/shrink-wrapping-vla.ll | 5 +-
llvm/test/CodeGen/AArch64/sme-agnostic-za.ll | 3 +-
.../CodeGen/AArch64/sme-framelower-use-bp.ll | 5 +-
.../CodeGen/AArch64/sme-lazy-save-windows.ll | 3 +-
...nging-call-disable-stackslot-scavenging.ll | 9 +-
.../AArch64/sme-za-lazy-save-buffer.ll | 4 +-
.../AArch64/split-sve-stack-frame-layout.ll | 42 +-
.../CodeGen/AArch64/stack-guard-sysreg.ll | 28 +-
llvm/test/CodeGen/AArch64/stack-hazard.ll | 51 ++-
.../CodeGen/AArch64/stack-probing-dynamic.ll | 108 ++---
llvm/test/CodeGen/AArch64/sve-alloca.ll | 9 +-
.../CodeGen/AArch64/sve-stack-frame-layout.ll | 10 +-
.../AArch64/win-alloca-no-stack-probe.ll | 3 +-
llvm/test/CodeGen/AArch64/win-alloca.ll | 3 +-
llvm/test/CodeGen/AArch64/win-sve.ll | 6 +-
llvm/test/CodeGen/AArch64/win64_vararg.ll | 3 +-
23 files changed, 345 insertions(+), 539 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 6da83a1f1fb9b..3af0f13f6377e 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -5062,13 +5062,15 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
break;
case ISD::SUB: {
- // Check for stack guard unmixing pattern: SUB(CopyFromReg(SP), X)
+ // Check for stack guard unmixing pattern: SUB(CopyFromReg(SP), LOAD(...))
// Select STACK_GUARD_UNMIX pseudo which will be expanded post-RA
+ // Only match when N1 is a LOAD (the stored guard value from stack).
+ // Other patterns like shifts for dynamic allocation will use normal SUB.
SDValue N0 = Node->getOperand(0);
- if (N0.getOpcode() == ISD::CopyFromReg) {
+ SDValue N1 = Node->getOperand(1);
+ if (N0.getOpcode() == ISD::CopyFromReg && N1.getOpcode() == ISD::LOAD) {
RegisterSDNode *R = dyn_cast<RegisterSDNode>(N0.getOperand(1));
if (R && R->getReg() == AArch64::SP && VT == MVT::i64) {
- SDValue N1 = Node->getOperand(1);
SDValue Ops[] = {N1};
SDNode *ResNode = CurDAG->getMachineNode(AArch64::STACK_GUARD_UNMIX,
SDLoc(Node), MVT::i64, Ops);
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index ae58bd4184627..14d22d8347087 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -31547,9 +31547,8 @@ bool AArch64TargetLowering::fallBackToDAGISel(const Instruction &Inst) const {
auto CallAttrs = SMECallAttrs(*Base, &getRuntimeLibcallsInfo());
if (CallAttrs.requiresSMChange() || CallAttrs.requiresLazySave() ||
CallAttrs.requiresPreservingZT0() ||
- CallAttrs.requiresPreservingAllZAState()) {
+ CallAttrs.requiresPreservingAllZAState())
return true;
- }
}
}
return false;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index ee448dc1f6926..aaf538cad850b 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2754,11 +2754,23 @@ def : InstAlias<"mov $dst, $src",
defm ADDS : AddSubS<0, "adds", AArch64add_flag, "cmn", "subs", "cmp">;
defm SUBS : AddSubS<1, "subs", AArch64sub_flag, "cmp", "adds", "cmn">;
+// Matches when SP is used directly via CopyFromReg, not after being moved to a GPR.
+// This ensures we don't incorrectly optimize "mov x8, sp; sub x8, x8, x9" into
+// "sub x8, sp, x9" - once SP is in x8, it's no longer a CopyFromReg node.
def copyFromSP: PatLeaf<(i64 GPR64:$src), [{
return N->getOpcode() == ISD::CopyFromReg &&
cast<RegisterSDNode>(N->getOperand(1))->getReg() == AArch64::SP;
}]>;
+// Helper to convert shift amount to UXTX extend with LSL (valid range 0-4)
+def UXTXLSLImm : SDNodeXForm<imm, [{
+ uint64_t ShiftAmt = N->getZExtValue();
+ assert(ShiftAmt <= 4 && "Invalid shift amount for UXTX");
+ return CurDAG->getTargetConstant(
+ AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, ShiftAmt),
+ SDLoc(N), MVT::i32);
+}]>;
+
// Pseudo instruction for stack guard cookie unmixing (epilogue).
// This will be expanded post-RA to use SP directly, avoiding an extra mov.
// Pattern matching for this will be done via custom C++ code during instruction selection.
@@ -2785,6 +2797,9 @@ def : Pat<(sub GPR64sp:$R2, arith_extended_reg32to64_i64:$R3),
(SUBSXrx GPR64sp:$R2, arith_extended_reg32to64_i64:$R3)>;
def : Pat<(sub copyFromSP:$R2, (arith_uxtx GPR64:$R3, arith_extendlsl64:$imm)),
(SUBXrx64 GPR64sp:$R2, GPR64:$R3, arith_extendlsl64:$imm)>;
+// Handle SUB(copyFromSP, SHL) for dynamic stack allocation
+def : Pat<(sub copyFromSP:$sp, (shl GPR64:$val, (i64 imm:$shift))),
+ (SUBXrx64 GPR64sp:$sp, GPR64:$val, (UXTXLSLImm (i64 imm:$shift)))>;
}
// Because of the immediate format for add/sub-imm instructions, the
diff --git a/llvm/test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll b/llvm/test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll
index adaf7f17d4a0f..8da0e111357d0 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll
@@ -299,12 +299,13 @@ entry:
; CHECK: .cfi_offset w29, -32
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; CHECK: ubfiz x8, x0, #2, #32
-; CHECK: add x8, x8, #15
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
+; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
-; CHECK: sub x[[VLASPTMP:[0-9]+]], sp, x8
+; CHECK: mov x10, sp
+; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through frame pointer
; CHECK: ldur w[[ILOC:[0-9]+]], [x29, #-4]
@@ -345,11 +346,12 @@ entry:
; CHECK: ubfiz x8, x0, #2, #32
; Check correctness of cfi pseudo-instructions
; Check correct access to arguments passed on the stack, through frame pointer
-; CHECK: add x8, x8, #15
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40]
+; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
-; CHECK: sub x[[VLASPTMP:[0-9]+]], sp, x8
+; CHECK: mov x10, sp
+; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through frame pointer
; CHECK: ldur w[[ILOC:[0-9]+]], [x29, #-4]
@@ -404,11 +406,12 @@ entry:
; and set-up of base pointer (x19).
; CHECK: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
-; CHECK: add x8, x8, #15
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #56]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #72]
+; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
-; CHECK: sub x[[VLASPTMP:[0-9]+]], sp, x8
+; CHECK: mov x10, sp
+; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [x19]
@@ -449,11 +452,12 @@ entry:
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
-; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
+; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: and x8, x8, #0x7fffffff0
-; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], sp, x8
+; CHECK-MACHO: mov x10, sp
+; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK-MACHO: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19]
@@ -500,11 +504,12 @@ entry:
; and set-up of base pointer (x19).
; CHECK: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
-; CHECK: add x8, x8, #15
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
+; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
-; CHECK: sub x[[VLASPTMP:[0-9]+]], sp, x8
+; CHECK: mov x10, sp
+; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [x19]
@@ -533,11 +538,12 @@ entry:
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
-; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
+; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: and x8, x8, #0x7fffffff0
-; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], sp, x8
+; CHECK-MACHO: mov x10, sp
+; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK-MACHO: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19]
@@ -582,11 +588,12 @@ entry:
; and set-up of base pointer (x19).
; CHECK: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
-; CHECK: add x8, x8, #15
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
+; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
-; CHECK: sub x[[VLASPTMP:[0-9]+]], sp, x8
+; CHECK: mov x10, sp
+; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [x19]
@@ -615,11 +622,12 @@ entry:
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
-; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
+; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: and x8, x8, #0x7fffffff0
-; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], sp, x8
+; CHECK-MACHO: mov x10, sp
+; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK-MACHO: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19]
diff --git a/llvm/test/CodeGen/AArch64/alloca.ll b/llvm/test/CodeGen/AArch64/alloca.ll
index 6be49dc8e26ee..119b84e352c74 100644
--- a/llvm/test/CodeGen/AArch64/alloca.ll
+++ b/llvm/test/CodeGen/AArch64/alloca.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=aarch64-linux-gnu -disable-post-ra -verify-machineinstrs -o - %s | FileCheck %s
; RUN: llc -mtriple=arm64-apple-ios -disable-post-ra -verify-machineinstrs -o - %s | FileCheck %s --check-prefix=CHECK-MACHO
; RUN: llc -mtriple=aarch64-none-linux-gnu -disable-post-ra -mattr=-fp-armv8 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-NOFP-ARM64 %s
@@ -7,224 +6,66 @@ declare void @use_addr(ptr)
define void @test_simple_alloca(i64 %n) {
; CHECK-LABEL: test_simple_alloca:
-; CHECK: // %bb.0:
-; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
-; CHECK-NEXT: mov x29, sp
-; CHECK-NEXT: .cfi_def_cfa w29, 16
-; CHECK-NEXT: .cfi_offset w30, -8
-; CHECK-NEXT: .cfi_offset w29, -16
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x0, sp, x8
-; CHECK-NEXT: mov sp, x0
-; CHECK-NEXT: bl use_addr
-; CHECK-NEXT: mov sp, x29
-; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
-; CHECK-NEXT: ret
-;
-; CHECK-MACHO-LABEL: test_simple_alloca:
-; CHECK-MACHO: ; %bb.0:
-; CHECK-MACHO-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
-; CHECK-MACHO-NEXT: mov x29, sp
-; CHECK-MACHO-NEXT: .cfi_def_cfa w29, 16
-; CHECK-MACHO-NEXT: .cfi_offset w30, -8
-; CHECK-MACHO-NEXT: .cfi_offset w29, -16
-; CHECK-MACHO-NEXT: add x8, x0, #15
-; CHECK-MACHO-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-MACHO-NEXT: sub x0, sp, x8
-; CHECK-MACHO-NEXT: mov sp, x0
-; CHECK-MACHO-NEXT: bl _use_addr
-; CHECK-MACHO-NEXT: mov sp, x29
-; CHECK-MACHO-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
-; CHECK-MACHO-NEXT: ret
-;
-; CHECK-NOFP-ARM64-LABEL: test_simple_alloca:
-; CHECK-NOFP-ARM64: // %bb.0:
-; CHECK-NOFP-ARM64-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
-; CHECK-NOFP-ARM64-NEXT: mov x29, sp
-; CHECK-NOFP-ARM64-NEXT: .cfi_def_cfa w29, 16
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w30, -8
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w29, -16
-; CHECK-NOFP-ARM64-NEXT: add x8, x0, #15
-; CHECK-NOFP-ARM64-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NOFP-ARM64-NEXT: sub x0, sp, x8
-; CHECK-NOFP-ARM64-NEXT: mov sp, x0
-; CHECK-NOFP-ARM64-NEXT: bl use_addr
-; CHECK-NOFP-ARM64-NEXT: mov sp, x29
-; CHECK-NOFP-ARM64-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
-; CHECK-NOFP-ARM64-NEXT: ret
%buf = alloca i8, i64 %n
; Make sure we align the stack change to 16 bytes:
+; CHECK: {{mov|add}} x29
+; CHECK: mov [[TMP:x[0-9]+]], sp
+; CHECK: add [[SPDELTA_TMP:x[0-9]+]], x0, #15
+; CHECK: and [[SPDELTA:x[0-9]+]], [[SPDELTA_TMP]], #0xfffffffffffffff0
; Make sure we change SP. It would be surprising if anything but x0 were used
; for the final sp, but it could be if it was then moved into x0.
+; CHECK: sub [[NEWSP:x[0-9]+]], [[TMP]], [[SPDELTA]]
+; CHECK: mov sp, [[NEWSP]]
call void @use_addr(ptr %buf)
+; CHECK: bl use_addr
ret void
; Make sure epilogue restores sp from fp
+; CHECK: {{sub|mov}} sp, x29
+; CHECK: ret
}
declare void @use_addr_loc(ptr, ptr)
define i64 @test_alloca_with_local(i64 %n) {
; CHECK-LABEL: test_alloca_with_local:
-; CHECK: // %bb.0:
-; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
-; CHECK-NEXT: mov x29, sp
-; CHECK-NEXT: sub sp, sp, #16
-; CHECK-NEXT: .cfi_def_cfa w29, 16
-; CHECK-NEXT: .cfi_offset w30, -8
-; CHECK-NEXT: .cfi_offset w29, -16
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x0, sp, x8
-; CHECK-NEXT: mov sp, x0
-; CHECK-NEXT: sub x1, x29, #8
-; CHECK-NEXT: bl use_addr_loc
-; CHECK-NEXT: ldur x0, [x29, #-8]
-; CHECK-NEXT: mov sp, x29
-; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
-; CHECK-NEXT: ret
-;
-; CHECK-MACHO-LABEL: test_alloca_with_local:
-; CHECK-MACHO: ; %bb.0:
-; CHECK-MACHO-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
-; CHECK-MACHO-NEXT: mov x29, sp
-; CHECK-MACHO-NEXT: sub sp, sp, #16
-; CHECK-MACHO-NEXT: .cfi_def_cfa w29, 16
-; CHECK-MACHO-NEXT: .cfi_offset w30, -8
-; CHECK-MACHO-NEXT: .cfi_offset w29, -16
-; CHECK-MACHO-NEXT: add x8, x0, #15
-; CHECK-MACHO-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-MACHO-NEXT: sub x0, sp, x8
-; CHECK-MACHO-NEXT: mov sp, x0
-; CHECK-MACHO-NEXT: sub x1, x29, #8
-; CHECK-MACHO-NEXT: bl _use_addr_loc
-; CHECK-MACHO-NEXT: ldur x0, [x29, #-8]
-; CHECK-MACHO-NEXT: mov sp, x29
-; CHECK-MACHO-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
-; CHECK-MACHO-NEXT: ret
-;
-; CHECK-NOFP-ARM64-LABEL: test_alloca_with_local:
-; CHECK-NOFP-ARM64: // %bb.0:
-; CHECK-NOFP-ARM64-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
-; CHECK-NOFP-ARM64-NEXT: mov x29, sp
-; CHECK-NOFP-ARM64-NEXT: sub sp, sp, #16
-; CHECK-NOFP-ARM64-NEXT: .cfi_def_cfa w29, 16
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w30, -8
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w29, -16
-; CHECK-NOFP-ARM64-NEXT: add x8, x0, #15
-; CHECK-NOFP-ARM64-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NOFP-ARM64-NEXT: sub x0, sp, x8
-; CHECK-NOFP-ARM64-NEXT: mov sp, x0
-; CHECK-NOFP-ARM64-NEXT: sub x1, x29, #8
-; CHECK-NOFP-ARM64-NEXT: bl use_addr_loc
-; CHECK-NOFP-ARM64-NEXT: ldur x0, [x29, #-8]
-; CHECK-NOFP-ARM64-NEXT: mov sp, x29
-; CHECK-NOFP-ARM64-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
-; CHECK-NOFP-ARM64-NEXT: ret
+; CHECK-DAG: sub sp, sp, [[LOCAL_STACK:#[0-9]+]]
+; CHECK-DAG: {{mov|add}} x29, sp
%loc = alloca i64
%buf = alloca i8, i64 %n
; Make sure we align the stack change to 16 bytes:
+; CHECK: mov [[TMP:x[0-9]+]], sp
+; CHECK: add [[SPDELTA_TMP:x[0-9]+]], x0, #15
+; CHECK: and [[SPDELTA:x[0-9]+]], [[SPDELTA_TMP]], #0xfffffffffffffff0
; Make sure we change SP. It would be surprising if anything but x0 were used
; for the final sp, but it could be if it was then moved into x0.
+; CHECK: sub [[NEWSP:x[0-9]+]], [[TMP]], [[SPDELTA]]
+; CHECK: mov sp, [[NEWSP]]
+; CHECK: sub {{x[0-9]+}}, x29, #[[LOC_FROM_FP:[0-9]+]]
call void @use_addr_loc(ptr %buf, ptr %loc)
+; CHECK: bl use_addr
%val = load i64, ptr %loc
+; CHECK: ldur x0, [x29, #-[[LOC_FROM_FP]]]
ret i64 %val
; Make sure epilogue restores sp from fp
+; CHECK: {{sub|mov}} sp, x29
+; CHECK: ret
}
%struct.__va_list = type { ptr, ptr, ptr, i32, i32 }
define void @test_variadic_alloca(i64 %n, ...) {
; CHECK-LABEL: test_variadic_alloca:
-; CHECK: // %bb.0:
-; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
-; CHECK-NEXT: mov x29, sp
-; CHECK-NEXT: sub sp, sp, #224
-; CHECK-NEXT: .cfi_def_cfa w29, 16
-; CHECK-NEXT: .cfi_offset w30, -8
-; CHECK-NEXT: .cfi_offset w29, -16
-; CHECK-NEXT: stp x1, x2, [x29, #-88]
-; CHECK-NEXT: stp x3, x4, [x29, #-72]
-; CHECK-NEXT: stp x5, x6, [x29, #-56]
-; CHECK-NEXT: stp q0, q1, [x29, #-224]
-; CHECK-NEXT: stp q2, q3, [x29, #-192]
-; CHECK-NEXT: stp q4, q5, [x29, #-160]
-; CHECK-NEXT: stp q6, q7, [x29, #-128]
-; CHECK-NEXT: mov x8, #-56 // =0xffffffffffffffc8
-; CHECK-NEXT: movk x8, #65408, lsl #32
-; CHECK-NEXT: sub x9, x29, #224
-; CHECK-NEXT: add x9, x9, #128
-; CHECK-NEXT: sub x10, x29, #88
-; CHECK-NEXT: stp x9, x8, [x29, #-16]
-; CHECK-NEXT: add x8, x10, #56
-; CHECK-NEXT: add x9, x29, #16
-; CHECK-NEXT: stur x8, [x29, #-24]
-; CHECK-NEXT: stp x7, x9, [x29, #-40]
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x0, sp, x8
-; CHECK-NEXT: mov sp, x0
-; CHECK-NEXT: bl use_addr
-; CHECK-NEXT: mov sp, x29
-; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
-; CHECK-NEXT: ret
-;
-; CHECK-MACHO-LABEL: test_variadic_alloca:
-; CHECK-MACHO: ; %bb.0:
-; CHECK-MACHO-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
-; CHECK-MACHO-NEXT: mov x29, sp
-; CHECK-MACHO-NEXT: sub sp, sp, #32
-; CHECK-MACHO-NEXT: .cfi_def_cfa w29, 16
-; CHECK-MACHO-NEXT: .cfi_offset w30, -8
-; CHECK-MACHO-NEXT: .cfi_offset w29, -16
-; CHECK-MACHO-NEXT: add x8, x29, #16
-; CHECK-MACHO-NEXT: stur x8, [x29, #-32]
-; CHECK-MACHO-NEXT: add x8, x0, #15
-; CHECK-MACHO-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-MACHO-NEXT: sub x0, sp, x8
-; CHECK-MACHO-NEXT: mov sp, x0
-; CHECK-MACHO-NEXT: bl _use_addr
-; CHECK-MACHO-NEXT: mov sp, x29
-; CHECK-MACHO-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
-; CHECK-MACHO-NEXT: ret
-;
-; CHECK-NOFP-ARM64-LABEL: test_variadic_alloca:
-; CHECK-NOFP-ARM64: // %bb.0:
-; CHECK-NOFP-ARM64-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
-; CHECK-NOFP-ARM64-NEXT: mov x29, sp
-; CHECK-NOFP-ARM64-NEXT: sub sp, sp, #96
-; CHECK-NOFP-ARM64-NEXT: .cfi_def_cfa w29, 16
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w30, -8
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w29, -16
-; CHECK-NOFP-ARM64-NEXT: stp x1, x2, [x29, #-88]
-; CHECK-NOFP-ARM64-NEXT: stp x3, x4, [x29, #-72]
-; CHECK-NOFP-ARM64-NEXT: stp x5, x6, [x29, #-56]
-; CHECK-NOFP-ARM64-NEXT: add x8, x29, #16
-; CHECK-NOFP-ARM64-NEXT: sub x9, x29, #88
-; CHECK-NOFP-ARM64-NEXT: add x9, x9, #56
-; CHECK-NOFP-ARM64-NEXT: stp x7, x8, [x29, #-40]
-; CHECK-NOFP-ARM64-NEXT: stur x9, [x29, #-24]
-; CHECK-NOFP-ARM64-NEXT: mov w8, #-56 // =0xffffffc8
-; CHECK-NOFP-ARM64-NEXT: stur x8, [x29, #-8]
-; CHECK-NOFP-ARM64-NEXT: add x8, x0, #15
-; CHECK-NOFP-ARM64-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NOFP-ARM64-NEXT: sub x0, sp, x8
-; CHECK-NOFP-ARM64-NEXT: mov sp, x0
-; CHECK-NOFP-ARM64-NEXT: bl use_addr
-; CHECK-NOFP-ARM64-NEXT: mov sp, x29
-; CHECK-NOFP-ARM64-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
-; CHECK-NOFP-ARM64-NEXT: ret
; [...]
@@ -236,18 +77,33 @@ define void @test_variadic_alloca(i64 %n, ...) {
; CHECK-NOFP-AARCH64: add x8, [[TMP]], #0
+; CHECK: stp x29, x30, [sp, #-16]!
+; CHECK: mov x29, sp
+; CHECK: sub sp, sp, #224
+; CHECK-DAG: stp q6, q7, [x29, #-128]
; [...]
+; CHECK-DAG: stp q2, q3, [x29, #-192]
+; CHECK-DAG: stp x5, x6, [x29, #-56]
; [...]
+; CHECK-DAG: stp x1, x2, [x29, #-88]
+; CHECK-NOFP-ARM64: stp x29, x30, [sp, #-16]!
+; CHECK-NOFP-ARM64: mov x29, sp
+; CHECK-NOFP-ARM64: sub sp, sp, #16
+; CHECK-NOFP-ARM64-DAG: stp x5, x6, [x29, #-56]
; [...]
+; CHECK-NOFP-ARM64-DAG: stp x3, x4, [x29, #-72]
; [...]
+; CHECK-NOFP-ARM64-DAG: stp x1, x2, [x29, #-88]
; [...]
+; CHECK-NOFP-ARM64: mov x8, sp
%valist = alloca %struct.__va_list
call void @llvm.va_start(ptr %valist)
%addr = alloca i8, i64 %n
call void @use_addr(ptr %addr)
+; CHECK: bl use_addr
call void @llvm.va_end(ptr %valist)
ret void
@@ -256,83 +112,26 @@ define void @test_variadic_alloca(i64 %n, ...) {
; CHECK-NOFP-AARCH64: ldp x29, x30, [sp, #64]
; CHECK-NOFP-AARCH64: add sp, sp, #80
+; CHECK-NOFP-ARM64: mov sp, x29
+; CHECK-NOFP-ARM64: ldp x29, x30, [sp], #16
}
define void @test_alloca_large_frame(i64 %n) {
; CHECK-LABEL: test_alloca_large_frame:
-; CHECK: // %bb.0:
-; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
-; CHECK-NEXT: stp x28, x19, [sp, #16] // 16-byte Folded Spill
-; CHECK-NEXT: mov x29, sp
-; CHECK-NEXT: sub sp, sp, #1953, lsl #12 // =7999488
-; CHECK-NEXT: sub sp, sp, #512
-; CHECK-NEXT: mov x19, sp
-; CHECK-NEXT: .cfi_def_cfa w29, 32
-; CHECK-NEXT: .cfi_offset w19, -8
-; CHECK-NEXT: .cfi_offset w28, -16
-; CHECK-NEXT: .cfi_offset w30, -24
-; CHECK-NEXT: .cfi_offset w29, -32
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x0, sp, x8
-; CHECK-NEXT: mov sp, x0
-; CHECK-NEXT: add x1, x19, #0
-; CHECK-NEXT: bl use_addr_loc
-; CHECK-NEXT: mov sp, x29
-; CHECK-NEXT: ldp x28, x19, [sp, #16] // 16-byte Folded Reload
-; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
-; CHECK-NEXT: ret
-;
; CHECK-MACHO-LABEL: test_alloca_large_frame:
-; CHECK-MACHO: ; %bb.0:
-; CHECK-MACHO-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
-; CHECK-MACHO-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill
-; CHECK-MACHO-NEXT: add x29, sp, #16
-; CHECK-MACHO-NEXT: sub sp, sp, #1953, lsl #12 ; =7999488
-; CHECK-MACHO-NEXT: sub sp, sp, #512
-; CHECK-MACHO-NEXT: mov x19, sp
-; CHECK-MACHO-NEXT: .cfi_def_cfa w29, 16
-; CHECK-MACHO-NEXT: .cfi_offset w30, -8
-; CHECK-MACHO-NEXT: .cfi_offset w29, -16
-; CHECK-MACHO-NEXT: .cfi_offset w19, -24
-; CHECK-MACHO-NEXT: .cfi_offset w20, -32
-; CHECK-MACHO-NEXT: add x8, x0, #15
-; CHECK-MACHO-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-MACHO-NEXT: sub x0, sp, x8
-; CHECK-MACHO-NEXT: mov sp, x0
-; CHECK-MACHO-NEXT: add x1, x19, #0
-; CHECK-MACHO-NEXT: bl _use_addr_loc
-; CHECK-MACHO-NEXT: sub sp, x29, #16
-; CHECK-MACHO-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
-; CHECK-MACHO-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
-; CHECK-MACHO-NEXT: ret
-;
-; CHECK-NOFP-ARM64-LABEL: test_alloca_large_frame:
-; CHECK-NOFP-ARM64: // %bb.0:
-; CHECK-NOFP-ARM64-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
-; CHECK-NOFP-ARM64-NEXT: stp x28, x19, [sp, #16] // 16-byte Folded Spill
-; CHECK-NOFP-ARM64-NEXT: mov x29, sp
-; CHECK-NOFP-ARM64-NEXT: sub sp, sp, #1953, lsl #12 // =7999488
-; CHECK-NOFP-ARM64-NEXT: sub sp, sp, #512
-; CHECK-NOFP-ARM64-NEXT: mov x19, sp
-; CHECK-NOFP-ARM64-NEXT: .cfi_def_cfa w29, 32
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w19, -8
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w28, -16
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w30, -24
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w29, -32
-; CHECK-NOFP-ARM64-NEXT: add x8, x0, #15
-; CHECK-NOFP-ARM64-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NOFP-ARM64-NEXT: sub x0, sp, x8
-; CHECK-NOFP-ARM64-NEXT: mov sp, x0
-; CHECK-NOFP-ARM64-NEXT: add x1, x19, #0
-; CHECK-NOFP-ARM64-NEXT: bl use_addr_loc
-; CHECK-NOFP-ARM64-NEXT: mov sp, x29
-; CHECK-NOFP-ARM64-NEXT: ldp x28, x19, [sp, #16] // 16-byte Folded Reload
-; CHECK-NOFP-ARM64-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
-; CHECK-NOFP-ARM64-NEXT: ret
+; CHECK: stp x29, x30, [sp, #-32]!
+; CHECK: stp x28, x19, [sp, #16]
+; CHECK: mov x29, sp
+; CHECK: sub sp, sp, #1953, lsl #12
+; CHECK: sub sp, sp, #512
+; CHECK-MACHO: stp x20, x19, [sp, #-32]!
+; CHECK-MACHO: stp x29, x30, [sp, #16]
+; CHECK-MACHO: add x29, sp, #16
+; CHECK-MACHO: sub sp, sp, #1953, lsl #12
+; CHECK-MACHO: sub sp, sp, #512
%addr1 = alloca i8, i64 %n
%addr2 = alloca i64, i64 1000000
@@ -341,7 +140,13 @@ define void @test_alloca_large_frame(i64 %n) {
ret void
+; CHECK: mov sp, x29
+; CHECK: ldp x28, x19, [sp, #16]
+; CHECK: ldp x29, x30, [sp], #32
+; CHECK-MACHO: sub sp, x29, #16
+; CHECK-MACHO: ldp x29, x30, [sp, #16]
+; CHECK-MACHO: ldp x20, x19, [sp], #32
}
declare ptr @llvm.stacksave()
@@ -349,76 +154,22 @@ declare void @llvm.stackrestore(ptr)
define void @test_scoped_alloca(i64 %n) {
; CHECK-LABEL: test_scoped_alloca:
-; CHECK: // %bb.0:
-; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
-; CHECK-NEXT: str x19, [sp, #16] // 8-byte Spill
-; CHECK-NEXT: mov x29, sp
-; CHECK-NEXT: .cfi_def_cfa w29, 32
-; CHECK-NEXT: .cfi_offset w19, -16
-; CHECK-NEXT: .cfi_offset w30, -24
-; CHECK-NEXT: .cfi_offset w29, -32
-; CHECK-NEXT: mov x19, sp
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x0, sp, x8
-; CHECK-NEXT: mov sp, x0
-; CHECK-NEXT: bl use_addr
-; CHECK-NEXT: mov sp, x19
-; CHECK-NEXT: mov sp, x29
-; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
-; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
-; CHECK-NEXT: ret
-;
-; CHECK-MACHO-LABEL: test_scoped_alloca:
-; CHECK-MACHO: ; %bb.0:
-; CHECK-MACHO-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
-; CHECK-MACHO-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill
-; CHECK-MACHO-NEXT: add x29, sp, #16
-; CHECK-MACHO-NEXT: .cfi_def_cfa w29, 16
-; CHECK-MACHO-NEXT: .cfi_offset w30, -8
-; CHECK-MACHO-NEXT: .cfi_offset w29, -16
-; CHECK-MACHO-NEXT: .cfi_offset w19, -24
-; CHECK-MACHO-NEXT: .cfi_offset w20, -32
-; CHECK-MACHO-NEXT: mov x19, sp
-; CHECK-MACHO-NEXT: add x8, x0, #15
-; CHECK-MACHO-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-MACHO-NEXT: sub x0, sp, x8
-; CHECK-MACHO-NEXT: mov sp, x0
-; CHECK-MACHO-NEXT: bl _use_addr
-; CHECK-MACHO-NEXT: mov sp, x19
-; CHECK-MACHO-NEXT: sub sp, x29, #16
-; CHECK-MACHO-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
-; CHECK-MACHO-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
-; CHECK-MACHO-NEXT: ret
-;
-; CHECK-NOFP-ARM64-LABEL: test_scoped_alloca:
-; CHECK-NOFP-ARM64: // %bb.0:
-; CHECK-NOFP-ARM64-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
-; CHECK-NOFP-ARM64-NEXT: str x19, [sp, #16] // 8-byte Spill
-; CHECK-NOFP-ARM64-NEXT: mov x29, sp
-; CHECK-NOFP-ARM64-NEXT: .cfi_def_cfa w29, 32
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w19, -16
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w30, -24
-; CHECK-NOFP-ARM64-NEXT: .cfi_offset w29, -32
-; CHECK-NOFP-ARM64-NEXT: mov x19, sp
-; CHECK-NOFP-ARM64-NEXT: add x8, x0, #15
-; CHECK-NOFP-ARM64-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NOFP-ARM64-NEXT: sub x0, sp, x8
-; CHECK-NOFP-ARM64-NEXT: mov sp, x0
-; CHECK-NOFP-ARM64-NEXT: bl use_addr
-; CHECK-NOFP-ARM64-NEXT: mov sp, x19
-; CHECK-NOFP-ARM64-NEXT: mov sp, x29
-; CHECK-NOFP-ARM64-NEXT: ldr x19, [sp, #16] // 8-byte Reload
-; CHECK-NOFP-ARM64-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
-; CHECK-NOFP-ARM64-NEXT: ret
%sp = call ptr @llvm.stacksave()
+; CHECK: mov x29, sp
+; CHECK: mov [[SAVED_SP:x[0-9]+]], sp
+; CHECK: mov [[OLDSP:x[0-9]+]], sp
%addr = alloca i8, i64 %n
+; CHECK: and [[SPDELTA:x[0-9]+]], {{x[0-9]+}}, #0xfffffffffffffff0
+; CHECK-DAG: sub [[NEWSP:x[0-9]+]], [[OLDSP]], [[SPDELTA]]
+; CHECK: mov sp, [[NEWSP]]
call void @use_addr(ptr %addr)
+; CHECK: bl use_addr
call void @llvm.stackrestore(ptr %sp)
+; CHECK: mov sp, [[SAVED_SP]]
ret void
}
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
index 26239d2633241..9e5580d054935 100644
--- a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
+++ b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
@@ -1,7 +1,22 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s
define void @simple(ptr %g) {
+; CHECK-LABEL: "#simple":
+; CHECK: str x30, [sp, #-16]!
+; CHECK-NEXT: .seh_save_reg_x x30, 16
+; CHECK-NEXT: .seh_endprologue
+; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
+; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$v$v
+; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$v$v
+; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
+; CHECK-NEXT: mov x11, x0
+; CHECK-NEXT: blr x8
+; CHECK-NEXT: blr x11
+; CHECK-NEXT: .seh_startepilogue
+; CHECK-NEXT: ldr x30, [sp], #16
+; CHECK-NEXT: .seh_save_reg_x x30, 16
+; CHECK-NEXT: .seh_endepilogue
+; CHECK-NEXT: ret
entry:
call void %g()
@@ -10,10 +25,27 @@ entry:
; Make sure the check for the security cookie doesn't use x9.
define void @stackguard(ptr %g) sspreq {
+; CHECK-LABEL: "#stackguard":
+; CHECK: adrp x8, __os_arm64x_check_icall
+; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
+; CHECK-NEXT: blr x8
+; CHECK-NEXT: ldr x8, [sp, #8]
+; CHECK-NEXT: adrp x10, __security_cookie
+; CHECK-NEXT: ldr x10, [x10, :lo12:__security_cookie]
+; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: cmp x10, x8
+; CHECK-NEXT: b.ne .LBB1_2
+; CHECK-NEXT: // %bb.1:
+; CHECK-NEXT: fmov d0, #1.00000000
+; CHECK-NEXT: .seh_startepilogue
+; CHECK-NEXT: ldr x30, [sp, #16]
+; CHECK-NEXT: .seh_save_reg x30, 16
+; CHECK-NEXT: add sp, sp, #32
+; CHECK-NEXT: .seh_stackalloc 32
+; CHECK-NEXT: .seh_endepilogue
+; CHECK-NEXT: br x11
entry:
%call = tail call double %g(double noundef 1.000000e+00)
ret void
}
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/mingw-refptr.ll b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
index 8074bf1ade154..5799c5f73cafe 100644
--- a/llvm/test/CodeGen/AArch64/mingw-refptr.ll
+++ b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
@@ -77,77 +77,47 @@ entry:
declare dso_local void @otherFunc()
define dso_local void @sspFunc() #0 {
-; CHECK-SD-LABEL: sspFunc:
-; CHECK-SD: .seh_proc sspFunc
-; CHECK-SD-NEXT: // %bb.0: // %entry
-; CHECK-SD-NEXT: sub sp, sp, #32
-; CHECK-SD-NEXT: .seh_stackalloc 32
-; CHECK-SD-NEXT: str x30, [sp, #16] // 8-byte Spill
-; CHECK-SD-NEXT: .seh_save_reg x30, 16
-; CHECK-SD-NEXT: .seh_endprologue
-; CHECK-SD-NEXT: adrp x8, .refptr.__stack_chk_guard
-; CHECK-SD-NEXT: add x0, sp, #7
-; CHECK-SD-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
-; CHECK-SD-NEXT: ldr x8, [x8]
-; CHECK-SD-NEXT: sub x8, sp, x8
-; CHECK-SD-NEXT: str x8, [sp, #8]
-; CHECK-SD-NEXT: bl ptrUser
-; CHECK-SD-NEXT: adrp x9, .refptr.__stack_chk_guard
-; CHECK-SD-NEXT: ldr x8, [sp, #8]
-; CHECK-SD-NEXT: ldr x9, [x9, :lo12:.refptr.__stack_chk_guard]
-; CHECK-SD-NEXT: sub x8, sp, x8
-; CHECK-SD-NEXT: ldr x9, [x9]
-; CHECK-SD-NEXT: cmp x9, x8
-; CHECK-SD-NEXT: b.ne .LBB6_2
-; CHECK-SD-NEXT: // %bb.1: // %entry
-; CHECK-SD-NEXT: .seh_startepilogue
-; CHECK-SD-NEXT: ldr x30, [sp, #16] // 8-byte Reload
-; CHECK-SD-NEXT: .seh_save_reg x30, 16
-; CHECK-SD-NEXT: add sp, sp, #32
-; CHECK-SD-NEXT: .seh_stackalloc 32
-; CHECK-SD-NEXT: .seh_endepilogue
-; CHECK-SD-NEXT: ret
-; CHECK-SD-NEXT: .LBB6_2: // %entry
-; CHECK-SD-NEXT: bl __stack_chk_fail
-; CHECK-SD-NEXT: brk #0x1
-; CHECK-SD-NEXT: .seh_endfunclet
-; CHECK-SD-NEXT: .seh_endproc
-;
-; CHECK-GI-LABEL: sspFunc:
-; CHECK-GI: .seh_proc sspFunc
-; CHECK-GI-NEXT: // %bb.0: // %entry
-; CHECK-GI-NEXT: sub sp, sp, #32
-; CHECK-GI-NEXT: .seh_stackalloc 32
-; CHECK-GI-NEXT: str x30, [sp, #16] // 8-byte Spill
-; CHECK-GI-NEXT: .seh_save_reg x30, 16
-; CHECK-GI-NEXT: .seh_endprologue
-; CHECK-GI-NEXT: adrp x8, .refptr.__stack_chk_guard
-; CHECK-GI-NEXT: add x0, sp, #7
-; CHECK-GI-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
-; CHECK-GI-NEXT: ldr x8, [x8]
-; CHECK-GI-NEXT: sub x8, sp, x8
-; CHECK-GI-NEXT: str x8, [sp, #8]
-; CHECK-GI-NEXT: bl ptrUser
-; CHECK-GI-NEXT: adrp x8, .refptr.__stack_chk_guard
-; CHECK-GI-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
-; CHECK-GI-NEXT: ldr x9, [sp, #8]
-; CHECK-GI-NEXT: ldr x8, [x8]
-; CHECK-GI-NEXT: sub x8, sp, x8
-; CHECK-GI-NEXT: cmp x8, x9
-; CHECK-GI-NEXT: b.ne .LBB6_2
-; CHECK-GI-NEXT: // %bb.1: // %entry
-; CHECK-GI-NEXT: .seh_startepilogue
-; CHECK-GI-NEXT: ldr x30, [sp, #16] // 8-byte Reload
-; CHECK-GI-NEXT: .seh_save_reg x30, 16
-; CHECK-GI-NEXT: add sp, sp, #32
-; CHECK-GI-NEXT: .seh_stackalloc 32
-; CHECK-GI-NEXT: .seh_endepilogue
-; CHECK-GI-NEXT: ret
-; CHECK-GI-NEXT: .LBB6_2: // %entry
-; CHECK-GI-NEXT: bl __stack_chk_fail
-; CHECK-GI-NEXT: brk #0x1
-; CHECK-GI-NEXT: .seh_endfunclet
-; CHECK-GI-NEXT: .seh_endproc
+; CHECK-LABEL: sspFunc:
+; CHECK: .seh_proc sspFunc
+; CHECK-NEXT: // %bb.0: // %entry
+; CHECK-NEXT: sub sp, sp, #32
+; CHECK-NEXT: .seh_stackalloc 32
+; CHECK-NEXT: str x30, [sp, #16] // 8-byte Spill
+; CHECK-NEXT: .seh_save_reg x30, 16
+; CHECK-NEXT: .seh_endprologue
+; CHECK-NEXT: adrp x8, .refptr.__stack_chk_guard
+; CHECK-NEXT: add x0, sp, #7
+; CHECK-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
+; CHECK-NEXT: ldr x8, [x8]
+; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: str x8, [sp, #8]
+; CHECK-NEXT: bl ptrUser
+; CHECK-SD-NEXT: adrp x9, .refptr.__stack_chk_guard
+; CHECK-SD-NEXT: ldr x8, [sp, #8]
+; CHECK-SD-NEXT: ldr x9, [x9, :lo12:.refptr.__stack_chk_guard]
+; CHECK-SD-NEXT: sub x8, sp, x8
+; CHECK-SD-NEXT: ldr x9, [x9]
+; CHECK-SD-NEXT: cmp x9, x8
+; CHECK-GI-NEXT: adrp x8, .refptr.__stack_chk_guard
+; CHECK-GI-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
+; CHECK-GI-NEXT: ldr x9, [sp, #8]
+; CHECK-GI-NEXT: ldr x8, [x8]
+; CHECK-GI-NEXT: sub x8, sp, x8
+; CHECK-GI-NEXT: cmp x8, x9
+; CHECK-NEXT: b.ne .LBB6_2
+; CHECK-NEXT: // %bb.1: // %entry
+; CHECK-NEXT: .seh_startepilogue
+; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Reload
+; CHECK-NEXT: .seh_save_reg x30, 16
+; CHECK-NEXT: add sp, sp, #32
+; CHECK-NEXT: .seh_stackalloc 32
+; CHECK-NEXT: .seh_endepilogue
+; CHECK-NEXT: ret
+; CHECK-NEXT: .LBB6_2: // %entry
+; CHECK-NEXT: bl __stack_chk_fail
+; CHECK-NEXT: brk #0x1
+; CHECK-NEXT: .seh_endfunclet
+; CHECK-NEXT: .seh_endproc
entry:
%c = alloca i8, align 1
call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %c)
@@ -171,3 +141,6 @@ attributes #0 = { sspstrong }
; CHECK: .refptr.var:
; CHECK: .xword var
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK-GI: {{.*}}
+; CHECK-SD: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/shrink-wrapping-vla.ll b/llvm/test/CodeGen/AArch64/shrink-wrapping-vla.ll
index 5075bc9879e78..c21ccfe522d74 100644
--- a/llvm/test/CodeGen/AArch64/shrink-wrapping-vla.ll
+++ b/llvm/test/CodeGen/AArch64/shrink-wrapping-vla.ll
@@ -87,11 +87,12 @@ declare void @llvm.stackrestore(ptr)
; VLA allocation
; CHECK: ubfiz x8, x0, #2, #32
-; Saving the SP via llvm.stacksave()
+; CHECK: mov x9, sp
; CHECK: mov [[SAVE:x[0-9]+]], sp
; CHECK: add x8, x8, #15
; CHECK: and [[X1:x[0-9]+]], [[X1]], #0x7fffffff0
-; CHECK: sub [[X1]], sp, [[X1]]
+; Saving the SP via llvm.stacksave()
+; CHECK: sub [[X1]], [[X2:x[0-9]+]], [[X1]]
; The next instruction comes from llvm.stackrestore()
; CHECK: mov sp, [[SAVE]]
diff --git a/llvm/test/CodeGen/AArch64/sme-agnostic-za.ll b/llvm/test/CodeGen/AArch64/sme-agnostic-za.ll
index c01314373266d..e9d7971560474 100644
--- a/llvm/test/CodeGen/AArch64/sme-agnostic-za.ll
+++ b/llvm/test/CodeGen/AArch64/sme-agnostic-za.ll
@@ -212,7 +212,8 @@ define void @agnostic_za_buffer_alloc_with_stack_probes() nounwind "aarch64_za_s
; CHECK-NEXT: str x19, [sp, #16] // 8-byte Spill
; CHECK-NEXT: mov x29, sp
; CHECK-NEXT: bl __arm_sme_state_size
-; CHECK-NEXT: sub x19, sp, x0
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: sub x19, x8, x0
; CHECK-NEXT: .LBB7_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #16, lsl #12 // =65536
; CHECK-NEXT: cmp sp, x19
diff --git a/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll b/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll
index b603197a03943..301eee43d33e6 100644
--- a/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll
+++ b/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll
@@ -19,8 +19,9 @@ define void @quux(i64 %n) "aarch64_new_za" "aarch64_pstate_sm_enabled" {
; CHECK-NEXT: .cfi_offset w30, -24
; CHECK-NEXT: .cfi_offset w29, -32
; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: and x9, x8, #0xfffffffffffffff0
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: subs x8, x8, x9
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: mov sp, x29
diff --git a/llvm/test/CodeGen/AArch64/sme-lazy-save-windows.ll b/llvm/test/CodeGen/AArch64/sme-lazy-save-windows.ll
index 75ad7c01829db..6e2d2c0269757 100644
--- a/llvm/test/CodeGen/AArch64/sme-lazy-save-windows.ll
+++ b/llvm/test/CodeGen/AArch64/sme-lazy-save-windows.ll
@@ -15,8 +15,7 @@ define void @test_lazy_save() nounwind "aarch64_inout_za" {
; CHECK-NEXT: mul x9, x8, x8
; CHECK-NEXT: lsr x15, x9, #4
; CHECK-NEXT: bl __chkstk
-; CHECK-NEXT: lsl x9, x15, #4
-; CHECK-NEXT: sub x9, sp, x9
+; CHECK-NEXT: sub x9, sp, x15, lsl #4
; CHECK-NEXT: mov sp, x9
; CHECK-NEXT: sub x10, x29, #24
; CHECK-NEXT: stp x9, x8, [x29, #-24]
diff --git a/llvm/test/CodeGen/AArch64/sme-streaming-mode-changing-call-disable-stackslot-scavenging.ll b/llvm/test/CodeGen/AArch64/sme-streaming-mode-changing-call-disable-stackslot-scavenging.ll
index 3ec2ea9ff57ce..72f0eac9b659c 100644
--- a/llvm/test/CodeGen/AArch64/sme-streaming-mode-changing-call-disable-stackslot-scavenging.ll
+++ b/llvm/test/CodeGen/AArch64/sme-streaming-mode-changing-call-disable-stackslot-scavenging.ll
@@ -57,12 +57,13 @@ define void @test_no_stackslot_scavenging_with_fp(float %f, i64 %n) #0 "frame-po
; CHECK-NEXT: stp x24, x19, [sp, #96] // 16-byte Folded Spill
; CHECK-NEXT: sub sp, sp, #16
; CHECK-NEXT: addvl sp, sp, #-1
-; CHECK-NEXT: lsl x8, x0, #3
+; CHECK-NEXT: lsl x9, x0, #3
+; CHECK-NEXT: mov x8, sp
; CHECK-NEXT: mov x19, sp
; CHECK-NEXT: str s0, [x19, #12] // 4-byte Spill
-; CHECK-NEXT: add x8, x8, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: add x9, x9, #15
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: //APP
; CHECK-NEXT: //NO_APP
diff --git a/llvm/test/CodeGen/AArch64/sme-za-lazy-save-buffer.ll b/llvm/test/CodeGen/AArch64/sme-za-lazy-save-buffer.ll
index 6d5bf42536e43..27082d9af93b3 100644
--- a/llvm/test/CodeGen/AArch64/sme-za-lazy-save-buffer.ll
+++ b/llvm/test/CodeGen/AArch64/sme-za-lazy-save-buffer.ll
@@ -72,8 +72,8 @@ define float @multi_bb_stpidr2_save_required_stackprobe(i32 %a, float %b, float
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
; CHECK-NEXT: rdsvl x8, #1
-; CHECK-NEXT: mul x9, x8, x8
-; CHECK-NEXT: sub x9, sp, x9
+; CHECK-NEXT: mov x9, sp
+; CHECK-NEXT: msub x9, x8, x8, x9
; CHECK-NEXT: .LBB2_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #16, lsl #12 // =65536
; CHECK-NEXT: cmp sp, x9
diff --git a/llvm/test/CodeGen/AArch64/split-sve-stack-frame-layout.ll b/llvm/test/CodeGen/AArch64/split-sve-stack-frame-layout.ll
index dd90ec2c887df..c237248085df3 100644
--- a/llvm/test/CodeGen/AArch64/split-sve-stack-frame-layout.ll
+++ b/llvm/test/CodeGen/AArch64/split-sve-stack-frame-layout.ll
@@ -811,9 +811,10 @@ define aarch64_sve_vector_pcs void @only_ppr_csr_vla(i64 %n) {
; CHECK-NEXT: .cfi_offset w19, -16
; CHECK-NEXT: .cfi_offset w30, -24
; CHECK-NEXT: .cfi_offset w29, -32
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: //APP
@@ -855,9 +856,10 @@ define aarch64_sve_vector_pcs void @only_zpr_csr_vla(i64 %n) {
; CHECK-NEXT: .cfi_escape 0x10, 0x48, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x78, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d8 @ cfa - 8 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x49, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x70, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d9 @ cfa - 16 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x4a, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x68, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d10 @ cfa - 24 * VG - 1056
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: sub x8, x29, #1024
@@ -906,9 +908,10 @@ define aarch64_sve_vector_pcs void @zpr_ppr_csr_vla(i64 %n) {
; CHECK-NEXT: .cfi_escape 0x10, 0x48, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x70, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d8 @ cfa - 16 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x49, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x68, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d9 @ cfa - 24 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x4a, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x60, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d10 @ cfa - 32 * VG - 1056
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: sub x8, x29, #1024
@@ -954,9 +957,10 @@ define void @sve_locals_only_ppr_csr_vla(i64 %n, <vscale x 16 x i1> %pred, <vsca
; CHECK-NEXT: .cfi_offset w19, -16
; CHECK-NEXT: .cfi_offset w30, -24
; CHECK-NEXT: .cfi_offset w29, -32
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: sub x8, x29, #1024
@@ -1007,9 +1011,10 @@ define void @sve_locals_only_zpr_csr_vla(i64 %n, <vscale x 16 x i1> %pred, <vsca
; CHECK-NEXT: .cfi_escape 0x10, 0x48, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x70, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d8 @ cfa - 16 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x49, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x68, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d9 @ cfa - 24 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x4a, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x60, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d10 @ cfa - 32 * VG - 1056
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: sub x8, x29, #1024
@@ -1065,9 +1070,10 @@ define void @sve_locals_zpr_ppr_csr_vla(i64 %n, <vscale x 16 x i1> %pred, <vscal
; CHECK-NEXT: .cfi_escape 0x10, 0x48, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x68, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d8 @ cfa - 24 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x49, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x60, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d9 @ cfa - 32 * VG - 1056
; CHECK-NEXT: .cfi_escape 0x10, 0x4a, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x58, 0x1e, 0x22, 0x11, 0xe0, 0x77, 0x22 // $d10 @ cfa - 40 * VG - 1056
-; CHECK-NEXT: add x8, x0, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: // fake_use: $x8
; CHECK-NEXT: sub x8, x29, #1024
diff --git a/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll b/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
index 9dbeac976bf4d..44bd696640113 100644
--- a/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
+++ b/llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
@@ -55,16 +55,17 @@ define dso_local void @foo(i64 %t) local_unnamed_addr #0 {
; CHECK-TPIDR0: mrs x8, TPIDR_EL0
; CHECK-TPIDR1: mrs x8, TPIDR_EL1
; CHECK-TPIDR2: mrs x8, TPIDR_EL2
-; CHECK-NO-OFFSET-NEXT: ldr x8, [x8]
-; CHECK-POSITIVE-OFFSET-NEXT: ldr x8, [x8, #8]
-; CHECK-NEGATIVE-OFFSET-NEXT: ldur x8, [x8, #-8]
-; CHECK-NPOT-OFFSET-NEXT: ldur x8, [x8, #1]
-; CHECK-NPOT-NEG-OFFSET-NEXT: ldur x8, [x8, #-1]
+; CHECK-NEXT: lsl x9, x0, #2
+; CHECK-NO-OFFSET: ldr x8, [x8]
+; CHECK-POSITIVE-OFFSET: ldr x8, [x8, #8]
+; CHECK-NEGATIVE-OFFSET: ldur x8, [x8, #-8]
+; CHECK-NPOT-OFFSET: ldur x8, [x8, #1]
+; CHECK-NPOT-NEG-OFFSET: ldur x8, [x8, #-1]
+; CHECK-NEXT: add x9, x9, #15
; CHECK-NEXT: stur x8, [x29, #-8]
-; CHECK-NEXT: lsl x8, x0, #2
-; CHECK-NEXT: add x8, x8, #15
-; CHECK-NEXT and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT sub x0, sp, x8
+; CHECK-NEXT mov x8, sp
+; CHECK-NEXT and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT sub x0, x8, x9
; CHECK-NEXT mov sp, x0
; CHECK-NEXT bl baz
; CHECK-SP: mrs x8, SP_EL0
@@ -108,14 +109,15 @@ define dso_local void @foo(i64 %t) local_unnamed_addr #0 {
; CHECK-ADD-NEXT: sub sp, sp, #16
; CHECK-FAR1: mrs x8, FAR_EL1
; CHECK-FAR2: mrs x8, FAR_EL2
+; CHECK-ADD-NEXT: lsl x9, x0, #2
; CHECK-MINUS-257-OFFSET: sub x8, x8, #257
; CHECK-257-OFFSET: add x8, x8, #257
; CHECK-ADD-NEXT: ldr x8, [x8]
+; CHECK-ADD-NEXT: add x9, x9, #15
+; CHECK-ADD-NEXT: and x9, x9, #0xfffffffffffffff0
; CHECK-ADD-NEXT: stur x8, [x29, #-8]
-; CHECK-ADD-NEXT: lsl x8, x0, #2
-; CHECK-ADD-NEXT: add x8, x8, #15
-; CHECK-ADD-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-ADD-NEXT: sub x0, sp, x8
+; CHECK-ADD-NEXT: mov x8, sp
+; CHECK-ADD-NEXT: sub x0, x8, x9
; CHECK-ADD-NEXT: mov sp, x0
; CHECK-ADD-NEXT: bl baz
; CHECK-FAR1: mrs x8, FAR_EL1
diff --git a/llvm/test/CodeGen/AArch64/stack-hazard.ll b/llvm/test/CodeGen/AArch64/stack-hazard.ll
index 0454cef9fec24..8a43720faf2a5 100644
--- a/llvm/test/CodeGen/AArch64/stack-hazard.ll
+++ b/llvm/test/CodeGen/AArch64/stack-hazard.ll
@@ -3449,10 +3449,11 @@ define i32 @sve_stack_object_and_vla(double %d, i64 %sz) "aarch64_pstate_sm_comp
; CHECK0-NEXT: .cfi_offset w28, -16
; CHECK0-NEXT: .cfi_offset w30, -24
; CHECK0-NEXT: .cfi_offset w29, -32
-; CHECK0-NEXT: lsl x8, x0, #2
-; CHECK0-NEXT: add x8, x8, #15
-; CHECK0-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK0-NEXT: sub x0, sp, x8
+; CHECK0-NEXT: lsl x9, x0, #2
+; CHECK0-NEXT: mov x8, sp
+; CHECK0-NEXT: add x9, x9, #15
+; CHECK0-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK0-NEXT: sub x0, x8, x9
; CHECK0-NEXT: mov sp, x0
; CHECK0-NEXT: mov z0.s, #0 // =0x0
; CHECK0-NEXT: str z0, [x29, #-1, mul vl]
@@ -3477,10 +3478,11 @@ define i32 @sve_stack_object_and_vla(double %d, i64 %sz) "aarch64_pstate_sm_comp
; CHECK64-NEXT: .cfi_offset w28, -16
; CHECK64-NEXT: .cfi_offset w30, -24
; CHECK64-NEXT: .cfi_offset w29, -32
-; CHECK64-NEXT: lsl x8, x0, #2
-; CHECK64-NEXT: add x8, x8, #15
-; CHECK64-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK64-NEXT: sub x0, sp, x8
+; CHECK64-NEXT: lsl x9, x0, #2
+; CHECK64-NEXT: mov x8, sp
+; CHECK64-NEXT: add x9, x9, #15
+; CHECK64-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK64-NEXT: sub x0, x8, x9
; CHECK64-NEXT: mov sp, x0
; CHECK64-NEXT: mov z0.s, #0 // =0x0
; CHECK64-NEXT: sub x8, x29, #64
@@ -3509,10 +3511,11 @@ define i32 @sve_stack_object_and_vla(double %d, i64 %sz) "aarch64_pstate_sm_comp
; CHECK1024-NEXT: .cfi_offset w28, -16
; CHECK1024-NEXT: .cfi_offset w30, -24
; CHECK1024-NEXT: .cfi_offset w29, -32
-; CHECK1024-NEXT: lsl x8, x0, #2
-; CHECK1024-NEXT: add x8, x8, #15
-; CHECK1024-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK1024-NEXT: sub x0, sp, x8
+; CHECK1024-NEXT: lsl x9, x0, #2
+; CHECK1024-NEXT: mov x8, sp
+; CHECK1024-NEXT: add x9, x9, #15
+; CHECK1024-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK1024-NEXT: sub x0, x8, x9
; CHECK1024-NEXT: mov sp, x0
; CHECK1024-NEXT: mov z0.s, #0 // =0x0
; CHECK1024-NEXT: sub x8, x29, #1024
@@ -3596,10 +3599,11 @@ define i32 @svecc_call_dynamic_alloca(<4 x i16> %P0, i32 %P1, i32 %P2, <vscale x
; CHECK0-NEXT: mov w8, w0
; CHECK0-NEXT: bl __arm_sme_state
; CHECK0-NEXT: mov w8, w8
+; CHECK0-NEXT: mov x9, sp
; CHECK0-NEXT: mov x20, x0
; CHECK0-NEXT: add x8, x8, #15
; CHECK0-NEXT: and x8, x8, #0x1fffffff0
-; CHECK0-NEXT: sub x8, sp, x8
+; CHECK0-NEXT: sub x8, x9, x8
; CHECK0-NEXT: mov sp, x8
; CHECK0-NEXT: //APP
; CHECK0-NEXT: //NO_APP
@@ -3733,10 +3737,11 @@ define i32 @svecc_call_dynamic_alloca(<4 x i16> %P0, i32 %P1, i32 %P2, <vscale x
; CHECK64-NEXT: mov w8, w0
; CHECK64-NEXT: bl __arm_sme_state
; CHECK64-NEXT: mov w8, w8
+; CHECK64-NEXT: mov x9, sp
; CHECK64-NEXT: mov x20, x0
; CHECK64-NEXT: add x8, x8, #15
; CHECK64-NEXT: and x8, x8, #0x1fffffff0
-; CHECK64-NEXT: sub x8, sp, x8
+; CHECK64-NEXT: sub x8, x9, x8
; CHECK64-NEXT: mov sp, x8
; CHECK64-NEXT: //APP
; CHECK64-NEXT: //NO_APP
@@ -3875,10 +3880,11 @@ define i32 @svecc_call_dynamic_alloca(<4 x i16> %P0, i32 %P1, i32 %P2, <vscale x
; CHECK1024-NOSPLITSVE-NEXT: mov w8, w0
; CHECK1024-NOSPLITSVE-NEXT: bl __arm_sme_state
; CHECK1024-NOSPLITSVE-NEXT: mov w8, w8
+; CHECK1024-NOSPLITSVE-NEXT: mov x9, sp
; CHECK1024-NOSPLITSVE-NEXT: mov x20, x0
; CHECK1024-NOSPLITSVE-NEXT: add x8, x8, #15
; CHECK1024-NOSPLITSVE-NEXT: and x8, x8, #0x1fffffff0
-; CHECK1024-NOSPLITSVE-NEXT: sub x8, sp, x8
+; CHECK1024-NOSPLITSVE-NEXT: sub x8, x9, x8
; CHECK1024-NOSPLITSVE-NEXT: mov sp, x8
; CHECK1024-NOSPLITSVE-NEXT: //APP
; CHECK1024-NOSPLITSVE-NEXT: //NO_APP
@@ -4017,10 +4023,11 @@ define i32 @svecc_call_dynamic_alloca(<4 x i16> %P0, i32 %P1, i32 %P2, <vscale x
; CHECK1024-SPLITSVE-NEXT: mov w8, w0
; CHECK1024-SPLITSVE-NEXT: bl __arm_sme_state
; CHECK1024-SPLITSVE-NEXT: mov w8, w8
+; CHECK1024-SPLITSVE-NEXT: mov x9, sp
; CHECK1024-SPLITSVE-NEXT: mov x20, x0
; CHECK1024-SPLITSVE-NEXT: add x8, x8, #15
; CHECK1024-SPLITSVE-NEXT: and x8, x8, #0x1fffffff0
-; CHECK1024-SPLITSVE-NEXT: sub x8, sp, x8
+; CHECK1024-SPLITSVE-NEXT: sub x8, x9, x8
; CHECK1024-SPLITSVE-NEXT: mov sp, x8
; CHECK1024-SPLITSVE-NEXT: //APP
; CHECK1024-SPLITSVE-NEXT: //NO_APP
@@ -4687,9 +4694,10 @@ define i32 @svecc_call_dynamic_and_scalable_alloca(<4 x i16> %P0, i32 %P1, i32 %
; CHECK0-NEXT: .cfi_escape 0x10, 0x4f, 0x0a, 0x92, 0x2e, 0x00, 0x11, 0x40, 0x1e, 0x22, 0x11, 0x40, 0x22 // $d15 @ cfa - 64 * VG - 64
; CHECK0-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK0-NEXT: ubfiz x8, x0, #2, #32
+; CHECK0-NEXT: mov x9, sp
; CHECK0-NEXT: add x8, x8, #15
; CHECK0-NEXT: and x8, x8, #0x7fffffff0
-; CHECK0-NEXT: sub x20, sp, x8
+; CHECK0-NEXT: sub x20, x9, x8
; CHECK0-NEXT: mov sp, x20
; CHECK0-NEXT: //APP
; CHECK0-NEXT: //NO_APP
@@ -4796,9 +4804,10 @@ define i32 @svecc_call_dynamic_and_scalable_alloca(<4 x i16> %P0, i32 %P1, i32 %
; CHECK64-NEXT: .cfi_escape 0x10, 0x4f, 0x0c, 0x92, 0x2e, 0x00, 0x11, 0xb0, 0x7f, 0x1e, 0x22, 0x11, 0x80, 0x7f, 0x22 // $d15 @ cfa - 80 * VG - 128
; CHECK64-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK64-NEXT: ubfiz x8, x0, #2, #32
+; CHECK64-NEXT: mov x9, sp
; CHECK64-NEXT: add x8, x8, #15
; CHECK64-NEXT: and x8, x8, #0x7fffffff0
-; CHECK64-NEXT: sub x20, sp, x8
+; CHECK64-NEXT: sub x20, x9, x8
; CHECK64-NEXT: mov sp, x20
; CHECK64-NEXT: //APP
; CHECK64-NEXT: //NO_APP
@@ -4910,9 +4919,10 @@ define i32 @svecc_call_dynamic_and_scalable_alloca(<4 x i16> %P0, i32 %P1, i32 %
; CHECK1024-NOSPLITSVE-NEXT: .cfi_escape 0x10, 0x4f, 0x0b, 0x92, 0x2e, 0x00, 0x11, 0x40, 0x1e, 0x22, 0x11, 0xc0, 0x77, 0x22 // $d15 @ cfa - 64 * VG - 1088
; CHECK1024-NOSPLITSVE-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK1024-NOSPLITSVE-NEXT: ubfiz x8, x0, #2, #32
+; CHECK1024-NOSPLITSVE-NEXT: mov x9, sp
; CHECK1024-NOSPLITSVE-NEXT: add x8, x8, #15
; CHECK1024-NOSPLITSVE-NEXT: and x8, x8, #0x7fffffff0
-; CHECK1024-NOSPLITSVE-NEXT: sub x20, sp, x8
+; CHECK1024-NOSPLITSVE-NEXT: sub x20, x9, x8
; CHECK1024-NOSPLITSVE-NEXT: mov sp, x20
; CHECK1024-NOSPLITSVE-NEXT: //APP
; CHECK1024-NOSPLITSVE-NEXT: //NO_APP
@@ -5025,9 +5035,10 @@ define i32 @svecc_call_dynamic_and_scalable_alloca(<4 x i16> %P0, i32 %P1, i32 %
; CHECK1024-SPLITSVE-NEXT: .cfi_escape 0x10, 0x4f, 0x0c, 0x92, 0x2e, 0x00, 0x11, 0xb0, 0x7f, 0x1e, 0x22, 0x11, 0xc0, 0x77, 0x22 // $d15 @ cfa - 80 * VG - 1088
; CHECK1024-SPLITSVE-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK1024-SPLITSVE-NEXT: ubfiz x8, x0, #2, #32
+; CHECK1024-SPLITSVE-NEXT: mov x9, sp
; CHECK1024-SPLITSVE-NEXT: add x8, x8, #15
; CHECK1024-SPLITSVE-NEXT: and x8, x8, #0x7fffffff0
-; CHECK1024-SPLITSVE-NEXT: sub x20, sp, x8
+; CHECK1024-SPLITSVE-NEXT: sub x20, x9, x8
; CHECK1024-SPLITSVE-NEXT: mov sp, x20
; CHECK1024-SPLITSVE-NEXT: //APP
; CHECK1024-SPLITSVE-NEXT: //NO_APP
diff --git a/llvm/test/CodeGen/AArch64/stack-probing-dynamic.ll b/llvm/test/CodeGen/AArch64/stack-probing-dynamic.ll
index 108cb8476fc00..42a8e3b61cddc 100644
--- a/llvm/test/CodeGen/AArch64/stack-probing-dynamic.ll
+++ b/llvm/test/CodeGen/AArch64/stack-probing-dynamic.ll
@@ -17,21 +17,21 @@ define void @dynamic(i64 %size, ptr %out) #0 {
; CHECK-NEXT: .cfi_def_cfa w29, 16
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
-; CHECK-NEXT: add [[REG1:x[0-9]+]], x0, #15
-; CHECK-GI-NEXT: mov x8, sp
-; CHECK-NEXT: and [[REG1]], [[REG1]], #0xfffffffffffffff0
-; CHECK-NEXT: sub [[REG2:x[0-9]+]], {{(sp|x8)}}, [[REG1]]
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: .LBB0_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
-; CHECK-NEXT: cmp sp, [[REG2]]
+; CHECK-NEXT: cmp sp, x8
; CHECK-NEXT: b.le .LBB0_3
; CHECK-NEXT: // %bb.2: // in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB0_1
; CHECK-NEXT: .LBB0_3:
-; CHECK-NEXT: mov sp, [[REG2]]
+; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str [[REG2]], [x1]
+; CHECK-NEXT: str x8, [x1]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 16
; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
@@ -59,23 +59,24 @@ define void @dynamic_fixed(i64 %size, ptr %out1, ptr %out2) #0 {
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
; CHECK-NEXT: ldr xzr, [sp, #-64]!
-; CHECK-NEXT: add [[REG1:x[0-9]+]], x0, #15
-; CHECK-GI-NEXT: mov [[REG2:x[0-9]+]], sp
-; CHECK-DAG: sub [[REG3:x[0-9]+]], x29, #64
-; CHECK-DAG: and [[REG1]], [[REG1]], #0xfffffffffffffff0
-; CHECK-DAG: str [[REG3]], [x1]
-; CHECK-DAG: sub [[REG2]], {{(sp|x[0-9]+)}}, [[REG1]]
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
+; CHECK-DAG: sub x10, x29, #64
+; CHECK-DAG: and x9, x9, #0xfffffffffffffff0
+; CHECK-NOT: INVALID_TO_BREAK_UP_CHECK_DAG
+; CHECK-DAG: str x10, [x1]
+; CHECK-DAG: sub x8, x8, x9
; CHECK-NEXT: .LBB1_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
-; CHECK-NEXT: cmp sp, [[REG2]]
+; CHECK-NEXT: cmp sp, x8
; CHECK-NEXT: b.le .LBB1_3
; CHECK-NEXT: // %bb.2: // in Loop: Header=BB1_1 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB1_1
; CHECK-NEXT: .LBB1_3:
-; CHECK-NEXT: mov sp, [[REG2]]
+; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str [[REG2]], [x2]
+; CHECK-NEXT: str x8, [x2]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 16
; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
@@ -108,24 +109,25 @@ define void @dynamic_align_64(i64 %size, ptr %out) #0 {
; CHECK-NEXT: .cfi_offset w29, -32
; CHECK-NEXT: sub x9, sp, #32
; CHECK-NEXT: and sp, x9, #0xffffffffffffffc0
-; CHECK-NEXT: add [[REG1:x[0-9]+]], x0, #15
-; CHECK-GI-NEXT: mov [[REG2:x[0-9]+]], sp
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
; CHECK-DAG: ldr xzr, [sp]
-; CHECK-DAG: and [[REG1]], [[REG1]], #0xfffffffffffffff0
+; CHECK-DAG: and x9, x9, #0xfffffffffffffff0
+; CHECK-NOT: INVALID_TO_BREAK_UP_CHECK_DAG
; CHECK-DAG: mov x19, sp
-; CHECK-DAG: sub [[REG2]], {{(sp|x[0-9]+)}}, [[REG1]]
-; CHECK-NEXT: and [[REG2]], [[REG2]], #0xffffffffffffffc0
+; CHECK-DAG: sub x8, x8, x9
+; CHECK-NEXT: and x8, x8, #0xffffffffffffffc0
; CHECK-NEXT: .LBB2_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
-; CHECK-NEXT: cmp sp, [[REG2]]
+; CHECK-NEXT: cmp sp, x8
; CHECK-NEXT: b.le .LBB2_3
; CHECK-NEXT: // %bb.2: // in Loop: Header=BB2_1 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB2_1
; CHECK-NEXT: .LBB2_3:
-; CHECK-NEXT: mov sp, [[REG2]]
+; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str [[REG2]], [x1]
+; CHECK-NEXT: str x8, [x1]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 32
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
@@ -167,24 +169,25 @@ define void @dynamic_align_8192(i64 %size, ptr %out) #0 {
; CHECK-NEXT: b .LBB3_1
; CHECK-NEXT: .LBB3_3:
; CHECK-NEXT: mov sp, x9
-; CHECK-NEXT: add [[REG1:x[0-9]+]], x0, #15
-; CHECK-GI-NEXT: mov [[REG2:x[0-9]+]], sp
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
; CHECK-DAG: ldr xzr, [sp]
-; CHECK-DAG: and [[REG1]], [[REG1]], #0xfffffffffffffff0
+; CHECK-DAG: and x9, x9, #0xfffffffffffffff0
+; CHECK-NOT: INVALID_TO_BREAK_UP_CHECK_DAG
; CHECK-DAG: mov x19, sp
-; CHECK-DAG: sub [[REG2]], {{(sp|x[0-9]+)}}, [[REG1]]
-; CHECK-NEXT: and [[REG2]], [[REG2]], #0xffffffffffffe000
+; CHECK-DAG: sub x8, x8, x9
+; CHECK-NEXT: and x8, x8, #0xffffffffffffe000
; CHECK-NEXT: .LBB3_4: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
-; CHECK-NEXT: cmp sp, [[REG2]]
+; CHECK-NEXT: cmp sp, x8
; CHECK-NEXT: b.le .LBB3_6
; CHECK-NEXT: // %bb.5: // in Loop: Header=BB3_4 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB3_4
; CHECK-NEXT: .LBB3_6:
-; CHECK-NEXT: mov sp, [[REG2]]
+; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str [[REG2]], [x1]
+; CHECK-NEXT: str x8, [x1]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 32
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
@@ -210,21 +213,21 @@ define void @dynamic_64k_guard(i64 %size, ptr %out) #0 "stack-probe-size"="65536
; CHECK-NEXT: .cfi_def_cfa w29, 16
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
-; CHECK-NEXT: add [[REG1:x[0-9]+]], x0, #15
-; CHECK-GI-NEXT: mov [[REG2:x[0-9]+]], sp
-; CHECK-NEXT: and [[REG1]], [[REG1]], #0xfffffffffffffff0
-; CHECK-NEXT: sub [[REG3:x[0-9]+]], {{(sp|x[0-9]+)}}, [[REG1]]
+; CHECK-NEXT: add x9, x0, #15
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: .LBB4_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #16, lsl #12 // =65536
-; CHECK-NEXT: cmp sp, [[REG3]]
+; CHECK-NEXT: cmp sp, x8
; CHECK-NEXT: b.le .LBB4_3
; CHECK-NEXT: // %bb.2: // in Loop: Header=BB4_1 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB4_1
; CHECK-NEXT: .LBB4_3:
-; CHECK-NEXT: mov sp, [[REG3]]
+; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str [[REG3]], [x1]
+; CHECK-NEXT: str x8, [x1]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 16
; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
@@ -251,11 +254,11 @@ define void @no_reserved_call_frame(i64 %n) #0 {
; CHECK-NEXT: .cfi_def_cfa w29, 16
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
-; CHECK-NEXT: lsl [[REG1:x[0-9]+]], x0, #2
-; CHECK-GI-NEXT: mov x8, sp
-; CHECK-NEXT: add [[REG1]], [[REG1]], #15
-; CHECK-NEXT: and [[REG1]], [[REG1]], #0xfffffffffffffff0
-; CHECK-NEXT: sub x0, {{(sp|x8)}}, [[REG1]]
+; CHECK-NEXT: lsl x9, x0, #2
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: add x9, x9, #15
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x0, x8, x9
; CHECK-NEXT: .LBB5_1: // %entry
; CHECK-NEXT: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
@@ -331,22 +334,23 @@ define void @dynamic_sve(i64 %size, ptr %out) #0 "target-features"="+sve" {
; CHECK-NEXT: .cfi_offset w19, -16
; CHECK-NEXT: .cfi_offset w30, -24
; CHECK-NEXT: .cfi_offset w29, -32
-; CHECK-NEXT: rdvl [[REG1:x[0-9]+]], #1
-; CHECK-NEXT: mov [[REG2:x[0-9]+]], #15 // =0xf
-; CHECK-NEXT: madd [[REG1]], x0, [[REG1]], [[REG2]]
-; CHECK-NEXT: and [[REG1]], [[REG1]], #0xfffffffffffffff0
-; CHECK-NEXT: sub [[REG1]], sp, [[REG1]]
+; CHECK-NEXT: rdvl x9, #1
+; CHECK-NEXT: mov x10, #15 // =0xf
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: madd x9, x0, x9, x10
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: .LBB7_1: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: sub sp, sp, #1, lsl #12 // =4096
-; CHECK-NEXT: cmp sp, [[REG1]]
+; CHECK-NEXT: cmp sp, x8
; CHECK-NEXT: b.le .LBB7_3
; CHECK-NEXT: // %bb.2: // in Loop: Header=BB7_1 Depth=1
; CHECK-NEXT: ldr xzr, [sp]
; CHECK-NEXT: b .LBB7_1
; CHECK-NEXT: .LBB7_3:
-; CHECK-NEXT: mov sp, [[REG1]]
+; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: ldr xzr, [sp]
-; CHECK-NEXT: str [[REG1]], [x1]
+; CHECK-NEXT: str x8, [x1]
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: .cfi_def_cfa wsp, 32
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
diff --git a/llvm/test/CodeGen/AArch64/sve-alloca.ll b/llvm/test/CodeGen/AArch64/sve-alloca.ll
index 2624ba8fe55cd..324c35b340ed6 100644
--- a/llvm/test/CodeGen/AArch64/sve-alloca.ll
+++ b/llvm/test/CodeGen/AArch64/sve-alloca.ll
@@ -54,10 +54,11 @@ define void @foo(<vscale x 4 x i64> %dst, i1 %cond) {
; CHECK-NEXT: .cfi_escape 0x10, 0x4d, 0x0a, 0x92, 0x2e, 0x00, 0x11, 0x50, 0x1e, 0x22, 0x11, 0x60, 0x22 // $d13 @ cfa - 48 * VG - 32
; CHECK-NEXT: .cfi_escape 0x10, 0x4e, 0x0a, 0x92, 0x2e, 0x00, 0x11, 0x48, 0x1e, 0x22, 0x11, 0x60, 0x22 // $d14 @ cfa - 56 * VG - 32
; CHECK-NEXT: .cfi_escape 0x10, 0x4f, 0x0a, 0x92, 0x2e, 0x00, 0x11, 0x40, 0x1e, 0x22, 0x11, 0x60, 0x22 // $d15 @ cfa - 64 * VG - 32
-; CHECK-NEXT: rdvl x8, #2
-; CHECK-NEXT: add x8, x8, #15
-; CHECK-NEXT: and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: rdvl x9, #2
+; CHECK-NEXT: mov x8, sp
+; CHECK-NEXT: add x9, x9, #15
+; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: and x0, x8, #0xffffffffffffffe0
; CHECK-NEXT: mov sp, x0
; CHECK-NEXT: str z1, [x0, #1, mul vl]
diff --git a/llvm/test/CodeGen/AArch64/sve-stack-frame-layout.ll b/llvm/test/CodeGen/AArch64/sve-stack-frame-layout.ll
index 7c0cd22f75663..2cedcfec77826 100644
--- a/llvm/test/CodeGen/AArch64/sve-stack-frame-layout.ll
+++ b/llvm/test/CodeGen/AArch64/sve-stack-frame-layout.ll
@@ -168,10 +168,13 @@ define i32 @csr_d8_allocnxv4i32i32f64_vla(double %d, i32 %i) "aarch64_pstate_sm_
; CHECK-NEXT: .cfi_offset b8, -32
; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-NEXT: ubfiz x8, x0, #2, #32
+; CHECK-NEXT: mov x9, sp
; CHECK-NEXT: add x8, x8, #15
; CHECK-NEXT: and x8, x8, #0x7fffffff0
-; CHECK-NEXT: sub x8, sp, x8
-; CHECK-NEXT: mov sp, x8
+; CHECK-NEXT: sub x9, x9, x8
+; CHECK-NEXT: mov sp, x9
+; CHECK-NEXT: mov x10, sp
+; CHECK-NEXT: sub x8, x10, x8
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: mov z1.s, #0 // =0x0
; CHECK-NEXT: //APP
@@ -179,6 +182,7 @@ define i32 @csr_d8_allocnxv4i32i32f64_vla(double %d, i32 %i) "aarch64_pstate_sm_
; CHECK-NEXT: str wzr, [x8]
; CHECK-NEXT: sub x8, x29, #8
; CHECK-NEXT: mov w0, wzr
+; CHECK-NEXT: str wzr, [x9]
; CHECK-NEXT: str d0, [x19, #8]
; CHECK-NEXT: str z1, [x8, #-1, mul vl]
; CHECK-NEXT: sub sp, x29, #8
@@ -594,5 +598,3 @@ entry:
ret i32 %x
}
declare void @other()
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK-FRAMELAYOUT: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/win-alloca-no-stack-probe.ll b/llvm/test/CodeGen/AArch64/win-alloca-no-stack-probe.ll
index cd77ffaacb1c8..3d60944051e1e 100644
--- a/llvm/test/CodeGen/AArch64/win-alloca-no-stack-probe.ll
+++ b/llvm/test/CodeGen/AArch64/win-alloca-no-stack-probe.ll
@@ -11,6 +11,7 @@ declare void @func2(ptr)
; CHECK: add [[REG1:x[0-9]+]], x0, #15
; CHECK-NOT: bl __chkstk
+; CHECK: mov [[REG2:x[0-9]+]], sp
; CHECK: and [[REG1]], [[REG1]], #0xfffffffffffffff0
-; CHECK: sub [[REG3:x[0-9]+]], sp, [[REG1]]
+; CHECK: sub [[REG3:x[0-9]+]], [[REG2]], [[REG1]]
; CHECK: mov sp, [[REG3]]
diff --git a/llvm/test/CodeGen/AArch64/win-alloca.ll b/llvm/test/CodeGen/AArch64/win-alloca.ll
index b28555b616bb5..94c3d88458169 100644
--- a/llvm/test/CodeGen/AArch64/win-alloca.ll
+++ b/llvm/test/CodeGen/AArch64/win-alloca.ll
@@ -18,8 +18,7 @@ declare void @func2(ptr)
; CHECK: add [[REG1:x[0-9]+]], x0, #15
; CHECK-OPT: lsr x15, [[REG1]], #4
; CHECK: bl __chkstk
-; CHECK-OPT: lsl [[REG2:x[0-9]+]], x15, #4
-; CHECK-OPT: sub [[REG3:x[0-9]+]], sp, [[REG2]]
+; CHECK-OPT: sub [[REG3:x[0-9]+]], sp, x15, lsl #4
; CHECK-OPT: mov sp, [[REG3]]
; CHECK: bl func2
; CHECK-ARM64EC: bl "#__chkstk_arm64ec"
diff --git a/llvm/test/CodeGen/AArch64/win-sve.ll b/llvm/test/CodeGen/AArch64/win-sve.ll
index 4425fab765599..dea7781ba16e2 100644
--- a/llvm/test/CodeGen/AArch64/win-sve.ll
+++ b/llvm/test/CodeGen/AArch64/win-sve.ll
@@ -221,8 +221,7 @@ define void @f2(i64 %n, <vscale x 2 x i64> %x) {
; CHECK-NEXT: add x8, x8, #15
; CHECK-NEXT: lsr x15, x8, #4
; CHECK-NEXT: bl __chkstk
-; CHECK-NEXT: lsl x8, x15, #4
-; CHECK-NEXT: sub x1, sp, x8
+; CHECK-NEXT: sub x1, sp, x15, lsl #4
; CHECK-NEXT: mov sp, x1
; CHECK-NEXT: add x0, x19, #0
; CHECK-NEXT: bl g2
@@ -682,8 +681,7 @@ define void @f5(i64 %n, <vscale x 2 x i64> %x) {
; CHECK-NEXT: add x8, x8, #15
; CHECK-NEXT: lsr x15, x8, #4
; CHECK-NEXT: bl __chkstk
-; CHECK-NEXT: lsl x8, x15, #4
-; CHECK-NEXT: sub x2, sp, x8
+; CHECK-NEXT: sub x2, sp, x15, lsl #4
; CHECK-NEXT: mov sp, x2
; CHECK-NEXT: sub x1, x29, #16
; CHECK-NEXT: add x0, x19, #0
diff --git a/llvm/test/CodeGen/AArch64/win64_vararg.ll b/llvm/test/CodeGen/AArch64/win64_vararg.ll
index 47e6628b91304..0f4cb44a6f73b 100644
--- a/llvm/test/CodeGen/AArch64/win64_vararg.ll
+++ b/llvm/test/CodeGen/AArch64/win64_vararg.ll
@@ -190,8 +190,7 @@ define void @vla(i32, ptr, ...) local_unnamed_addr {
; CHECK-NEXT: stp x4, x5, [x29, #40]
; CHECK-NEXT: stp x6, x7, [x29, #56]
; CHECK-NEXT: bl __chkstk
-; CHECK-NEXT: lsl x8, x15, #4
-; CHECK-NEXT: sub x20, sp, x8
+; CHECK-NEXT: sub x20, sp, x15, lsl #4
; CHECK-NEXT: mov sp, x20
; CHECK-NEXT: ldr x21, [x29, #16]
; CHECK-NEXT: sxtw x22, w0
>From 9a77889d4c7c85de3153a68d6c38b2c19ee8fb3a Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Fri, 29 May 2026 17:56:46 +0800
Subject: [PATCH 10/11] Change to using fp to mix cookie
---
llvm/lib/Target/AArch64/AArch64FrameLowering.cpp | 10 ++++++++++
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 10 +++++-----
.../irtranslator-stack-protector-windows.ll | 16 +++++++++-------
.../CodeGen/AArch64/arm64ec-indirect-call.ll | 6 +++---
llvm/test/CodeGen/AArch64/mingw-refptr.ll | 16 +++++++++-------
.../CodeGen/AArch64/stack-protector-target.ll | 8 ++++----
6 files changed, 40 insertions(+), 26 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index 2c68e379205ce..42db4f0bd5d67 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -570,6 +570,16 @@ bool AArch64FrameLowering::hasFPImpl(const MachineFunction &MF) const {
// funclets.
if (MF.hasEHFunclets())
return true;
+
+ // Force FP for functions with stack guards on MSVCRT.
+ // The cookie mixing uses FP to ensure consistent addressing even with
+ // dynamic stack allocation (e.g., _alloca).
+ if (MFI.hasStackProtectorIndex()) {
+ const auto &Subtarget = MF.getSubtarget<AArch64Subtarget>();
+ if (Subtarget.getTargetTriple().isOSMSVCRT())
+ return true;
+ }
+
// Retain behavior of always omitting the FP for leaf functions when possible.
if (MF.getTarget().Options.DisableFramePointerElim(MF))
return true;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index b3a76db3064c5..9b572238ebd97 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -2466,13 +2466,13 @@ bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
DebugLoc DL = MI.getDebugLoc();
if (MI.getOpcode() == AArch64::STACK_GUARD_UNMIX) {
- // Expand STACK_GUARD_UNMIX to: sub Rd, sp, Rs
- // This computes SP - stored_mixed_value to unmix the cookie
+ // Expand STACK_GUARD_UNMIX to: sub Rd, fp, Rs
+ // This computes FP - stored_mixed_value to unmix the cookie
Register DstReg = MI.getOperand(0).getReg();
Register SrcReg = MI.getOperand(1).getReg();
BuildMI(MBB, MI, DL, get(AArch64::SUBXrx64), DstReg)
- .addReg(AArch64::SP)
+ .addReg(AArch64::FP)
.addReg(SrcReg)
.addImm(AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, 0));
@@ -2636,10 +2636,10 @@ bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
// To match MSVC. Unlike x86_64 which uses xor instruction to mix the cookie,
// we use sub instruction to mix the cookie on aarch64.
// The mixing happens here in expandPostRAPseudo (after RA) to ensure we use
- // the final stack pointer value.
+ // the final frame pointer value.
if (Subtarget.getTargetTriple().isOSMSVCRT())
BuildMI(MBB, MI, DL, get(AArch64::SUBXrx64), Reg)
- .addReg(AArch64::SP)
+ .addReg(AArch64::FP)
.addReg(Reg, RegState::Kill)
.addImm(AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, 0));
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
index 267b2110d1582..73e6c7958f994 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
@@ -9,32 +9,34 @@ define void @caller() sspreq {
; CHECK-NEXT: // %bb.0: // %entry
; CHECK-NEXT: sub sp, sp, #32
; CHECK-NEXT: .seh_stackalloc 32
-; CHECK-NEXT: str x30, [sp, #16] // 8-byte Spill
-; CHECK-NEXT: .seh_save_reg x30, 16
+; CHECK-NEXT: stp x29, x30, [sp, #16] // 16-byte Folded Spill
+; CHECK-NEXT: .seh_save_fplr 16
+; CHECK-NEXT: add x29, sp, #16
+; CHECK-NEXT: .seh_add_fp 16
; CHECK-NEXT: .seh_endprologue
; CHECK-NEXT: adrp x8, __security_cookie
; CHECK-NEXT: add x0, sp, #4
; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: sub x8, x29, x8, uxtx
; CHECK-NEXT: str x8, [sp, #8]
; CHECK-NEXT: bl callee
; CHECK-NEXT: ldr x8, [sp, #8]
; CHECK-NEXT: adrp x9, __security_cookie
; CHECK-NEXT: ldr x9, [x9, :lo12:__security_cookie]
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: sub x8, x29, x8, uxtx
; CHECK-NEXT: cmp x9, x8
; CHECK-NEXT: b.ne .LBB0_2
; CHECK-NEXT: // %bb.1: // %entry
; CHECK-NEXT: .seh_startepilogue
-; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Reload
-; CHECK-NEXT: .seh_save_reg x30, 16
+; CHECK-NEXT: ldp x29, x30, [sp, #16] // 16-byte Folded Reload
+; CHECK-NEXT: .seh_save_fplr 16
; CHECK-NEXT: add sp, sp, #32
; CHECK-NEXT: .seh_stackalloc 32
; CHECK-NEXT: .seh_endepilogue
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB0_2: // %entry
; CHECK-NEXT: ldr x8, [sp, #8]
-; CHECK-NEXT: sub x0, sp, x8
+; CHECK-NEXT: sub x0, x29, x8, uxtx
; CHECK-NEXT: bl __security_check_cookie
; CHECK-NEXT: brk #0x1
; CHECK-NEXT: .seh_endfunclet
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
index 9e5580d054935..64b0de62d4eda 100644
--- a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
+++ b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
@@ -32,14 +32,14 @@ define void @stackguard(ptr %g) sspreq {
; CHECK-NEXT: ldr x8, [sp, #8]
; CHECK-NEXT: adrp x10, __security_cookie
; CHECK-NEXT: ldr x10, [x10, :lo12:__security_cookie]
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: sub x8, x29, x8, uxtx
; CHECK-NEXT: cmp x10, x8
; CHECK-NEXT: b.ne .LBB1_2
; CHECK-NEXT: // %bb.1:
; CHECK-NEXT: fmov d0, #1.00000000
; CHECK-NEXT: .seh_startepilogue
-; CHECK-NEXT: ldr x30, [sp, #16]
-; CHECK-NEXT: .seh_save_reg x30, 16
+; CHECK-NEXT: ldp x29, x30, [sp, #16]
+; CHECK-NEXT: .seh_save_fplr 16
; CHECK-NEXT: add sp, sp, #32
; CHECK-NEXT: .seh_stackalloc 32
; CHECK-NEXT: .seh_endepilogue
diff --git a/llvm/test/CodeGen/AArch64/mingw-refptr.ll b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
index 5799c5f73cafe..07ed9b85c8f6d 100644
--- a/llvm/test/CodeGen/AArch64/mingw-refptr.ll
+++ b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
@@ -82,33 +82,35 @@ define dso_local void @sspFunc() #0 {
; CHECK-NEXT: // %bb.0: // %entry
; CHECK-NEXT: sub sp, sp, #32
; CHECK-NEXT: .seh_stackalloc 32
-; CHECK-NEXT: str x30, [sp, #16] // 8-byte Spill
-; CHECK-NEXT: .seh_save_reg x30, 16
+; CHECK-NEXT: stp x29, x30, [sp, #16] // 16-byte Folded Spill
+; CHECK-NEXT: .seh_save_fplr 16
+; CHECK-NEXT: add x29, sp, #16
+; CHECK-NEXT: .seh_add_fp 16
; CHECK-NEXT: .seh_endprologue
; CHECK-NEXT: adrp x8, .refptr.__stack_chk_guard
; CHECK-NEXT: add x0, sp, #7
; CHECK-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
; CHECK-NEXT: ldr x8, [x8]
-; CHECK-NEXT: sub x8, sp, x8
+; CHECK-NEXT: sub x8, x29, x8, uxtx
; CHECK-NEXT: str x8, [sp, #8]
; CHECK-NEXT: bl ptrUser
; CHECK-SD-NEXT: adrp x9, .refptr.__stack_chk_guard
; CHECK-SD-NEXT: ldr x8, [sp, #8]
; CHECK-SD-NEXT: ldr x9, [x9, :lo12:.refptr.__stack_chk_guard]
-; CHECK-SD-NEXT: sub x8, sp, x8
+; CHECK-SD-NEXT: sub x8, x29, x8, uxtx
; CHECK-SD-NEXT: ldr x9, [x9]
; CHECK-SD-NEXT: cmp x9, x8
; CHECK-GI-NEXT: adrp x8, .refptr.__stack_chk_guard
; CHECK-GI-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
; CHECK-GI-NEXT: ldr x9, [sp, #8]
; CHECK-GI-NEXT: ldr x8, [x8]
-; CHECK-GI-NEXT: sub x8, sp, x8
+; CHECK-GI-NEXT: sub x8, x29, x8, uxtx
; CHECK-GI-NEXT: cmp x8, x9
; CHECK-NEXT: b.ne .LBB6_2
; CHECK-NEXT: // %bb.1: // %entry
; CHECK-NEXT: .seh_startepilogue
-; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Reload
-; CHECK-NEXT: .seh_save_reg x30, 16
+; CHECK-NEXT: ldp x29, x30, [sp, #16] // 16-byte Folded Reload
+; CHECK-NEXT: .seh_save_fplr 16
; CHECK-NEXT: add sp, sp, #32
; CHECK-NEXT: .seh_stackalloc 32
; CHECK-NEXT: .seh_endepilogue
diff --git a/llvm/test/CodeGen/AArch64/stack-protector-target.ll b/llvm/test/CodeGen/AArch64/stack-protector-target.ll
index 64412de44bc5d..7871a54f82a2c 100644
--- a/llvm/test/CodeGen/AArch64/stack-protector-target.ll
+++ b/llvm/test/CodeGen/AArch64/stack-protector-target.ll
@@ -31,18 +31,18 @@ declare void @_Z7CapturePi(ptr)
; WINDOWS-AARCH64: adrp x8, __security_cookie
; WINDOWS-AARCH64: ldr x8, [x8, :lo12:__security_cookie]
-; WINDOWS-AARCH64: sub x8, sp, x8
+; WINDOWS-AARCH64: sub x8, x29, x8, uxtx
; WINDOWS-AARCH64: str x8, [sp, #8]
; WINDOWS-AARCH64: bl _Z7CapturePi
; WINDOWS-AARCH64: ldr x8, [sp, #8]
-; WINDOWS-AARCH64: sub x0, sp, x8
+; WINDOWS-AARCH64: sub x0, x29, x8, uxtx
; WINDOWS-AARCH64: bl __security_check_cookie
; WINDOWS-ARM64EC: adrp x8, __security_cookie
; WINDOWS-ARM64EC: ldr x8, [x8, :lo12:__security_cookie]
-; WINDOWS-ARM64EC: sub x8, sp, x8
+; WINDOWS-ARM64EC: sub x8, x29, x8, uxtx
; WINDOWS-ARM64EC: str x8, [sp, #8]
; WINDOWS-ARM64EC: bl "#_Z7CapturePi"
; WINDOWS-ARM64EC: ldr x8, [sp, #8]
-; WINDOWS-ARM64EC: sub x0, sp, x8
+; WINDOWS-ARM64EC: sub x0, x29, x8, uxtx
; WINDOWS-ARM64EC: bl "#__security_check_cookie_arm64ec"
>From e22349e610c26a8c1565292f5444ee6d55bc82de Mon Sep 17 00:00:00 2001
From: "Pan, Tao" <tao.pan at intel.com>
Date: Tue, 2 Jun 2026 09:04:39 +0800
Subject: [PATCH 11/11] Remove uxtx and redundant code
---
llvm/include/llvm/CodeGen/TargetLowering.h | 8 ++---
.../SelectionDAG/SelectionDAGBuilder.cpp | 22 ++++++------
llvm/lib/CodeGen/StackProtector.cpp | 2 +-
.../Target/AArch64/AArch64ISelDAGToDAG.cpp | 35 -------------------
.../Target/AArch64/AArch64ISelLowering.cpp | 30 ++++++----------
llvm/lib/Target/AArch64/AArch64ISelLowering.h | 7 ++--
.../lib/Target/AArch64/AArch64InstrFormats.td | 2 --
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 10 +++---
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 22 +-----------
llvm/lib/Target/X86/X86ISelLowering.cpp | 7 ++--
llvm/lib/Target/X86/X86ISelLowering.h | 7 ++--
.../irtranslator-stack-protector-windows.ll | 6 ++--
.../CodeGen/AArch64/arm64ec-indirect-call.ll | 2 +-
llvm/test/CodeGen/AArch64/mingw-refptr.ll | 21 +++++------
.../CodeGen/AArch64/stack-protector-target.ll | 8 ++---
15 files changed, 57 insertions(+), 132 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index ac719756084a7..f4206ac5d8fe1 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -2183,9 +2183,10 @@ class LLVM_ABI TargetLoweringBase {
const LibcallLoweringInfo &Libcalls) const;
/// If this function returns true, stack protection checks should mix the
+ /// frame pointer (or whichever pointer is used to address locals) into the
/// stack guard value before checking it. getIRStackGuard must return nullptr
/// if this returns true.
- virtual bool useStackGuardMixCookie() const { return false; }
+ virtual bool useStackGuardMixFP() const { return false; }
/// If the target has a standard stack protection check function that
/// performs validation and error handling, returns the function. Otherwise,
@@ -5966,9 +5967,8 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
/// LOAD_STACK_GUARD node when it is lowering Intrinsic::stackprotector.
virtual bool useLoadStackGuardNode(const Module &M) const { return false; }
- virtual SDValue emitStackGuardMixCookie(SelectionDAG &DAG, SDValue Val,
- const SDLoc &DL,
- bool FailureBB) const {
+ virtual SDValue emitStackGuardMixFP(SelectionDAG &DAG, SDValue Val,
+ const SDLoc &DL) const {
llvm_unreachable("not implemented for this target");
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 198c9ec9a8e61..1f5a6decd2b73 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3125,11 +3125,11 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
MachineMemOperand::MOVolatile);
// If cookie mixing is enabled, unmix the stored GuardVal to get back the
- // original cookie for comparison. The prologue stored (SP - Cookie) or
- // (SP XOR Cookie), so we apply the same operation again to unmix:
- // SP - (SP - Cookie) = Cookie, or (SP XOR Cookie) XOR SP = Cookie.
- if (TLI.useStackGuardMixCookie())
- GuardVal = TLI.emitStackGuardMixCookie(DAG, GuardVal, dl, false);
+ // original cookie for comparison. The prologue stored (FP - Cookie) or
+ // (FP XOR Cookie), so we apply the same operation again to unmix:
+ // FP - (FP - Cookie) = Cookie, or (FP XOR Cookie) XOR FP = Cookie.
+ if (TLI.useStackGuardMixFP())
+ GuardVal = TLI.emitStackGuardMixFP(DAG, GuardVal, dl);
// If we're using function-based instrumentation, call the guard check
// function
@@ -3167,7 +3167,7 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
// For targets that mix the cookie in LOAD_STACK_GUARD expansion, we need to
// load directly without using LOAD_STACK_GUARD to avoid unwanted mixing.
SDValue Chain = DAG.getEntryNode();
- if (TLI.useStackGuardMixCookie()) {
+ if (TLI.useStackGuardMixFP()) {
// Mixing targets: load cookie directly to avoid mixing in LOAD_STACK_GUARD
if (const Value *IRGuard = TLI.getSDagStackGuard(M, DAG.getLibcalls())) {
SDValue GuardPtr = getValue(IRGuard);
@@ -3256,8 +3256,8 @@ void SelectionDAGBuilder::visitSPDescriptorFailure(
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), Align,
MachineMemOperand::MOVolatile);
- if (TLI.useStackGuardMixCookie())
- GuardVal = TLI.emitStackGuardMixCookie(DAG, GuardVal, dl, true);
+ if (TLI.useStackGuardMixFP())
+ GuardVal = TLI.emitStackGuardMixFP(DAG, GuardVal, dl);
// The target provides a guard check function to validate the guard value.
// Generate a call to that function with the content of the guard slot as
@@ -7562,11 +7562,11 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
MachinePointerInfo(Global, 0), Align,
MachineMemOperand::MOVolatile);
}
- // Mix the cookie with SP/FP if enabled. Skip if using LOAD_STACK_GUARD
+ // Mix the cookie with FP if enabled. Skip if using LOAD_STACK_GUARD
// with post-RA mixing (AArch64 MSVCRT), as the mixing will be done during
// post-RA expansion of LOAD_STACK_GUARD.
- if (TLI.useStackGuardMixCookie() && !TLI.useLoadStackGuardNode(M))
- Res = TLI.emitStackGuardMixCookie(DAG, Res, sdl, false);
+ if (TLI.useStackGuardMixFP() && !TLI.useLoadStackGuardNode(M))
+ Res = TLI.emitStackGuardMixFP(DAG, Res, sdl);
DAG.setRoot(Chain);
setValue(&I, Res);
return;
diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp
index 5eb41841f6ab6..f8134c93e50b7 100644
--- a/llvm/lib/CodeGen/StackProtector.cpp
+++ b/llvm/lib/CodeGen/StackProtector.cpp
@@ -610,7 +610,7 @@ bool InsertStackProtectors(const TargetLowering &TLI,
// impossible to emit the check in IR, so the target *must* support stack
// protection in SDAG.
bool SupportsSelectionDAGSP =
- TLI.useStackGuardMixCookie() ||
+ TLI.useStackGuardMixFP() ||
(EnableSelectionDAGSP && !TLI.getTargetMachine().Options.EnableFastISel);
AllocaInst *AI = nullptr; // Place on stack that stores the stack guard.
BasicBlock *FailBB = nullptr;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 3af0f13f6377e..64ccf606b4ef7 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -75,8 +75,6 @@ class AArch64DAGToDAGISel : public SelectionDAGISel {
template <signed Low, signed High>
bool SelectRDSVLShiftImm(SDValue N, SDValue &Imm);
- bool SelectAddUXTXRegister(SDValue N, SDValue &Reg, SDValue &Shift);
-
bool SelectArithExtendedRegister(SDValue N, SDValue &Reg, SDValue &Shift);
bool SelectArithUXTXRegister(SDValue N, SDValue &Reg, SDValue &Shift);
bool SelectArithImmed(SDValue N, SDValue &Val, SDValue &Shift);
@@ -1085,19 +1083,6 @@ bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(SDValue N, SDValue &Imm) {
return false;
}
-/// SelectAddUXTXRegister - Select a "UXTX register" operand. This
-/// operand is referred by the instructions have SP operand
-bool AArch64DAGToDAGISel::SelectAddUXTXRegister(SDValue N, SDValue &Reg,
- SDValue &Shift) {
- // TODO: Relax condition to apply to more scenarios
- if (N.getOpcode() != ISD::LOAD)
- return false;
- Reg = N;
- Shift = CurDAG->getTargetConstant(getArithExtendImm(AArch64_AM::UXTX, 0),
- SDLoc(N), MVT::i32);
- return true;
-}
-
/// SelectArithExtendedRegister - Select a "extended register" operand. This
/// operand folds in an extend followed by an optional left shift.
bool AArch64DAGToDAGISel::SelectArithExtendedRegister(SDValue N, SDValue &Reg,
@@ -5061,26 +5046,6 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
return;
break;
- case ISD::SUB: {
- // Check for stack guard unmixing pattern: SUB(CopyFromReg(SP), LOAD(...))
- // Select STACK_GUARD_UNMIX pseudo which will be expanded post-RA
- // Only match when N1 is a LOAD (the stored guard value from stack).
- // Other patterns like shifts for dynamic allocation will use normal SUB.
- SDValue N0 = Node->getOperand(0);
- SDValue N1 = Node->getOperand(1);
- if (N0.getOpcode() == ISD::CopyFromReg && N1.getOpcode() == ISD::LOAD) {
- RegisterSDNode *R = dyn_cast<RegisterSDNode>(N0.getOperand(1));
- if (R && R->getReg() == AArch64::SP && VT == MVT::i64) {
- SDValue Ops[] = {N1};
- SDNode *ResNode = CurDAG->getMachineNode(AArch64::STACK_GUARD_UNMIX,
- SDLoc(Node), MVT::i64, Ops);
- ReplaceNode(Node, ResNode);
- return;
- }
- }
- break;
- }
-
case ISD::EXTRACT_SUBVECTOR: {
if (trySelectCastScalableToFixedLengthVector(Node))
return;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 14d22d8347087..68cefbdc02454 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -30718,28 +30718,20 @@ bool AArch64TargetLowering::useLoadStackGuardNode(const Module &M) const {
return true;
}
-bool AArch64TargetLowering::useStackGuardMixCookie() const {
- // MSVC CRTs mix the stack pointer into the stack guard value.
- // The prologue mixing is handled via post-RA expansion of LOAD_STACK_GUARD,
- // but the epilogue unmixing is done at the DAG level via
- // emitStackGuardMixCookie.
+bool AArch64TargetLowering::useStackGuardMixFP() const {
+ // Currently only MSVC CRTs mix the frame pointer into the stack guard value.
return Subtarget->getTargetTriple().isOSMSVCRT();
}
-SDValue AArch64TargetLowering::emitStackGuardMixCookie(SelectionDAG &DAG,
- SDValue Val,
- const SDLoc &DL,
- bool FailureBB) const {
- // Mix the cookie value with SP to create a position-dependent guard.
- // Both prologue (stores SP - Cookie) and epilogue (compares SP - Cookie)
- // use the same mixing operation.
- // For FailureBB=true: Val is the stored mixed value, compute SP - Val to
- // unmix For FailureBB=false: Val is the fresh cookie, compute SP - Val to mix
- return DAG.getNode(ISD::SUB, DL, Val.getValueType(),
- DAG.getCopyFromReg(DAG.getEntryNode(), DL,
- getStackPointerRegisterToSaveRestore(),
- MVT::i64),
- Val);
+SDValue AArch64TargetLowering::emitStackGuardMixFP(SelectionDAG &DAG,
+ SDValue Val,
+ const SDLoc &DL) const {
+ // Mix the cookie value with FP to create a position-dependent guard.
+ // Both prologue (stores FP - Cookie) and epilogue (compares FP - Cookie)
+ // use the same mixing operation: FP - Val.
+ return DAG.getNode(
+ ISD::SUB, DL, Val.getValueType(),
+ DAG.getCopyFromReg(DAG.getEntryNode(), DL, AArch64::FP, MVT::i64), Val);
}
unsigned AArch64TargetLowering::combineRepeatedFPDivisors() const {
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 6d9f15ee0ae29..7917b30b17d17 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -366,10 +366,9 @@ class AArch64TargetLowering : public TargetLowering {
}
bool useLoadStackGuardNode(const Module &M) const override;
- bool useStackGuardMixCookie() const override;
- SDValue emitStackGuardMixCookie(SelectionDAG &DAG, SDValue Val,
- const SDLoc &DL,
- bool FailureBB) const override;
+ bool useStackGuardMixFP() const override;
+ SDValue emitStackGuardMixFP(SelectionDAG &DAG, SDValue Val,
+ const SDLoc &DL) const override;
TargetLoweringBase::LegalizeTypeAction
getPreferredVectorAction(MVT VT) const override;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 1e891764ad861..04bcef5b7de29 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -1490,8 +1490,6 @@ def gi_arith_extended_reg32to64_i64 :
def arith_uxtx : ComplexPattern<i64, 2, "SelectArithUXTXRegister", []>;
-def add_uxtx : ComplexPattern<i64, 2, "SelectAddUXTXRegister", []>;
-
// Floating-point immediate.
def fpimm16XForm : SDNodeXForm<fpimm, [{
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 9b572238ebd97..cbbc6d1196679 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -2471,10 +2471,9 @@ bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
Register DstReg = MI.getOperand(0).getReg();
Register SrcReg = MI.getOperand(1).getReg();
- BuildMI(MBB, MI, DL, get(AArch64::SUBXrx64), DstReg)
+ BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), DstReg)
.addReg(AArch64::FP)
- .addReg(SrcReg)
- .addImm(AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, 0));
+ .addReg(SrcReg);
MBB.erase(MI);
return true;
@@ -2638,10 +2637,9 @@ bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
// The mixing happens here in expandPostRAPseudo (after RA) to ensure we use
// the final frame pointer value.
if (Subtarget.getTargetTriple().isOSMSVCRT())
- BuildMI(MBB, MI, DL, get(AArch64::SUBXrx64), Reg)
+ BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), Reg)
.addReg(AArch64::FP)
- .addReg(Reg, RegState::Kill)
- .addImm(AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, 0));
+ .addReg(Reg, RegState::Kill);
MBB.erase(MI);
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index aaf538cad850b..83a7b95c6bbf5 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2754,25 +2754,13 @@ def : InstAlias<"mov $dst, $src",
defm ADDS : AddSubS<0, "adds", AArch64add_flag, "cmn", "subs", "cmp">;
defm SUBS : AddSubS<1, "subs", AArch64sub_flag, "cmp", "adds", "cmn">;
-// Matches when SP is used directly via CopyFromReg, not after being moved to a GPR.
-// This ensures we don't incorrectly optimize "mov x8, sp; sub x8, x8, x9" into
-// "sub x8, sp, x9" - once SP is in x8, it's no longer a CopyFromReg node.
def copyFromSP: PatLeaf<(i64 GPR64:$src), [{
return N->getOpcode() == ISD::CopyFromReg &&
cast<RegisterSDNode>(N->getOperand(1))->getReg() == AArch64::SP;
}]>;
-// Helper to convert shift amount to UXTX extend with LSL (valid range 0-4)
-def UXTXLSLImm : SDNodeXForm<imm, [{
- uint64_t ShiftAmt = N->getZExtValue();
- assert(ShiftAmt <= 4 && "Invalid shift amount for UXTX");
- return CurDAG->getTargetConstant(
- AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, ShiftAmt),
- SDLoc(N), MVT::i32);
-}]>;
-
// Pseudo instruction for stack guard cookie unmixing (epilogue).
-// This will be expanded post-RA to use SP directly, avoiding an extra mov.
+// This will be expanded post-RA to use FP directly, avoiding an extra mov.
// Pattern matching for this will be done via custom C++ code during instruction selection.
def STACK_GUARD_UNMIX : Pseudo<(outs GPR64:$dst), (ins GPR64:$stored_val), []>,
Sched<[]>;
@@ -2797,9 +2785,6 @@ def : Pat<(sub GPR64sp:$R2, arith_extended_reg32to64_i64:$R3),
(SUBSXrx GPR64sp:$R2, arith_extended_reg32to64_i64:$R3)>;
def : Pat<(sub copyFromSP:$R2, (arith_uxtx GPR64:$R3, arith_extendlsl64:$imm)),
(SUBXrx64 GPR64sp:$R2, GPR64:$R3, arith_extendlsl64:$imm)>;
-// Handle SUB(copyFromSP, SHL) for dynamic stack allocation
-def : Pat<(sub copyFromSP:$sp, (shl GPR64:$val, (i64 imm:$shift))),
- (SUBXrx64 GPR64sp:$sp, GPR64:$val, (UXTXLSLImm (i64 imm:$shift)))>;
}
// Because of the immediate format for add/sub-imm instructions, the
@@ -2830,11 +2815,6 @@ def : Pat<(AArch64sub_flag GPR64:$Rn, neg_addsub_shifted_imm64:$imm),
(ADDSXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>;
}
-let AddedComplexity = 1 in {
-def : Pat<(add copyFromSP:$R2, (add_uxtx GPR64:$R3, arith_extendlsl64:$imm)),
- (ADDXrx64 GPR64sp:$R2, GPR64:$R3, arith_extendlsl64:$imm)>;
-}
-
def trunc_isWorthFoldingALU : PatFrag<(ops node:$src), (trunc $src)> {
let PredicateCode = [{ return isWorthFoldingALU(SDValue(N, 0)); }];
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index aa1b82577e6ab..f4555d3155650 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -2859,14 +2859,13 @@ bool X86TargetLowering::useLoadStackGuardNode(const Module &M) const {
return Subtarget.isTargetMachO() && Subtarget.is64Bit();
}
-bool X86TargetLowering::useStackGuardMixCookie() const {
+bool X86TargetLowering::useStackGuardMixFP() const {
// Currently only MSVC CRTs mix the frame pointer into the stack guard value.
return Subtarget.getTargetTriple().isOSMSVCRT() && !Subtarget.isTargetMachO();
}
-SDValue X86TargetLowering::emitStackGuardMixCookie(SelectionDAG &DAG,
- SDValue Val, const SDLoc &DL,
- bool FailureBB) const {
+SDValue X86TargetLowering::emitStackGuardMixFP(SelectionDAG &DAG, SDValue Val,
+ const SDLoc &DL) const {
EVT PtrTy = getPointerTy(DAG.getDataLayout());
unsigned XorOp = Subtarget.is64Bit() ? X86::XOR64_FP : X86::XOR32_FP;
MachineSDNode *Node = DAG.getMachineNode(XorOp, DL, PtrTy, Val);
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index b4faa395cd0ba..4e700f6a48db5 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -636,13 +636,12 @@ namespace llvm {
const LibcallLoweringInfo &Libcalls) const override;
bool useLoadStackGuardNode(const Module &M) const override;
- bool useStackGuardMixCookie() const override;
+ bool useStackGuardMixFP() const override;
void
insertSSPDeclarations(Module &M,
const LibcallLoweringInfo &Libcalls) const override;
- SDValue emitStackGuardMixCookie(SelectionDAG &DAG, SDValue Val,
- const SDLoc &DL,
- bool FailureBB) const override;
+ SDValue emitStackGuardMixFP(SelectionDAG &DAG, SDValue Val,
+ const SDLoc &DL) const override;
/// Return true if the target stores SafeStack pointer at a fixed offset in
/// some non-standard address space, and populates the address space and
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
index 73e6c7958f994..0be0fb5b9137e 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
@@ -17,13 +17,13 @@ define void @caller() sspreq {
; CHECK-NEXT: adrp x8, __security_cookie
; CHECK-NEXT: add x0, sp, #4
; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
-; CHECK-NEXT: sub x8, x29, x8, uxtx
+; CHECK-NEXT: sub x8, x29, x8
; CHECK-NEXT: str x8, [sp, #8]
; CHECK-NEXT: bl callee
; CHECK-NEXT: ldr x8, [sp, #8]
; CHECK-NEXT: adrp x9, __security_cookie
; CHECK-NEXT: ldr x9, [x9, :lo12:__security_cookie]
-; CHECK-NEXT: sub x8, x29, x8, uxtx
+; CHECK-NEXT: sub x8, x29, x8
; CHECK-NEXT: cmp x9, x8
; CHECK-NEXT: b.ne .LBB0_2
; CHECK-NEXT: // %bb.1: // %entry
@@ -36,7 +36,7 @@ define void @caller() sspreq {
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB0_2: // %entry
; CHECK-NEXT: ldr x8, [sp, #8]
-; CHECK-NEXT: sub x0, x29, x8, uxtx
+; CHECK-NEXT: sub x0, x29, x8
; CHECK-NEXT: bl __security_check_cookie
; CHECK-NEXT: brk #0x1
; CHECK-NEXT: .seh_endfunclet
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
index 64b0de62d4eda..dce77ca343511 100644
--- a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
+++ b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll
@@ -32,7 +32,7 @@ define void @stackguard(ptr %g) sspreq {
; CHECK-NEXT: ldr x8, [sp, #8]
; CHECK-NEXT: adrp x10, __security_cookie
; CHECK-NEXT: ldr x10, [x10, :lo12:__security_cookie]
-; CHECK-NEXT: sub x8, x29, x8, uxtx
+; CHECK-NEXT: sub x8, x29, x8
; CHECK-NEXT: cmp x10, x8
; CHECK-NEXT: b.ne .LBB1_2
; CHECK-NEXT: // %bb.1:
diff --git a/llvm/test/CodeGen/AArch64/mingw-refptr.ll b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
index 07ed9b85c8f6d..fe02b62cf6b93 100644
--- a/llvm/test/CodeGen/AArch64/mingw-refptr.ll
+++ b/llvm/test/CodeGen/AArch64/mingw-refptr.ll
@@ -91,21 +91,16 @@ define dso_local void @sspFunc() #0 {
; CHECK-NEXT: add x0, sp, #7
; CHECK-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
; CHECK-NEXT: ldr x8, [x8]
-; CHECK-NEXT: sub x8, x29, x8, uxtx
+; CHECK-NEXT: sub x8, x29, x8
; CHECK-NEXT: str x8, [sp, #8]
; CHECK-NEXT: bl ptrUser
-; CHECK-SD-NEXT: adrp x9, .refptr.__stack_chk_guard
-; CHECK-SD-NEXT: ldr x8, [sp, #8]
-; CHECK-SD-NEXT: ldr x9, [x9, :lo12:.refptr.__stack_chk_guard]
-; CHECK-SD-NEXT: sub x8, x29, x8, uxtx
-; CHECK-SD-NEXT: ldr x9, [x9]
-; CHECK-SD-NEXT: cmp x9, x8
-; CHECK-GI-NEXT: adrp x8, .refptr.__stack_chk_guard
-; CHECK-GI-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
-; CHECK-GI-NEXT: ldr x9, [sp, #8]
-; CHECK-GI-NEXT: ldr x8, [x8]
-; CHECK-GI-NEXT: sub x8, x29, x8, uxtx
-; CHECK-GI-NEXT: cmp x8, x9
+; CHECK-NEXT: adrp x8, .refptr.__stack_chk_guard
+; CHECK-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard]
+; CHECK-NEXT: ldr x9, [sp, #8]
+; CHECK-NEXT: ldr x8, [x8]
+; CHECK-SD-NEXT: sub x9, x29, x9
+; CHECK-GI-NEXT: sub x8, x29, x8
+; CHECK-NEXT: cmp x8, x9
; CHECK-NEXT: b.ne .LBB6_2
; CHECK-NEXT: // %bb.1: // %entry
; CHECK-NEXT: .seh_startepilogue
diff --git a/llvm/test/CodeGen/AArch64/stack-protector-target.ll b/llvm/test/CodeGen/AArch64/stack-protector-target.ll
index 7871a54f82a2c..1f20c526628be 100644
--- a/llvm/test/CodeGen/AArch64/stack-protector-target.ll
+++ b/llvm/test/CodeGen/AArch64/stack-protector-target.ll
@@ -31,18 +31,18 @@ declare void @_Z7CapturePi(ptr)
; WINDOWS-AARCH64: adrp x8, __security_cookie
; WINDOWS-AARCH64: ldr x8, [x8, :lo12:__security_cookie]
-; WINDOWS-AARCH64: sub x8, x29, x8, uxtx
+; WINDOWS-AARCH64: sub x8, x29, x8
; WINDOWS-AARCH64: str x8, [sp, #8]
; WINDOWS-AARCH64: bl _Z7CapturePi
; WINDOWS-AARCH64: ldr x8, [sp, #8]
-; WINDOWS-AARCH64: sub x0, x29, x8, uxtx
+; WINDOWS-AARCH64: sub x0, x29, x8
; WINDOWS-AARCH64: bl __security_check_cookie
; WINDOWS-ARM64EC: adrp x8, __security_cookie
; WINDOWS-ARM64EC: ldr x8, [x8, :lo12:__security_cookie]
-; WINDOWS-ARM64EC: sub x8, x29, x8, uxtx
+; WINDOWS-ARM64EC: sub x8, x29, x8
; WINDOWS-ARM64EC: str x8, [sp, #8]
; WINDOWS-ARM64EC: bl "#_Z7CapturePi"
; WINDOWS-ARM64EC: ldr x8, [sp, #8]
-; WINDOWS-ARM64EC: sub x0, x29, x8, uxtx
+; WINDOWS-ARM64EC: sub x0, x29, x8
; WINDOWS-ARM64EC: bl "#__security_check_cookie_arm64ec"
More information about the llvm-commits
mailing list