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