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