225 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 32; Test high-part i64->i128 multiplications on z13.3;4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s5 6; Check zero-extended multiplication in which only the high part is used.7define i64 @f1(i64 %dummy, i64 %a, i64 %b) {8; CHECK-LABEL: f1:9; CHECK: # %bb.0:10; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q11; CHECK-NEXT: mlgr %r2, %r412; CHECK-NEXT: # kill: def $r2d killed $r2d killed $r2q13; CHECK-NEXT: br %r1414 %ax = zext i64 %a to i12815 %bx = zext i64 %b to i12816 %mulx = mul i128 %ax, %bx17 %highx = lshr i128 %mulx, 6418 %high = trunc i128 %highx to i6419 ret i64 %high20}21 22; Check sign-extended multiplication in which only the high part is used.23; This needs a rather convoluted sequence.24define i64 @f2(i64 %dummy, i64 %a, i64 %b) {25; CHECK-LABEL: f2:26; CHECK: # %bb.0:27; CHECK-NEXT: srag %r1, %r4, 6328; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q29; CHECK-NEXT: srag %r0, %r3, 6330; CHECK-NEXT: ngr %r1, %r331; CHECK-NEXT: mlgr %r2, %r432; CHECK-NEXT: ngr %r0, %r433; CHECK-NEXT: agr %r0, %r134; CHECK-NEXT: sgr %r2, %r035; CHECK-NEXT: br %r1436 %ax = sext i64 %a to i12837 %bx = sext i64 %b to i12838 %mulx = mul i128 %ax, %bx39 %highx = lshr i128 %mulx, 6440 %high = trunc i128 %highx to i6441 ret i64 %high42}43 44; Check zero-extended multiplication in which only part of the high half45; is used.46define i64 @f3(i64 %dummy, i64 %a, i64 %b) {47; CHECK-LABEL: f3:48; CHECK: # %bb.0:49; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q50; CHECK-NEXT: mlgr %r2, %r451; CHECK-NEXT: srlg %r2, %r2, 352; CHECK-NEXT: br %r1453 %ax = zext i64 %a to i12854 %bx = zext i64 %b to i12855 %mulx = mul i128 %ax, %bx56 %highx = lshr i128 %mulx, 6757 %high = trunc i128 %highx to i6458 ret i64 %high59}60 61; Check zero-extended multiplication in which the result is split into62; high and low halves.63define i64 @f4(i64 %dummy, i64 %a, i64 %b) {64; CHECK-LABEL: f4:65; CHECK: # %bb.0:66; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q67; CHECK-NEXT: mlgr %r2, %r468; CHECK-NEXT: ogr %r2, %r369; CHECK-NEXT: br %r1470 %ax = zext i64 %a to i12871 %bx = zext i64 %b to i12872 %mulx = mul i128 %ax, %bx73 %highx = lshr i128 %mulx, 6474 %high = trunc i128 %highx to i6475 %low = trunc i128 %mulx to i6476 %or = or i64 %high, %low77 ret i64 %or78}79 80; Check division by a constant, which should use multiplication instead.81define i64 @f5(i64 %dummy, i64 %a) {82; CHECK-LABEL: f5:83; CHECK: # %bb.0:84; CHECK-NEXT: llihf %r0, 178202857085; CHECK-NEXT: oilf %r0, 59865022386; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q87; CHECK-NEXT: mlgr %r2, %r088; CHECK-NEXT: srlg %r2, %r2, 989; CHECK-NEXT: br %r1490 %res = udiv i64 %a, 123491 ret i64 %res92}93 94; Check MLG with no displacement.95define i64 @f6(i64 %dummy, i64 %a, ptr %src) {96; CHECK-LABEL: f6:97; CHECK: # %bb.0:98; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q99; CHECK-NEXT: mlg %r2, 0(%r4)100; CHECK-NEXT: # kill: def $r2d killed $r2d killed $r2q101; CHECK-NEXT: br %r14102 %b = load i64, ptr %src103 %ax = zext i64 %a to i128104 %bx = zext i64 %b to i128105 %mulx = mul i128 %ax, %bx106 %highx = lshr i128 %mulx, 64107 %high = trunc i128 %highx to i64108 ret i64 %high109}110 111; Check the high end of the aligned MLG range.112define i64 @f7(i64 %dummy, i64 %a, ptr %src) {113; CHECK-LABEL: f7:114; CHECK: # %bb.0:115; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q116; CHECK-NEXT: mlg %r2, 524280(%r4)117; CHECK-NEXT: # kill: def $r2d killed $r2d killed $r2q118; CHECK-NEXT: br %r14119 %ptr = getelementptr i64, ptr %src, i64 65535120 %b = load i64, ptr %ptr121 %ax = zext i64 %a to i128122 %bx = zext i64 %b to i128123 %mulx = mul i128 %ax, %bx124 %highx = lshr i128 %mulx, 64125 %high = trunc i128 %highx to i64126 ret i64 %high127}128 129; Check the next doubleword up, which requires separate address logic.130; Other sequences besides this one would be OK.131define i64 @f8(i64 %dummy, i64 %a, ptr %src) {132; CHECK-LABEL: f8:133; CHECK: # %bb.0:134; CHECK-NEXT: agfi %r4, 524288135; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q136; CHECK-NEXT: mlg %r2, 0(%r4)137; CHECK-NEXT: # kill: def $r2d killed $r2d killed $r2q138; CHECK-NEXT: br %r14139 %ptr = getelementptr i64, ptr %src, i64 65536140 %b = load i64, ptr %ptr141 %ax = zext i64 %a to i128142 %bx = zext 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 the high end of the negative aligned MLG range.150define i64 @f9(i64 %dummy, i64 %a, ptr %src) {151; CHECK-LABEL: f9:152; CHECK: # %bb.0:153; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q154; CHECK-NEXT: mlg %r2, -8(%r4)155; CHECK-NEXT: # kill: def $r2d killed $r2d killed $r2q156; CHECK-NEXT: br %r14157 %ptr = getelementptr i64, ptr %src, i64 -1158 %b = load i64, ptr %ptr159 %ax = zext i64 %a to i128160 %bx = zext i64 %b to i128161 %mulx = mul i128 %ax, %bx162 %highx = lshr i128 %mulx, 64163 %high = trunc i128 %highx to i64164 ret i64 %high165}166 167; Check the low end of the MLG range.168define i64 @f10(i64 %dummy, i64 %a, ptr %src) {169; CHECK-LABEL: f10:170; CHECK: # %bb.0:171; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q172; CHECK-NEXT: mlg %r2, -524288(%r4)173; CHECK-NEXT: # kill: def $r2d killed $r2d killed $r2q174; CHECK-NEXT: br %r14175 %ptr = getelementptr i64, ptr %src, i64 -65536176 %b = load i64, ptr %ptr177 %ax = zext i64 %a to i128178 %bx = zext i64 %b to i128179 %mulx = mul i128 %ax, %bx180 %highx = lshr i128 %mulx, 64181 %high = trunc i128 %highx to i64182 ret i64 %high183}184 185; Check the next doubleword down, which needs separate address logic.186; Other sequences besides this one would be OK.187define i64 @f11(ptr %dest, i64 %a, ptr %src) {188; CHECK-LABEL: f11:189; CHECK: # %bb.0:190; CHECK-NEXT: agfi %r4, -524296191; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q192; CHECK-NEXT: mlg %r2, 0(%r4)193; CHECK-NEXT: # kill: def $r2d killed $r2d killed $r2q194; CHECK-NEXT: br %r14195 %ptr = getelementptr i64, ptr %src, i64 -65537196 %b = load i64, ptr %ptr197 %ax = zext i64 %a to i128198 %bx = zext i64 %b to i128199 %mulx = mul i128 %ax, %bx200 %highx = lshr i128 %mulx, 64201 %high = trunc i128 %highx to i64202 ret i64 %high203}204 205; Check that MLG allows an index.206define i64 @f12(ptr %dest, i64 %a, i64 %src, i64 %index) {207; CHECK-LABEL: f12:208; CHECK: # %bb.0:209; CHECK-NEXT: # kill: def $r3d killed $r3d def $r2q210; CHECK-NEXT: mlg %r2, 524287(%r5,%r4)211; CHECK-NEXT: # kill: def $r2d killed $r2d killed $r2q212; CHECK-NEXT: br %r14213 %add1 = add i64 %src, %index214 %add2 = add i64 %add1, 524287215 %ptr = inttoptr i64 %add2 to ptr216 %b = load i64, ptr %ptr217 %ax = zext i64 %a to i128218 %bx = zext i64 %b to i128219 %mulx = mul i128 %ax, %bx220 %highx = lshr i128 %mulx, 64221 %high = trunc i128 %highx to i64222 ret i64 %high223}224 225