blob: b6ae85c7768928a8d72c5e6a2ef2a46bd96999f0 [file] [edit]
; RUN: llc < %s -mtriple=bpf -mcpu=v1 | FileCheck --check-prefixes=CHECK,CHECK-SHIFT,CHECK-NOALU32 %s
; RUN: llc < %s -mtriple=bpf -mcpu=v3 | FileCheck --check-prefixes=CHECK,CHECK-SHIFT,CHECK-V3 %s
; RUN: llc < %s -mtriple=bpf -mcpu=v4 | FileCheck --check-prefixes=CHECK,CHECK-V4 %s
; signext/zeroext i32 stack arguments are extended to the full 64-bit slot
; by the caller, with and without ALU32, and the callee uses the slot
; without extending.
declare i64 @ext(i64, i64, i64, i64, i64, i32 zeroext, i32 signext)
define i64 @caller(i64 %v) {
%t = trunc i64 %v to i32
%r = call i64 @ext(i64 1, i64 2, i64 3, i64 4, i64 5, i32 zeroext %t, i32 signext %t)
ret i64 %r
}
; CHECK-LABEL: caller:
; CHECK-SHIFT: r[[Z:[0-9]+]] >>= 32
; CHECK-SHIFT: *(u64 *)(r11 - 8) = r[[Z]]
; CHECK-SHIFT: r[[S:[0-9]+]] s>>= 32
; CHECK-SHIFT: *(u64 *)(r11 - 16) = r[[S]]
; CHECK-V4: r[[Z:[0-9]+]] >>= 32
; CHECK-V4: *(u64 *)(r11 - 8) = r[[Z]]
; CHECK-V4: r[[S:[0-9]+]] = (s32)r{{[0-9]+}}
; CHECK-V4: *(u64 *)(r11 - 16) = r[[S]]
; CHECK: call ext
define i64 @callee(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i32 zeroext %f, i32 signext %g) {
%x = zext i32 %f to i64
%y = sext i32 %g to i64
%r = xor i64 %x, %y
ret i64 %r
}
; CHECK-LABEL: callee:
; CHECK: r{{[0-9]+}} = *(u64 *)(r11 + 8)
; CHECK-NEXT: r{{[0-9]+}} = *(u64 *)(r11 + 16)
; CHECK-NEXT: r{{[0-9]+}} ^= r{{[0-9]+}}
; CHECK-NEXT: exit
; With ALU32, a signext/zeroext register argument is only known to be
; extended within its 32-bit subregister. Forwarding it as a stack
; argument must extend it to the full slot. In C:
; long fwd(short s) { return ext16(1, 2, 3, 4, 5, s); }
; long fwdz(unsigned char c) { return ext8(1, 2, 3, 4, 5, c); }
declare i64 @ext16(i64, i64, i64, i64, i64, i16 signext)
define i64 @fwd(i16 signext %s) {
%r = call i64 @ext16(i64 1, i64 2, i64 3, i64 4, i64 5, i16 signext %s)
ret i64 %r
}
; CHECK-LABEL: fwd:
; CHECK-NOALU32: *(u64 *)(r11 - 8) = r1
; CHECK-V3: r1 = w1
; CHECK-V3-NEXT: r1 <<= 32
; CHECK-V3-NEXT: r1 s>>= 32
; CHECK-V3-NEXT: *(u64 *)(r11 - 8) = r1
; CHECK-V4: r1 = (s32)r1
; CHECK-V4-NEXT: *(u64 *)(r11 - 8) = r1
; CHECK: call ext16
declare i64 @ext8(i64, i64, i64, i64, i64, i8 zeroext)
define i64 @fwdz(i8 zeroext %c) {
%r = call i64 @ext8(i64 1, i64 2, i64 3, i64 4, i64 5, i8 zeroext %c)
ret i64 %r
}
; CHECK-LABEL: fwdz:
; CHECK-NOALU32: *(u64 *)(r11 - 8) = r1
; CHECK-V3: r1 = w1
; CHECK-V3-NEXT: *(u64 *)(r11 - 8) = r1
; CHECK-V4: r1 = w1
; CHECK-V4-NEXT: *(u64 *)(r11 - 8) = r1
; CHECK: call ext8