Home | History | Annotate | Download | only in WebAssembly
      1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
      2 
      3 ; Test that basic 128-bit integer operations assemble as expected.
      4 
      5 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
      6 target triple = "wasm32-unknown-unknown"
      7 
      8 declare i128 @llvm.ctlz.i128(i128, i1)
      9 declare i128 @llvm.cttz.i128(i128, i1)
     10 declare i128 @llvm.ctpop.i128(i128)
     11 
     12 ; CHECK-LABEL: add128:
     13 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
     14 ; CHECK-NOT:  .result
     15 ; CHECK:      i64.add
     16 ; CHECK:      i64.store
     17 ; CHECK:      i64.add
     18 ; CHECK:      i64.store
     19 ; CHECK-NEXT: return{{$}}
     20 define i128 @add128(i128 %x, i128 %y) {
     21   %a = add i128 %x, %y
     22   ret i128 %a
     23 }
     24 
     25 ; CHECK-LABEL: sub128:
     26 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
     27 ; CHECK-NOT: .result
     28 ; CHECK:      i64.sub
     29 ; CHECK:      i64.store
     30 ; CHECK:      i64.sub
     31 ; CHECK:      i64.store
     32 ; CHECK-NEXT: return{{$}}
     33 define i128 @sub128(i128 %x, i128 %y) {
     34   %a = sub i128 %x, %y
     35   ret i128 %a
     36 }
     37 
     38 ; CHECK-LABEL: mul128:
     39 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
     40 ; CHECK-NOT: .result
     41 ; CHECK: call __multi3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
     42 ; CHECK: return{{$}}
     43 define i128 @mul128(i128 %x, i128 %y) {
     44   %a = mul i128 %x, %y
     45   ret i128 %a
     46 }
     47 
     48 ; CHECK-LABEL: sdiv128:
     49 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
     50 ; CHECK-NOT: .result
     51 ; CHECK: call __divti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
     52 ; CHECK: return{{$}}
     53 define i128 @sdiv128(i128 %x, i128 %y) {
     54   %a = sdiv i128 %x, %y
     55   ret i128 %a
     56 }
     57 
     58 ; CHECK-LABEL: udiv128:
     59 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
     60 ; CHECK-NOT: .result
     61 ; CHECK: call __udivti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
     62 ; CHECK: return{{$}}
     63 define i128 @udiv128(i128 %x, i128 %y) {
     64   %a = udiv i128 %x, %y
     65   ret i128 %a
     66 }
     67 
     68 ; CHECK-LABEL: srem128:
     69 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
     70 ; CHECK-NOT: .result
     71 ; CHECK: call __modti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
     72 ; CHECK: return{{$}}
     73 define i128 @srem128(i128 %x, i128 %y) {
     74   %a = srem i128 %x, %y
     75   ret i128 %a
     76 }
     77 
     78 ; CHECK-LABEL: urem128:
     79 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
     80 ; CHECK-NOT: .result
     81 ; CHECK: call __umodti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
     82 ; CHECK: return{{$}}
     83 define i128 @urem128(i128 %x, i128 %y) {
     84   %a = urem i128 %x, %y
     85   ret i128 %a
     86 }
     87 
     88 ; CHECK-LABEL: and128:
     89 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
     90 ; CHECK-NOT:  .result
     91 ; CHECK:      i64.and
     92 ; CHECK:      i64.store
     93 ; CHECK:      i64.and
     94 ; CHECK:      i64.store
     95 ; CHECK-NEXT: return{{$}}
     96 define i128 @and128(i128 %x, i128 %y) {
     97   %a = and i128 %x, %y
     98   ret i128 %a
     99 }
    100 
    101 ; CHECK-LABEL: or128:
    102 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
    103 ; CHECK-NOT: .result
    104 ; CHECK:      i64.or
    105 ; CHECK:      i64.store
    106 ; CHECK:      i64.or
    107 ; CHECK:      i64.store
    108 ; CHECK-NEXT: return{{$}}
    109 define i128 @or128(i128 %x, i128 %y) {
    110   %a = or i128 %x, %y
    111   ret i128 %a
    112 }
    113 
    114 ; CHECK-LABEL: xor128:
    115 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
    116 ; CHECK-NOT: .result
    117 ; CHECK:      i64.xor
    118 ; CHECK:      i64.store
    119 ; CHECK:      i64.xor
    120 ; CHECK:      i64.store
    121 ; CHECK-NEXT: return{{$}}
    122 define i128 @xor128(i128 %x, i128 %y) {
    123   %a = xor i128 %x, %y
    124   ret i128 %a
    125 }
    126 
    127 ; CHECK-LABEL: shl128:
    128 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
    129 ; CHECK-NOT: .result
    130 ; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    131 ; CHECK: return{{$}}
    132 define i128 @shl128(i128 %x, i128 %y) {
    133   %a = shl i128 %x, %y
    134   ret i128 %a
    135 }
    136 
    137 ; CHECK-LABEL: shr128:
    138 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
    139 ; CHECK-NOT: .result
    140 ; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    141 ; CHECK: return{{$}}
    142 define i128 @shr128(i128 %x, i128 %y) {
    143   %a = lshr i128 %x, %y
    144   ret i128 %a
    145 }
    146 
    147 ; CHECK-LABEL: sar128:
    148 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
    149 ; CHECK-NOT: .result
    150 ; CHECK: call __ashrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    151 ; CHECK: return{{$}}
    152 define i128 @sar128(i128 %x, i128 %y) {
    153   %a = ashr i128 %x, %y
    154   ret i128 %a
    155 }
    156 
    157 ; CHECK-LABEL: clz128:
    158 ; CHECK-NEXT: .param i32, i64, i64{{$}}
    159 ; CHECK-NOT:  .result
    160 ; CHECK:      i64.clz
    161 ; CHECK:      i64.clz
    162 ; CHECK:      return{{$}}
    163 define i128 @clz128(i128 %x) {
    164   %a = call i128 @llvm.ctlz.i128(i128 %x, i1 false)
    165   ret i128 %a
    166 }
    167 
    168 ; CHECK-LABEL: clz128_zero_undef:
    169 ; CHECK-NEXT: .param i32, i64, i64{{$}}
    170 ; CHECK-NOT: .result
    171 ; CHECK:      i64.clz
    172 ; CHECK:      i64.clz
    173 ; CHECK:      return{{$}}
    174 define i128 @clz128_zero_undef(i128 %x) {
    175   %a = call i128 @llvm.ctlz.i128(i128 %x, i1 true)
    176   ret i128 %a
    177 }
    178 
    179 ; CHECK-LABEL: ctz128:
    180 ; CHECK-NEXT: .param i32, i64, i64{{$}}
    181 ; CHECK-NOT: .result
    182 ; CHECK:      i64.ctz
    183 ; CHECK:      i64.ctz
    184 ; CHECK:      return{{$}}
    185 define i128 @ctz128(i128 %x) {
    186   %a = call i128 @llvm.cttz.i128(i128 %x, i1 false)
    187   ret i128 %a
    188 }
    189 
    190 ; CHECK-LABEL: ctz128_zero_undef:
    191 ; CHECK-NEXT: .param i32, i64, i64{{$}}
    192 ; CHECK-NOT: .result
    193 ; CHECK:      i64.ctz
    194 ; CHECK:      i64.ctz
    195 ; CHECK:      return{{$}}
    196 define i128 @ctz128_zero_undef(i128 %x) {
    197   %a = call i128 @llvm.cttz.i128(i128 %x, i1 true)
    198   ret i128 %a
    199 }
    200 
    201 ; CHECK-LABEL: popcnt128:
    202 ; CHECK-NEXT: .param i32, i64, i64{{$}}
    203 ; CHECK-NOT: .result
    204 ; CHECK:      i64.popcnt
    205 ; CHECK:      i64.popcnt
    206 ; CHECK:      return{{$}}
    207 define i128 @popcnt128(i128 %x) {
    208   %a = call i128 @llvm.ctpop.i128(i128 %x)
    209   ret i128 %a
    210 }
    211 
    212 ; CHECK-LABEL: eqz128:
    213 ; CHECK-NEXT: .param i64, i64{{$}}
    214 ; CHECK-NEXT: .result i32{{$}}
    215 ; CHECK:     i64.or
    216 ; CHECK:     i64.eqz
    217 ; CHECK:     return $
    218 define i32 @eqz128(i128 %x) {
    219   %a = icmp eq i128 %x, 0
    220   %b = zext i1 %a to i32
    221   ret i32 %b
    222 }
    223 
    224 ; CHECK-LABEL: rotl:
    225 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
    226 ; CHECK-NOT: .result
    227 ; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    228 ; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    229 ; CHECK: return{{$}}
    230 define i128 @rotl(i128 %x, i128 %y) {
    231   %z = sub i128 128, %y
    232   %b = shl i128 %x, %y
    233   %c = lshr i128 %x, %z
    234   %d = or i128 %b, %c
    235   ret i128 %d
    236 }
    237 
    238 ; CHECK-LABEL: masked_rotl:
    239 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
    240 ; CHECK-NOT: .result
    241 ; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    242 ; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    243 ; CHECK: return{{$}}
    244 define i128 @masked_rotl(i128 %x, i128 %y) {
    245   %a = and i128 %y, 127
    246   %z = sub i128 128, %a
    247   %b = shl i128 %x, %a
    248   %c = lshr i128 %x, %z
    249   %d = or i128 %b, %c
    250   ret i128 %d
    251 }
    252 
    253 ; CHECK-LABEL: rotr:
    254 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
    255 ; CHECK-NOT: .result
    256 ; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    257 ; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    258 ; CHECK: return{{$}}
    259 define i128 @rotr(i128 %x, i128 %y) {
    260   %z = sub i128 128, %y
    261   %b = lshr i128 %x, %y
    262   %c = shl i128 %x, %z
    263   %d = or i128 %b, %c
    264   ret i128 %d
    265 }
    266 
    267 ; CHECK-LABEL: masked_rotr:
    268 ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
    269 ; CHECK-NOT: .result
    270 ; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    271 ; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
    272 ; CHECK: return{{$}}
    273 define i128 @masked_rotr(i128 %x, i128 %y) {
    274   %a = and i128 %y, 127
    275   %z = sub i128 128, %a
    276   %b = lshr i128 %x, %a
    277   %c = shl i128 %x, %z
    278   %d = or i128 %b, %c
    279   ret i128 %d
    280 }
    281