-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Aarch64] [ISel] Don't save vaargs registers if vaargs are unused #126780
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,40 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | ||
; RUN: llc < %s -mtriple=aarch64-pc-win32 | FileCheck %s | ||
; RUN: llc < %s -global-isel -mtriple=aarch64-pc-win32 | FileCheck %s --check-prefix=GISEL | ||
; RUN: llc < %s -global-isel -mtriple=aarch64-pc-win32 -global-isel-abort=0 | FileCheck %s --check-prefix=GISEL | ||
|
||
%struct.__va_list = type { ptr, ptr, ptr, i32, i32 } | ||
|
||
; Function Attrs: mustprogress noinline nounwind optnone uwtable | ||
define i1 @va_func(i32 %a, i8 %b, i8 %c, ...) { | ||
; CHECK-LABEL: va_func: | ||
; CHECK: .seh_proc va_func | ||
; CHECK-NEXT: // %bb.0: | ||
; CHECK-NEXT: sub sp, sp, #80 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is another test which is trying to check vararg behaviour, so should have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So looks like GISel does not support vastart for win calling convention bool AArch64InstructionSelector::selectVaStartAAPCS(
MachineInstr &I, MachineFunction &MF, MachineRegisterInfo &MRI) const {
if (STI.isCallingConvWin64(MF.getFunction().getCallingConv(),
MF.getFunction().isVarArg()))
return false; |
||
; CHECK-NEXT: .seh_stackalloc 80 | ||
; CHECK-NEXT: str x19, [sp, #16] // 8-byte Folded Spill | ||
; CHECK-NEXT: .seh_save_reg x19, 16 | ||
; CHECK-NEXT: str x30, [sp, #24] // 8-byte Folded Spill | ||
; CHECK-NEXT: .seh_save_reg x30, 24 | ||
; CHECK-NEXT: sub sp, sp, #112 | ||
; CHECK-NEXT: .seh_stackalloc 112 | ||
; CHECK-NEXT: str x19, [sp, #48] // 8-byte Folded Spill | ||
; CHECK-NEXT: .seh_save_reg x19, 48 | ||
; CHECK-NEXT: str x30, [sp, #56] // 8-byte Folded Spill | ||
; CHECK-NEXT: .seh_save_reg x30, 56 | ||
; CHECK-NEXT: .seh_endprologue | ||
; CHECK-NEXT: add x8, sp, #72 | ||
; CHECK-NEXT: mov w19, w0 | ||
; CHECK-NEXT: stp x3, x4, [sp, #40] | ||
; CHECK-NEXT: stp x5, x6, [sp, #56] | ||
; CHECK-NEXT: str x7, [sp, #72] | ||
; CHECK-NEXT: stp x3, x4, [sp, #72] | ||
; CHECK-NEXT: stp x5, x6, [sp, #88] | ||
; CHECK-NEXT: str x7, [sp, #104] | ||
; CHECK-NEXT: str x8, [sp, #16] | ||
; CHECK-NEXT: str w0, [sp, #12] | ||
; CHECK-NEXT: strb w1, [sp, #11] | ||
; CHECK-NEXT: strb w2, [sp, #10] | ||
; CHECK-NEXT: bl other | ||
; CHECK-NEXT: cmp w19, w0 | ||
; CHECK-NEXT: cset w0, ls | ||
; CHECK-NEXT: .seh_startepilogue | ||
; CHECK-NEXT: ldr x30, [sp, #24] // 8-byte Folded Reload | ||
; CHECK-NEXT: .seh_save_reg x30, 24 | ||
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Folded Reload | ||
; CHECK-NEXT: .seh_save_reg x19, 16 | ||
; CHECK-NEXT: add sp, sp, #80 | ||
; CHECK-NEXT: .seh_stackalloc 80 | ||
; CHECK-NEXT: ldr x30, [sp, #56] // 8-byte Folded Reload | ||
; CHECK-NEXT: .seh_save_reg x30, 56 | ||
; CHECK-NEXT: ldr x19, [sp, #48] // 8-byte Folded Reload | ||
; CHECK-NEXT: .seh_save_reg x19, 48 | ||
; CHECK-NEXT: add sp, sp, #112 | ||
; CHECK-NEXT: .seh_stackalloc 112 | ||
; CHECK-NEXT: .seh_endepilogue | ||
; CHECK-NEXT: ret | ||
; CHECK-NEXT: .seh_endfunclet | ||
|
@@ -39,34 +43,38 @@ define i1 @va_func(i32 %a, i8 %b, i8 %c, ...) { | |
; GISEL-LABEL: va_func: | ||
; GISEL: .seh_proc va_func | ||
; GISEL-NEXT: // %bb.0: | ||
; GISEL-NEXT: sub sp, sp, #80 | ||
; GISEL-NEXT: .seh_stackalloc 80 | ||
; GISEL-NEXT: str x19, [sp, #16] // 8-byte Folded Spill | ||
; GISEL-NEXT: .seh_save_reg x19, 16 | ||
; GISEL-NEXT: str x30, [sp, #24] // 8-byte Folded Spill | ||
; GISEL-NEXT: .seh_save_reg x30, 24 | ||
; GISEL-NEXT: sub sp, sp, #112 | ||
; GISEL-NEXT: .seh_stackalloc 112 | ||
; GISEL-NEXT: str x19, [sp, #48] // 8-byte Folded Spill | ||
; GISEL-NEXT: .seh_save_reg x19, 48 | ||
; GISEL-NEXT: str x30, [sp, #56] // 8-byte Folded Spill | ||
; GISEL-NEXT: .seh_save_reg x30, 56 | ||
; GISEL-NEXT: .seh_endprologue | ||
; GISEL-NEXT: stp x3, x4, [sp, #40] | ||
; GISEL-NEXT: add x8, sp, #72 | ||
; GISEL-NEXT: mov w19, w0 | ||
; GISEL-NEXT: stp x5, x6, [sp, #56] | ||
; GISEL-NEXT: str x7, [sp, #72] | ||
; GISEL-NEXT: stp x3, x4, [sp, #72] | ||
; GISEL-NEXT: stp x5, x6, [sp, #88] | ||
; GISEL-NEXT: str x7, [sp, #104] | ||
; GISEL-NEXT: str x8, [sp, #16] | ||
; GISEL-NEXT: str w0, [sp, #12] | ||
; GISEL-NEXT: strb w1, [sp, #11] | ||
; GISEL-NEXT: strb w2, [sp, #10] | ||
; GISEL-NEXT: bl other | ||
; GISEL-NEXT: cmp w19, w0 | ||
; GISEL-NEXT: cset w0, ls | ||
; GISEL-NEXT: .seh_startepilogue | ||
; GISEL-NEXT: ldr x30, [sp, #24] // 8-byte Folded Reload | ||
; GISEL-NEXT: .seh_save_reg x30, 24 | ||
; GISEL-NEXT: ldr x19, [sp, #16] // 8-byte Folded Reload | ||
; GISEL-NEXT: .seh_save_reg x19, 16 | ||
; GISEL-NEXT: add sp, sp, #80 | ||
; GISEL-NEXT: .seh_stackalloc 80 | ||
; GISEL-NEXT: ldr x30, [sp, #56] // 8-byte Folded Reload | ||
; GISEL-NEXT: .seh_save_reg x30, 56 | ||
; GISEL-NEXT: ldr x19, [sp, #48] // 8-byte Folded Reload | ||
; GISEL-NEXT: .seh_save_reg x19, 48 | ||
; GISEL-NEXT: add sp, sp, #112 | ||
; GISEL-NEXT: .seh_stackalloc 112 | ||
; GISEL-NEXT: .seh_endepilogue | ||
; GISEL-NEXT: ret | ||
; GISEL-NEXT: .seh_endfunclet | ||
; GISEL-NEXT: .seh_endproc | ||
%valist = alloca %struct.__va_list | ||
call void @llvm.va_start(ptr %valist) | ||
%a_alloc = alloca i32, align 4 | ||
%b_alloc = alloca i8, align 1 | ||
%c_alloc = alloca i8, align 1 | ||
|
@@ -76,6 +84,7 @@ define i1 @va_func(i32 %a, i8 %b, i8 %c, ...) { | |
%a_load = load i32, ptr %a_alloc, align 4 | ||
%ret = call noundef i32 @other() | ||
%cmp = icmp ule i32 %a_load, %ret | ||
call void @llvm.va_end(ptr %valist) | ||
ret i1 %cmp | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this path is already handled in globalisel that should also be updated to match
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I don't think I get what you mean, sorry.
IIUC, GlobalIsel is quite new approach for generating machine code, which is supposed to be a successor for SelectionDAG. It can be turned on using
--global-isel=1
.So, I didn't find any
hasVAStart()
references in GISel code and tried simple examples to see if such optimization exists.After some tests I've observed that llc actually crashes on vaargs, when GISel is turned on. Here is godbolt link for x86 https://godbolt.org/z/q66feEb65. And locally (after addressing @ostannard review) I got similar failure on
CodeGen/AArch64/win64_vararg2.ll
test.Is it known? If not, I will try to look deeper
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as it works with
-global-isel-abort=0
, you're fine; you don't need to implement G_VASTART on any target where it isn't already implemented.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Added
-global-isel-abort=0
to failing test.