1 ; Test 128-bit addition in which the second operand is a zero-extended i32. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5 ; Check register additions. The XOR ensures that we don't instead zero-extend 6 ; %b into a register and use memory addition. 7 define void @f1(i128 *%aptr, i32 %b) { 8 ; CHECK-LABEL: f1: 9 ; CHECK: slgfr {{%r[0-5]}}, %r3 10 ; CHECK: slbgr 11 ; CHECK: br %r14 12 %a = load i128 *%aptr 13 %xor = xor i128 %a, 127 14 %bext = zext i32 %b to i128 15 %sub = sub i128 %xor, %bext 16 store i128 %sub, i128 *%aptr 17 ret void 18 } 19 20 ; Like f1, but using an "in-register" extension. 21 define void @f2(i128 *%aptr, i64 %b) { 22 ; CHECK-LABEL: f2: 23 ; CHECK: slgfr {{%r[0-5]}}, %r3 24 ; CHECK: slbgr 25 ; CHECK: br %r14 26 %a = load i128 *%aptr 27 %xor = xor i128 %a, 127 28 %trunc = trunc i64 %b to i32 29 %bext = zext i32 %trunc to i128 30 %sub = sub i128 %xor, %bext 31 store i128 %sub, i128 *%aptr 32 ret void 33 } 34 35 ; Test register addition in cases where the second operand is zero extended 36 ; from i64 rather than i32, but is later masked to i32 range. 37 define void @f3(i128 *%aptr, i64 %b) { 38 ; CHECK-LABEL: f3: 39 ; CHECK: slgfr {{%r[0-5]}}, %r3 40 ; CHECK: slbgr 41 ; CHECK: br %r14 42 %a = load i128 *%aptr 43 %xor = xor i128 %a, 127 44 %bext = zext i64 %b to i128 45 %and = and i128 %bext, 4294967295 46 %sub = sub i128 %xor, %and 47 store i128 %sub, i128 *%aptr 48 ret void 49 } 50 51 ; Test SLGF with no offset. 52 define void @f4(i128 *%aptr, i32 *%bsrc) { 53 ; CHECK-LABEL: f4: 54 ; CHECK: slgf {{%r[0-5]}}, 0(%r3) 55 ; CHECK: slbgr 56 ; CHECK: br %r14 57 %a = load i128 *%aptr 58 %xor = xor i128 %a, 127 59 %b = load i32 *%bsrc 60 %bext = zext i32 %b to i128 61 %sub = sub i128 %xor, %bext 62 store i128 %sub, i128 *%aptr 63 ret void 64 } 65 66 ; Check the high end of the SLGF range. 67 define void @f5(i128 *%aptr, i32 *%bsrc) { 68 ; CHECK-LABEL: f5: 69 ; CHECK: slgf {{%r[0-5]}}, 524284(%r3) 70 ; CHECK: slbgr 71 ; CHECK: br %r14 72 %a = load i128 *%aptr 73 %xor = xor i128 %a, 127 74 %ptr = getelementptr i32 *%bsrc, i64 131071 75 %b = load i32 *%ptr 76 %bext = zext i32 %b to i128 77 %sub = sub i128 %xor, %bext 78 store i128 %sub, i128 *%aptr 79 ret void 80 } 81 82 ; Check the next word up, which must use separate address logic. 83 ; Other sequences besides this one would be OK. 84 define void @f6(i128 *%aptr, i32 *%bsrc) { 85 ; CHECK-LABEL: f6: 86 ; CHECK: agfi %r3, 524288 87 ; CHECK: slgf {{%r[0-5]}}, 0(%r3) 88 ; CHECK: slbgr 89 ; CHECK: br %r14 90 %a = load i128 *%aptr 91 %xor = xor i128 %a, 127 92 %ptr = getelementptr i32 *%bsrc, i64 131072 93 %b = load i32 *%ptr 94 %bext = zext i32 %b to i128 95 %sub = sub i128 %xor, %bext 96 store i128 %sub, i128 *%aptr 97 ret void 98 } 99 100 ; Check the high end of the negative aligned SLGF range. 101 define void @f7(i128 *%aptr, i32 *%bsrc) { 102 ; CHECK-LABEL: f7: 103 ; CHECK: slgf {{%r[0-5]}}, -4(%r3) 104 ; CHECK: slbgr 105 ; CHECK: br %r14 106 %a = load i128 *%aptr 107 %xor = xor i128 %a, 127 108 %ptr = getelementptr i32 *%bsrc, i128 -1 109 %b = load i32 *%ptr 110 %bext = zext i32 %b to i128 111 %sub = sub i128 %xor, %bext 112 store i128 %sub, i128 *%aptr 113 ret void 114 } 115 116 ; Check the low end of the SLGF range. 117 define void @f8(i128 *%aptr, i32 *%bsrc) { 118 ; CHECK-LABEL: f8: 119 ; CHECK: slgf {{%r[0-5]}}, -524288(%r3) 120 ; CHECK: slbgr 121 ; CHECK: br %r14 122 %a = load i128 *%aptr 123 %xor = xor i128 %a, 127 124 %ptr = getelementptr i32 *%bsrc, i128 -131072 125 %b = load i32 *%ptr 126 %bext = zext i32 %b to i128 127 %sub = sub i128 %xor, %bext 128 store i128 %sub, i128 *%aptr 129 ret void 130 } 131 132 ; Check the next word down, which needs separate address logic. 133 ; Other sequences besides this one would be OK. 134 define void @f9(i128 *%aptr, i32 *%bsrc) { 135 ; CHECK-LABEL: f9: 136 ; CHECK: agfi %r3, -524292 137 ; CHECK: slgf {{%r[0-5]}}, 0(%r3) 138 ; CHECK: slbgr 139 ; CHECK: br %r14 140 %a = load i128 *%aptr 141 %xor = xor i128 %a, 127 142 %ptr = getelementptr i32 *%bsrc, i128 -131073 143 %b = load i32 *%ptr 144 %bext = zext i32 %b to i128 145 %sub = sub i128 %xor, %bext 146 store i128 %sub, i128 *%aptr 147 ret void 148 } 149 150 ; Check that SLGF allows an index. 151 define void @f10(i128 *%aptr, i64 %src, i64 %index) { 152 ; CHECK-LABEL: f10: 153 ; CHECK: slgf {{%r[0-5]}}, 524284({{%r4,%r3|%r3,%r4}}) 154 ; CHECK: br %r14 155 %a = load i128 *%aptr 156 %xor = xor i128 %a, 127 157 %add1 = add i64 %src, %index 158 %add2 = add i64 %add1, 524284 159 %ptr = inttoptr i64 %add2 to i32 * 160 %b = load i32 *%ptr 161 %bext = zext i32 %b to i128 162 %sub = sub i128 %xor, %bext 163 store i128 %sub, i128 *%aptr 164 ret void 165 } 166