diff options
Diffstat (limited to 'test/CodeGen/SystemZ')
69 files changed, 2167 insertions, 153 deletions
diff --git a/test/CodeGen/SystemZ/Large/branch-range-01.py b/test/CodeGen/SystemZ/Large/branch-range-01.py index 552c9ca0ea85..edb631d8c6d5 100644 --- a/test/CodeGen/SystemZ/Large/branch-range-01.py +++ b/test/CodeGen/SystemZ/Large/branch-range-01.py @@ -79,7 +79,7 @@ for i in xrange(branch_blocks): next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main' print 'before%d:' % i print ' %%bstop%d = getelementptr i32 *%%stop, i64 %d' % (i, i) - print ' %%bcur%d = load volatile i32 *%%bstop%d' % (i, i) + print ' %%bcur%d = load i32 *%%bstop%d' % (i, i) print ' %%btest%d = icmp eq i32 %%limit, %%bcur%d' % (i, i) print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next) print '' @@ -95,7 +95,7 @@ for i in xrange(0, main_size, 6): for i in xrange(branch_blocks): print ' %%astop%d = getelementptr i32 *%%stop, i64 %d' % (i, i + 25) - print ' %%acur%d = load volatile i32 *%%astop%d' % (i, i) + print ' %%acur%d = load i32 *%%astop%d' % (i, i) print ' %%atest%d = icmp eq i32 %%limit, %%acur%d' % (i, i) print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i) print '' diff --git a/test/CodeGen/SystemZ/Large/branch-range-02.py b/test/CodeGen/SystemZ/Large/branch-range-02.py index 0b21ced99a1f..743e12de0f1f 100644 --- a/test/CodeGen/SystemZ/Large/branch-range-02.py +++ b/test/CodeGen/SystemZ/Large/branch-range-02.py @@ -72,7 +72,7 @@ for i in xrange(blocks): print 'b%d:' % i print ' store volatile i8 %d, i8 *%%base' % value print ' %%astop%d = getelementptr i32 *%%stop, i64 %d' % (i, i) - print ' %%acur%d = load volatile i32 *%%astop%d' % (i, i) + print ' %%acur%d = load i32 *%%astop%d' % (i, i) print ' %%atest%d = icmp eq i32 %%limit, %%acur%d' % (i, i) print ' br i1 %%atest%d, label %%%s, label %%%s' % (i, other, next) diff --git a/test/CodeGen/SystemZ/Large/branch-range-03.py b/test/CodeGen/SystemZ/Large/branch-range-03.py index 75cdf247c6f3..5c9a93b87f73 100644 --- a/test/CodeGen/SystemZ/Large/branch-range-03.py +++ b/test/CodeGen/SystemZ/Large/branch-range-03.py @@ -79,7 +79,7 @@ for i in xrange(branch_blocks): next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main' print 'before%d:' % i print ' %%bstop%d = getelementptr i8 *%%stop, i64 %d' % (i, i) - print ' %%bcur%d = load volatile i8 *%%bstop%d' % (i, i) + print ' %%bcur%d = load i8 *%%bstop%d' % (i, i) print ' %%bext%d = sext i8 %%bcur%d to i32' % (i, i) print ' %%btest%d = icmp eq i32 %%limit, %%bext%d' % (i, i) print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next) @@ -96,7 +96,7 @@ for i in xrange(0, main_size, 6): for i in xrange(branch_blocks): print ' %%astop%d = getelementptr i8 *%%stop, i64 %d' % (i, i + 25) - print ' %%acur%d = load volatile i8 *%%astop%d' % (i, i) + print ' %%acur%d = load i8 *%%astop%d' % (i, i) print ' %%aext%d = sext i8 %%acur%d to i32' % (i, i) print ' %%atest%d = icmp eq i32 %%limit, %%aext%d' % (i, i) print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i) diff --git a/test/CodeGen/SystemZ/Large/branch-range-04.py b/test/CodeGen/SystemZ/Large/branch-range-04.py index 3ae3ae9c37f7..2c9090fa2067 100644 --- a/test/CodeGen/SystemZ/Large/branch-range-04.py +++ b/test/CodeGen/SystemZ/Large/branch-range-04.py @@ -83,7 +83,7 @@ for i in xrange(branch_blocks): next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main' print 'before%d:' % i print ' %%bstop%d = getelementptr i8 *%%stop, i64 %d' % (i, i) - print ' %%bcur%d = load volatile i8 *%%bstop%d' % (i, i) + print ' %%bcur%d = load i8 *%%bstop%d' % (i, i) print ' %%bext%d = sext i8 %%bcur%d to i64' % (i, i) print ' %%btest%d = icmp eq i64 %%limit, %%bext%d' % (i, i) print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next) @@ -100,7 +100,7 @@ for i in xrange(0, main_size, 6): for i in xrange(branch_blocks): print ' %%astop%d = getelementptr i8 *%%stop, i64 %d' % (i, i + 25) - print ' %%acur%d = load volatile i8 *%%astop%d' % (i, i) + print ' %%acur%d = load i8 *%%astop%d' % (i, i) print ' %%aext%d = sext i8 %%acur%d to i64' % (i, i) print ' %%atest%d = icmp eq i64 %%limit, %%aext%d' % (i, i) print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i) diff --git a/test/CodeGen/SystemZ/Large/branch-range-05.py b/test/CodeGen/SystemZ/Large/branch-range-05.py index 6928b8fc21d6..52f4a961c88f 100644 --- a/test/CodeGen/SystemZ/Large/branch-range-05.py +++ b/test/CodeGen/SystemZ/Large/branch-range-05.py @@ -82,7 +82,7 @@ print '' for i in xrange(branch_blocks): next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main' print 'before%d:' % i - print ' %%bcur%d = load volatile i8 *%%stop' % i + print ' %%bcur%d = load i8 *%%stop' % i print ' %%bext%d = sext i8 %%bcur%d to i32' % (i, i) print ' %%btest%d = icmp slt i32 %%bext%d, %d' % (i, i, i + 50) print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next) @@ -98,7 +98,7 @@ for i in xrange(0, main_size, 6): print ' store volatile i8 %d, i8 *%%ptr%d' % (value, i) for i in xrange(branch_blocks): - print ' %%acur%d = load volatile i8 *%%stop' % i + print ' %%acur%d = load i8 *%%stop' % i print ' %%aext%d = sext i8 %%acur%d to i32' % (i, i) print ' %%atest%d = icmp slt i32 %%aext%d, %d' % (i, i, i + 100) print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i) diff --git a/test/CodeGen/SystemZ/Large/branch-range-06.py b/test/CodeGen/SystemZ/Large/branch-range-06.py index aabc72fa6ec8..c34ebac4ce36 100644 --- a/test/CodeGen/SystemZ/Large/branch-range-06.py +++ b/test/CodeGen/SystemZ/Large/branch-range-06.py @@ -82,7 +82,7 @@ print '' for i in xrange(branch_blocks): next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main' print 'before%d:' % i - print ' %%bcur%d = load volatile i8 *%%stop' % i + print ' %%bcur%d = load i8 *%%stop' % i print ' %%bext%d = sext i8 %%bcur%d to i64' % (i, i) print ' %%btest%d = icmp slt i64 %%bext%d, %d' % (i, i, i + 50) print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next) @@ -98,7 +98,7 @@ for i in xrange(0, main_size, 6): print ' store volatile i8 %d, i8 *%%ptr%d' % (value, i) for i in xrange(branch_blocks): - print ' %%acur%d = load volatile i8 *%%stop' % i + print ' %%acur%d = load i8 *%%stop' % i print ' %%aext%d = sext i8 %%acur%d to i64' % (i, i) print ' %%atest%d = icmp slt i64 %%aext%d, %d' % (i, i, i + 100) print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i) diff --git a/test/CodeGen/SystemZ/Large/branch-range-09.py b/test/CodeGen/SystemZ/Large/branch-range-09.py index b3fd81324dab..bc712cb164ea 100644 --- a/test/CodeGen/SystemZ/Large/branch-range-09.py +++ b/test/CodeGen/SystemZ/Large/branch-range-09.py @@ -79,7 +79,7 @@ for i in xrange(branch_blocks): next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main' print 'before%d:' % i print ' %%bstop%d = getelementptr i8 *%%stop, i64 %d' % (i, i) - print ' %%bcur%d = load volatile i8 *%%bstop%d' % (i, i) + print ' %%bcur%d = load i8 *%%bstop%d' % (i, i) print ' %%bext%d = sext i8 %%bcur%d to i32' % (i, i) print ' %%btest%d = icmp ult i32 %%limit, %%bext%d' % (i, i) print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next) @@ -96,7 +96,7 @@ for i in xrange(0, main_size, 6): for i in xrange(branch_blocks): print ' %%astop%d = getelementptr i8 *%%stop, i64 %d' % (i, i + 25) - print ' %%acur%d = load volatile i8 *%%astop%d' % (i, i) + print ' %%acur%d = load i8 *%%astop%d' % (i, i) print ' %%aext%d = sext i8 %%acur%d to i32' % (i, i) print ' %%atest%d = icmp ult i32 %%limit, %%aext%d' % (i, i) print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i) diff --git a/test/CodeGen/SystemZ/Large/branch-range-10.py b/test/CodeGen/SystemZ/Large/branch-range-10.py index 3aeea3ebccdf..8c483c33724c 100644 --- a/test/CodeGen/SystemZ/Large/branch-range-10.py +++ b/test/CodeGen/SystemZ/Large/branch-range-10.py @@ -83,7 +83,7 @@ for i in xrange(branch_blocks): next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main' print 'before%d:' % i print ' %%bstop%d = getelementptr i8 *%%stop, i64 %d' % (i, i) - print ' %%bcur%d = load volatile i8 *%%bstop%d' % (i, i) + print ' %%bcur%d = load i8 *%%bstop%d' % (i, i) print ' %%bext%d = sext i8 %%bcur%d to i64' % (i, i) print ' %%btest%d = icmp ult i64 %%limit, %%bext%d' % (i, i) print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next) @@ -100,7 +100,7 @@ for i in xrange(0, main_size, 6): for i in xrange(branch_blocks): print ' %%astop%d = getelementptr i8 *%%stop, i64 %d' % (i, i + 25) - print ' %%acur%d = load volatile i8 *%%astop%d' % (i, i) + print ' %%acur%d = load i8 *%%astop%d' % (i, i) print ' %%aext%d = sext i8 %%acur%d to i64' % (i, i) print ' %%atest%d = icmp ult i64 %%limit, %%aext%d' % (i, i) print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i) diff --git a/test/CodeGen/SystemZ/Large/branch-range-11.py b/test/CodeGen/SystemZ/Large/branch-range-11.py index 034902c4a342..054610380e31 100644 --- a/test/CodeGen/SystemZ/Large/branch-range-11.py +++ b/test/CodeGen/SystemZ/Large/branch-range-11.py @@ -98,8 +98,8 @@ print '' for i in xrange(branch_blocks): next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main' print 'before%d:' % i - print ' %%bcur%da = load volatile i32 *%%stopa' % i - print ' %%bcur%db = load volatile i32 *%%stopb' % i + print ' %%bcur%da = load i32 *%%stopa' % i + print ' %%bcur%db = load i32 *%%stopb' % i print ' %%bsub%d = sub i32 %%bcur%da, %%bcur%db' % (i, i, i) print ' %%btest%d = icmp ult i32 %%bsub%d, %d' % (i, i, i + 50) print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next) @@ -115,8 +115,8 @@ for i in xrange(0, main_size, 6): print ' store volatile i8 %d, i8 *%%ptr%d' % (value, i) for i in xrange(branch_blocks): - print ' %%acur%da = load volatile i32 *%%stopa' % i - print ' %%acur%db = load volatile i32 *%%stopb' % i + print ' %%acur%da = load i32 *%%stopa' % i + print ' %%acur%db = load i32 *%%stopb' % i print ' %%asub%d = sub i32 %%acur%da, %%acur%db' % (i, i, i) print ' %%atest%d = icmp ult i32 %%asub%d, %d' % (i, i, i + 100) print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i) diff --git a/test/CodeGen/SystemZ/Large/branch-range-12.py b/test/CodeGen/SystemZ/Large/branch-range-12.py index 007d477e2140..626c8998d5d4 100644 --- a/test/CodeGen/SystemZ/Large/branch-range-12.py +++ b/test/CodeGen/SystemZ/Large/branch-range-12.py @@ -98,8 +98,8 @@ print '' for i in xrange(branch_blocks): next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main' print 'before%d:' % i - print ' %%bcur%da = load volatile i64 *%%stopa' % i - print ' %%bcur%db = load volatile i64 *%%stopb' % i + print ' %%bcur%da = load i64 *%%stopa' % i + print ' %%bcur%db = load i64 *%%stopb' % i print ' %%bsub%d = sub i64 %%bcur%da, %%bcur%db' % (i, i, i) print ' %%btest%d = icmp ult i64 %%bsub%d, %d' % (i, i, i + 50) print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next) @@ -115,8 +115,8 @@ for i in xrange(0, main_size, 6): print ' store volatile i8 %d, i8 *%%ptr%d' % (value, i) for i in xrange(branch_blocks): - print ' %%acur%da = load volatile i64 *%%stopa' % i - print ' %%acur%db = load volatile i64 *%%stopb' % i + print ' %%acur%da = load i64 *%%stopa' % i + print ' %%acur%db = load i64 *%%stopb' % i print ' %%asub%d = sub i64 %%acur%da, %%acur%db' % (i, i, i) print ' %%atest%d = icmp ult i64 %%asub%d, %d' % (i, i, i + 100) print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i) diff --git a/test/CodeGen/SystemZ/Large/lit.local.cfg b/test/CodeGen/SystemZ/Large/lit.local.cfg index 9a02f849c347..4f22a970c3a6 100644 --- a/test/CodeGen/SystemZ/Large/lit.local.cfg +++ b/test/CodeGen/SystemZ/Large/lit.local.cfg @@ -5,6 +5,5 @@ config.suffixes = ['.py'] if config.root.host_arch not in ['SystemZ']: config.unsupported = True -targets = set(config.root.targets_to_build.split()) -if not 'SystemZ' in targets: +if not 'SystemZ' in config.root.targets: config.unsupported = True diff --git a/test/CodeGen/SystemZ/atomic-load-01.ll b/test/CodeGen/SystemZ/atomic-load-01.ll index a5bc8833e78a..f3acd605b012 100644 --- a/test/CodeGen/SystemZ/atomic-load-01.ll +++ b/test/CodeGen/SystemZ/atomic-load-01.ll @@ -2,11 +2,10 @@ ; ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -; This is just a placeholder to make sure that loads are handled. -; The CS-based sequence is probably far too conservative. define i8 @f1(i8 *%src) { ; CHECK-LABEL: f1: -; CHECK: cs +; CHECK: bcr 1{{[45]}}, %r0 +; CHECK: lb %r2, 0(%r2) ; CHECK: br %r14 %val = load atomic i8 *%src seq_cst, align 1 ret i8 %val diff --git a/test/CodeGen/SystemZ/atomic-load-02.ll b/test/CodeGen/SystemZ/atomic-load-02.ll index 2c9bbdb488a1..d9bec60f4c1b 100644 --- a/test/CodeGen/SystemZ/atomic-load-02.ll +++ b/test/CodeGen/SystemZ/atomic-load-02.ll @@ -2,11 +2,10 @@ ; ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -; This is just a placeholder to make sure that loads are handled. -; The CS-based sequence is probably far too conservative. define i16 @f1(i16 *%src) { ; CHECK-LABEL: f1: -; CHECK: cs +; CHECK: bcr 1{{[45]}}, %r0 +; CHECK: lh %r2, 0(%r2) ; CHECK: br %r14 %val = load atomic i16 *%src seq_cst, align 2 ret i16 %val diff --git a/test/CodeGen/SystemZ/atomic-load-03.ll b/test/CodeGen/SystemZ/atomic-load-03.ll index 1fb41f5e39aa..7e5eb9249a93 100644 --- a/test/CodeGen/SystemZ/atomic-load-03.ll +++ b/test/CodeGen/SystemZ/atomic-load-03.ll @@ -2,12 +2,10 @@ ; ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -; This is just a placeholder to make sure that loads are handled. -; Using CS is probably too conservative. -define i32 @f1(i32 %dummy, i32 *%src) { +define i32 @f1(i32 *%src) { ; CHECK-LABEL: f1: -; CHECK: lhi %r2, 0 -; CHECK: cs %r2, %r2, 0(%r3) +; CHECK: bcr 1{{[45]}}, %r0 +; CHECK: l %r2, 0(%r2) ; CHECK: br %r14 %val = load atomic i32 *%src seq_cst, align 4 ret i32 %val diff --git a/test/CodeGen/SystemZ/atomic-load-04.ll b/test/CodeGen/SystemZ/atomic-load-04.ll index 92cac406e200..c7a9a98a425d 100644 --- a/test/CodeGen/SystemZ/atomic-load-04.ll +++ b/test/CodeGen/SystemZ/atomic-load-04.ll @@ -2,12 +2,10 @@ ; ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -; This is just a placeholder to make sure that loads are handled. -; Using CSG is probably too conservative. -define i64 @f1(i64 %dummy, i64 *%src) { +define i64 @f1(i64 *%src) { ; CHECK-LABEL: f1: -; CHECK: lghi %r2, 0 -; CHECK: csg %r2, %r2, 0(%r3) +; CHECK: bcr 1{{[45]}}, %r0 +; CHECK: lg %r2, 0(%r2) ; CHECK: br %r14 %val = load atomic i64 *%src seq_cst, align 8 ret i64 %val diff --git a/test/CodeGen/SystemZ/atomic-store-01.ll b/test/CodeGen/SystemZ/atomic-store-01.ll index 53ed24f623cf..952e1a912168 100644 --- a/test/CodeGen/SystemZ/atomic-store-01.ll +++ b/test/CodeGen/SystemZ/atomic-store-01.ll @@ -2,11 +2,10 @@ ; ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -; This is just a placeholder to make sure that stores are handled. -; The CS-based sequence is probably far too conservative. define void @f1(i8 %val, i8 *%src) { ; CHECK-LABEL: f1: -; CHECK: cs +; CHECK: stc %r2, 0(%r3) +; CHECK: bcr 1{{[45]}}, %r0 ; CHECK: br %r14 store atomic i8 %val, i8 *%src seq_cst, align 1 ret void diff --git a/test/CodeGen/SystemZ/atomic-store-02.ll b/test/CodeGen/SystemZ/atomic-store-02.ll index 42d6695b51d9..c9576e556566 100644 --- a/test/CodeGen/SystemZ/atomic-store-02.ll +++ b/test/CodeGen/SystemZ/atomic-store-02.ll @@ -2,11 +2,10 @@ ; ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -; This is just a placeholder to make sure that stores are handled. -; The CS-based sequence is probably far too conservative. define void @f1(i16 %val, i16 *%src) { ; CHECK-LABEL: f1: -; CHECK: cs +; CHECK: sth %r2, 0(%r3) +; CHECK: bcr 1{{[45]}}, %r0 ; CHECK: br %r14 store atomic i16 %val, i16 *%src seq_cst, align 2 ret void diff --git a/test/CodeGen/SystemZ/atomic-store-03.ll b/test/CodeGen/SystemZ/atomic-store-03.ll index 846c86fd3662..459cb6a94e12 100644 --- a/test/CodeGen/SystemZ/atomic-store-03.ll +++ b/test/CodeGen/SystemZ/atomic-store-03.ll @@ -2,14 +2,10 @@ ; ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -; This is just a placeholder to make sure that stores are handled. -; Using CS is probably too conservative. define void @f1(i32 %val, i32 *%src) { ; CHECK-LABEL: f1: -; CHECK: l %r0, 0(%r3) -; CHECK: [[LABEL:\.[^:]*]]: -; CHECK: cs %r0, %r2, 0(%r3) -; CHECK: jl [[LABEL]] +; CHECK: st %r2, 0(%r3) +; CHECK: bcr 1{{[45]}}, %r0 ; CHECK: br %r14 store atomic i32 %val, i32 *%src seq_cst, align 4 ret void diff --git a/test/CodeGen/SystemZ/atomic-store-04.ll b/test/CodeGen/SystemZ/atomic-store-04.ll index 24615b115658..7f2406eb5468 100644 --- a/test/CodeGen/SystemZ/atomic-store-04.ll +++ b/test/CodeGen/SystemZ/atomic-store-04.ll @@ -2,14 +2,10 @@ ; ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -; This is just a placeholder to make sure that stores are handled. -; Using CS is probably too conservative. define void @f1(i64 %val, i64 *%src) { ; CHECK-LABEL: f1: -; CHECK: lg %r0, 0(%r3) -; CHECK: [[LABEL:\.[^:]*]]: -; CHECK: csg %r0, %r2, 0(%r3) -; CHECK: jl [[LABEL]] +; CHECK: stg %r2, 0(%r3) +; CHECK: bcr 1{{[45]}}, %r0 ; CHECK: br %r14 store atomic i64 %val, i64 *%src seq_cst, align 8 ret void diff --git a/test/CodeGen/SystemZ/atomicrmw-add-05.ll b/test/CodeGen/SystemZ/atomicrmw-add-05.ll new file mode 100644 index 000000000000..956c0d9642cd --- /dev/null +++ b/test/CodeGen/SystemZ/atomicrmw-add-05.ll @@ -0,0 +1,64 @@ +; Test 32-bit atomic additions, z196 version. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check addition of a variable. +define i32 @f1(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f1: +; CHECK: laa %r2, %r4, 0(%r3) +; CHECK: br %r14 + %res = atomicrmw add i32 *%src, i32 %b seq_cst + ret i32 %res +} + +; Check addition of 1, which needs a temporary. +define i32 @f2(i32 %dummy, i32 *%src) { +; CHECK-LABEL: f2: +; CHECK: lhi [[TMP:%r[0-5]]], 1 +; CHECK: laa %r2, [[TMP]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw add i32 *%src, i32 1 seq_cst + ret i32 %res +} + +; Check the high end of the LAA range. +define i32 @f3(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f3: +; CHECK: laa %r2, %r4, 524284(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 131071 + %res = atomicrmw add i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the next word up, which needs separate address logic. +define i32 @f4(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f4: +; CHECK: agfi %r3, 524288 +; CHECK: laa %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 131072 + %res = atomicrmw add i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the low end of the LAA range. +define i32 @f5(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f5: +; CHECK: laa %r2, %r4, -524288(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 -131072 + %res = atomicrmw add i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the next word down, which needs separate address logic. +define i32 @f6(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f6: +; CHECK: agfi %r3, -524292 +; CHECK: laa %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 -131073 + %res = atomicrmw add i32 *%ptr, i32 %b seq_cst + ret i32 %res +} diff --git a/test/CodeGen/SystemZ/atomicrmw-add-06.ll b/test/CodeGen/SystemZ/atomicrmw-add-06.ll new file mode 100644 index 000000000000..f508858d1562 --- /dev/null +++ b/test/CodeGen/SystemZ/atomicrmw-add-06.ll @@ -0,0 +1,64 @@ +; Test 64-bit atomic additions, z196 version. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check addition of a variable. +define i64 @f1(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f1: +; CHECK: laag %r2, %r4, 0(%r3) +; CHECK: br %r14 + %res = atomicrmw add i64 *%src, i64 %b seq_cst + ret i64 %res +} + +; Check addition of 1, which needs a temporary. +define i64 @f2(i64 %dummy, i64 *%src) { +; CHECK-LABEL: f2: +; CHECK: lghi [[TMP:%r[0-5]]], 1 +; CHECK: laag %r2, [[TMP]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw add i64 *%src, i64 1 seq_cst + ret i64 %res +} + +; Check the high end of the LAAG range. +define i64 @f3(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f3: +; CHECK: laag %r2, %r4, 524280(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 65535 + %res = atomicrmw add i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the next doubleword up, which needs separate address logic. +define i64 @f4(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f4: +; CHECK: agfi %r3, 524288 +; CHECK: laag %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 65536 + %res = atomicrmw add i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the low end of the LAAG range. +define i64 @f5(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f5: +; CHECK: laag %r2, %r4, -524288(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 -65536 + %res = atomicrmw add i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the next doubleword down, which needs separate address logic. +define i64 @f6(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f6: +; CHECK: agfi %r3, -524296 +; CHECK: laag %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 -65537 + %res = atomicrmw add i64 *%ptr, i64 %b seq_cst + ret i64 %res +} diff --git a/test/CodeGen/SystemZ/atomicrmw-and-05.ll b/test/CodeGen/SystemZ/atomicrmw-and-05.ll new file mode 100644 index 000000000000..f0b999c60431 --- /dev/null +++ b/test/CodeGen/SystemZ/atomicrmw-and-05.ll @@ -0,0 +1,64 @@ +; Test 32-bit atomic ANDs, z196 version. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check AND of a variable. +define i32 @f1(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f1: +; CHECK: lan %r2, %r4, 0(%r3) +; CHECK: br %r14 + %res = atomicrmw and i32 *%src, i32 %b seq_cst + ret i32 %res +} + +; Check AND of 1, which needs a temporary. +define i32 @f2(i32 %dummy, i32 *%src) { +; CHECK-LABEL: f2: +; CHECK: lhi [[TMP:%r[0-5]]], 1 +; CHECK: lan %r2, [[TMP]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw and i32 *%src, i32 1 seq_cst + ret i32 %res +} + +; Check the high end of the LAN range. +define i32 @f3(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f3: +; CHECK: lan %r2, %r4, 524284(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 131071 + %res = atomicrmw and i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the next word up, which needs separate address logic. +define i32 @f4(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f4: +; CHECK: agfi %r3, 524288 +; CHECK: lan %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 131072 + %res = atomicrmw and i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the low end of the LAN range. +define i32 @f5(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f5: +; CHECK: lan %r2, %r4, -524288(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 -131072 + %res = atomicrmw and i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the next word down, which needs separate address logic. +define i32 @f6(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f6: +; CHECK: agfi %r3, -524292 +; CHECK: lan %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 -131073 + %res = atomicrmw and i32 *%ptr, i32 %b seq_cst + ret i32 %res +} diff --git a/test/CodeGen/SystemZ/atomicrmw-and-06.ll b/test/CodeGen/SystemZ/atomicrmw-and-06.ll new file mode 100644 index 000000000000..e5b71945d57c --- /dev/null +++ b/test/CodeGen/SystemZ/atomicrmw-and-06.ll @@ -0,0 +1,64 @@ +; Test 64-bit atomic ANDs, z196 version. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check AND of a variable. +define i64 @f1(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f1: +; CHECK: lang %r2, %r4, 0(%r3) +; CHECK: br %r14 + %res = atomicrmw and i64 *%src, i64 %b seq_cst + ret i64 %res +} + +; Check AND of -2, which needs a temporary. +define i64 @f2(i64 %dummy, i64 *%src) { +; CHECK-LABEL: f2: +; CHECK: lghi [[TMP:%r[0-5]]], -2 +; CHECK: lang %r2, [[TMP]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw and i64 *%src, i64 -2 seq_cst + ret i64 %res +} + +; Check the high end of the LANG range. +define i64 @f3(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f3: +; CHECK: lang %r2, %r4, 524280(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 65535 + %res = atomicrmw and i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the next doubleword up, which needs separate address logic. +define i64 @f4(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f4: +; CHECK: agfi %r3, 524288 +; CHECK: lang %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 65536 + %res = atomicrmw and i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the low end of the LANG range. +define i64 @f5(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f5: +; CHECK: lang %r2, %r4, -524288(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 -65536 + %res = atomicrmw and i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the next doubleword down, which needs separate address logic. +define i64 @f6(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f6: +; CHECK: agfi %r3, -524296 +; CHECK: lang %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 -65537 + %res = atomicrmw and i64 *%ptr, i64 %b seq_cst + ret i64 %res +} diff --git a/test/CodeGen/SystemZ/atomicrmw-or-05.ll b/test/CodeGen/SystemZ/atomicrmw-or-05.ll new file mode 100644 index 000000000000..b38654ca6f07 --- /dev/null +++ b/test/CodeGen/SystemZ/atomicrmw-or-05.ll @@ -0,0 +1,64 @@ +; Test 32-bit atomic ORs, z196 version. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check OR of a variable. +define i32 @f1(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f1: +; CHECK: lao %r2, %r4, 0(%r3) +; CHECK: br %r14 + %res = atomicrmw or i32 *%src, i32 %b seq_cst + ret i32 %res +} + +; Check OR of 1, which needs a temporary. +define i32 @f2(i32 %dummy, i32 *%src) { +; CHECK-LABEL: f2: +; CHECK: lhi [[TMP:%r[0-5]]], 1 +; CHECK: lao %r2, [[TMP]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw or i32 *%src, i32 1 seq_cst + ret i32 %res +} + +; Check the high end of the LAO range. +define i32 @f3(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f3: +; CHECK: lao %r2, %r4, 524284(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 131071 + %res = atomicrmw or i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the next word up, which needs separate address logic. +define i32 @f4(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f4: +; CHECK: agfi %r3, 524288 +; CHECK: lao %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 131072 + %res = atomicrmw or i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the low end of the LAO range. +define i32 @f5(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f5: +; CHECK: lao %r2, %r4, -524288(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 -131072 + %res = atomicrmw or i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the next word down, which needs separate address logic. +define i32 @f6(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f6: +; CHECK: agfi %r3, -524292 +; CHECK: lao %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 -131073 + %res = atomicrmw or i32 *%ptr, i32 %b seq_cst + ret i32 %res +} diff --git a/test/CodeGen/SystemZ/atomicrmw-or-06.ll b/test/CodeGen/SystemZ/atomicrmw-or-06.ll new file mode 100644 index 000000000000..30874abfe4a2 --- /dev/null +++ b/test/CodeGen/SystemZ/atomicrmw-or-06.ll @@ -0,0 +1,64 @@ +; Test 64-bit atomic ORs, z196 version. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check OR of a variable. +define i64 @f1(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f1: +; CHECK: laog %r2, %r4, 0(%r3) +; CHECK: br %r14 + %res = atomicrmw or i64 *%src, i64 %b seq_cst + ret i64 %res +} + +; Check OR of 1, which needs a temporary. +define i64 @f2(i64 %dummy, i64 *%src) { +; CHECK-LABEL: f2: +; CHECK: lghi [[TMP:%r[0-5]]], 1 +; CHECK: laog %r2, [[TMP]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw or i64 *%src, i64 1 seq_cst + ret i64 %res +} + +; Check the high end of the LAOG range. +define i64 @f3(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f3: +; CHECK: laog %r2, %r4, 524280(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 65535 + %res = atomicrmw or i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the next doubleword up, which needs separate address logic. +define i64 @f4(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f4: +; CHECK: agfi %r3, 524288 +; CHECK: laog %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 65536 + %res = atomicrmw or i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the low end of the LAOG range. +define i64 @f5(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f5: +; CHECK: laog %r2, %r4, -524288(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 -65536 + %res = atomicrmw or i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the next doubleword down, which needs separate address logic. +define i64 @f6(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f6: +; CHECK: agfi %r3, -524296 +; CHECK: laog %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 -65537 + %res = atomicrmw or i64 *%ptr, i64 %b seq_cst + ret i64 %res +} diff --git a/test/CodeGen/SystemZ/atomicrmw-sub-05.ll b/test/CodeGen/SystemZ/atomicrmw-sub-05.ll new file mode 100644 index 000000000000..7668f0e2a7ac --- /dev/null +++ b/test/CodeGen/SystemZ/atomicrmw-sub-05.ll @@ -0,0 +1,69 @@ +; Test 32-bit atomic subtractions, z196 version. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check addition of a variable. +define i32 @f1(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f1: +; CHECK: lcr [[NEG:%r[0-5]]], %r4 +; CHECK: laa %r2, [[NEG]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw sub i32 *%src, i32 %b seq_cst + ret i32 %res +} + +; Check addition of 1, which needs a temporary. +define i32 @f2(i32 %dummy, i32 *%src) { +; CHECK-LABEL: f2: +; CHECK: lhi [[TMP:%r[0-5]]], -1 +; CHECK: laa %r2, [[TMP]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw sub i32 *%src, i32 1 seq_cst + ret i32 %res +} + +; Check the high end of the LAA range. +define i32 @f3(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f3: +; CHECK: lcr [[NEG:%r[0-5]]], %r4 +; CHECK: laa %r2, [[NEG]], 524284(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 131071 + %res = atomicrmw sub i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the next word up, which needs separate address logic. +define i32 @f4(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f4: +; CHECK-DAG: lcr [[NEG:%r[0-5]]], %r4 +; CHECK-DAG: agfi %r3, 524288 +; CHECK: laa %r2, [[NEG]], 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 131072 + %res = atomicrmw sub i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the low end of the LAA range. +define i32 @f5(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f5: +; CHECK: lcr [[NEG:%r[0-5]]], %r4 +; CHECK: laa %r2, [[NEG]], -524288(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 -131072 + %res = atomicrmw sub i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the next word down, which needs separate address logic. +define i32 @f6(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f6: +; CHECK-DAG: lcr [[NEG:%r[0-5]]], %r4 +; CHECK-DAG: agfi %r3, -524292 +; CHECK: laa %r2, [[NEG]], 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 -131073 + %res = atomicrmw sub i32 *%ptr, i32 %b seq_cst + ret i32 %res +} diff --git a/test/CodeGen/SystemZ/atomicrmw-sub-06.ll b/test/CodeGen/SystemZ/atomicrmw-sub-06.ll new file mode 100644 index 000000000000..5d11bdf96cde --- /dev/null +++ b/test/CodeGen/SystemZ/atomicrmw-sub-06.ll @@ -0,0 +1,69 @@ +; Test 64-bit atomic subtractions, z196 version. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check addition of a variable. +define i64 @f1(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f1: +; CHECK: lcgr [[NEG:%r[0-5]]], %r4 +; CHECK: laag %r2, [[NEG]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw sub i64 *%src, i64 %b seq_cst + ret i64 %res +} + +; Check addition of 1, which needs a temporary. +define i64 @f2(i64 %dummy, i64 *%src) { +; CHECK-LABEL: f2: +; CHECK: lghi [[TMP:%r[0-5]]], -1 +; CHECK: laag %r2, [[TMP]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw sub i64 *%src, i64 1 seq_cst + ret i64 %res +} + +; Check the high end of the LAAG range. +define i64 @f3(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f3: +; CHECK: lcgr [[NEG:%r[0-5]]], %r4 +; CHECK: laag %r2, [[NEG]], 524280(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 65535 + %res = atomicrmw sub i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the next doubleword up, which needs separate address logic. +define i64 @f4(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f4: +; CHECK-DAG: lcgr [[NEG:%r[0-5]]], %r4 +; CHECK-DAG: agfi %r3, 524288 +; CHECK: laag %r2, [[NEG]], 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 65536 + %res = atomicrmw sub i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the low end of the LAAG range. +define i64 @f5(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f5: +; CHECK: lcgr [[NEG:%r[0-5]]], %r4 +; CHECK: laag %r2, [[NEG]], -524288(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 -65536 + %res = atomicrmw sub i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the next doubleword down, which needs separate address logic. +define i64 @f6(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f6: +; CHECK-DAG: lcgr [[NEG:%r[0-5]]], %r4 +; CHECK-DAG: agfi %r3, -524296 +; CHECK: laag %r2, [[NEG]], 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 -65537 + %res = atomicrmw sub i64 *%ptr, i64 %b seq_cst + ret i64 %res +} diff --git a/test/CodeGen/SystemZ/atomicrmw-xor-05.ll b/test/CodeGen/SystemZ/atomicrmw-xor-05.ll new file mode 100644 index 000000000000..e9e7d30b3578 --- /dev/null +++ b/test/CodeGen/SystemZ/atomicrmw-xor-05.ll @@ -0,0 +1,64 @@ +; Test 32-bit atomic ORs, z196 version. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check OR of a variable. +define i32 @f1(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f1: +; CHECK: lax %r2, %r4, 0(%r3) +; CHECK: br %r14 + %res = atomicrmw xor i32 *%src, i32 %b seq_cst + ret i32 %res +} + +; Check OR of 1, which needs a temporary. +define i32 @f2(i32 %dummy, i32 *%src) { +; CHECK-LABEL: f2: +; CHECK: lhi [[TMP:%r[0-5]]], 1 +; CHECK: lax %r2, [[TMP]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw xor i32 *%src, i32 1 seq_cst + ret i32 %res +} + +; Check the high end of the LAX range. +define i32 @f3(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f3: +; CHECK: lax %r2, %r4, 524284(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 131071 + %res = atomicrmw xor i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the next word up, which needs separate address logic. +define i32 @f4(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f4: +; CHECK: agfi %r3, 524288 +; CHECK: lax %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 131072 + %res = atomicrmw xor i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the low end of the LAX range. +define i32 @f5(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f5: +; CHECK: lax %r2, %r4, -524288(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 -131072 + %res = atomicrmw xor i32 *%ptr, i32 %b seq_cst + ret i32 %res +} + +; Check the next word down, which needs separate address logic. +define i32 @f6(i32 %dummy, i32 *%src, i32 %b) { +; CHECK-LABEL: f6: +; CHECK: agfi %r3, -524292 +; CHECK: lax %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i32 *%src, i32 -131073 + %res = atomicrmw xor i32 *%ptr, i32 %b seq_cst + ret i32 %res +} diff --git a/test/CodeGen/SystemZ/atomicrmw-xor-06.ll b/test/CodeGen/SystemZ/atomicrmw-xor-06.ll new file mode 100644 index 000000000000..0870c6476f61 --- /dev/null +++ b/test/CodeGen/SystemZ/atomicrmw-xor-06.ll @@ -0,0 +1,64 @@ +; Test 64-bit atomic XORs, z196 version. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check XOR of a variable. +define i64 @f1(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f1: +; CHECK: laxg %r2, %r4, 0(%r3) +; CHECK: br %r14 + %res = atomicrmw xor i64 *%src, i64 %b seq_cst + ret i64 %res +} + +; Check XOR of 1, which needs a temporary. +define i64 @f2(i64 %dummy, i64 *%src) { +; CHECK-LABEL: f2: +; CHECK: lghi [[TMP:%r[0-5]]], 1 +; CHECK: laxg %r2, [[TMP]], 0(%r3) +; CHECK: br %r14 + %res = atomicrmw xor i64 *%src, i64 1 seq_cst + ret i64 %res +} + +; Check the high end of the LAXG range. +define i64 @f3(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f3: +; CHECK: laxg %r2, %r4, 524280(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 65535 + %res = atomicrmw xor i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the next doubleword up, which needs separate address logic. +define i64 @f4(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f4: +; CHECK: agfi %r3, 524288 +; CHECK: laxg %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 65536 + %res = atomicrmw xor i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the low end of the LAXG range. +define i64 @f5(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f5: +; CHECK: laxg %r2, %r4, -524288(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 -65536 + %res = atomicrmw xor i64 *%ptr, i64 %b seq_cst + ret i64 %res +} + +; Check the next doubleword down, which needs separate address logic. +define i64 @f6(i64 %dummy, i64 *%src, i64 %b) { +; CHECK-LABEL: f6: +; CHECK: agfi %r3, -524296 +; CHECK: laxg %r2, %r4, 0(%r3) +; CHECK: br %r14 + %ptr = getelementptr i64 *%src, i64 -65537 + %res = atomicrmw xor i64 *%ptr, i64 %b seq_cst + ret i64 %res +} diff --git a/test/CodeGen/SystemZ/cmpxchg-01.ll b/test/CodeGen/SystemZ/cmpxchg-01.ll index d5ea97786900..5118aadcf2ad 100644 --- a/test/CodeGen/SystemZ/cmpxchg-01.ll +++ b/test/CodeGen/SystemZ/cmpxchg-01.ll @@ -32,7 +32,8 @@ define i8 @f1(i8 %dummy, i8 *%src, i8 %cmp, i8 %swap) { ; CHECK-SHIFT: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]] ; CHECK-SHIFT: rll ; CHECK-SHIFT: rll {{%r[0-9]+}}, %r5, -8([[NEGSHIFT]]) - %res = cmpxchg i8 *%src, i8 %cmp, i8 %swap seq_cst + %pair = cmpxchg i8 *%src, i8 %cmp, i8 %swap seq_cst seq_cst + %res = extractvalue { i8, i1 } %pair, 0 ret i8 %res } @@ -50,6 +51,7 @@ define i8 @f2(i8 *%src) { ; CHECK-SHIFT: risbg ; CHECK-SHIFT: risbg [[SWAP]], {{%r[0-9]+}}, 32, 55, 0 ; CHECK-SHIFT: br %r14 - %res = cmpxchg i8 *%src, i8 42, i8 88 seq_cst + %pair = cmpxchg i8 *%src, i8 42, i8 88 seq_cst seq_cst + %res = extractvalue { i8, i1 } %pair, 0 ret i8 %res } diff --git a/test/CodeGen/SystemZ/cmpxchg-02.ll b/test/CodeGen/SystemZ/cmpxchg-02.ll index 08c79d717c1e..9eb0628b5a30 100644 --- a/test/CodeGen/SystemZ/cmpxchg-02.ll +++ b/test/CodeGen/SystemZ/cmpxchg-02.ll @@ -32,7 +32,8 @@ define i16 @f1(i16 %dummy, i16 *%src, i16 %cmp, i16 %swap) { ; CHECK-SHIFT: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]] ; CHECK-SHIFT: rll ; CHECK-SHIFT: rll {{%r[0-9]+}}, %r5, -16([[NEGSHIFT]]) - %res = cmpxchg i16 *%src, i16 %cmp, i16 %swap seq_cst + %pair = cmpxchg i16 *%src, i16 %cmp, i16 %swap seq_cst seq_cst + %res = extractvalue { i16, i1 } %pair, 0 ret i16 %res } @@ -50,6 +51,7 @@ define i16 @f2(i16 *%src) { ; CHECK-SHIFT: risbg ; CHECK-SHIFT: risbg [[SWAP]], {{%r[0-9]+}}, 32, 47, 0 ; CHECK-SHIFT: br %r14 - %res = cmpxchg i16 *%src, i16 42, i16 88 seq_cst + %pair = cmpxchg i16 *%src, i16 42, i16 88 seq_cst seq_cst + %res = extractvalue { i16, i1 } %pair, 0 ret i16 %res } diff --git a/test/CodeGen/SystemZ/cmpxchg-03.ll b/test/CodeGen/SystemZ/cmpxchg-03.ll index 3917979ac24c..c5fab4dc0439 100644 --- a/test/CodeGen/SystemZ/cmpxchg-03.ll +++ b/test/CodeGen/SystemZ/cmpxchg-03.ll @@ -7,7 +7,8 @@ define i32 @f1(i32 %cmp, i32 %swap, i32 *%src) { ; CHECK-LABEL: f1: ; CHECK: cs %r2, %r3, 0(%r4) ; CHECK: br %r14 - %val = cmpxchg i32 *%src, i32 %cmp, i32 %swap seq_cst + %pair = cmpxchg i32 *%src, i32 %cmp, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -17,7 +18,8 @@ define i32 @f2(i32 %cmp, i32 %swap, i32 *%src) { ; CHECK: cs %r2, %r3, 4092(%r4) ; CHECK: br %r14 %ptr = getelementptr i32 *%src, i64 1023 - %val = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst + %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -27,7 +29,8 @@ define i32 @f3(i32 %cmp, i32 %swap, i32 *%src) { ; CHECK: csy %r2, %r3, 4096(%r4) ; CHECK: br %r14 %ptr = getelementptr i32 *%src, i64 1024 - %val = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst + %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -37,7 +40,8 @@ define i32 @f4(i32 %cmp, i32 %swap, i32 *%src) { ; CHECK: csy %r2, %r3, 524284(%r4) ; CHECK: br %r14 %ptr = getelementptr i32 *%src, i64 131071 - %val = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst + %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -49,7 +53,8 @@ define i32 @f5(i32 %cmp, i32 %swap, i32 *%src) { ; CHECK: cs %r2, %r3, 0(%r4) ; CHECK: br %r14 %ptr = getelementptr i32 *%src, i64 131072 - %val = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst + %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -59,7 +64,8 @@ define i32 @f6(i32 %cmp, i32 %swap, i32 *%src) { ; CHECK: csy %r2, %r3, -4(%r4) ; CHECK: br %r14 %ptr = getelementptr i32 *%src, i64 -1 - %val = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst + %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -69,7 +75,8 @@ define i32 @f7(i32 %cmp, i32 %swap, i32 *%src) { ; CHECK: csy %r2, %r3, -524288(%r4) ; CHECK: br %r14 %ptr = getelementptr i32 *%src, i64 -131072 - %val = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst + %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -81,7 +88,8 @@ define i32 @f8(i32 %cmp, i32 %swap, i32 *%src) { ; CHECK: cs %r2, %r3, 0(%r4) ; CHECK: br %r14 %ptr = getelementptr i32 *%src, i64 -131073 - %val = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst + %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -93,7 +101,8 @@ define i32 @f9(i32 %cmp, i32 %swap, i64 %src, i64 %index) { ; CHECK: br %r14 %add1 = add i64 %src, %index %ptr = inttoptr i64 %add1 to i32 * - %val = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst + %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -106,7 +115,8 @@ define i32 @f10(i32 %cmp, i32 %swap, i64 %src, i64 %index) { %add1 = add i64 %src, %index %add2 = add i64 %add1, 4096 %ptr = inttoptr i64 %add2 to i32 * - %val = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst + %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -116,7 +126,8 @@ define i32 @f11(i32 %dummy, i32 %swap, i32 *%ptr) { ; CHECK: lhi %r2, 1001 ; CHECK: cs %r2, %r3, 0(%r4) ; CHECK: br %r14 - %val = cmpxchg i32 *%ptr, i32 1001, i32 %swap seq_cst + %pair = cmpxchg i32 *%ptr, i32 1001, i32 %swap seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } @@ -126,6 +137,7 @@ define i32 @f12(i32 %cmp, i32 *%ptr) { ; CHECK: lhi [[SWAP:%r[0-9]+]], 1002 ; CHECK: cs %r2, [[SWAP]], 0(%r3) ; CHECK: br %r14 - %val = cmpxchg i32 *%ptr, i32 %cmp, i32 1002 seq_cst + %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 1002 seq_cst seq_cst + %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val } diff --git a/test/CodeGen/SystemZ/cmpxchg-04.ll b/test/CodeGen/SystemZ/cmpxchg-04.ll index f58868f04f2d..ba1493e1853e 100644 --- a/test/CodeGen/SystemZ/cmpxchg-04.ll +++ b/test/CodeGen/SystemZ/cmpxchg-04.ll @@ -7,7 +7,8 @@ define i64 @f1(i64 %cmp, i64 %swap, i64 *%src) { ; CHECK-LABEL: f1: ; CHECK: csg %r2, %r3, 0(%r4) ; CHECK: br %r14 - %val = cmpxchg i64 *%src, i64 %cmp, i64 %swap seq_cst + %pairval = cmpxchg i64 *%src, i64 %cmp, i64 %swap seq_cst seq_cst + %val = extractvalue { i64, i1 } %pairval, 0 ret i64 %val } @@ -17,7 +18,8 @@ define i64 @f2(i64 %cmp, i64 %swap, i64 *%src) { ; CHECK: csg %r2, %r3, 524280(%r4) ; CHECK: br %r14 %ptr = getelementptr i64 *%src, i64 65535 - %val = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst + %pairval = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst seq_cst + %val = extractvalue { i64, i1 } %pairval, 0 ret i64 %val } @@ -29,7 +31,8 @@ define i64 @f3(i64 %cmp, i64 %swap, i64 *%src) { ; CHECK: csg %r2, %r3, 0(%r4) ; CHECK: br %r14 %ptr = getelementptr i64 *%src, i64 65536 - %val = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst + %pairval = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst seq_cst + %val = extractvalue { i64, i1 } %pairval, 0 ret i64 %val } @@ -39,7 +42,8 @@ define i64 @f4(i64 %cmp, i64 %swap, i64 *%src) { ; CHECK: csg %r2, %r3, -8(%r4) ; CHECK: br %r14 %ptr = getelementptr i64 *%src, i64 -1 - %val = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst + %pairval = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst seq_cst + %val = extractvalue { i64, i1 } %pairval, 0 ret i64 %val } @@ -49,7 +53,8 @@ define i64 @f5(i64 %cmp, i64 %swap, i64 *%src) { ; CHECK: csg %r2, %r3, -524288(%r4) ; CHECK: br %r14 %ptr = getelementptr i64 *%src, i64 -65536 - %val = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst + %pairval = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst seq_cst + %val = extractvalue { i64, i1 } %pairval, 0 ret i64 %val } @@ -61,7 +66,8 @@ define i64 @f6(i64 %cmp, i64 %swap, i64 *%src) { ; CHECK: csg %r2, %r3, 0(%r4) ; CHECK: br %r14 %ptr = getelementptr i64 *%src, i64 -65537 - %val = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst + %pairval = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst seq_cst + %val = extractvalue { i64, i1 } %pairval, 0 ret i64 %val } @@ -73,7 +79,8 @@ define i64 @f7(i64 %cmp, i64 %swap, i64 %src, i64 %index) { ; CHECK: br %r14 %add1 = add i64 %src, %index %ptr = inttoptr i64 %add1 to i64 * - %val = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst + %pairval = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst seq_cst + %val = extractvalue { i64, i1 } %pairval, 0 ret i64 %val } @@ -83,7 +90,8 @@ define i64 @f8(i64 %dummy, i64 %swap, i64 *%ptr) { ; CHECK: lghi %r2, 1001 ; CHECK: csg %r2, %r3, 0(%r4) ; CHECK: br %r14 - %val = cmpxchg i64 *%ptr, i64 1001, i64 %swap seq_cst + %pairval = cmpxchg i64 *%ptr, i64 1001, i64 %swap seq_cst seq_cst + %val = extractvalue { i64, i1 } %pairval, 0 ret i64 %val } @@ -93,6 +101,7 @@ define i64 @f9(i64 %cmp, i64 *%ptr) { ; CHECK: lghi [[SWAP:%r[0-9]+]], 1002 ; CHECK: csg %r2, [[SWAP]], 0(%r3) ; CHECK: br %r14 - %val = cmpxchg i64 *%ptr, i64 %cmp, i64 1002 seq_cst + %pairval = cmpxchg i64 *%ptr, i64 %cmp, i64 1002 seq_cst seq_cst + %val = extractvalue { i64, i1 } %pairval, 0 ret i64 %val } diff --git a/test/CodeGen/SystemZ/cond-store-01.ll b/test/CodeGen/SystemZ/cond-store-01.ll index d55ea2133e8f..62e9796fa21b 100644 --- a/test/CodeGen/SystemZ/cond-store-01.ll +++ b/test/CodeGen/SystemZ/cond-store-01.ll @@ -347,11 +347,10 @@ define void @f19(i8 *%ptr, i8 %alt, i32 %limit) { define void @f20(i8 *%ptr, i8 %alt, i32 %limit) { ; FIXME: should use a normal load instead of CS. ; CHECK-LABEL: f20: -; CHECK: cs {{%r[0-9]+}}, -; CHECK: jl +; CHECK: lb {{%r[0-9]+}}, 0(%r2) ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]] ; CHECK: [[LABEL]]: -; CHECK: stc {{%r[0-9]+}}, +; CHECK: stc {{%r[0-9]+}}, 0(%r2) ; CHECK: br %r14 %cond = icmp ult i32 %limit, 420 %orig = load atomic i8 *%ptr unordered, align 1 @@ -367,7 +366,7 @@ define void @f21(i8 *%ptr, i8 %alt, i32 %limit) { ; CHECK: jhe [[LABEL:[^ ]*]] ; CHECK: lb %r3, 0(%r2) ; CHECK: [[LABEL]]: -; CHECK: cs {{%r[0-9]+}}, +; CHECK: stc %r3, 0(%r2) ; CHECK: br %r14 %cond = icmp ult i32 %limit, 420 %orig = load i8 *%ptr diff --git a/test/CodeGen/SystemZ/cond-store-02.ll b/test/CodeGen/SystemZ/cond-store-02.ll index 91bc4860b384..4fbcdaba5103 100644 --- a/test/CodeGen/SystemZ/cond-store-02.ll +++ b/test/CodeGen/SystemZ/cond-store-02.ll @@ -347,11 +347,10 @@ define void @f19(i16 *%ptr, i16 %alt, i32 %limit) { define void @f20(i16 *%ptr, i16 %alt, i32 %limit) { ; FIXME: should use a normal load instead of CS. ; CHECK-LABEL: f20: -; CHECK: cs {{%r[0-9]+}}, -; CHECK: jl +; CHECK: lh {{%r[0-9]+}}, 0(%r2) ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]] ; CHECK: [[LABEL]]: -; CHECK: sth {{%r[0-9]+}}, +; CHECK: sth {{%r[0-9]+}}, 0(%r2) ; CHECK: br %r14 %cond = icmp ult i32 %limit, 420 %orig = load atomic i16 *%ptr unordered, align 2 @@ -367,7 +366,7 @@ define void @f21(i16 *%ptr, i16 %alt, i32 %limit) { ; CHECK: jhe [[LABEL:[^ ]*]] ; CHECK: lh %r3, 0(%r2) ; CHECK: [[LABEL]]: -; CHECK: cs {{%r[0-9]+}}, +; CHECK: sth %r3, 0(%r2) ; CHECK: br %r14 %cond = icmp ult i32 %limit, 420 %orig = load i16 *%ptr diff --git a/test/CodeGen/SystemZ/cond-store-03.ll b/test/CodeGen/SystemZ/cond-store-03.ll index d4fd48d61324..4b22555d0d60 100644 --- a/test/CodeGen/SystemZ/cond-store-03.ll +++ b/test/CodeGen/SystemZ/cond-store-03.ll @@ -272,7 +272,7 @@ define void @f15(i32 *%ptr, i32 %alt, i32 %limit) { define void @f16(i32 *%ptr, i32 %alt, i32 %limit) { ; FIXME: should use a normal load instead of CS. ; CHECK-LABEL: f16: -; CHECK: cs {{%r[0-5]}}, {{%r[0-5]}}, 0(%r2) +; CHECK: l {{%r[0-5]}}, 0(%r2) ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]] ; CHECK: [[LABEL]]: ; CHECK: st {{%r[0-5]}}, 0(%r2) @@ -291,7 +291,7 @@ define void @f17(i32 *%ptr, i32 %alt, i32 %limit) { ; CHECK: jhe [[LABEL:[^ ]*]] ; CHECK: l %r3, 0(%r2) ; CHECK: [[LABEL]]: -; CHECK: cs {{%r[0-5]}}, %r3, 0(%r2) +; CHECK: st %r3, 0(%r2) ; CHECK: br %r14 %cond = icmp ult i32 %limit, 420 %orig = load i32 *%ptr diff --git a/test/CodeGen/SystemZ/cond-store-04.ll b/test/CodeGen/SystemZ/cond-store-04.ll index fc565c432fff..346b51a17d78 100644 --- a/test/CodeGen/SystemZ/cond-store-04.ll +++ b/test/CodeGen/SystemZ/cond-store-04.ll @@ -164,7 +164,7 @@ define void @f9(i64 *%ptr, i64 %alt, i32 %limit) { define void @f10(i64 *%ptr, i64 %alt, i32 %limit) { ; FIXME: should use a normal load instead of CSG. ; CHECK-LABEL: f10: -; CHECK: csg {{%r[0-5]}}, {{%r[0-5]}}, 0(%r2) +; CHECK: lg {{%r[0-5]}}, 0(%r2) ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]] ; CHECK: [[LABEL]]: ; CHECK: stg {{%r[0-5]}}, 0(%r2) @@ -183,7 +183,7 @@ define void @f11(i64 *%ptr, i64 %alt, i32 %limit) { ; CHECK: jhe [[LABEL:[^ ]*]] ; CHECK: lg %r3, 0(%r2) ; CHECK: [[LABEL]]: -; CHECK: csg {{%r[0-5]}}, %r3, 0(%r2) +; CHECK: stg %r3, 0(%r2) ; CHECK: br %r14 %cond = icmp ult i32 %limit, 420 %orig = load i64 *%ptr diff --git a/test/CodeGen/SystemZ/fp-cmp-04.ll b/test/CodeGen/SystemZ/fp-cmp-04.ll index 8d842164fa4f..781a3beb4d4d 100644 --- a/test/CodeGen/SystemZ/fp-cmp-04.ll +++ b/test/CodeGen/SystemZ/fp-cmp-04.ll @@ -1,4 +1,4 @@ -; Test that floating-point compares are ommitted if CC already has the +; Test that floating-point compares are omitted if CC already has the ; right value. ; ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s @@ -346,3 +346,62 @@ store: exit: ret double %val } + +; Repeat f2 with a comparison against -0. +define float @f17(float %a, float %b, float *%dest) { +; CHECK-LABEL: f17: +; CHECK: aebr %f0, %f2 +; CHECK-NEXT: jl .L{{.*}} +; CHECK: br %r14 +entry: + %res = fadd float %a, %b + %cmp = fcmp olt float %res, -0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %b, float *%dest + br label %exit + +exit: + ret float %res +} + +; Test another form of f7 in which the condition is based on the unnegated +; result. This is what InstCombine would produce. +define float @f18(float %dummy, float %a, float *%dest) { +; CHECK-LABEL: f18: +; CHECK: lnebr %f0, %f2 +; CHECK-NEXT: jl .L{{.*}} +; CHECK: br %r14 +entry: + %abs = call float @llvm.fabs.f32(float %a) + %res = fsub float -0.0, %abs + %cmp = fcmp ogt float %abs, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %res, float *%dest + br label %exit + +exit: + ret float %res +} + +; Similarly for f8. +define float @f19(float %dummy, float %a, float *%dest) { +; CHECK-LABEL: f19: +; CHECK: lcebr %f0, %f2 +; CHECK-NEXT: jle .L{{.*}} +; CHECK: br %r14 +entry: + %res = fsub float -0.0, %a + %cmp = fcmp oge float %a, 0.0 + br i1 %cmp, label %exit, label %store + +store: + store float %res, float *%dest + br label %exit + +exit: + ret float %res +} diff --git a/test/CodeGen/SystemZ/fp-conv-06.ll b/test/CodeGen/SystemZ/fp-conv-06.ll index 466c1456a0cb..8a3971a9929c 100644 --- a/test/CodeGen/SystemZ/fp-conv-06.ll +++ b/test/CodeGen/SystemZ/fp-conv-06.ll @@ -1,6 +1,6 @@ -; Test conversions of unsigned i32s to floating-point values. +; Test conversions of unsigned i32s to floating-point values (z10 only). ; -; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s ; Check i32->f32. There is no native instruction, so we must promote ; to i64 first. diff --git a/test/CodeGen/SystemZ/fp-conv-08.ll b/test/CodeGen/SystemZ/fp-conv-08.ll index 69b2d13e29f0..295ce8bdbe2c 100644 --- a/test/CodeGen/SystemZ/fp-conv-08.ll +++ b/test/CodeGen/SystemZ/fp-conv-08.ll @@ -1,6 +1,6 @@ -; Test conversions of unsigned i64s to floating-point values. +; Test conversions of unsigned i64s to floating-point values (z10 only). ; -; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s ; Test i64->f32. There's no native support for unsigned i64-to-fp conversions, ; but we should be able to implement them using signed i64-to-fp conversions. diff --git a/test/CodeGen/SystemZ/fp-conv-10.ll b/test/CodeGen/SystemZ/fp-conv-10.ll index 723d19d2a1de..b8155ed067da 100644 --- a/test/CodeGen/SystemZ/fp-conv-10.ll +++ b/test/CodeGen/SystemZ/fp-conv-10.ll @@ -1,6 +1,6 @@ -; Test conversion of floating-point values to unsigned i32s. +; Test conversion of floating-point values to unsigned i32s (z10 only). ; -; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s ; z10 doesn't have native support for unsigned fp-to-i32 conversions; ; they were added in z196 as the Convert to Logical family of instructions. diff --git a/test/CodeGen/SystemZ/fp-conv-12.ll b/test/CodeGen/SystemZ/fp-conv-12.ll index 6cc343abdafc..770c9407a0af 100644 --- a/test/CodeGen/SystemZ/fp-conv-12.ll +++ b/test/CodeGen/SystemZ/fp-conv-12.ll @@ -1,6 +1,6 @@ -; Test conversion of floating-point values to unsigned i64s. +; Test conversion of floating-point values to unsigned i64s (z10 only). ; -; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s ; z10 doesn't have native support for unsigned fp-to-i64 conversions; ; they were added in z196 as the Convert to Logical family of instructions. diff --git a/test/CodeGen/SystemZ/fp-conv-13.ll b/test/CodeGen/SystemZ/fp-conv-13.ll new file mode 100644 index 000000000000..96293bc8d270 --- /dev/null +++ b/test/CodeGen/SystemZ/fp-conv-13.ll @@ -0,0 +1,64 @@ +; Test conversions of unsigned integers to floating-point values +; (z196 and above). +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check i32->f32. +define float @f1(i32 %i) { +; CHECK-LABEL: f1: +; CHECK: celfbr %f0, 0, %r2, 0 +; CHECK: br %r14 + %conv = uitofp i32 %i to float + ret float %conv +} + +; Check i32->f64. +define double @f2(i32 %i) { +; CHECK-LABEL: f2: +; CHECK: cdlfbr %f0, 0, %r2, 0 +; CHECK: br %r14 + %conv = uitofp i32 %i to double + ret double %conv +} + +; Check i32->f128. +define void @f3(i32 %i, fp128 *%dst) { +; CHECK-LABEL: f3: +; CHECK: cxlfbr %f0, 0, %r2, 0 +; CHECK-DAG: std %f0, 0(%r3) +; CHECK-DAG: std %f2, 8(%r3) +; CHECK: br %r14 + %conv = uitofp i32 %i to fp128 + store fp128 %conv, fp128 *%dst + ret void +} + +; Check i64->f32. +define float @f4(i64 %i) { +; CHECK-LABEL: f4: +; CHECK: celgbr %f0, 0, %r2, 0 +; CHECK: br %r14 + %conv = uitofp i64 %i to float + ret float %conv +} + +; Check i64->f64. +define double @f5(i64 %i) { +; CHECK-LABEL: f5: +; CHECK: cdlgbr %f0, 0, %r2, 0 +; CHECK: br %r14 + %conv = uitofp i64 %i to double + ret double %conv +} + +; Check i64->f128. +define void @f6(i64 %i, fp128 *%dst) { +; CHECK-LABEL: f6: +; CHECK: cxlgbr %f0, 0, %r2, 0 +; CHECK-DAG: std %f0, 0(%r3) +; CHECK-DAG: std %f2, 8(%r3) +; CHECK: br %r14 + %conv = uitofp i64 %i to fp128 + store fp128 %conv, fp128 *%dst + ret void +} diff --git a/test/CodeGen/SystemZ/fp-conv-14.ll b/test/CodeGen/SystemZ/fp-conv-14.ll new file mode 100644 index 000000000000..e926e9bb31f5 --- /dev/null +++ b/test/CodeGen/SystemZ/fp-conv-14.ll @@ -0,0 +1,63 @@ +; Test conversion of floating-point values to unsigned integers. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Test f32->i32. +define i32 @f1(float %f) { +; CHECK-LABEL: f1: +; CHECK: clfebr %r2, 5, %f0, 0 +; CHECK: br %r14 + %conv = fptoui float %f to i32 + ret i32 %conv +} + +; Test f64->i32. +define i32 @f2(double %f) { +; CHECK-LABEL: f2: +; CHECK: clfdbr %r2, 5, %f0, 0 +; CHECK: br %r14 + %conv = fptoui double %f to i32 + ret i32 %conv +} + +; Test f128->i32. +define i32 @f3(fp128 *%src) { +; CHECK-LABEL: f3: +; CHECK-DAG: ld %f0, 0(%r2) +; CHECK-DAG: ld %f2, 8(%r2) +; CHECK: clfxbr %r2, 5, %f0, 0 +; CHECK: br %r14 + %f = load fp128 *%src + %conv = fptoui fp128 %f to i32 + ret i32 %conv +} + +; Test f32->i64. +define i64 @f4(float %f) { +; CHECK-LABEL: f4: +; CHECK: clgebr %r2, 5, %f0, 0 +; CHECK: br %r14 + %conv = fptoui float %f to i64 + ret i64 %conv +} + +; Test f64->i64. +define i64 @f5(double %f) { +; CHECK-LABEL: f5: +; CHECK: clgdbr %r2, 5, %f0, 0 +; CHECK: br %r14 + %conv = fptoui double %f to i64 + ret i64 %conv +} + +; Test f128->i64. +define i64 @f6(fp128 *%src) { +; CHECK-LABEL: f6: +; CHECK-DAG: ld %f0, 0(%r2) +; CHECK-DAG: ld %f2, 8(%r2) +; CHECK: clgxbr %r2, 5, %f0, 0 +; CHECK: br %r14 + %f = load fp128 *%src + %conv = fptoui fp128 %f to i64 + ret i64 %conv +} diff --git a/test/CodeGen/SystemZ/frame-08.ll b/test/CodeGen/SystemZ/frame-08.ll index da2a6142fb47..aa4e3f481da4 100644 --- a/test/CodeGen/SystemZ/frame-08.ll +++ b/test/CodeGen/SystemZ/frame-08.ll @@ -208,7 +208,7 @@ define void @f4(i32 *%ptr, i64 %x) { ret void } -; This is the largest frame size for which the prepatory increment for +; This is the largest frame size for which the preparatory increment for ; "lmg %r14, %r15, ..." can be done using AGHI. define void @f5(i32 *%ptr, i64 %x) { ; CHECK-LABEL: f5: @@ -242,7 +242,7 @@ define void @f5(i32 *%ptr, i64 %x) { ret void } -; This is the smallest frame size for which the prepatory increment for +; This is the smallest frame size for which the preparatory increment for ; "lmg %r14, %r15, ..." needs to be done using AGFI. define void @f6(i32 *%ptr, i64 %x) { ; CHECK-LABEL: f6: diff --git a/test/CodeGen/SystemZ/frame-11.ll b/test/CodeGen/SystemZ/frame-11.ll index 5145b4d1c862..575a4335d5da 100644 --- a/test/CodeGen/SystemZ/frame-11.ll +++ b/test/CodeGen/SystemZ/frame-11.ll @@ -2,17 +2,24 @@ ; ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s +declare i8 *@llvm.stacksave() declare void @llvm.stackrestore(i8 *) ; we should use a frame pointer and tear down the frame based on %r11 ; rather than %r15. -define void @f1(i8 *%src) { +define void @f1(i32 %count1, i32 %count2) { ; CHECK-LABEL: f1: ; CHECK: stmg %r11, %r15, 88(%r15) +; CHECK: aghi %r15, -160 ; CHECK: lgr %r11, %r15 -; CHECK: lgr %r15, %r2 -; CHECK: lmg %r11, %r15, 88(%r11) +; CHECK: lgr %r15, %r{{[0-5]}} +; CHECK: lmg %r11, %r15, 248(%r11) ; CHECK: br %r14 + %src = call i8 *@llvm.stacksave() + %array1 = alloca i8, i32 %count1 + store volatile i8 0, i8 *%array1 call void @llvm.stackrestore(i8 *%src) + %array2 = alloca i8, i32 %count2 + store volatile i8 0, i8 *%array2 ret void } diff --git a/test/CodeGen/SystemZ/frame-13.ll b/test/CodeGen/SystemZ/frame-13.ll index 393850fbf617..58dee1da58b5 100644 --- a/test/CodeGen/SystemZ/frame-13.ll +++ b/test/CodeGen/SystemZ/frame-13.ll @@ -243,8 +243,8 @@ define void @f10(i32 *%vptr) { ; And again with maximum register pressure. The only spill slots that the ; NOFP case needs are the emergency ones, so the offsets are the same as for f2. -; However, the FP case uses %r11 as the frame pointer and must therefore -; spill a second register. This leads to an extra displacement of 8. +; The FP case needs to spill an extra register and is too dependent on +; register allocation heuristics for a stable test. define void @f11(i32 *%vptr) { ; CHECK-NOFP-LABEL: f11: ; CHECK-NOFP: stmg %r6, %r15, @@ -254,15 +254,6 @@ define void @f11(i32 *%vptr) { ; CHECK-NOFP: lg [[REGISTER]], [[OFFSET]](%r15) ; CHECK-NOFP: lmg %r6, %r15, ; CHECK-NOFP: br %r14 -; -; CHECK-FP-LABEL: f11: -; CHECK-FP: stmg %r6, %r15, -; CHECK-FP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r11) -; CHECK-FP: lay [[REGISTER]], 4096(%r11) -; CHECK-FP: mvhi 8([[REGISTER]]), 42 -; CHECK-FP: lg [[REGISTER]], [[OFFSET]](%r11) -; CHECK-FP: lmg %r6, %r15, -; CHECK-FP: br %r14 %i0 = load volatile i32 *%vptr %i1 = load volatile i32 *%vptr %i3 = load volatile i32 *%vptr diff --git a/test/CodeGen/SystemZ/frame-14.ll b/test/CodeGen/SystemZ/frame-14.ll index 3b48179c40b6..24169cf61f00 100644 --- a/test/CodeGen/SystemZ/frame-14.ll +++ b/test/CodeGen/SystemZ/frame-14.ll @@ -266,8 +266,8 @@ define void @f10(i32 *%vptr) { ; And again with maximum register pressure. The only spill slots that the ; NOFP case needs are the emergency ones, so the offsets are the same as for f4. -; However, the FP case uses %r11 as the frame pointer and must therefore -; spill a second register. This leads to an extra displacement of 8. +; The FP case needs to spill an extra register and is too dependent on +; register allocation heuristics for a stable test. define void @f11(i32 *%vptr) { ; CHECK-NOFP-LABEL: f11: ; CHECK-NOFP: stmg %r6, %r15, @@ -278,16 +278,6 @@ define void @f11(i32 *%vptr) { ; CHECK-NOFP: lg [[REGISTER]], [[OFFSET]](%r15) ; CHECK-NOFP: lmg %r6, %r15, ; CHECK-NOFP: br %r14 -; -; CHECK-FP-LABEL: f11: -; CHECK-FP: stmg %r6, %r15, -; CHECK-FP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r11) -; CHECK-FP: llilh [[REGISTER]], 8 -; CHECK-FP: agr [[REGISTER]], %r11 -; CHECK-FP: mvi 8([[REGISTER]]), 42 -; CHECK-FP: lg [[REGISTER]], [[OFFSET]](%r11) -; CHECK-FP: lmg %r6, %r15, -; CHECK-FP: br %r14 %i0 = load volatile i32 *%vptr %i1 = load volatile i32 *%vptr %i3 = load volatile i32 *%vptr diff --git a/test/CodeGen/SystemZ/insert-06.ll b/test/CodeGen/SystemZ/insert-06.ll index edcd0c5dccd2..81a9c8770708 100644 --- a/test/CodeGen/SystemZ/insert-06.ll +++ b/test/CodeGen/SystemZ/insert-06.ll @@ -178,3 +178,17 @@ define i64 @f14(i64 %a, i64 %b) { %ext = sext i1 %res to i64 ret i64 %ext } + +; Check another representation of f8. +define i64 @f15(i64 %a, i8 *%src) { +; CHECK-LABEL: f15: +; CHECK-NOT: {{%r[23]}} +; CHECK: lb %r2, 0(%r3) +; CHECK: br %r14 + %byte = load i8 *%src + %b = sext i8 %byte to i64 + %low = and i64 %b, 4294967295 + %high = and i64 %a, -4294967296 + %res = or i64 %high, %low + ret i64 %res +} diff --git a/test/CodeGen/SystemZ/int-abs-01.ll b/test/CodeGen/SystemZ/int-abs-01.ll index 40fb61192c6e..053c347c0b75 100644 --- a/test/CodeGen/SystemZ/int-abs-01.ll +++ b/test/CodeGen/SystemZ/int-abs-01.ll @@ -81,3 +81,67 @@ define i64 @f7(i64 %val) { %res = select i1 %cmp, i64 %neg, i64 %val ret i64 %res } + +; Test another form of f6, which is that produced by InstCombine. +define i64 @f8(i64 %val) { +; CHECK-LABEL: f8: +; CHECK: lpgfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp slt i64 %shl, 0 + %abs = select i1 %cmp, i64 %neg, i64 %ashr + ret i64 %abs +} + +; Try again with sle rather than slt. +define i64 @f9(i64 %val) { +; CHECK-LABEL: f9: +; CHECK: lpgfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp sle i64 %shl, 0 + %abs = select i1 %cmp, i64 %neg, i64 %ashr + ret i64 %abs +} + +; Repeat f8 with the operands reversed. +define i64 @f10(i64 %val) { +; CHECK-LABEL: f10: +; CHECK: lpgfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp sgt i64 %shl, 0 + %abs = select i1 %cmp, i64 %ashr, i64 %neg + ret i64 %abs +} + +; Try again with sge rather than sgt. +define i64 @f11(i64 %val) { +; CHECK-LABEL: f11: +; CHECK: lpgfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp sge i64 %shl, 0 + %abs = select i1 %cmp, i64 %ashr, i64 %neg + ret i64 %abs +} + +; Repeat f5 with the comparison on the unextended value. +define i64 @f12(i32 %val) { +; CHECK-LABEL: f12: +; CHECK: lpgfr %r2, %r2 +; CHECK: br %r14 + %ext = sext i32 %val to i64 + %cmp = icmp slt i32 %val, 0 + %neg = sub i64 0, %ext + %abs = select i1 %cmp, i64 %neg, i64 %ext + ret i64 %abs +} diff --git a/test/CodeGen/SystemZ/int-cmp-05.ll b/test/CodeGen/SystemZ/int-cmp-05.ll index f15b76bb87fe..0be43a3ef1bf 100644 --- a/test/CodeGen/SystemZ/int-cmp-05.ll +++ b/test/CodeGen/SystemZ/int-cmp-05.ll @@ -291,9 +291,22 @@ define i64 @f15(i32 *%ptr0) { ret i64 %sel9 } -; Check the comparison can be reversed if that allows CGF to be used. -define double @f16(double %a, double %b, i64 %i2, i32 *%ptr) { +; Check the comparison can be reversed if that allows CGFR to be used. +define double @f16(double %a, double %b, i64 %i1, i32 %unext) { ; CHECK-LABEL: f16: +; CHECK: cgfr %r2, %r3 +; CHECK-NEXT: jh +; CHECK: ldr %f0, %f2 +; CHECK: br %r14 + %i2 = sext i32 %unext to i64 + %cond = icmp slt i64 %i2, %i1 + %res = select i1 %cond, double %a, double %b + ret double %res +} + +; Likewise CGF. +define double @f17(double %a, double %b, i64 %i2, i32 *%ptr) { +; CHECK-LABEL: f17: ; CHECK: cgf %r2, 0(%r3) ; CHECK-NEXT: jh {{\.L.*}} ; CHECK: ldr %f0, %f2 diff --git a/test/CodeGen/SystemZ/int-cmp-06.ll b/test/CodeGen/SystemZ/int-cmp-06.ll index 8ab62e89ec39..82007e221766 100644 --- a/test/CodeGen/SystemZ/int-cmp-06.ll +++ b/test/CodeGen/SystemZ/int-cmp-06.ll @@ -341,9 +341,35 @@ define i64 @f19(i32 *%ptr0) { ret i64 %sel9 } -; Check the comparison can be reversed if that allows CLGF to be used. -define double @f20(double %a, double %b, i64 %i2, i32 *%ptr) { +; Check the comparison can be reversed if that allows CLGFR to be used. +define double @f20(double %a, double %b, i64 %i1, i32 %unext) { ; CHECK-LABEL: f20: +; CHECK: clgfr %r2, %r3 +; CHECK-NEXT: jh +; CHECK: ldr %f0, %f2 +; CHECK: br %r14 + %i2 = zext i32 %unext to i64 + %cond = icmp ult i64 %i2, %i1 + %res = select i1 %cond, double %a, double %b + ret double %res +} + +; ...and again with the AND representation. +define double @f21(double %a, double %b, i64 %i1, i64 %unext) { +; CHECK-LABEL: f21: +; CHECK: clgfr %r2, %r3 +; CHECK-NEXT: jh +; CHECK: ldr %f0, %f2 +; CHECK: br %r14 + %i2 = and i64 %unext, 4294967295 + %cond = icmp ult i64 %i2, %i1 + %res = select i1 %cond, double %a, double %b + ret double %res +} + +; Check the comparison can be reversed if that allows CLGF to be used. +define double @f22(double %a, double %b, i64 %i2, i32 *%ptr) { +; CHECK-LABEL: f22: ; CHECK: clgf %r2, 0(%r3) ; CHECK-NEXT: jh {{\.L.*}} ; CHECK: ldr %f0, %f2 diff --git a/test/CodeGen/SystemZ/int-cmp-44.ll b/test/CodeGen/SystemZ/int-cmp-44.ll index ae0133f10860..f065e6421295 100644 --- a/test/CodeGen/SystemZ/int-cmp-44.ll +++ b/test/CodeGen/SystemZ/int-cmp-44.ll @@ -1,4 +1,4 @@ -; Test that compares are ommitted if CC already has the right value +; Test that compares are omitted if CC already has the right value ; (z10 version). ; ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s @@ -797,3 +797,93 @@ store: exit: ret i32 %val } + +; Test f35 for in-register extensions. +define i64 @f39(i64 %dummy, i64 %a, i64 *%dest) { +; CHECK-LABEL: f39: +; CHECK: ltgfr %r2, %r3 +; CHECK-NEXT: #APP +; CHECK-NEXT: blah %r2 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: jh .L{{.*}} +; CHECK: br %r14 +entry: + %val = trunc i64 %a to i32 + %ext = sext i32 %val to i64 + call void asm sideeffect "blah $0", "{r2}"(i64 %ext) + %cmp = icmp sgt i64 %ext, 0 + br i1 %cmp, label %exit, label %store + +store: + store i64 %ext, i64 *%dest + br label %exit + +exit: + ret i64 %ext +} + +; ...and again with what InstCombine would produce for f40. +define i64 @f40(i64 %dummy, i64 %a, i64 *%dest) { +; CHECK-LABEL: f40: +; CHECK: ltgfr %r2, %r3 +; CHECK-NEXT: #APP +; CHECK-NEXT: blah %r2 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: jh .L{{.*}} +; CHECK: br %r14 +entry: + %shl = shl i64 %a, 32 + %ext = ashr i64 %shl, 32 + call void asm sideeffect "blah $0", "{r2}"(i64 %ext) + %cmp = icmp sgt i64 %shl, 0 + br i1 %cmp, label %exit, label %store + +store: + store i64 %ext, i64 *%dest + br label %exit + +exit: + ret i64 %ext +} + +; Try a form of f7 in which the subtraction operands are compared directly. +define i32 @f41(i32 %a, i32 %b, i32 *%dest) { +; CHECK-LABEL: f41: +; CHECK: s %r2, 0(%r4) +; CHECK-NEXT: jne .L{{.*}} +; CHECK: br %r14 +entry: + %cur = load i32 *%dest + %res = sub i32 %a, %cur + %cmp = icmp ne i32 %a, %cur + br i1 %cmp, label %exit, label %store + +store: + store i32 %b, i32 *%dest + br label %exit + +exit: + ret i32 %res +} + +; A version of f32 that tests the unextended value. +define i64 @f42(i64 %base, i64 %index, i64 *%dest) { +; CHECK-LABEL: f42: +; CHECK: ltgf %r2, 0({{%r2,%r3|%r3,%r2}}) +; CHECK-NEXT: jh .L{{.*}} +; CHECK: br %r14 +entry: + %add = add i64 %base, %index + %ptr = inttoptr i64 %add to i32 * + %val = load i32 *%ptr + %res = sext i32 %val to i64 + %cmp = icmp sgt i32 %val, 0 + br i1 %cmp, label %exit, label %store + +store: + store i64 %res, i64 *%dest + br label %exit + +exit: + ret i64 %res +} diff --git a/test/CodeGen/SystemZ/int-cmp-45.ll b/test/CodeGen/SystemZ/int-cmp-45.ll index 753a528e46c9..9c9c49c05df1 100644 --- a/test/CodeGen/SystemZ/int-cmp-45.ll +++ b/test/CodeGen/SystemZ/int-cmp-45.ll @@ -1,4 +1,4 @@ -; Test that compares are ommitted if CC already has the right value +; Test that compares are omitted if CC already has the right value ; (z196 version). ; ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s diff --git a/test/CodeGen/SystemZ/int-cmp-47.ll b/test/CodeGen/SystemZ/int-cmp-47.ll index 9ebcbfe525ba..038a25b2a6ed 100644 --- a/test/CodeGen/SystemZ/int-cmp-47.ll +++ b/test/CodeGen/SystemZ/int-cmp-47.ll @@ -232,3 +232,112 @@ store: exit: ret void } + +; Check a case where TMHH can be used to implement a ult comparison. +define void @f13(i64 %a) { +; CHECK-LABEL: f13: +; CHECK: tmhh %r2, 49152 +; CHECK: jno {{\.L.*}} +; CHECK: br %r14 +entry: + %cmp = icmp ult i64 %a, 13835058055282163712 + br i1 %cmp, label %exit, label %store + +store: + store i32 1, i32 *@g + br label %exit + +exit: + ret void +} + +; And again with ule. +define void @f14(i64 %a) { +; CHECK-LABEL: f14: +; CHECK: tmhh %r2, 49152 +; CHECK: jno {{\.L.*}} +; CHECK: br %r14 +entry: + %cmp = icmp ule i64 %a, 13835058055282163711 + br i1 %cmp, label %exit, label %store + +store: + store i32 1, i32 *@g + br label %exit + +exit: + ret void +} + +; And again with ugt. +define void @f15(i64 %a) { +; CHECK-LABEL: f15: +; CHECK: tmhh %r2, 49152 +; CHECK: jo {{\.L.*}} +; CHECK: br %r14 +entry: + %cmp = icmp ugt i64 %a, 13835058055282163711 + br i1 %cmp, label %exit, label %store + +store: + store i32 1, i32 *@g + br label %exit + +exit: + ret void +} + +; And again with uge. +define void @f16(i64 %a) { +; CHECK-LABEL: f16: +; CHECK: tmhh %r2, 49152 +; CHECK: jo {{\.L.*}} +; CHECK: br %r14 +entry: + %cmp = icmp uge i64 %a, 13835058055282163712 + br i1 %cmp, label %exit, label %store + +store: + store i32 1, i32 *@g + br label %exit + +exit: + ret void +} + +; Decrease the constant from f13 to make TMHH invalid. +define void @f17(i64 %a) { +; CHECK-LABEL: f17: +; CHECK-NOT: tmhh +; CHECK: llihh {{%r[0-5]}}, 49151 +; CHECK-NOT: tmhh +; CHECK: br %r14 +entry: + %cmp = icmp ult i64 %a, 13834776580305453056 + br i1 %cmp, label %exit, label %store + +store: + store i32 1, i32 *@g + br label %exit + +exit: + ret void +} + +; Check that we don't use TMHH just to test the top bit. +define void @f18(i64 %a) { +; CHECK-LABEL: f18: +; CHECK-NOT: tmhh +; CHECK: cgijhe %r2, 0, +; CHECK: br %r14 +entry: + %cmp = icmp ult i64 %a, 9223372036854775808 + br i1 %cmp, label %exit, label %store + +store: + store i32 1, i32 *@g + br label %exit + +exit: + ret void +} diff --git a/test/CodeGen/SystemZ/int-neg-02.ll b/test/CodeGen/SystemZ/int-neg-02.ll index e26194c162d4..7f3f6375129a 100644 --- a/test/CodeGen/SystemZ/int-neg-02.ll +++ b/test/CodeGen/SystemZ/int-neg-02.ll @@ -89,3 +89,136 @@ define i64 @f7(i64 %val) { %res = sub i64 0, %abs ret i64 %res } + +; Test another form of f6, which is that produced by InstCombine. +define i64 @f8(i64 %val) { +; CHECK-LABEL: f8: +; CHECK: lngfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp slt i64 %shl, 0 + %abs = select i1 %cmp, i64 %neg, i64 %ashr + %res = sub i64 0, %abs + ret i64 %res +} + +; Try again with sle rather than slt. +define i64 @f9(i64 %val) { +; CHECK-LABEL: f9: +; CHECK: lngfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp sle i64 %shl, 0 + %abs = select i1 %cmp, i64 %neg, i64 %ashr + %res = sub i64 0, %abs + ret i64 %res +} + +; Repeat f8 with the operands reversed. +define i64 @f10(i64 %val) { +; CHECK-LABEL: f10: +; CHECK: lngfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp sgt i64 %shl, 0 + %abs = select i1 %cmp, i64 %ashr, i64 %neg + %res = sub i64 0, %abs + ret i64 %res +} + +; Try again with sge rather than sgt. +define i64 @f11(i64 %val) { +; CHECK-LABEL: f11: +; CHECK: lngfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp sge i64 %shl, 0 + %abs = select i1 %cmp, i64 %ashr, i64 %neg + %res = sub i64 0, %abs + ret i64 %res +} + +; Repeat f8 with the negation coming from swapped operands. +define i64 @f12(i64 %val) { +; CHECK-LABEL: f12: +; CHECK: lngfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp slt i64 %shl, 0 + %negabs = select i1 %cmp, i64 %ashr, i64 %neg + ret i64 %negabs +} + +; Likewise f9. +define i64 @f13(i64 %val) { +; CHECK-LABEL: f13: +; CHECK: lngfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp sle i64 %shl, 0 + %negabs = select i1 %cmp, i64 %ashr, i64 %neg + ret i64 %negabs +} + +; Likewise f10. +define i64 @f14(i64 %val) { +; CHECK-LABEL: f14: +; CHECK: lngfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp sgt i64 %shl, 0 + %negabs = select i1 %cmp, i64 %neg, i64 %ashr + ret i64 %negabs +} + +; Likewise f11. +define i64 @f15(i64 %val) { +; CHECK-LABEL: f15: +; CHECK: lngfr %r2, %r2 +; CHECK: br %r14 + %shl = shl i64 %val, 32 + %ashr = ashr i64 %shl, 32 + %neg = sub i64 0, %ashr + %cmp = icmp sge i64 %shl, 0 + %negabs = select i1 %cmp, i64 %neg, i64 %ashr + ret i64 %negabs +} + +; Repeat f5 with the comparison on the unextended value. +define i64 @f16(i32 %val) { +; CHECK-LABEL: f16: +; CHECK: lngfr %r2, %r2 +; CHECK: br %r14 + %ext = sext i32 %val to i64 + %cmp = icmp slt i32 %val, 0 + %neg = sub i64 0, %ext + %abs = select i1 %cmp, i64 %neg, i64 %ext + %res = sub i64 0, %abs + ret i64 %res +} + +; And again with the negation coming from swapped operands. +define i64 @f17(i32 %val) { +; CHECK-LABEL: f17: +; CHECK: lngfr %r2, %r2 +; CHECK: br %r14 + %ext = sext i32 %val to i64 + %cmp = icmp slt i32 %val, 0 + %neg = sub i64 0, %ext + %abs = select i1 %cmp, i64 %ext, i64 %neg + ret i64 %abs +} diff --git a/test/CodeGen/SystemZ/lit.local.cfg b/test/CodeGen/SystemZ/lit.local.cfg index b12af09434be..5c02dd3614a4 100644 --- a/test/CodeGen/SystemZ/lit.local.cfg +++ b/test/CodeGen/SystemZ/lit.local.cfg @@ -1,4 +1,3 @@ -targets = set(config.root.targets_to_build.split()) -if not 'SystemZ' in targets: +if not 'SystemZ' in config.root.targets: config.unsupported = True diff --git a/test/CodeGen/SystemZ/mature-mc-support.ll b/test/CodeGen/SystemZ/mature-mc-support.ll new file mode 100644 index 000000000000..5520f55e1e29 --- /dev/null +++ b/test/CodeGen/SystemZ/mature-mc-support.ll @@ -0,0 +1,15 @@ +; Test that inline assembly is parsed by the MC layer when MC support is mature +; (even when the output is assembly). +; FIXME: SystemZ doesn't use the integrated assembler by default so we only test +; that -filetype=obj tries to parse the assembly. + +; SKIP: not llc -march=systemz < %s > /dev/null 2> %t1 +; SKIP: FileCheck %s < %t1 + +; RUN: not llc -march=systemz -filetype=obj < %s > /dev/null 2> %t2 +; RUN: FileCheck %s < %t2 + + +module asm " .this_directive_is_very_unlikely_to_exist" + +; CHECK: LLVM ERROR: Error parsing inline asm diff --git a/test/CodeGen/SystemZ/risbg-01.ll b/test/CodeGen/SystemZ/risbg-01.ll index a4d11fdae5b9..d75e8e4b11a6 100644 --- a/test/CodeGen/SystemZ/risbg-01.ll +++ b/test/CodeGen/SystemZ/risbg-01.ll @@ -269,12 +269,12 @@ define i64 @f23(i64 %foo) { ; mask and rotate. define i32 @f24(i32 %foo) { ; CHECK-LABEL: f24: -; CHECK: nilf %r2, 14 -; CHECK: rll %r2, %r2, 3 +; CHECK: nilf %r2, 254 +; CHECK: rll %r2, %r2, 29 ; CHECK: br %r14 - %and = and i32 %foo, 14 - %parta = shl i32 %and, 3 - %partb = lshr i32 %and, 29 + %and = and i32 %foo, 254 + %parta = lshr i32 %and, 3 + %partb = shl i32 %and, 29 %rotl = or i32 %parta, %partb ret i32 %rotl } @@ -295,7 +295,6 @@ define i64 @f25(i64 %foo) { ; This again needs a separate mask and rotate. define i32 @f26(i32 %foo) { ; CHECK-LABEL: f26: -; CHECK: nill %r2, 65487 ; CHECK: rll %r2, %r2, 5 ; CHECK: br %r14 %and = and i32 %foo, -49 @@ -457,11 +456,22 @@ define i64 @f40(i64 %foo, i64 *%dest) { ret i64 %and } +; Check a case where the result is zero-extended. +define i64 @f41(i32 %a) { +; CHECK-LABEL: f41 +; CHECK: risbg %r2, %r2, 36, 191, 62 +; CHECK: br %r14 + %shl = shl i32 %a, 2 + %shr = lshr i32 %shl, 4 + %ext = zext i32 %shr to i64 + ret i64 %ext +} + ; In this case the sign extension is converted to a pair of 32-bit shifts, ; which is then extended to 64 bits. We previously used the wrong bit size ; when testing whether the shifted-in bits of the shift right were significant. -define i64 @f41(i1 %x) { -; CHECK-LABEL: f41: +define i64 @f42(i1 %x) { +; CHECK-LABEL: f42: ; CHECK: sll %r2, 31 ; CHECK: sra %r2, 31 ; CHECK: llgcr %r2, %r2 diff --git a/test/CodeGen/SystemZ/rnsbg-01.ll b/test/CodeGen/SystemZ/rnsbg-01.ll index 666aeb21e8d8..282810a78151 100644 --- a/test/CodeGen/SystemZ/rnsbg-01.ll +++ b/test/CodeGen/SystemZ/rnsbg-01.ll @@ -255,3 +255,14 @@ define i64 @f22(i64 %a, i64 %b) { %and = and i64 %a, %rotlorb ret i64 %and } + +; Check the handling of zext and AND, which isn't suitable for RNSBG. +define i64 @f23(i64 %a, i32 %b) { +; CHECK-LABEL: f23: +; CHECK-NOT: rnsbg +; CHECK: br %r14 + %add = add i32 %b, 1 + %ext = zext i32 %add to i64 + %and = and i64 %a, %ext + ret i64 %and +} diff --git a/test/CodeGen/SystemZ/rosbg-01.ll b/test/CodeGen/SystemZ/rosbg-01.ll index 0abacccba14c..96ee870d42b4 100644 --- a/test/CodeGen/SystemZ/rosbg-01.ll +++ b/test/CodeGen/SystemZ/rosbg-01.ll @@ -108,3 +108,14 @@ define i64 @f11(i64 %a, i64 %b) { %or = or i64 %a, %andb ret i64 %or } + +; Check the handling of zext and OR, which can use ROSBG. +define i64 @f12(i64 %a, i32 %b) { +; CHECK-LABEL: f12: +; CHECK: rosbg %r2, %r3, 32, 63, 0 +; CHECK: br %r14 + %add = add i32 %b, 1 + %ext = zext i32 %add to i64 + %or = or i64 %a, %ext + ret i64 %or +} diff --git a/test/CodeGen/SystemZ/rxsbg-01.ll b/test/CodeGen/SystemZ/rxsbg-01.ll index 5491bff2ecdc..339fe2a289f0 100644 --- a/test/CodeGen/SystemZ/rxsbg-01.ll +++ b/test/CodeGen/SystemZ/rxsbg-01.ll @@ -110,3 +110,14 @@ define i64 @f11(i64 %a, i64 %b) { %xor = xor i64 %a, %andb ret i64 %xor } + +; Check the handling of zext and XOR, which can use ROSBG. +define i64 @f12(i64 %a, i32 %b) { +; CHECK-LABEL: f12: +; CHECK: rxsbg %r2, %r3, 32, 63, 0 +; CHECK: br %r14 + %add = add i32 %b, 1 + %ext = zext i32 %add to i64 + %xor = xor i64 %a, %ext + ret i64 %xor +} diff --git a/test/CodeGen/SystemZ/selectcc-01.ll b/test/CodeGen/SystemZ/selectcc-01.ll new file mode 100644 index 000000000000..a57444c831a5 --- /dev/null +++ b/test/CodeGen/SystemZ/selectcc-01.ll @@ -0,0 +1,178 @@ +; Test an i32 0/-1 SELECTCCC for every floating-point condition. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +; Test CC in { 0 } +define i32 @f1(float %a, float %b) { +; CHECK-LABEL: f1: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, -268435456 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp oeq float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 1 } +define i32 @f2(float %a, float %b) { +; CHECK-LABEL: f2: +; CHECK: ipm %r2 +; CHECK-NEXT: xilf %r2, 268435456 +; CHECK-NEXT: afi %r2, -268435456 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp olt float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 0, 1 } +define i32 @f3(float %a, float %b) { +; CHECK-LABEL: f3: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, -536870912 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ole float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 2 } +define i32 @f4(float %a, float %b) { +; CHECK-LABEL: f4: +; CHECK: ipm %r2 +; CHECK-NEXT: xilf %r2, 268435456 +; CHECK-NEXT: afi %r2, 1342177280 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ogt float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 0, 2 } +define i32 @f5(float %a, float %b) { +; CHECK-LABEL: f5: +; CHECK: ipm %r2 +; CHECK-NEXT: xilf %r2, 4294967295 +; CHECK-NEXT: sll %r2, 3 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp oge float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 1, 2 } +define i32 @f6(float %a, float %b) { +; CHECK-LABEL: f6: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, 268435456 +; CHECK-NEXT: sll %r2, 2 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp one float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 0, 1, 2 } +define i32 @f7(float %a, float %b) { +; CHECK-LABEL: f7: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, -805306368 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ord float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 3 } +define i32 @f8(float %a, float %b) { +; CHECK-LABEL: f8: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, 1342177280 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp uno float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 0, 3 } +define i32 @f9(float %a, float %b) { +; CHECK-LABEL: f9: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, -268435456 +; CHECK-NEXT: sll %r2, 2 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ueq float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 1, 3 } +define i32 @f10(float %a, float %b) { +; CHECK-LABEL: f10: +; CHECK: ipm %r2 +; CHECK-NEXT: sll %r2, 3 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ult float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 0, 1, 3 } +define i32 @f11(float %a, float %b) { +; CHECK-LABEL: f11: +; CHECK: ipm %r2 +; CHECK-NEXT: xilf %r2, 268435456 +; CHECK-NEXT: afi %r2, -805306368 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ule float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 2, 3 } +define i32 @f12(float %a, float %b) { +; CHECK-LABEL: f12: +; CHECK: ipm %r2 +; CHECK-NEXT: sll %r2, 2 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ugt float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 0, 2, 3 } +define i32 @f13(float %a, float %b) { +; CHECK-LABEL: f13: +; CHECK: ipm %r2 +; CHECK-NEXT: xilf %r2, 268435456 +; CHECK-NEXT: afi %r2, 1879048192 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp uge float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} + +; Test CC in { 1, 2, 3 } +define i32 @f14(float %a, float %b) { +; CHECK-LABEL: f14: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, 1879048192 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp une float %a, %b + %res = select i1 %cond, i32 -1, i32 0 + ret i32 %res +} diff --git a/test/CodeGen/SystemZ/selectcc-02.ll b/test/CodeGen/SystemZ/selectcc-02.ll new file mode 100644 index 000000000000..b1081a0621d6 --- /dev/null +++ b/test/CodeGen/SystemZ/selectcc-02.ll @@ -0,0 +1,178 @@ +; Test an i32 0/-1 SELECTCCC for every floating-point condition. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +; Test CC in { 1, 2, 3 } +define i32 @f1(float %a, float %b) { +; CHECK-LABEL: f1: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, 1879048192 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp oeq float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 0, 2, 3 } +define i32 @f2(float %a, float %b) { +; CHECK-LABEL: f2: +; CHECK: ipm %r2 +; CHECK-NEXT: xilf %r2, 268435456 +; CHECK-NEXT: afi %r2, 1879048192 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp olt float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 2, 3 } +define i32 @f3(float %a, float %b) { +; CHECK-LABEL: f3: +; CHECK: ipm %r2 +; CHECK-NEXT: sll %r2, 2 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ole float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 0, 1, 3 } +define i32 @f4(float %a, float %b) { +; CHECK-LABEL: f4: +; CHECK: ipm %r2 +; CHECK-NEXT: xilf %r2, 268435456 +; CHECK-NEXT: afi %r2, -805306368 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ogt float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 1, 3 } +define i32 @f5(float %a, float %b) { +; CHECK-LABEL: f5: +; CHECK: ipm %r2 +; CHECK-NEXT: sll %r2, 3 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp oge float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 0, 3 } +define i32 @f6(float %a, float %b) { +; CHECK-LABEL: f6: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, -268435456 +; CHECK-NEXT: sll %r2, 2 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp one float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 3 } +define i32 @f7(float %a, float %b) { +; CHECK-LABEL: f7: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, 1342177280 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ord float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 0, 1, 2 } +define i32 @f8(float %a, float %b) { +; CHECK-LABEL: f8: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, -805306368 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp uno float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 1, 2 } +define i32 @f9(float %a, float %b) { +; CHECK-LABEL: f9: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, 268435456 +; CHECK-NEXT: sll %r2, 2 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ueq float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 0, 2 } +define i32 @f10(float %a, float %b) { +; CHECK-LABEL: f10: +; CHECK: ipm %r2 +; CHECK-NEXT: xilf %r2, 4294967295 +; CHECK-NEXT: sll %r2, 3 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ult float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 2 } +define i32 @f11(float %a, float %b) { +; CHECK-LABEL: f11: +; CHECK: ipm %r2 +; CHECK-NEXT: xilf %r2, 268435456 +; CHECK-NEXT: afi %r2, 1342177280 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ule float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 0, 1 } +define i32 @f12(float %a, float %b) { +; CHECK-LABEL: f12: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, -536870912 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp ugt float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 1 } +define i32 @f13(float %a, float %b) { +; CHECK-LABEL: f13: +; CHECK: ipm %r2 +; CHECK-NEXT: xilf %r2, 268435456 +; CHECK-NEXT: afi %r2, -268435456 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp uge float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} + +; Test CC in { 0 } +define i32 @f14(float %a, float %b) { +; CHECK-LABEL: f14: +; CHECK: ipm %r2 +; CHECK-NEXT: afi %r2, -268435456 +; CHECK-NEXT: sra %r2, 31 +; CHECK: br %r14 + %cond = fcmp une float %a, %b + %res = select i1 %cond, i32 0, i32 -1 + ret i32 %res +} diff --git a/test/CodeGen/SystemZ/selectcc-03.ll b/test/CodeGen/SystemZ/selectcc-03.ll new file mode 100644 index 000000000000..cafb4a2f1842 --- /dev/null +++ b/test/CodeGen/SystemZ/selectcc-03.ll @@ -0,0 +1,187 @@ +; Test an i64 0/-1 SELECTCCC for every floating-point condition. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +; Test CC in { 0 } +define i64 @f1(float %a, float %b) { +; CHECK-LABEL: f1: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], -268435456 +; CHECK-NEXT: sllg [[REG]], [[REG]], 32 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp oeq float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 1 } +define i64 @f2(float %a, float %b) { +; CHECK-LABEL: f2: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 268435456 +; CHECK-NEXT: afi [[REG]], -268435456 +; CHECK-NEXT: sllg [[REG]], [[REG]], 32 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp olt float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 0, 1 } +define i64 @f3(float %a, float %b) { +; CHECK-LABEL: f3: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], -536870912 +; CHECK-NEXT: sllg [[REG]], [[REG]], 32 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp ole float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 2 } +define i64 @f4(float %a, float %b) { +; CHECK-LABEL: f4: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 268435456 +; CHECK-NEXT: afi [[REG]], 1342177280 +; CHECK-NEXT: sllg [[REG]], [[REG]], 32 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp ogt float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 0, 2 } +define i64 @f5(float %a, float %b) { +; CHECK-LABEL: f5: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 4294967295 +; CHECK-NEXT: sllg [[REG]], [[REG]], 35 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp oge float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 1, 2 } +define i64 @f6(float %a, float %b) { +; CHECK-LABEL: f6: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], 268435456 +; CHECK-NEXT: sllg [[REG]], [[REG]], 34 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp one float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 0, 1, 2 } +define i64 @f7(float %a, float %b) { +; CHECK-LABEL: f7: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], -805306368 +; CHECK-NEXT: sllg [[REG]], [[REG]], 32 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp ord float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 3 } +define i64 @f8(float %a, float %b) { +; CHECK-LABEL: f8: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], 1342177280 +; CHECK-NEXT: sllg [[REG]], [[REG]], 32 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp uno float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 0, 3 } +define i64 @f9(float %a, float %b) { +; CHECK-LABEL: f9: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], -268435456 +; CHECK-NEXT: sllg [[REG]], [[REG]], 34 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp ueq float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 1, 3 } +define i64 @f10(float %a, float %b) { +; CHECK-LABEL: f10: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: sllg [[REG]], [[REG]], 35 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp ult float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 0, 1, 3 } +define i64 @f11(float %a, float %b) { +; CHECK-LABEL: f11: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 268435456 +; CHECK-NEXT: afi [[REG]], -805306368 +; CHECK-NEXT: sllg [[REG]], [[REG]], 32 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp ule float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 2, 3 } +define i64 @f12(float %a, float %b) { +; CHECK-LABEL: f12: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: sllg [[REG]], [[REG]], 34 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp ugt float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 0, 2, 3 } +define i64 @f13(float %a, float %b) { +; CHECK-LABEL: f13: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 268435456 +; CHECK-NEXT: afi [[REG]], 1879048192 +; CHECK-NEXT: sllg [[REG]], [[REG]], 32 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp uge float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} + +; Test CC in { 1, 2, 3 } +define i64 @f14(float %a, float %b) { +; CHECK-LABEL: f14: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], 1879048192 +; CHECK-NEXT: sllg [[REG]], [[REG]], 32 +; CHECK-NEXT: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %cond = fcmp une float %a, %b + %res = select i1 %cond, i64 -1, i64 0 + ret i64 %res +} diff --git a/test/CodeGen/SystemZ/serialize-01.ll b/test/CodeGen/SystemZ/serialize-01.ll new file mode 100644 index 000000000000..7801fac8d472 --- /dev/null +++ b/test/CodeGen/SystemZ/serialize-01.ll @@ -0,0 +1,21 @@ +; Test serialization instructions. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | \ +; RUN: FileCheck %s -check-prefix=CHECK-FULL +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | \ +; RUN: FileCheck %s -check-prefix=CHECK-FAST + +; Check that volatile loads produce a serialisation. +define i32 @f1(i32 *%src) { +; CHECK-FULL-LABEL: f1: +; CHECK-FULL: bcr 15, %r0 +; CHECK-FULL: l %r2, 0(%r2) +; CHECK-FULL: br %r14 +; +; CHECK-FAST-LABEL: f1: +; CHECK-FAST: bcr 14, %r0 +; CHECK-FAST: l %r2, 0(%r2) +; CHECK-FAST: br %r14 + %val = load volatile i32 *%src + ret i32 %val +} diff --git a/test/CodeGen/SystemZ/shift-04.ll b/test/CodeGen/SystemZ/shift-04.ll index 04b39d002c5d..de2d74f27fa3 100644 --- a/test/CodeGen/SystemZ/shift-04.ll +++ b/test/CodeGen/SystemZ/shift-04.ll @@ -187,3 +187,104 @@ define i32 @f14(i32 %a, i32 *%ptr) { %or = or i32 %parta, %partb ret i32 %or } + +; Check another form of f5, which is the one produced by running f5 through +; instcombine. +define i32 @f15(i32 %a, i32 %amt) { +; CHECK-LABEL: f15: +; CHECK: rll %r2, %r2, 10(%r3) +; CHECK: br %r14 + %add = add i32 %amt, 10 + %sub = sub i32 22, %amt + %parta = shl i32 %a, %add + %partb = lshr i32 %a, %sub + %or = or i32 %parta, %partb + ret i32 %or +} + +; Likewise for f7. +define i32 @f16(i32 %a, i64 %amt) { +; CHECK-LABEL: f16: +; CHECK: rll %r2, %r2, 10(%r3) +; CHECK: br %r14 + %add = add i64 %amt, 10 + %sub = sub i64 22, %amt + %addtrunc = trunc i64 %add to i32 + %subtrunc = trunc i64 %sub to i32 + %parta = shl i32 %a, %addtrunc + %partb = lshr i32 %a, %subtrunc + %or = or i32 %parta, %partb + ret i32 %or +} + +; Check cases where (-x & 31) is used instead of 32 - x. +define i32 @f17(i32 %x, i32 %y) { +; CHECK-LABEL: f17: +; CHECK: rll %r2, %r2, 0(%r3) +; CHECK: br %r14 +entry: + %shl = shl i32 %x, %y + %sub = sub i32 0, %y + %and = and i32 %sub, 31 + %shr = lshr i32 %x, %and + %or = or i32 %shr, %shl + ret i32 %or +} + +; ...and again with ((32 - x) & 31). +define i32 @f18(i32 %x, i32 %y) { +; CHECK-LABEL: f18: +; CHECK: rll %r2, %r2, 0(%r3) +; CHECK: br %r14 +entry: + %shl = shl i32 %x, %y + %sub = sub i32 32, %y + %and = and i32 %sub, 31 + %shr = lshr i32 %x, %and + %or = or i32 %shr, %shl + ret i32 %or +} + +; This is not a rotation. +define i32 @f19(i32 %x, i32 %y) { +; CHECK-LABEL: f19: +; CHECK-NOT: rll +; CHECK: br %r14 +entry: + %shl = shl i32 %x, %y + %sub = sub i32 16, %y + %and = and i32 %sub, 31 + %shr = lshr i32 %x, %and + %or = or i32 %shr, %shl + ret i32 %or +} + +; Repeat f17 with an addition on the shift count. +define i32 @f20(i32 %x, i32 %y) { +; CHECK-LABEL: f20: +; CHECK: rll %r2, %r2, 199(%r3) +; CHECK: br %r14 +entry: + %add = add i32 %y, 199 + %shl = shl i32 %x, %add + %sub = sub i32 0, %add + %and = and i32 %sub, 31 + %shr = lshr i32 %x, %and + %or = or i32 %shr, %shl + ret i32 %or +} + +; ...and again with the InstCombine version. +define i32 @f21(i32 %x, i32 %y) { +; CHECK-LABEL: f21: +; CHECK: rll %r2, %r2, 199(%r3) +; CHECK: br %r14 +entry: + %add = add i32 %y, 199 + %shl = shl i32 %x, %add + %sub = sub i32 -199, %y + %and = and i32 %sub, 31 + %shr = lshr i32 %x, %and + %or = or i32 %shr, %shl + ret i32 %or +} diff --git a/test/CodeGen/SystemZ/shift-10.ll b/test/CodeGen/SystemZ/shift-10.ll index 46ed2180dfd4..bf2f0f1776ee 100644 --- a/test/CodeGen/SystemZ/shift-10.ll +++ b/test/CodeGen/SystemZ/shift-10.ll @@ -14,13 +14,14 @@ define i64 @f1(i32 %a) { ret i64 %ext } -; ...and again with the highest shift count. +; ...and again with the highest shift count that doesn't reduce to an +; ashr/sext pair. define i64 @f2(i32 %a) { ; CHECK-LABEL: f2: -; CHECK: sllg [[REG:%r[0-5]]], %r2, 32 +; CHECK: sllg [[REG:%r[0-5]]], %r2, 33 ; CHECK: srag %r2, [[REG]], 63 ; CHECK: br %r14 - %shr = lshr i32 %a, 31 + %shr = lshr i32 %a, 30 %trunc = trunc i32 %shr to i1 %ext = sext i1 %trunc to i64 ret i64 %ext @@ -76,3 +77,15 @@ define i64 @f6(i64 %a) { %and = and i64 %shr, 256 ret i64 %and } + +; Test another form of f1. +define i64 @f7(i32 %a) { +; CHECK-LABEL: f7: +; CHECK: sllg [[REG:%r[0-5]]], %r2, 62 +; CHECK: srag %r2, [[REG]], 63 +; CHECK: br %r14 + %1 = shl i32 %a, 30 + %sext = ashr i32 %1, 31 + %ext = sext i32 %sext to i64 + ret i64 %ext +} diff --git a/test/CodeGen/SystemZ/spill-01.ll b/test/CodeGen/SystemZ/spill-01.ll index ca64a88f2a0d..c1f780c55d3c 100644 --- a/test/CodeGen/SystemZ/spill-01.ll +++ b/test/CodeGen/SystemZ/spill-01.ll @@ -400,6 +400,7 @@ define void @f10() { ; CHECK: stgrl [[REG]], h8 ; CHECK: br %r14 entry: + %val8 = load volatile i64 *@h8 %val0 = load volatile i64 *@h0 %val1 = load volatile i64 *@h1 %val2 = load volatile i64 *@h2 @@ -408,7 +409,6 @@ entry: %val5 = load volatile i64 *@h5 %val6 = load volatile i64 *@h6 %val7 = load volatile i64 *@h7 - %val8 = load volatile i64 *@h8 %val9 = load volatile i64 *@h9 call void @foo() |