From 0146d206317e1d40775621639a4dde7c43e0f433 Mon Sep 17 00:00:00 2001 From: Amara Emerson Date: Thu, 21 Jan 2021 14:54:26 -0800 Subject: [PATCH] [AArch64] Do not fold SP adjustments into pre-increment addr modes if it overflows the redzone. Instead of outright disabling this completely with the noredzone attribute, we only avoid doing the optimization if there are memory operations between the adjustment and the load/store that the adjustment would be folded into. This avoids the case of something like a stack cookie being corrupted if an exception happens before the pre-increment to the SP occurs. This also prevents the folding happening if we have a redzone, but the offset being folded is above the redzone amount (128 bytes in this case). rdar://73269336 Differential Revision: https://reviews.llvm.org/D95179 --- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp | 8 +- llvm/lib/Target/AArch64/AArch64ISelLowering.h | 8 + .../Target/AArch64/AArch64LoadStoreOptimizer.cpp | 19 +- .../CodeGen/AArch64/ldst-nopreidx-sp-redzone.mir | 407 +++++++++++++++++++++ 4 files changed, 439 insertions(+), 3 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/ldst-nopreidx-sp-redzone.mir diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index acfd178..cf4152f 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -325,16 +325,20 @@ static StackOffset getSVEStackSize(const MachineFunction &MF) { bool AArch64FrameLowering::canUseRedZone(const MachineFunction &MF) const { if (!EnableRedZone) return false; + // Don't use the red zone if the function explicitly asks us not to. // This is typically used for kernel code. - if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone)) + const AArch64Subtarget &Subtarget = MF.getSubtarget(); + const unsigned RedZoneSize = + Subtarget.getTargetLowering()->getRedZoneSize(MF.getFunction()); + if (!RedZoneSize) return false; const MachineFrameInfo &MFI = MF.getFrameInfo(); const AArch64FunctionInfo *AFI = MF.getInfo(); uint64_t NumBytes = AFI->getLocalStackSize(); - return !(MFI.hasCalls() || hasFP(MF) || NumBytes > 128 || + return !(MFI.hasCalls() || hasFP(MF) || NumBytes > RedZoneSize || getSVEStackSize(MF)); } diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index 4959c8c..8360b76 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -16,6 +16,7 @@ #include "AArch64.h" #include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/IR/CallingConv.h" @@ -807,6 +808,13 @@ public: /// vector types this override can be removed. bool mergeStoresAfterLegalization(EVT VT) const override; + // If the platform/function should have a redzone, return the size in bytes. + unsigned getRedZoneSize(const Function &F) const { + if (F.hasFnAttribute(Attribute::NoRedZone)) + return 0; + return 128; + } + private: /// Keep a pointer to the AArch64Subtarget around so that we can /// make the right decision when generating code for different targets. diff --git a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp index ad180cb..c56f466 100644 --- a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp +++ b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "AArch64InstrInfo.h" +#include "AArch64MachineFunctionInfo.h" #include "AArch64Subtarget.h" #include "MCTargetDesc/AArch64AddressingModes.h" #include "llvm/ADT/BitVector.h" @@ -1849,6 +1850,7 @@ MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnBackward( MachineBasicBlock::iterator E = I->getParent()->end(); MachineInstr &MemMI = *I; MachineBasicBlock::iterator MBBI = I; + MachineFunction &MF = *MemMI.getMF(); Register BaseReg = getLdStBaseOp(MemMI).getReg(); int Offset = getLdStOffsetOp(MemMI).getImm(); @@ -1876,11 +1878,16 @@ MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnBackward( return E; } + const AArch64Subtarget &Subtarget = MF.getSubtarget(); + unsigned RedZoneSize = + Subtarget.getTargetLowering()->getRedZoneSize(MF.getFunction()); + // Track which register units have been modified and used between the first // insn (inclusive) and the second insn. ModifiedRegUnits.clear(); UsedRegUnits.clear(); unsigned Count = 0; + bool MemAcessBeforeSPPreInc = false; do { MBBI = prev_nodbg(MBBI, B); MachineInstr &MI = *MBBI; @@ -1891,8 +1898,13 @@ MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnBackward( ++Count; // If we found a match, return it. - if (isMatchingUpdateInsn(*I, MI, BaseReg, Offset)) + if (isMatchingUpdateInsn(*I, MI, BaseReg, Offset)) { + // Check that the update value is within our red zone limit (which may be + // zero). + if (MemAcessBeforeSPPreInc && MBBI->getOperand(2).getImm() > RedZoneSize) + return E; return MBBI; + } // Update the status of what the instruction clobbered and used. LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI); @@ -1902,6 +1914,11 @@ MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnBackward( if (!ModifiedRegUnits.available(BaseReg) || !UsedRegUnits.available(BaseReg)) return E; + // Keep track if we have a memory access before an SP pre-increment, in this + // case we need to validate later that the update amount respects the red + // zone. + if (BaseRegSP && MBBI->mayLoadOrStore()) + MemAcessBeforeSPPreInc = true; } while (MBBI != B && Count < Limit); return E; } diff --git a/llvm/test/CodeGen/AArch64/ldst-nopreidx-sp-redzone.mir b/llvm/test/CodeGen/AArch64/ldst-nopreidx-sp-redzone.mir new file mode 100644 index 0000000..8c66937 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ldst-nopreidx-sp-redzone.mir @@ -0,0 +1,407 @@ +# RUN: llc -mtriple=aarch64-apple-darwin -run-pass=aarch64-ldst-opt -verify-machineinstrs -o - %s | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "arm64e-apple-ios13.0" + + %struct.widget = type { i64, i64, i32, i32, i64, i64, i64, i64, i64, i32, i32, i32, i16, i32, %struct.snork*, %struct.zot, %struct.zot, %struct.zot, %struct.zot, %struct.zot, i64, i64, i64, i32, i64, i32, i32, i32, i8*, %struct.baz, %struct.baz, i64, i64, %struct.snork*, %struct.zot, i32, i32, i32, i32, i32, i32, i32, [32 x i8], i64, i64, %struct.wombat, i32, i64, i64, i64, i64 } + %struct.baz = type { [4 x i32] } + %struct.snork = type { i32, i32, [1 x %struct.spam] } + %struct.spam = type { %struct.baz, i32, i32 } + %struct.zot = type { i64, i64 } + %struct.wombat = type { [2 x i32] } + %struct.wombat.0 = type { [200 x i32] } + + @__stack_chk_guard = external global i8* + + ; Function Attrs: noredzone ssp + define hidden void @with_noredzone_80bytes() #0 { + bb: + %StackGuardSlot = alloca i8*, align 8 + %0 = call i8* @llvm.stackguard() + call void @llvm.stackprotector(i8* %0, i8** %StackGuardSlot) + %tmp = alloca %struct.widget, align 16 + %tmp1 = alloca %struct.wombat.0*, align 8 + %tmp2 = alloca %struct.wombat.0*, align 8 + %tmp3 = alloca %struct.wombat.0*, align 8 + %tmp4 = alloca %struct.wombat.0*, align 8 + store %struct.wombat.0* null, %struct.wombat.0** %tmp3, align 8 + store %struct.wombat.0* null, %struct.wombat.0** %tmp4, align 8 + ret void + } + + define hidden void @with_redzone_480bytes() #2 { + bb: + %StackGuardSlot = alloca i8*, align 8 + %0 = call i8* @llvm.stackguard() + call void @llvm.stackprotector(i8* %0, i8** %StackGuardSlot) + %tmp = alloca %struct.widget, align 16 + %tmp1 = alloca %struct.wombat.0*, align 8 + %tmp2 = alloca %struct.wombat.0*, align 8 + %tmp3 = alloca %struct.wombat.0*, align 8 + %tmp4 = alloca %struct.wombat.0*, align 8 + store %struct.wombat.0* null, %struct.wombat.0** %tmp3, align 8 + store %struct.wombat.0* null, %struct.wombat.0** %tmp4, align 8 + ret void + } + + define hidden void @with_noredzone_no_mem_between() #0 { + bb: + %StackGuardSlot = alloca i8*, align 8 + %0 = call i8* @llvm.stackguard() + call void @llvm.stackprotector(i8* %0, i8** %StackGuardSlot) + %tmp = alloca %struct.widget, align 16 + %tmp1 = alloca %struct.wombat.0*, align 8 + %tmp2 = alloca %struct.wombat.0*, align 8 + %tmp3 = alloca %struct.wombat.0*, align 8 + %tmp4 = alloca %struct.wombat.0*, align 8 + store %struct.wombat.0* null, %struct.wombat.0** %tmp3, align 8 + store %struct.wombat.0* null, %struct.wombat.0** %tmp4, align 8 + ret void + } + + ; Function Attrs: nofree nosync nounwind willreturn + declare i8* @llvm.stackguard() #1 + + ; Function Attrs: nofree nosync nounwind willreturn + declare void @llvm.stackprotector(i8*, i8**) #1 + + attributes #0 = { noredzone ssp "frame-pointer"="non-leaf" } + attributes #1 = { nofree nosync nounwind willreturn } + attributes #2 = { ssp "frame-pointer"="non-leaf" } +... +# Check that we don't try to combine the SUB with the STP using pre-index addressing +# if the function does not have redzone enabled. +# CHECK-LABEL: name: with_noredzone_80bytes +# CHECK-NOT: STPXpre $xzr, $xzr +--- +name: with_noredzone_80bytes +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: [] +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 512 + offsetAdjustment: 0 + maxAlignment: 16 + adjustsStack: true + hasCalls: true + stackProtector: '%stack.0.StackGuardSlot' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 480 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: StackGuardSlot, type: default, offset: -40, size: 8, + alignment: 8, stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -8, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 1, name: tmp, type: default, offset: -480, size: 440, alignment: 16, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -448, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 2, name: tmp1, type: default, offset: -488, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -456, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 3, name: tmp2, type: default, offset: -496, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -464, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 4, name: tmp3, type: default, offset: -504, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -472, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 5, name: tmp4, type: default, offset: -512, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -480, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 6, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 7, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$fp', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 8, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$x27', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 9, name: '', type: spill-slot, offset: -32, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$x28', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + hasRedZone: false +body: | + bb.0.bb: + successors: %bb.1(0x7ffff800), %bb.2(0x00000800) + liveins: $x27, $x28, $lr + early-clobber $sp = frame-setup STPXpre killed $x28, killed $x27, $sp, -4 :: (store 8 into %stack.9), (store 8 into %stack.8) + frame-setup STPXi killed $fp, killed $lr, $sp, 2 :: (store 8 into %stack.7), (store 8 into %stack.6) + $fp = frame-setup ADDXri $sp, 16, 0 + $sp = frame-setup SUBXri $sp, 80, 0 + frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + frame-setup CFI_INSTRUCTION offset $w30, -8 + frame-setup CFI_INSTRUCTION offset $w29, -16 + frame-setup CFI_INSTRUCTION offset $w27, -24 + frame-setup CFI_INSTRUCTION offset $w28, -32 + $x8 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard + $x8 = LDRXui killed $x8, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @__stack_chk_guard + $x8 = LDRXui killed $x8, 0 :: (dereferenceable invariant load 8 from @__stack_chk_guard) + STURXi killed renamable $x8, $fp, -24 :: (volatile store 8 into %stack.0.StackGuardSlot) + STRXui $xzr, $sp, 1 :: (store 8 into %ir.tmp3) + STRXui $xzr, $sp, 0 :: (store 8 into %ir.tmp4) + renamable $x8 = LDURXi $fp, -24 :: (volatile load 8 from %stack.0.StackGuardSlot) + $x9 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard + $x9 = LDRXui killed $x9, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @__stack_chk_guard + $x9 = LDRXui killed $x9, 0 :: (dereferenceable invariant load 8 from @__stack_chk_guard) + $xzr = SUBSXrs killed renamable $x9, killed renamable $x8, 0, implicit-def $nzcv, implicit-def $nzcv + Bcc 1, %bb.2, implicit $nzcv + + bb.1.bb: + $sp = frame-destroy ADDXri $sp, 480, 0 + $fp, $lr = frame-destroy LDPXi $sp, 2 :: (load 8 from %stack.7), (load 8 from %stack.6) + early-clobber $sp, $x28, $x27 = frame-destroy LDPXpost $sp, 4 :: (load 8 from %stack.9), (load 8 from %stack.8) + RET undef $lr + + bb.2.bb: + BL &__stack_chk_fail, csr_darwin_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp + +... +# Check we don't try to fold a 480 byte offset, even if we have a 128 byte redzone. +# CHECK-LABEL: name: with_redzone_480bytes +# CHECK-NOT: STPXpre $xzr, $xzr +--- +name: with_redzone_480bytes +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: [] +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 512 + offsetAdjustment: 0 + maxAlignment: 16 + adjustsStack: true + hasCalls: true + stackProtector: '%stack.0.StackGuardSlot' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 480 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: StackGuardSlot, type: default, offset: -40, size: 8, + alignment: 8, stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -8, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 1, name: tmp, type: default, offset: -480, size: 440, alignment: 16, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -448, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 2, name: tmp1, type: default, offset: -488, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -456, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 3, name: tmp2, type: default, offset: -496, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -464, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 4, name: tmp3, type: default, offset: -504, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -472, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 5, name: tmp4, type: default, offset: -512, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -480, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 6, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 7, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$fp', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 8, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$x27', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 9, name: '', type: spill-slot, offset: -32, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$x28', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +callSites: [] +debugValueSubstitutions: [] +constants: [] +body: | + bb.0.bb: + successors: %bb.1(0x7ffff800), %bb.2(0x00000800) + liveins: $x27, $x28, $lr + early-clobber $sp = frame-setup STPXpre killed $x28, killed $x27, $sp, -4 :: (store 8 into %stack.9), (store 8 into %stack.8) + frame-setup STPXi killed $fp, killed $lr, $sp, 2 :: (store 8 into %stack.7), (store 8 into %stack.6) + $fp = frame-setup ADDXri $sp, 16, 0 + $sp = frame-setup SUBXri $sp, 480, 0 + frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + frame-setup CFI_INSTRUCTION offset $w30, -8 + frame-setup CFI_INSTRUCTION offset $w29, -16 + frame-setup CFI_INSTRUCTION offset $w27, -24 + frame-setup CFI_INSTRUCTION offset $w28, -32 + $x8 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard + $x8 = LDRXui killed $x8, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @__stack_chk_guard + $x8 = LDRXui killed $x8, 0 :: (dereferenceable invariant load 8 from @__stack_chk_guard) + STURXi killed renamable $x8, $fp, -24 :: (volatile store 8 into %stack.0.StackGuardSlot) + STRXui $xzr, $sp, 1 :: (store 8 into %ir.tmp3) + STRXui $xzr, $sp, 0 :: (store 8 into %ir.tmp4) + renamable $x8 = LDURXi $fp, -24 :: (volatile load 8 from %stack.0.StackGuardSlot) + $x9 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard + $x9 = LDRXui killed $x9, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @__stack_chk_guard + $x9 = LDRXui killed $x9, 0 :: (dereferenceable invariant load 8 from @__stack_chk_guard) + $xzr = SUBSXrs killed renamable $x9, killed renamable $x8, 0, implicit-def $nzcv, implicit-def $nzcv + Bcc 1, %bb.2, implicit $nzcv + + bb.1.bb: + $sp = frame-destroy ADDXri $sp, 480, 0 + $fp, $lr = frame-destroy LDPXi $sp, 2 :: (load 8 from %stack.7), (load 8 from %stack.6) + early-clobber $sp, $x28, $x27 = frame-destroy LDPXpost $sp, 4 :: (load 8 from %stack.9), (load 8 from %stack.8) + RET undef $lr + + bb.2.bb: + BL &__stack_chk_fail, csr_darwin_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp + +... +# Check we still do the opt if there are no mem ops between. +# CHECK-LABEL: name: with_noredzone_no_mem_between +# CHECK: STPXpre $xzr, $xzr +--- +name: with_noredzone_no_mem_between +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: [] +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 512 + offsetAdjustment: 0 + maxAlignment: 16 + adjustsStack: true + hasCalls: true + stackProtector: '%stack.0.StackGuardSlot' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 480 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: StackGuardSlot, type: default, offset: -40, size: 8, + alignment: 8, stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -8, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 1, name: tmp, type: default, offset: -480, size: 440, alignment: 16, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -448, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 2, name: tmp1, type: default, offset: -488, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -456, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 3, name: tmp2, type: default, offset: -496, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -464, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 4, name: tmp3, type: default, offset: -504, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -472, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 5, name: tmp4, type: default, offset: -512, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -480, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 6, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 7, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$fp', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 8, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$x27', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 9, name: '', type: spill-slot, offset: -32, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$x28', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + hasRedZone: false +body: | + bb.0.bb: + successors: %bb.1(0x7ffff800), %bb.2(0x00000800) + liveins: $x27, $x28, $lr + early-clobber $sp = frame-setup STPXpre killed $x28, killed $x27, $sp, -4 :: (store 8 into %stack.9), (store 8 into %stack.8) + frame-setup STPXi killed $fp, killed $lr, $sp, 2 :: (store 8 into %stack.7), (store 8 into %stack.6) + $fp = frame-setup ADDXri $sp, 16, 0 + $sp = frame-setup SUBXri $sp, 480, 0 + frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + frame-setup CFI_INSTRUCTION offset $w30, -8 + frame-setup CFI_INSTRUCTION offset $w29, -16 + frame-setup CFI_INSTRUCTION offset $w27, -24 + frame-setup CFI_INSTRUCTION offset $w28, -32 + $x8 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard + STRXui $xzr, $sp, 1 :: (store 8 into %ir.tmp3) + STRXui $xzr, $sp, 0 :: (store 8 into %ir.tmp4) + renamable $x8 = LDURXi $fp, -24 :: (volatile load 8 from %stack.0.StackGuardSlot) + $x9 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard + $x9 = LDRXui killed $x9, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @__stack_chk_guard + $x9 = LDRXui killed $x9, 0 :: (dereferenceable invariant load 8 from @__stack_chk_guard) + $xzr = SUBSXrs killed renamable $x9, killed renamable $x8, 0, implicit-def $nzcv, implicit-def $nzcv + Bcc 1, %bb.2, implicit $nzcv + + bb.1.bb: + $sp = frame-destroy ADDXri $sp, 480, 0 + $fp, $lr = frame-destroy LDPXi $sp, 2 :: (load 8 from %stack.7), (load 8 from %stack.6) + early-clobber $sp, $x28, $x27 = frame-destroy LDPXpost $sp, 4 :: (load 8 from %stack.9), (load 8 from %stack.8) + RET undef $lr + + bb.2.bb: + BL &__stack_chk_fail, csr_darwin_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp + +... -- 2.7.4