[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
Tue May 12 18:46:02 PDT 2026


https://github.com/PanTao2 created https://github.com/llvm/llvm-project/pull/197346

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.


>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] [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"



More information about the llvm-commits mailing list