diff --git a/llvm/test/CodeGen/BPF/32-bit-subreg-alu.ll b/llvm/test/CodeGen/BPF/32-bit-subreg-alu.ll new file mode 100644 index 000000000000..2a498494589a --- /dev/null +++ b/llvm/test/CodeGen/BPF/32-bit-subreg-alu.ll @@ -0,0 +1,298 @@ +; RUN: llc -O2 -march=bpfel -mattr=+alu32 < %s | FileCheck %s +; +; int mov(int a) +; { +; return a; +; } +; +; int mov_ri(void) +; { +; return 0xff; +; } +; +; int add(int a, int b) +; { +; return a + b; +; } +; +; int add_i(int a) +; { +; return a + 0x7fffffff; +; } +; +; int sub(int a, int b) +; { +; return a - b; +; } +; +; int sub_i(int a) +; { +; return a - 0xffffffff; +; } +; +; int mul(int a, int b) +; { +; return a * b; +; } +; +; int mul_i(int a) +; { +; return a * 0xf; +; } +; +; unsigned div(unsigned a, unsigned b) +; { +; return a / b; +; } +; +; unsigned div_i(unsigned a) +; { +; return a / 0xf; +; } +; +; int or(int a, int b) +; { +; return a | b; +; } +; +; int or_i(int a) +; { +; return a | 0xff; +; } +; +; int xor(int a, int b) +; { +; return a ^ b; +; } +; +; int xor_i(int a) +; { +; return a ^ 0xfff; +; } +; +; int and(int a, int b) +; { +; return a & b; +; } +; +; int and_i(int a) +; { +; return a & 0xffff; +; } +; +; int sll(int a, int b) +; { +; return a << b; +; } +; +; int sll_i(int a) +; { +; return a << 17; +; } +; +; unsigned srl(unsigned a, unsigned b) +; { +; return a >> b; +; } +; +; unsigned srl_i(unsigned a, unsigned b) +; { +; return a >> 31; +; } +; +; int sra(int a, int b) +; { +; return a >> b; +; } +; +; int sra_i(int a, int b) +; { +; return a >> 7; +; } +; +; int neg(int a) +; { +; return -a; +; } + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @mov(i32 returned %a) local_unnamed_addr #0 { +entry: + ret i32 %a +; CHECK: w{{[0-9]+}} = w{{[0-9]+}} +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @mov_ri() local_unnamed_addr #0 { +entry: + ret i32 255 +; CHECK: w{{[0-9]+}} = 255 +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @add(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %add = add nsw i32 %b, %a +; CHECK: w{{[0-9]+}} += w{{[0-9]+}} + ret i32 %add +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @add_i(i32 %a) local_unnamed_addr #0 { +entry: + %add = add nsw i32 %a, 2147483647 +; CHECK: w{{[0-9]+}} += 2147483647 + ret i32 %add +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @sub(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %sub = sub nsw i32 %a, %b +; CHECK: w{{[0-9]+}} -= w{{[0-9]+}} + ret i32 %sub +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @sub_i(i32 %a) local_unnamed_addr #0 { +entry: + %sub = add i32 %a, 1 +; CHECK: w{{[0-9]+}} += 1 + ret i32 %sub +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @mul(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %mul = mul nsw i32 %b, %a +; CHECK: w{{[0-9]+}} *= w{{[0-9]+}} + ret i32 %mul +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @mul_i(i32 %a) local_unnamed_addr #0 { +entry: + %mul = mul nsw i32 %a, 15 +; CHECK: w{{[0-9]+}} *= 15 + ret i32 %mul +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @div(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %div = udiv i32 %a, %b +; CHECK: w{{[0-9]+}} /= w{{[0-9]+}} + ret i32 %div +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @div_i(i32 %a) local_unnamed_addr #0 { +entry: + %div = udiv i32 %a, 15 +; CHECK: w{{[0-9]+}} /= 15 + ret i32 %div +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @or(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %or = or i32 %b, %a +; CHECK: w{{[0-9]+}} |= w{{[0-9]+}} + ret i32 %or +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @or_i(i32 %a) local_unnamed_addr #0 { +entry: + %or = or i32 %a, 255 +; CHECK: w{{[0-9]+}} |= 255 + ret i32 %or +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @xor(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %xor = xor i32 %b, %a +; CHECK: w{{[0-9]+}} ^= w{{[0-9]+}} + ret i32 %xor +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @xor_i(i32 %a) local_unnamed_addr #0 { +entry: + %xor = xor i32 %a, 4095 +; CHECK: w{{[0-9]+}} ^= 4095 + ret i32 %xor +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @and(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %and = and i32 %b, %a +; CHECK: w{{[0-9]+}} &= w{{[0-9]+}} + ret i32 %and +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @and_i(i32 %a) local_unnamed_addr #0 { +entry: + %and = and i32 %a, 65535 +; CHECK: w{{[0-9]+}} &= 65535 + ret i32 %and +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @sll(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %shl = shl i32 %a, %b +; CHECK: w{{[0-9]+}} <<= w{{[0-9]+}} + ret i32 %shl +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @sll_i(i32 %a) local_unnamed_addr #0 { +entry: + %shl = shl i32 %a, 17 +; CHECK: w{{[0-9]+}} <<= 17 + ret i32 %shl +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @srl(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %shr = lshr i32 %a, %b +; CHECK: w{{[0-9]+}} >>= w{{[0-9]+}} + ret i32 %shr +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @srl_i(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %shr = lshr i32 %a, 31 +; CHECK: w{{[0-9]+}} >>= 31 + ret i32 %shr +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @sra(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %shr = ashr i32 %a, %b +; CHECK: w{{[0-9]+}} s>>= w{{[0-9]+}} + ret i32 %shr +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @sra_i(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %shr = ashr i32 %a, 7 +; CHECK: w{{[0-9]+}} s>>= 7 + ret i32 %shr +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @neg(i32 %a) local_unnamed_addr #0 { +entry: + %sub = sub nsw i32 0, %a +; CHECK: w{{[0-9]+}} = -w{{[0-9]+}} + ret i32 %sub +} diff --git a/llvm/test/CodeGen/BPF/32-bit-subreg-cond-select.ll b/llvm/test/CodeGen/BPF/32-bit-subreg-cond-select.ll new file mode 100644 index 000000000000..a48141cf0404 --- /dev/null +++ b/llvm/test/CodeGen/BPF/32-bit-subreg-cond-select.ll @@ -0,0 +1,100 @@ +; 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 +} + +; 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 +} + +; 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 +} + +; 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 +} + +; 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 +} + +; 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 +} +; There shouldn't be any type promotion, all of them are expected to be +; eliminated by peephole optimization. +; CHECK-NOT: r{{[0-9]+}} <<= 32 diff --git a/llvm/test/CodeGen/BPF/32-bit-subreg-load-store.ll b/llvm/test/CodeGen/BPF/32-bit-subreg-load-store.ll new file mode 100644 index 000000000000..9906cee35dde --- /dev/null +++ b/llvm/test/CodeGen/BPF/32-bit-subreg-load-store.ll @@ -0,0 +1,107 @@ +; RUN: llc -O2 -march=bpfel -mattr=+alu32 < %s | FileCheck %s +; +; unsigned char loadu8(unsigned char *p) +; { +; return *p; +; } +; +; unsigned short loadu16(unsigned short *p) +; { +; return *p; +; } +; +; unsigned loadu32(unsigned *p) +; { +; return *p; +; } +; +; unsigned long long loadu64(unsigned long long *p) +; { +; return *p; +; } +; +; void storeu8(unsigned char *p, unsigned long long v) +; { +; *p = (unsigned char)v; +; } +; +; void storeu16(unsigned short *p, unsigned long long v) +; { +; *p = (unsigned short)v; +; } +; +; void storeu32(unsigned *p, unsigned long long v) +; { +; *p = (unsigned)v; +; } +; +; void storeu64(unsigned long long *p, unsigned long long v) +; { +; *p = v; +; } +; Function Attrs: norecurse nounwind readonly +define dso_local zeroext i8 @loadu8(i8* nocapture readonly %p) local_unnamed_addr #0 { +entry: + %0 = load i8, i8* %p, align 1 +; CHECK: w{{[0-9]+}} = *(u8 *)(r{{[0-9]+}} + 0) + ret i8 %0 +} + +; Function Attrs: norecurse nounwind readonly +define dso_local zeroext i16 @loadu16(i16* nocapture readonly %p) local_unnamed_addr #0 { +entry: + %0 = load i16, i16* %p, align 2 +; CHECK: w{{[0-9]+}} = *(u16 *)(r{{[0-9]+}} + 0) + ret i16 %0 +} + +; Function Attrs: norecurse nounwind readonly +define dso_local i32 @loadu32(i32* nocapture readonly %p) local_unnamed_addr #0 { +entry: + %0 = load i32, i32* %p, align 4 +; CHECK: w{{[0-9]+}} = *(u32 *)(r{{[0-9]+}} + 0) + ret i32 %0 +} + +; Function Attrs: norecurse nounwind readonly +define dso_local i64 @loadu64(i64* nocapture readonly %p) local_unnamed_addr #0 { +entry: + %0 = load i64, i64* %p, align 8 +; CHECK: r{{[0-9]+}} = *(u64 *)(r{{[0-9]+}} + 0) + ret i64 %0 +} + +; Function Attrs: norecurse nounwind +define dso_local void @storeu8(i8* nocapture %p, i64 %v) local_unnamed_addr #1 { +entry: + %conv = trunc i64 %v to i8 + store i8 %conv, i8* %p, align 1 +; CHECK: *(u8 *)(r{{[0-9]+}} + 0) = w{{[0-9]+}} + ret void +} + +; Function Attrs: norecurse nounwind +define dso_local void @storeu16(i16* nocapture %p, i64 %v) local_unnamed_addr #1 { +entry: + %conv = trunc i64 %v to i16 + store i16 %conv, i16* %p, align 2 +; CHECK: *(u16 *)(r{{[0-9]+}} + 0) = w{{[0-9]+}} + ret void +} + +; Function Attrs: norecurse nounwind +define dso_local void @storeu32(i32* nocapture %p, i64 %v) local_unnamed_addr #1 { +entry: + %conv = trunc i64 %v to i32 + store i32 %conv, i32* %p, align 4 +; CHECK: *(u32 *)(r{{[0-9]+}} + 0) = w{{[0-9]+}} + ret void +} + +; Function Attrs: norecurse nounwind +define dso_local void @storeu64(i64* nocapture %p, i64 %v) local_unnamed_addr #1 { +entry: + store i64 %v, i64* %p, align 8 +; CHECK: *(u64 *)(r{{[0-9]+}} + 0) = r{{[0-9]+}} + ret void +} diff --git a/llvm/test/CodeGen/BPF/32-bit-subreg-peephole.ll b/llvm/test/CodeGen/BPF/32-bit-subreg-peephole.ll new file mode 100644 index 000000000000..8ec74ca3bf22 --- /dev/null +++ b/llvm/test/CodeGen/BPF/32-bit-subreg-peephole.ll @@ -0,0 +1,36 @@ +; RUN: llc -O2 -march=bpfel -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_s(signed a, signed b, long long c, long long d) +; { +; if (a > b) +; return c; +; else +; return d; +;} +; 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: if r{{[0-9]+}} {{<|>}} r{{[0-9]+}} goto + 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: if r{{[0-9]+}} s{{<|>}} r{{[0-9]+}} goto + ret i64 %c.d +}