diff options
Diffstat (limited to 'test/CodeGen/SystemZ')
-rw-r--r-- | test/CodeGen/SystemZ/ctpop-01.ll | 96 | ||||
-rw-r--r-- | test/CodeGen/SystemZ/htm-intrinsics.ll | 352 | ||||
-rw-r--r-- | test/CodeGen/SystemZ/int-cmp-12.ll | 15 | ||||
-rw-r--r-- | test/CodeGen/SystemZ/int-cmp-47.ll | 3 | ||||
-rw-r--r-- | test/CodeGen/SystemZ/int-cmp-50.ll | 30 | ||||
-rw-r--r-- | test/CodeGen/SystemZ/risbg-03.ll | 30 | ||||
-rw-r--r-- | test/CodeGen/SystemZ/tail-call-mem-intrinsics.ll | 31 |
7 files changed, 554 insertions, 3 deletions
diff --git a/test/CodeGen/SystemZ/ctpop-01.ll b/test/CodeGen/SystemZ/ctpop-01.ll new file mode 100644 index 0000000..ad80f9f --- /dev/null +++ b/test/CodeGen/SystemZ/ctpop-01.ll @@ -0,0 +1,96 @@ +; Test population-count instruction +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +declare i32 @llvm.ctpop.i32(i32 %a) +declare i64 @llvm.ctpop.i64(i64 %a) + +define i32 @f1(i32 %a) { +; CHECK-LABEL: f1: +; CHECK: popcnt %r0, %r2 +; CHECK: sllk %r1, %r0, 16 +; CHECK: ar %r1, %r0 +; CHECK: sllk %r2, %r1, 8 +; CHECK: ar %r2, %r1 +; CHECK: srl %r2, 24 +; CHECK: br %r14 + + %popcnt = call i32 @llvm.ctpop.i32(i32 %a) + ret i32 %popcnt +} + +define i32 @f2(i32 %a) { +; CHECK-LABEL: f2: +; CHECK: llhr %r0, %r2 +; CHECK: popcnt %r0, %r0 +; CHECK: risblg %r2, %r0, 16, 151, 8 +; CHECK: ar %r2, %r0 +; CHECK: srl %r2, 8 +; CHECK: br %r14 + %and = and i32 %a, 65535 + %popcnt = call i32 @llvm.ctpop.i32(i32 %and) + ret i32 %popcnt +} + +define i32 @f3(i32 %a) { +; CHECK-LABEL: f3: +; CHECK: llcr %r0, %r2 +; CHECK: popcnt %r2, %r0 +; CHECK: br %r14 + %and = and i32 %a, 255 + %popcnt = call i32 @llvm.ctpop.i32(i32 %and) + ret i32 %popcnt +} + +define i64 @f4(i64 %a) { +; CHECK-LABEL: f4: +; CHECK: popcnt %r0, %r2 +; CHECK: sllg %r1, %r0, 32 +; CHECK: agr %r1, %r0 +; CHECK: sllg %r0, %r1, 16 +; CHECK: agr %r0, %r1 +; CHECK: sllg %r1, %r0, 8 +; CHECK: agr %r1, %r0 +; CHECK: srlg %r2, %r1, 56 +; CHECK: br %r14 + %popcnt = call i64 @llvm.ctpop.i64(i64 %a) + ret i64 %popcnt +} + +define i64 @f5(i64 %a) { +; CHECK-LABEL: f5: +; CHECK: llgfr %r0, %r2 +; CHECK: popcnt %r0, %r0 +; CHECK: sllg %r1, %r0, 16 +; CHECK: algfr %r0, %r1 +; CHECK: sllg %r1, %r0, 8 +; CHECK: algfr %r0, %r1 +; CHECK: srlg %r2, %r0, 24 + %and = and i64 %a, 4294967295 + %popcnt = call i64 @llvm.ctpop.i64(i64 %and) + ret i64 %popcnt +} + +define i64 @f6(i64 %a) { +; CHECK-LABEL: f6: +; CHECK: llghr %r0, %r2 +; CHECK: popcnt %r0, %r0 +; CHECK: risbg %r1, %r0, 48, 183, 8 +; CHECK: agr %r1, %r0 +; CHECK: srlg %r2, %r1, 8 +; CHECK: br %r14 + %and = and i64 %a, 65535 + %popcnt = call i64 @llvm.ctpop.i64(i64 %and) + ret i64 %popcnt +} + +define i64 @f7(i64 %a) { +; CHECK-LABEL: f7: +; CHECK: llgcr %r0, %r2 +; CHECK: popcnt %r2, %r0 +; CHECK: br %r14 + %and = and i64 %a, 255 + %popcnt = call i64 @llvm.ctpop.i64(i64 %and) + ret i64 %popcnt +} + diff --git a/test/CodeGen/SystemZ/htm-intrinsics.ll b/test/CodeGen/SystemZ/htm-intrinsics.ll new file mode 100644 index 0000000..6441ef9 --- /dev/null +++ b/test/CodeGen/SystemZ/htm-intrinsics.ll @@ -0,0 +1,352 @@ +; Test transactional-execution intrinsics. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s + +declare i32 @llvm.s390.tbegin(i8 *, i32) +declare i32 @llvm.s390.tbegin.nofloat(i8 *, i32) +declare void @llvm.s390.tbeginc(i8 *, i32) +declare i32 @llvm.s390.tend() +declare void @llvm.s390.tabort(i64) +declare void @llvm.s390.ntstg(i64, i64 *) +declare i32 @llvm.s390.etnd() +declare void @llvm.s390.ppa.txassist(i32) + +; TBEGIN. +define void @test_tbegin() { +; CHECK-LABEL: test_tbegin: +; CHECK-NOT: stmg +; CHECK: std %f8, +; CHECK: std %f9, +; CHECK: std %f10, +; CHECK: std %f11, +; CHECK: std %f12, +; CHECK: std %f13, +; CHECK: std %f14, +; CHECK: std %f15, +; CHECK: tbegin 0, 65292 +; CHECK: ld %f8, +; CHECK: ld %f9, +; CHECK: ld %f10, +; CHECK: ld %f11, +; CHECK: ld %f12, +; CHECK: ld %f13, +; CHECK: ld %f14, +; CHECK: ld %f15, +; CHECK: br %r14 + call i32 @llvm.s390.tbegin(i8 *null, i32 65292) + ret void +} + +; TBEGIN (nofloat). +define void @test_tbegin_nofloat1() { +; CHECK-LABEL: test_tbegin_nofloat1: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0, 65292 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) + ret void +} + +; TBEGIN (nofloat) with integer CC return value. +define i32 @test_tbegin_nofloat2() { +; CHECK-LABEL: test_tbegin_nofloat2: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0, 65292 +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) + ret i32 %res +} + +; TBEGIN (nofloat) with implicit CC check. +define void @test_tbegin_nofloat3(i32 *%ptr) { +; CHECK-LABEL: test_tbegin_nofloat3: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0, 65292 +; CHECK: jnh {{\.L*}} +; CHECK: mvhi 0(%r2), 0 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) + %cmp = icmp eq i32 %res, 2 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + store i32 0, i32* %ptr, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; TBEGIN (nofloat) with dual CC use. +define i32 @test_tbegin_nofloat4(i32 %pad, i32 *%ptr) { +; CHECK-LABEL: test_tbegin_nofloat4: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0, 65292 +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 +; CHECK: cijlh %r2, 2, {{\.L*}} +; CHECK: mvhi 0(%r3), 0 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) + %cmp = icmp eq i32 %res, 2 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + store i32 0, i32* %ptr, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret i32 %res +} + +; TBEGIN (nofloat) with register. +define void @test_tbegin_nofloat5(i8 *%ptr) { +; CHECK-LABEL: test_tbegin_nofloat5: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0(%r2), 65292 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *%ptr, i32 65292) + ret void +} + +; TBEGIN (nofloat) with GRSM 0x0f00. +define void @test_tbegin_nofloat6() { +; CHECK-LABEL: test_tbegin_nofloat6: +; CHECK: stmg %r6, %r15, +; CHECK-NOT: std +; CHECK: tbegin 0, 3840 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 3840) + ret void +} + +; TBEGIN (nofloat) with GRSM 0xf100. +define void @test_tbegin_nofloat7() { +; CHECK-LABEL: test_tbegin_nofloat7: +; CHECK: stmg %r8, %r15, +; CHECK-NOT: std +; CHECK: tbegin 0, 61696 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 61696) + ret void +} + +; TBEGIN (nofloat) with GRSM 0xfe00 -- stack pointer added automatically. +define void @test_tbegin_nofloat8() { +; CHECK-LABEL: test_tbegin_nofloat8: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0, 65280 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65024) + ret void +} + +; TBEGIN (nofloat) with GRSM 0xfb00 -- no frame pointer needed. +define void @test_tbegin_nofloat9() { +; CHECK-LABEL: test_tbegin_nofloat9: +; CHECK: stmg %r10, %r15, +; CHECK-NOT: std +; CHECK: tbegin 0, 64256 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 64256) + ret void +} + +; TBEGIN (nofloat) with GRSM 0xfb00 -- frame pointer added automatically. +define void @test_tbegin_nofloat10(i64 %n) { +; CHECK-LABEL: test_tbegin_nofloat10: +; CHECK: stmg %r11, %r15, +; CHECK-NOT: std +; CHECK: tbegin 0, 65280 +; CHECK: br %r14 + %buf = alloca i8, i64 %n + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 64256) + ret void +} + +; TBEGINC. +define void @test_tbeginc() { +; CHECK-LABEL: test_tbeginc: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbeginc 0, 65288 +; CHECK: br %r14 + call void @llvm.s390.tbeginc(i8 *null, i32 65288) + ret void +} + +; TEND with integer CC return value. +define i32 @test_tend1() { +; CHECK-LABEL: test_tend1: +; CHECK: tend +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tend() + ret i32 %res +} + +; TEND with implicit CC check. +define void @test_tend3(i32 *%ptr) { +; CHECK-LABEL: test_tend3: +; CHECK: tend +; CHECK: je {{\.L*}} +; CHECK: mvhi 0(%r2), 0 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tend() + %cmp = icmp eq i32 %res, 2 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + store i32 0, i32* %ptr, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; TEND with dual CC use. +define i32 @test_tend2(i32 %pad, i32 *%ptr) { +; CHECK-LABEL: test_tend2: +; CHECK: tend +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 +; CHECK: cijlh %r2, 2, {{\.L*}} +; CHECK: mvhi 0(%r3), 0 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tend() + %cmp = icmp eq i32 %res, 2 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + store i32 0, i32* %ptr, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret i32 %res +} + +; TABORT with register only. +define void @test_tabort1(i64 %val) { +; CHECK-LABEL: test_tabort1: +; CHECK: tabort 0(%r2) +; CHECK: br %r14 + call void @llvm.s390.tabort(i64 %val) + ret void +} + +; TABORT with immediate only. +define void @test_tabort2(i64 %val) { +; CHECK-LABEL: test_tabort2: +; CHECK: tabort 1234 +; CHECK: br %r14 + call void @llvm.s390.tabort(i64 1234) + ret void +} + +; TABORT with register + immediate. +define void @test_tabort3(i64 %val) { +; CHECK-LABEL: test_tabort3: +; CHECK: tabort 1234(%r2) +; CHECK: br %r14 + %sum = add i64 %val, 1234 + call void @llvm.s390.tabort(i64 %sum) + ret void +} + +; TABORT with out-of-range immediate. +define void @test_tabort4(i64 %val) { +; CHECK-LABEL: test_tabort4: +; CHECK: tabort 0({{%r[1-5]}}) +; CHECK: br %r14 + call void @llvm.s390.tabort(i64 4096) + ret void +} + +; NTSTG with base pointer only. +define void @test_ntstg1(i64 *%ptr, i64 %val) { +; CHECK-LABEL: test_ntstg1: +; CHECK: ntstg %r3, 0(%r2) +; CHECK: br %r14 + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; NTSTG with base and index. +; Check that VSTL doesn't allow an index. +define void @test_ntstg2(i64 *%base, i64 %index, i64 %val) { +; CHECK-LABEL: test_ntstg2: +; CHECK: sllg [[REG:%r[1-5]]], %r3, 3 +; CHECK: ntstg %r4, 0([[REG]],%r2) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%base, i64 %index + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; NTSTG with the highest in-range displacement. +define void @test_ntstg3(i64 *%base, i64 %val) { +; CHECK-LABEL: test_ntstg3: +; CHECK: ntstg %r3, 524280(%r2) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%base, i64 65535 + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; NTSTG with an out-of-range positive displacement. +define void @test_ntstg4(i64 *%base, i64 %val) { +; CHECK-LABEL: test_ntstg4: +; CHECK: ntstg %r3, 0({{%r[1-5]}}) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%base, i64 65536 + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; NTSTG with the lowest in-range displacement. +define void @test_ntstg5(i64 *%base, i64 %val) { +; CHECK-LABEL: test_ntstg5: +; CHECK: ntstg %r3, -524288(%r2) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%base, i64 -65536 + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; NTSTG with an out-of-range negative displacement. +define void @test_ntstg6(i64 *%base, i64 %val) { +; CHECK-LABEL: test_ntstg6: +; CHECK: ntstg %r3, 0({{%r[1-5]}}) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%base, i64 -65537 + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; ETND. +define i32 @test_etnd() { +; CHECK-LABEL: test_etnd: +; CHECK: etnd %r2 +; CHECK: br %r14 + %res = call i32 @llvm.s390.etnd() + ret i32 %res +} + +; PPA (Transaction-Abort Assist) +define void @test_ppa_txassist(i32 %val) { +; CHECK-LABEL: test_ppa_txassist: +; CHECK: ppa %r2, 0, 1 +; CHECK: br %r14 + call void @llvm.s390.ppa.txassist(i32 %val) + ret void +} + diff --git a/test/CodeGen/SystemZ/int-cmp-12.ll b/test/CodeGen/SystemZ/int-cmp-12.ll index 077b224..d9c6a9f 100644 --- a/test/CodeGen/SystemZ/int-cmp-12.ll +++ b/test/CodeGen/SystemZ/int-cmp-12.ll @@ -49,13 +49,24 @@ define double @f4(double %a, double %b, i64 %i1) { ret double %res } -; Check the next value up, which must use a register comparison. +; Check the next value up, which can use a shifted comparison define double @f5(double %a, double %b, i64 %i1) { ; CHECK-LABEL: f5: -; CHECK: clgrjl %r2, +; CHECK: srlg [[REG:%r[0-5]]], %r2, 32 +; CHECK: cgije [[REG]], 0 ; CHECK: ldr %f0, %f2 ; CHECK: br %r14 %cond = icmp ult i64 %i1, 4294967296 %res = select i1 %cond, double %a, double %b ret double %res } +; Check the next value up, which must use a register comparison. +define double @f6(double %a, double %b, i64 %i1) { +; CHECK-LABEL: f6: +; CHECK: clgrjl %r2, +; CHECK: ldr %f0, %f2 +; CHECK: br %r14 + %cond = icmp ult i64 %i1, 4294967297 + %res = select i1 %cond, double %a, double %b + ret double %res +} diff --git a/test/CodeGen/SystemZ/int-cmp-47.ll b/test/CodeGen/SystemZ/int-cmp-47.ll index 038a25b..274350d 100644 --- a/test/CodeGen/SystemZ/int-cmp-47.ll +++ b/test/CodeGen/SystemZ/int-cmp-47.ll @@ -309,7 +309,8 @@ exit: define void @f17(i64 %a) { ; CHECK-LABEL: f17: ; CHECK-NOT: tmhh -; CHECK: llihh {{%r[0-5]}}, 49151 +; CHECK: srlg [[REG:%r[0-5]]], %r2, 48 +; CHECK: cgfi [[REG]], 49151 ; CHECK-NOT: tmhh ; CHECK: br %r14 entry: diff --git a/test/CodeGen/SystemZ/int-cmp-50.ll b/test/CodeGen/SystemZ/int-cmp-50.ll new file mode 100644 index 0000000..287ac2c --- /dev/null +++ b/test/CodeGen/SystemZ/int-cmp-50.ll @@ -0,0 +1,30 @@ +; Verify that we do not crash on always-true conditions +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -O0 +; +; This test was compiled using clang -O0 from the following source code: +; +; int test(unsigned long x) +; { +; return x >= 0 && x <= 15; +; } + +define signext i32 @test(i64 %x) { +entry: + %x.addr = alloca i64, align 8 + store i64 %x, i64* %x.addr, align 8 + %0 = load i64, i64* %x.addr, align 8 + %cmp = icmp uge i64 %0, 0 + br i1 %cmp, label %land.rhs, label %land.end + +land.rhs: ; preds = %entry + %1 = load i64, i64* %x.addr, align 8 + %cmp1 = icmp ule i64 %1, 15 + br label %land.end + +land.end: ; preds = %land.rhs, %entry + %2 = phi i1 [ false, %entry ], [ %cmp1, %land.rhs ] + %land.ext = zext i1 %2 to i32 + ret i32 %land.ext +} + diff --git a/test/CodeGen/SystemZ/risbg-03.ll b/test/CodeGen/SystemZ/risbg-03.ll new file mode 100644 index 0000000..c3c08ad --- /dev/null +++ b/test/CodeGen/SystemZ/risbg-03.ll @@ -0,0 +1,30 @@ +; Test use of RISBG vs RISBGN on zEC12. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s + +; On zEC12, we generally prefer RISBGN. +define i64 @f1(i64 %a, i64 %b) { +; CHECK-LABEL: f1: +; CHECK: risbgn %r2, %r3, 60, 62, 0 +; CHECK: br %r14 + %anda = and i64 %a, -15 + %andb = and i64 %b, 14 + %or = or i64 %anda, %andb + ret i64 %or +} + +; But we may fall back to RISBG if we can use the condition code. +define i64 @f2(i64 %a, i64 %b, i32* %c) { +; CHECK-LABEL: f2: +; CHECK: risbg %r2, %r3, 60, 62, 0 +; CHECK-NEXT: ipm +; CHECK: br %r14 + %anda = and i64 %a, -15 + %andb = and i64 %b, 14 + %or = or i64 %anda, %andb + %cmp = icmp sgt i64 %or, 0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* %c, align 4 + ret i64 %or +} + diff --git a/test/CodeGen/SystemZ/tail-call-mem-intrinsics.ll b/test/CodeGen/SystemZ/tail-call-mem-intrinsics.ll new file mode 100644 index 0000000..65cc394 --- /dev/null +++ b/test/CodeGen/SystemZ/tail-call-mem-intrinsics.ll @@ -0,0 +1,31 @@ +; RUN: llc -march=systemz < %s | FileCheck %s + +; CHECK-LABEL: tail_memcpy: +; CHECK: jg memcpy +define void @tail_memcpy(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 { +entry: + tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false) + ret void +} + +; CHECK-LABEL: tail_memmove: +; CHECK: jg memmove +define void @tail_memmove(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 { +entry: + tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false) + ret void +} + +; CHECK-LABEL: tail_memset: +; CHECK: jg memset +define void @tail_memset(i8* nocapture %p, i8 %c, i32 %n) #0 { +entry: + tail call void @llvm.memset.p0i8.i32(i8* %p, i8 %c, i32 %n, i32 1, i1 false) + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0 +declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0 +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0 + +attributes #0 = { nounwind } |