1 ; Test 128-bit addition in which the second operand is variable.
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
5 ; Test register addition.
6 define void @f1(i128 *%ptr, i64 %high, i64 %low) {
8 ; CHECK: slgr {{%r[0-5]}}, %r4
9 ; CHECK: slbgr {{%r[0-5]}}, %r3
12 %highx = zext i64 %high to i128
13 %lowx = zext i64 %low to i128
14 %bhigh = shl i128 %highx, 64
15 %b = or i128 %bhigh, %lowx
16 %sub = sub i128 %a, %b
17 store i128 %sub, i128 *%ptr
21 ; Test memory addition with no offset.
22 define void @f2(i64 %addr) {
24 ; CHECK: slg {{%r[0-5]}}, 8(%r2)
25 ; CHECK: slbg {{%r[0-5]}}, 0(%r2)
27 %bptr = inttoptr i64 %addr to i128 *
28 %aptr = getelementptr i128 *%bptr, i64 -8
31 %sub = sub i128 %a, %b
32 store i128 %sub, i128 *%aptr
36 ; Test the highest aligned offset that is in range of both SLG and SLBG.
37 define void @f3(i64 %base) {
39 ; CHECK: slg {{%r[0-5]}}, 524280(%r2)
40 ; CHECK: slbg {{%r[0-5]}}, 524272(%r2)
42 %addr = add i64 %base, 524272
43 %bptr = inttoptr i64 %addr to i128 *
44 %aptr = getelementptr i128 *%bptr, i64 -8
47 %sub = sub i128 %a, %b
48 store i128 %sub, i128 *%aptr
52 ; Test the next doubleword up, which requires separate address logic for SLG.
53 define void @f4(i64 %base) {
55 ; CHECK: lgr [[BASE:%r[1-5]]], %r2
56 ; CHECK: agfi [[BASE]], 524288
57 ; CHECK: slg {{%r[0-5]}}, 0([[BASE]])
58 ; CHECK: slbg {{%r[0-5]}}, 524280(%r2)
60 %addr = add i64 %base, 524280
61 %bptr = inttoptr i64 %addr to i128 *
62 %aptr = getelementptr i128 *%bptr, i64 -8
65 %sub = sub i128 %a, %b
66 store i128 %sub, i128 *%aptr
70 ; Test the next doubleword after that, which requires separate logic for
71 ; both instructions. It would be better to create an anchor at 524288
72 ; that both instructions can use, but that isn't implemented yet.
73 define void @f5(i64 %base) {
75 ; CHECK: slg {{%r[0-5]}}, 0({{%r[1-5]}})
76 ; CHECK: slbg {{%r[0-5]}}, 0({{%r[1-5]}})
78 %addr = add i64 %base, 524288
79 %bptr = inttoptr i64 %addr to i128 *
80 %aptr = getelementptr i128 *%bptr, i64 -8
83 %sub = sub i128 %a, %b
84 store i128 %sub, i128 *%aptr
88 ; Test the lowest displacement that is in range of both SLG and SLBG.
89 define void @f6(i64 %base) {
91 ; CHECK: slg {{%r[0-5]}}, -524280(%r2)
92 ; CHECK: slbg {{%r[0-5]}}, -524288(%r2)
94 %addr = add i64 %base, -524288
95 %bptr = inttoptr i64 %addr to i128 *
96 %aptr = getelementptr i128 *%bptr, i64 -8
99 %sub = sub i128 %a, %b
100 store i128 %sub, i128 *%aptr
104 ; Test the next doubleword down, which is out of range of the SLBG.
105 define void @f7(i64 %base) {
107 ; CHECK: slg {{%r[0-5]}}, -524288(%r2)
108 ; CHECK: slbg {{%r[0-5]}}, 0({{%r[1-5]}})
110 %addr = add i64 %base, -524296
111 %bptr = inttoptr i64 %addr to i128 *
112 %aptr = getelementptr i128 *%bptr, i64 -8
113 %a = load i128 *%aptr
114 %b = load i128 *%bptr
115 %sub = sub i128 %a, %b
116 store i128 %sub, i128 *%aptr