Skip to content

Commit ffb598e

Browse files
authored
Merge pull request #11751 from compnerd/wos-preservation
AArch64: correct `preserve_most` and `preserve_all` on Windows (llvm#166436)
2 parents 7c51e5d + dcc82b5 commit ffb598e

File tree

8 files changed

+119
-25
lines changed

8 files changed

+119
-25
lines changed

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3406,6 +3406,22 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
34063406
TS->emitARM64WinCFIPACSignLR();
34073407
return;
34083408

3409+
case AArch64::SEH_SaveAnyRegI:
3410+
assert(MI->getOperand(1).getImm() <= 1008 &&
3411+
"SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3412+
TS->emitARM64WinCFISaveAnyRegI(MI->getOperand(0).getImm(),
3413+
MI->getOperand(1).getImm());
3414+
return;
3415+
3416+
case AArch64::SEH_SaveAnyRegIP:
3417+
assert(MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1 &&
3418+
"Non-consecutive registers not allowed for save_any_reg");
3419+
assert(MI->getOperand(2).getImm() <= 1008 &&
3420+
"SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3421+
TS->emitARM64WinCFISaveAnyRegIP(MI->getOperand(0).getImm(),
3422+
MI->getOperand(2).getImm());
3423+
return;
3424+
34093425
case AArch64::SEH_SaveAnyRegQP:
34103426
assert(MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1 &&
34113427
"Non-consecutive registers not allowed for save_any_reg");

llvm/lib/Target/AArch64/AArch64CallingConvention.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,12 @@ def CSR_Win_AArch64_AAPCS_SwiftError
610610
def CSR_Win_AArch64_AAPCS_SwiftTail
611611
: CalleeSavedRegs<(sub CSR_Win_AArch64_AAPCS, X20, X22)>;
612612

613+
def CSR_Win_AArch64_RT_MostRegs
614+
: CalleeSavedRegs<(add CSR_Win_AArch64_AAPCS, (sequence "X%u", 9, 15))>;
615+
616+
def CSR_Win_AArch64_RT_AllRegs
617+
: CalleeSavedRegs<(add CSR_Win_AArch64_RT_MostRegs, (sequence "Q%u", 8, 31))>;
618+
613619
// The Control Flow Guard check call uses a custom calling convention that also
614620
// preserves X0-X8 and Q0-Q7.
615621
def CSR_Win_AArch64_CFGuard_Check : CalleeSavedRegs<(add CSR_Win_AArch64_AAPCS,

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,25 +1407,41 @@ static MachineBasicBlock::iterator InsertSEH(MachineBasicBlock::iterator MBBI,
14071407
case AArch64::LDPXi: {
14081408
Register Reg0 = MBBI->getOperand(0).getReg();
14091409
Register Reg1 = MBBI->getOperand(1).getReg();
1410+
1411+
int SEHReg0 = RegInfo->getSEHRegNum(Reg0);
1412+
int SEHReg1 = RegInfo->getSEHRegNum(Reg1);
1413+
14101414
if (Reg0 == AArch64::FP && Reg1 == AArch64::LR)
14111415
MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFPLR))
14121416
.addImm(Imm * 8)
14131417
.setMIFlag(Flag);
1414-
else
1418+
else if (SEHReg0 >= 19 && SEHReg1 >= 19)
14151419
MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveRegP))
1416-
.addImm(RegInfo->getSEHRegNum(Reg0))
1417-
.addImm(RegInfo->getSEHRegNum(Reg1))
1420+
.addImm(SEHReg0)
1421+
.addImm(SEHReg1)
1422+
.addImm(Imm * 8)
1423+
.setMIFlag(Flag);
1424+
else
1425+
MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveAnyRegIP))
1426+
.addImm(SEHReg0)
1427+
.addImm(SEHReg1)
14181428
.addImm(Imm * 8)
14191429
.setMIFlag(Flag);
14201430
break;
14211431
}
14221432
case AArch64::STRXui:
14231433
case AArch64::LDRXui: {
14241434
int Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());
1425-
MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveReg))
1426-
.addImm(Reg)
1427-
.addImm(Imm * 8)
1428-
.setMIFlag(Flag);
1435+
if (Reg >= 19)
1436+
MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveReg))
1437+
.addImm(Reg)
1438+
.addImm(Imm * 8)
1439+
.setMIFlag(Flag);
1440+
else
1441+
MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveAnyRegI))
1442+
.addImm(Reg)
1443+
.addImm(Imm * 8)
1444+
.setMIFlag(Flag);
14291445
break;
14301446
}
14311447
case AArch64::STRDui:
@@ -1479,6 +1495,8 @@ static void fixupSEHOpcode(MachineBasicBlock::iterator MBBI,
14791495
case AArch64::SEH_SaveReg:
14801496
case AArch64::SEH_SaveFRegP:
14811497
case AArch64::SEH_SaveFReg:
1498+
case AArch64::SEH_SaveAnyRegI:
1499+
case AArch64::SEH_SaveAnyRegIP:
14821500
case AArch64::SEH_SaveAnyRegQP:
14831501
case AArch64::SEH_SaveAnyRegQPX:
14841502
ImmOpnd = &MBBI->getOperand(ImmIdx);

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,8 @@ bool AArch64InstrInfo::isSEHInstruction(const MachineInstr &MI) {
11741174
case AArch64::SEH_EpilogStart:
11751175
case AArch64::SEH_EpilogEnd:
11761176
case AArch64::SEH_PACSignLR:
1177+
case AArch64::SEH_SaveAnyRegI:
1178+
case AArch64::SEH_SaveAnyRegIP:
11771179
case AArch64::SEH_SaveAnyRegQP:
11781180
case AArch64::SEH_SaveAnyRegQPX:
11791181
case AArch64::SEH_AllocZ:

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5634,6 +5634,8 @@ let isPseudo = 1 in {
56345634
def SEH_EpilogStart : Pseudo<(outs), (ins), []>, Sched<[]>;
56355635
def SEH_EpilogEnd : Pseudo<(outs), (ins), []>, Sched<[]>;
56365636
def SEH_PACSignLR : Pseudo<(outs), (ins), []>, Sched<[]>;
5637+
def SEH_SaveAnyRegI : Pseudo<(outs), (ins i32imm:$reg0, i32imm:$offs), []>, Sched<[]>;
5638+
def SEH_SaveAnyRegIP : Pseudo<(outs), (ins i32imm:$reg0, i32imm:$reg1, i32imm:$offs), []>, Sched<[]>;
56375639
def SEH_SaveAnyRegQP : Pseudo<(outs), (ins i32imm:$reg0, i32imm:$reg1, i32imm:$offs), []>, Sched<[]>;
56385640
def SEH_SaveAnyRegQPX : Pseudo<(outs), (ins i32imm:$reg0, i32imm:$reg1, i32imm:$offs), []>, Sched<[]>;
56395641
def SEH_AllocZ : Pseudo<(outs), (ins i32imm:$offs), []>, Sched<[]>;

llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
8989
if (MF->getSubtarget<AArch64Subtarget>().isTargetDarwin())
9090
return getDarwinCalleeSavedRegs(MF);
9191

92+
if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost)
93+
return MF->getSubtarget<AArch64Subtarget>().isTargetWindows()
94+
? CSR_Win_AArch64_RT_MostRegs_SaveList
95+
: CSR_AArch64_RT_MostRegs_SaveList;
96+
97+
if (MF->getFunction().getCallingConv() == CallingConv::PreserveAll)
98+
return MF->getSubtarget<AArch64Subtarget>().isTargetWindows()
99+
? CSR_Win_AArch64_RT_AllRegs_SaveList
100+
: CSR_AArch64_RT_AllRegs_SaveList;
101+
92102
if (MF->getFunction().getCallingConv() == CallingConv::CFGuard_Check)
93103
return CSR_Win_AArch64_CFGuard_Check_SaveList;
94104
if (MF->getSubtarget<AArch64Subtarget>().isTargetWindows()) {
@@ -140,10 +150,6 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
140150
return CSR_AArch64_AAPCS_SwiftError_SaveList;
141151
if (MF->getFunction().getCallingConv() == CallingConv::SwiftTail)
142152
return CSR_AArch64_AAPCS_SwiftTail_SaveList;
143-
if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost)
144-
return CSR_AArch64_RT_MostRegs_SaveList;
145-
if (MF->getFunction().getCallingConv() == CallingConv::PreserveAll)
146-
return CSR_AArch64_RT_AllRegs_SaveList;
147153
if (MF->getFunction().getCallingConv() == CallingConv::Win64)
148154
// This is for OSes other than Windows; Windows is a separate case further
149155
// above.

llvm/test/CodeGen/AArch64/preserve_mostcc.ll

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
; RUN: llc < %s -mtriple=arm64-apple-ios-8.0.0 | FileCheck %s
1+
; RUN: llc < %s -mtriple=arm64-apple-ios-8.0.0 | FileCheck -check-prefix CHECK -check-prefix CHECK-DARWIN %s
2+
; RUN: llc < %s -mtriple=aarch64-unknown-windows-msvc | FileCheck -check-prefix CHECK -check-prefix CHECK-WIN %s
23

34
declare void @standard_cc_func()
45
declare preserve_mostcc void @preserve_mostcc_func()
@@ -8,18 +9,26 @@ declare preserve_mostcc void @preserve_mostcc_func()
89
define preserve_mostcc void @preserve_mostcc1() nounwind {
910
entry:
1011
;CHECK-LABEL: preserve_mostcc1
11-
;CHECK-NOT: stp
12-
;CHECK-NOT: str
13-
;CHECK: str x15
14-
;CHECK-NEXT: stp x14, x13,
15-
;CHECK-NEXT: stp x12, x11,
16-
;CHECK-NEXT: stp x10, x9,
17-
;CHECK: bl _standard_cc_func
12+
;CHECK-DARWIN-NOT: stp
13+
;CHECK-DARWIN-NOT: str
14+
;CHECK-DARWIN: str x15
15+
;CHECK-DARWIN-NEXT: stp x14, x13,
16+
;CHECK-DARWIN-NEXT: stp x12, x11,
17+
;CHECK-DARWIN-NEXT: stp x10, x9,
18+
;CHECK-WIN: stp x15, x14
19+
;CHECK-WIN-NEXT: stp x13, x12,
20+
;CHECK-WIN-NEXT: stp x11, x10,
21+
;CHECK-WIN-NEXT: stp x9, x30
22+
;CHECK: bl {{_?}}standard_cc_func
1823
call void @standard_cc_func()
19-
;CHECK: ldp x10, x9,
20-
;CHECK-NEXT: ldp x12, x11,
21-
;CHECK-NEXT: ldp x14, x13,
22-
;CHECK-NEXT: ldr x15
24+
;CHECK-DARWIN: ldp x10, x9,
25+
;CHECK-DARWIN-NEXT: ldp x12, x11,
26+
;CHECK-DARWIN-NEXT: ldp x14, x13,
27+
;CHECK-DARWIN-NEXT: ldr x15
28+
;CHECK-WIN: ldp x9, x30
29+
;CHECK-WIN-NEXT: ldp x11, x10,
30+
;CHECK-WIN-NEXT: ldp x13, x12,
31+
;CHECK-WIN-NEXT: ldp x15, x14,
2332
ret void
2433
}
2534

@@ -31,9 +40,10 @@ define preserve_mostcc void @preserve_mostcc2() nounwind {
3140
entry:
3241
;CHECK-LABEL: preserve_mostcc2
3342
;CHECK-NOT: x14
34-
;CHECK: stp x29, x30,
43+
;CHECK-DARWIN: stp x29, x30,
44+
;CHECK-WIN: str x30
3545
;CHECK-NOT: x14
36-
;CHECK: bl _preserve_mostcc_func
46+
;CHECK: bl {{_?}}preserve_mostcc_func
3747
call preserve_mostcc void @preserve_mostcc_func()
3848
ret void
3949
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; RUN: llc -mtriple aarch64-unknown-windows-msvc -filetype asm -o - %s | FileCheck %s
2+
3+
declare dso_local void @g(ptr noundef)
4+
define dso_local preserve_mostcc void @f(ptr noundef %p) #0 {
5+
entry:
6+
%p.addr = alloca ptr, align 8
7+
store ptr %p, ptr %p.addr, align 8
8+
%0 = load ptr, ptr %p.addr, align 8
9+
call void @g(ptr noundef %0)
10+
ret void
11+
}
12+
13+
attributes #0 = { nounwind uwtable(sync) }
14+
15+
; CHECK: stp x9, x10, [sp, #[[OFFSET_0:[0-9]+]]]
16+
; CHECK-NEXT: .seh_save_any_reg_p x9, [[OFFSET_0]]
17+
; CHECK: stp x11, x12, [sp, #[[OFFSET_1:[0-9]+]]]
18+
; CHECK-NEXT: .seh_save_any_reg_p x11, [[OFFSET_1]]
19+
; CHECK: stp x13, x14, [sp, #[[OFFSET_2:[0-9]+]]]
20+
; CHECK-NEXT: .seh_save_any_reg_p x13, [[OFFSET_2]]
21+
; CHECK: str x15, [sp, #[[OFFSET_3:[0-9]+]]]
22+
; CHECK-NEXT: .seh_save_any_reg x15, [[OFFSET_3]]
23+
; CHECK: .seh_endprologue
24+
25+
; CHECK: .seh_startepilogue
26+
; CHECK: ldr x15, [sp, #[[OFFSET_3]]]
27+
; CHECK-NEXT: .seh_save_any_reg x15, [[OFFSET_3]]
28+
; CHECK: ldp x13, x14, [sp, #[[OFFSET_2]]]
29+
; CHECK-NEXT: .seh_save_any_reg_p x13, [[OFFSET_2]]
30+
; CHECK: ldp x11, x12, [sp, #[[OFFSET_1]]]
31+
; CHECK-NEXT: .seh_save_any_reg_p x11, [[OFFSET_1]]
32+
; CHECK: ldp x9, x10, [sp, #[[OFFSET_0]]]
33+
; CHECK-NEXT: .seh_save_any_reg_p x9, [[OFFSET_0]]
34+
; CHECK: .seh_endepilogue

0 commit comments

Comments
 (0)