mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
1efbe554a0
One of current peephole optimiations is to remove SLL/SRL if the sub register has been zero extended. This phase has two bugs and one limitations. First, for the physical subregister used in pseudo insn COPY like below, it permits incorrect optimization. %0:gpr32 = COPY $w0 ... %4:gpr = MOV_32_64 %0:gpr32 %5:gpr = SLL_ri %4:gpr(tied-def 0), 32 %6:gpr = SRA_ri %5:gpr(tied-def 0), 32 The $w0 could be from the return value of a previous function call and its upper 32-bit value might contain some non-zero values. The same applies to function arguments. Second, the current code may permits removing SLL/SRA like below: %0:gpr32 = COPY $w0 %1:gpr32 = COPY %0:gpr32 ... %4:gpr = MOV_32_64 %1:gpr32 %5:gpr = SLL_ri %4:gpr(tied-def 0), 32 %6:gpr = SRA_ri %5:gpr(tied-def 0), 32 The reason is that it did not follow def-use chain to skip all intermediate 32bit-to-32bit COPY instructions. The current implementation is also very conservative for PHI instructions. If any PHI insn component is another PHI or COPY insn, it will just permit SLL/SRA. This patch fixed the issue as follows: - During def/use chain traversal, if any physical register is read, SLL/SRA will be preserved as these physical registers are mostly from function return values or current function arguments. - Recursively visit all COPY and PHI instructions.
114 lines
2.6 KiB
LLVM
114 lines
2.6 KiB
LLVM
; RUN: llc -O2 -march=bpfel -mattr=+alu32 < %s | FileCheck %s
|
|
;
|
|
; unsigned int select_cc_32 (unsigned a, unsigned b, int c, int d)
|
|
; {
|
|
; if (a > b)
|
|
; return c;
|
|
; else
|
|
; return d;
|
|
; }
|
|
;
|
|
; long long select_cc_32_64 (unsigned a, unsigned b, long long c, long long d)
|
|
; {
|
|
; if (a > b)
|
|
; return c;
|
|
; else
|
|
; return d;
|
|
; }
|
|
;
|
|
; int select_cc_64_32 (long long a, long long b, int c, int d)
|
|
; {
|
|
; if (a > b)
|
|
; return c;
|
|
; else
|
|
; return d;
|
|
; }
|
|
;
|
|
; int selecti_cc_32 (unsigned a, int c, int d)
|
|
; {
|
|
; if (a > 10)
|
|
; return c;
|
|
; else
|
|
; return d;
|
|
; }
|
|
;
|
|
; long long selecti_cc_32_64 (unsigned a, long long c, long long d)
|
|
; {
|
|
; if (a > 11)
|
|
; return c;
|
|
; else
|
|
; return d;
|
|
; }
|
|
;
|
|
; int selecti_cc_64_32 (long long a, int c, int d)
|
|
; {
|
|
; if (a > 12)
|
|
; return c;
|
|
; else
|
|
; return d;
|
|
; }
|
|
|
|
; Function Attrs: norecurse nounwind readnone
|
|
define dso_local i32 @select_cc_32(i32 %a, i32 %b, i32 %c, i32 %d) local_unnamed_addr #0 {
|
|
entry:
|
|
%cmp = icmp ugt i32 %a, %b
|
|
%c.d = select i1 %cmp, i32 %c, i32 %d
|
|
ret i32 %c.d
|
|
}
|
|
; CHECK-LABEL: select_cc_32
|
|
; CHECK: r{{[0-9]+}} <<= 32
|
|
; CHECK-NEXT: r{{[0-9]+}} >>= 32
|
|
|
|
; Function Attrs: norecurse nounwind readnone
|
|
define dso_local i64 @select_cc_32_64(i32 %a, i32 %b, i64 %c, i64 %d) local_unnamed_addr #0 {
|
|
entry:
|
|
%cmp = icmp ugt i32 %a, %b
|
|
%c.d = select i1 %cmp, i64 %c, i64 %d
|
|
ret i64 %c.d
|
|
}
|
|
; CHECK-LABEL: select_cc_32_64
|
|
; CHECK: r{{[0-9]+}} <<= 32
|
|
; CHECK-NEXT: r{{[0-9]+}} >>= 32
|
|
|
|
; Function Attrs: norecurse nounwind readnone
|
|
define dso_local i32 @select_cc_64_32(i64 %a, i64 %b, i32 %c, i32 %d) local_unnamed_addr #0 {
|
|
entry:
|
|
%cmp = icmp sgt i64 %a, %b
|
|
%c.d = select i1 %cmp, i32 %c, i32 %d
|
|
ret i32 %c.d
|
|
}
|
|
; CHECK-LABEL: select_cc_64_32
|
|
; CHECK-NOT: r{{[0-9]+}} <<= 32
|
|
|
|
; Function Attrs: norecurse nounwind readnone
|
|
define dso_local i32 @selecti_cc_32(i32 %a, i32 %c, i32 %d) local_unnamed_addr #0 {
|
|
entry:
|
|
%cmp = icmp ugt i32 %a, 10
|
|
%c.d = select i1 %cmp, i32 %c, i32 %d
|
|
ret i32 %c.d
|
|
}
|
|
; CHECK-LABEL: selecti_cc_32
|
|
; CHECK: r{{[0-9]+}} <<= 32
|
|
; CHECK-NEXT: r{{[0-9]+}} >>= 32
|
|
|
|
; Function Attrs: norecurse nounwind readnone
|
|
define dso_local i64 @selecti_cc_32_64(i32 %a, i64 %c, i64 %d) local_unnamed_addr #0 {
|
|
entry:
|
|
%cmp = icmp ugt i32 %a, 11
|
|
%c.d = select i1 %cmp, i64 %c, i64 %d
|
|
ret i64 %c.d
|
|
}
|
|
; CHECK-LABEL: selecti_cc_32_64
|
|
; CHECK: r{{[0-9]+}} <<= 32
|
|
; CHECK-NEXT: r{{[0-9]+}} >>= 32
|
|
|
|
; Function Attrs: norecurse nounwind readnone
|
|
define dso_local i32 @selecti_cc_64_32(i64 %a, i32 %c, i32 %d) local_unnamed_addr #0 {
|
|
entry:
|
|
%cmp = icmp sgt i64 %a, 12
|
|
%c.d = select i1 %cmp, i32 %c, i32 %d
|
|
ret i32 %c.d
|
|
}
|
|
; CHECK-LABEL: selecti_cc_64_32
|
|
; CHECK-NOT: r{{[0-9]+}} <<= 32
|