mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
b609feb61f
Commit 37962a331c77 ("bpf: Improve expanding logic in LowerSELECT_CC") intended to improve code quality for certain jmp conditions. The commit, however, has a couple of issues: (1). In code, just swap is not enough, ConditionalCode CC should also be swapped, otherwise incorrect code will be generated. (2). The ConditionalCode swap should be subject to getHasJmpExt(). If getHasJmpExt() is False, certain conditional codes will not be supported and swap may generate incorrect code. The original goal for this patch is to optimize jmp operations which does not have JmpExt turned on. If JmpExt is on, better code could be generated. For example, the test select_ri.ll is introduced to demonstrate the optimization. The same result can be achieved with -mcpu=v2 flag. Signed-off-by: Yonghong Song <yhs@fb.com> Acked-by: Alexei Starovoitov <ast@kernel.org> llvm-svn: 329043
108 lines
2.7 KiB
LLVM
108 lines
2.7 KiB
LLVM
; RUN: llc -O2 -march=bpfel -mcpu=v2 -mattr=+alu32 < %s | FileCheck %s
|
|
;
|
|
; long long select_u(unsigned a, unsigned b, long long c, long long d)
|
|
; {
|
|
; if (a > b)
|
|
; return c;
|
|
; else
|
|
; return d;
|
|
; }
|
|
;
|
|
; long long select_u_2(unsigned a, unsigned long long b, long long c, long long d)
|
|
; {
|
|
; if (a > b)
|
|
; return c;
|
|
; else
|
|
; return d;
|
|
; }
|
|
;
|
|
; long long select_s(signed a, signed b, long long c, long long d)
|
|
; {
|
|
; if (a > b)
|
|
; return c;
|
|
; else
|
|
; return d;
|
|
; }
|
|
;
|
|
; long long bar ();
|
|
;
|
|
; int foo (int b, int c)
|
|
; {
|
|
; unsigned int i32_val = (unsigned int) bar();
|
|
;
|
|
; if (i32_val < 10)
|
|
; return b;
|
|
; else
|
|
; return c;
|
|
; }
|
|
;
|
|
; int *inc_p (int *p, unsigned a)
|
|
; {
|
|
; return p + a;
|
|
; }
|
|
|
|
; Function Attrs: norecurse nounwind readnone
|
|
define dso_local i64 @select_u(i32 %a, i32 %b, i64 %c, i64 %d) local_unnamed_addr #0 {
|
|
; CHECK-LABEL: select_u:
|
|
entry:
|
|
%cmp = icmp ugt i32 %a, %b
|
|
%c.d = select i1 %cmp, i64 %c, i64 %d
|
|
; CHECK-NOT: r{{[0-9]+}} <<= 32
|
|
; CHECK-NOT: r{{[0-9]+}} >>= 32
|
|
; CHECK: if r{{[0-9]+}} {{<|>}} r{{[0-9]+}} goto
|
|
ret i64 %c.d
|
|
}
|
|
|
|
; Function Attrs: norecurse nounwind readnone
|
|
define dso_local i64 @select_u_2(i32 %a, i64 %b, i64 %c, i64 %d) local_unnamed_addr #0 {
|
|
; CHECK-LABEL: select_u_2:
|
|
entry:
|
|
%conv = zext i32 %a to i64
|
|
; CHECK-NOT: r{{[0-9]+}} <<= 32
|
|
; CHECK-NOT: r{{[0-9]+}} >>= 32
|
|
%cmp = icmp ugt i64 %conv, %b
|
|
%c.d = select i1 %cmp, i64 %c, i64 %d
|
|
ret i64 %c.d
|
|
}
|
|
|
|
; Function Attrs: norecurse nounwind readnone
|
|
define dso_local i64 @select_s(i32 %a, i32 %b, i64 %c, i64 %d) local_unnamed_addr #0 {
|
|
; CHECK-LABEL: select_s:
|
|
entry:
|
|
%cmp = icmp sgt i32 %a, %b
|
|
%c.d = select i1 %cmp, i64 %c, i64 %d
|
|
; CHECK: r{{[0-9]+}} <<= 32
|
|
; CHECK-NEXT: r{{[0-9]+}} s>>= 32
|
|
; CHECK: if r{{[0-9]+}} s{{<|>}} r{{[0-9]+}} goto
|
|
ret i64 %c.d
|
|
}
|
|
|
|
; Function Attrs: nounwind
|
|
define dso_local i32 @foo(i32 %b, i32 %c) local_unnamed_addr #0 {
|
|
; CHECK-LABEL: foo:
|
|
entry:
|
|
%call = tail call i64 bitcast (i64 (...)* @bar to i64 ()*)() #2
|
|
%conv = trunc i64 %call to i32
|
|
%cmp = icmp ult i32 %conv, 10
|
|
; The shifts can't be optimized out because %call comes from function call
|
|
; returning i64 so the high bits might be valid.
|
|
; CHECK: r{{[0-9]+}} <<= 32
|
|
; CHECK-NEXT: r{{[0-9]+}} >>= 32
|
|
%b.c = select i1 %cmp, i32 %b, i32 %c
|
|
; CHECK: if r{{[0-9]+}} {{<|>}} {{[0-9]+}} goto
|
|
ret i32 %b.c
|
|
}
|
|
|
|
declare dso_local i64 @bar(...) local_unnamed_addr #1
|
|
|
|
; Function Attrs: norecurse nounwind readnone
|
|
define dso_local i32* @inc_p(i32* readnone %p, i32 %a) local_unnamed_addr #0 {
|
|
; CHECK-LABEL: inc_p:
|
|
entry:
|
|
%idx.ext = zext i32 %a to i64
|
|
; CHECK-NOT: r{{[0-9]+}} <<= 32
|
|
; CHECK-NOT: r{{[0-9]+}} >>= 32
|
|
%add.ptr = getelementptr inbounds i32, i32* %p, i64 %idx.ext
|
|
ret i32* %add.ptr
|
|
}
|