mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
[SystemZ] Add CodeGen test cases
This adds all CodeGen tests for the SystemZ target. This version of the patch incorporates feedback from a review by Sean Silva. Thanks to all reviewers! Patch by Richard Sandiford. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181204 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1d09d56fe1
commit
b503b49b51
107
test/CodeGen/SystemZ/addr-01.ll
Normal file
107
test/CodeGen/SystemZ/addr-01.ll
Normal file
@ -0,0 +1,107 @@
|
||||
; Test selection of addresses with indices in cases where the address
|
||||
; is used once.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; A simple index address.
|
||||
define void @f1(i64 %addr, i64 %index) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lb %r0, 0(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %addr, %index
|
||||
%ptr = inttoptr i64 %add to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; An address with an index and a displacement (order 1).
|
||||
define void @f2(i64 %addr, i64 %index) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lb %r0, 100(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %addr, %index
|
||||
%add2 = add i64 %add1, 100
|
||||
%ptr = inttoptr i64 %add2 to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; An address with an index and a displacement (order 2).
|
||||
define void @f3(i64 %addr, i64 %index) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lb %r0, 100(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %addr, 100
|
||||
%add2 = add i64 %add1, %index
|
||||
%ptr = inttoptr i64 %add2 to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; An address with an index and a subtracted displacement (order 1).
|
||||
define void @f4(i64 %addr, i64 %index) {
|
||||
; CHECK: f4:
|
||||
; CHECK: lb %r0, -100(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %addr, %index
|
||||
%add2 = sub i64 %add1, 100
|
||||
%ptr = inttoptr i64 %add2 to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; An address with an index and a subtracted displacement (order 2).
|
||||
define void @f5(i64 %addr, i64 %index) {
|
||||
; CHECK: f5:
|
||||
; CHECK: lb %r0, -100(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%add1 = sub i64 %addr, 100
|
||||
%add2 = add i64 %add1, %index
|
||||
%ptr = inttoptr i64 %add2 to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; An address with an index and a displacement added using OR.
|
||||
define void @f6(i64 %addr, i64 %index) {
|
||||
; CHECK: f6:
|
||||
; CHECK: nill %r2, 65528
|
||||
; CHECK: lb %r0, 6(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%aligned = and i64 %addr, -8
|
||||
%or = or i64 %aligned, 6
|
||||
%add = add i64 %or, %index
|
||||
%ptr = inttoptr i64 %add to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Like f6, but without the masking. This OR doesn't count as a displacement.
|
||||
define void @f7(i64 %addr, i64 %index) {
|
||||
; CHECK: f7:
|
||||
; CHECK: oill %r2, 6
|
||||
; CHECK: lb %r0, 0(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%or = or i64 %addr, 6
|
||||
%add = add i64 %or, %index
|
||||
%ptr = inttoptr i64 %add to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Like f6, but with the OR applied after the index. We don't know anything
|
||||
; about the alignment of %add here.
|
||||
define void @f8(i64 %addr, i64 %index) {
|
||||
; CHECK: f8:
|
||||
; CHECK: nill %r2, 65528
|
||||
; CHECK: agr %r2, %r3
|
||||
; CHECK: oill %r2, 6
|
||||
; CHECK: lb %r0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%aligned = and i64 %addr, -8
|
||||
%add = add i64 %aligned, %index
|
||||
%or = or i64 %add, 6
|
||||
%ptr = inttoptr i64 %or to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
116
test/CodeGen/SystemZ/addr-02.ll
Normal file
116
test/CodeGen/SystemZ/addr-02.ll
Normal file
@ -0,0 +1,116 @@
|
||||
; addr-01.ll in which the address is also used in a non-address context.
|
||||
; The assumption here is that we should match complex addresses where
|
||||
; possible, but this might well need to change in future.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; A simple index address.
|
||||
define void @f1(i64 %addr, i64 %index, i8 **%dst) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lb %r0, 0(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %addr, %index
|
||||
%ptr = inttoptr i64 %add to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
store volatile i8 *%ptr, i8 **%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
; An address with an index and a displacement (order 1).
|
||||
define void @f2(i64 %addr, i64 %index, i8 **%dst) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lb %r0, 100(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %addr, %index
|
||||
%add2 = add i64 %add1, 100
|
||||
%ptr = inttoptr i64 %add2 to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
store volatile i8 *%ptr, i8 **%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
; An address with an index and a displacement (order 2).
|
||||
define void @f3(i64 %addr, i64 %index, i8 **%dst) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lb %r0, 100(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %addr, 100
|
||||
%add2 = add i64 %add1, %index
|
||||
%ptr = inttoptr i64 %add2 to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
store volatile i8 *%ptr, i8 **%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
; An address with an index and a subtracted displacement (order 1).
|
||||
define void @f4(i64 %addr, i64 %index, i8 **%dst) {
|
||||
; CHECK: f4:
|
||||
; CHECK: lb %r0, -100(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %addr, %index
|
||||
%add2 = sub i64 %add1, 100
|
||||
%ptr = inttoptr i64 %add2 to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
store volatile i8 *%ptr, i8 **%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
; An address with an index and a subtracted displacement (order 2).
|
||||
define void @f5(i64 %addr, i64 %index, i8 **%dst) {
|
||||
; CHECK: f5:
|
||||
; CHECK: lb %r0, -100(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%add1 = sub i64 %addr, 100
|
||||
%add2 = add i64 %add1, %index
|
||||
%ptr = inttoptr i64 %add2 to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
store volatile i8 *%ptr, i8 **%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
; An address with an index and a displacement added using OR.
|
||||
define void @f6(i64 %addr, i64 %index, i8 **%dst) {
|
||||
; CHECK: f6:
|
||||
; CHECK: nill %r2, 65528
|
||||
; CHECK: lb %r0, 6(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%aligned = and i64 %addr, -8
|
||||
%or = or i64 %aligned, 6
|
||||
%add = add i64 %or, %index
|
||||
%ptr = inttoptr i64 %add to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
store volatile i8 *%ptr, i8 **%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
; Like f6, but without the masking. This OR doesn't count as a displacement.
|
||||
define void @f7(i64 %addr, i64 %index, i8 **%dst) {
|
||||
; CHECK: f7:
|
||||
; CHECK: oill %r2, 6
|
||||
; CHECK: lb %r0, 0(%r3,%r2)
|
||||
; CHECK: br %r14
|
||||
%or = or i64 %addr, 6
|
||||
%add = add i64 %or, %index
|
||||
%ptr = inttoptr i64 %add to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
store volatile i8 *%ptr, i8 **%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
; Like f6, but with the OR applied after the index. We don't know anything
|
||||
; about the alignment of %add here.
|
||||
define void @f8(i64 %addr, i64 %index, i8 **%dst) {
|
||||
; CHECK: f8:
|
||||
; CHECK: nill %r2, 65528
|
||||
; CHECK: agr %r2, %r3
|
||||
; CHECK: oill %r2, 6
|
||||
; CHECK: lb %r0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%aligned = and i64 %addr, -8
|
||||
%add = add i64 %aligned, %index
|
||||
%or = or i64 %add, 6
|
||||
%ptr = inttoptr i64 %or to i8 *
|
||||
%a = load volatile i8 *%ptr
|
||||
store volatile i8 *%ptr, i8 **%dst
|
||||
ret void
|
||||
}
|
48
test/CodeGen/SystemZ/addr-03.ll
Normal file
48
test/CodeGen/SystemZ/addr-03.ll
Normal file
@ -0,0 +1,48 @@
|
||||
; Test constant addresses, unlikely as they are.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define void @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: lb %r0, 0
|
||||
; CHECK: br %r14
|
||||
%ptr = inttoptr i64 0 to i8 *
|
||||
%val = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: lb %r0, -524288
|
||||
; CHECK: br %r14
|
||||
%ptr = inttoptr i64 -524288 to i8 *
|
||||
%val = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK-NOT: lb %r0, -524289
|
||||
; CHECK: br %r14
|
||||
%ptr = inttoptr i64 -524289 to i8 *
|
||||
%val = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f4() {
|
||||
; CHECK: f4:
|
||||
; CHECK: lb %r0, 524287
|
||||
; CHECK: br %r14
|
||||
%ptr = inttoptr i64 524287 to i8 *
|
||||
%val = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f5() {
|
||||
; CHECK: f5:
|
||||
; CHECK-NOT: lb %r0, 524288
|
||||
; CHECK: br %r14
|
||||
%ptr = inttoptr i64 524288 to i8 *
|
||||
%val = load volatile i8 *%ptr
|
||||
ret void
|
||||
}
|
81
test/CodeGen/SystemZ/alloca-01.ll
Normal file
81
test/CodeGen/SystemZ/alloca-01.ll
Normal file
@ -0,0 +1,81 @@
|
||||
; Test variable-sized allocas and addresses based on them in cases where
|
||||
; stack arguments are needed.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK2
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-A
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-B
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-C
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-D
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-FP
|
||||
|
||||
declare i64 @bar(i8 *%a, i8 *%b, i8 *%c, i8 *%d, i8 *%e, i64 %f, i64 %g)
|
||||
|
||||
; Allocate %length bytes and take addresses based on the result.
|
||||
; There are two stack arguments, so an offset of 160 + 2 * 8 == 176
|
||||
; is added to the copy of %r15.
|
||||
define i64 @f1(i64 %length, i64 %index) {
|
||||
; The full allocation sequence is:
|
||||
;
|
||||
; la %r0, 7(%r2) 1
|
||||
; nill %r0, 0xfff8 1
|
||||
; lgr %r1, %r15 2
|
||||
; sgr %r1, %r0 1 2
|
||||
; lgr %r15, %r1 2
|
||||
;
|
||||
; The third instruction does not depend on the first two, so check for
|
||||
; two fully-ordered sequences.
|
||||
;
|
||||
; FIXME: a better sequence would be:
|
||||
;
|
||||
; lgr %r1, %r15
|
||||
; sgr %r1, %r2
|
||||
; nill %r1, 0xfff8
|
||||
; lgr %r15, %r1
|
||||
;
|
||||
; CHECK1: f1:
|
||||
; CHECK1: la %r0, 7(%r2)
|
||||
; CHECK1: nill %r0, 65528
|
||||
; CHECK1: sgr %r1, %r0
|
||||
; CHECK1: lgr %r15, %r1
|
||||
;
|
||||
; CHECK2: f1:
|
||||
; CHECK2: lgr %r1, %r15
|
||||
; CHECK2: sgr %r1, %r0
|
||||
; CHECK2: lgr %r15, %r1
|
||||
;
|
||||
; CHECK-A: f1:
|
||||
; CHECK-A: lgr %r15, %r1
|
||||
; CHECK-A: la %r2, 176(%r1)
|
||||
;
|
||||
; CHECK-B: f1:
|
||||
; CHECK-B: lgr %r15, %r1
|
||||
; CHECK-B: la %r3, 177(%r1)
|
||||
;
|
||||
; CHECK-C: f1:
|
||||
; CHECK-C: lgr %r15, %r1
|
||||
; CHECK-C: la %r4, 4095({{%r3,%r1|%r1,%r3}})
|
||||
;
|
||||
; CHECK-D: f1:
|
||||
; CHECK-D: lgr %r15, %r1
|
||||
; CHECK-D: lay %r5, 4096({{%r3,%r1|%r1,%r3}})
|
||||
;
|
||||
; CHECK-E: f1:
|
||||
; CHECK-E: lgr %r15, %r1
|
||||
; CHECK-E: lay %r6, 4271({{%r3,%r1|%r1,%r3}})
|
||||
;
|
||||
; CHECK-FP: f1:
|
||||
; CHECK-FP: lgr %r11, %r15
|
||||
; CHECK-FP: lmg %r6, %r15, 224(%r11)
|
||||
%a = alloca i8, i64 %length
|
||||
%b = getelementptr i8 *%a, i64 1
|
||||
%cindex = add i64 %index, 3919
|
||||
%c = getelementptr i8 *%a, i64 %cindex
|
||||
%dindex = add i64 %index, 3920
|
||||
%d = getelementptr i8 *%a, i64 %dindex
|
||||
%eindex = add i64 %index, 4095
|
||||
%e = getelementptr i8 *%a, i64 %eindex
|
||||
%count = call i64 @bar(i8 *%a, i8 *%b, i8 *%c, i8 *%d, i8 *%e, i64 0, i64 0)
|
||||
%res = add i64 %count, 1
|
||||
ret i64 %res
|
||||
}
|
49
test/CodeGen/SystemZ/alloca-02.ll
Normal file
49
test/CodeGen/SystemZ/alloca-02.ll
Normal file
@ -0,0 +1,49 @@
|
||||
; Make sure that the alloca offset isn't lost when the alloca result is
|
||||
; used directly in a load or store. There must always be an LA or LAY.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-A
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-B
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-C
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-D
|
||||
|
||||
declare i64 @bar(i8 *%a)
|
||||
|
||||
define i64 @f1(i64 %length, i64 %index) {
|
||||
; CHECK-A: f1:
|
||||
; CHECK-A: lgr %r15, [[ADDR:%r[1-5]]]
|
||||
; CHECK-A: la %r2, 160([[ADDR]])
|
||||
; CHECK-A: mvi 0(%r2), 0
|
||||
;
|
||||
; CHECK-B: f1:
|
||||
; CHECK-B: lgr %r15, [[ADDR:%r[1-5]]]
|
||||
; CHECK-B: la %r2, 160([[ADDR]])
|
||||
; CHECK-B: mvi 4095(%r2), 1
|
||||
;
|
||||
; CHECK-C: f1:
|
||||
; CHECK-C: lgr %r15, [[ADDR:%r[1-5]]]
|
||||
; CHECK-C: la [[TMP:%r[1-5]]], 160(%r3,[[ADDR]])
|
||||
; CHECK-C: mvi 0([[TMP]]), 2
|
||||
;
|
||||
; CHECK-D: f1:
|
||||
; CHECK-D: lgr %r15, [[ADDR:%r[1-5]]]
|
||||
; CHECK-D: la [[TMP:%r[1-5]]], 160(%r3,[[ADDR]])
|
||||
; CHECK-D: mvi 4095([[TMP]]), 3
|
||||
;
|
||||
; CHECK-E: f1:
|
||||
; CHECK-E: lgr %r15, [[ADDR:%r[1-5]]]
|
||||
; CHECK-E: la [[TMP:%r[1-5]]], 160(%r3,[[ADDR]])
|
||||
; CHECK-E: mviy 4096([[TMP]]), 4
|
||||
%a = alloca i8, i64 %length
|
||||
store i8 0, i8 *%a
|
||||
%b = getelementptr i8 *%a, i64 4095
|
||||
store i8 1, i8 *%b
|
||||
%c = getelementptr i8 *%a, i64 %index
|
||||
store i8 2, i8 *%c
|
||||
%d = getelementptr i8 *%c, i64 4095
|
||||
store i8 3, i8 *%d
|
||||
%e = getelementptr i8 *%d, i64 1
|
||||
store i8 4, i8 *%e
|
||||
%count = call i64 @bar(i8 *%a)
|
||||
%res = add i64 %count, 1
|
||||
ret i64 %res
|
||||
}
|
129
test/CodeGen/SystemZ/and-01.ll
Normal file
129
test/CodeGen/SystemZ/and-01.ll
Normal file
@ -0,0 +1,129 @@
|
||||
; Test 32-bit ANDs in which the second operand is variable.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check NR.
|
||||
define i32 @f1(i32 %a, i32 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: nr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the low end of the N range.
|
||||
define i32 @f2(i32 %a, i32 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: n %r2, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%b = load i32 *%src
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the high end of the aligned N range.
|
||||
define i32 @f3(i32 %a, i32 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: n %r2, 4092(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 1023
|
||||
%b = load i32 *%ptr
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the next word up, which should use NY instead of N.
|
||||
define i32 @f4(i32 %a, i32 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: ny %r2, 4096(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 1024
|
||||
%b = load i32 *%ptr
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the high end of the aligned NY range.
|
||||
define i32 @f5(i32 %a, i32 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: ny %r2, 524284(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 131071
|
||||
%b = load i32 *%ptr
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the next word up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i32 @f6(i32 %a, i32 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: agfi %r3, 524288
|
||||
; CHECK: n %r2, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 131072
|
||||
%b = load i32 *%ptr
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the high end of the negative aligned NY range.
|
||||
define i32 @f7(i32 %a, i32 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: ny %r2, -4(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -1
|
||||
%b = load i32 *%ptr
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the low end of the NY range.
|
||||
define i32 @f8(i32 %a, i32 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: ny %r2, -524288(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -131072
|
||||
%b = load i32 *%ptr
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the next word down, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i32 @f9(i32 %a, i32 *%src) {
|
||||
; CHECK: f9:
|
||||
; CHECK: agfi %r3, -524292
|
||||
; CHECK: n %r2, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -131073
|
||||
%b = load i32 *%ptr
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check that N allows an index.
|
||||
define i32 @f10(i32 %a, i64 %src, i64 %index) {
|
||||
; CHECK: f10:
|
||||
; CHECK: n %r2, 4092({{%r4,%r3|%r3,%r4}})
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%add2 = add i64 %add1, 4092
|
||||
%ptr = inttoptr i64 %add2 to i32 *
|
||||
%b = load i32 *%ptr
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check that NY allows an index.
|
||||
define i32 @f11(i32 %a, i64 %src, i64 %index) {
|
||||
; CHECK: f11:
|
||||
; CHECK: ny %r2, 4096({{%r4,%r3|%r3,%r4}})
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%add2 = add i64 %add1, 4096
|
||||
%ptr = inttoptr i64 %add2 to i32 *
|
||||
%b = load i32 *%ptr
|
||||
%and = and i32 %a, %b
|
||||
ret i32 %and
|
||||
}
|
93
test/CodeGen/SystemZ/and-02.ll
Normal file
93
test/CodeGen/SystemZ/and-02.ll
Normal file
@ -0,0 +1,93 @@
|
||||
; Test 32-bit ANDs in which the second operand is constant.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check the lowest useful NILF value.
|
||||
define i32 @f1(i32 %a) {
|
||||
; CHECK: f1:
|
||||
; CHECK: nilf %r2, 1
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, 1
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the highest 16-bit constant that must be handled by NILF.
|
||||
define i32 @f2(i32 %a) {
|
||||
; CHECK: f2:
|
||||
; CHECK: nilf %r2, 65534
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, 65534
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; ANDs of 0xffff are zero extensions from i16.
|
||||
define i32 @f3(i32 %a) {
|
||||
; CHECK: f3:
|
||||
; CHECK: llhr %r2, %r2
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, 65535
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the next value up, which must again use NILF.
|
||||
define i32 @f4(i32 %a) {
|
||||
; CHECK: f4:
|
||||
; CHECK: nilf %r2, 65536
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, 65536
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the lowest useful NILH value. (LLHR is used instead of NILH of 0.)
|
||||
define i32 @f5(i32 %a) {
|
||||
; CHECK: f5:
|
||||
; CHECK: nilh %r2, 1
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, 131071
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the highest useful NILF value.
|
||||
define i32 @f6(i32 %a) {
|
||||
; CHECK: f6:
|
||||
; CHECK: nilf %r2, 4294901758
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, -65538
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the highest useful NILH value, which is one up from the above.
|
||||
define i32 @f7(i32 %a) {
|
||||
; CHECK: f7:
|
||||
; CHECK: nilh %r2, 65534
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, -65537
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the low end of the NILL range, which is one up again.
|
||||
define i32 @f8(i32 %a) {
|
||||
; CHECK: f8:
|
||||
; CHECK: nill %r2, 0
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, -65536
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the next value up.
|
||||
define i32 @f9(i32 %a) {
|
||||
; CHECK: f9:
|
||||
; CHECK: nill %r2, 1
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, -65535
|
||||
ret i32 %and
|
||||
}
|
||||
|
||||
; Check the highest useful NILL value.
|
||||
define i32 @f10(i32 %a) {
|
||||
; CHECK: f10:
|
||||
; CHECK: nill %r2, 65534
|
||||
; CHECK: br %r14
|
||||
%and = and i32 %a, -2
|
||||
ret i32 %and
|
||||
}
|
94
test/CodeGen/SystemZ/and-03.ll
Normal file
94
test/CodeGen/SystemZ/and-03.ll
Normal file
@ -0,0 +1,94 @@
|
||||
; Test 64-bit ANDs in which the second operand is variable.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check NGR.
|
||||
define i64 @f1(i64 %a, i64 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: ngr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, %b
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check NG with no displacement.
|
||||
define i64 @f2(i64 %a, i64 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: ng %r2, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%b = load i64 *%src
|
||||
%and = and i64 %a, %b
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the high end of the aligned NG range.
|
||||
define i64 @f3(i64 %a, i64 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: ng %r2, 524280(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 65535
|
||||
%b = load i64 *%ptr
|
||||
%and = and i64 %a, %b
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the next doubleword up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i64 @f4(i64 %a, i64 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: agfi %r3, 524288
|
||||
; CHECK: ng %r2, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 65536
|
||||
%b = load i64 *%ptr
|
||||
%and = and i64 %a, %b
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the high end of the negative aligned NG range.
|
||||
define i64 @f5(i64 %a, i64 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: ng %r2, -8(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -1
|
||||
%b = load i64 *%ptr
|
||||
%and = and i64 %a, %b
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the low end of the NG range.
|
||||
define i64 @f6(i64 %a, i64 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: ng %r2, -524288(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -65536
|
||||
%b = load i64 *%ptr
|
||||
%and = and i64 %a, %b
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the next doubleword down, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i64 @f7(i64 %a, i64 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: agfi %r3, -524296
|
||||
; CHECK: ng %r2, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -65537
|
||||
%b = load i64 *%ptr
|
||||
%and = and i64 %a, %b
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check that NG allows an index.
|
||||
define i64 @f8(i64 %a, i64 %src, i64 %index) {
|
||||
; CHECK: f8:
|
||||
; CHECK: ng %r2, 524280({{%r4,%r3|%r3,%r4}})
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%add2 = add i64 %add1, 524280
|
||||
%ptr = inttoptr i64 %add2 to i64 *
|
||||
%b = load i64 *%ptr
|
||||
%and = and i64 %a, %b
|
||||
ret i64 %and
|
||||
}
|
180
test/CodeGen/SystemZ/and-04.ll
Normal file
180
test/CodeGen/SystemZ/and-04.ll
Normal file
@ -0,0 +1,180 @@
|
||||
; Test 64-bit ANDs in which the second operand is constant.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; There is no 64-bit AND instruction for a mask of 1.
|
||||
; FIXME: we ought to be able to require "ngr %r2, %r0", but at the moment,
|
||||
; two-address optimisations force "ngr %r0, %r2; lgr %r2, %r0" instead.
|
||||
define i64 @f1(i64 %a) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lghi %r0, 1
|
||||
; CHECK: ngr
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, 1
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Likewise 0xfffe.
|
||||
define i64 @f2(i64 %a) {
|
||||
; CHECK: f2:
|
||||
; CHECK: llill %r0, 65534
|
||||
; CHECK: ngr
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, 65534
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; ...but 0xffff is a 16-bit zero extension.
|
||||
define i64 @f3(i64 %a) {
|
||||
; CHECK: f3:
|
||||
; CHECK: llghr %r2, %r2
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, 65535
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the next value up, which again has no dedicated instruction.
|
||||
define i64 @f4(i64 %a) {
|
||||
; CHECK: f4:
|
||||
; CHECK: llilh %r0, 1
|
||||
; CHECK: ngr
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, 65536
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check 0xfffffffe.
|
||||
define i64 @f5(i64 %a) {
|
||||
; CHECK: f5:
|
||||
; CHECK: lilf %r0, 4294967294
|
||||
; CHECK: ngr
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, 4294967294
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the next value up, which is a 32-bit zero extension.
|
||||
define i64 @f6(i64 %a) {
|
||||
; CHECK: f6:
|
||||
; CHECK: llgfr %r2, %r2
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, 4294967295
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the lowest useful NIHF value (0x00000001_ffffffff).
|
||||
define i64 @f7(i64 %a) {
|
||||
; CHECK: f7:
|
||||
; CHECK: nihf %r2, 1
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, 8589934591
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the low end of the NIHH range (0x0000ffff_ffffffff).
|
||||
define i64 @f8(i64 %a) {
|
||||
; CHECK: f8:
|
||||
; CHECK: nihh %r2, 0
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, 281474976710655
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the highest useful NIHH value (0xfffeffff_ffffffff).
|
||||
define i64 @f9(i64 %a) {
|
||||
; CHECK: f9:
|
||||
; CHECK: nihh %r2, 65534
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -281474976710657
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the highest useful NIHF value (0xfffefffe_ffffffff).
|
||||
define i64 @f10(i64 %a) {
|
||||
; CHECK: f10:
|
||||
; CHECK: nihf %r2, 4294901758
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -281479271677953
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the low end of the NIHL range (0xffff0000_ffffffff).
|
||||
define i64 @f11(i64 %a) {
|
||||
; CHECK: f11:
|
||||
; CHECK: nihl %r2, 0
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -281470681743361
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the highest useful NIHL value (0xfffffffe_ffffffff).
|
||||
define i64 @f12(i64 %a) {
|
||||
; CHECK: f12:
|
||||
; CHECK: nihl %r2, 65534
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -4294967297
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the low end of the NILF range (0xffffffff_00000000).
|
||||
define i64 @f13(i64 %a) {
|
||||
; CHECK: f13:
|
||||
; CHECK: nilf %r2, 0
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -4294967296
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the low end of the NILH range (0xffffffff_0000ffff).
|
||||
define i64 @f14(i64 %a) {
|
||||
; CHECK: f14:
|
||||
; CHECK: nilh %r2, 0
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -4294901761
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the next value up, which must use NILF.
|
||||
define i64 @f15(i64 %a) {
|
||||
; CHECK: f15:
|
||||
; CHECK: nilf %r2, 65536
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -4294901760
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the maximum useful NILF value (0xffffffff_fffefffe).
|
||||
define i64 @f16(i64 %a) {
|
||||
; CHECK: f16:
|
||||
; CHECK: nilf %r2, 4294901758
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -65538
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the highest useful NILH value, which is one greater than the above.
|
||||
define i64 @f17(i64 %a) {
|
||||
; CHECK: f17:
|
||||
; CHECK: nilh %r2, 65534
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -65537
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the low end of the NILL range, which is one greater again.
|
||||
define i64 @f18(i64 %a) {
|
||||
; CHECK: f18:
|
||||
; CHECK: nill %r2, 0
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -65536
|
||||
ret i64 %and
|
||||
}
|
||||
|
||||
; Check the highest useful NILL value.
|
||||
define i64 @f19(i64 %a) {
|
||||
; CHECK: f19:
|
||||
; CHECK: nill %r2, 65534
|
||||
; CHECK: br %r14
|
||||
%and = and i64 %a, -2
|
||||
ret i64 %and
|
||||
}
|
165
test/CodeGen/SystemZ/and-05.ll
Normal file
165
test/CodeGen/SystemZ/and-05.ll
Normal file
@ -0,0 +1,165 @@
|
||||
; Test ANDs of a constant into a byte of memory.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check the lowest useful constant, expressed as a signed integer.
|
||||
define void @f1(i8 *%ptr) {
|
||||
; CHECK: f1:
|
||||
; CHECK: ni 0(%r2), 1
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, -255
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the highest useful constant, expressed as a signed integer.
|
||||
define void @f2(i8 *%ptr) {
|
||||
; CHECK: f2:
|
||||
; CHECK: ni 0(%r2), 254
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, -2
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the lowest useful constant, expressed as an unsigned integer.
|
||||
define void @f3(i8 *%ptr) {
|
||||
; CHECK: f3:
|
||||
; CHECK: ni 0(%r2), 1
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 1
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the highest useful constant, expressed as a unsigned integer.
|
||||
define void @f4(i8 *%ptr) {
|
||||
; CHECK: f4:
|
||||
; CHECK: ni 0(%r2), 254
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 254
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the high end of the NI range.
|
||||
define void @f5(i8 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: ni 4095(%r2), 127
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i8 *%src, i64 4095
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 127
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next byte up, which should use NIY instead of NI.
|
||||
define void @f6(i8 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: niy 4096(%r2), 127
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i8 *%src, i64 4096
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 127
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the high end of the NIY range.
|
||||
define void @f7(i8 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: niy 524287(%r2), 127
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i8 *%src, i64 524287
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 127
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next byte up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define void @f8(i8 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: agfi %r2, 524288
|
||||
; CHECK: ni 0(%r2), 127
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i8 *%src, i64 524288
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 127
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the high end of the negative NIY range.
|
||||
define void @f9(i8 *%src) {
|
||||
; CHECK: f9:
|
||||
; CHECK: niy -1(%r2), 127
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i8 *%src, i64 -1
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 127
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the low end of the NIY range.
|
||||
define void @f10(i8 *%src) {
|
||||
; CHECK: f10:
|
||||
; CHECK: niy -524288(%r2), 127
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i8 *%src, i64 -524288
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 127
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next byte down, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define void @f11(i8 *%src) {
|
||||
; CHECK: f11:
|
||||
; CHECK: agfi %r2, -524289
|
||||
; CHECK: ni 0(%r2), 127
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i8 *%src, i64 -524289
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 127
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check that NI does not allow an index
|
||||
define void @f12(i64 %src, i64 %index) {
|
||||
; CHECK: f12:
|
||||
; CHECK: agr %r2, %r3
|
||||
; CHECK: ni 4095(%r2), 127
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%add2 = add i64 %add1, 4095
|
||||
%ptr = inttoptr i64 %add2 to i8 *
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 127
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check that NIY does not allow an index
|
||||
define void @f13(i64 %src, i64 %index) {
|
||||
; CHECK: f13:
|
||||
; CHECK: agr %r2, %r3
|
||||
; CHECK: niy 4096(%r2), 127
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%add2 = add i64 %add1, 4096
|
||||
%ptr = inttoptr i64 %add2 to i8 *
|
||||
%val = load i8 *%ptr
|
||||
%and = and i8 %val, 127
|
||||
store i8 %and, i8 *%ptr
|
||||
ret void
|
||||
}
|
108
test/CodeGen/SystemZ/and-06.ll
Normal file
108
test/CodeGen/SystemZ/and-06.ll
Normal file
@ -0,0 +1,108 @@
|
||||
; Test that we can use NI for byte operations that are expressed as i32
|
||||
; or i64 operations.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Zero extension to 32 bits, negative constant.
|
||||
define void @f1(i8 *%ptr) {
|
||||
; CHECK: f1:
|
||||
; CHECK: ni 0(%r2), 254
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%ext = zext i8 %val to i32
|
||||
%and = and i32 %ext, -2
|
||||
%trunc = trunc i32 %and to i8
|
||||
store i8 %trunc, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Zero extension to 64 bits, negative constant.
|
||||
define void @f2(i8 *%ptr) {
|
||||
; CHECK: f2:
|
||||
; CHECK: ni 0(%r2), 254
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%ext = zext i8 %val to i64
|
||||
%and = and i64 %ext, -2
|
||||
%trunc = trunc i64 %and to i8
|
||||
store i8 %trunc, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Zero extension to 32 bits, positive constant.
|
||||
define void @f3(i8 *%ptr) {
|
||||
; CHECK: f3:
|
||||
; CHECK: ni 0(%r2), 254
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%ext = zext i8 %val to i32
|
||||
%and = and i32 %ext, 254
|
||||
%trunc = trunc i32 %and to i8
|
||||
store i8 %trunc, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Zero extension to 64 bits, positive constant.
|
||||
define void @f4(i8 *%ptr) {
|
||||
; CHECK: f4:
|
||||
; CHECK: ni 0(%r2), 254
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%ext = zext i8 %val to i64
|
||||
%and = and i64 %ext, 254
|
||||
%trunc = trunc i64 %and to i8
|
||||
store i8 %trunc, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Sign extension to 32 bits, negative constant.
|
||||
define void @f5(i8 *%ptr) {
|
||||
; CHECK: f5:
|
||||
; CHECK: ni 0(%r2), 254
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%ext = sext i8 %val to i32
|
||||
%and = and i32 %ext, -2
|
||||
%trunc = trunc i32 %and to i8
|
||||
store i8 %trunc, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Sign extension to 64 bits, negative constant.
|
||||
define void @f6(i8 *%ptr) {
|
||||
; CHECK: f6:
|
||||
; CHECK: ni 0(%r2), 254
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%ext = sext i8 %val to i64
|
||||
%and = and i64 %ext, -2
|
||||
%trunc = trunc i64 %and to i8
|
||||
store i8 %trunc, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Sign extension to 32 bits, positive constant.
|
||||
define void @f7(i8 *%ptr) {
|
||||
; CHECK: f7:
|
||||
; CHECK: ni 0(%r2), 254
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%ext = sext i8 %val to i32
|
||||
%and = and i32 %ext, 254
|
||||
%trunc = trunc i32 %and to i8
|
||||
store i8 %trunc, i8 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Sign extension to 64 bits, positive constant.
|
||||
define void @f8(i8 *%ptr) {
|
||||
; CHECK: f8:
|
||||
; CHECK: ni 0(%r2), 254
|
||||
; CHECK: br %r14
|
||||
%val = load i8 *%ptr
|
||||
%ext = sext i8 %val to i64
|
||||
%and = and i64 %ext, 254
|
||||
%trunc = trunc i64 %and to i8
|
||||
store i8 %trunc, i8 *%ptr
|
||||
ret void
|
||||
}
|
74
test/CodeGen/SystemZ/args-01.ll
Normal file
74
test/CodeGen/SystemZ/args-01.ll
Normal file
@ -0,0 +1,74 @@
|
||||
; Test the handling of GPR, FPR and stack arguments when no extension
|
||||
; type is given. This type of argument is used for passing structures, etc.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-INT
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-FLOAT
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-DOUBLE
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-FP128-1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-FP128-2
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-STACK
|
||||
|
||||
declare void @bar(i8, i16, i32, i64, float, double, fp128, i64,
|
||||
float, double, i8, i16, i32, i64, float, double, fp128)
|
||||
|
||||
; There are two indirect fp128 slots, one at offset 224 (the first available
|
||||
; byte after the outgoing arguments) and one immediately after it at 240.
|
||||
; These slots should be set up outside the glued call sequence, so would
|
||||
; normally use %f0/%f2 as the first available 128-bit pair. This choice
|
||||
; is hard-coded in the FP128 tests.
|
||||
;
|
||||
; The order of the CHECK-INT loads doesn't matter. The same goes for the
|
||||
; CHECK_FP128-* stores and the CHECK-STACK stores. It would be OK to reorder
|
||||
; them in response to future code changes.
|
||||
define void @foo() {
|
||||
; CHECK-INT: foo:
|
||||
; CHECK-INT: lhi %r2, 1
|
||||
; CHECK-INT: lhi %r3, 2
|
||||
; CHECK-INT: lhi %r4, 3
|
||||
; CHECK-INT: lghi %r5, 4
|
||||
; CHECK-INT: la %r6, {{224|240}}(%r15)
|
||||
; CHECK-INT: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-FLOAT: foo:
|
||||
; CHECK-FLOAT: lzer %f0
|
||||
; CHECK-FLOAT: lcebr %f4, %f0
|
||||
; CHECK-FLOAT: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-DOUBLE: foo:
|
||||
; CHECK-DOUBLE: lzdr %f2
|
||||
; CHECK-DOUBLE: lcdbr %f6, %f2
|
||||
; CHECK-DOUBLE: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-FP128-1: foo:
|
||||
; CHECK-FP128-1: aghi %r15, -256
|
||||
; CHECK-FP128-1: lzxr %f0
|
||||
; CHECK-FP128-1: std %f0, 224(%r15)
|
||||
; CHECK-FP128-1: std %f2, 232(%r15)
|
||||
; CHECK-FP128-1: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-FP128-2: foo:
|
||||
; CHECK-FP128-2: aghi %r15, -256
|
||||
; CHECK-FP128-2: lzxr %f0
|
||||
; CHECK-FP128-2: std %f0, 240(%r15)
|
||||
; CHECK-FP128-2: std %f2, 248(%r15)
|
||||
; CHECK-FP128-2: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-STACK: foo:
|
||||
; CHECK-STACK: aghi %r15, -256
|
||||
; CHECK-STACK: la [[REGISTER:%r[0-5]+]], {{224|240}}(%r15)
|
||||
; CHECK-STACK: stg [[REGISTER]], 216(%r15)
|
||||
; CHECK-STACK: mvghi 208(%r15), 0
|
||||
; CHECK-STACK: mvhi 204(%r15), 0
|
||||
; CHECK-STACK: mvghi 192(%r15), 9
|
||||
; CHECK-STACK: mvhi 188(%r15), 8
|
||||
; CHECK-STACK: mvhi 180(%r15), 7
|
||||
; CHECK-STACK: mvhi 172(%r15), 6
|
||||
; CHECK-STACK: mvghi 160(%r15), 5
|
||||
; CHECK-STACK: brasl %r14, bar@PLT
|
||||
|
||||
call void @bar (i8 1, i16 2, i32 3, i64 4, float 0.0, double 0.0,
|
||||
fp128 0xL00000000000000000000000000000000, i64 5,
|
||||
float -0.0, double -0.0, i8 6, i16 7, i32 8, i64 9, float 0.0,
|
||||
double 0.0, fp128 0xL00000000000000000000000000000000)
|
||||
ret void
|
||||
}
|
76
test/CodeGen/SystemZ/args-02.ll
Normal file
76
test/CodeGen/SystemZ/args-02.ll
Normal file
@ -0,0 +1,76 @@
|
||||
; Test the handling of GPR, FPR and stack arguments when integers are
|
||||
; sign-extended.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-INT
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-FLOAT
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-DOUBLE
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-FP128-1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-FP128-2
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-STACK
|
||||
|
||||
declare void @bar(i8 signext, i16 signext, i32 signext, i64, float, double,
|
||||
fp128, i64, float, double, i8 signext, i16 signext,
|
||||
i32 signext, i64, float, double, fp128)
|
||||
|
||||
; There are two indirect fp128 slots, one at offset 224 (the first available
|
||||
; byte after the outgoing arguments) and one immediately after it at 240.
|
||||
; These slots should be set up outside the glued call sequence, so would
|
||||
; normally use %f0/%f2 as the first available 128-bit pair. This choice
|
||||
; is hard-coded in the FP128 tests.
|
||||
;
|
||||
; The order of the CHECK-INT loads doesn't matter. The same goes for the
|
||||
; CHECK_FP128-* stores and the CHECK-STACK stores. It would be OK to reorder
|
||||
; them in response to future code changes.
|
||||
define void @foo() {
|
||||
; CHECK-INT: foo:
|
||||
; CHECK-INT: lghi %r2, -1
|
||||
; CHECK-INT: lghi %r3, -2
|
||||
; CHECK-INT: lghi %r4, -3
|
||||
; CHECK-INT: lghi %r5, -4
|
||||
; CHECK-INT: la %r6, {{224|240}}(%r15)
|
||||
; CHECK-INT: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-FLOAT: foo:
|
||||
; CHECK-FLOAT: lzer %f0
|
||||
; CHECK-FLOAT: lcebr %f4, %f0
|
||||
; CHECK-FLOAT: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-DOUBLE: foo:
|
||||
; CHECK-DOUBLE: lzdr %f2
|
||||
; CHECK-DOUBLE: lcdbr %f6, %f2
|
||||
; CHECK-DOUBLE: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-FP128-1: foo:
|
||||
; CHECK-FP128-1: aghi %r15, -256
|
||||
; CHECK-FP128-1: lzxr %f0
|
||||
; CHECK-FP128-1: std %f0, 224(%r15)
|
||||
; CHECK-FP128-1: std %f2, 232(%r15)
|
||||
; CHECK-FP128-1: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-FP128-2: foo:
|
||||
; CHECK-FP128-2: aghi %r15, -256
|
||||
; CHECK-FP128-2: lzxr %f0
|
||||
; CHECK-FP128-2: std %f0, 240(%r15)
|
||||
; CHECK-FP128-2: std %f2, 248(%r15)
|
||||
; CHECK-FP128-2: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-STACK: foo:
|
||||
; CHECK-STACK: aghi %r15, -256
|
||||
; CHECK-STACK: la [[REGISTER:%r[0-5]+]], {{224|240}}(%r15)
|
||||
; CHECK-STACK: stg [[REGISTER]], 216(%r15)
|
||||
; CHECK-STACK: mvghi 208(%r15), 0
|
||||
; CHECK-STACK: mvhi 204(%r15), 0
|
||||
; CHECK-STACK: mvghi 192(%r15), -9
|
||||
; CHECK-STACK: mvghi 184(%r15), -8
|
||||
; CHECK-STACK: mvghi 176(%r15), -7
|
||||
; CHECK-STACK: mvghi 168(%r15), -6
|
||||
; CHECK-STACK: mvghi 160(%r15), -5
|
||||
; CHECK-STACK: brasl %r14, bar@PLT
|
||||
|
||||
call void @bar (i8 -1, i16 -2, i32 -3, i64 -4, float 0.0, double 0.0,
|
||||
fp128 0xL00000000000000000000000000000000, i64 -5,
|
||||
float -0.0, double -0.0, i8 -6, i16 -7, i32 -8, i64 -9,
|
||||
float 0.0, double 0.0,
|
||||
fp128 0xL00000000000000000000000000000000)
|
||||
ret void
|
||||
}
|
78
test/CodeGen/SystemZ/args-03.ll
Normal file
78
test/CodeGen/SystemZ/args-03.ll
Normal file
@ -0,0 +1,78 @@
|
||||
; Test the handling of GPR, FPR and stack arguments when integers are
|
||||
; zero-extended.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-INT
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-FLOAT
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-DOUBLE
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-FP128-1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-FP128-2
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-STACK
|
||||
|
||||
declare void @bar(i8 zeroext, i16 zeroext, i32 zeroext, i64, float, double,
|
||||
fp128, i64, float, double, i8 zeroext, i16 zeroext,
|
||||
i32 zeroext, i64, float, double, fp128)
|
||||
|
||||
; There are two indirect fp128 slots, one at offset 224 (the first available
|
||||
; byte after the outgoing arguments) and one immediately after it at 240.
|
||||
; These slots should be set up outside the glued call sequence, so would
|
||||
; normally use %f0/%f2 as the first available 128-bit pair. This choice
|
||||
; is hard-coded in the FP128 tests.
|
||||
;
|
||||
; The order of the CHECK-INT loads doesn't matter. The same goes for the
|
||||
; CHECK_FP128-* stores and the CHECK-STACK stores. It would be OK to reorder
|
||||
; them in response to future code changes.
|
||||
define void @foo() {
|
||||
; CHECK-INT: foo:
|
||||
; CHECK-INT: lghi %r2, 255
|
||||
; CHECK-INT: llill %r3, 65534
|
||||
; CHECK-INT: llilf %r4, 4294967293
|
||||
; CHECK-INT: lghi %r5, -4
|
||||
; CHECK-INT: la %r6, {{224|240}}(%r15)
|
||||
; CHECK-INT: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-FLOAT: foo:
|
||||
; CHECK-FLOAT: lzer %f0
|
||||
; CHECK-FLOAT: lcebr %f4, %f0
|
||||
; CHECK-FLOAT: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-DOUBLE: foo:
|
||||
; CHECK-DOUBLE: lzdr %f2
|
||||
; CHECK-DOUBLE: lcdbr %f6, %f2
|
||||
; CHECK-DOUBLE: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-FP128-1: foo:
|
||||
; CHECK-FP128-1: aghi %r15, -256
|
||||
; CHECK-FP128-1: lzxr %f0
|
||||
; CHECK-FP128-1: std %f0, 224(%r15)
|
||||
; CHECK-FP128-1: std %f2, 232(%r15)
|
||||
; CHECK-FP128-1: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-FP128-2: foo:
|
||||
; CHECK-FP128-2: aghi %r15, -256
|
||||
; CHECK-FP128-2: lzxr %f0
|
||||
; CHECK-FP128-2: std %f0, 240(%r15)
|
||||
; CHECK-FP128-2: std %f2, 248(%r15)
|
||||
; CHECK-FP128-2: brasl %r14, bar@PLT
|
||||
;
|
||||
; CHECK-STACK: foo:
|
||||
; CHECK-STACK: aghi %r15, -256
|
||||
; CHECK-STACK: la [[REGISTER:%r[0-5]+]], {{224|240}}(%r15)
|
||||
; CHECK-STACK: stg [[REGISTER]], 216(%r15)
|
||||
; CHECK-STACK: llilf [[AT184:%r[0-5]+]], 4294967288
|
||||
; CHECK-STACK: stg [[AT184]], 184(%r15)
|
||||
; CHECK-STACK: llill [[AT176:%r[0-5]+]], 65529
|
||||
; CHECK-STACK: stg [[AT176]], 176(%r15)
|
||||
; CHECK-STACK: mvghi 208(%r15), 0
|
||||
; CHECK-STACK: mvhi 204(%r15), 0
|
||||
; CHECK-STACK: mvghi 192(%r15), -9
|
||||
; CHECK-STACK: mvghi 168(%r15), 250
|
||||
; CHECK-STACK: mvghi 160(%r15), -5
|
||||
; CHECK-STACK: brasl %r14, bar@PLT
|
||||
|
||||
call void @bar (i8 -1, i16 -2, i32 -3, i64 -4, float 0.0, double 0.0,
|
||||
fp128 0xL00000000000000000000000000000000, i64 -5,
|
||||
float -0.0, double -0.0, i8 -6, i16 -7, i32 -8, i64 -9,
|
||||
float 0.0, double 0.0,
|
||||
fp128 0xL00000000000000000000000000000000)
|
||||
ret void
|
||||
}
|
126
test/CodeGen/SystemZ/args-04.ll
Normal file
126
test/CodeGen/SystemZ/args-04.ll
Normal file
@ -0,0 +1,126 @@
|
||||
; Test incoming GPR, FPR and stack arguments when no extension type is given.
|
||||
; This type of argument is used for passing structures, etc.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Do some arithmetic so that we can see the register being used.
|
||||
define i8 @f1(i8 %r2) {
|
||||
; CHECK: f1:
|
||||
; CHECK: ahi %r2, 1
|
||||
; CHECK: br %r14
|
||||
%y = add i8 %r2, 1
|
||||
ret i8 %y
|
||||
}
|
||||
|
||||
define i16 @f2(i8 %r2, i16 %r3) {
|
||||
; CHECK: f2:
|
||||
; CHECK: {{lr|lgr}} %r2, %r3
|
||||
; CHECK: br %r14
|
||||
ret i16 %r3
|
||||
}
|
||||
|
||||
define i32 @f3(i8 %r2, i16 %r3, i32 %r4) {
|
||||
; CHECK: f3:
|
||||
; CHECK: {{lr|lgr}} %r2, %r4
|
||||
; CHECK: br %r14
|
||||
ret i32 %r4
|
||||
}
|
||||
|
||||
define i64 @f4(i8 %r2, i16 %r3, i32 %r4, i64 %r5) {
|
||||
; CHECK: f4:
|
||||
; CHECK: {{lr|lgr}} %r2, %r5
|
||||
; CHECK: br %r14
|
||||
ret i64 %r5
|
||||
}
|
||||
|
||||
; Do some arithmetic so that we can see the register being used.
|
||||
define float @f5(i8 %r2, i16 %r3, i32 %r4, i64 %r5, float %f0) {
|
||||
; CHECK: f5:
|
||||
; CHECK: aebr %f0, %f0
|
||||
; CHECK: br %r14
|
||||
%y = fadd float %f0, %f0
|
||||
ret float %y
|
||||
}
|
||||
|
||||
define double @f6(i8 %r2, i16 %r3, i32 %r4, i64 %r5, float %f0, double %f2) {
|
||||
; CHECK: f6:
|
||||
; CHECK: ldr %f0, %f2
|
||||
; CHECK: br %r14
|
||||
ret double %f2
|
||||
}
|
||||
|
||||
; fp128s are passed indirectly. Do some arithmetic so that the value
|
||||
; must be interpreted as a float, rather than as a block of memory to
|
||||
; be copied.
|
||||
define void @f7(fp128 *%r2, i16 %r3, i32 %r4, i64 %r5, float %f0, double %f2,
|
||||
fp128 %r6) {
|
||||
; CHECK: f7:
|
||||
; CHECK: ld %f0, 0(%r6)
|
||||
; CHECK: ld %f2, 8(%r6)
|
||||
; CHECK: axbr %f0, %f0
|
||||
; CHECK: std %f0, 0(%r2)
|
||||
; CHECK: std %f2, 8(%r2)
|
||||
; CHECK: br %r14
|
||||
%y = fadd fp128 %r6, %r6
|
||||
store fp128 %y, fp128 *%r2
|
||||
ret void
|
||||
}
|
||||
|
||||
define i64 @f8(i8 %r2, i16 %r3, i32 %r4, i64 %r5, float %f0, double %f2,
|
||||
fp128 %r6, i64 %s1) {
|
||||
; CHECK: f8:
|
||||
; CHECK: lg %r2, 160(%r15)
|
||||
; CHECK: br %r14
|
||||
ret i64 %s1
|
||||
}
|
||||
|
||||
define float @f9(i8 %r2, i16 %r3, i32 %r4, i64 %r5, float %f0, double %f2,
|
||||
fp128 %r6, i64 %s1, float %f4) {
|
||||
; CHECK: f9:
|
||||
; CHECK: ler %f0, %f4
|
||||
; CHECK: br %r14
|
||||
ret float %f4
|
||||
}
|
||||
|
||||
define double @f10(i8 %r2, i16 %r3, i32 %r4, i64 %r5, float %f0, double %f2,
|
||||
fp128 %r6, i64 %s1, float %f4, double %f6) {
|
||||
; CHECK: f10:
|
||||
; CHECK: ldr %f0, %f6
|
||||
; CHECK: br %r14
|
||||
ret double %f6
|
||||
}
|
||||
|
||||
define i64 @f11(i8 %r2, i16 %r3, i32 %r4, i64 %r5, float %f0, double %f2,
|
||||
fp128 %r6, i64 %s1, float %f4, double %f6, i64 %s2) {
|
||||
; CHECK: f11:
|
||||
; CHECK: lg %r2, 168(%r15)
|
||||
; CHECK: br %r14
|
||||
ret i64 %s2
|
||||
}
|
||||
|
||||
; Floats are passed right-justified.
|
||||
define float @f12(i8 %r2, i16 %r3, i32 %r4, i64 %r5, float %f0, double %f2,
|
||||
fp128 %r6, i64 %s1, float %f4, double %f6, i64 %s2,
|
||||
float %s3) {
|
||||
; CHECK: f12:
|
||||
; CHECK: le %f0, 180(%r15)
|
||||
; CHECK: br %r14
|
||||
ret float %s3
|
||||
}
|
||||
|
||||
; Test a case where the fp128 address is passed on the stack.
|
||||
define void @f13(fp128 *%r2, i16 %r3, i32 %r4, i64 %r5, float %f0, double %f2,
|
||||
fp128 %r6, i64 %s1, float %f4, double %f6, i64 %s2,
|
||||
float %s3, fp128 %s4) {
|
||||
; CHECK: f13:
|
||||
; CHECK: lg [[REGISTER:%r[1-5]+]], 184(%r15)
|
||||
; CHECK: ld %f0, 0([[REGISTER]])
|
||||
; CHECK: ld %f2, 8([[REGISTER]])
|
||||
; CHECK: axbr %f0, %f0
|
||||
; CHECK: std %f0, 0(%r2)
|
||||
; CHECK: std %f2, 8(%r2)
|
||||
; CHECK: br %r14
|
||||
%y = fadd fp128 %s4, %s4
|
||||
store fp128 %y, fp128 *%r2
|
||||
ret void
|
||||
}
|
47
test/CodeGen/SystemZ/args-05.ll
Normal file
47
test/CodeGen/SystemZ/args-05.ll
Normal file
@ -0,0 +1,47 @@
|
||||
; Test that we take advantage of signext and zeroext annotations.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Zero extension of something that is already zero-extended.
|
||||
define void @f1(i32 zeroext %r2, i64 *%r3) {
|
||||
; CHECK: f1:
|
||||
; CHECK-NOT: %r2
|
||||
; CHECK: stg %r2, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%conv = zext i32 %r2 to i64
|
||||
store i64 %conv, i64* %r3
|
||||
ret void
|
||||
}
|
||||
|
||||
; Sign extension of something that is already sign-extended.
|
||||
define void @f2(i32 signext %r2, i64 *%r3) {
|
||||
; CHECK: f2:
|
||||
; CHECK-NOT: %r2
|
||||
; CHECK: stg %r2, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%conv = sext i32 %r2 to i64
|
||||
store i64 %conv, i64* %r3
|
||||
ret void
|
||||
}
|
||||
|
||||
; Sign extension of something that is already zero-extended.
|
||||
define void @f3(i32 zeroext %r2, i64 *%r3) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lgfr [[REGISTER:%r[0-5]+]], %r2
|
||||
; CHECK: stg [[REGISTER]], 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%conv = sext i32 %r2 to i64
|
||||
store i64 %conv, i64* %r3
|
||||
ret void
|
||||
}
|
||||
|
||||
; Zero extension of something that is already sign-extended.
|
||||
define void @f4(i32 signext %r2, i64 *%r3) {
|
||||
; CHECK: f4:
|
||||
; CHECK: llgfr [[REGISTER:%r[0-5]+]], %r2
|
||||
; CHECK: stg [[REGISTER]], 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%conv = zext i32 %r2 to i64
|
||||
store i64 %conv, i64* %r3
|
||||
ret void
|
||||
}
|
76
test/CodeGen/SystemZ/args-06.ll
Normal file
76
test/CodeGen/SystemZ/args-06.ll
Normal file
@ -0,0 +1,76 @@
|
||||
; Test the padding of unextended integer stack parameters. These are used
|
||||
; to pass structures.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define i8 @f1(i8 %a, i8 %b, i8 %c, i8 %d, i8 %e, i8 %f, i8 %g) {
|
||||
; CHECK: f1:
|
||||
; CHECK: ar %r2, %r3
|
||||
; CHECK: ar %r2, %r4
|
||||
; CHECK: ar %r2, %r5
|
||||
; CHECK: ar %r2, %r6
|
||||
; CHECK: lb {{%r[0-5]}}, 167(%r15)
|
||||
; CHECK: lb {{%r[0-5]}}, 175(%r15)
|
||||
; CHECK: br %r14
|
||||
%addb = add i8 %a, %b
|
||||
%addc = add i8 %addb, %c
|
||||
%addd = add i8 %addc, %d
|
||||
%adde = add i8 %addd, %e
|
||||
%addf = add i8 %adde, %f
|
||||
%addg = add i8 %addf, %g
|
||||
ret i8 %addg
|
||||
}
|
||||
|
||||
define i16 @f2(i16 %a, i16 %b, i16 %c, i16 %d, i16 %e, i16 %f, i16 %g) {
|
||||
; CHECK: f2:
|
||||
; CHECK: ar %r2, %r3
|
||||
; CHECK: ar %r2, %r4
|
||||
; CHECK: ar %r2, %r5
|
||||
; CHECK: ar %r2, %r6
|
||||
; CHECK: lh {{%r[0-5]}}, 166(%r15)
|
||||
; CHECK: lh {{%r[0-5]}}, 174(%r15)
|
||||
; CHECK: br %r14
|
||||
%addb = add i16 %a, %b
|
||||
%addc = add i16 %addb, %c
|
||||
%addd = add i16 %addc, %d
|
||||
%adde = add i16 %addd, %e
|
||||
%addf = add i16 %adde, %f
|
||||
%addg = add i16 %addf, %g
|
||||
ret i16 %addg
|
||||
}
|
||||
|
||||
define i32 @f3(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g) {
|
||||
; CHECK: f3:
|
||||
; CHECK: ar %r2, %r3
|
||||
; CHECK: ar %r2, %r4
|
||||
; CHECK: ar %r2, %r5
|
||||
; CHECK: ar %r2, %r6
|
||||
; CHECK: a %r2, 164(%r15)
|
||||
; CHECK: a %r2, 172(%r15)
|
||||
; CHECK: br %r14
|
||||
%addb = add i32 %a, %b
|
||||
%addc = add i32 %addb, %c
|
||||
%addd = add i32 %addc, %d
|
||||
%adde = add i32 %addd, %e
|
||||
%addf = add i32 %adde, %f
|
||||
%addg = add i32 %addf, %g
|
||||
ret i32 %addg
|
||||
}
|
||||
|
||||
define i64 @f4(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i64 %g) {
|
||||
; CHECK: f4:
|
||||
; CHECK: agr %r2, %r3
|
||||
; CHECK: agr %r2, %r4
|
||||
; CHECK: agr %r2, %r5
|
||||
; CHECK: agr %r2, %r6
|
||||
; CHECK: ag %r2, 160(%r15)
|
||||
; CHECK: ag %r2, 168(%r15)
|
||||
; CHECK: br %r14
|
||||
%addb = add i64 %a, %b
|
||||
%addc = add i64 %addb, %c
|
||||
%addd = add i64 %addc, %d
|
||||
%adde = add i64 %addd, %e
|
||||
%addf = add i64 %adde, %f
|
||||
%addg = add i64 %addf, %g
|
||||
ret i64 %addg
|
||||
}
|
61
test/CodeGen/SystemZ/asm-01.ll
Normal file
61
test/CodeGen/SystemZ/asm-01.ll
Normal file
@ -0,0 +1,61 @@
|
||||
; Test the "Q" asm constraint, which accepts addresses that have a base
|
||||
; and a 12-bit displacement.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check the lowest range.
|
||||
define void @f1(i64 %base) {
|
||||
; CHECK: f1:
|
||||
; CHECK: blah 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%addr = inttoptr i64 %base to i64 *
|
||||
call void asm "blah $0", "=*Q" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next lowest byte.
|
||||
define void @f2(i64 %base) {
|
||||
; CHECK: f2:
|
||||
; CHECK: aghi %r2, -1
|
||||
; CHECK: blah 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, -1
|
||||
%addr = inttoptr i64 %add to i64 *
|
||||
call void asm "blah $0", "=*Q" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the highest range.
|
||||
define void @f3(i64 %base) {
|
||||
; CHECK: f3:
|
||||
; CHECK: blah 4095(%r2)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, 4095
|
||||
%addr = inttoptr i64 %add to i64 *
|
||||
call void asm "blah $0", "=*Q" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next highest byte.
|
||||
define void @f4(i64 %base) {
|
||||
; CHECK: f4:
|
||||
; CHECK: aghi %r2, 4096
|
||||
; CHECK: blah 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, 4096
|
||||
%addr = inttoptr i64 %add to i64 *
|
||||
call void asm "blah $0", "=*Q" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check that indices aren't allowed
|
||||
define void @f5(i64 %base, i64 %index) {
|
||||
; CHECK: f5:
|
||||
; CHECK: agr %r2, %r3
|
||||
; CHECK: blah 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, %index
|
||||
%addr = inttoptr i64 %add to i64 *
|
||||
call void asm "blah $0", "=*Q" (i64 *%addr)
|
||||
ret void
|
||||
}
|
52
test/CodeGen/SystemZ/asm-02.ll
Normal file
52
test/CodeGen/SystemZ/asm-02.ll
Normal file
@ -0,0 +1,52 @@
|
||||
; Test the "R" asm constraint, which accepts addresses that have a base,
|
||||
; an index and a 12-bit displacement.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check the lowest range.
|
||||
define void @f1(i64 %base) {
|
||||
; CHECK: f1:
|
||||
; CHECK: blah 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%addr = inttoptr i64 %base to i64 *
|
||||
call void asm "blah $0", "=*R" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next lowest byte.
|
||||
define void @f2(i64 %base) {
|
||||
; CHECK: f2:
|
||||
; CHECK: aghi %r2, -1
|
||||
; CHECK: blah 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, -1
|
||||
%addr = inttoptr i64 %add to i64 *
|
||||
call void asm "blah $0", "=*R" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the highest range.
|
||||
define void @f3(i64 %base) {
|
||||
; CHECK: f3:
|
||||
; CHECK: blah 4095(%r2)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, 4095
|
||||
%addr = inttoptr i64 %add to i64 *
|
||||
call void asm "blah $0", "=*R" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next highest byte.
|
||||
define void @f4(i64 %base) {
|
||||
; CHECK: f4:
|
||||
; CHECK: aghi %r2, 4096
|
||||
; CHECK: blah 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, 4096
|
||||
%addr = inttoptr i64 %add to i64 *
|
||||
call void asm "blah $0", "=*R" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; FIXME: at the moment the precise constraint is not passed down to
|
||||
; target code, so we must conservatively treat "R" as "Q".
|
16
test/CodeGen/SystemZ/asm-03.ll
Normal file
16
test/CodeGen/SystemZ/asm-03.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; Test the "S" asm constraint, which accepts addresses that have a base
|
||||
; and a 20-bit displacement.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define void @f1(i64 %base) {
|
||||
; CHECK: f1:
|
||||
; CHECK: blah 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%addr = inttoptr i64 %base to i64 *
|
||||
call void asm "blah $0", "=*S" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; FIXME: at the moment the precise constraint is not passed down to
|
||||
; target code, so we must conservatively treat "S" as "Q".
|
16
test/CodeGen/SystemZ/asm-04.ll
Normal file
16
test/CodeGen/SystemZ/asm-04.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; Test the "T" asm constraint, which accepts addresses that have a base,
|
||||
; an index and a 20-bit displacement.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define void @f1(i64 %base) {
|
||||
; CHECK: f1:
|
||||
; CHECK: blah 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%addr = inttoptr i64 %base to i64 *
|
||||
call void asm "blah $0", "=*T" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; FIXME: at the moment the precise constraint is not passed down to
|
||||
; target code, so we must conservatively treat "T" as "Q".
|
15
test/CodeGen/SystemZ/asm-05.ll
Normal file
15
test/CodeGen/SystemZ/asm-05.ll
Normal file
@ -0,0 +1,15 @@
|
||||
; Test the "m" asm constraint, which is equivalent to "T".
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define void @f1(i64 %base) {
|
||||
; CHECK: f1:
|
||||
; CHECK: blah 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%addr = inttoptr i64 %base to i64 *
|
||||
call void asm "blah $0", "=*m" (i64 *%addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
; FIXME: at the moment the precise constraint is not passed down to
|
||||
; target code, so we must conservatively treat "m" as "Q".
|
39
test/CodeGen/SystemZ/asm-06.ll
Normal file
39
test/CodeGen/SystemZ/asm-06.ll
Normal file
@ -0,0 +1,39 @@
|
||||
; Test the GPR constraint "a", which forbids %r0.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define i64 @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: lhi %r1, 1
|
||||
; CHECK: blah %r2 %r1
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=r,a" (i8 1)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: lhi %r1, 2
|
||||
; CHECK: blah %r2 %r1
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=r,a" (i16 2)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK: lhi %r1, 3
|
||||
; CHECK: blah %r2 %r1
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=r,a" (i32 3)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f4() {
|
||||
; CHECK: f4:
|
||||
; CHECK: lghi %r1, 4
|
||||
; CHECK: blah %r2 %r1
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=r,a" (i64 4)
|
||||
ret i64 %val
|
||||
}
|
39
test/CodeGen/SystemZ/asm-07.ll
Normal file
39
test/CodeGen/SystemZ/asm-07.ll
Normal file
@ -0,0 +1,39 @@
|
||||
; Test the GPR constraint "r".
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define i64 @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: lhi %r0, 1
|
||||
; CHECK: blah %r2 %r0
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=r,r" (i8 1)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: lhi %r0, 2
|
||||
; CHECK: blah %r2 %r0
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=r,r" (i16 2)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK: lhi %r0, 3
|
||||
; CHECK: blah %r2 %r0
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=r,r" (i32 3)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f4() {
|
||||
; CHECK: f4:
|
||||
; CHECK: lghi %r0, 4
|
||||
; CHECK: blah %r2 %r0
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=r,r" (i64 4)
|
||||
ret i64 %val
|
||||
}
|
39
test/CodeGen/SystemZ/asm-08.ll
Normal file
39
test/CodeGen/SystemZ/asm-08.ll
Normal file
@ -0,0 +1,39 @@
|
||||
; Test the GPR constraint "d", which is equivalent to "r".
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define i64 @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: lhi %r0, 1
|
||||
; CHECK: blah %r2 %r0
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=d,d" (i8 1)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: lhi %r0, 2
|
||||
; CHECK: blah %r2 %r0
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=d,d" (i16 2)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK: lhi %r0, 3
|
||||
; CHECK: blah %r2 %r0
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=d,d" (i32 3)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f4() {
|
||||
; CHECK: f4:
|
||||
; CHECK: lghi %r0, 4
|
||||
; CHECK: blah %r2 %r0
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0 $1", "=d,d" (i64 4)
|
||||
ret i64 %val
|
||||
}
|
83
test/CodeGen/SystemZ/asm-09.ll
Normal file
83
test/CodeGen/SystemZ/asm-09.ll
Normal file
@ -0,0 +1,83 @@
|
||||
; Test matching operands with the GPR constraint "r".
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define void @f1(i32 *%dst) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lhi %r0, 100
|
||||
; CHECK: blah %r0
|
||||
; CHECK: st %r0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0", "=r,0" (i8 100)
|
||||
store i32 %val, i32 *%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f2(i32 *%dst) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lhi %r0, 101
|
||||
; CHECK: blah %r0
|
||||
; CHECK: st %r0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0", "=r,0" (i16 101)
|
||||
store i32 %val, i32 *%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f3(i32 *%dst) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lhi %r0, 102
|
||||
; CHECK: blah %r0
|
||||
; CHECK: st %r0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0", "=r,0" (i32 102)
|
||||
store i32 %val, i32 *%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
; FIXME: this uses "lhi %r0, 103", but should use "lghi %r0, 103".
|
||||
define void @f4(i32 *%dst) {
|
||||
; CHECK: f4:
|
||||
; CHECK: blah %r0
|
||||
; CHECK: st %r0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0", "=r,0" (i64 103)
|
||||
store i32 %val, i32 *%dst
|
||||
ret void
|
||||
}
|
||||
|
||||
define i64 @f5() {
|
||||
; CHECK: f5:
|
||||
; CHECK: lghi %r2, 104
|
||||
; CHECK: blah %r2
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0", "=r,0" (i8 104)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f6() {
|
||||
; CHECK: f6:
|
||||
; CHECK: lghi %r2, 105
|
||||
; CHECK: blah %r2
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0", "=r,0" (i16 105)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f7() {
|
||||
; CHECK: f7:
|
||||
; CHECK: lghi %r2, 106
|
||||
; CHECK: blah %r2
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0", "=r,0" (i32 106)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
define i64 @f8() {
|
||||
; CHECK: f8:
|
||||
; CHECK: lghi %r2, 107
|
||||
; CHECK: blah %r2
|
||||
; CHECK: br %r14
|
||||
%val = call i64 asm "blah $0", "=r,0" (i64 107)
|
||||
ret i64 %val
|
||||
}
|
30
test/CodeGen/SystemZ/asm-10.ll
Normal file
30
test/CodeGen/SystemZ/asm-10.ll
Normal file
@ -0,0 +1,30 @@
|
||||
; Test the FPR constraint "f".
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define float @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: lzer %f1
|
||||
; CHECK: blah %f0 %f1
|
||||
; CHECK: br %r14
|
||||
%val = call float asm "blah $0 $1", "=&f,f" (float 0.0)
|
||||
ret float %val
|
||||
}
|
||||
|
||||
define double @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: lzdr %f1
|
||||
; CHECK: blah %f0 %f1
|
||||
; CHECK: br %r14
|
||||
%val = call double asm "blah $0 $1", "=&f,f" (double 0.0)
|
||||
ret double %val
|
||||
}
|
||||
|
||||
define double @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK: lzxr %f1
|
||||
; CHECK: blah %f0 %f1
|
||||
; CHECK: br %r14
|
||||
%val = call double asm "blah $0 $1", "=&f,f" (fp128 0xL00000000000000000000000000000000)
|
||||
ret double %val
|
||||
}
|
41
test/CodeGen/SystemZ/asm-11.ll
Normal file
41
test/CodeGen/SystemZ/asm-11.ll
Normal file
@ -0,0 +1,41 @@
|
||||
; Test the "I" constraint (8-bit unsigned constants).
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Test 1 below the first valid value.
|
||||
define i32 @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: lhi [[REG:%r[0-5]]], -1
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rI" (i32 -1)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test the first valid value.
|
||||
define i32 @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: blah %r2 0
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rI" (i32 0)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test the last valid value.
|
||||
define i32 @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK: blah %r2 255
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rI" (i32 255)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test 1 above the last valid value.
|
||||
define i32 @f4() {
|
||||
; CHECK: f4:
|
||||
; CHECK: lhi [[REG:%r[0-5]]], 256
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rI" (i32 256)
|
||||
ret i32 %val
|
||||
}
|
41
test/CodeGen/SystemZ/asm-12.ll
Normal file
41
test/CodeGen/SystemZ/asm-12.ll
Normal file
@ -0,0 +1,41 @@
|
||||
; Test the "J" constraint (12-bit unsigned constants).
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Test 1 below the first valid value.
|
||||
define i32 @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: lhi [[REG:%r[0-5]]], -1
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rJ" (i32 -1)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test the first valid value.
|
||||
define i32 @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: blah %r2 0
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rJ" (i32 0)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test the last valid value.
|
||||
define i32 @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK: blah %r2 4095
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rJ" (i32 4095)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test 1 above the last valid value.
|
||||
define i32 @f4() {
|
||||
; CHECK: f4:
|
||||
; CHECK: lhi [[REG:%r[0-5]]], 4096
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rJ" (i32 4096)
|
||||
ret i32 %val
|
||||
}
|
41
test/CodeGen/SystemZ/asm-13.ll
Normal file
41
test/CodeGen/SystemZ/asm-13.ll
Normal file
@ -0,0 +1,41 @@
|
||||
; Test the "K" constraint (16-bit signed constants).
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Test 1 below the first valid value.
|
||||
define i32 @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: iilf [[REG:%r[0-5]]], 4294934527
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rK" (i32 -32769)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test the first valid value.
|
||||
define i32 @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: blah %r2 -32768
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rK" (i32 -32768)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test the last valid value.
|
||||
define i32 @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK: blah %r2 32767
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rK" (i32 32767)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test 1 above the last valid value.
|
||||
define i32 @f4() {
|
||||
; CHECK: f4:
|
||||
; CHECK: llill [[REG:%r[0-5]]], 32768
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rK" (i32 32768)
|
||||
ret i32 %val
|
||||
}
|
41
test/CodeGen/SystemZ/asm-14.ll
Normal file
41
test/CodeGen/SystemZ/asm-14.ll
Normal file
@ -0,0 +1,41 @@
|
||||
; Test the "L" constraint (20-bit signed constants).
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Test 1 below the first valid value.
|
||||
define i32 @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: iilf [[REG:%r[0-5]]], 4294443007
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rL" (i32 -524289)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test the first valid value.
|
||||
define i32 @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: blah %r2 -524288
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rL" (i32 -524288)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test the last valid value.
|
||||
define i32 @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK: blah %r2 524287
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rL" (i32 524287)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test 1 above the last valid value.
|
||||
define i32 @f4() {
|
||||
; CHECK: f4:
|
||||
; CHECK: llilh [[REG:%r[0-5]]], 8
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rL" (i32 524288)
|
||||
ret i32 %val
|
||||
}
|
32
test/CodeGen/SystemZ/asm-15.ll
Normal file
32
test/CodeGen/SystemZ/asm-15.ll
Normal file
@ -0,0 +1,32 @@
|
||||
; Test the "M" constraint (0x7fffffff)
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Test 1 below the valid value.
|
||||
define i32 @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: iilf [[REG:%r[0-5]]], 2147483646
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rM" (i32 2147483646)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test the first valid value.
|
||||
define i32 @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: blah %r2 2147483647
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rM" (i32 2147483647)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test 1 above the valid value.
|
||||
define i32 @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK: llilh [[REG:%r[0-5]]], 32768
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rM" (i32 2147483648)
|
||||
ret i32 %val
|
||||
}
|
32
test/CodeGen/SystemZ/asm-16.ll
Normal file
32
test/CodeGen/SystemZ/asm-16.ll
Normal file
@ -0,0 +1,32 @@
|
||||
; Test the "M" constraint (0x7fffffff)
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Test 1 below the valid value.
|
||||
define i32 @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: iilf [[REG:%r[0-5]]], 2147483646
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rM" (i32 2147483646)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test the first valid value.
|
||||
define i32 @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: blah %r2 2147483647
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rM" (i32 2147483647)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Test 1 above the valid value.
|
||||
define i32 @f3() {
|
||||
; CHECK: f3:
|
||||
; CHECK: llilh [[REG:%r[0-5]]], 32768
|
||||
; CHECK: blah %r2 [[REG]]
|
||||
; CHECK: br %r14
|
||||
%val = call i32 asm "blah $0 $1", "=&r,rM" (i32 2147483648)
|
||||
ret i32 %val
|
||||
}
|
13
test/CodeGen/SystemZ/atomic-load-01.ll
Normal file
13
test/CodeGen/SystemZ/atomic-load-01.ll
Normal file
@ -0,0 +1,13 @@
|
||||
; Test 8-bit atomic loads.
|
||||
;
|
||||
; 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: f1:
|
||||
; CHECK: cs
|
||||
; CHECK: br %r14
|
||||
%val = load atomic i8 *%src seq_cst, align 1
|
||||
ret i8 %val
|
||||
}
|
13
test/CodeGen/SystemZ/atomic-load-02.ll
Normal file
13
test/CodeGen/SystemZ/atomic-load-02.ll
Normal file
@ -0,0 +1,13 @@
|
||||
; Test 16-bit atomic loads.
|
||||
;
|
||||
; 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: f1:
|
||||
; CHECK: cs
|
||||
; CHECK: br %r14
|
||||
%val = load atomic i16 *%src seq_cst, align 2
|
||||
ret i16 %val
|
||||
}
|
14
test/CodeGen/SystemZ/atomic-load-03.ll
Normal file
14
test/CodeGen/SystemZ/atomic-load-03.ll
Normal file
@ -0,0 +1,14 @@
|
||||
; Test 32-bit atomic loads.
|
||||
;
|
||||
; 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) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lhi %r2, 0
|
||||
; CHECK: cs %r2, %r2, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%val = load atomic i32 *%src seq_cst, align 4
|
||||
ret i32 %val
|
||||
}
|
14
test/CodeGen/SystemZ/atomic-load-04.ll
Normal file
14
test/CodeGen/SystemZ/atomic-load-04.ll
Normal file
@ -0,0 +1,14 @@
|
||||
; Test 64-bit atomic loads.
|
||||
;
|
||||
; 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) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lghi %r2, 0
|
||||
; CHECK: csg %r2, %r2, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%val = load atomic i64 *%src seq_cst, align 8
|
||||
ret i64 %val
|
||||
}
|
13
test/CodeGen/SystemZ/atomic-store-01.ll
Normal file
13
test/CodeGen/SystemZ/atomic-store-01.ll
Normal file
@ -0,0 +1,13 @@
|
||||
; Test 8-bit atomic stores.
|
||||
;
|
||||
; 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: f1:
|
||||
; CHECK: cs
|
||||
; CHECK: br %r14
|
||||
store atomic i8 %val, i8 *%src seq_cst, align 1
|
||||
ret void
|
||||
}
|
13
test/CodeGen/SystemZ/atomic-store-02.ll
Normal file
13
test/CodeGen/SystemZ/atomic-store-02.ll
Normal file
@ -0,0 +1,13 @@
|
||||
; Test 16-bit atomic stores.
|
||||
;
|
||||
; 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: f1:
|
||||
; CHECK: cs
|
||||
; CHECK: br %r14
|
||||
store atomic i16 %val, i16 *%src seq_cst, align 2
|
||||
ret void
|
||||
}
|
16
test/CodeGen/SystemZ/atomic-store-03.ll
Normal file
16
test/CodeGen/SystemZ/atomic-store-03.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; Test 32-bit atomic stores.
|
||||
;
|
||||
; 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: f1:
|
||||
; CHECK: l %r0, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: cs %r0, %r2, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
store atomic i32 %val, i32 *%src seq_cst, align 4
|
||||
ret void
|
||||
}
|
16
test/CodeGen/SystemZ/atomic-store-04.ll
Normal file
16
test/CodeGen/SystemZ/atomic-store-04.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; Test 64-bit atomic stores.
|
||||
;
|
||||
; 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: f1:
|
||||
; CHECK: lg %r0, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: csg %r0, %r2, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
store atomic i64 %val, i64 *%src seq_cst, align 8
|
||||
ret void
|
||||
}
|
132
test/CodeGen/SystemZ/atomicrmw-add-01.ll
Normal file
132
test/CodeGen/SystemZ/atomicrmw-add-01.ll
Normal file
@ -0,0 +1,132 @@
|
||||
; Test 8-bit atomic additions.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check addition of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used. This shift is independent of the other loop prologue
|
||||
; instructions.
|
||||
define i8 @f1(i8 *%src, i8 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: ar [[ROT]], %r3
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 24
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: ar {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We add 0x80000000 to the rotated word.
|
||||
define i8 @f2(i8 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: afi [[ROT]], -2147483648
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i8 *%src, i8 -128 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check addition of -1. We add 0xff000000 to the rotated word.
|
||||
define i8 @f3(i8 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: afi [[ROT]], -16777216
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i8 *%src, i8 -1 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check addition of 1. We add 0x01000000 to the rotated word.
|
||||
define i8 @f4(i8 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: afi [[ROT]], 16777216
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i8 *%src, i8 1 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We add 0x7f000000 to the rotated word.
|
||||
define i8 @f5(i8 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: afi [[ROT]], 2130706432
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i8 *%src, i8 127 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check addition of a large unsigned value. We add 0xfe000000 to the
|
||||
; rotated word, expressed as a negative AFI operand.
|
||||
define i8 @f6(i8 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: afi [[ROT]], -33554432
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i8 *%src, i8 254 seq_cst
|
||||
ret i8 %res
|
||||
}
|
132
test/CodeGen/SystemZ/atomicrmw-add-02.ll
Normal file
132
test/CodeGen/SystemZ/atomicrmw-add-02.ll
Normal file
@ -0,0 +1,132 @@
|
||||
; Test 16-bit atomic additions.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check addition of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used. This shift is independent of the other loop prologue
|
||||
; instructions.
|
||||
define i16 @f1(i16 *%src, i16 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: ar [[ROT]], %r3
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 16
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: ar {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We add 0x80000000 to the rotated word.
|
||||
define i16 @f2(i16 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: afi [[ROT]], -2147483648
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i16 *%src, i16 -32768 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check addition of -1. We add 0xffff0000 to the rotated word.
|
||||
define i16 @f3(i16 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: afi [[ROT]], -65536
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i16 *%src, i16 -1 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check addition of 1. We add 0x00010000 to the rotated word.
|
||||
define i16 @f4(i16 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: afi [[ROT]], 65536
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i16 *%src, i16 1 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We add 0x7fff0000 to the rotated word.
|
||||
define i16 @f5(i16 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: afi [[ROT]], 2147418112
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i16 *%src, i16 32767 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check addition of a large unsigned value. We add 0xfffe0000 to the
|
||||
; rotated word, expressed as a negative AFI operand.
|
||||
define i16 @f6(i16 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: afi [[ROT]], -131072
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw add i16 *%src, i16 65534 seq_cst
|
||||
ret i16 %res
|
||||
}
|
94
test/CodeGen/SystemZ/atomicrmw-add-03.ll
Normal file
94
test/CodeGen/SystemZ/atomicrmw-add-03.ll
Normal file
@ -0,0 +1,94 @@
|
||||
; Test 32-bit atomic additions.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check addition of a variable.
|
||||
define i32 @f1(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: ar %r0, %r4
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check addition of 1, which can use AHI.
|
||||
define i32 @f2(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: ahi %r0, 1
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i32 *%src, i32 1 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the AHI range.
|
||||
define i32 @f3(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: ahi %r0, 32767
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i32 *%src, i32 32767 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use AFI.
|
||||
define i32 @f4(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: afi %r0, 32768
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i32 *%src, i32 32768 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the AFI range.
|
||||
define i32 @f5(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: afi %r0, 2147483647
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i32 *%src, i32 2147483647 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which gets treated as a negative operand.
|
||||
define i32 @f6(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: afi %r0, -2147483648
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i32 *%src, i32 2147483648 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check addition of -1, which can use AHI.
|
||||
define i32 @f7(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: ahi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i32 *%src, i32 -1 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the low end of the AHI range.
|
||||
define i32 @f8(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: ahi %r0, -32768
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i32 *%src, i32 -32768 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next value down, which must use AFI instead.
|
||||
define i32 @f9(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f9:
|
||||
; CHECK: afi %r0, -32769
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i32 *%src, i32 -32769 seq_cst
|
||||
ret i32 %res
|
||||
}
|
112
test/CodeGen/SystemZ/atomicrmw-add-04.ll
Normal file
112
test/CodeGen/SystemZ/atomicrmw-add-04.ll
Normal file
@ -0,0 +1,112 @@
|
||||
; Test 64-bit atomic additions.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check addition of a variable.
|
||||
define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: agr %r0, %r4
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check addition of 1, which can use AGHI.
|
||||
define i64 @f2(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: aghi %r0, 1
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 1 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the AGHI range.
|
||||
define i64 @f3(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: aghi %r0, 32767
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 32767 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use AGFI.
|
||||
define i64 @f4(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: agfi %r0, 32768
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 32768 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the AGFI range.
|
||||
define i64 @f5(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: agfi %r0, 2147483647
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 2147483647 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use a register addition.
|
||||
define i64 @f6(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: agr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 2147483648 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check addition of -1, which can use AGHI.
|
||||
define i64 @f7(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 -1 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the AGHI range.
|
||||
define i64 @f8(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: aghi %r0, -32768
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 -32768 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value down, which must use AGFI instead.
|
||||
define i64 @f9(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f9:
|
||||
; CHECK: agfi %r0, -32769
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 -32769 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the AGFI range.
|
||||
define i64 @f10(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f10:
|
||||
; CHECK: agfi %r0, -2147483648
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 -2147483648 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value down, which must use a register addition.
|
||||
define i64 @f11(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f11:
|
||||
; CHECK: agr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw add i64 *%src, i64 -2147483649 seq_cst
|
||||
ret i64 %res
|
||||
}
|
133
test/CodeGen/SystemZ/atomicrmw-and-01.ll
Normal file
133
test/CodeGen/SystemZ/atomicrmw-and-01.ll
Normal file
@ -0,0 +1,133 @@
|
||||
; Test 8-bit atomic ANDs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check AND of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used, and that the low bits are set to 1. This sequence is
|
||||
; independent of the other loop prologue instructions.
|
||||
define i8 @f1(i8 *%src, i8 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: nr [[ROT]], %r3
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 24
|
||||
; CHECK-SHIFT2: oilf %r3, 16777215
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: nr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We AND the rotated word with 0x80ffffff.
|
||||
define i8 @f2(i8 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: nilh [[ROT]], 33023
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i8 *%src, i8 -128 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check ANDs of -2 (-1 isn't useful). We AND the rotated word with 0xfeffffff.
|
||||
define i8 @f3(i8 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: nilh [[ROT]], 65279
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i8 *%src, i8 -2 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check ANDs of 1. We AND the rotated word with 0x01ffffff.
|
||||
define i8 @f4(i8 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: nilh [[ROT]], 511
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i8 *%src, i8 1 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We AND the rotated word with 0x7fffffff.
|
||||
define i8 @f5(i8 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: nilh [[ROT]], 32767
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i8 *%src, i8 127 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check ANDs of a large unsigned value. We AND the rotated word with
|
||||
; 0xfdffffff.
|
||||
define i8 @f6(i8 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: nilh [[ROT]], 65023
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i8 *%src, i8 253 seq_cst
|
||||
ret i8 %res
|
||||
}
|
133
test/CodeGen/SystemZ/atomicrmw-and-02.ll
Normal file
133
test/CodeGen/SystemZ/atomicrmw-and-02.ll
Normal file
@ -0,0 +1,133 @@
|
||||
; Test 16-bit atomic ANDs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check AND of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used, and that the low bits are set to 1. This sequence is
|
||||
; independent of the other loop prologue instructions.
|
||||
define i16 @f1(i16 *%src, i16 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: nr [[ROT]], %r3
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 16
|
||||
; CHECK-SHIFT2: oill %r3, 65535
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: nr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We AND the rotated word with 0x8000ffff.
|
||||
define i16 @f2(i16 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: nilh [[ROT]], 32768
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i16 *%src, i16 -32768 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check ANDs of -2 (-1 isn't useful). We AND the rotated word with 0xfffeffff.
|
||||
define i16 @f3(i16 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: nilh [[ROT]], 65534
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i16 *%src, i16 -2 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check ANDs of 1. We AND the rotated word with 0x0001ffff.
|
||||
define i16 @f4(i16 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: nilh [[ROT]], 1
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i16 *%src, i16 1 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We AND the rotated word with 0x7fffffff.
|
||||
define i16 @f5(i16 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: nilh [[ROT]], 32767
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i16 *%src, i16 32767 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check ANDs of a large unsigned value. We AND the rotated word with
|
||||
; 0xfffdffff.
|
||||
define i16 @f6(i16 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: nilh [[ROT]], 65533
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw and i16 *%src, i16 65533 seq_cst
|
||||
ret i16 %res
|
||||
}
|
85
test/CodeGen/SystemZ/atomicrmw-and-03.ll
Normal file
85
test/CodeGen/SystemZ/atomicrmw-and-03.ll
Normal file
@ -0,0 +1,85 @@
|
||||
; Test 32-bit atomic ANDs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check ANDs of a variable.
|
||||
define i32 @f1(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: nr %r0, %r4
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check ANDs of 1.
|
||||
define i32 @f2(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: nilf %r0, 1
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i32 *%src, i32 1 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check ANDs of the low end of the NILH range.
|
||||
define i32 @f3(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: nilh %r0, 0
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i32 *%src, i32 65535 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use NILF.
|
||||
define i32 @f4(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: nilf %r0, 65536
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i32 *%src, i32 65536 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the largest useful NILL value.
|
||||
define i32 @f5(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: nill %r0, 65534
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i32 *%src, i32 -2 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NILL range.
|
||||
define i32 @f6(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: nill %r0, 0
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i32 *%src, i32 -65536 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the largest useful NILH value, which is one less than the above.
|
||||
define i32 @f7(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: nilh %r0, 65534
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i32 *%src, i32 -65537 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NILF value, which is one less than the above.
|
||||
define i32 @f8(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: nilf %r0, 4294901758
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i32 *%src, i32 -65538 seq_cst
|
||||
ret i32 %res
|
||||
}
|
157
test/CodeGen/SystemZ/atomicrmw-and-04.ll
Normal file
157
test/CodeGen/SystemZ/atomicrmw-and-04.ll
Normal file
@ -0,0 +1,157 @@
|
||||
; Test 64-bit atomic ANDs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check ANDs of a variable.
|
||||
define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: ngr %r0, %r4
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check ANDs of 1, which must be done using a register.
|
||||
define i64 @f2(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: ngr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 1 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NIHF range.
|
||||
define i64 @f3(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: nihf %r0, 0
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 4294967295 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use a register.
|
||||
define i64 @f4(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: ngr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 4294967296 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NIHH range.
|
||||
define i64 @f5(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: nihh %r0, 0
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 281474976710655 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use a register.
|
||||
define i64 @f6(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: ngr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 281474976710656 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NILL value.
|
||||
define i64 @f7(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: nill %r0, 65534
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 -2 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NILL range.
|
||||
define i64 @f8(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: nill %r0, 0
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 -65536 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NILH value, which is one less than the above.
|
||||
define i64 @f9(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f9:
|
||||
; CHECK: nilh %r0, 65534
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 -65537 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NILF value, which is one less than the above.
|
||||
define i64 @f10(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f10:
|
||||
; CHECK: nilf %r0, 4294901758
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 -65538 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NILH range.
|
||||
define i64 @f11(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f11:
|
||||
; CHECK: nilh %r0, 0
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 -4294901761 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NILF range.
|
||||
define i64 @f12(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f12:
|
||||
; CHECK: nilf %r0, 0
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 -4294967296 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NIHL value, which is one less than the above.
|
||||
define i64 @f13(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f13:
|
||||
; CHECK: nihl %r0, 65534
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 -4294967297 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NIHL range.
|
||||
define i64 @f14(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f14:
|
||||
; CHECK: nihl %r0, 0
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 -281470681743361 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NIHH value, which is 1<<32 less than the above.
|
||||
define i64 @f15(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f15:
|
||||
; CHECK: nihh %r0, 65534
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 -281474976710657 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NIHF value, which is 1<<32 less than the above.
|
||||
define i64 @f16(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f16:
|
||||
; CHECK: nihf %r0, 4294901758
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw and i64 *%src, i64 -281479271677953 seq_cst
|
||||
ret i64 %res
|
||||
}
|
228
test/CodeGen/SystemZ/atomicrmw-minmax-01.ll
Normal file
228
test/CodeGen/SystemZ/atomicrmw-minmax-01.ll
Normal file
@ -0,0 +1,228 @@
|
||||
; Test 8-bit atomic min/max operations.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check signed minimum.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used, and that the low bits are set to 1. This sequence is
|
||||
; independent of the other loop prologue instructions.
|
||||
define i8 @f1(i8 *%src, i8 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: cr [[ROT]], %r3
|
||||
; CHECK: j{{g?}}le [[KEEP:\..*]]
|
||||
; CHECK: risbg [[ROT]], %r3, 32, 39, 0
|
||||
; CHECK: [[KEEP]]:
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 24
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: cr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw min i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check signed maximum.
|
||||
define i8 @f2(i8 *%src, i8 %b) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: cr [[ROT]], %r3
|
||||
; CHECK: j{{g?}}he [[KEEP:\..*]]
|
||||
; CHECK: risbg [[ROT]], %r3, 32, 39, 0
|
||||
; CHECK: [[KEEP]]:
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: sll %r3, 24
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: cr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw max i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check unsigned minimum.
|
||||
define i8 @f3(i8 *%src, i8 %b) {
|
||||
; CHECK: f3:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: clr [[ROT]], %r3
|
||||
; CHECK: j{{g?}}le [[KEEP:\..*]]
|
||||
; CHECK: risbg [[ROT]], %r3, 32, 39, 0
|
||||
; CHECK: [[KEEP]]:
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: sll %r3, 24
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: clr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw umin i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check unsigned maximum.
|
||||
define i8 @f4(i8 *%src, i8 %b) {
|
||||
; CHECK: f4:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: clr [[ROT]], %r3
|
||||
; CHECK: j{{g?}}he [[KEEP:\..*]]
|
||||
; CHECK: risbg [[ROT]], %r3, 32, 39, 0
|
||||
; CHECK: [[KEEP]]:
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: sll %r3, 24
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: clr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw umax i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful signed minimum value. We need to load 0x81000000
|
||||
; into the source register.
|
||||
define i8 @f5(i8 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: llilh [[SRC2:%r[0-9]+]], 33024
|
||||
; CHECK: cr [[ROT:%r[0-9]+]], [[SRC2]]
|
||||
; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw min i8 *%src, i8 -127 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the highest useful signed maximum value. We need to load 0x7e000000
|
||||
; into the source register.
|
||||
define i8 @f6(i8 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: llilh [[SRC2:%r[0-9]+]], 32256
|
||||
; CHECK: cr [[ROT:%r[0-9]+]], [[SRC2]]
|
||||
; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw max i8 *%src, i8 126 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful unsigned minimum value. We need to load 0x01000000
|
||||
; into the source register.
|
||||
define i8 @f7(i8 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: llilh [[SRC2:%r[0-9]+]], 256
|
||||
; CHECK: clr [[ROT:%r[0-9]+]], [[SRC2]]
|
||||
; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f7:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f7:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw umin i8 *%src, i8 1 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the highest useful unsigned maximum value. We need to load 0xfe000000
|
||||
; into the source register.
|
||||
define i8 @f8(i8 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: llilh [[SRC2:%r[0-9]+]], 65024
|
||||
; CHECK: clr [[ROT:%r[0-9]+]], [[SRC2]]
|
||||
; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f8:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f8:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw umax i8 *%src, i8 254 seq_cst
|
||||
ret i8 %res
|
||||
}
|
228
test/CodeGen/SystemZ/atomicrmw-minmax-02.ll
Normal file
228
test/CodeGen/SystemZ/atomicrmw-minmax-02.ll
Normal file
@ -0,0 +1,228 @@
|
||||
; Test 8-bit atomic min/max operations.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check signed minimum.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used, and that the low bits are set to 1. This sequence is
|
||||
; independent of the other loop prologue instructions.
|
||||
define i16 @f1(i16 *%src, i16 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: cr [[ROT]], %r3
|
||||
; CHECK: j{{g?}}le [[KEEP:\..*]]
|
||||
; CHECK: risbg [[ROT]], %r3, 32, 47, 0
|
||||
; CHECK: [[KEEP]]:
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 16
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: cr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw min i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check signed maximum.
|
||||
define i16 @f2(i16 *%src, i16 %b) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: cr [[ROT]], %r3
|
||||
; CHECK: j{{g?}}he [[KEEP:\..*]]
|
||||
; CHECK: risbg [[ROT]], %r3, 32, 47, 0
|
||||
; CHECK: [[KEEP]]:
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: sll %r3, 16
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: cr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw max i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check unsigned minimum.
|
||||
define i16 @f3(i16 *%src, i16 %b) {
|
||||
; CHECK: f3:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: clr [[ROT]], %r3
|
||||
; CHECK: j{{g?}}le [[KEEP:\..*]]
|
||||
; CHECK: risbg [[ROT]], %r3, 32, 47, 0
|
||||
; CHECK: [[KEEP]]:
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: sll %r3, 16
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: clr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw umin i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check unsigned maximum.
|
||||
define i16 @f4(i16 *%src, i16 %b) {
|
||||
; CHECK: f4:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: clr [[ROT]], %r3
|
||||
; CHECK: j{{g?}}he [[KEEP:\..*]]
|
||||
; CHECK: risbg [[ROT]], %r3, 32, 47, 0
|
||||
; CHECK: [[KEEP]]:
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: sll %r3, 16
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: clr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw umax i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful signed minimum value. We need to load 0x80010000
|
||||
; into the source register.
|
||||
define i16 @f5(i16 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: llilh [[SRC2:%r[0-9]+]], 32769
|
||||
; CHECK: cr [[ROT:%r[0-9]+]], [[SRC2]]
|
||||
; CHECK: risbg [[ROT]], [[SRC2]], 32, 47, 0
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw min i16 *%src, i16 -32767 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the highest useful signed maximum value. We need to load 0x7ffe0000
|
||||
; into the source register.
|
||||
define i16 @f6(i16 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: llilh [[SRC2:%r[0-9]+]], 32766
|
||||
; CHECK: cr [[ROT:%r[0-9]+]], [[SRC2]]
|
||||
; CHECK: risbg [[ROT]], [[SRC2]], 32, 47, 0
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw max i16 *%src, i16 32766 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful unsigned maximum value. We need to load 0x00010000
|
||||
; into the source register.
|
||||
define i16 @f7(i16 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: llilh [[SRC2:%r[0-9]+]], 1
|
||||
; CHECK: clr [[ROT:%r[0-9]+]], [[SRC2]]
|
||||
; CHECK: risbg [[ROT]], [[SRC2]], 32, 47, 0
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f7:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f7:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw umin i16 *%src, i16 1 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the highest useful unsigned maximum value. We need to load 0xfffe0000
|
||||
; into the source register.
|
||||
define i16 @f8(i16 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: llilh [[SRC2:%r[0-9]+]], 65534
|
||||
; CHECK: clr [[ROT:%r[0-9]+]], [[SRC2]]
|
||||
; CHECK: risbg [[ROT]], [[SRC2]], 32, 47, 0
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f8:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f8:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw umax i16 *%src, i16 65534 seq_cst
|
||||
ret i16 %res
|
||||
}
|
176
test/CodeGen/SystemZ/atomicrmw-minmax-03.ll
Normal file
176
test/CodeGen/SystemZ/atomicrmw-minmax-03.ll
Normal file
@ -0,0 +1,176 @@
|
||||
; Test 32-bit atomic minimum and maximum.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check signed minium.
|
||||
define i32 @f1(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: cr %r2, %r4
|
||||
; CHECK: lr [[NEW:%r[0-9]+]], %r2
|
||||
; CHECK: j{{g?}}le [[KEEP:\..*]]
|
||||
; CHECK: lr [[NEW]], %r4
|
||||
; CHECK: cs %r2, [[NEW]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw min i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check signed maximum.
|
||||
define i32 @f2(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f2:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: cr %r2, %r4
|
||||
; CHECK: lr [[NEW:%r[0-9]+]], %r2
|
||||
; CHECK: j{{g?}}he [[KEEP:\..*]]
|
||||
; CHECK: lr [[NEW]], %r4
|
||||
; CHECK: cs %r2, [[NEW]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw max i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check unsigned minimum.
|
||||
define i32 @f3(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f3:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: clr %r2, %r4
|
||||
; CHECK: lr [[NEW:%r[0-9]+]], %r2
|
||||
; CHECK: j{{g?}}le [[KEEP:\..*]]
|
||||
; CHECK: lr [[NEW]], %r4
|
||||
; CHECK: cs %r2, [[NEW]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw umin i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check unsigned maximum.
|
||||
define i32 @f4(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f4:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: clr %r2, %r4
|
||||
; CHECK: lr [[NEW:%r[0-9]+]], %r2
|
||||
; CHECK: j{{g?}}he [[KEEP:\..*]]
|
||||
; CHECK: lr [[NEW]], %r4
|
||||
; CHECK: cs %r2, [[NEW]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw umax i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CS range.
|
||||
define i32 @f5(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f5:
|
||||
; CHECK: l %r2, 4092(%r3)
|
||||
; CHECK: cs %r2, {{%r[0-9]+}}, 4092(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 1023
|
||||
%res = atomicrmw min i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next word up, which requires CSY.
|
||||
define i32 @f6(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f6:
|
||||
; CHECK: ly %r2, 4096(%r3)
|
||||
; CHECK: csy %r2, {{%r[0-9]+}}, 4096(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 1024
|
||||
%res = atomicrmw min i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CSY range.
|
||||
define i32 @f7(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f7:
|
||||
; CHECK: ly %r2, 524284(%r3)
|
||||
; CHECK: csy %r2, {{%r[0-9]+}}, 524284(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 131071
|
||||
%res = atomicrmw min i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next word up, which needs separate address logic.
|
||||
define i32 @f8(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f8:
|
||||
; CHECK: agfi %r3, 524288
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: cs %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 131072
|
||||
%res = atomicrmw min i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the negative aligned CSY range.
|
||||
define i32 @f9(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f9:
|
||||
; CHECK: ly %r2, -4(%r3)
|
||||
; CHECK: csy %r2, {{%r[0-9]+}}, -4(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -1
|
||||
%res = atomicrmw min i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the low end of the CSY range.
|
||||
define i32 @f10(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f10:
|
||||
; CHECK: ly %r2, -524288(%r3)
|
||||
; CHECK: csy %r2, {{%r[0-9]+}}, -524288(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -131072
|
||||
%res = atomicrmw min i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next word down, which needs separate address logic.
|
||||
define i32 @f11(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f11:
|
||||
; CHECK: agfi %r3, -524292
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: cs %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -131073
|
||||
%res = atomicrmw min i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check that indexed addresses are not allowed.
|
||||
define i32 @f12(i32 %dummy, i64 %base, i64 %index, i32 %b) {
|
||||
; CHECK: f12:
|
||||
; CHECK: agr %r3, %r4
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: cs %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, %index
|
||||
%ptr = inttoptr i64 %add to i32 *
|
||||
%res = atomicrmw min i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check that constants are forced into a register.
|
||||
define i32 @f13(i32 %dummy, i32 *%ptr) {
|
||||
; CHECK: f13:
|
||||
; CHECK: lhi [[LIMIT:%r[0-9]+]], 42
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: cr %r2, [[LIMIT]]
|
||||
; CHECK: lr [[NEW:%r[0-9]+]], %r2
|
||||
; CHECK: j{{g?}}le [[KEEP:\..*]]
|
||||
; CHECK: lr [[NEW]], [[LIMIT]]
|
||||
; CHECK: cs %r2, [[NEW]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw min i32 *%ptr, i32 42 seq_cst
|
||||
ret i32 %res
|
||||
}
|
143
test/CodeGen/SystemZ/atomicrmw-minmax-04.ll
Normal file
143
test/CodeGen/SystemZ/atomicrmw-minmax-04.ll
Normal file
@ -0,0 +1,143 @@
|
||||
; Test 64-bit atomic minimum and maximum.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check signed minium.
|
||||
define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: cgr %r2, %r4
|
||||
; CHECK: lgr [[NEW:%r[0-9]+]], %r2
|
||||
; CHECK: j{{g?}}le [[KEEP:\..*]]
|
||||
; CHECK: lgr [[NEW]], %r4
|
||||
; CHECK: csg %r2, [[NEW]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw min i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check signed maximum.
|
||||
define i64 @f2(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: cgr %r2, %r4
|
||||
; CHECK: lgr [[NEW:%r[0-9]+]], %r2
|
||||
; CHECK: j{{g?}}he [[KEEP:\..*]]
|
||||
; CHECK: lgr [[NEW]], %r4
|
||||
; CHECK: csg %r2, [[NEW]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw max i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check unsigned minimum.
|
||||
define i64 @f3(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: clgr %r2, %r4
|
||||
; CHECK: lgr [[NEW:%r[0-9]+]], %r2
|
||||
; CHECK: j{{g?}}le [[KEEP:\..*]]
|
||||
; CHECK: lgr [[NEW]], %r4
|
||||
; CHECK: csg %r2, [[NEW]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw umin i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check unsigned maximum.
|
||||
define i64 @f4(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f4:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: clgr %r2, %r4
|
||||
; CHECK: lgr [[NEW:%r[0-9]+]], %r2
|
||||
; CHECK: j{{g?}}he [[KEEP:\..*]]
|
||||
; CHECK: lgr [[NEW]], %r4
|
||||
; CHECK: csg %r2, [[NEW]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw umax i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CSG range.
|
||||
define i64 @f5(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f5:
|
||||
; CHECK: lg %r2, 524280(%r3)
|
||||
; CHECK: csg %r2, {{%r[0-9]+}}, 524280(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 65535
|
||||
%res = atomicrmw min i64 *%ptr, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next doubleword up, which requires separate address logic.
|
||||
define i64 @f6(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f6:
|
||||
; CHECK: agfi %r3, 524288
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: csg %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 65536
|
||||
%res = atomicrmw min i64 *%ptr, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the CSG range.
|
||||
define i64 @f7(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f7:
|
||||
; CHECK: lg %r2, -524288(%r3)
|
||||
; CHECK: csg %r2, {{%r[0-9]+}}, -524288(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -65536
|
||||
%res = atomicrmw min i64 *%ptr, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next doubleword down, which requires separate address logic.
|
||||
define i64 @f8(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f8:
|
||||
; CHECK: agfi %r3, -524296
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: csg %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -65537
|
||||
%res = atomicrmw min i64 *%ptr, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check that indexed addresses are not allowed.
|
||||
define i64 @f9(i64 %dummy, i64 %base, i64 %index, i64 %b) {
|
||||
; CHECK: f9:
|
||||
; CHECK: agr %r3, %r4
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: csg %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, %index
|
||||
%ptr = inttoptr i64 %add to i64 *
|
||||
%res = atomicrmw min i64 *%ptr, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check that constants are forced into a register.
|
||||
define i64 @f10(i64 %dummy, i64 *%ptr) {
|
||||
; CHECK: f10:
|
||||
; CHECK: lghi [[LIMIT:%r[0-9]+]], 42
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LOOP:\.[^:]*]]:
|
||||
; CHECK: cgr %r2, [[LIMIT]]
|
||||
; CHECK: lgr [[NEW:%r[0-9]+]], %r2
|
||||
; CHECK: j{{g?}}le [[KEEP:\..*]]
|
||||
; CHECK: lgr [[NEW]], [[LIMIT]]
|
||||
; CHECK: csg %r2, [[NEW]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LOOP]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw min i64 *%ptr, i64 42 seq_cst
|
||||
ret i64 %res
|
||||
}
|
139
test/CodeGen/SystemZ/atomicrmw-nand-01.ll
Normal file
139
test/CodeGen/SystemZ/atomicrmw-nand-01.ll
Normal file
@ -0,0 +1,139 @@
|
||||
; Test 8-bit atomic NANDs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check NAND of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used, and that the low bits are set to 1. This sequence is
|
||||
; independent of the other loop prologue instructions.
|
||||
define i8 @f1(i8 *%src, i8 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: nr [[ROT]], %r3
|
||||
; CHECK: xilf [[ROT]], 4278190080
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 24
|
||||
; CHECK-SHIFT2: oilf %r3, 16777215
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: nr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We AND the rotated word with 0x80ffffff.
|
||||
define i8 @f2(i8 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: nilh [[ROT]], 33023
|
||||
; CHECK: xilf [[ROT]], 4278190080
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i8 *%src, i8 -128 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check NANDs of -2 (-1 isn't useful). We AND the rotated word with 0xfeffffff.
|
||||
define i8 @f3(i8 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: nilh [[ROT]], 65279
|
||||
; CHECK: xilf [[ROT]], 4278190080
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i8 *%src, i8 -2 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check NANDs of 1. We AND the rotated word with 0x01ffffff.
|
||||
define i8 @f4(i8 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: nilh [[ROT]], 511
|
||||
; CHECK: xilf [[ROT]], 4278190080
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i8 *%src, i8 1 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We AND the rotated word with 0x7fffffff.
|
||||
define i8 @f5(i8 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: nilh [[ROT]], 32767
|
||||
; CHECK: xilf [[ROT]], 4278190080
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i8 *%src, i8 127 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check NANDs of a large unsigned value. We AND the rotated word with
|
||||
; 0xfdffffff.
|
||||
define i8 @f6(i8 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: nilh [[ROT]], 65023
|
||||
; CHECK: xilf [[ROT]], 4278190080
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i8 *%src, i8 253 seq_cst
|
||||
ret i8 %res
|
||||
}
|
139
test/CodeGen/SystemZ/atomicrmw-nand-02.ll
Normal file
139
test/CodeGen/SystemZ/atomicrmw-nand-02.ll
Normal file
@ -0,0 +1,139 @@
|
||||
; Test 16-bit atomic NANDs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check NAND of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used, and that the low bits are set to 1. This sequence is
|
||||
; independent of the other loop prologue instructions.
|
||||
define i16 @f1(i16 *%src, i16 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: nr [[ROT]], %r3
|
||||
; CHECK: xilf [[ROT]], 4294901760
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 16
|
||||
; CHECK-SHIFT2: oill %r3, 65535
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: nr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We AND the rotated word with 0x8000ffff.
|
||||
define i16 @f2(i16 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: nilh [[ROT]], 32768
|
||||
; CHECK: xilf [[ROT]], 4294901760
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i16 *%src, i16 -32768 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check NANDs of -2 (-1 isn't useful). We AND the rotated word with 0xfffeffff.
|
||||
define i16 @f3(i16 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: nilh [[ROT]], 65534
|
||||
; CHECK: xilf [[ROT]], 4294901760
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i16 *%src, i16 -2 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check ANDs of 1. We AND the rotated word with 0x0001ffff.
|
||||
define i16 @f4(i16 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: nilh [[ROT]], 1
|
||||
; CHECK: xilf [[ROT]], 4294901760
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i16 *%src, i16 1 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We AND the rotated word with 0x7fffffff.
|
||||
define i16 @f5(i16 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: nilh [[ROT]], 32767
|
||||
; CHECK: xilf [[ROT]], 4294901760
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i16 *%src, i16 32767 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check NANDs of a large unsigned value. We AND the rotated word with
|
||||
; 0xfffdffff.
|
||||
define i16 @f6(i16 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: nilh [[ROT]], 65533
|
||||
; CHECK: xilf [[ROT]], 4294901760
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw nand i16 *%src, i16 65533 seq_cst
|
||||
ret i16 %res
|
||||
}
|
93
test/CodeGen/SystemZ/atomicrmw-nand-03.ll
Normal file
93
test/CodeGen/SystemZ/atomicrmw-nand-03.ll
Normal file
@ -0,0 +1,93 @@
|
||||
; Test 32-bit atomic NANDs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check NANDs of a variable.
|
||||
define i32 @f1(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: nr %r0, %r4
|
||||
; CHECK: xilf %r0, 4294967295
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check NANDs of 1.
|
||||
define i32 @f2(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: nilf %r0, 1
|
||||
; CHECK: xilf %r0, 4294967295
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i32 *%src, i32 1 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check NANDs of the low end of the NILH range.
|
||||
define i32 @f3(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: nilh %r0, 0
|
||||
; CHECK: xilf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i32 *%src, i32 65535 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use NILF.
|
||||
define i32 @f4(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: nilf %r0, 65536
|
||||
; CHECK: xilf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i32 *%src, i32 65536 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the largest useful NILL value.
|
||||
define i32 @f5(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: nill %r0, 65534
|
||||
; CHECK: xilf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i32 *%src, i32 -2 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NILL range.
|
||||
define i32 @f6(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: nill %r0, 0
|
||||
; CHECK: xilf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i32 *%src, i32 -65536 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the largest useful NILH value, which is one less than the above.
|
||||
define i32 @f7(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: nilh %r0, 65534
|
||||
; CHECK: xilf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i32 *%src, i32 -65537 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NILF value, which is one less than the above.
|
||||
define i32 @f8(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: nilf %r0, 4294901758
|
||||
; CHECK: xilf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i32 *%src, i32 -65538 seq_cst
|
||||
ret i32 %res
|
||||
}
|
183
test/CodeGen/SystemZ/atomicrmw-nand-04.ll
Normal file
183
test/CodeGen/SystemZ/atomicrmw-nand-04.ll
Normal file
@ -0,0 +1,183 @@
|
||||
; Test 64-bit atomic NANDs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check NANDs of a variable.
|
||||
define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: ngr %r0, %r4
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check NANDs of 1, which must be done using a register.
|
||||
define i64 @f2(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: ngr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 1 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NIHF range.
|
||||
define i64 @f3(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: nihf %r0, 0
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 4294967295 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use a register.
|
||||
define i64 @f4(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: ngr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 4294967296 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NIHH range.
|
||||
define i64 @f5(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: nihh %r0, 0
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 281474976710655 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use a register.
|
||||
define i64 @f6(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: ngr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 281474976710656 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NILL value.
|
||||
define i64 @f7(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: nill %r0, 65534
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 -2 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NILL range.
|
||||
define i64 @f8(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: nill %r0, 0
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 -65536 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NILH value, which is one less than the above.
|
||||
define i64 @f9(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f9:
|
||||
; CHECK: nilh %r0, 65534
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 -65537 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NILF value, which is one less than the above.
|
||||
define i64 @f10(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f10:
|
||||
; CHECK: nilf %r0, 4294901758
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 -65538 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NILH range.
|
||||
define i64 @f11(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f11:
|
||||
; CHECK: nilh %r0, 0
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 -4294901761 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NILF range.
|
||||
define i64 @f12(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f12:
|
||||
; CHECK: nilf %r0, 0
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 -4294967296 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NIHL value, which is one less than the above.
|
||||
define i64 @f13(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f13:
|
||||
; CHECK: nihl %r0, 65534
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 -4294967297 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the NIHL range.
|
||||
define i64 @f14(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f14:
|
||||
; CHECK: nihl %r0, 0
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 -281470681743361 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NIHH value, which is 1<<32 less than the above.
|
||||
define i64 @f15(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f15:
|
||||
; CHECK: nihh %r0, 65534
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 -281474976710657 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the highest useful NIHF value, which is 1<<32 less than the above.
|
||||
define i64 @f16(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f16:
|
||||
; CHECK: nihf %r0, 4294901758
|
||||
; CHECK: lcgr %r0, %r0
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw nand i64 *%src, i64 -281479271677953 seq_cst
|
||||
ret i64 %res
|
||||
}
|
132
test/CodeGen/SystemZ/atomicrmw-or-01.ll
Normal file
132
test/CodeGen/SystemZ/atomicrmw-or-01.ll
Normal file
@ -0,0 +1,132 @@
|
||||
; Test 8-bit atomic ORs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check OR of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used. This shift is independent of the other loop prologue
|
||||
; instructions.
|
||||
define i8 @f1(i8 *%src, i8 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: or [[ROT]], %r3
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 24
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: or {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We OR the rotated word with 0x80000000.
|
||||
define i8 @f2(i8 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: oilh [[ROT]], 32768
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i8 *%src, i8 -128 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check ORs of -2 (-1 isn't useful). We OR the rotated word with 0xfe000000.
|
||||
define i8 @f3(i8 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: oilh [[ROT]], 65024
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i8 *%src, i8 -2 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check ORs of 1. We OR the rotated word with 0x01000000.
|
||||
define i8 @f4(i8 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: oilh [[ROT]], 256
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i8 *%src, i8 1 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We OR the rotated word with 0x7f000000.
|
||||
define i8 @f5(i8 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: oilh [[ROT]], 32512
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i8 *%src, i8 127 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check ORs of a large unsigned value. We OR the rotated word with
|
||||
; 0xfd000000.
|
||||
define i8 @f6(i8 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: oilh [[ROT]], 64768
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i8 *%src, i8 253 seq_cst
|
||||
ret i8 %res
|
||||
}
|
132
test/CodeGen/SystemZ/atomicrmw-or-02.ll
Normal file
132
test/CodeGen/SystemZ/atomicrmw-or-02.ll
Normal file
@ -0,0 +1,132 @@
|
||||
; Test 16-bit atomic ORs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check OR of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used. This shift is independent of the other loop prologue
|
||||
; instructions.
|
||||
define i16 @f1(i16 *%src, i16 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: or [[ROT]], %r3
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 16
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: or {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We OR the rotated word with 0x80000000.
|
||||
define i16 @f2(i16 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: oilh [[ROT]], 32768
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i16 *%src, i16 -32768 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check ORs of -2 (-1 isn't useful). We OR the rotated word with 0xfffe0000.
|
||||
define i16 @f3(i16 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: oilh [[ROT]], 65534
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i16 *%src, i16 -2 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check ORs of 1. We OR the rotated word with 0x00010000.
|
||||
define i16 @f4(i16 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: oilh [[ROT]], 1
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i16 *%src, i16 1 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We OR the rotated word with 0x7fff0000.
|
||||
define i16 @f5(i16 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: oilh [[ROT]], 32767
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i16 *%src, i16 32767 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check ORs of a large unsigned value. We OR the rotated word with
|
||||
; 0xfffd0000.
|
||||
define i16 @f6(i16 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: oilh [[ROT]], 65533
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw or i16 *%src, i16 65533 seq_cst
|
||||
ret i16 %res
|
||||
}
|
85
test/CodeGen/SystemZ/atomicrmw-or-03.ll
Normal file
85
test/CodeGen/SystemZ/atomicrmw-or-03.ll
Normal file
@ -0,0 +1,85 @@
|
||||
; Test 32-bit atomic ORs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check ORs of a variable.
|
||||
define i32 @f1(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: or %r0, %r4
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful OILL value.
|
||||
define i32 @f2(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: oill %r0, 1
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i32 *%src, i32 1 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the OILL range.
|
||||
define i32 @f3(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: oill %r0, 65535
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i32 *%src, i32 65535 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful OILH value, which is the next value up.
|
||||
define i32 @f4(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: oilh %r0, 1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i32 *%src, i32 65536 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful OILF value, which is the next value up.
|
||||
define i32 @f5(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: oilf %r0, 65537
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i32 *%src, i32 65537 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the OILH range.
|
||||
define i32 @f6(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: oilh %r0, 65535
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i32 *%src, i32 -65536 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use OILF.
|
||||
define i32 @f7(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: oilf %r0, 4294901761
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i32 *%src, i32 -65535 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the largest useful OILF value.
|
||||
define i32 @f8(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: oilf %r0, 4294967294
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i32 *%src, i32 -2 seq_cst
|
||||
ret i32 %res
|
||||
}
|
158
test/CodeGen/SystemZ/atomicrmw-or-04.ll
Normal file
158
test/CodeGen/SystemZ/atomicrmw-or-04.ll
Normal file
@ -0,0 +1,158 @@
|
||||
; Test 64-bit atomic ORs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check ORs of a variable.
|
||||
define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: ogr %r0, %r4
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful OILL value.
|
||||
define i64 @f2(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: oill %r0, 1
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 1 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the OILL range.
|
||||
define i64 @f3(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: oill %r0, 65535
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 65535 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful OILH value, which is the next value up.
|
||||
define i64 @f4(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: oilh %r0, 1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 65536 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful OILF value, which is the next value up again.
|
||||
define i64 @f5(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: oilf %r0, 65537
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 65537 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the OILH range.
|
||||
define i64 @f6(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: oilh %r0, 65535
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 4294901760 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use OILF.
|
||||
define i64 @f7(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: oilf %r0, 4294901761
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 4294901761 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the OILF range.
|
||||
define i64 @f8(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: oilf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 4294967295 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful OIHL value, which is one greater than above.
|
||||
define i64 @f9(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f9:
|
||||
; CHECK: oihl %r0, 1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 4294967296 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use a register. (We could use
|
||||
; combinations of OIH* and OIL* instead, but that isn't implemented.)
|
||||
define i64 @f10(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f10:
|
||||
; CHECK: ogr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 4294967297 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the OIHL range.
|
||||
define i64 @f11(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f11:
|
||||
; CHECK: oihl %r0, 65535
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 281470681743360 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful OIHH value, which is 1<<32 greater than above.
|
||||
define i64 @f12(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f12:
|
||||
; CHECK: oihh %r0, 1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 281474976710656 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful OIHF value, which is 1<<32 greater again.
|
||||
define i64 @f13(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f13:
|
||||
; CHECK: oihf %r0, 65537
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 281479271677952 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the OIHH range.
|
||||
define i64 @f14(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f14:
|
||||
; CHECK: oihh %r0, 65535
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 18446462598732840960 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use a register.
|
||||
define i64 @f15(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f15:
|
||||
; CHECK: ogr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 18446462598732840961 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the OIHF range.
|
||||
define i64 @f16(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f16:
|
||||
; CHECK: oihf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw or i64 *%src, i64 -4294967296 seq_cst
|
||||
ret i64 %res
|
||||
}
|
132
test/CodeGen/SystemZ/atomicrmw-sub-01.ll
Normal file
132
test/CodeGen/SystemZ/atomicrmw-sub-01.ll
Normal file
@ -0,0 +1,132 @@
|
||||
; Test 8-bit atomic subtractions.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check subtraction of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used. This shift is independent of the other loop prologue
|
||||
; instructions.
|
||||
define i8 @f1(i8 *%src, i8 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: sr [[ROT]], %r3
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 24
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: sr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We add 0x80000000 to the rotated word.
|
||||
define i8 @f2(i8 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: afi [[ROT]], -2147483648
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i8 *%src, i8 -128 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check subtraction of -1. We add 0x01000000 to the rotated word.
|
||||
define i8 @f3(i8 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: afi [[ROT]], 16777216
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i8 *%src, i8 -1 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check subtraction of -1. We add 0xff000000 to the rotated word.
|
||||
define i8 @f4(i8 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: afi [[ROT]], -16777216
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i8 *%src, i8 1 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We add 0x81000000 to the rotated word.
|
||||
define i8 @f5(i8 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: afi [[ROT]], -2130706432
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i8 *%src, i8 127 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check subtraction of a large unsigned value. We add 0x02000000 to the
|
||||
; rotated word.
|
||||
define i8 @f6(i8 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: afi [[ROT]], 33554432
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i8 *%src, i8 254 seq_cst
|
||||
ret i8 %res
|
||||
}
|
132
test/CodeGen/SystemZ/atomicrmw-sub-02.ll
Normal file
132
test/CodeGen/SystemZ/atomicrmw-sub-02.ll
Normal file
@ -0,0 +1,132 @@
|
||||
; Test 16-bit atomic subtractions.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check subtraction of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used. This shift is independent of the other loop prologue
|
||||
; instructions.
|
||||
define i16 @f1(i16 *%src, i16 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: sr [[ROT]], %r3
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 16
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: sr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We add 0x80000000 to the rotated word.
|
||||
define i16 @f2(i16 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: afi [[ROT]], -2147483648
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i16 *%src, i16 -32768 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check subtraction of -1. We add 0x00010000 to the rotated word.
|
||||
define i16 @f3(i16 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: afi [[ROT]], 65536
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i16 *%src, i16 -1 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check subtraction of 1. We add 0xffff0000 to the rotated word.
|
||||
define i16 @f4(i16 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: afi [[ROT]], -65536
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i16 *%src, i16 1 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We add 0x80010000 to the rotated word.
|
||||
define i16 @f5(i16 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: afi [[ROT]], -2147418112
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i16 *%src, i16 32767 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check subtraction of a large unsigned value. We add 0x00020000 to the
|
||||
; rotated word.
|
||||
define i16 @f6(i16 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: afi [[ROT]], 131072
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw sub i16 *%src, i16 65534 seq_cst
|
||||
ret i16 %res
|
||||
}
|
94
test/CodeGen/SystemZ/atomicrmw-sub-03.ll
Normal file
94
test/CodeGen/SystemZ/atomicrmw-sub-03.ll
Normal file
@ -0,0 +1,94 @@
|
||||
; Test 32-bit atomic subtractions.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check subtraction of a variable.
|
||||
define i32 @f1(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: sr %r0, %r4
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check subtraction of 1, which can use AHI.
|
||||
define i32 @f2(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: ahi %r0, -1
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i32 *%src, i32 1 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the low end of the AHI range.
|
||||
define i32 @f3(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: ahi %r0, -32768
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i32 *%src, i32 32768 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next value down, which must use AFI.
|
||||
define i32 @f4(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: afi %r0, -32769
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i32 *%src, i32 32769 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the low end of the AFI range.
|
||||
define i32 @f5(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: afi %r0, -2147483648
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i32 *%src, i32 2147483648 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which gets treated as a positive operand.
|
||||
define i32 @f6(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: afi %r0, 2147483647
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i32 *%src, i32 2147483649 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check subtraction of -1, which can use AHI.
|
||||
define i32 @f7(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: ahi %r0, 1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i32 *%src, i32 -1 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the AHI range.
|
||||
define i32 @f8(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: ahi %r0, 32767
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i32 *%src, i32 -32767 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next value down, which must use AFI instead.
|
||||
define i32 @f9(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f9:
|
||||
; CHECK: afi %r0, 32768
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i32 *%src, i32 -32768 seq_cst
|
||||
ret i32 %res
|
||||
}
|
112
test/CodeGen/SystemZ/atomicrmw-sub-04.ll
Normal file
112
test/CodeGen/SystemZ/atomicrmw-sub-04.ll
Normal file
@ -0,0 +1,112 @@
|
||||
; Test 64-bit atomic subtractions.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check subtraction of a variable.
|
||||
define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: sgr %r0, %r4
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check subtraction of 1, which can use AGHI.
|
||||
define i64 @f2(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: aghi %r0, -1
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 1 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the AGHI range.
|
||||
define i64 @f3(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: aghi %r0, -32768
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 32768 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use AGFI.
|
||||
define i64 @f4(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: agfi %r0, -32769
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 32769 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the AGFI range.
|
||||
define i64 @f5(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: agfi %r0, -2147483648
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 2147483648 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use a register operation.
|
||||
define i64 @f6(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: sgr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 2147483649 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check subtraction of -1, which can use AGHI.
|
||||
define i64 @f7(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: aghi %r0, 1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 -1 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the AGHI range.
|
||||
define i64 @f8(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: aghi %r0, 32767
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 -32767 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value down, which must use AGFI instead.
|
||||
define i64 @f9(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f9:
|
||||
; CHECK: agfi %r0, 32768
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 -32768 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the AGFI range.
|
||||
define i64 @f10(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f10:
|
||||
; CHECK: agfi %r0, 2147483647
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 -2147483647 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value down, which must use a register operation.
|
||||
define i64 @f11(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f11:
|
||||
; CHECK: sgr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw sub i64 *%src, i64 -2147483648 seq_cst
|
||||
ret i64 %res
|
||||
}
|
55
test/CodeGen/SystemZ/atomicrmw-xchg-01.ll
Normal file
55
test/CodeGen/SystemZ/atomicrmw-xchg-01.ll
Normal file
@ -0,0 +1,55 @@
|
||||
; Test 8-bit atomic exchange.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT
|
||||
|
||||
; Check exchange with a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK. CHECK-SHIFT also checks that %r3 is not modified before
|
||||
; being used in the RISBG (in contrast to things like atomic addition,
|
||||
; which shift %r3 left so that %b is at the high end of the word).
|
||||
define i8 @f1(i8 *%src, i8 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: risbg [[ROT]], %r3, 32, 39, 24
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT: f1:
|
||||
; CHECK-SHIFT-NOT: %r3
|
||||
; CHECK-SHIFT: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT-NOT: %r3
|
||||
; CHECK-SHIFT: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT-NOT: %r3
|
||||
; CHECK-SHIFT: rll
|
||||
; CHECK-SHIFT-NOT: %r3
|
||||
; CHECK-SHIFT: risbg {{%r[0-9]+}}, %r3, 32, 39, 24
|
||||
; CHECK-SHIFT: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT: rll
|
||||
; CHECK-SHIFT: br %r14
|
||||
%res = atomicrmw xchg i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check exchange with a constant. We should force the constant into
|
||||
; a register and use the sequence above.
|
||||
define i8 @f2(i8 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lhi [[VALUE:%r[0-9]+]], 88
|
||||
; CHECK: risbg {{%r[0-9]+}}, [[VALUE]], 32, 39, 24
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT: f2:
|
||||
; CHECK-SHIFT: br %r14
|
||||
%res = atomicrmw xchg i8 *%src, i8 88 seq_cst
|
||||
ret i8 %res
|
||||
}
|
55
test/CodeGen/SystemZ/atomicrmw-xchg-02.ll
Normal file
55
test/CodeGen/SystemZ/atomicrmw-xchg-02.ll
Normal file
@ -0,0 +1,55 @@
|
||||
; Test 16-bit atomic exchange.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT
|
||||
|
||||
; Check exchange with a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK. CHECK-SHIFT also checks that %r3 is not modified before
|
||||
; being used in the RISBG (in contrast to things like atomic addition,
|
||||
; which shift %r3 left so that %b is at the high end of the word).
|
||||
define i16 @f1(i16 *%src, i16 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: risbg [[ROT]], %r3, 32, 47, 16
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT: f1:
|
||||
; CHECK-SHIFT-NOT: %r3
|
||||
; CHECK-SHIFT: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT-NOT: %r3
|
||||
; CHECK-SHIFT: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT-NOT: %r3
|
||||
; CHECK-SHIFT: rll
|
||||
; CHECK-SHIFT-NOT: %r3
|
||||
; CHECK-SHIFT: risbg {{%r[0-9]+}}, %r3, 32, 47, 16
|
||||
; CHECK-SHIFT: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT: rll
|
||||
; CHECK-SHIFT: br %r14
|
||||
%res = atomicrmw xchg i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check exchange with a constant. We should force the constant into
|
||||
; a register and use the sequence above.
|
||||
define i16 @f2(i16 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lhi [[VALUE:%r[0-9]+]], -25536
|
||||
; CHECK: risbg {{%r[0-9]+}}, [[VALUE]], 32, 47, 16
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT: f2:
|
||||
; CHECK-SHIFT: br %r14
|
||||
%res = atomicrmw xchg i16 *%src, i16 40000 seq_cst
|
||||
ret i16 %res
|
||||
}
|
122
test/CodeGen/SystemZ/atomicrmw-xchg-03.ll
Normal file
122
test/CodeGen/SystemZ/atomicrmw-xchg-03.ll
Normal file
@ -0,0 +1,122 @@
|
||||
; Test 32-bit atomic exchange.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check register exchange.
|
||||
define i32 @f1(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: cs %r2, %r4, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xchg i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CS range.
|
||||
define i32 @f2(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f2:
|
||||
; CHECK: l %r2, 4092(%r3)
|
||||
; CHECK: cs %r2, {{%r[0-9]+}}, 4092(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 1023
|
||||
%res = atomicrmw xchg i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next word up, which requires CSY.
|
||||
define i32 @f3(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f3:
|
||||
; CHECK: ly %r2, 4096(%r3)
|
||||
; CHECK: csy %r2, {{%r[0-9]+}}, 4096(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 1024
|
||||
%res = atomicrmw xchg i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CSY range.
|
||||
define i32 @f4(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f4:
|
||||
; CHECK: ly %r2, 524284(%r3)
|
||||
; CHECK: csy %r2, {{%r[0-9]+}}, 524284(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 131071
|
||||
%res = atomicrmw xchg i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next word up, which needs separate address logic.
|
||||
define i32 @f5(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f5:
|
||||
; CHECK: agfi %r3, 524288
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: cs %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 131072
|
||||
%res = atomicrmw xchg i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the high end of the negative aligned CSY range.
|
||||
define i32 @f6(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f6:
|
||||
; CHECK: ly %r2, -4(%r3)
|
||||
; CHECK: csy %r2, {{%r[0-9]+}}, -4(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -1
|
||||
%res = atomicrmw xchg i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the low end of the CSY range.
|
||||
define i32 @f7(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f7:
|
||||
; CHECK: ly %r2, -524288(%r3)
|
||||
; CHECK: csy %r2, {{%r[0-9]+}}, -524288(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -131072
|
||||
%res = atomicrmw xchg i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the next word down, which needs separate address logic.
|
||||
define i32 @f8(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f8:
|
||||
; CHECK: agfi %r3, -524292
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: cs %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -131073
|
||||
%res = atomicrmw xchg i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check that indexed addresses are not allowed.
|
||||
define i32 @f9(i32 %dummy, i64 %base, i64 %index, i32 %b) {
|
||||
; CHECK: f9:
|
||||
; CHECK: agr %r3, %r4
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: cs %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, %index
|
||||
%ptr = inttoptr i64 %add to i32 *
|
||||
%res = atomicrmw xchg i32 *%ptr, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check exchange of a constant. We should force it into a register and
|
||||
; use the sequence above.
|
||||
define i32 @f10(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f10:
|
||||
; CHECK: llill [[VALUE:%r[0-9+]]], 40000
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: cs %r2, [[VALUE]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xchg i32 *%src, i32 40000 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
88
test/CodeGen/SystemZ/atomicrmw-xchg-04.ll
Normal file
88
test/CodeGen/SystemZ/atomicrmw-xchg-04.ll
Normal file
@ -0,0 +1,88 @@
|
||||
; Test 64-bit atomic exchange.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check register exchange.
|
||||
define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: csg %r2, %r4, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xchg i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CSG range.
|
||||
define i64 @f2(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lg %r2, 524280(%r3)
|
||||
; CHECK: csg %r2, {{%r[0-9]+}}, 524280(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 65535
|
||||
%res = atomicrmw xchg i64 *%ptr, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next doubleword up, which requires separate address logic.
|
||||
define i64 @f3(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f3:
|
||||
; CHECK: agfi %r3, 524288
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: csg %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 65536
|
||||
%res = atomicrmw xchg i64 *%ptr, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the CSG range.
|
||||
define i64 @f4(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f4:
|
||||
; CHECK: lg %r2, -524288(%r3)
|
||||
; CHECK: csg %r2, {{%r[0-9]+}}, -524288(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -65536
|
||||
%res = atomicrmw xchg i64 *%ptr, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next doubleword down, which requires separate address logic.
|
||||
define i64 @f5(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f5:
|
||||
; CHECK: agfi %r3, -524296
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: csg %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -65537
|
||||
%res = atomicrmw xchg i64 *%ptr, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check that indexed addresses are not allowed.
|
||||
define i64 @f6(i64 %dummy, i64 %base, i64 %index, i64 %b) {
|
||||
; CHECK: f6:
|
||||
; CHECK: agr %r3, %r4
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: csg %r2, {{%r[0-9]+}}, 0(%r3)
|
||||
; CHECK: br %r14
|
||||
%add = add i64 %base, %index
|
||||
%ptr = inttoptr i64 %add to i64 *
|
||||
%res = atomicrmw xchg i64 *%ptr, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check exchange of a constant. We should force it into a register and
|
||||
; use the sequence above.
|
||||
define i64 @f7(i64 %dummy, i64 *%ptr) {
|
||||
; CHECK: f7:
|
||||
; CHECK: llilf [[VALUE:%r[0-9+]]], 3000000000
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: csg %r2, [[VALUE]], 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xchg i64 *%ptr, i64 3000000000 seq_cst
|
||||
ret i64 %res
|
||||
}
|
132
test/CodeGen/SystemZ/atomicrmw-xor-01.ll
Normal file
132
test/CodeGen/SystemZ/atomicrmw-xor-01.ll
Normal file
@ -0,0 +1,132 @@
|
||||
; Test 8-bit atomic XORs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check XOR of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used. This shift is independent of the other loop prologue
|
||||
; instructions.
|
||||
define i8 @f1(i8 *%src, i8 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: xr [[ROT]], %r3
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 24
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: xr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i8 *%src, i8 %b seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We XOR the rotated word with 0x80000000.
|
||||
define i8 @f2(i8 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: xilf [[ROT]], 2147483648
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i8 *%src, i8 -128 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check XORs of -1. We XOR the rotated word with 0xff000000.
|
||||
define i8 @f3(i8 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: xilf [[ROT]], 4278190080
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i8 *%src, i8 -1 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check XORs of 1. We XOR the rotated word with 0x01000000.
|
||||
define i8 @f4(i8 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: xilf [[ROT]], 16777216
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i8 *%src, i8 1 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We XOR the rotated word with 0x7f000000.
|
||||
define i8 @f5(i8 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: xilf [[ROT]], 2130706432
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i8 *%src, i8 127 seq_cst
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check XORs of a large unsigned value. We XOR the rotated word with
|
||||
; 0xfd000000.
|
||||
define i8 @f6(i8 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: xilf [[ROT]], 4244635648
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i8 *%src, i8 253 seq_cst
|
||||
ret i8 %res
|
||||
}
|
132
test/CodeGen/SystemZ/atomicrmw-xor-02.ll
Normal file
132
test/CodeGen/SystemZ/atomicrmw-xor-02.ll
Normal file
@ -0,0 +1,132 @@
|
||||
; Test 16-bit atomic XORs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
|
||||
|
||||
; Check XOR of a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK.
|
||||
; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
|
||||
; before being used. This shift is independent of the other loop prologue
|
||||
; instructions.
|
||||
define i16 @f1(i16 *%src, i16 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: xr [[ROT]], %r3
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f1:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f1:
|
||||
; CHECK-SHIFT2: sll %r3, 16
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: xr {{%r[0-9]+}}, %r3
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: rll
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i16 *%src, i16 %b seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the minimum signed value. We XOR the rotated word with 0x80000000.
|
||||
define i16 @f2(i16 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK: nill %r2, 65532
|
||||
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
|
||||
; CHECK: [[LABEL:\.[^:]*]]:
|
||||
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
|
||||
; CHECK: xilf [[ROT]], 2147483648
|
||||
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
|
||||
; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f2:
|
||||
; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
|
||||
; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
|
||||
; CHECK-SHIFT1: rll
|
||||
; CHECK-SHIFT1: br %r14
|
||||
;
|
||||
; CHECK-SHIFT2: f2:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i16 *%src, i16 -32768 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check XORs of -1. We XOR the rotated word with 0xffff0000.
|
||||
define i16 @f3(i16 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: xilf [[ROT]], 4294901760
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f3:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f3:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i16 *%src, i16 -1 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check XORs of 1. We XOR the rotated word with 0x00010000.
|
||||
define i16 @f4(i16 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: xilf [[ROT]], 65536
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f4:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f4:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i16 *%src, i16 1 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check the maximum signed value. We XOR the rotated word with 0x7fff0000.
|
||||
define i16 @f5(i16 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: xilf [[ROT]], 2147418112
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f5:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f5:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i16 *%src, i16 32767 seq_cst
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check XORs of a large unsigned value. We XOR the rotated word with
|
||||
; 0xfffd0000.
|
||||
define i16 @f6(i16 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: xilf [[ROT]], 4294770688
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT1: f6:
|
||||
; CHECK-SHIFT1: br %r14
|
||||
; CHECK-SHIFT2: f6:
|
||||
; CHECK-SHIFT2: br %r14
|
||||
%res = atomicrmw xor i16 *%src, i16 65533 seq_cst
|
||||
ret i16 %res
|
||||
}
|
49
test/CodeGen/SystemZ/atomicrmw-xor-03.ll
Normal file
49
test/CodeGen/SystemZ/atomicrmw-xor-03.ll
Normal file
@ -0,0 +1,49 @@
|
||||
; Test 32-bit atomic XORs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check XORs of a variable.
|
||||
define i32 @f1(i32 %dummy, i32 *%src, i32 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: xr %r0, %r4
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i32 *%src, i32 %b seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful constant.
|
||||
define i32 @f2(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: l %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lr %r0, %r2
|
||||
; CHECK: xilf %r0, 1
|
||||
; CHECK: cs %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i32 *%src, i32 1 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check an arbitrary constant.
|
||||
define i32 @f3(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: xilf %r0, 3000000000
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i32 *%src, i32 3000000000 seq_cst
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; Check bitwise negation.
|
||||
define i32 @f4(i32 %dummy, i32 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: xilf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i32 *%src, i32 -1 seq_cst
|
||||
ret i32 %res
|
||||
}
|
77
test/CodeGen/SystemZ/atomicrmw-xor-04.ll
Normal file
77
test/CodeGen/SystemZ/atomicrmw-xor-04.ll
Normal file
@ -0,0 +1,77 @@
|
||||
; Test 64-bit atomic XORs.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check XORs of a variable.
|
||||
define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: xgr %r0, %r4
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i64 *%src, i64 %b seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful XILF value.
|
||||
define i64 @f2(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lg %r2, 0(%r3)
|
||||
; CHECK: [[LABEL:\.[^ ]*]]:
|
||||
; CHECK: lgr %r0, %r2
|
||||
; CHECK: xilf %r0, 1
|
||||
; CHECK: csg %r2, %r0, 0(%r3)
|
||||
; CHECK: j{{g?}}lh [[LABEL]]
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i64 *%src, i64 1 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the XILF range.
|
||||
define i64 @f3(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: xilf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i64 *%src, i64 4294967295 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the lowest useful XIHF value, which is one greater than above.
|
||||
define i64 @f4(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: xihf %r0, 1
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i64 *%src, i64 4294967296 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use a register. (We could use
|
||||
; combinations of XIH* and XIL* instead, but that isn't implemented.)
|
||||
define i64 @f5(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: xgr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i64 *%src, i64 4294967297 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the XIHF range.
|
||||
define i64 @f6(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: xihf %r0, 4294967295
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i64 *%src, i64 -4294967296 seq_cst
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next value up, which must use a register.
|
||||
define i64 @f7(i64 %dummy, i64 *%src) {
|
||||
; CHECK: f7:
|
||||
; CHECK: xgr
|
||||
; CHECK: br %r14
|
||||
%res = atomicrmw xor i64 *%src, i64 -4294967295 seq_cst
|
||||
ret i64 %res
|
||||
}
|
14
test/CodeGen/SystemZ/branch-01.ll
Normal file
14
test/CodeGen/SystemZ/branch-01.ll
Normal file
@ -0,0 +1,14 @@
|
||||
; Test a simple unconditional jump.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define void @f1(i8 *%dest) {
|
||||
; CHECK: f1:
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: mvi 0(%r2), 1
|
||||
; CHECK: j{{g?}} .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
store volatile i8 1, i8 *%dest
|
||||
br label %loop
|
||||
}
|
94
test/CodeGen/SystemZ/branch-02.ll
Normal file
94
test/CodeGen/SystemZ/branch-02.ll
Normal file
@ -0,0 +1,94 @@
|
||||
; Test all condition-code masks that are relevant for signed integer
|
||||
; comparisons.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define void @f1(i32 *%src, i32 %target) {
|
||||
; CHECK: f1:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: c %r3, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}e .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile i32 *%src
|
||||
%cond = icmp eq i32 %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f2(i32 *%src, i32 %target) {
|
||||
; CHECK: f2:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: c %r3, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}lh .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile i32 *%src
|
||||
%cond = icmp ne i32 %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f3(i32 *%src, i32 %target) {
|
||||
; CHECK: f3:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: c %r3, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}le .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile i32 *%src
|
||||
%cond = icmp sle i32 %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f4(i32 *%src, i32 %target) {
|
||||
; CHECK: f4:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: c %r3, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}l .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile i32 *%src
|
||||
%cond = icmp slt i32 %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f5(i32 *%src, i32 %target) {
|
||||
; CHECK: f5:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: c %r3, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}h .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile i32 *%src
|
||||
%cond = icmp sgt i32 %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f6(i32 *%src, i32 %target) {
|
||||
; CHECK: f6:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: c %r3, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}he .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile i32 *%src
|
||||
%cond = icmp sge i32 %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
63
test/CodeGen/SystemZ/branch-03.ll
Normal file
63
test/CodeGen/SystemZ/branch-03.ll
Normal file
@ -0,0 +1,63 @@
|
||||
; Test all condition-code masks that are relevant for unsigned integer
|
||||
; comparisons.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
define void @f1(i32 *%src, i32 %target) {
|
||||
; CHECK: f1:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: cl %r3, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}le .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile i32 *%src
|
||||
%cond = icmp ule i32 %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f2(i32 *%src, i32 %target) {
|
||||
; CHECK: f2:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: cl %r3, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}l .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile i32 *%src
|
||||
%cond = icmp ult i32 %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f3(i32 *%src, i32 %target) {
|
||||
; CHECK: f3:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: cl %r3, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}h .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile i32 *%src
|
||||
%cond = icmp ugt i32 %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f4(i32 *%src, i32 %target) {
|
||||
; CHECK: f4:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: cl %r3, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}he .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile i32 *%src
|
||||
%cond = icmp uge i32 %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
218
test/CodeGen/SystemZ/branch-04.ll
Normal file
218
test/CodeGen/SystemZ/branch-04.ll
Normal file
@ -0,0 +1,218 @@
|
||||
; Test all condition-code masks that are relevant for floating-point
|
||||
; comparisons.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define void @f1(float *%src, float %target) {
|
||||
; CHECK: f1:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}e .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp oeq float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f2(float *%src, float %target) {
|
||||
; CHECK: f2:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}lh .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp one float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f3(float *%src, float %target) {
|
||||
; CHECK: f3:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}le .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp ole float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f4(float *%src, float %target) {
|
||||
; CHECK: f4:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}l .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp olt float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f5(float *%src, float %target) {
|
||||
; CHECK: f5:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}h .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp ogt float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f6(float *%src, float %target) {
|
||||
; CHECK: f6:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}he .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp oge float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f7(float *%src, float %target) {
|
||||
; CHECK: f7:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}nlh .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp ueq float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f8(float *%src, float %target) {
|
||||
; CHECK: f8:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}ne .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp une float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f9(float *%src, float %target) {
|
||||
; CHECK: f9:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}nh .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp ule float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f10(float *%src, float %target) {
|
||||
; CHECK: f10:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}nhe .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp ult float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f11(float *%src, float %target) {
|
||||
; CHECK: f11:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}nle .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp ugt float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f12(float *%src, float %target) {
|
||||
; CHECK: f12:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}nl .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp uge float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
; "jno" == "jump if no overflow", which corresponds to "jump if ordered"
|
||||
; rather than "jump if not ordered" after a floating-point comparison.
|
||||
define void @f13(float *%src, float %target) {
|
||||
; CHECK: f13:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}no .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp ord float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
; "jo" == "jump if overflow", which corresponds to "jump if not ordered"
|
||||
; rather than "jump if ordered" after a floating-point comparison.
|
||||
define void @f14(float *%src, float %target) {
|
||||
; CHECK: f14:
|
||||
; CHECK: .cfi_startproc
|
||||
; CHECK: .L[[LABEL:.*]]:
|
||||
; CHECK: ceb %f0, 0(%r2)
|
||||
; CHECK-NEXT: j{{g?}}o .L[[LABEL]]
|
||||
br label %loop
|
||||
loop:
|
||||
%val = load volatile float *%src
|
||||
%cond = fcmp uno float %target, %val
|
||||
br i1 %cond, label %loop, label %exit
|
||||
exit:
|
||||
ret void
|
||||
}
|
58
test/CodeGen/SystemZ/branch-05.ll
Normal file
58
test/CodeGen/SystemZ/branch-05.ll
Normal file
@ -0,0 +1,58 @@
|
||||
; Test indirect jumps.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
define i32 @f1(i32 %x, i32 %y, i32 %op) {
|
||||
; CHECK: f1:
|
||||
; CHECK: ahi %r4, -1
|
||||
; CHECK: clfi %r4, 5
|
||||
; CHECK-NEXT: j{{g?}}g
|
||||
; CHECK: llgfr [[OP64:%r[0-5]]], %r4
|
||||
; CHECK: sllg [[INDEX:%r[1-5]]], [[OP64]], 3
|
||||
; CHECK: larl [[BASE:%r[1-5]]]
|
||||
; CHECK: lg [[TARGET:%r[1-5]]], 0([[BASE]],[[INDEX]])
|
||||
; CHECK: br [[TARGET]]
|
||||
entry:
|
||||
switch i32 %op, label %exit [
|
||||
i32 1, label %b.add
|
||||
i32 2, label %b.sub
|
||||
i32 3, label %b.and
|
||||
i32 4, label %b.or
|
||||
i32 5, label %b.xor
|
||||
i32 6, label %b.mul
|
||||
]
|
||||
|
||||
b.add:
|
||||
%add = add i32 %x, %y
|
||||
br label %exit
|
||||
|
||||
b.sub:
|
||||
%sub = sub i32 %x, %y
|
||||
br label %exit
|
||||
|
||||
b.and:
|
||||
%and = and i32 %x, %y
|
||||
br label %exit
|
||||
|
||||
b.or:
|
||||
%or = or i32 %x, %y
|
||||
br label %exit
|
||||
|
||||
b.xor:
|
||||
%xor = xor i32 %x, %y
|
||||
br label %exit
|
||||
|
||||
b.mul:
|
||||
%mul = mul i32 %x, %y
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
%res = phi i32 [ %x, %entry ],
|
||||
[ %add, %b.add ],
|
||||
[ %sub, %b.sub ],
|
||||
[ %and, %b.and ],
|
||||
[ %or, %b.or ],
|
||||
[ %xor, %b.xor ],
|
||||
[ %mul, %b.mul ]
|
||||
ret i32 %res
|
||||
}
|
24
test/CodeGen/SystemZ/bswap-01.ll
Normal file
24
test/CodeGen/SystemZ/bswap-01.ll
Normal file
@ -0,0 +1,24 @@
|
||||
; Test byteswaps between registers.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
declare i32 @llvm.bswap.i32(i32 %a)
|
||||
declare i64 @llvm.bswap.i64(i64 %a)
|
||||
|
||||
; Check 32-bit register-to-register byteswaps.
|
||||
define i32 @f1(i32 %a) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lrvr [[REGISTER:%r[0-5]]], %r2
|
||||
; CHECk: br %r14
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
ret i32 %swapped
|
||||
}
|
||||
|
||||
; Check 64-bit register-to-register byteswaps.
|
||||
define i64 @f2(i64 %a) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lrvgr %r2, %r2
|
||||
; CHECk: br %r14
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
ret i64 %swapped
|
||||
}
|
87
test/CodeGen/SystemZ/bswap-02.ll
Normal file
87
test/CodeGen/SystemZ/bswap-02.ll
Normal file
@ -0,0 +1,87 @@
|
||||
; Test 32-bit byteswaps from memory to registers.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
declare i32 @llvm.bswap.i32(i32 %a)
|
||||
|
||||
; Check LRV with no displacement.
|
||||
define i32 @f1(i32 *%src) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lrv %r2, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%a = load i32 *%src
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
ret i32 %swapped
|
||||
}
|
||||
|
||||
; Check the high end of the aligned LRV range.
|
||||
define i32 @f2(i32 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lrv %r2, 524284(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 131071
|
||||
%a = load i32 *%ptr
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
ret i32 %swapped
|
||||
}
|
||||
|
||||
; Check the next word up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i32 @f3(i32 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: agfi %r2, 524288
|
||||
; CHECK: lrv %r2, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 131072
|
||||
%a = load i32 *%ptr
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
ret i32 %swapped
|
||||
}
|
||||
|
||||
; Check the high end of the negative aligned LRV range.
|
||||
define i32 @f4(i32 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: lrv %r2, -4(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -1
|
||||
%a = load i32 *%ptr
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
ret i32 %swapped
|
||||
}
|
||||
|
||||
; Check the low end of the LRV range.
|
||||
define i32 @f5(i32 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: lrv %r2, -524288(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -131072
|
||||
%a = load i32 *%ptr
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
ret i32 %swapped
|
||||
}
|
||||
|
||||
; Check the next word down, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i32 @f6(i32 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: agfi %r2, -524292
|
||||
; CHECK: lrv %r2, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -131073
|
||||
%a = load i32 *%ptr
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
ret i32 %swapped
|
||||
}
|
||||
|
||||
; Check that LRV allows an index.
|
||||
define i32 @f7(i64 %src, i64 %index) {
|
||||
; CHECK: f7:
|
||||
; CHECK: lrv %r2, 524287({{%r3,%r2|%r2,%r3}})
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%add2 = add i64 %add1, 524287
|
||||
%ptr = inttoptr i64 %add2 to i32 *
|
||||
%a = load i32 *%ptr
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
ret i32 %swapped
|
||||
}
|
87
test/CodeGen/SystemZ/bswap-03.ll
Normal file
87
test/CodeGen/SystemZ/bswap-03.ll
Normal file
@ -0,0 +1,87 @@
|
||||
; Test 64-bit byteswaps from memory to registers.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
declare i64 @llvm.bswap.i64(i64 %a)
|
||||
|
||||
; Check LRVG with no displacement.
|
||||
define i64 @f1(i64 *%src) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lrvg %r2, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%a = load i64 *%src
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
ret i64 %swapped
|
||||
}
|
||||
|
||||
; Check the high end of the aligned LRVG range.
|
||||
define i64 @f2(i64 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lrvg %r2, 524280(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 65535
|
||||
%a = load i64 *%ptr
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
ret i64 %swapped
|
||||
}
|
||||
|
||||
; Check the next doubleword up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i64 @f3(i64 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: agfi %r2, 524288
|
||||
; CHECK: lrvg %r2, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 65536
|
||||
%a = load i64 *%ptr
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
ret i64 %swapped
|
||||
}
|
||||
|
||||
; Check the high end of the negative aligned LRVG range.
|
||||
define i64 @f4(i64 *%src) {
|
||||
; CHECK: f4:
|
||||
; CHECK: lrvg %r2, -8(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -1
|
||||
%a = load i64 *%ptr
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
ret i64 %swapped
|
||||
}
|
||||
|
||||
; Check the low end of the LRVG range.
|
||||
define i64 @f5(i64 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: lrvg %r2, -524288(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -65536
|
||||
%a = load i64 *%ptr
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
ret i64 %swapped
|
||||
}
|
||||
|
||||
; Check the next doubleword down, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i64 @f6(i64 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: agfi %r2, -524296
|
||||
; CHECK: lrvg %r2, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -65537
|
||||
%a = load i64 *%ptr
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
ret i64 %swapped
|
||||
}
|
||||
|
||||
; Check that LRVG allows an index.
|
||||
define i64 @f7(i64 %src, i64 %index) {
|
||||
; CHECK: f7:
|
||||
; CHECK: lrvg %r2, 524287({{%r3,%r2|%r2,%r3}})
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%add2 = add i64 %add1, 524287
|
||||
%ptr = inttoptr i64 %add2 to i64 *
|
||||
%a = load i64 *%ptr
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
ret i64 %swapped
|
||||
}
|
87
test/CodeGen/SystemZ/bswap-04.ll
Normal file
87
test/CodeGen/SystemZ/bswap-04.ll
Normal file
@ -0,0 +1,87 @@
|
||||
; Test 32-bit byteswaps from registers to memory.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
declare i32 @llvm.bswap.i32(i32 %a)
|
||||
|
||||
; Check STRV with no displacement.
|
||||
define void @f1(i32 *%src, i32 %a) {
|
||||
; CHECK: f1:
|
||||
; CHECK: strv %r3, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
store i32 %swapped, i32 *%src
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the high end of the aligned STRV range.
|
||||
define void @f2(i32 *%src, i32 %a) {
|
||||
; CHECK: f2:
|
||||
; CHECK: strv %r3, 524284(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 131071
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
store i32 %swapped, i32 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next word up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define void @f3(i32 *%src, i32 %a) {
|
||||
; CHECK: f3:
|
||||
; CHECK: agfi %r2, 524288
|
||||
; CHECK: strv %r3, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 131072
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
store i32 %swapped, i32 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the high end of the negative aligned STRV range.
|
||||
define void @f4(i32 *%src, i32 %a) {
|
||||
; CHECK: f4:
|
||||
; CHECK: strv %r3, -4(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -1
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
store i32 %swapped, i32 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the low end of the STRV range.
|
||||
define void @f5(i32 *%src, i32 %a) {
|
||||
; CHECK: f5:
|
||||
; CHECK: strv %r3, -524288(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -131072
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
store i32 %swapped, i32 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next word down, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define void @f6(i32 *%src, i32 %a) {
|
||||
; CHECK: f6:
|
||||
; CHECK: agfi %r2, -524292
|
||||
; CHECK: strv %r3, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i32 *%src, i64 -131073
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
store i32 %swapped, i32 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check that STRV allows an index.
|
||||
define void @f7(i64 %src, i64 %index, i32 %a) {
|
||||
; CHECK: f7:
|
||||
; CHECK: strv %r4, 524287({{%r3,%r2|%r2,%r3}})
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%add2 = add i64 %add1, 524287
|
||||
%ptr = inttoptr i64 %add2 to i32 *
|
||||
%swapped = call i32 @llvm.bswap.i32(i32 %a)
|
||||
store i32 %swapped, i32 *%ptr
|
||||
ret void
|
||||
}
|
87
test/CodeGen/SystemZ/bswap-05.ll
Normal file
87
test/CodeGen/SystemZ/bswap-05.ll
Normal file
@ -0,0 +1,87 @@
|
||||
; Test 64-bit byteswaps from registers to memory.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
declare i64 @llvm.bswap.i64(i64 %a)
|
||||
|
||||
; Check STRVG with no displacement.
|
||||
define void @f1(i64 *%src, i64 %a) {
|
||||
; CHECK: f1:
|
||||
; CHECK: strvg %r3, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
store i64 %swapped, i64 *%src
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the high end of the aligned STRVG range.
|
||||
define void @f2(i64 *%src, i64 %a) {
|
||||
; CHECK: f2:
|
||||
; CHECK: strvg %r3, 524280(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 65535
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
store i64 %swapped, i64 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next doubleword up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define void @f3(i64 *%src, i64 %a) {
|
||||
; CHECK: f3:
|
||||
; CHECK: agfi %r2, 524288
|
||||
; CHECK: strvg %r3, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 65536
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
store i64 %swapped, i64 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the high end of the negative aligned STRVG range.
|
||||
define void @f4(i64 *%src, i64 %a) {
|
||||
; CHECK: f4:
|
||||
; CHECK: strvg %r3, -8(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -1
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
store i64 %swapped, i64 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the low end of the STRVG range.
|
||||
define void @f5(i64 *%src, i64 %a) {
|
||||
; CHECK: f5:
|
||||
; CHECK: strvg %r3, -524288(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -65536
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
store i64 %swapped, i64 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check the next doubleword down, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define void @f6(i64 *%src, i64 %a) {
|
||||
; CHECK: f6:
|
||||
; CHECK: agfi %r2, -524296
|
||||
; CHECK: strvg %r3, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr i64 *%src, i64 -65537
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
store i64 %swapped, i64 *%ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check that STRVG allows an index.
|
||||
define void @f7(i64 %src, i64 %index, i64 %a) {
|
||||
; CHECK: f7:
|
||||
; CHECK: strvg %r4, 524287({{%r3,%r2|%r2,%r3}})
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%add2 = add i64 %add1, 524287
|
||||
%ptr = inttoptr i64 %add2 to i64 *
|
||||
%swapped = call i64 @llvm.bswap.i64(i64 %a)
|
||||
store i64 %swapped, i64 *%ptr
|
||||
ret void
|
||||
}
|
18
test/CodeGen/SystemZ/call-01.ll
Normal file
18
test/CodeGen/SystemZ/call-01.ll
Normal file
@ -0,0 +1,18 @@
|
||||
; Test direct calls.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
declare i64 @bar()
|
||||
|
||||
; We must allocate 160 bytes for the callee and save and restore %r14.
|
||||
define i64 @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: stmg %r14, %r15, 112(%r15)
|
||||
; CHECK: aghi %r15, -160
|
||||
; CHECK: brasl %r14, bar@PLT
|
||||
; CHECK: lmg %r14, %r15, 272(%r15)
|
||||
; CHECK: br %r14
|
||||
%ret = call i64 @bar()
|
||||
%inc = add i64 %ret, 1
|
||||
ret i64 %inc
|
||||
}
|
16
test/CodeGen/SystemZ/call-02.ll
Normal file
16
test/CodeGen/SystemZ/call-02.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; Test indirect calls.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; We must allocate 160 bytes for the callee and save and restore %r14.
|
||||
define i64 @f1(i64() *%bar) {
|
||||
; CHECK: f1:
|
||||
; CHECK: stmg %r14, %r15, 112(%r15)
|
||||
; CHECK: aghi %r15, -160
|
||||
; CHECK: basr %r14, %r2
|
||||
; CHECK: lmg %r14, %r15, 272(%r15)
|
||||
; CHECK: br %r14
|
||||
%ret = call i64 %bar()
|
||||
%inc = add i64 %ret, 1
|
||||
ret i64 %inc
|
||||
}
|
56
test/CodeGen/SystemZ/cmpxchg-01.ll
Normal file
56
test/CodeGen/SystemZ/cmpxchg-01.ll
Normal file
@ -0,0 +1,56 @@
|
||||
; Test 8-bit compare and swap.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-MAIN
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT
|
||||
|
||||
; Check compare and swap with a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK. CHECK-SHIFT also checks that %r3 is not modified before
|
||||
; being used in the RISBG (in contrast to things like atomic addition,
|
||||
; which shift %r3 left so that %b is at the high end of the word).
|
||||
define i8 @f1(i8 %dummy, i8 *%src, i8 %cmp, i8 %swap) {
|
||||
; CHECK-MAIN: f1:
|
||||
; CHECK-MAIN: sllg [[SHIFT:%r[1-9]+]], %r3, 3
|
||||
; CHECK-MAIN: nill %r3, 65532
|
||||
; CHECK-MAIN: l [[OLD:%r[0-9]+]], 0(%r3)
|
||||
; CHECK-MAIN: [[LOOP:\.[^ ]*]]:
|
||||
; CHECK-MAIN: rll %r2, [[OLD]], 8([[SHIFT]])
|
||||
; CHECK-MAIN: risbg %r4, %r2, 32, 55, 0
|
||||
; CHECK-MAIN: cr %r2, %r4
|
||||
; CHECK-MAIN: j{{g?}}lh [[EXIT:\.[^ ]*]]
|
||||
; CHECK-MAIN: risbg %r5, %r2, 32, 55, 0
|
||||
; CHECK-MAIN: rll [[NEW:%r[0-9]+]], %r5, -8({{%r[1-9]+}})
|
||||
; CHECK-MAIN: cs [[OLD]], [[NEW]], 0(%r3)
|
||||
; CHECK-MAIN: j{{g?}}lh [[LOOP]]
|
||||
; CHECK-MAIN: [[EXIT]]:
|
||||
; CHECK-MAIN-NOT: %r2
|
||||
; CHECK-MAIN: br %r14
|
||||
;
|
||||
; CHECK-SHIFT: f1:
|
||||
; CHECK-SHIFT: sllg [[SHIFT:%r[1-9]+]], %r3, 3
|
||||
; 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
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check compare and swap with constants. We should force the constants into
|
||||
; registers and use the sequence above.
|
||||
define i8 @f2(i8 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lhi [[CMP:%r[0-9]+]], 42
|
||||
; CHECK: risbg [[CMP]], {{%r[0-9]+}}, 32, 55, 0
|
||||
; CHECK: risbg
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT: f2:
|
||||
; CHECK-SHIFT: lhi [[SWAP:%r[0-9]+]], 88
|
||||
; 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
|
||||
ret i8 %res
|
||||
}
|
56
test/CodeGen/SystemZ/cmpxchg-02.ll
Normal file
56
test/CodeGen/SystemZ/cmpxchg-02.ll
Normal file
@ -0,0 +1,56 @@
|
||||
; Test 16-bit compare and swap.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-MAIN
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT
|
||||
|
||||
; Check compare and swap with a variable.
|
||||
; - CHECK is for the main loop.
|
||||
; - CHECK-SHIFT makes sure that the negated shift count used by the second
|
||||
; RLL is set up correctly. The negation is independent of the NILL and L
|
||||
; tested in CHECK. CHECK-SHIFT also checks that %r3 is not modified before
|
||||
; being used in the RISBG (in contrast to things like atomic addition,
|
||||
; which shift %r3 left so that %b is at the high end of the word).
|
||||
define i16 @f1(i16 %dummy, i16 *%src, i16 %cmp, i16 %swap) {
|
||||
; CHECK-MAIN: f1:
|
||||
; CHECK-MAIN: sllg [[SHIFT:%r[1-9]+]], %r3, 3
|
||||
; CHECK-MAIN: nill %r3, 65532
|
||||
; CHECK-MAIN: l [[OLD:%r[0-9]+]], 0(%r3)
|
||||
; CHECK-MAIN: [[LOOP:\.[^ ]*]]:
|
||||
; CHECK-MAIN: rll %r2, [[OLD]], 16([[SHIFT]])
|
||||
; CHECK-MAIN: risbg %r4, %r2, 32, 47, 0
|
||||
; CHECK-MAIN: cr %r2, %r4
|
||||
; CHECK-MAIN: j{{g?}}lh [[EXIT:\.[^ ]*]]
|
||||
; CHECK-MAIN: risbg %r5, %r2, 32, 47, 0
|
||||
; CHECK-MAIN: rll [[NEW:%r[0-9]+]], %r5, -16({{%r[1-9]+}})
|
||||
; CHECK-MAIN: cs [[OLD]], [[NEW]], 0(%r3)
|
||||
; CHECK-MAIN: j{{g?}}lh [[LOOP]]
|
||||
; CHECK-MAIN: [[EXIT]]:
|
||||
; CHECK-MAIN-NOT: %r2
|
||||
; CHECK-MAIN: br %r14
|
||||
;
|
||||
; CHECK-SHIFT: f1:
|
||||
; CHECK-SHIFT: sllg [[SHIFT:%r[1-9]+]], %r3, 3
|
||||
; 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
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
; Check compare and swap with constants. We should force the constants into
|
||||
; registers and use the sequence above.
|
||||
define i16 @f2(i16 *%src) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lhi [[CMP:%r[0-9]+]], 42
|
||||
; CHECK: risbg [[CMP]], {{%r[0-9]+}}, 32, 47, 0
|
||||
; CHECK: risbg
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CHECK-SHIFT: f2:
|
||||
; CHECK-SHIFT: lhi [[SWAP:%r[0-9]+]], 88
|
||||
; 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
|
||||
ret i16 %res
|
||||
}
|
131
test/CodeGen/SystemZ/cmpxchg-03.ll
Normal file
131
test/CodeGen/SystemZ/cmpxchg-03.ll
Normal file
@ -0,0 +1,131 @@
|
||||
; Test 32-bit compare and swap.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check the low end of the CS range.
|
||||
define i32 @f1(i32 %cmp, i32 %swap, i32 *%src) {
|
||||
; CHECK: f1:
|
||||
; CHECK: cs %r2, %r3, 0(%r4)
|
||||
; CHECK: br %r14
|
||||
%val = cmpxchg i32 *%src, i32 %cmp, i32 %swap seq_cst
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CS range.
|
||||
define i32 @f2(i32 %cmp, i32 %swap, i32 *%src) {
|
||||
; CHECK: f2:
|
||||
; 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
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check the next word up, which should use CSY instead of CS.
|
||||
define i32 @f3(i32 %cmp, i32 %swap, i32 *%src) {
|
||||
; CHECK: f3:
|
||||
; 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
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CSY range.
|
||||
define i32 @f4(i32 %cmp, i32 %swap, i32 *%src) {
|
||||
; CHECK: f4:
|
||||
; 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
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check the next word up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i32 @f5(i32 %cmp, i32 %swap, i32 *%src) {
|
||||
; CHECK: f5:
|
||||
; CHECK: agfi %r4, 524288
|
||||
; 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
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check the high end of the negative aligned CSY range.
|
||||
define i32 @f6(i32 %cmp, i32 %swap, i32 *%src) {
|
||||
; CHECK: f6:
|
||||
; 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
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check the low end of the CSY range.
|
||||
define i32 @f7(i32 %cmp, i32 %swap, i32 *%src) {
|
||||
; CHECK: f7:
|
||||
; 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
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check the next word down, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i32 @f8(i32 %cmp, i32 %swap, i32 *%src) {
|
||||
; CHECK: f8:
|
||||
; CHECK: agfi %r4, -524292
|
||||
; 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
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check that CS does not allow an index.
|
||||
define i32 @f9(i32 %cmp, i32 %swap, i64 %src, i64 %index) {
|
||||
; CHECK: f9:
|
||||
; CHECK: agr %r4, %r5
|
||||
; CHECK: cs %r2, %r3, 0(%r4)
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%ptr = inttoptr i64 %add1 to i32 *
|
||||
%val = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check that CSY does not allow an index.
|
||||
define i32 @f10(i32 %cmp, i32 %swap, i64 %src, i64 %index) {
|
||||
; CHECK: f10:
|
||||
; CHECK: agr %r4, %r5
|
||||
; CHECK: csy %r2, %r3, 4096(%r4)
|
||||
; CHECK: br %r14
|
||||
%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
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check that a constant %cmp value is loaded into a register first.
|
||||
define i32 @f11(i32 %dummy, i32 %swap, i32 *%ptr) {
|
||||
; CHECK: f11:
|
||||
; CHECK: lhi %r2, 1001
|
||||
; CHECK: cs %r2, %r3, 0(%r4)
|
||||
; CHECK: br %r14
|
||||
%val = cmpxchg i32 *%ptr, i32 1001, i32 %swap seq_cst
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; Check that a constant %swap value is loaded into a register first.
|
||||
define i32 @f12(i32 %cmp, i32 *%ptr) {
|
||||
; CHECK: f12:
|
||||
; 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
|
||||
ret i32 %val
|
||||
}
|
98
test/CodeGen/SystemZ/cmpxchg-04.ll
Normal file
98
test/CodeGen/SystemZ/cmpxchg-04.ll
Normal file
@ -0,0 +1,98 @@
|
||||
; Test 64-bit compare and swap.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check CSG without a displacement.
|
||||
define i64 @f1(i64 %cmp, i64 %swap, i64 *%src) {
|
||||
; CHECK: f1:
|
||||
; CHECK: csg %r2, %r3, 0(%r4)
|
||||
; CHECK: br %r14
|
||||
%val = cmpxchg i64 *%src, i64 %cmp, i64 %swap seq_cst
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CSG range.
|
||||
define i64 @f2(i64 %cmp, i64 %swap, i64 *%src) {
|
||||
; CHECK: f2:
|
||||
; 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
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
; Check the next doubleword up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i64 @f3(i64 %cmp, i64 %swap, i64 *%src) {
|
||||
; CHECK: f3:
|
||||
; CHECK: agfi %r4, 524288
|
||||
; 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
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
; Check the high end of the negative aligned CSG range.
|
||||
define i64 @f4(i64 %cmp, i64 %swap, i64 *%src) {
|
||||
; CHECK: f4:
|
||||
; 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
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
; Check the low end of the CSG range.
|
||||
define i64 @f5(i64 %cmp, i64 %swap, i64 *%src) {
|
||||
; CHECK: f5:
|
||||
; 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
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
; Check the next doubleword down, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i64 @f6(i64 %cmp, i64 %swap, i64 *%src) {
|
||||
; CHECK: f6:
|
||||
; CHECK: agfi %r4, -524296
|
||||
; 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
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
; Check that CSG does not allow an index.
|
||||
define i64 @f7(i64 %cmp, i64 %swap, i64 %src, i64 %index) {
|
||||
; CHECK: f7:
|
||||
; CHECK: agr %r4, %r5
|
||||
; CHECK: csg %r2, %r3, 0(%r4)
|
||||
; CHECK: br %r14
|
||||
%add1 = add i64 %src, %index
|
||||
%ptr = inttoptr i64 %add1 to i64 *
|
||||
%val = cmpxchg i64 *%ptr, i64 %cmp, i64 %swap seq_cst
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
; Check that a constant %cmp value is loaded into a register first.
|
||||
define i64 @f8(i64 %dummy, i64 %swap, i64 *%ptr) {
|
||||
; CHECK: f8:
|
||||
; CHECK: lghi %r2, 1001
|
||||
; CHECK: csg %r2, %r3, 0(%r4)
|
||||
; CHECK: br %r14
|
||||
%val = cmpxchg i64 *%ptr, i64 1001, i64 %swap seq_cst
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
; Check that a constant %swap value is loaded into a register first.
|
||||
define i64 @f9(i64 %cmp, i64 *%ptr) {
|
||||
; CHECK: f9:
|
||||
; 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
|
||||
ret i64 %val
|
||||
}
|
40
test/CodeGen/SystemZ/fp-abs-01.ll
Normal file
40
test/CodeGen/SystemZ/fp-abs-01.ll
Normal file
@ -0,0 +1,40 @@
|
||||
; Test floating-point absolute.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Test f32.
|
||||
declare float @llvm.fabs.f32(float %f)
|
||||
define float @f1(float %f) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lpebr %f0, %f0
|
||||
; CHECK: br %r14
|
||||
%res = call float @llvm.fabs.f32(float %f)
|
||||
ret float %res
|
||||
}
|
||||
|
||||
; Test f64.
|
||||
declare double @llvm.fabs.f64(double %f)
|
||||
define double @f2(double %f) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lpdbr %f0, %f0
|
||||
; CHECK: br %r14
|
||||
%res = call double @llvm.fabs.f64(double %f)
|
||||
ret double %res
|
||||
}
|
||||
|
||||
; Test f128. With the loads and stores, a pure absolute would probably
|
||||
; be better implemented using an NI on the upper byte. Do some extra
|
||||
; processing so that using FPRs is unequivocally better.
|
||||
declare fp128 @llvm.fabs.f128(fp128 %f)
|
||||
define void @f3(fp128 *%ptr, fp128 *%ptr2) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lpxbr
|
||||
; CHECK: dxbr
|
||||
; CHECK: br %r14
|
||||
%orig = load fp128 *%ptr
|
||||
%abs = call fp128 @llvm.fabs.f128(fp128 %orig)
|
||||
%op2 = load fp128 *%ptr2
|
||||
%res = fdiv fp128 %abs, %op2
|
||||
store fp128 %res, fp128 *%ptr
|
||||
ret void
|
||||
}
|
43
test/CodeGen/SystemZ/fp-abs-02.ll
Normal file
43
test/CodeGen/SystemZ/fp-abs-02.ll
Normal file
@ -0,0 +1,43 @@
|
||||
; Test negated floating-point absolute.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Test f32.
|
||||
declare float @llvm.fabs.f32(float %f)
|
||||
define float @f1(float %f) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lnebr %f0, %f0
|
||||
; CHECK: br %r14
|
||||
%abs = call float @llvm.fabs.f32(float %f)
|
||||
%res = fsub float -0.0, %abs
|
||||
ret float %res
|
||||
}
|
||||
|
||||
; Test f64.
|
||||
declare double @llvm.fabs.f64(double %f)
|
||||
define double @f2(double %f) {
|
||||
; CHECK: f2:
|
||||
; CHECK: lndbr %f0, %f0
|
||||
; CHECK: br %r14
|
||||
%abs = call double @llvm.fabs.f64(double %f)
|
||||
%res = fsub double -0.0, %abs
|
||||
ret double %res
|
||||
}
|
||||
|
||||
; Test f128. With the loads and stores, a pure negative-absolute would
|
||||
; probably be better implemented using an OI on the upper byte. Do some
|
||||
; extra processing so that using FPRs is unequivocally better.
|
||||
declare fp128 @llvm.fabs.f128(fp128 %f)
|
||||
define void @f3(fp128 *%ptr, fp128 *%ptr2) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lnxbr
|
||||
; CHECK: dxbr
|
||||
; CHECK: br %r14
|
||||
%orig = load fp128 *%ptr
|
||||
%abs = call fp128 @llvm.fabs.f128(fp128 %orig)
|
||||
%negabs = fsub fp128 0xL00000000000000008000000000000000, %abs
|
||||
%op2 = load fp128 *%ptr2
|
||||
%res = fdiv fp128 %negabs, %op2
|
||||
store fp128 %res, fp128 *%ptr
|
||||
ret void
|
||||
}
|
71
test/CodeGen/SystemZ/fp-add-01.ll
Normal file
71
test/CodeGen/SystemZ/fp-add-01.ll
Normal file
@ -0,0 +1,71 @@
|
||||
; Test 32-bit floating-point addition.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check register addition.
|
||||
define float @f1(float %f1, float %f2) {
|
||||
; CHECK: f1:
|
||||
; CHECK: aebr %f0, %f2
|
||||
; CHECK: br %r14
|
||||
%res = fadd float %f1, %f2
|
||||
ret float %res
|
||||
}
|
||||
|
||||
; Check the low end of the AEB range.
|
||||
define float @f2(float %f1, float *%ptr) {
|
||||
; CHECK: f2:
|
||||
; CHECK: aeb %f0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%f2 = load float *%ptr
|
||||
%res = fadd float %f1, %f2
|
||||
ret float %res
|
||||
}
|
||||
|
||||
; Check the high end of the aligned AEB range.
|
||||
define float @f3(float %f1, float *%base) {
|
||||
; CHECK: f3:
|
||||
; CHECK: aeb %f0, 4092(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr float *%base, i64 1023
|
||||
%f2 = load float *%ptr
|
||||
%res = fadd float %f1, %f2
|
||||
ret float %res
|
||||
}
|
||||
|
||||
; Check the next word up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define float @f4(float %f1, float *%base) {
|
||||
; CHECK: f4:
|
||||
; CHECK: aghi %r2, 4096
|
||||
; CHECK: aeb %f0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr float *%base, i64 1024
|
||||
%f2 = load float *%ptr
|
||||
%res = fadd float %f1, %f2
|
||||
ret float %res
|
||||
}
|
||||
|
||||
; Check negative displacements, which also need separate address logic.
|
||||
define float @f5(float %f1, float *%base) {
|
||||
; CHECK: f5:
|
||||
; CHECK: aghi %r2, -4
|
||||
; CHECK: aeb %f0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr float *%base, i64 -1
|
||||
%f2 = load float *%ptr
|
||||
%res = fadd float %f1, %f2
|
||||
ret float %res
|
||||
}
|
||||
|
||||
; Check that AEB allows indices.
|
||||
define float @f6(float %f1, float *%base, i64 %index) {
|
||||
; CHECK: f6:
|
||||
; CHECK: sllg %r1, %r3, 2
|
||||
; CHECK: aeb %f0, 400(%r1,%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr1 = getelementptr float *%base, i64 %index
|
||||
%ptr2 = getelementptr float *%ptr1, i64 100
|
||||
%f2 = load float *%ptr2
|
||||
%res = fadd float %f1, %f2
|
||||
ret float %res
|
||||
}
|
71
test/CodeGen/SystemZ/fp-add-02.ll
Normal file
71
test/CodeGen/SystemZ/fp-add-02.ll
Normal file
@ -0,0 +1,71 @@
|
||||
; Test 64-bit floating-point addition.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check register addition.
|
||||
define double @f1(double %f1, double %f2) {
|
||||
; CHECK: f1:
|
||||
; CHECK: adbr %f0, %f2
|
||||
; CHECK: br %r14
|
||||
%res = fadd double %f1, %f2
|
||||
ret double %res
|
||||
}
|
||||
|
||||
; Check the low end of the ADB range.
|
||||
define double @f2(double %f1, double *%ptr) {
|
||||
; CHECK: f2:
|
||||
; CHECK: adb %f0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%f2 = load double *%ptr
|
||||
%res = fadd double %f1, %f2
|
||||
ret double %res
|
||||
}
|
||||
|
||||
; Check the high end of the aligned ADB range.
|
||||
define double @f3(double %f1, double *%base) {
|
||||
; CHECK: f3:
|
||||
; CHECK: adb %f0, 4088(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr double *%base, i64 511
|
||||
%f2 = load double *%ptr
|
||||
%res = fadd double %f1, %f2
|
||||
ret double %res
|
||||
}
|
||||
|
||||
; Check the next doubleword up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define double @f4(double %f1, double *%base) {
|
||||
; CHECK: f4:
|
||||
; CHECK: aghi %r2, 4096
|
||||
; CHECK: adb %f0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr double *%base, i64 512
|
||||
%f2 = load double *%ptr
|
||||
%res = fadd double %f1, %f2
|
||||
ret double %res
|
||||
}
|
||||
|
||||
; Check negative displacements, which also need separate address logic.
|
||||
define double @f5(double %f1, double *%base) {
|
||||
; CHECK: f5:
|
||||
; CHECK: aghi %r2, -8
|
||||
; CHECK: adb %f0, 0(%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr double *%base, i64 -1
|
||||
%f2 = load double *%ptr
|
||||
%res = fadd double %f1, %f2
|
||||
ret double %res
|
||||
}
|
||||
|
||||
; Check that ADB allows indices.
|
||||
define double @f6(double %f1, double *%base, i64 %index) {
|
||||
; CHECK: f6:
|
||||
; CHECK: sllg %r1, %r3, 3
|
||||
; CHECK: adb %f0, 800(%r1,%r2)
|
||||
; CHECK: br %r14
|
||||
%ptr1 = getelementptr double *%base, i64 %index
|
||||
%ptr2 = getelementptr double *%ptr1, i64 100
|
||||
%f2 = load double *%ptr2
|
||||
%res = fadd double %f1, %f2
|
||||
ret double %res
|
||||
}
|
20
test/CodeGen/SystemZ/fp-add-03.ll
Normal file
20
test/CodeGen/SystemZ/fp-add-03.ll
Normal file
@ -0,0 +1,20 @@
|
||||
; Test 128-bit floating-point addition.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; There is no memory form of 128-bit addition.
|
||||
define void @f1(fp128 *%ptr, float %f2) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lxebr %f0, %f0
|
||||
; CHECK: ld %f1, 0(%r2)
|
||||
; CHECK: ld %f3, 8(%r2)
|
||||
; CHECK: axbr %f1, %f0
|
||||
; CHECK: std %f1, 0(%r2)
|
||||
; CHECK: std %f3, 8(%r2)
|
||||
; CHECK: br %r14
|
||||
%f1 = load fp128 *%ptr
|
||||
%f2x = fpext float %f2 to fp128
|
||||
%sum = fadd fp128 %f1, %f2x
|
||||
store fp128 %sum, fp128 *%ptr
|
||||
ret void
|
||||
}
|
89
test/CodeGen/SystemZ/fp-cmp-01.ll
Normal file
89
test/CodeGen/SystemZ/fp-cmp-01.ll
Normal file
@ -0,0 +1,89 @@
|
||||
; Test 32-bit floating-point comparison.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check comparison with registers.
|
||||
define i64 @f1(i64 %a, i64 %b, float %f1, float %f2) {
|
||||
; CHECK: f1:
|
||||
; CHECK: cebr %f0, %f2
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%cond = fcmp oeq float %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the CEB range.
|
||||
define i64 @f2(i64 %a, i64 %b, float %f1, float *%ptr) {
|
||||
; CHECK: f2:
|
||||
; CHECK: ceb %f0, 0(%r4)
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%f2 = load float *%ptr
|
||||
%cond = fcmp oeq float %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CEB range.
|
||||
define i64 @f3(i64 %a, i64 %b, float %f1, float *%base) {
|
||||
; CHECK: f3:
|
||||
; CHECK: ceb %f0, 4092(%r4)
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr float *%base, i64 1023
|
||||
%f2 = load float *%ptr
|
||||
%cond = fcmp oeq float %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next word up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i64 @f4(i64 %a, i64 %b, float %f1, float *%base) {
|
||||
; CHECK: f4:
|
||||
; CHECK: aghi %r4, 4096
|
||||
; CHECK: ceb %f0, 0(%r4)
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr float *%base, i64 1024
|
||||
%f2 = load float *%ptr
|
||||
%cond = fcmp oeq float %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check negative displacements, which also need separate address logic.
|
||||
define i64 @f5(i64 %a, i64 %b, float %f1, float *%base) {
|
||||
; CHECK: f5:
|
||||
; CHECK: aghi %r4, -4
|
||||
; CHECK: ceb %f0, 0(%r4)
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr float *%base, i64 -1
|
||||
%f2 = load float *%ptr
|
||||
%cond = fcmp oeq float %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check that CEB allows indices.
|
||||
define i64 @f6(i64 %a, i64 %b, float %f1, float *%base, i64 %index) {
|
||||
; CHECK: f6:
|
||||
; CHECK: sllg %r1, %r5, 2
|
||||
; CHECK: ceb %f0, 400(%r1,%r4)
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%ptr1 = getelementptr float *%base, i64 %index
|
||||
%ptr2 = getelementptr float *%ptr1, i64 100
|
||||
%f2 = load float *%ptr2
|
||||
%cond = fcmp oeq float %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
89
test/CodeGen/SystemZ/fp-cmp-02.ll
Normal file
89
test/CodeGen/SystemZ/fp-cmp-02.ll
Normal file
@ -0,0 +1,89 @@
|
||||
; Test 64-bit floating-point comparison.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Check comparison with registers.
|
||||
define i64 @f1(i64 %a, i64 %b, double %f1, double %f2) {
|
||||
; CHECK: f1:
|
||||
; CHECK: cdbr %f0, %f2
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%cond = fcmp oeq double %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the low end of the CDB range.
|
||||
define i64 @f2(i64 %a, i64 %b, double %f1, double *%ptr) {
|
||||
; CHECK: f2:
|
||||
; CHECK: cdb %f0, 0(%r4)
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%f2 = load double *%ptr
|
||||
%cond = fcmp oeq double %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the high end of the aligned CDB range.
|
||||
define i64 @f3(i64 %a, i64 %b, double %f1, double *%base) {
|
||||
; CHECK: f3:
|
||||
; CHECK: cdb %f0, 4088(%r4)
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr double *%base, i64 511
|
||||
%f2 = load double *%ptr
|
||||
%cond = fcmp oeq double %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check the next doubleword up, which needs separate address logic.
|
||||
; Other sequences besides this one would be OK.
|
||||
define i64 @f4(i64 %a, i64 %b, double %f1, double *%base) {
|
||||
; CHECK: f4:
|
||||
; CHECK: aghi %r4, 4096
|
||||
; CHECK: cdb %f0, 0(%r4)
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr double *%base, i64 512
|
||||
%f2 = load double *%ptr
|
||||
%cond = fcmp oeq double %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check negative displacements, which also need separate address logic.
|
||||
define i64 @f5(i64 %a, i64 %b, double %f1, double *%base) {
|
||||
; CHECK: f5:
|
||||
; CHECK: aghi %r4, -8
|
||||
; CHECK: cdb %f0, 0(%r4)
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%ptr = getelementptr double *%base, i64 -1
|
||||
%f2 = load double *%ptr
|
||||
%cond = fcmp oeq double %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; Check that CDB allows indices.
|
||||
define i64 @f6(i64 %a, i64 %b, double %f1, double *%base, i64 %index) {
|
||||
; CHECK: f6:
|
||||
; CHECK: sllg %r1, %r5, 3
|
||||
; CHECK: cdb %f0, 800(%r1,%r4)
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%ptr1 = getelementptr double *%base, i64 %index
|
||||
%ptr2 = getelementptr double *%ptr1, i64 100
|
||||
%f2 = load double *%ptr2
|
||||
%cond = fcmp oeq double %f1, %f2
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
20
test/CodeGen/SystemZ/fp-cmp-03.ll
Normal file
20
test/CodeGen/SystemZ/fp-cmp-03.ll
Normal file
@ -0,0 +1,20 @@
|
||||
; Test 128-bit floating-point comparison.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; There is no memory form of 128-bit comparison.
|
||||
define i64 @f1(i64 %a, i64 %b, fp128 *%ptr, float %f2) {
|
||||
; CHECK: f1:
|
||||
; CHECK: lxebr %f0, %f0
|
||||
; CHECK: ld %f1, 0(%r4)
|
||||
; CHECK: ld %f3, 8(%r4)
|
||||
; CHECK: cxbr %f1, %f0
|
||||
; CHECK-NEXT: j{{g?}}e
|
||||
; CHECK: lgr %r2, %r3
|
||||
; CHECK: br %r14
|
||||
%f2x = fpext float %f2 to fp128
|
||||
%f1 = load fp128 *%ptr
|
||||
%cond = fcmp oeq fp128 %f1, %f2x
|
||||
%res = select i1 %cond, i64 %a, i64 %b
|
||||
ret i64 %res
|
||||
}
|
30
test/CodeGen/SystemZ/fp-const-01.ll
Normal file
30
test/CodeGen/SystemZ/fp-const-01.ll
Normal file
@ -0,0 +1,30 @@
|
||||
; Test loads of floating-point zero.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Test f32.
|
||||
define float @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: lzer %f0
|
||||
; CHECK: br %r14
|
||||
ret float 0.0
|
||||
}
|
||||
|
||||
; Test f64.
|
||||
define double @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: lzdr %f0
|
||||
; CHECK: br %r14
|
||||
ret double 0.0
|
||||
}
|
||||
|
||||
; Test f128.
|
||||
define void @f3(fp128 *%x) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lzxr %f0
|
||||
; CHECK: std %f0, 0(%r2)
|
||||
; CHECK: std %f2, 8(%r2)
|
||||
; CHECK: br %r14
|
||||
store fp128 0xL00000000000000000000000000000000, fp128 *%x
|
||||
ret void
|
||||
}
|
31
test/CodeGen/SystemZ/fp-const-02.ll
Normal file
31
test/CodeGen/SystemZ/fp-const-02.ll
Normal file
@ -0,0 +1,31 @@
|
||||
; Test loads of negative floating-point zero.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Test f32.
|
||||
define float @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: lzer [[REGISTER:%f[0-5]+]]
|
||||
; CHECK: lcebr %f0, [[REGISTER]]
|
||||
; CHECK: br %r14
|
||||
ret float -0.0
|
||||
}
|
||||
|
||||
; Test f64.
|
||||
define double @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: lzdr [[REGISTER:%f[0-5]+]]
|
||||
; CHECK: lcdbr %f0, [[REGISTER]]
|
||||
; CHECK: br %r14
|
||||
ret double -0.0
|
||||
}
|
||||
|
||||
; Test f128.
|
||||
define void @f3(fp128 *%x) {
|
||||
; CHECK: f3:
|
||||
; CHECK: lzxr [[REGISTER:%f[0-5]+]]
|
||||
; CHECK: lcxbr %f0, [[REGISTER]]
|
||||
; CHECK: br %r14
|
||||
store fp128 0xL00000000000000008000000000000000, fp128 *%x
|
||||
ret void
|
||||
}
|
14
test/CodeGen/SystemZ/fp-const-03.ll
Normal file
14
test/CodeGen/SystemZ/fp-const-03.ll
Normal file
@ -0,0 +1,14 @@
|
||||
; Test loads of 32-bit floating-point constants.
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CONST
|
||||
|
||||
define float @f1() {
|
||||
; CHECK: f1:
|
||||
; CHECK: larl [[REGISTER:%r[1-5]]], {{.*}}
|
||||
; CHECK: le %f0, 0([[REGISTER]])
|
||||
; CHECK: br %r14
|
||||
;
|
||||
; CONST: .long 1065353217
|
||||
ret float 0x3ff0000020000000
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user