1; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt 2; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+atomics,+sign-ext | FileCheck %s 3 4; Test atomic RMW (read-modify-write) instructions are assembled properly. 5 6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 7target triple = "wasm32-unknown-unknown" 8 9;===---------------------------------------------------------------------------- 10; Atomic read-modify-writes: 32-bit 11;===---------------------------------------------------------------------------- 12 13; CHECK-LABEL: add_i32: 14; CHECK-NEXT: .param i32, i32{{$}} 15; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}} 16; CHECK-NEXT: return $pop0{{$}} 17define i32 @add_i32(i32* %p, i32 %v) { 18 %old = atomicrmw add i32* %p, i32 %v seq_cst 19 ret i32 %old 20} 21 22; CHECK-LABEL: sub_i32: 23; CHECK-NEXT: .param i32, i32{{$}} 24; CHECK: i32.atomic.rmw.sub $push0=, 0($0), $1{{$}} 25; CHECK-NEXT: return $pop0{{$}} 26define i32 @sub_i32(i32* %p, i32 %v) { 27 %old = atomicrmw sub i32* %p, i32 %v seq_cst 28 ret i32 %old 29} 30 31; CHECK-LABEL: and_i32: 32; CHECK-NEXT: .param i32, i32{{$}} 33; CHECK: i32.atomic.rmw.and $push0=, 0($0), $1{{$}} 34; CHECK-NEXT: return $pop0{{$}} 35define i32 @and_i32(i32* %p, i32 %v) { 36 %old = atomicrmw and i32* %p, i32 %v seq_cst 37 ret i32 %old 38} 39 40; CHECK-LABEL: or_i32: 41; CHECK-NEXT: .param i32, i32{{$}} 42; CHECK: i32.atomic.rmw.or $push0=, 0($0), $1{{$}} 43; CHECK-NEXT: return $pop0{{$}} 44define i32 @or_i32(i32* %p, i32 %v) { 45 %old = atomicrmw or i32* %p, i32 %v seq_cst 46 ret i32 %old 47} 48 49; CHECK-LABEL: xor_i32: 50; CHECK-NEXT: .param i32, i32{{$}} 51; CHECK: i32.atomic.rmw.xor $push0=, 0($0), $1{{$}} 52; CHECK-NEXT: return $pop0{{$}} 53define i32 @xor_i32(i32* %p, i32 %v) { 54 %old = atomicrmw xor i32* %p, i32 %v seq_cst 55 ret i32 %old 56} 57 58; CHECK-LABEL: xchg_i32: 59; CHECK-NEXT: .param i32, i32{{$}} 60; CHECK: i32.atomic.rmw.xchg $push0=, 0($0), $1{{$}} 61; CHECK-NEXT: return $pop0{{$}} 62define i32 @xchg_i32(i32* %p, i32 %v) { 63 %old = atomicrmw xchg i32* %p, i32 %v seq_cst 64 ret i32 %old 65} 66 67;===---------------------------------------------------------------------------- 68; Atomic read-modify-writes: 64-bit 69;===---------------------------------------------------------------------------- 70 71; CHECK-LABEL: add_i64: 72; CHECK-NEXT: .param i32, i64{{$}} 73; CHECK: i64.atomic.rmw.add $push0=, 0($0), $1{{$}} 74; CHECK-NEXT: return $pop0{{$}} 75define i64 @add_i64(i64* %p, i64 %v) { 76 %old = atomicrmw add i64* %p, i64 %v seq_cst 77 ret i64 %old 78} 79 80; CHECK-LABEL: sub_i64: 81; CHECK-NEXT: .param i32, i64{{$}} 82; CHECK: i64.atomic.rmw.sub $push0=, 0($0), $1{{$}} 83; CHECK-NEXT: return $pop0{{$}} 84define i64 @sub_i64(i64* %p, i64 %v) { 85 %old = atomicrmw sub i64* %p, i64 %v seq_cst 86 ret i64 %old 87} 88 89; CHECK-LABEL: and_i64: 90; CHECK-NEXT: .param i32, i64{{$}} 91; CHECK: i64.atomic.rmw.and $push0=, 0($0), $1{{$}} 92; CHECK-NEXT: return $pop0{{$}} 93define i64 @and_i64(i64* %p, i64 %v) { 94 %old = atomicrmw and i64* %p, i64 %v seq_cst 95 ret i64 %old 96} 97 98; CHECK-LABEL: or_i64: 99; CHECK-NEXT: .param i32, i64{{$}} 100; CHECK: i64.atomic.rmw.or $push0=, 0($0), $1{{$}} 101; CHECK-NEXT: return $pop0{{$}} 102define i64 @or_i64(i64* %p, i64 %v) { 103 %old = atomicrmw or i64* %p, i64 %v seq_cst 104 ret i64 %old 105} 106 107; CHECK-LABEL: xor_i64: 108; CHECK-NEXT: .param i32, i64{{$}} 109; CHECK: i64.atomic.rmw.xor $push0=, 0($0), $1{{$}} 110; CHECK-NEXT: return $pop0{{$}} 111define i64 @xor_i64(i64* %p, i64 %v) { 112 %old = atomicrmw xor i64* %p, i64 %v seq_cst 113 ret i64 %old 114} 115 116; CHECK-LABEL: xchg_i64: 117; CHECK-NEXT: .param i32, i64{{$}} 118; CHECK: i64.atomic.rmw.xchg $push0=, 0($0), $1{{$}} 119; CHECK-NEXT: return $pop0{{$}} 120define i64 @xchg_i64(i64* %p, i64 %v) { 121 %old = atomicrmw xchg i64* %p, i64 %v seq_cst 122 ret i64 %old 123} 124 125;===---------------------------------------------------------------------------- 126; Atomic truncating & sign-extending RMWs 127;===---------------------------------------------------------------------------- 128 129; add 130 131; CHECK-LABEL: add_sext_i8_i32: 132; CHECK-NEXT: .param i32, i32{{$}} 133; CHECK: i32.atomic.rmw8_u.add $push0=, 0($0), $1{{$}} 134; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}} 135; CHECK-NEXT: return $pop1{{$}} 136define i32 @add_sext_i8_i32(i8* %p, i32 %v) { 137 %t = trunc i32 %v to i8 138 %old = atomicrmw add i8* %p, i8 %t seq_cst 139 %e = sext i8 %old to i32 140 ret i32 %e 141} 142 143; CHECK-LABEL: add_sext_i16_i32: 144; CHECK-NEXT: .param i32, i32{{$}} 145; CHECK: i32.atomic.rmw16_u.add $push0=, 0($0), $1{{$}} 146; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}} 147; CHECK-NEXT: return $pop1{{$}} 148define i32 @add_sext_i16_i32(i16* %p, i32 %v) { 149 %t = trunc i32 %v to i16 150 %old = atomicrmw add i16* %p, i16 %t seq_cst 151 %e = sext i16 %old to i32 152 ret i32 %e 153} 154 155; CHECK-LABEL: add_sext_i8_i64: 156; CHECK-NEXT: .param i32, i64{{$}} 157; CHECK: i64.atomic.rmw8_u.add $push0=, 0($0), $1{{$}} 158; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}} 159; CHECK-NEXT: return $pop1{{$}} 160define i64 @add_sext_i8_i64(i8* %p, i64 %v) { 161 %t = trunc i64 %v to i8 162 %old = atomicrmw add i8* %p, i8 %t seq_cst 163 %e = sext i8 %old to i64 164 ret i64 %e 165} 166 167; CHECK-LABEL: add_sext_i16_i64: 168; CHECK-NEXT: .param i32, i64{{$}} 169; CHECK: i64.atomic.rmw16_u.add $push0=, 0($0), $1{{$}} 170; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}} 171; CHECK-NEXT: return $pop1{{$}} 172define i64 @add_sext_i16_i64(i16* %p, i64 %v) { 173 %t = trunc i64 %v to i16 174 %old = atomicrmw add i16* %p, i16 %t seq_cst 175 %e = sext i16 %old to i64 176 ret i64 %e 177} 178 179; 32->64 sext rmw gets selected as i32.atomic.rmw.add, i64_extend_s/i32 180; CHECK-LABEL: add_sext_i32_i64: 181; CHECK-NEXT: .param i32, i64{{$}} 182; CHECK: i32.wrap/i64 $push0=, $1{{$}} 183; CHECK: i32.atomic.rmw.add $push1=, 0($0), $pop0{{$}} 184; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}} 185; CHECK-NEXT: return $pop2{{$}} 186define i64 @add_sext_i32_i64(i32* %p, i64 %v) { 187 %t = trunc i64 %v to i32 188 %old = atomicrmw add i32* %p, i32 %t seq_cst 189 %e = sext i32 %old to i64 190 ret i64 %e 191} 192 193; sub 194 195; CHECK-LABEL: sub_sext_i8_i32: 196; CHECK-NEXT: .param i32, i32{{$}} 197; CHECK: i32.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}} 198; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}} 199; CHECK-NEXT: return $pop1{{$}} 200define i32 @sub_sext_i8_i32(i8* %p, i32 %v) { 201 %t = trunc i32 %v to i8 202 %old = atomicrmw sub i8* %p, i8 %t seq_cst 203 %e = sext i8 %old to i32 204 ret i32 %e 205} 206 207; CHECK-LABEL: sub_sext_i16_i32: 208; CHECK-NEXT: .param i32, i32{{$}} 209; CHECK: i32.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}} 210; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}} 211; CHECK-NEXT: return $pop1{{$}} 212define i32 @sub_sext_i16_i32(i16* %p, i32 %v) { 213 %t = trunc i32 %v to i16 214 %old = atomicrmw sub i16* %p, i16 %t seq_cst 215 %e = sext i16 %old to i32 216 ret i32 %e 217} 218 219; CHECK-LABEL: sub_sext_i8_i64: 220; CHECK-NEXT: .param i32, i64{{$}} 221; CHECK: i64.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}} 222; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}} 223; CHECK-NEXT: return $pop1{{$}} 224define i64 @sub_sext_i8_i64(i8* %p, i64 %v) { 225 %t = trunc i64 %v to i8 226 %old = atomicrmw sub i8* %p, i8 %t seq_cst 227 %e = sext i8 %old to i64 228 ret i64 %e 229} 230 231; CHECK-LABEL: sub_sext_i16_i64: 232; CHECK-NEXT: .param i32, i64{{$}} 233; CHECK: i64.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}} 234; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}} 235; CHECK-NEXT: return $pop1{{$}} 236define i64 @sub_sext_i16_i64(i16* %p, i64 %v) { 237 %t = trunc i64 %v to i16 238 %old = atomicrmw sub i16* %p, i16 %t seq_cst 239 %e = sext i16 %old to i64 240 ret i64 %e 241} 242 243; 32->64 sext rmw gets selected as i32.atomic.rmw.sub, i64_extend_s/i32 244; CHECK-LABEL: sub_sext_i32_i64: 245; CHECK-NEXT: .param i32, i64{{$}} 246; CHECK: i32.wrap/i64 $push0=, $1 247; CHECK: i32.atomic.rmw.sub $push1=, 0($0), $pop0{{$}} 248; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}} 249; CHECK-NEXT: return $pop2{{$}} 250define i64 @sub_sext_i32_i64(i32* %p, i64 %v) { 251 %t = trunc i64 %v to i32 252 %old = atomicrmw sub i32* %p, i32 %t seq_cst 253 %e = sext i32 %old to i64 254 ret i64 %e 255} 256 257; and 258 259; CHECK-LABEL: and_sext_i8_i32: 260; CHECK-NEXT: .param i32, i32{{$}} 261; CHECK: i32.atomic.rmw8_u.and $push0=, 0($0), $1{{$}} 262; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}} 263; CHECK-NEXT: return $pop1{{$}} 264define i32 @and_sext_i8_i32(i8* %p, i32 %v) { 265 %t = trunc i32 %v to i8 266 %old = atomicrmw and i8* %p, i8 %t seq_cst 267 %e = sext i8 %old to i32 268 ret i32 %e 269} 270 271; CHECK-LABEL: and_sext_i16_i32: 272; CHECK-NEXT: .param i32, i32{{$}} 273; CHECK: i32.atomic.rmw16_u.and $push0=, 0($0), $1{{$}} 274; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}} 275; CHECK-NEXT: return $pop1{{$}} 276define i32 @and_sext_i16_i32(i16* %p, i32 %v) { 277 %t = trunc i32 %v to i16 278 %old = atomicrmw and i16* %p, i16 %t seq_cst 279 %e = sext i16 %old to i32 280 ret i32 %e 281} 282 283; CHECK-LABEL: and_sext_i8_i64: 284; CHECK-NEXT: .param i32, i64{{$}} 285; CHECK: i64.atomic.rmw8_u.and $push0=, 0($0), $1{{$}} 286; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}} 287; CHECK-NEXT: return $pop1{{$}} 288define i64 @and_sext_i8_i64(i8* %p, i64 %v) { 289 %t = trunc i64 %v to i8 290 %old = atomicrmw and i8* %p, i8 %t seq_cst 291 %e = sext i8 %old to i64 292 ret i64 %e 293} 294 295; CHECK-LABEL: and_sext_i16_i64: 296; CHECK-NEXT: .param i32, i64{{$}} 297; CHECK: i64.atomic.rmw16_u.and $push0=, 0($0), $1{{$}} 298; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}} 299; CHECK-NEXT: return $pop1{{$}} 300define i64 @and_sext_i16_i64(i16* %p, i64 %v) { 301 %t = trunc i64 %v to i16 302 %old = atomicrmw and i16* %p, i16 %t seq_cst 303 %e = sext i16 %old to i64 304 ret i64 %e 305} 306 307; 32->64 sext rmw gets selected as i32.atomic.rmw.and, i64_extend_s/i32 308; CHECK-LABEL: and_sext_i32_i64: 309; CHECK-NEXT: .param i32, i64{{$}} 310; CHECK: i32.wrap/i64 $push0=, $1{{$}} 311; CHECK: i32.atomic.rmw.and $push1=, 0($0), $pop0{{$}} 312; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}} 313; CHECK-NEXT: return $pop2{{$}} 314define i64 @and_sext_i32_i64(i32* %p, i64 %v) { 315 %t = trunc i64 %v to i32 316 %old = atomicrmw and i32* %p, i32 %t seq_cst 317 %e = sext i32 %old to i64 318 ret i64 %e 319} 320 321; or 322 323; CHECK-LABEL: or_sext_i8_i32: 324; CHECK-NEXT: .param i32, i32{{$}} 325; CHECK: i32.atomic.rmw8_u.or $push0=, 0($0), $1{{$}} 326; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}} 327; CHECK-NEXT: return $pop1{{$}} 328define i32 @or_sext_i8_i32(i8* %p, i32 %v) { 329 %t = trunc i32 %v to i8 330 %old = atomicrmw or i8* %p, i8 %t seq_cst 331 %e = sext i8 %old to i32 332 ret i32 %e 333} 334 335; CHECK-LABEL: or_sext_i16_i32: 336; CHECK-NEXT: .param i32, i32{{$}} 337; CHECK: i32.atomic.rmw16_u.or $push0=, 0($0), $1{{$}} 338; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}} 339; CHECK-NEXT: return $pop1{{$}} 340define i32 @or_sext_i16_i32(i16* %p, i32 %v) { 341 %t = trunc i32 %v to i16 342 %old = atomicrmw or i16* %p, i16 %t seq_cst 343 %e = sext i16 %old to i32 344 ret i32 %e 345} 346 347; CHECK-LABEL: or_sext_i8_i64: 348; CHECK-NEXT: .param i32, i64{{$}} 349; CHECK: i64.atomic.rmw8_u.or $push0=, 0($0), $1{{$}} 350; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}} 351; CHECK-NEXT: return $pop1{{$}} 352define i64 @or_sext_i8_i64(i8* %p, i64 %v) { 353 %t = trunc i64 %v to i8 354 %old = atomicrmw or i8* %p, i8 %t seq_cst 355 %e = sext i8 %old to i64 356 ret i64 %e 357} 358 359; CHECK-LABEL: or_sext_i16_i64: 360; CHECK-NEXT: .param i32, i64{{$}} 361; CHECK: i64.atomic.rmw16_u.or $push0=, 0($0), $1{{$}} 362; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}} 363; CHECK-NEXT: return $pop1{{$}} 364define i64 @or_sext_i16_i64(i16* %p, i64 %v) { 365 %t = trunc i64 %v to i16 366 %old = atomicrmw or i16* %p, i16 %t seq_cst 367 %e = sext i16 %old to i64 368 ret i64 %e 369} 370 371; 32->64 sext rmw gets selected as i32.atomic.rmw.or, i64_extend_s/i32 372; CHECK-LABEL: or_sext_i32_i64: 373; CHECK-NEXT: .param i32, i64{{$}} 374; CHECK: i32.wrap/i64 $push0=, $1{{$}} 375; CHECK: i32.atomic.rmw.or $push1=, 0($0), $pop0{{$}} 376; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}} 377; CHECK-NEXT: return $pop2{{$}} 378define i64 @or_sext_i32_i64(i32* %p, i64 %v) { 379 %t = trunc i64 %v to i32 380 %old = atomicrmw or i32* %p, i32 %t seq_cst 381 %e = sext i32 %old to i64 382 ret i64 %e 383} 384 385; xor 386 387; CHECK-LABEL: xor_sext_i8_i32: 388; CHECK-NEXT: .param i32, i32{{$}} 389; CHECK: i32.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}} 390; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}} 391; CHECK-NEXT: return $pop1{{$}} 392define i32 @xor_sext_i8_i32(i8* %p, i32 %v) { 393 %t = trunc i32 %v to i8 394 %old = atomicrmw xor i8* %p, i8 %t seq_cst 395 %e = sext i8 %old to i32 396 ret i32 %e 397} 398 399; CHECK-LABEL: xor_sext_i16_i32: 400; CHECK-NEXT: .param i32, i32{{$}} 401; CHECK: i32.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}} 402; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}} 403; CHECK-NEXT: return $pop1{{$}} 404define i32 @xor_sext_i16_i32(i16* %p, i32 %v) { 405 %t = trunc i32 %v to i16 406 %old = atomicrmw xor i16* %p, i16 %t seq_cst 407 %e = sext i16 %old to i32 408 ret i32 %e 409} 410 411; CHECK-LABEL: xor_sext_i8_i64: 412; CHECK-NEXT: .param i32, i64{{$}} 413; CHECK: i64.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}} 414; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}} 415; CHECK-NEXT: return $pop1{{$}} 416define i64 @xor_sext_i8_i64(i8* %p, i64 %v) { 417 %t = trunc i64 %v to i8 418 %old = atomicrmw xor i8* %p, i8 %t seq_cst 419 %e = sext i8 %old to i64 420 ret i64 %e 421} 422 423; CHECK-LABEL: xor_sext_i16_i64: 424; CHECK-NEXT: .param i32, i64{{$}} 425; CHECK: i64.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}} 426; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}} 427; CHECK-NEXT: return $pop1{{$}} 428define i64 @xor_sext_i16_i64(i16* %p, i64 %v) { 429 %t = trunc i64 %v to i16 430 %old = atomicrmw xor i16* %p, i16 %t seq_cst 431 %e = sext i16 %old to i64 432 ret i64 %e 433} 434 435; 32->64 sext rmw gets selected as i32.atomic.rmw.xor, i64_extend_s/i32 436; CHECK-LABEL: xor_sext_i32_i64: 437; CHECK-NEXT: .param i32, i64{{$}} 438; CHECK: i32.wrap/i64 $push0=, $1{{$}} 439; CHECK: i32.atomic.rmw.xor $push1=, 0($0), $pop0{{$}} 440; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}} 441; CHECK-NEXT: return $pop2{{$}} 442define i64 @xor_sext_i32_i64(i32* %p, i64 %v) { 443 %t = trunc i64 %v to i32 444 %old = atomicrmw xor i32* %p, i32 %t seq_cst 445 %e = sext i32 %old to i64 446 ret i64 %e 447} 448 449; xchg 450 451; CHECK-LABEL: xchg_sext_i8_i32: 452; CHECK-NEXT: .param i32, i32{{$}} 453; CHECK: i32.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}} 454; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}} 455; CHECK-NEXT: return $pop1{{$}} 456define i32 @xchg_sext_i8_i32(i8* %p, i32 %v) { 457 %t = trunc i32 %v to i8 458 %old = atomicrmw xchg i8* %p, i8 %t seq_cst 459 %e = sext i8 %old to i32 460 ret i32 %e 461} 462 463; CHECK-LABEL: xchg_sext_i16_i32: 464; CHECK-NEXT: .param i32, i32{{$}} 465; CHECK: i32.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}} 466; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}} 467; CHECK-NEXT: return $pop1{{$}} 468define i32 @xchg_sext_i16_i32(i16* %p, i32 %v) { 469 %t = trunc i32 %v to i16 470 %old = atomicrmw xchg i16* %p, i16 %t seq_cst 471 %e = sext i16 %old to i32 472 ret i32 %e 473} 474 475; CHECK-LABEL: xchg_sext_i8_i64: 476; CHECK-NEXT: .param i32, i64{{$}} 477; CHECK: i64.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}} 478; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}} 479; CHECK-NEXT: return $pop1{{$}} 480define i64 @xchg_sext_i8_i64(i8* %p, i64 %v) { 481 %t = trunc i64 %v to i8 482 %old = atomicrmw xchg i8* %p, i8 %t seq_cst 483 %e = sext i8 %old to i64 484 ret i64 %e 485} 486 487; CHECK-LABEL: xchg_sext_i16_i64: 488; CHECK-NEXT: .param i32, i64{{$}} 489; CHECK: i64.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}} 490; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}} 491; CHECK-NEXT: return $pop1{{$}} 492define i64 @xchg_sext_i16_i64(i16* %p, i64 %v) { 493 %t = trunc i64 %v to i16 494 %old = atomicrmw xchg i16* %p, i16 %t seq_cst 495 %e = sext i16 %old to i64 496 ret i64 %e 497} 498 499; 32->64 sext rmw gets selected as i32.atomic.rmw.xchg, i64_extend_s/i32 500; CHECK-LABEL: xchg_sext_i32_i64: 501; CHECK-NEXT: .param i32, i64{{$}} 502; CHECK: i32.wrap/i64 $push0=, $1{{$}} 503; CHECK: i32.atomic.rmw.xchg $push1=, 0($0), $pop0{{$}} 504; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}} 505; CHECK-NEXT: return $pop2{{$}} 506define i64 @xchg_sext_i32_i64(i32* %p, i64 %v) { 507 %t = trunc i64 %v to i32 508 %old = atomicrmw xchg i32* %p, i32 %t seq_cst 509 %e = sext i32 %old to i64 510 ret i64 %e 511} 512 513;===---------------------------------------------------------------------------- 514; Atomic truncating & zero-extending RMWs 515;===---------------------------------------------------------------------------- 516 517; add 518 519; CHECK-LABEL: add_zext_i8_i32: 520; CHECK-NEXT: .param i32, i32{{$}} 521; CHECK: i32.atomic.rmw8_u.add $push0=, 0($0), $1{{$}} 522; CHECK-NEXT: return $pop0{{$}} 523define i32 @add_zext_i8_i32(i8* %p, i32 %v) { 524 %t = trunc i32 %v to i8 525 %old = atomicrmw add i8* %p, i8 %t seq_cst 526 %e = zext i8 %old to i32 527 ret i32 %e 528} 529 530; CHECK-LABEL: add_zext_i16_i32: 531; CHECK-NEXT: .param i32, i32{{$}} 532; CHECK: i32.atomic.rmw16_u.add $push0=, 0($0), $1{{$}} 533; CHECK-NEXT: return $pop0{{$}} 534define i32 @add_zext_i16_i32(i16* %p, i32 %v) { 535 %t = trunc i32 %v to i16 536 %old = atomicrmw add i16* %p, i16 %t seq_cst 537 %e = zext i16 %old to i32 538 ret i32 %e 539} 540 541; CHECK-LABEL: add_zext_i8_i64: 542; CHECK-NEXT: .param i32, i64{{$}} 543; CHECK: i64.atomic.rmw8_u.add $push0=, 0($0), $1{{$}} 544; CHECK-NEXT: return $pop0{{$}} 545define i64 @add_zext_i8_i64(i8* %p, i64 %v) { 546 %t = trunc i64 %v to i8 547 %old = atomicrmw add i8* %p, i8 %t seq_cst 548 %e = zext i8 %old to i64 549 ret i64 %e 550} 551 552; CHECK-LABEL: add_zext_i16_i64: 553; CHECK-NEXT: .param i32, i64{{$}} 554; CHECK: i64.atomic.rmw16_u.add $push0=, 0($0), $1{{$}} 555; CHECK-NEXT: return $pop0{{$}} 556define i64 @add_zext_i16_i64(i16* %p, i64 %v) { 557 %t = trunc i64 %v to i16 558 %old = atomicrmw add i16* %p, i16 %t seq_cst 559 %e = zext i16 %old to i64 560 ret i64 %e 561} 562 563; CHECK-LABEL: add_zext_i32_i64: 564; CHECK-NEXT: .param i32, i64{{$}} 565; CHECK: i64.atomic.rmw32_u.add $push0=, 0($0), $1{{$}} 566; CHECK-NEXT: return $pop0{{$}} 567define i64 @add_zext_i32_i64(i32* %p, i64 %v) { 568 %t = trunc i64 %v to i32 569 %old = atomicrmw add i32* %p, i32 %t seq_cst 570 %e = zext i32 %old to i64 571 ret i64 %e 572} 573 574; sub 575 576; CHECK-LABEL: sub_zext_i8_i32: 577; CHECK-NEXT: .param i32, i32{{$}} 578; CHECK: i32.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}} 579; CHECK-NEXT: return $pop0{{$}} 580define i32 @sub_zext_i8_i32(i8* %p, i32 %v) { 581 %t = trunc i32 %v to i8 582 %old = atomicrmw sub i8* %p, i8 %t seq_cst 583 %e = zext i8 %old to i32 584 ret i32 %e 585} 586 587; CHECK-LABEL: sub_zext_i16_i32: 588; CHECK-NEXT: .param i32, i32{{$}} 589; CHECK: i32.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}} 590; CHECK-NEXT: return $pop0{{$}} 591define i32 @sub_zext_i16_i32(i16* %p, i32 %v) { 592 %t = trunc i32 %v to i16 593 %old = atomicrmw sub i16* %p, i16 %t seq_cst 594 %e = zext i16 %old to i32 595 ret i32 %e 596} 597 598; CHECK-LABEL: sub_zext_i8_i64: 599; CHECK-NEXT: .param i32, i64{{$}} 600; CHECK: i64.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}} 601; CHECK-NEXT: return $pop0{{$}} 602define i64 @sub_zext_i8_i64(i8* %p, i64 %v) { 603 %t = trunc i64 %v to i8 604 %old = atomicrmw sub i8* %p, i8 %t seq_cst 605 %e = zext i8 %old to i64 606 ret i64 %e 607} 608 609; CHECK-LABEL: sub_zext_i16_i64: 610; CHECK-NEXT: .param i32, i64{{$}} 611; CHECK: i64.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}} 612; CHECK-NEXT: return $pop0{{$}} 613define i64 @sub_zext_i16_i64(i16* %p, i64 %v) { 614 %t = trunc i64 %v to i16 615 %old = atomicrmw sub i16* %p, i16 %t seq_cst 616 %e = zext i16 %old to i64 617 ret i64 %e 618} 619 620; CHECK-LABEL: sub_zext_i32_i64: 621; CHECK-NEXT: .param i32, i64{{$}} 622; CHECK: i64.atomic.rmw32_u.sub $push0=, 0($0), $1{{$}} 623; CHECK-NEXT: return $pop0{{$}} 624define i64 @sub_zext_i32_i64(i32* %p, i64 %v) { 625 %t = trunc i64 %v to i32 626 %old = atomicrmw sub i32* %p, i32 %t seq_cst 627 %e = zext i32 %old to i64 628 ret i64 %e 629} 630 631; and 632 633; CHECK-LABEL: and_zext_i8_i32: 634; CHECK-NEXT: .param i32, i32{{$}} 635; CHECK: i32.atomic.rmw8_u.and $push0=, 0($0), $1{{$}} 636; CHECK-NEXT: return $pop0{{$}} 637define i32 @and_zext_i8_i32(i8* %p, i32 %v) { 638 %t = trunc i32 %v to i8 639 %old = atomicrmw and i8* %p, i8 %t seq_cst 640 %e = zext i8 %old to i32 641 ret i32 %e 642} 643 644; CHECK-LABEL: and_zext_i16_i32: 645; CHECK-NEXT: .param i32, i32{{$}} 646; CHECK: i32.atomic.rmw16_u.and $push0=, 0($0), $1{{$}} 647; CHECK-NEXT: return $pop0{{$}} 648define i32 @and_zext_i16_i32(i16* %p, i32 %v) { 649 %t = trunc i32 %v to i16 650 %old = atomicrmw and i16* %p, i16 %t seq_cst 651 %e = zext i16 %old to i32 652 ret i32 %e 653} 654 655; CHECK-LABEL: and_zext_i8_i64: 656; CHECK-NEXT: .param i32, i64{{$}} 657; CHECK: i64.atomic.rmw8_u.and $push0=, 0($0), $1{{$}} 658; CHECK-NEXT: return $pop0{{$}} 659define i64 @and_zext_i8_i64(i8* %p, i64 %v) { 660 %t = trunc i64 %v to i8 661 %old = atomicrmw and i8* %p, i8 %t seq_cst 662 %e = zext i8 %old to i64 663 ret i64 %e 664} 665 666; CHECK-LABEL: and_zext_i16_i64: 667; CHECK-NEXT: .param i32, i64{{$}} 668; CHECK: i64.atomic.rmw16_u.and $push0=, 0($0), $1{{$}} 669; CHECK-NEXT: return $pop0{{$}} 670define i64 @and_zext_i16_i64(i16* %p, i64 %v) { 671 %t = trunc i64 %v to i16 672 %old = atomicrmw and i16* %p, i16 %t seq_cst 673 %e = zext i16 %old to i64 674 ret i64 %e 675} 676 677; CHECK-LABEL: and_zext_i32_i64: 678; CHECK-NEXT: .param i32, i64{{$}} 679; CHECK: i64.atomic.rmw32_u.and $push0=, 0($0), $1{{$}} 680; CHECK-NEXT: return $pop0{{$}} 681define i64 @and_zext_i32_i64(i32* %p, i64 %v) { 682 %t = trunc i64 %v to i32 683 %old = atomicrmw and i32* %p, i32 %t seq_cst 684 %e = zext i32 %old to i64 685 ret i64 %e 686} 687 688; or 689 690; CHECK-LABEL: or_zext_i8_i32: 691; CHECK-NEXT: .param i32, i32{{$}} 692; CHECK: i32.atomic.rmw8_u.or $push0=, 0($0), $1{{$}} 693; CHECK-NEXT: return $pop0{{$}} 694define i32 @or_zext_i8_i32(i8* %p, i32 %v) { 695 %t = trunc i32 %v to i8 696 %old = atomicrmw or i8* %p, i8 %t seq_cst 697 %e = zext i8 %old to i32 698 ret i32 %e 699} 700 701; CHECK-LABEL: or_zext_i16_i32: 702; CHECK-NEXT: .param i32, i32{{$}} 703; CHECK: i32.atomic.rmw16_u.or $push0=, 0($0), $1{{$}} 704; CHECK-NEXT: return $pop0{{$}} 705define i32 @or_zext_i16_i32(i16* %p, i32 %v) { 706 %t = trunc i32 %v to i16 707 %old = atomicrmw or i16* %p, i16 %t seq_cst 708 %e = zext i16 %old to i32 709 ret i32 %e 710} 711 712; CHECK-LABEL: or_zext_i8_i64: 713; CHECK-NEXT: .param i32, i64{{$}} 714; CHECK: i64.atomic.rmw8_u.or $push0=, 0($0), $1{{$}} 715; CHECK-NEXT: return $pop0{{$}} 716define i64 @or_zext_i8_i64(i8* %p, i64 %v) { 717 %t = trunc i64 %v to i8 718 %old = atomicrmw or i8* %p, i8 %t seq_cst 719 %e = zext i8 %old to i64 720 ret i64 %e 721} 722 723; CHECK-LABEL: or_zext_i16_i64: 724; CHECK-NEXT: .param i32, i64{{$}} 725; CHECK: i64.atomic.rmw16_u.or $push0=, 0($0), $1{{$}} 726; CHECK-NEXT: return $pop0{{$}} 727define i64 @or_zext_i16_i64(i16* %p, i64 %v) { 728 %t = trunc i64 %v to i16 729 %old = atomicrmw or i16* %p, i16 %t seq_cst 730 %e = zext i16 %old to i64 731 ret i64 %e 732} 733 734; CHECK-LABEL: or_zext_i32_i64: 735; CHECK-NEXT: .param i32, i64{{$}} 736; CHECK: i64.atomic.rmw32_u.or $push0=, 0($0), $1{{$}} 737; CHECK-NEXT: return $pop0{{$}} 738define i64 @or_zext_i32_i64(i32* %p, i64 %v) { 739 %t = trunc i64 %v to i32 740 %old = atomicrmw or i32* %p, i32 %t seq_cst 741 %e = zext i32 %old to i64 742 ret i64 %e 743} 744 745; xor 746 747; CHECK-LABEL: xor_zext_i8_i32: 748; CHECK-NEXT: .param i32, i32{{$}} 749; CHECK: i32.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}} 750; CHECK-NEXT: return $pop0{{$}} 751define i32 @xor_zext_i8_i32(i8* %p, i32 %v) { 752 %t = trunc i32 %v to i8 753 %old = atomicrmw xor i8* %p, i8 %t seq_cst 754 %e = zext i8 %old to i32 755 ret i32 %e 756} 757 758; CHECK-LABEL: xor_zext_i16_i32: 759; CHECK-NEXT: .param i32, i32{{$}} 760; CHECK: i32.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}} 761; CHECK-NEXT: return $pop0{{$}} 762define i32 @xor_zext_i16_i32(i16* %p, i32 %v) { 763 %t = trunc i32 %v to i16 764 %old = atomicrmw xor i16* %p, i16 %t seq_cst 765 %e = zext i16 %old to i32 766 ret i32 %e 767} 768 769; CHECK-LABEL: xor_zext_i8_i64: 770; CHECK-NEXT: .param i32, i64{{$}} 771; CHECK: i64.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}} 772; CHECK-NEXT: return $pop0{{$}} 773define i64 @xor_zext_i8_i64(i8* %p, i64 %v) { 774 %t = trunc i64 %v to i8 775 %old = atomicrmw xor i8* %p, i8 %t seq_cst 776 %e = zext i8 %old to i64 777 ret i64 %e 778} 779 780; CHECK-LABEL: xor_zext_i16_i64: 781; CHECK-NEXT: .param i32, i64{{$}} 782; CHECK: i64.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}} 783; CHECK-NEXT: return $pop0{{$}} 784define i64 @xor_zext_i16_i64(i16* %p, i64 %v) { 785 %t = trunc i64 %v to i16 786 %old = atomicrmw xor i16* %p, i16 %t seq_cst 787 %e = zext i16 %old to i64 788 ret i64 %e 789} 790 791; CHECK-LABEL: xor_zext_i32_i64: 792; CHECK-NEXT: .param i32, i64{{$}} 793; CHECK: i64.atomic.rmw32_u.xor $push0=, 0($0), $1{{$}} 794; CHECK-NEXT: return $pop0{{$}} 795define i64 @xor_zext_i32_i64(i32* %p, i64 %v) { 796 %t = trunc i64 %v to i32 797 %old = atomicrmw xor i32* %p, i32 %t seq_cst 798 %e = zext i32 %old to i64 799 ret i64 %e 800} 801 802; xchg 803 804; CHECK-LABEL: xchg_zext_i8_i32: 805; CHECK-NEXT: .param i32, i32{{$}} 806; CHECK: i32.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}} 807; CHECK-NEXT: return $pop0{{$}} 808define i32 @xchg_zext_i8_i32(i8* %p, i32 %v) { 809 %t = trunc i32 %v to i8 810 %old = atomicrmw xchg i8* %p, i8 %t seq_cst 811 %e = zext i8 %old to i32 812 ret i32 %e 813} 814 815; CHECK-LABEL: xchg_zext_i16_i32: 816; CHECK-NEXT: .param i32, i32{{$}} 817; CHECK: i32.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}} 818; CHECK-NEXT: return $pop0{{$}} 819define i32 @xchg_zext_i16_i32(i16* %p, i32 %v) { 820 %t = trunc i32 %v to i16 821 %old = atomicrmw xchg i16* %p, i16 %t seq_cst 822 %e = zext i16 %old to i32 823 ret i32 %e 824} 825 826; CHECK-LABEL: xchg_zext_i8_i64: 827; CHECK-NEXT: .param i32, i64{{$}} 828; CHECK: i64.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}} 829; CHECK-NEXT: return $pop0{{$}} 830define i64 @xchg_zext_i8_i64(i8* %p, i64 %v) { 831 %t = trunc i64 %v to i8 832 %old = atomicrmw xchg i8* %p, i8 %t seq_cst 833 %e = zext i8 %old to i64 834 ret i64 %e 835} 836 837; CHECK-LABEL: xchg_zext_i16_i64: 838; CHECK-NEXT: .param i32, i64{{$}} 839; CHECK: i64.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}} 840; CHECK-NEXT: return $pop0{{$}} 841define i64 @xchg_zext_i16_i64(i16* %p, i64 %v) { 842 %t = trunc i64 %v to i16 843 %old = atomicrmw xchg i16* %p, i16 %t seq_cst 844 %e = zext i16 %old to i64 845 ret i64 %e 846} 847 848; CHECK-LABEL: xchg_zext_i32_i64: 849; CHECK-NEXT: .param i32, i64{{$}} 850; CHECK: i64.atomic.rmw32_u.xchg $push0=, 0($0), $1{{$}} 851; CHECK-NEXT: return $pop0{{$}} 852define i64 @xchg_zext_i32_i64(i32* %p, i64 %v) { 853 %t = trunc i64 %v to i32 854 %old = atomicrmw xchg i32* %p, i32 %t seq_cst 855 %e = zext i32 %old to i64 856 ret i64 %e 857} 858