[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