Home | History | Annotate | Download | only in SystemZ
      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 %s
      4 
      5 declare i64 @foo()
      6 
      7 ; Check sign-extended multiplication in which only the high part is used.
      8 define i64 @f1(i64 %dummy, i64 %a, i64 %b) {
      9 ; CHECK-LABEL: f1:
     10 ; CHECK-NOT: {{%r[234]}}
     11 ; CHECK: mgrk %r2, %r3, %r4
     12 ; CHECK: br %r14
     13   %ax = sext i64 %a to i128
     14   %bx = sext i64 %b to i128
     15   %mulx = mul i128 %ax, %bx
     16   %highx = lshr i128 %mulx, 64
     17   %high = trunc i128 %highx to i64
     18   ret i64 %high
     19 }
     20 
     21 ; Check sign-extended multiplication in which only part of the high half
     22 ; is used.
     23 define 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, %r4
     27 ; CHECK: srlg %r2, [[REG]], 3
     28 ; CHECK: br %r14
     29   %ax = sext i64 %a to i128
     30   %bx = sext i64 %b to i128
     31   %mulx = mul i128 %ax, %bx
     32   %highx = lshr i128 %mulx, 67
     33   %high = trunc i128 %highx to i64
     34   ret i64 %high
     35 }
     36 
     37 ; Check sign-extended multiplication in which the result is split into
     38 ; high and low halves.
     39 define i64 @f3(i64 %dummy, i64 %a, i64 %b) {
     40 ; CHECK-LABEL: f3:
     41 ; CHECK-NOT: {{%r[234]}}
     42 ; CHECK: mgrk %r2, %r3, %r4
     43 ; CHECK: ogr %r2, %r3
     44 ; CHECK: br %r14
     45   %ax = sext i64 %a to i128
     46   %bx = sext i64 %b to i128
     47   %mulx = mul i128 %ax, %bx
     48   %highx = lshr i128 %mulx, 64
     49   %high = trunc i128 %highx to i64
     50   %low = trunc i128 %mulx to i64
     51   %or = or i64 %high, %low
     52   ret i64 %or
     53 }
     54 
     55 ; Check MG with no displacement.
     56 define i64 @f4(i64 %dummy, i64 %a, i64 *%src) {
     57 ; CHECK-LABEL: f4:
     58 ; CHECK-NOT: {{%r[234]}}
     59 ; CHECK: mg %r2, 0(%r4)
     60 ; CHECK: br %r14
     61   %b = load i64, i64 *%src
     62   %ax = sext i64 %a to i128
     63   %bx = sext i64 %b to i128
     64   %mulx = mul i128 %ax, %bx
     65   %highx = lshr i128 %mulx, 64
     66   %high = trunc i128 %highx to i64
     67   ret i64 %high
     68 }
     69 
     70 ; Check the high end of the aligned MG range.
     71 define i64 @f5(i64 %dummy, i64 %a, i64 *%src) {
     72 ; CHECK-LABEL: f5:
     73 ; CHECK: mg %r2, 524280(%r4)
     74 ; CHECK: br %r14
     75   %ptr = getelementptr i64, i64 *%src, i64 65535
     76   %b = load i64, i64 *%ptr
     77   %ax = sext i64 %a to i128
     78   %bx = sext i64 %b to i128
     79   %mulx = mul i128 %ax, %bx
     80   %highx = lshr i128 %mulx, 64
     81   %high = trunc i128 %highx to i64
     82   ret i64 %high
     83 }
     84 
     85 ; Check the next doubleword up, which requires separate address logic.
     86 ; Other sequences besides this one would be OK.
     87 define i64 @f6(i64 %dummy, i64 %a, i64 *%src) {
     88 ; CHECK-LABEL: f6:
     89 ; CHECK: agfi %r4, 524288
     90 ; CHECK: mg %r2, 0(%r4)
     91 ; CHECK: br %r14
     92   %ptr = getelementptr i64, i64 *%src, i64 65536
     93   %b = load i64, i64 *%ptr
     94   %ax = sext i64 %a to i128
     95   %bx = sext i64 %b to i128
     96   %mulx = mul i128 %ax, %bx
     97   %highx = lshr i128 %mulx, 64
     98   %high = trunc i128 %highx to i64
     99   ret i64 %high
    100 }
    101 
    102 ; Check the high end of the negative aligned MG range.
    103 define i64 @f7(i64 %dummy, i64 %a, i64 *%src) {
    104 ; CHECK-LABEL: f7:
    105 ; CHECK: mg %r2, -8(%r4)
    106 ; CHECK: br %r14
    107   %ptr = getelementptr i64, i64 *%src, i64 -1
    108   %b = load i64, i64 *%ptr
    109   %ax = sext i64 %a to i128
    110   %bx = sext i64 %b to i128
    111   %mulx = mul i128 %ax, %bx
    112   %highx = lshr i128 %mulx, 64
    113   %high = trunc i128 %highx to i64
    114   ret i64 %high
    115 }
    116 
    117 ; Check the low end of the MG range.
    118 define i64 @f8(i64 %dummy, i64 %a, i64 *%src) {
    119 ; CHECK-LABEL: f8:
    120 ; CHECK: mg %r2, -524288(%r4)
    121 ; CHECK: br %r14
    122   %ptr = getelementptr i64, i64 *%src, i64 -65536
    123   %b = load i64, i64 *%ptr
    124   %ax = sext i64 %a to i128
    125   %bx = sext i64 %b to i128
    126   %mulx = mul i128 %ax, %bx
    127   %highx = lshr i128 %mulx, 64
    128   %high = trunc i128 %highx to i64
    129   ret i64 %high
    130 }
    131 
    132 ; Check the next doubleword down, which needs separate address logic.
    133 ; Other sequences besides this one would be OK.
    134 define i64 @f9(i64 *%dest, i64 %a, i64 *%src) {
    135 ; CHECK-LABEL: f9:
    136 ; CHECK: agfi %r4, -524296
    137 ; CHECK: mg %r2, 0(%r4)
    138 ; CHECK: br %r14
    139   %ptr = getelementptr i64, i64 *%src, i64 -65537
    140   %b = load i64, i64 *%ptr
    141   %ax = sext i64 %a to i128
    142   %bx = sext i64 %b to i128
    143   %mulx = mul i128 %ax, %bx
    144   %highx = lshr i128 %mulx, 64
    145   %high = trunc i128 %highx to i64
    146   ret i64 %high
    147 }
    148 
    149 ; Check that MG allows an index.
    150 define i64 @f10(i64 *%dest, i64 %a, i64 %src, i64 %index) {
    151 ; CHECK-LABEL: f10:
    152 ; CHECK: mg %r2, 524287(%r5,%r4)
    153 ; CHECK: br %r14
    154   %add1 = add i64 %src, %index
    155   %add2 = add i64 %add1, 524287
    156   %ptr = inttoptr i64 %add2 to i64 *
    157   %b = load i64, i64 *%ptr
    158   %ax = sext i64 %a to i128
    159   %bx = sext i64 %b to i128
    160   %mulx = mul i128 %ax, %bx
    161   %highx = lshr i128 %mulx, 64
    162   %high = trunc i128 %highx to i64
    163   ret i64 %high
    164 }
    165 
    166