bpf_fastcall induced spill/fill pairs should be generated for
sub-register as well as for sub-registers. At the moment this is not the
case, e.g.:
$ cat t.c
extern int foo(void) __attribute__((bpf_fastcall));
int bar(int a) {
foo();
return a;
}
$ clang --target=bpf -mcpu=v3 -O2 -S t.c -o -
...
call foo
w0 = w1
exit
Modify BPFMIPeephole.cpp:collectBPFFastCalls() to check sub-registers
liveness and thus produce correct code for example above:
*(u64 *)(r10 - 8) = r1
call foo
r1 = *(u64 *)(r10 - 8)
w0 = w1
exit
36 lines
799 B
LLVM
36 lines
799 B
LLVM
; RUN: llc -O2 --march=bpfel %s -o - | FileCheck %s
|
|
|
|
; Generated from the following C code:
|
|
;
|
|
; extern int foo(void) __attribute__((bpf_fastcall));
|
|
;
|
|
; int bar(int a, int b, int c, int d, int e) {
|
|
; foo();
|
|
; return e;
|
|
; }
|
|
;
|
|
; Using the following command:
|
|
;
|
|
; clang --target=bpf -emit-llvm -O2 -S -o - t.c
|
|
;
|
|
; (unnecessary attrs removed maually)
|
|
|
|
; Check that function marked with bpf_fastcall does not clobber W1-W5.
|
|
|
|
define dso_local i32 @bar(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
|
|
entry:
|
|
%call = tail call i32 @foo() #0
|
|
ret i32 %e
|
|
}
|
|
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: *(u64 *)(r10 - 8) = r5
|
|
; CHECK-NEXT: call foo
|
|
; CHECK-NEXT: r5 = *(u64 *)(r10 - 8)
|
|
; CHECK-NEXT: w0 = w5
|
|
; CHECK-NEXT: exit
|
|
|
|
declare dso_local i32 @foo() #0
|
|
|
|
attributes #0 = { "bpf_fastcall" }
|