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