[llvm] 33b9634 - [ARM] v6-M XO: save CPSR around LoadStackGuard
Simon Wallis via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 9 00:41:05 PDT 2023
Author: Simon Wallis
Date: 2023-08-09T08:40:35+01:00
New Revision: 33b9634394de673fce8a60281979df8328687a81
URL: https://github.com/llvm/llvm-project/commit/33b9634394de673fce8a60281979df8328687a81
DIFF: https://github.com/llvm/llvm-project/commit/33b9634394de673fce8a60281979df8328687a81.diff
LOG: [ARM] v6-M XO: save CPSR around LoadStackGuard
For Thumb-1 Execute-Only, expandLoadStackGuardBase generates a tMOVimm32 pseudo when calculating the stack offset.
It does this in a context where the CSPR maybe be live. tMOVimm32 may corrupt CPSR.
To fix this, generate save/restore CPSR around the tMOVimm32 using MRS/MSR to/from a scratch register.
expandLoadStackGuardBase this runs after register allocation, so the scratch register needs to be a physical register.
Use R12 as a scratch register, as is usual when expanding a pseudo.
MSR/MRS are some of the few v6-M instructions which operate on a high register.
New stack-guard test case added which was generating incorrect code without the save/restore CPSR.
Reviewed By: stuij
Differential Revision: https://reviews.llvm.org/D156968
Added:
Modified:
llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
llvm/test/CodeGen/Thumb/stack-guard-xo.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
index e07687a88a222b..d85698e031376f 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -4982,8 +4982,24 @@ void ARMBaseInstrInfo::expandLoadStackGuardBase(MachineBasicBlock::iterator MI,
TargetFlags |= ARMII::MO_GOT;
}
- BuildMI(MBB, MI, DL, get(LoadImmOpc), Reg)
- .addGlobalAddress(GV, 0, TargetFlags);
+ if (LoadImmOpc == ARM::tMOVi32imm) { // Thumb-1 execute-only
+ MachineFunction &MF = *MBB.getParent();
+ Register CPSRSaveReg = ARM::R12; // Use R12 as scratch register
+ auto APSREncoding =
+ ARMSysReg::lookupMClassSysRegByName("apsr_nzcvq")->Encoding;
+ BuildMI(MBB, MI, DL, get(ARM::t2MRS_M), CPSRSaveReg)
+ .addImm(APSREncoding)
+ .add(predOps(ARMCC::AL));
+ BuildMI(MBB, MI, DL, get(LoadImmOpc), Reg)
+ .addGlobalAddress(GV, 0, TargetFlags);
+ BuildMI(MBB, MI, DL, get(ARM::t2MSR_M))
+ .addImm(APSREncoding)
+ .addReg(CPSRSaveReg, RegState::Kill)
+ .add(predOps(ARMCC::AL));
+ } else {
+ BuildMI(MBB, MI, DL, get(LoadImmOpc), Reg)
+ .addGlobalAddress(GV, 0, TargetFlags);
+ }
if (IsIndirect) {
MIB = BuildMI(MBB, MI, DL, get(LoadOpc), Reg);
diff --git a/llvm/test/CodeGen/Thumb/stack-guard-xo.ll b/llvm/test/CodeGen/Thumb/stack-guard-xo.ll
index 1c2b5bf7145e7f..c344e4f7fc022d 100644
--- a/llvm/test/CodeGen/Thumb/stack-guard-xo.ll
+++ b/llvm/test/CodeGen/Thumb/stack-guard-xo.ll
@@ -33,9 +33,10 @@ define dso_local i32 @main() #0 {
; V6M-LABEL: main:
; V6M: @ %bb.0: @ %entry
; V6M-NEXT: push {r7, lr}
-; V6M-NEXT: sub sp, #24
+; V6M-NEXT: sub sp, #
; V6M-NEXT: movs r0, #0
-; V6M-NEXT: str r0, [sp, #4]
+; V6M-NEXT: str r0, [sp, #
+; V6M-NEXT: mrs r12, apsr
; V6M-NEXT: movs r0, :upper8_15:__stack_chk_guard
; V6M-NEXT: lsls r0, r0, #8
; V6M-NEXT: adds r0, :upper0_7:__stack_chk_guard
@@ -43,11 +44,13 @@ define dso_local i32 @main() #0 {
; V6M-NEXT: adds r0, :lower8_15:__stack_chk_guard
; V6M-NEXT: lsls r0, r0, #8
; V6M-NEXT: adds r0, :lower0_7:__stack_chk_guard
+; V6M-NEXT: msr apsr, r12
; V6M-NEXT: ldr r0, [r0]
-; V6M-NEXT: str r0, [sp, #20]
-; V6M-NEXT: add r0, sp, #8
+; V6M-NEXT: str r0, [sp, #
+; V6M-NEXT: add r0, sp, #
; V6M-NEXT: ldrb r0, [r0]
-; V6M-NEXT: ldr r1, [sp, #20]
+; V6M-NEXT: ldr r1, [sp, #
+; V6M-NEXT: mrs r12, apsr
; V6M-NEXT: movs r2, :upper8_15:__stack_chk_guard
; V6M-NEXT: lsls r2, r2, #8
; V6M-NEXT: adds r2, :upper0_7:__stack_chk_guard
@@ -55,11 +58,12 @@ define dso_local i32 @main() #0 {
; V6M-NEXT: adds r2, :lower8_15:__stack_chk_guard
; V6M-NEXT: lsls r2, r2, #8
; V6M-NEXT: adds r2, :lower0_7:__stack_chk_guard
+; V6M-NEXT: msr apsr, r12
; V6M-NEXT: ldr r2, [r2]
; V6M-NEXT: cmp r2, r1
; V6M-NEXT: bne .LBB0_2
; V6M-NEXT: @ %bb.1: @ %entry
-; V6M-NEXT: add sp, #24
+; V6M-NEXT: add sp, #
; V6M-NEXT: pop {r7, pc}
; V6M-NEXT: .LBB0_2: @ %entry
; V6M-NEXT: bl __stack_chk_fail
@@ -97,4 +101,94 @@ entry:
ret i32 %conv
}
+ at aa = hidden local_unnamed_addr global i32 0, align 4
+ at bb = hidden local_unnamed_addr global i64 0, align 8
+
+define dso_local i64 @cc() local_unnamed_addr #1 {
+; V6M-LABEL: cc:
+; V6M: @ %bb.0: @ %entry
+; V6M-NEXT: push {r4, r5, r7, lr}
+; V6M-NEXT: sub sp, #8
+; V6M-NEXT: movs r0, #1
+; V6M-NEXT: lsls r3, r0, #31
+; V6M-NEXT: movs r0, :upper8_15:aa
+; V6M-NEXT: lsls r0, r0, #8
+; V6M-NEXT: adds r0, :upper0_7:aa
+; V6M-NEXT: lsls r0, r0, #8
+; V6M-NEXT: adds r0, :lower8_15:aa
+; V6M-NEXT: lsls r0, r0, #8
+; V6M-NEXT: adds r0, :lower0_7:aa
+; V6M-NEXT: ldr r2, [r0]
+; V6M-NEXT: asrs r4, r2, #31
+; V6M-NEXT: eors r3, r4
+; V6M-NEXT: movs r0, :upper8_15:bb
+; V6M-NEXT: lsls r0, r0, #8
+; V6M-NEXT: adds r0, :upper0_7:bb
+; V6M-NEXT: lsls r0, r0, #8
+; V6M-NEXT: adds r0, :lower8_15:bb
+; V6M-NEXT: lsls r0, r0, #8
+; V6M-NEXT: adds r0, :lower0_7:bb
+; V6M-NEXT: ldm r0!, {r1, r5}
+; V6M-NEXT: subs r0, r2, r1
+; V6M-NEXT: sbcs r3, r5
+; V6M-NEXT: subs r0, r2, r1
+; V6M-NEXT: mrs r12, apsr
+; V6M-NEXT: movs r1, :upper8_15:__stack_chk_guard
+; V6M-NEXT: lsls r1, r1, #8
+; V6M-NEXT: adds r1, :upper0_7:__stack_chk_guard
+; V6M-NEXT: lsls r1, r1, #8
+; V6M-NEXT: adds r1, :lower8_15:__stack_chk_guard
+; V6M-NEXT: lsls r1, r1, #8
+; V6M-NEXT: adds r1, :lower0_7:__stack_chk_guard
+; V6M-NEXT: msr apsr, r12
+; V6M-NEXT: ldr r1, [r1]
+; V6M-NEXT: str r1, [sp, #4]
+; V6M-NEXT: mov r1, r4
+; V6M-NEXT: sbcs r1, r5
+; V6M-NEXT: ands r3, r4
+; V6M-NEXT: ands r2, r0
+; V6M-NEXT: mov r4, r2
+; V6M-NEXT: orrs r4, r3
+; V6M-NEXT: beq .LBB1_2
+; V6M-NEXT: @ %bb.1: @ %entry
+; V6M-NEXT: mov r1, r3
+; V6M-NEXT: .LBB1_2: @ %entry
+; V6M-NEXT: cmp r4, #0
+; V6M-NEXT: beq .LBB1_4
+; V6M-NEXT: @ %bb.3: @ %entry
+; V6M-NEXT: mov r0, r2
+; V6M-NEXT: .LBB1_4: @ %entry
+; V6M-NEXT: ldr r2, [sp, #4]
+; V6M-NEXT: mrs r12, apsr
+; V6M-NEXT: movs r3, :upper8_15:__stack_chk_guard
+; V6M-NEXT: lsls r3, r3, #8
+; V6M-NEXT: adds r3, :upper0_7:__stack_chk_guard
+; V6M-NEXT: lsls r3, r3, #8
+; V6M-NEXT: adds r3, :lower8_15:__stack_chk_guard
+; V6M-NEXT: lsls r3, r3, #8
+; V6M-NEXT: adds r3, :lower0_7:__stack_chk_guard
+; V6M-NEXT: msr apsr, r12
+; V6M-NEXT: ldr r3, [r3]
+; V6M-NEXT: cmp r3, r2
+; V6M-NEXT: bne .LBB1_6
+; V6M-NEXT: @ %bb.5: @ %entry
+; V6M-NEXT: add sp, #8
+; V6M-NEXT: pop {r4, r5, r7, pc}
+; V6M-NEXT: .LBB1_6: @ %entry
+; V6M-NEXT: bl __stack_chk_fail
+
+entry:
+ %0 = load i32, ptr @aa, align 4
+ %conv = sext i32 %0 to i64
+ %xor = xor i64 %conv, -9223372036854775808
+ %1 = load i64, ptr @bb, align 8
+ %sub = sub nsw i64 %xor, %1
+ %and = and i64 %sub, %conv
+ %tobool.not = icmp eq i64 %and, 0
+ %sub3 = sub nsw i64 %conv, %1
+ %spec.select = select i1 %tobool.not, i64 %sub3, i64 %and
+ ret i64 %spec.select
+}
+
attributes #0 = { ssp "stack-protector-buffer-size"="8" }
+attributes #1 = { sspreq }
More information about the llvm-commits
mailing list