205 lines · plain
1; Testg 64-bit signed division and remainder.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu -asm-verbose=0 | FileCheck %s4 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, %r412; CHECK: stg %r3, 0(%r5)13; CHECK: br %r1414 %div = sdiv i64 %a, %b15 store i64 %div, ptr %dest16 ret void17}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, %r424; CHECK: stg %r2, 0(%r5)25; CHECK: br %r1426 %rem = srem i64 %a, %b27 store i64 %rem, ptr %dest28 ret void29}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, %r436; CHECK-NOT: dsgr37; CHECK: ogr %r3, %r238; CHECK: lgr %r2, %r339; CHECK: br %r1440 %div = sdiv i64 %a, %b41 %rem = srem i64 %a, %b42 %or = or i64 %rem, %div43 ret i64 %or44}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 %r1453 %b = load i64, ptr %src54 %div = sdiv i64 %a, %b55 store i64 %div, ptr %dest56 ret void57}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 %r1466 %b = load i64, ptr %src67 %rem = srem i64 %a, %b68 store i64 %rem, ptr %dest69 ret void70}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, %r279; CHECK: lgr %r2, %r380; CHECK: br %r1481 %b = load i64, ptr %src82 %div = sdiv i64 %a, %b83 %rem = srem i64 %a, %b84 %or = or i64 %rem, %div85 ret i64 %or86}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 %r1493 %ptr = getelementptr i64, ptr %src, i64 6553594 %b = load i64, ptr %ptr95 %rem = srem i64 %a, %b96 ret i64 %rem97}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, 524288104; CHECK: dsg %r2, 0(%r4)105; CHECK: br %r14106 %ptr = getelementptr i64, ptr %src, i64 65536107 %b = load i64, ptr %ptr108 %rem = srem i64 %a, %b109 ret i64 %rem110}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 %r14117 %ptr = getelementptr i64, ptr %src, i64 -1118 %b = load i64, ptr %ptr119 %rem = srem i64 %a, %b120 ret i64 %rem121}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 %r14128 %ptr = getelementptr i64, ptr %src, i64 -65536129 %b = load i64, ptr %ptr130 %rem = srem i64 %a, %b131 ret i64 %rem132}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, -524296139; CHECK: dsg %r2, 0(%r4)140; CHECK: br %r14141 %ptr = getelementptr i64, ptr %src, i64 -65537142 %b = load i64, ptr %ptr143 %rem = srem i64 %a, %b144 ret i64 %rem145}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 %r14152 %add1 = add i64 %src, %index153 %add2 = add i64 %add1, 524287154 %ptr = inttoptr i64 %add2 to ptr155 %b = load i64, ptr %ptr156 %rem = srem i64 %a, %b157 ret i64 %rem158}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@PLT164; CHECK: dsg {{%r[0-9]+}}, 160(%r15)165; CHECK: br %r14166 %ptr1 = getelementptr i64, ptr %ptr0, i64 2167 %ptr2 = getelementptr i64, ptr %ptr0, i64 4168 %ptr3 = getelementptr i64, ptr %ptr0, i64 6169 %ptr4 = getelementptr i64, ptr %ptr0, i64 8170 %ptr5 = getelementptr i64, ptr %ptr0, i64 10171 %ptr6 = getelementptr i64, ptr %ptr0, i64 12172 %ptr7 = getelementptr i64, ptr %ptr0, i64 14173 %ptr8 = getelementptr i64, ptr %ptr0, i64 16174 %ptr9 = getelementptr i64, ptr %ptr0, i64 18175 %ptr10 = getelementptr i64, ptr %ptr0, i64 20176 177 %val0 = load i64, ptr %ptr0178 %val1 = load i64, ptr %ptr1179 %val2 = load i64, ptr %ptr2180 %val3 = load i64, ptr %ptr3181 %val4 = load i64, ptr %ptr4182 %val5 = load i64, ptr %ptr5183 %val6 = load i64, ptr %ptr6184 %val7 = load i64, ptr %ptr7185 %val8 = load i64, ptr %ptr8186 %val9 = load i64, ptr %ptr9187 %val10 = load i64, ptr %ptr10188 189 %ret = call i64 @foo()190 191 %div0 = sdiv i64 %ret, %val0192 %div1 = sdiv i64 %div0, %val1193 %div2 = sdiv i64 %div1, %val2194 %div3 = sdiv i64 %div2, %val3195 %div4 = sdiv i64 %div3, %val4196 %div5 = sdiv i64 %div4, %val5197 %div6 = sdiv i64 %div5, %val6198 %div7 = sdiv i64 %div6, %val7199 %div8 = sdiv i64 %div7, %val8200 %div9 = sdiv i64 %div8, %val9201 %div10 = sdiv i64 %div9, %val10202 203 ret i64 %div10204}205