[llvm] Spill/restore FP/BP around instructions in which they are clobbered (PR #81048)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 2 14:49:14 PDT 2024
================
@@ -0,0 +1,52 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc -mtriple=x86_64-pc-linux -stackrealign -verify-machineinstrs < %s | FileCheck %s
+
+; Calling convention ghccc uses ebp to pass parameter, so calling a function
+; using ghccc clobbers ebp. We should save and restore ebp around such a call
+; if ebp is used as frame pointer.
+
+declare ghccc i32 @external(i32)
+
+define i32 @foo(i32 %0, i32 %1) {
+; CHECK-LABEL: foo:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: movq %rsp, %rbp
+; CHECK-NEXT: .cfi_def_cfa_register %rbp
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: andq $-16, %rsp
+; CHECK-NEXT: subq $16, %rsp
+; CHECK-NEXT: .cfi_offset %rbx, -56
+; CHECK-NEXT: .cfi_offset %r12, -48
+; CHECK-NEXT: .cfi_offset %r13, -40
+; CHECK-NEXT: .cfi_offset %r14, -32
+; CHECK-NEXT: .cfi_offset %r15, -24
+; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: .cfi_remember_state
+; CHECK-NEXT: .cfi_escape 0x0f, 0x06, 0x77, 0x08, 0x06, 0x11, 0x10, 0x22 #
+; CHECK-NEXT: movl %esi, %ebp
+; CHECK-NEXT: movq %rdi, %r13
+; CHECK-NEXT: callq external at PLT
+; CHECK-NEXT: addq $8, %rsp
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_restore_state
+; CHECK-NEXT: leaq -40(%rbp), %rsp
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: popq %r13
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa %rsp, 8
+; CHECK-NEXT: retq
+ %x = call ghccc i32 @external(i32 %0, i32 %1)
----------------
weiguozhi wrote:
The only calling convention that clobbers RBP but no RBX is HiPE. I added a new test case for it. And this patch does correct work.
But the generated code is still wrong because of a different bug.
```
%6:gr64 = MOV64rm %fixed-stack.1, 1, $noreg, 0, $noreg :: (load (s64) from %fixed-stack.1)
%7:gr64 = MOV64rm %fixed-stack.0, 1, $noreg, 0, $noreg :: (load (s64) from %fixed-stack.0)
ADJCALLSTACKDOWN64 16, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
%8:gr64 = COPY $rsp
MOV64mr %8:gr64, 1, $noreg, 8, $noreg, killed %7:gr64 :: (store (s64) into stack + 8)
MOV64mr %8:gr64, 1, $noreg, 0, $noreg, killed %6:gr64 :: (store (s64) into stack)
$r15 = COPY %0:gr64
$rbp = COPY %1:gr64
$rsi = COPY %2:gr64
$rdx = COPY %3:gr64
$rcx = COPY %4:gr64
$r8 = COPY %5:gr64
CALL64pcrel32 target-flags(x86-plt) @external2, <regmask>, ...
```
x86-cf-opt transforms it to
```
ADJCALLSTACKDOWN64 16, 0, 16, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
$r15 = COPY %0:gr64
$rbp = COPY %1:gr64
$rsi = COPY %2:gr64
$rdx = COPY %3:gr64
$rcx = COPY %4:gr64
$r8 = COPY %5:gr64
PUSH64rmm %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def $rsp, implicit $rsp :: (load (s64) from %fixed-stack.0), (store (s64) into stack + 8)
PUSH64rmm %fixed-stack.1, 1, $noreg, 0, $noreg, implicit-def $rsp, implicit $rsp :: (load (s64) from %fixed-stack.1), (store (s64) into stack)
CALL64pcrel32 target-flags(x86-plt) @external2, <regmask>, ...
```
The access to %fixed-stack.0 needs rbp, but it is already assigned function argument.
https://github.com/llvm/llvm-project/pull/81048
More information about the llvm-commits
mailing list