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