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