Skip to content

Commit 96d150b

Browse files
mstorsjotru
authored andcommitted
[AArch64] [GlobalISel] Fix clobbered callee saved registers with win64 varargs
This fixes a regression since 1c10d5b / https://reviews.llvm.org/D130903 by applying the same fix from SelectionDAG from 8cb3667 / https://reviews.llvm.org/D35720. This could possibly have been detected if the existing testcases in win64_vararg.ll had been tested with GlobalISel too, but all the IR snippets there fail to be translated with GlobalISel. This adds a separate testcase based on real world LLVM IR (instead of hand-reduced IR), which GlobalISel does translate happily - tested with both SelectionDAG and GlobalISel. Before this change, the stack object locations (visible in MIR with "llc -print-after-all") didn't match with what the prologue emitted by AArch64FrameLowering actually looked like, which caused clobbered callee saved registers when function local stack objects aliased the actual location of the callee saved registers. This fixes llvm#64740. Differential Revision: https://reviews.llvm.org/D158272 (cherry picked from commit 955d761)
1 parent 6a82343 commit 96d150b

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,11 @@ void AArch64CallLowering::saveVarArgRegisters(
564564
if (IsWin64CC) {
565565
GPRIdx = MFI.CreateFixedObject(GPRSaveSize,
566566
-static_cast<int>(GPRSaveSize), false);
567+
if (GPRSaveSize & 15)
568+
// The extra size here, if triggered, will always be 8.
569+
MFI.CreateFixedObject(16 - (GPRSaveSize & 15),
570+
-static_cast<int>(alignTo(GPRSaveSize, 16)),
571+
false);
567572
} else
568573
GPRIdx = MFI.CreateStackObject(GPRSaveSize, Align(8), false);
569574

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -mtriple=aarch64-pc-win32 | FileCheck %s
3+
; RUN: llc < %s -global-isel -mtriple=aarch64-pc-win32 | FileCheck %s --check-prefix=GISEL
4+
5+
; Function Attrs: mustprogress noinline nounwind optnone uwtable
6+
define i1 @va_func(i32 %a, i8 %b, i8 %c, ...) {
7+
; CHECK-LABEL: va_func:
8+
; CHECK: .seh_proc va_func
9+
; CHECK-NEXT: // %bb.0:
10+
; CHECK-NEXT: sub sp, sp, #80
11+
; CHECK-NEXT: .seh_stackalloc 80
12+
; CHECK-NEXT: str x19, [sp, #16] // 8-byte Folded Spill
13+
; CHECK-NEXT: .seh_save_reg x19, 16
14+
; CHECK-NEXT: str x30, [sp, #24] // 8-byte Folded Spill
15+
; CHECK-NEXT: .seh_save_reg x30, 24
16+
; CHECK-NEXT: .seh_endprologue
17+
; CHECK-NEXT: mov w19, w0
18+
; CHECK-NEXT: stp x3, x4, [sp, #40]
19+
; CHECK-NEXT: stp x5, x6, [sp, #56]
20+
; CHECK-NEXT: str x7, [sp, #72]
21+
; CHECK-NEXT: str w0, [sp, #12]
22+
; CHECK-NEXT: strb w1, [sp, #11]
23+
; CHECK-NEXT: strb w2, [sp, #10]
24+
; CHECK-NEXT: bl other
25+
; CHECK-NEXT: cmp w19, w0
26+
; CHECK-NEXT: cset w0, ls
27+
; CHECK-NEXT: .seh_startepilogue
28+
; CHECK-NEXT: ldr x30, [sp, #24] // 8-byte Folded Reload
29+
; CHECK-NEXT: .seh_save_reg x30, 24
30+
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Folded Reload
31+
; CHECK-NEXT: .seh_save_reg x19, 16
32+
; CHECK-NEXT: add sp, sp, #80
33+
; CHECK-NEXT: .seh_stackalloc 80
34+
; CHECK-NEXT: .seh_endepilogue
35+
; CHECK-NEXT: ret
36+
; CHECK-NEXT: .seh_endfunclet
37+
; CHECK-NEXT: .seh_endproc
38+
;
39+
; GISEL-LABEL: va_func:
40+
; GISEL: .seh_proc va_func
41+
; GISEL-NEXT: // %bb.0:
42+
; GISEL-NEXT: sub sp, sp, #80
43+
; GISEL-NEXT: .seh_stackalloc 80
44+
; GISEL-NEXT: str x19, [sp, #16] // 8-byte Folded Spill
45+
; GISEL-NEXT: .seh_save_reg x19, 16
46+
; GISEL-NEXT: str x30, [sp, #24] // 8-byte Folded Spill
47+
; GISEL-NEXT: .seh_save_reg x30, 24
48+
; GISEL-NEXT: .seh_endprologue
49+
; GISEL-NEXT: stp x3, x4, [sp, #40]
50+
; GISEL-NEXT: mov w19, w0
51+
; GISEL-NEXT: stp x5, x6, [sp, #56]
52+
; GISEL-NEXT: str w0, [sp, #12]
53+
; GISEL-NEXT: str x7, [sp, #72]
54+
; GISEL-NEXT: strb w1, [sp, #11]
55+
; GISEL-NEXT: strb w2, [sp, #10]
56+
; GISEL-NEXT: bl other
57+
; GISEL-NEXT: cmp w19, w0
58+
; GISEL-NEXT: cset w0, ls
59+
; GISEL-NEXT: .seh_startepilogue
60+
; GISEL-NEXT: ldr x30, [sp, #24] // 8-byte Folded Reload
61+
; GISEL-NEXT: .seh_save_reg x30, 24
62+
; GISEL-NEXT: ldr x19, [sp, #16] // 8-byte Folded Reload
63+
; GISEL-NEXT: .seh_save_reg x19, 16
64+
; GISEL-NEXT: add sp, sp, #80
65+
; GISEL-NEXT: .seh_stackalloc 80
66+
; GISEL-NEXT: .seh_endepilogue
67+
; GISEL-NEXT: ret
68+
; GISEL-NEXT: .seh_endfunclet
69+
; GISEL-NEXT: .seh_endproc
70+
%a_alloc = alloca i32, align 4
71+
%b_alloc = alloca i8, align 1
72+
%c_alloc = alloca i8, align 1
73+
store i32 %a, ptr %a_alloc, align 4
74+
store i8 %b, ptr %b_alloc, align 1
75+
store i8 %c, ptr %c_alloc, align 1
76+
%a_load = load i32, ptr %a_alloc, align 4
77+
%ret = call noundef i32 @other()
78+
%cmp = icmp ule i32 %a_load, %ret
79+
ret i1 %cmp
80+
}
81+
82+
declare i32 @other()

0 commit comments

Comments
 (0)