; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s ; Test that basic 128-bit integer operations assemble as expected. target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown-wasm" declare i128 @llvm.ctlz.i128(i128, i1) declare i128 @llvm.cttz.i128(i128, i1) declare i128 @llvm.ctpop.i128(i128) ; CHECK-LABEL: add128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: i64.add ; CHECK: i64.store ; CHECK: i64.add ; CHECK: i64.store ; CHECK-NEXT: return{{$}} define i128 @add128(i128 %x, i128 %y) { %a = add i128 %x, %y ret i128 %a } ; CHECK-LABEL: sub128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: i64.sub ; CHECK: i64.store ; CHECK: i64.sub ; CHECK: i64.store ; CHECK-NEXT: return{{$}} define i128 @sub128(i128 %x, i128 %y) { %a = sub i128 %x, %y ret i128 %a } ; CHECK-LABEL: mul128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __multi3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @mul128(i128 %x, i128 %y) { %a = mul i128 %x, %y ret i128 %a } ; CHECK-LABEL: sdiv128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __divti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @sdiv128(i128 %x, i128 %y) { %a = sdiv i128 %x, %y ret i128 %a } ; CHECK-LABEL: udiv128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __udivti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @udiv128(i128 %x, i128 %y) { %a = udiv i128 %x, %y ret i128 %a } ; CHECK-LABEL: srem128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __modti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @srem128(i128 %x, i128 %y) { %a = srem i128 %x, %y ret i128 %a } ; CHECK-LABEL: urem128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __umodti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @urem128(i128 %x, i128 %y) { %a = urem i128 %x, %y ret i128 %a } ; CHECK-LABEL: and128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: i64.and ; CHECK: i64.store ; CHECK: i64.and ; CHECK: i64.store ; CHECK-NEXT: return{{$}} define i128 @and128(i128 %x, i128 %y) { %a = and i128 %x, %y ret i128 %a } ; CHECK-LABEL: or128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: i64.or ; CHECK: i64.store ; CHECK: i64.or ; CHECK: i64.store ; CHECK-NEXT: return{{$}} define i128 @or128(i128 %x, i128 %y) { %a = or i128 %x, %y ret i128 %a } ; CHECK-LABEL: xor128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: i64.xor ; CHECK: i64.store ; CHECK: i64.xor ; CHECK: i64.store ; CHECK-NEXT: return{{$}} define i128 @xor128(i128 %x, i128 %y) { %a = xor i128 %x, %y ret i128 %a } ; CHECK-LABEL: shl128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @shl128(i128 %x, i128 %y) { %a = shl i128 %x, %y ret i128 %a } ; CHECK-LABEL: shr128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @shr128(i128 %x, i128 %y) { %a = lshr i128 %x, %y ret i128 %a } ; CHECK-LABEL: sar128: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __ashrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @sar128(i128 %x, i128 %y) { %a = ashr i128 %x, %y ret i128 %a } ; CHECK-LABEL: clz128: ; CHECK-NEXT: .param i32, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: i64.clz ; CHECK: i64.clz ; CHECK: return{{$}} define i128 @clz128(i128 %x) { %a = call i128 @llvm.ctlz.i128(i128 %x, i1 false) ret i128 %a } ; CHECK-LABEL: clz128_zero_undef: ; CHECK-NEXT: .param i32, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: i64.clz ; CHECK: i64.clz ; CHECK: return{{$}} define i128 @clz128_zero_undef(i128 %x) { %a = call i128 @llvm.ctlz.i128(i128 %x, i1 true) ret i128 %a } ; CHECK-LABEL: ctz128: ; CHECK-NEXT: .param i32, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: i64.ctz ; CHECK: i64.ctz ; CHECK: return{{$}} define i128 @ctz128(i128 %x) { %a = call i128 @llvm.cttz.i128(i128 %x, i1 false) ret i128 %a } ; CHECK-LABEL: ctz128_zero_undef: ; CHECK-NEXT: .param i32, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: i64.ctz ; CHECK: i64.ctz ; CHECK: return{{$}} define i128 @ctz128_zero_undef(i128 %x) { %a = call i128 @llvm.cttz.i128(i128 %x, i1 true) ret i128 %a } ; CHECK-LABEL: popcnt128: ; CHECK-NEXT: .param i32, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: i64.popcnt ; CHECK: i64.popcnt ; CHECK: return{{$}} define i128 @popcnt128(i128 %x) { %a = call i128 @llvm.ctpop.i128(i128 %x) ret i128 %a } ; CHECK-LABEL: eqz128: ; CHECK-NEXT: .param i64, i64{{$}} ; CHECK-NEXT: .result i32{{$}} ; CHECK: i64.or ; CHECK: i64.eqz ; CHECK: return $ define i32 @eqz128(i128 %x) { %a = icmp eq i128 %x, 0 %b = zext i1 %a to i32 ret i32 %b } ; CHECK-LABEL: rotl: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @rotl(i128 %x, i128 %y) { %z = sub i128 128, %y %b = shl i128 %x, %y %c = lshr i128 %x, %z %d = or i128 %b, %c ret i128 %d } ; CHECK-LABEL: masked_rotl: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @masked_rotl(i128 %x, i128 %y) { %a = and i128 %y, 127 %z = sub i128 128, %a %b = shl i128 %x, %a %c = lshr i128 %x, %z %d = or i128 %b, %c ret i128 %d } ; CHECK-LABEL: rotr: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @rotr(i128 %x, i128 %y) { %z = sub i128 128, %y %b = lshr i128 %x, %y %c = shl i128 %x, %z %d = or i128 %b, %c ret i128 %d } ; CHECK-LABEL: masked_rotr: ; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}} ; CHECK-NOT: .result ; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}} ; CHECK: return{{$}} define i128 @masked_rotr(i128 %x, i128 %y) { %a = and i128 %y, 127 %z = sub i128 128, %a %b = lshr i128 %x, %a %c = shl i128 %x, %z %d = or i128 %b, %c ret i128 %d }