1 ; Test 64-bit signed division and remainder when the divisor is 2 ; a signed-extended i32. 3 ; 4 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 5 6 declare i64 @foo() 7 8 ; Test register division. The result is in the second of the two registers. 9 define void @f1(i64 %dummy, i64 %a, i32 %b, i64 *%dest) { 10 ; CHECK-LABEL: f1: 11 ; CHECK-NOT: {{%r[234]}} 12 ; CHECK: dsgfr %r2, %r4 13 ; CHECK: stg %r3, 0(%r5) 14 ; CHECK: br %r14 15 %bext = sext i32 %b to i64 16 %div = sdiv i64 %a, %bext 17 store i64 %div, i64 *%dest 18 ret void 19 } 20 21 ; Test register remainder. The result is in the first of the two registers. 22 define void @f2(i64 %dummy, i64 %a, i32 %b, i64 *%dest) { 23 ; CHECK-LABEL: f2: 24 ; CHECK-NOT: {{%r[234]}} 25 ; CHECK: dsgfr %r2, %r4 26 ; CHECK: stg %r2, 0(%r5) 27 ; CHECK: br %r14 28 %bext = sext i32 %b to i64 29 %rem = srem i64 %a, %bext 30 store i64 %rem, i64 *%dest 31 ret void 32 } 33 34 ; Test that division and remainder use a single instruction. 35 define i64 @f3(i64 %dummy, i64 %a, i32 %b) { 36 ; CHECK-LABEL: f3: 37 ; CHECK-NOT: {{%r[234]}} 38 ; CHECK: dsgfr %r2, %r4 39 ; CHECK: ogr %r2, %r3 40 ; CHECK: br %r14 41 %bext = sext i32 %b to i64 42 %div = sdiv i64 %a, %bext 43 %rem = srem i64 %a, %bext 44 %or = or i64 %rem, %div 45 ret i64 %or 46 } 47 48 ; Test register division when the dividend is zero rather than sign extended. 49 ; We can't use dsgfr here 50 define void @f4(i64 %dummy, i64 %a, i32 %b, i64 *%dest) { 51 ; CHECK-LABEL: f4: 52 ; CHECK-NOT: dsgfr 53 ; CHECK: br %r14 54 %bext = zext i32 %b to i64 55 %div = sdiv i64 %a, %bext 56 store i64 %div, i64 *%dest 57 ret void 58 } 59 60 ; ...likewise remainder. 61 define void @f5(i64 %dummy, i64 %a, i32 %b, i64 *%dest) { 62 ; CHECK-LABEL: f5: 63 ; CHECK-NOT: dsgfr 64 ; CHECK: br %r14 65 %bext = zext i32 %b to i64 66 %rem = srem i64 %a, %bext 67 store i64 %rem, i64 *%dest 68 ret void 69 } 70 71 ; Test memory division with no displacement. 72 define void @f6(i64 %dummy, i64 %a, i32 *%src, i64 *%dest) { 73 ; CHECK-LABEL: f6: 74 ; CHECK-NOT: {{%r[234]}} 75 ; CHECK: dsgf %r2, 0(%r4) 76 ; CHECK: stg %r3, 0(%r5) 77 ; CHECK: br %r14 78 %b = load i32 *%src 79 %bext = sext i32 %b to i64 80 %div = sdiv i64 %a, %bext 81 store i64 %div, i64 *%dest 82 ret void 83 } 84 85 ; Test memory remainder with no displacement. 86 define void @f7(i64 %dummy, i64 %a, i32 *%src, i64 *%dest) { 87 ; CHECK-LABEL: f7: 88 ; CHECK-NOT: {{%r[234]}} 89 ; CHECK: dsgf %r2, 0(%r4) 90 ; CHECK: stg %r2, 0(%r5) 91 ; CHECK: br %r14 92 %b = load i32 *%src 93 %bext = sext i32 %b to i64 94 %rem = srem i64 %a, %bext 95 store i64 %rem, i64 *%dest 96 ret void 97 } 98 99 ; Test both memory division and memory remainder. 100 define i64 @f8(i64 %dummy, i64 %a, i32 *%src) { 101 ; CHECK-LABEL: f8: 102 ; CHECK-NOT: {{%r[234]}} 103 ; CHECK: dsgf %r2, 0(%r4) 104 ; CHECK-NOT: {{dsgf|dsgfr}} 105 ; CHECK: ogr %r2, %r3 106 ; CHECK: br %r14 107 %b = load i32 *%src 108 %bext = sext i32 %b to i64 109 %div = sdiv i64 %a, %bext 110 %rem = srem i64 %a, %bext 111 %or = or i64 %rem, %div 112 ret i64 %or 113 } 114 115 ; Check the high end of the DSGF range. 116 define i64 @f9(i64 %dummy, i64 %a, i32 *%src) { 117 ; CHECK-LABEL: f9: 118 ; CHECK: dsgf %r2, 524284(%r4) 119 ; CHECK: br %r14 120 %ptr = getelementptr i32 *%src, i64 131071 121 %b = load i32 *%ptr 122 %bext = sext i32 %b to i64 123 %rem = srem i64 %a, %bext 124 ret i64 %rem 125 } 126 127 ; Check the next word up, which needs separate address logic. 128 ; Other sequences besides this one would be OK. 129 define i64 @f10(i64 %dummy, i64 %a, i32 *%src) { 130 ; CHECK-LABEL: f10: 131 ; CHECK: agfi %r4, 524288 132 ; CHECK: dsgf %r2, 0(%r4) 133 ; CHECK: br %r14 134 %ptr = getelementptr i32 *%src, i64 131072 135 %b = load i32 *%ptr 136 %bext = sext i32 %b to i64 137 %rem = srem i64 %a, %bext 138 ret i64 %rem 139 } 140 141 ; Check the high end of the negative aligned DSGF range. 142 define i64 @f11(i64 %dummy, i64 %a, i32 *%src) { 143 ; CHECK-LABEL: f11: 144 ; CHECK: dsgf %r2, -4(%r4) 145 ; CHECK: br %r14 146 %ptr = getelementptr i32 *%src, i64 -1 147 %b = load i32 *%ptr 148 %bext = sext i32 %b to i64 149 %rem = srem i64 %a, %bext 150 ret i64 %rem 151 } 152 153 ; Check the low end of the DSGF range. 154 define i64 @f12(i64 %dummy, i64 %a, i32 *%src) { 155 ; CHECK-LABEL: f12: 156 ; CHECK: dsgf %r2, -524288(%r4) 157 ; CHECK: br %r14 158 %ptr = getelementptr i32 *%src, i64 -131072 159 %b = load i32 *%ptr 160 %bext = sext i32 %b to i64 161 %rem = srem i64 %a, %bext 162 ret i64 %rem 163 } 164 165 ; Check the next word down, which needs separate address logic. 166 ; Other sequences besides this one would be OK. 167 define i64 @f13(i64 %dummy, i64 %a, i32 *%src) { 168 ; CHECK-LABEL: f13: 169 ; CHECK: agfi %r4, -524292 170 ; CHECK: dsgf %r2, 0(%r4) 171 ; CHECK: br %r14 172 %ptr = getelementptr i32 *%src, i64 -131073 173 %b = load i32 *%ptr 174 %bext = sext i32 %b to i64 175 %rem = srem i64 %a, %bext 176 ret i64 %rem 177 } 178 179 ; Check that DSGF allows an index. 180 define i64 @f14(i64 %dummy, i64 %a, i64 %src, i64 %index) { 181 ; CHECK-LABEL: f14: 182 ; CHECK: dsgf %r2, 524287(%r5,%r4) 183 ; CHECK: br %r14 184 %add1 = add i64 %src, %index 185 %add2 = add i64 %add1, 524287 186 %ptr = inttoptr i64 %add2 to i32 * 187 %b = load i32 *%ptr 188 %bext = sext i32 %b to i64 189 %rem = srem i64 %a, %bext 190 ret i64 %rem 191 } 192 193 ; Make sure that we still use DSGFR rather than DSGR in cases where 194 ; a load and division cannot be combined. 195 define void @f15(i64 *%dest, i32 *%src) { 196 ; CHECK-LABEL: f15: 197 ; CHECK: l [[B:%r[0-9]+]], 0(%r3) 198 ; CHECK: brasl %r14, foo@PLT 199 ; CHECK: lgr %r1, %r2 200 ; CHECK: dsgfr %r0, [[B]] 201 ; CHECK: br %r14 202 %b = load i32 *%src 203 %a = call i64 @foo() 204 %ext = sext i32 %b to i64 205 %div = sdiv i64 %a, %ext 206 store i64 %div, i64 *%dest 207 ret void 208 } 209