1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s 2 3; Test that basic 64-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 i64 @llvm.ctlz.i64(i64, i1) 9declare i64 @llvm.cttz.i64(i64, i1) 10declare i64 @llvm.ctpop.i64(i64) 11 12; CHECK-LABEL: add64: 13; CHECK-NEXT: .functype add64 (i64, i64) -> (i64){{$}} 14; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 15; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 16; CHECK-NEXT: i64.add $push0=, $pop[[L0]], $pop[[L1]]{{$}} 17; CHECK-NEXT: return $pop0{{$}} 18define i64 @add64(i64 %x, i64 %y) { 19 %a = add i64 %x, %y 20 ret i64 %a 21} 22 23; CHECK-LABEL: sub64: 24; CHECK-NEXT: .functype sub64 (i64, i64) -> (i64){{$}} 25; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 26; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 27; CHECK-NEXT: i64.sub $push0=, $pop[[L0]], $pop[[L1]]{{$}} 28; CHECK-NEXT: return $pop0{{$}} 29define i64 @sub64(i64 %x, i64 %y) { 30 %a = sub i64 %x, %y 31 ret i64 %a 32} 33 34; CHECK-LABEL: mul64: 35; CHECK-NEXT: .functype mul64 (i64, i64) -> (i64){{$}} 36; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 37; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 38; CHECK-NEXT: i64.mul $push0=, $pop[[L0]], $pop[[L1]]{{$}} 39; CHECK-NEXT: return $pop0{{$}} 40define i64 @mul64(i64 %x, i64 %y) { 41 %a = mul i64 %x, %y 42 ret i64 %a 43} 44 45; CHECK-LABEL: sdiv64: 46; CHECK-NEXT: .functype sdiv64 (i64, i64) -> (i64){{$}} 47; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 48; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 49; CHECK-NEXT: i64.div_s $push0=, $pop[[L0]], $pop[[L1]]{{$}} 50; CHECK-NEXT: return $pop0{{$}} 51define i64 @sdiv64(i64 %x, i64 %y) { 52 %a = sdiv i64 %x, %y 53 ret i64 %a 54} 55 56; CHECK-LABEL: udiv64: 57; CHECK-NEXT: .functype udiv64 (i64, i64) -> (i64){{$}} 58; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 59; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 60; CHECK-NEXT: i64.div_u $push0=, $pop[[L0]], $pop[[L1]]{{$}} 61; CHECK-NEXT: return $pop0{{$}} 62define i64 @udiv64(i64 %x, i64 %y) { 63 %a = udiv i64 %x, %y 64 ret i64 %a 65} 66 67; CHECK-LABEL: srem64: 68; CHECK-NEXT: .functype srem64 (i64, i64) -> (i64){{$}} 69; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 70; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 71; CHECK-NEXT: i64.rem_s $push0=, $pop[[L0]], $pop[[L1]]{{$}} 72; CHECK-NEXT: return $pop0{{$}} 73define i64 @srem64(i64 %x, i64 %y) { 74 %a = srem i64 %x, %y 75 ret i64 %a 76} 77 78; CHECK-LABEL: urem64: 79; CHECK-NEXT: .functype urem64 (i64, i64) -> (i64){{$}} 80; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 81; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 82; CHECK-NEXT: i64.rem_u $push0=, $pop[[L0]], $pop[[L1]]{{$}} 83; CHECK-NEXT: return $pop0{{$}} 84define i64 @urem64(i64 %x, i64 %y) { 85 %a = urem i64 %x, %y 86 ret i64 %a 87} 88 89; CHECK-LABEL: and64: 90; CHECK-NEXT: .functype and64 (i64, i64) -> (i64){{$}} 91; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 92; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 93; CHECK-NEXT: i64.and $push0=, $pop[[L0]], $pop[[L1]]{{$}} 94; CHECK-NEXT: return $pop0{{$}} 95define i64 @and64(i64 %x, i64 %y) { 96 %a = and i64 %x, %y 97 ret i64 %a 98} 99 100; CHECK-LABEL: or64: 101; CHECK-NEXT: .functype or64 (i64, i64) -> (i64){{$}} 102; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 103; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 104; CHECK-NEXT: i64.or $push0=, $pop[[L0]], $pop[[L1]]{{$}} 105; CHECK-NEXT: return $pop0{{$}} 106define i64 @or64(i64 %x, i64 %y) { 107 %a = or i64 %x, %y 108 ret i64 %a 109} 110 111; CHECK-LABEL: xor64: 112; CHECK-NEXT: .functype xor64 (i64, i64) -> (i64){{$}} 113; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 114; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 115; CHECK-NEXT: i64.xor $push0=, $pop[[L0]], $pop[[L1]]{{$}} 116; CHECK-NEXT: return $pop0{{$}} 117define i64 @xor64(i64 %x, i64 %y) { 118 %a = xor i64 %x, %y 119 ret i64 %a 120} 121 122; CHECK-LABEL: shl64: 123; CHECK-NEXT: .functype shl64 (i64, i64) -> (i64){{$}} 124; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 125; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 126; CHECK-NEXT: i64.shl $push0=, $pop[[L0]], $pop[[L1]]{{$}} 127; CHECK-NEXT: return $pop0{{$}} 128define i64 @shl64(i64 %x, i64 %y) { 129 %a = shl i64 %x, %y 130 ret i64 %a 131} 132 133; CHECK-LABEL: shr64: 134; CHECK-NEXT: .functype shr64 (i64, i64) -> (i64){{$}} 135; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 136; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 137; CHECK-NEXT: i64.shr_u $push0=, $pop[[L0]], $pop[[L1]]{{$}} 138; CHECK-NEXT: return $pop0{{$}} 139define i64 @shr64(i64 %x, i64 %y) { 140 %a = lshr i64 %x, %y 141 ret i64 %a 142} 143 144; CHECK-LABEL: sar64: 145; CHECK-NEXT: .functype sar64 (i64, i64) -> (i64){{$}} 146; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 147; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 148; CHECK-NEXT: i64.shr_s $push0=, $pop[[L0]], $pop[[L1]]{{$}} 149; CHECK-NEXT: return $pop0{{$}} 150define i64 @sar64(i64 %x, i64 %y) { 151 %a = ashr i64 %x, %y 152 ret i64 %a 153} 154 155; CHECK-LABEL: clz64: 156; CHECK-NEXT: .functype clz64 (i64) -> (i64){{$}} 157; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 158; CHECK-NEXT: i64.clz $push0=, $pop[[L0]]{{$}} 159; CHECK-NEXT: return $pop0{{$}} 160define i64 @clz64(i64 %x) { 161 %a = call i64 @llvm.ctlz.i64(i64 %x, i1 false) 162 ret i64 %a 163} 164 165; CHECK-LABEL: clz64_zero_undef: 166; CHECK-NEXT: .functype clz64_zero_undef (i64) -> (i64){{$}} 167; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 168; CHECK-NEXT: i64.clz $push0=, $pop[[L0]]{{$}} 169; CHECK-NEXT: return $pop0{{$}} 170define i64 @clz64_zero_undef(i64 %x) { 171 %a = call i64 @llvm.ctlz.i64(i64 %x, i1 true) 172 ret i64 %a 173} 174 175; CHECK-LABEL: ctz64: 176; CHECK-NEXT: .functype ctz64 (i64) -> (i64){{$}} 177; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 178; CHECK-NEXT: i64.ctz $push0=, $pop[[L0]]{{$}} 179; CHECK-NEXT: return $pop0{{$}} 180define i64 @ctz64(i64 %x) { 181 %a = call i64 @llvm.cttz.i64(i64 %x, i1 false) 182 ret i64 %a 183} 184 185; CHECK-LABEL: ctz64_zero_undef: 186; CHECK-NEXT: .functype ctz64_zero_undef (i64) -> (i64){{$}} 187; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 188; CHECK-NEXT: i64.ctz $push0=, $pop[[L0]]{{$}} 189; CHECK-NEXT: return $pop0{{$}} 190define i64 @ctz64_zero_undef(i64 %x) { 191 %a = call i64 @llvm.cttz.i64(i64 %x, i1 true) 192 ret i64 %a 193} 194 195; CHECK-LABEL: popcnt64: 196; CHECK-NEXT: .functype popcnt64 (i64) -> (i64){{$}} 197; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 198; CHECK-NEXT: i64.popcnt $push0=, $pop[[L0]]{{$}} 199; CHECK-NEXT: return $pop0{{$}} 200define i64 @popcnt64(i64 %x) { 201 %a = call i64 @llvm.ctpop.i64(i64 %x) 202 ret i64 %a 203} 204 205; CHECK-LABEL: eqz64: 206; CHECK-NEXT: .functype eqz64 (i64) -> (i32){{$}} 207; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 208; CHECK-NEXT: i64.eqz $push0=, $pop[[L0]]{{$}} 209; CHECK-NEXT: return $pop0{{$}} 210define i32 @eqz64(i64 %x) { 211 %a = icmp eq i64 %x, 0 212 %b = zext i1 %a to i32 213 ret i32 %b 214} 215 216; CHECK-LABEL: rotl: 217; CHECK-NEXT: .functype rotl (i64, i64) -> (i64){{$}} 218; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 219; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 220; CHECK-NEXT: i64.rotl $push0=, $pop[[L0]], $pop[[L1]] 221; CHECK-NEXT: return $pop0{{$}} 222define i64 @rotl(i64 %x, i64 %y) { 223 %z = sub i64 64, %y 224 %b = shl i64 %x, %y 225 %c = lshr i64 %x, %z 226 %d = or i64 %b, %c 227 ret i64 %d 228} 229 230; CHECK-LABEL: masked_rotl: 231; CHECK-NEXT: .functype masked_rotl (i64, i64) -> (i64){{$}} 232; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 233; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 234; CHECK-NEXT: i64.rotl $push0=, $pop[[L0]], $pop[[L1]] 235; CHECK-NEXT: return $pop0{{$}} 236define i64 @masked_rotl(i64 %x, i64 %y) { 237 %a = and i64 %y, 63 238 %z = sub i64 64, %a 239 %b = shl i64 %x, %a 240 %c = lshr i64 %x, %z 241 %d = or i64 %b, %c 242 ret i64 %d 243} 244 245; CHECK-LABEL: rotr: 246; CHECK-NEXT: .functype rotr (i64, i64) -> (i64){{$}} 247; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 248; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 249; CHECK-NEXT: i64.rotr $push0=, $pop[[L0]], $pop[[L1]] 250; CHECK-NEXT: return $pop0{{$}} 251define i64 @rotr(i64 %x, i64 %y) { 252 %z = sub i64 64, %y 253 %b = lshr i64 %x, %y 254 %c = shl i64 %x, %z 255 %d = or i64 %b, %c 256 ret i64 %d 257} 258 259; CHECK-LABEL: masked_rotr: 260; CHECK-NEXT: .functype masked_rotr (i64, i64) -> (i64){{$}} 261; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 262; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 263; CHECK-NEXT: i64.rotr $push0=, $pop[[L0]], $pop[[L1]] 264; CHECK-NEXT: return $pop0{{$}} 265define i64 @masked_rotr(i64 %x, i64 %y) { 266 %a = and i64 %y, 63 267 %z = sub i64 64, %a 268 %b = lshr i64 %x, %a 269 %c = shl i64 %x, %z 270 %d = or i64 %b, %c 271 ret i64 %d 272} 273