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 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: .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{{$}} 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: .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{{$}} 33define 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{{$}} 43define 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{{$}} 53define 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{{$}} 63define 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{{$}} 73define 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{{$}} 83define 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{{$}} 96define 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{{$}} 109define 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{{$}} 122define 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{{$}} 132define 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{{$}} 142define 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{{$}} 152define 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{{$}} 163define 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{{$}} 174define 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{{$}} 185define 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{{$}} 196define 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{{$}} 207define 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 $ 218define 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{{$}} 230define 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{{$}} 244define 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{{$}} 259define 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{{$}} 273define 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