253 lines · plain
1; Test 32-bit signed division and remainder.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu -asm-verbose=0 | FileCheck %s4 5declare i32 @foo()6 7; Test register division. The result is in the second of the two registers.8define void @f1(ptr %dest, i32 %a, i32 %b) {9; CHECK-LABEL: f1:10; CHECK: lgfr %r1, %r311; CHECK: dsgfr %r0, %r412; CHECK: st %r1, 0(%r2)13; CHECK: br %r1414 %div = sdiv i32 %a, %b15 store i32 %div, ptr %dest16 ret void17}18 19; Test register remainder. The result is in the first of the two registers.20define void @f2(ptr %dest, i32 %a, i32 %b) {21; CHECK-LABEL: f2:22; CHECK: lgfr %r1, %r323; CHECK: dsgfr %r0, %r424; CHECK: st %r0, 0(%r2)25; CHECK: br %r1426 %rem = srem i32 %a, %b27 store i32 %rem, ptr %dest28 ret void29}30 31; Test that division and remainder use a single instruction.32define i32 @f3(i32 %dummy, i32 %a, i32 %b) {33; CHECK-LABEL: f3:34; CHECK-NOT: %r235; CHECK: lgfr %r3, %r336; CHECK-NOT: %r237; CHECK: dsgfr %r2, %r438; CHECK-NOT: dsgfr39; CHECK: or %r2, %r340; CHECK: br %r1441 %div = sdiv i32 %a, %b42 %rem = srem i32 %a, %b43 %or = or i32 %rem, %div44 ret i32 %or45}46 47; Check that the sign extension of the dividend is elided when the argument48; is already sign-extended.49define i32 @f4(i32 %dummy, i32 signext %a, i32 %b) {50; CHECK-LABEL: f4:51; CHECK-NOT: {{%r[234]}}52; CHECK: dsgfr %r2, %r453; CHECK-NOT: dsgfr54; CHECK: or %r3, %r255; CHECK: lr %r2, %r356; CHECK: br %r1457 %div = sdiv i32 %a, %b58 %rem = srem i32 %a, %b59 %or = or i32 %rem, %div60 ret i32 %or61}62 63; Test that memory dividends are loaded using sign extension (LGF).64define i32 @f5(i32 %dummy, ptr %src, i32 %b) {65; CHECK-LABEL: f5:66; CHECK-NOT: %r267; CHECK: lgf %r3, 0(%r3)68; CHECK-NOT: %r269; CHECK: dsgfr %r2, %r470; CHECK-NOT: dsgfr71; CHECK: or %r2, %r372; CHECK: br %r1473 %a = load i32, ptr %src74 %div = sdiv i32 %a, %b75 %rem = srem i32 %a, %b76 %or = or i32 %rem, %div77 ret i32 %or78}79 80; Test memory division with no displacement.81define void @f6(ptr %dest, i32 %a, ptr %src) {82; CHECK-LABEL: f6:83; CHECK: lgfr %r1, %r384; CHECK: dsgf %r0, 0(%r4)85; CHECK: st %r1, 0(%r2)86; CHECK: br %r1487 %b = load i32, ptr %src88 %div = sdiv i32 %a, %b89 store i32 %div, ptr %dest90 ret void91}92 93; Test memory remainder with no displacement.94define void @f7(ptr %dest, i32 %a, ptr %src) {95; CHECK-LABEL: f7:96; CHECK: lgfr %r1, %r397; CHECK: dsgf %r0, 0(%r4)98; CHECK: st %r0, 0(%r2)99; CHECK: br %r14100 %b = load i32, ptr %src101 %rem = srem i32 %a, %b102 store i32 %rem, ptr %dest103 ret void104}105 106; Test both memory division and memory remainder.107define i32 @f8(i32 %dummy, i32 %a, ptr %src) {108; CHECK-LABEL: f8:109; CHECK-NOT: %r2110; CHECK: lgfr %r3, %r3111; CHECK-NOT: %r2112; CHECK: dsgf %r2, 0(%r4)113; CHECK-NOT: {{dsgf|dsgfr}}114; CHECK: or %r2, %r3115; CHECK: br %r14116 %b = load i32, ptr %src117 %div = sdiv i32 %a, %b118 %rem = srem i32 %a, %b119 %or = or i32 %rem, %div120 ret i32 %or121}122 123; Check the high end of the DSGF range.124define i32 @f9(i32 %dummy, i32 %a, ptr %src) {125; CHECK-LABEL: f9:126; CHECK: dsgf %r2, 524284(%r4)127; CHECK: br %r14128 %ptr = getelementptr i32, ptr %src, i64 131071129 %b = load i32, ptr %ptr130 %rem = srem i32 %a, %b131 ret i32 %rem132}133 134; Check the next word up, which needs separate address logic.135; Other sequences besides this one would be OK.136define i32 @f10(i32 %dummy, i32 %a, ptr %src) {137; CHECK-LABEL: f10:138; CHECK: agfi %r4, 524288139; CHECK: dsgf %r2, 0(%r4)140; CHECK: br %r14141 %ptr = getelementptr i32, ptr %src, i64 131072142 %b = load i32, ptr %ptr143 %rem = srem i32 %a, %b144 ret i32 %rem145}146 147; Check the high end of the negative aligned DSGF range.148define i32 @f11(i32 %dummy, i32 %a, ptr %src) {149; CHECK-LABEL: f11:150; CHECK: dsgf %r2, -4(%r4)151; CHECK: br %r14152 %ptr = getelementptr i32, ptr %src, i64 -1153 %b = load i32, ptr %ptr154 %rem = srem i32 %a, %b155 ret i32 %rem156}157 158; Check the low end of the DSGF range.159define i32 @f12(i32 %dummy, i32 %a, ptr %src) {160; CHECK-LABEL: f12:161; CHECK: dsgf %r2, -524288(%r4)162; CHECK: br %r14163 %ptr = getelementptr i32, ptr %src, i64 -131072164 %b = load i32, ptr %ptr165 %rem = srem i32 %a, %b166 ret i32 %rem167}168 169; Check the next word down, which needs separate address logic.170; Other sequences besides this one would be OK.171define i32 @f13(i32 %dummy, i32 %a, ptr %src) {172; CHECK-LABEL: f13:173; CHECK: agfi %r4, -524292174; CHECK: dsgf %r2, 0(%r4)175; CHECK: br %r14176 %ptr = getelementptr i32, ptr %src, i64 -131073177 %b = load i32, ptr %ptr178 %rem = srem i32 %a, %b179 ret i32 %rem180}181 182; Check that DSGF allows an index.183define i32 @f14(i32 %dummy, i32 %a, i64 %src, i64 %index) {184; CHECK-LABEL: f14:185; CHECK: dsgf %r2, 524287(%r5,%r4)186; CHECK: br %r14187 %add1 = add i64 %src, %index188 %add2 = add i64 %add1, 524287189 %ptr = inttoptr i64 %add2 to ptr190 %b = load i32, ptr %ptr191 %rem = srem i32 %a, %b192 ret i32 %rem193}194 195; Make sure that we still use DSGFR rather than DSGR in cases where196; a load and division cannot be combined.197define void @f15(ptr %dest, ptr %src) {198; CHECK-LABEL: f15:199; CHECK: l [[B:%r[0-9]+]], 0(%r3)200; CHECK: brasl %r14, foo@PLT201; CHECK: lgfr %r1, %r2202; CHECK: dsgfr %r0, [[B]]203; CHECK: br %r14204 %b = load i32, ptr %src205 %a = call i32 @foo()206 %div = sdiv i32 %a, %b207 store i32 %div, ptr %dest208 ret void209}210 211; Check that divisions of spilled values can use DSGF rather than DSGFR.212define i32 @f16(ptr %ptr0) {213; CHECK-LABEL: f16:214; CHECK: brasl %r14, foo@PLT215; CHECK: dsgf {{%r[0-9]+}}, 16{{[04]}}(%r15)216; CHECK: br %r14217 %ptr1 = getelementptr i32, ptr %ptr0, i64 2218 %ptr2 = getelementptr i32, ptr %ptr0, i64 4219 %ptr3 = getelementptr i32, ptr %ptr0, i64 6220 %ptr4 = getelementptr i32, ptr %ptr0, i64 8221 %ptr5 = getelementptr i32, ptr %ptr0, i64 10222 %ptr6 = getelementptr i32, ptr %ptr0, i64 12223 %ptr7 = getelementptr i32, ptr %ptr0, i64 14224 %ptr8 = getelementptr i32, ptr %ptr0, i64 16225 %ptr9 = getelementptr i32, ptr %ptr0, i64 18226 227 %val0 = load i32, ptr %ptr0228 %val1 = load i32, ptr %ptr1229 %val2 = load i32, ptr %ptr2230 %val3 = load i32, ptr %ptr3231 %val4 = load i32, ptr %ptr4232 %val5 = load i32, ptr %ptr5233 %val6 = load i32, ptr %ptr6234 %val7 = load i32, ptr %ptr7235 %val8 = load i32, ptr %ptr8236 %val9 = load i32, ptr %ptr9237 238 %ret = call i32 @foo()239 240 %div0 = sdiv i32 %ret, %val0241 %div1 = sdiv i32 %div0, %val1242 %div2 = sdiv i32 %div1, %val2243 %div3 = sdiv i32 %div2, %val3244 %div4 = sdiv i32 %div3, %val4245 %div5 = sdiv i32 %div4, %val5246 %div6 = sdiv i32 %div5, %val6247 %div7 = sdiv i32 %div6, %val7248 %div8 = sdiv i32 %div7, %val8249 %div9 = sdiv i32 %div8, %val9250 251 ret i32 %div9252}253