1 ; Testg 64-bit signed division and remainder. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5 declare i64 @foo() 6 7 ; Testg register division. The result is in the second of the two registers. 8 define void @f1(i64 %dummy, i64 %a, i64 %b, i64 *%dest) { 9 ; CHECK-LABEL: f1: 10 ; CHECK-NOT: {{%r[234]}} 11 ; CHECK: dsgr %r2, %r4 12 ; CHECK: stg %r3, 0(%r5) 13 ; CHECK: br %r14 14 %div = sdiv i64 %a, %b 15 store i64 %div, i64 *%dest 16 ret void 17 } 18 19 ; Testg register remainder. The result is in the first of the two registers. 20 define void @f2(i64 %dummy, i64 %a, i64 %b, i64 *%dest) { 21 ; CHECK-LABEL: f2: 22 ; CHECK-NOT: {{%r[234]}} 23 ; CHECK: dsgr %r2, %r4 24 ; CHECK: stg %r2, 0(%r5) 25 ; CHECK: br %r14 26 %rem = srem i64 %a, %b 27 store i64 %rem, i64 *%dest 28 ret void 29 } 30 31 ; Testg that division and remainder use a single instruction. 32 define i64 @f3(i64 %dummy1, i64 %a, i64 %b) { 33 ; CHECK-LABEL: f3: 34 ; CHECK-NOT: {{%r[234]}} 35 ; CHECK: dsgr %r2, %r4 36 ; CHECK-NOT: dsgr 37 ; CHECK: ogr %r2, %r3 38 ; CHECK: br %r14 39 %div = sdiv i64 %a, %b 40 %rem = srem i64 %a, %b 41 %or = or i64 %rem, %div 42 ret i64 %or 43 } 44 45 ; Testg memory division with no displacement. 46 define void @f4(i64 %dummy, i64 %a, i64 *%src, i64 *%dest) { 47 ; CHECK-LABEL: f4: 48 ; CHECK-NOT: {{%r[234]}} 49 ; CHECK: dsg %r2, 0(%r4) 50 ; CHECK: stg %r3, 0(%r5) 51 ; CHECK: br %r14 52 %b = load i64 *%src 53 %div = sdiv i64 %a, %b 54 store i64 %div, i64 *%dest 55 ret void 56 } 57 58 ; Testg memory remainder with no displacement. 59 define void @f5(i64 %dummy, i64 %a, i64 *%src, i64 *%dest) { 60 ; CHECK-LABEL: f5: 61 ; CHECK-NOT: {{%r[234]}} 62 ; CHECK: dsg %r2, 0(%r4) 63 ; CHECK: stg %r2, 0(%r5) 64 ; CHECK: br %r14 65 %b = load i64 *%src 66 %rem = srem i64 %a, %b 67 store i64 %rem, i64 *%dest 68 ret void 69 } 70 71 ; Testg both memory division and memory remainder. 72 define i64 @f6(i64 %dummy, i64 %a, i64 *%src) { 73 ; CHECK-LABEL: f6: 74 ; CHECK-NOT: {{%r[234]}} 75 ; CHECK: dsg %r2, 0(%r4) 76 ; CHECK-NOT: {{dsg|dsgr}} 77 ; CHECK: ogr %r2, %r3 78 ; CHECK: br %r14 79 %b = load i64 *%src 80 %div = sdiv i64 %a, %b 81 %rem = srem i64 %a, %b 82 %or = or i64 %rem, %div 83 ret i64 %or 84 } 85 86 ; Check the high end of the DSG range. 87 define i64 @f7(i64 %dummy, i64 %a, i64 *%src) { 88 ; CHECK-LABEL: f7: 89 ; CHECK: dsg %r2, 524280(%r4) 90 ; CHECK: br %r14 91 %ptr = getelementptr i64 *%src, i64 65535 92 %b = load i64 *%ptr 93 %rem = srem i64 %a, %b 94 ret i64 %rem 95 } 96 97 ; Check the next doubleword up, which needs separate address logic. 98 ; Other sequences besides this one would be OK. 99 define i64 @f8(i64 %dummy, i64 %a, i64 *%src) { 100 ; CHECK-LABEL: f8: 101 ; CHECK: agfi %r4, 524288 102 ; CHECK: dsg %r2, 0(%r4) 103 ; CHECK: br %r14 104 %ptr = getelementptr i64 *%src, i64 65536 105 %b = load i64 *%ptr 106 %rem = srem i64 %a, %b 107 ret i64 %rem 108 } 109 110 ; Check the high end of the negative aligned DSG range. 111 define i64 @f9(i64 %dummy, i64 %a, i64 *%src) { 112 ; CHECK-LABEL: f9: 113 ; CHECK: dsg %r2, -8(%r4) 114 ; CHECK: br %r14 115 %ptr = getelementptr i64 *%src, i64 -1 116 %b = load i64 *%ptr 117 %rem = srem i64 %a, %b 118 ret i64 %rem 119 } 120 121 ; Check the low end of the DSG range. 122 define i64 @f10(i64 %dummy, i64 %a, i64 *%src) { 123 ; CHECK-LABEL: f10: 124 ; CHECK: dsg %r2, -524288(%r4) 125 ; CHECK: br %r14 126 %ptr = getelementptr i64 *%src, i64 -65536 127 %b = load i64 *%ptr 128 %rem = srem i64 %a, %b 129 ret i64 %rem 130 } 131 132 ; Check the next doubleword down, which needs separate address logic. 133 ; Other sequences besides this one would be OK. 134 define i64 @f11(i64 %dummy, i64 %a, i64 *%src) { 135 ; CHECK-LABEL: f11: 136 ; CHECK: agfi %r4, -524296 137 ; CHECK: dsg %r2, 0(%r4) 138 ; CHECK: br %r14 139 %ptr = getelementptr i64 *%src, i64 -65537 140 %b = load i64 *%ptr 141 %rem = srem i64 %a, %b 142 ret i64 %rem 143 } 144 145 ; Check that DSG allows an index. 146 define i64 @f12(i64 %dummy, i64 %a, i64 %src, i64 %index) { 147 ; CHECK-LABEL: f12: 148 ; CHECK: dsg %r2, 524287(%r5,%r4) 149 ; CHECK: br %r14 150 %add1 = add i64 %src, %index 151 %add2 = add i64 %add1, 524287 152 %ptr = inttoptr i64 %add2 to i64 * 153 %b = load i64 *%ptr 154 %rem = srem i64 %a, %b 155 ret i64 %rem 156 } 157 158 ; Check that divisions of spilled values can use DSG rather than DSGR. 159 define i64 @f13(i64 *%ptr0) { 160 ; CHECK-LABEL: f13: 161 ; CHECK: brasl %r14, foo@PLT 162 ; CHECK: dsg {{%r[0-9]+}}, 160(%r15) 163 ; CHECK: br %r14 164 %ptr1 = getelementptr i64 *%ptr0, i64 2 165 %ptr2 = getelementptr i64 *%ptr0, i64 4 166 %ptr3 = getelementptr i64 *%ptr0, i64 6 167 %ptr4 = getelementptr i64 *%ptr0, i64 8 168 %ptr5 = getelementptr i64 *%ptr0, i64 10 169 %ptr6 = getelementptr i64 *%ptr0, i64 12 170 %ptr7 = getelementptr i64 *%ptr0, i64 14 171 %ptr8 = getelementptr i64 *%ptr0, i64 16 172 %ptr9 = getelementptr i64 *%ptr0, i64 18 173 %ptr10 = getelementptr i64 *%ptr0, i64 20 174 175 %val0 = load i64 *%ptr0 176 %val1 = load i64 *%ptr1 177 %val2 = load i64 *%ptr2 178 %val3 = load i64 *%ptr3 179 %val4 = load i64 *%ptr4 180 %val5 = load i64 *%ptr5 181 %val6 = load i64 *%ptr6 182 %val7 = load i64 *%ptr7 183 %val8 = load i64 *%ptr8 184 %val9 = load i64 *%ptr9 185 %val10 = load i64 *%ptr10 186 187 %ret = call i64 @foo() 188 189 %div0 = sdiv i64 %ret, %val0 190 %div1 = sdiv i64 %div0, %val1 191 %div2 = sdiv i64 %div1, %val2 192 %div3 = sdiv i64 %div2, %val3 193 %div4 = sdiv i64 %div3, %val4 194 %div5 = sdiv i64 %div4, %val5 195 %div6 = sdiv i64 %div5, %val6 196 %div7 = sdiv i64 %div6, %val7 197 %div8 = sdiv i64 %div7, %val8 198 %div9 = sdiv i64 %div8, %val9 199 %div10 = sdiv i64 %div9, %val10 200 201 ret i64 %div10 202 } 203