211 lines · plain
1; Test 64-bit signed division and remainder when the divisor is2; a signed-extended i32.3;4; RUN: llc < %s -mtriple=s390x-linux-gnu -asm-verbose=0 | FileCheck %s5 6declare i64 @foo()7 8; Test register division. The result is in the second of the two registers.9define void @f1(i64 %dummy, i64 %a, i32 %b, ptr %dest) {10; CHECK-LABEL: f1:11; CHECK-NOT: {{%r[234]}}12; CHECK: dsgfr %r2, %r413; CHECK: stg %r3, 0(%r5)14; CHECK: br %r1415 %bext = sext i32 %b to i6416 %div = sdiv i64 %a, %bext17 store i64 %div, ptr %dest18 ret void19}20 21; Test register remainder. The result is in the first of the two registers.22define void @f2(i64 %dummy, i64 %a, i32 %b, ptr %dest) {23; CHECK-LABEL: f2:24; CHECK-NOT: {{%r[234]}}25; CHECK: dsgfr %r2, %r426; CHECK: stg %r2, 0(%r5)27; CHECK: br %r1428 %bext = sext i32 %b to i6429 %rem = srem i64 %a, %bext30 store i64 %rem, ptr %dest31 ret void32}33 34; Test that division and remainder use a single instruction.35define i64 @f3(i64 %dummy, i64 %a, i32 %b) {36; CHECK-LABEL: f3:37; CHECK-NOT: {{%r[234]}}38; CHECK: dsgfr %r2, %r439; CHECK: ogr %r3, %r240; CHECK: lgr %r2, %r341; CHECK: br %r1442 %bext = sext i32 %b to i6443 %div = sdiv i64 %a, %bext44 %rem = srem i64 %a, %bext45 %or = or i64 %rem, %div46 ret i64 %or47}48 49; Test register division when the dividend is zero rather than sign extended.50; We can't use dsgfr here51define void @f4(i64 %dummy, i64 %a, i32 %b, ptr %dest) {52; CHECK-LABEL: f4:53; CHECK-NOT: dsgfr54; CHECK: br %r1455 %bext = zext i32 %b to i6456 %div = sdiv i64 %a, %bext57 store i64 %div, ptr %dest58 ret void59}60 61; ...likewise remainder.62define void @f5(i64 %dummy, i64 %a, i32 %b, ptr %dest) {63; CHECK-LABEL: f5:64; CHECK-NOT: dsgfr65; CHECK: br %r1466 %bext = zext i32 %b to i6467 %rem = srem i64 %a, %bext68 store i64 %rem, ptr %dest69 ret void70}71 72; Test memory division with no displacement.73define void @f6(i64 %dummy, i64 %a, ptr %src, ptr %dest) {74; CHECK-LABEL: f6:75; CHECK-NOT: {{%r[234]}}76; CHECK: dsgf %r2, 0(%r4)77; CHECK: stg %r3, 0(%r5)78; CHECK: br %r1479 %b = load i32, ptr %src80 %bext = sext i32 %b to i6481 %div = sdiv i64 %a, %bext82 store i64 %div, ptr %dest83 ret void84}85 86; Test memory remainder with no displacement.87define void @f7(i64 %dummy, i64 %a, ptr %src, ptr %dest) {88; CHECK-LABEL: f7:89; CHECK-NOT: {{%r[234]}}90; CHECK: dsgf %r2, 0(%r4)91; CHECK: stg %r2, 0(%r5)92; CHECK: br %r1493 %b = load i32, ptr %src94 %bext = sext i32 %b to i6495 %rem = srem i64 %a, %bext96 store i64 %rem, ptr %dest97 ret void98}99 100; Test both memory division and memory remainder.101define i64 @f8(i64 %dummy, i64 %a, ptr %src) {102; CHECK-LABEL: f8:103; CHECK-NOT: {{%r[234]}}104; CHECK: dsgf %r2, 0(%r4)105; CHECK-NOT: {{dsgf|dsgfr}}106; CHECK: ogr %r3, %r2107; CHECK: lgr %r2, %r3108; CHECK: br %r14109 %b = load i32, ptr %src110 %bext = sext i32 %b to i64111 %div = sdiv i64 %a, %bext112 %rem = srem i64 %a, %bext113 %or = or i64 %rem, %div114 ret i64 %or115}116 117; Check the high end of the DSGF range.118define i64 @f9(i64 %dummy, i64 %a, ptr %src) {119; CHECK-LABEL: f9:120; CHECK: dsgf %r2, 524284(%r4)121; CHECK: br %r14122 %ptr = getelementptr i32, ptr %src, i64 131071123 %b = load i32, ptr %ptr124 %bext = sext i32 %b to i64125 %rem = srem i64 %a, %bext126 ret i64 %rem127}128 129; Check the next word up, which needs separate address logic.130; Other sequences besides this one would be OK.131define i64 @f10(i64 %dummy, i64 %a, ptr %src) {132; CHECK-LABEL: f10:133; CHECK: agfi %r4, 524288134; CHECK: dsgf %r2, 0(%r4)135; CHECK: br %r14136 %ptr = getelementptr i32, ptr %src, i64 131072137 %b = load i32, ptr %ptr138 %bext = sext i32 %b to i64139 %rem = srem i64 %a, %bext140 ret i64 %rem141}142 143; Check the high end of the negative aligned DSGF range.144define i64 @f11(i64 %dummy, i64 %a, ptr %src) {145; CHECK-LABEL: f11:146; CHECK: dsgf %r2, -4(%r4)147; CHECK: br %r14148 %ptr = getelementptr i32, ptr %src, i64 -1149 %b = load i32, ptr %ptr150 %bext = sext i32 %b to i64151 %rem = srem i64 %a, %bext152 ret i64 %rem153}154 155; Check the low end of the DSGF range.156define i64 @f12(i64 %dummy, i64 %a, ptr %src) {157; CHECK-LABEL: f12:158; CHECK: dsgf %r2, -524288(%r4)159; CHECK: br %r14160 %ptr = getelementptr i32, ptr %src, i64 -131072161 %b = load i32, ptr %ptr162 %bext = sext i32 %b to i64163 %rem = srem i64 %a, %bext164 ret i64 %rem165}166 167; Check the next word down, which needs separate address logic.168; Other sequences besides this one would be OK.169define i64 @f13(i64 %dummy, i64 %a, ptr %src) {170; CHECK-LABEL: f13:171; CHECK: agfi %r4, -524292172; CHECK: dsgf %r2, 0(%r4)173; CHECK: br %r14174 %ptr = getelementptr i32, ptr %src, i64 -131073175 %b = load i32, ptr %ptr176 %bext = sext i32 %b to i64177 %rem = srem i64 %a, %bext178 ret i64 %rem179}180 181; Check that DSGF allows an index.182define i64 @f14(i64 %dummy, i64 %a, i64 %src, i64 %index) {183; CHECK-LABEL: f14:184; CHECK: dsgf %r2, 524287(%r5,%r4)185; CHECK: br %r14186 %add1 = add i64 %src, %index187 %add2 = add i64 %add1, 524287188 %ptr = inttoptr i64 %add2 to ptr189 %b = load i32, ptr %ptr190 %bext = sext i32 %b to i64191 %rem = srem i64 %a, %bext192 ret i64 %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: lgr %r1, %r2202; CHECK: dsgfr %r0, [[B]]203; CHECK: br %r14204 %b = load i32, ptr %src205 %a = call i64 @foo()206 %ext = sext i32 %b to i64207 %div = sdiv i64 %a, %ext208 store i64 %div, ptr %dest209 ret void210}211