1; Testg 64-bit signed division and remainder. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu -asm-verbose=0 | FileCheck %s 4 5declare i64 @foo() 6 7; Testg register division. The result is in the second of the two registers. 8define 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. 20define 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. 32define 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. 46define 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, 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. 59define 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, 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. 72define 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, 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. 87define 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, i64 *%src, i64 65535 92 %b = load i64, 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. 99define 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, i64 *%src, i64 65536 105 %b = load i64, 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. 111define 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, i64 *%src, i64 -1 116 %b = load i64, i64 *%ptr 117 %rem = srem i64 %a, %b 118 ret i64 %rem 119} 120 121; Check the low end of the DSG range. 122define 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, i64 *%src, i64 -65536 127 %b = load i64, 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. 134define 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, i64 *%src, i64 -65537 140 %b = load i64, i64 *%ptr 141 %rem = srem i64 %a, %b 142 ret i64 %rem 143} 144 145; Check that DSG allows an index. 146define 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, 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. 159define 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, i64 *%ptr0, i64 2 165 %ptr2 = getelementptr i64, i64 *%ptr0, i64 4 166 %ptr3 = getelementptr i64, i64 *%ptr0, i64 6 167 %ptr4 = getelementptr i64, i64 *%ptr0, i64 8 168 %ptr5 = getelementptr i64, i64 *%ptr0, i64 10 169 %ptr6 = getelementptr i64, i64 *%ptr0, i64 12 170 %ptr7 = getelementptr i64, i64 *%ptr0, i64 14 171 %ptr8 = getelementptr i64, i64 *%ptr0, i64 16 172 %ptr9 = getelementptr i64, i64 *%ptr0, i64 18 173 %ptr10 = getelementptr i64, i64 *%ptr0, i64 20 174 175 %val0 = load i64, i64 *%ptr0 176 %val1 = load i64, i64 *%ptr1 177 %val2 = load i64, i64 *%ptr2 178 %val3 = load i64, i64 *%ptr3 179 %val4 = load i64, i64 *%ptr4 180 %val5 = load i64, i64 *%ptr5 181 %val6 = load i64, i64 *%ptr6 182 %val7 = load i64, i64 *%ptr7 183 %val8 = load i64, i64 *%ptr8 184 %val9 = load i64, i64 *%ptr9 185 %val10 = load i64, 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