166 lines · plain
1; Test signed high-part i64->i128 multiplications on z14.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 -asm-verbose=0 | FileCheck %s4 5declare i64 @foo()6 7; Check sign-extended multiplication in which only the high part is used.8define i64 @f1(i64 %dummy, i64 %a, i64 %b) {9; CHECK-LABEL: f1:10; CHECK-NOT: {{%r[234]}}11; CHECK: mgrk %r2, %r3, %r412; CHECK: br %r1413 %ax = sext i64 %a to i12814 %bx = sext i64 %b to i12815 %mulx = mul i128 %ax, %bx16 %highx = lshr i128 %mulx, 6417 %high = trunc i128 %highx to i6418 ret i64 %high19}20 21; Check sign-extended multiplication in which only part of the high half22; is used.23define i64 @f2(i64 %dummy, i64 %a, i64 %b) {24; CHECK-LABEL: f2:25; CHECK-NOT: {{%r[234]}}26; CHECK: mgrk [[REG:%r[0-9]+]], %r3, %r427; CHECK: srlg %r2, [[REG]], 328; CHECK: br %r1429 %ax = sext i64 %a to i12830 %bx = sext i64 %b to i12831 %mulx = mul i128 %ax, %bx32 %highx = lshr i128 %mulx, 6733 %high = trunc i128 %highx to i6434 ret i64 %high35}36 37; Check sign-extended multiplication in which the result is split into38; high and low halves.39define i64 @f3(i64 %dummy, i64 %a, i64 %b) {40; CHECK-LABEL: f3:41; CHECK-NOT: {{%r[234]}}42; CHECK: mgrk %r2, %r3, %r443; CHECK: ogr %r2, %r344; CHECK: br %r1445 %ax = sext i64 %a to i12846 %bx = sext i64 %b to i12847 %mulx = mul i128 %ax, %bx48 %highx = lshr i128 %mulx, 6449 %high = trunc i128 %highx to i6450 %low = trunc i128 %mulx to i6451 %or = or i64 %high, %low52 ret i64 %or53}54 55; Check MG with no displacement.56define i64 @f4(i64 %dummy, i64 %a, ptr %src) {57; CHECK-LABEL: f4:58; CHECK-NOT: {{%r[234]}}59; CHECK: mg %r2, 0(%r4)60; CHECK: br %r1461 %b = load i64, ptr %src62 %ax = sext i64 %a to i12863 %bx = sext i64 %b to i12864 %mulx = mul i128 %ax, %bx65 %highx = lshr i128 %mulx, 6466 %high = trunc i128 %highx to i6467 ret i64 %high68}69 70; Check the high end of the aligned MG range.71define i64 @f5(i64 %dummy, i64 %a, ptr %src) {72; CHECK-LABEL: f5:73; CHECK: mg %r2, 524280(%r4)74; CHECK: br %r1475 %ptr = getelementptr i64, ptr %src, i64 6553576 %b = load i64, ptr %ptr77 %ax = sext i64 %a to i12878 %bx = sext i64 %b to i12879 %mulx = mul i128 %ax, %bx80 %highx = lshr i128 %mulx, 6481 %high = trunc i128 %highx to i6482 ret i64 %high83}84 85; Check the next doubleword up, which requires separate address logic.86; Other sequences besides this one would be OK.87define i64 @f6(i64 %dummy, i64 %a, ptr %src) {88; CHECK-LABEL: f6:89; CHECK: agfi %r4, 52428890; CHECK: mg %r2, 0(%r4)91; CHECK: br %r1492 %ptr = getelementptr i64, ptr %src, i64 6553693 %b = load i64, ptr %ptr94 %ax = sext i64 %a to i12895 %bx = sext i64 %b to i12896 %mulx = mul i128 %ax, %bx97 %highx = lshr i128 %mulx, 6498 %high = trunc i128 %highx to i6499 ret i64 %high100}101 102; Check the high end of the negative aligned MG range.103define i64 @f7(i64 %dummy, i64 %a, ptr %src) {104; CHECK-LABEL: f7:105; CHECK: mg %r2, -8(%r4)106; CHECK: br %r14107 %ptr = getelementptr i64, ptr %src, i64 -1108 %b = load i64, ptr %ptr109 %ax = sext i64 %a to i128110 %bx = sext i64 %b to i128111 %mulx = mul i128 %ax, %bx112 %highx = lshr i128 %mulx, 64113 %high = trunc i128 %highx to i64114 ret i64 %high115}116 117; Check the low end of the MG range.118define i64 @f8(i64 %dummy, i64 %a, ptr %src) {119; CHECK-LABEL: f8:120; CHECK: mg %r2, -524288(%r4)121; CHECK: br %r14122 %ptr = getelementptr i64, ptr %src, i64 -65536123 %b = load i64, ptr %ptr124 %ax = sext i64 %a to i128125 %bx = sext i64 %b to i128126 %mulx = mul i128 %ax, %bx127 %highx = lshr i128 %mulx, 64128 %high = trunc i128 %highx to i64129 ret i64 %high130}131 132; Check the next doubleword down, which needs separate address logic.133; Other sequences besides this one would be OK.134define i64 @f9(ptr %dest, i64 %a, ptr %src) {135; CHECK-LABEL: f9:136; CHECK: agfi %r4, -524296137; CHECK: mg %r2, 0(%r4)138; CHECK: br %r14139 %ptr = getelementptr i64, ptr %src, i64 -65537140 %b = load i64, ptr %ptr141 %ax = sext i64 %a to i128142 %bx = sext i64 %b to i128143 %mulx = mul i128 %ax, %bx144 %highx = lshr i128 %mulx, 64145 %high = trunc i128 %highx to i64146 ret i64 %high147}148 149; Check that MG allows an index.150define i64 @f10(ptr %dest, i64 %a, i64 %src, i64 %index) {151; CHECK-LABEL: f10:152; CHECK: mg %r2, 524287(%r5,%r4)153; CHECK: br %r14154 %add1 = add i64 %src, %index155 %add2 = add i64 %add1, 524287156 %ptr = inttoptr i64 %add2 to ptr157 %b = load i64, ptr %ptr158 %ax = sext i64 %a to i128159 %bx = sext i64 %b to i128160 %mulx = mul i128 %ax, %bx161 %highx = lshr i128 %mulx, 64162 %high = trunc i128 %highx to i64163 ret i64 %high164}165 166