1281 lines · plain
1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers2; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+atomics,+sign-ext | FileCheck %s3 4; Test atomic RMW (read-modify-write) instructions are assembled properly.5 6target triple = "wasm32-unknown-unknown"7 8;===----------------------------------------------------------------------------9; Atomic read-modify-writes: 32-bit10;===----------------------------------------------------------------------------11 12; CHECK-LABEL: add_i32:13; CHECK-NEXT: .functype add_i32 (i32, i32) -> (i32){{$}}14; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}15; CHECK-NEXT: return $pop0{{$}}16define i32 @add_i32(ptr %p, i32 %v) {17 %old = atomicrmw add ptr %p, i32 %v seq_cst18 ret i32 %old19}20 21; CHECK-LABEL: sub_i32:22; CHECK-NEXT: .functype sub_i32 (i32, i32) -> (i32){{$}}23; CHECK: i32.atomic.rmw.sub $push0=, 0($0), $1{{$}}24; CHECK-NEXT: return $pop0{{$}}25define i32 @sub_i32(ptr %p, i32 %v) {26 %old = atomicrmw sub ptr %p, i32 %v seq_cst27 ret i32 %old28}29 30; CHECK-LABEL: and_i32:31; CHECK-NEXT: .functype and_i32 (i32, i32) -> (i32){{$}}32; CHECK: i32.atomic.rmw.and $push0=, 0($0), $1{{$}}33; CHECK-NEXT: return $pop0{{$}}34define i32 @and_i32(ptr %p, i32 %v) {35 %old = atomicrmw and ptr %p, i32 %v seq_cst36 ret i32 %old37}38 39; CHECK-LABEL: or_i32:40; CHECK-NEXT: .functype or_i32 (i32, i32) -> (i32){{$}}41; CHECK: i32.atomic.rmw.or $push0=, 0($0), $1{{$}}42; CHECK-NEXT: return $pop0{{$}}43define i32 @or_i32(ptr %p, i32 %v) {44 %old = atomicrmw or ptr %p, i32 %v seq_cst45 ret i32 %old46}47 48; CHECK-LABEL: xor_i32:49; CHECK-NEXT: .functype xor_i32 (i32, i32) -> (i32){{$}}50; CHECK: i32.atomic.rmw.xor $push0=, 0($0), $1{{$}}51; CHECK-NEXT: return $pop0{{$}}52define i32 @xor_i32(ptr %p, i32 %v) {53 %old = atomicrmw xor ptr %p, i32 %v seq_cst54 ret i32 %old55}56 57; CHECK-LABEL: xchg_i32:58; CHECK-NEXT: .functype xchg_i32 (i32, i32) -> (i32){{$}}59; CHECK: i32.atomic.rmw.xchg $push0=, 0($0), $1{{$}}60; CHECK-NEXT: return $pop0{{$}}61define i32 @xchg_i32(ptr %p, i32 %v) {62 %old = atomicrmw xchg ptr %p, i32 %v seq_cst63 ret i32 %old64}65 66; CHECK-LABEL: cmpxchg_i32_loaded_value:67; CHECK-NEXT: .functype cmpxchg_i32_loaded_value (i32, i32, i32) -> (i32){{$}}68; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}69; CHECK-NEXT: return $pop0{{$}}70define i32 @cmpxchg_i32_loaded_value(ptr %p, i32 %exp, i32 %new) {71 %pair = cmpxchg ptr %p, i32 %exp, i32 %new seq_cst seq_cst72 %old = extractvalue { i32, i1 } %pair, 073 ret i32 %old74}75 76; CHECK-LABEL: cmpxchg_i32_success:77; CHECK-NEXT: .functype cmpxchg_i32_success (i32, i32, i32) -> (i32){{$}}78; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}79; CHECK-NEXT: i32.eq $push1=, $pop0, $1{{$}}80; CHECK-NEXT: return $pop1{{$}}81define i1 @cmpxchg_i32_success(ptr %p, i32 %exp, i32 %new) {82 %pair = cmpxchg ptr %p, i32 %exp, i32 %new seq_cst seq_cst83 %succ = extractvalue { i32, i1 } %pair, 184 ret i1 %succ85}86 87; Unsupported instructions are expanded using cmpxchg with a loop.88 89; CHECK-LABEL: nand_i32:90; CHECK: loop91; CHECK: i32.atomic.rmw.cmpxchg92; CHECK: br_if 093; CHECK: end_loop94define i32 @nand_i32(ptr %p, i32 %v) {95 %old = atomicrmw nand ptr %p, i32 %v seq_cst96 ret i32 %old97}98 99; CHECK-LABEL: max_i32:100; CHECK: loop101; CHECK: i32.atomic.rmw.cmpxchg102; CHECK: br_if 0103; CHECK: end_loop104define i32 @max_i32(ptr %p, i32 %v) {105 %old = atomicrmw max ptr %p, i32 %v seq_cst106 ret i32 %old107}108 109; CHECK-LABEL: min_i32:110; CHECK: loop111; CHECK: i32.atomic.rmw.cmpxchg112; CHECK: br_if 0113; CHECK: end_loop114define i32 @min_i32(ptr %p, i32 %v) {115 %old = atomicrmw min ptr %p, i32 %v seq_cst116 ret i32 %old117}118 119; CHECK-LABEL: umax_i32:120; CHECK: loop121; CHECK: i32.atomic.rmw.cmpxchg122; CHECK: br_if 0123; CHECK: end_loop124define i32 @umax_i32(ptr %p, i32 %v) {125 %old = atomicrmw umax ptr %p, i32 %v seq_cst126 ret i32 %old127}128 129; CHECK-LABEL: umin_i32:130; CHECK: loop131; CHECK: i32.atomic.rmw.cmpxchg132; CHECK: br_if 0133; CHECK: end_loop134define i32 @umin_i32(ptr %p, i32 %v) {135 %old = atomicrmw umin ptr %p, i32 %v seq_cst136 ret i32 %old137}138 139;===----------------------------------------------------------------------------140; Atomic read-modify-writes: 64-bit141;===----------------------------------------------------------------------------142 143; CHECK-LABEL: add_i64:144; CHECK-NEXT: .functype add_i64 (i32, i64) -> (i64){{$}}145; CHECK: i64.atomic.rmw.add $push0=, 0($0), $1{{$}}146; CHECK-NEXT: return $pop0{{$}}147define i64 @add_i64(ptr %p, i64 %v) {148 %old = atomicrmw add ptr %p, i64 %v seq_cst149 ret i64 %old150}151 152; CHECK-LABEL: sub_i64:153; CHECK-NEXT: .functype sub_i64 (i32, i64) -> (i64){{$}}154; CHECK: i64.atomic.rmw.sub $push0=, 0($0), $1{{$}}155; CHECK-NEXT: return $pop0{{$}}156define i64 @sub_i64(ptr %p, i64 %v) {157 %old = atomicrmw sub ptr %p, i64 %v seq_cst158 ret i64 %old159}160 161; CHECK-LABEL: and_i64:162; CHECK-NEXT: .functype and_i64 (i32, i64) -> (i64){{$}}163; CHECK: i64.atomic.rmw.and $push0=, 0($0), $1{{$}}164; CHECK-NEXT: return $pop0{{$}}165define i64 @and_i64(ptr %p, i64 %v) {166 %old = atomicrmw and ptr %p, i64 %v seq_cst167 ret i64 %old168}169 170; CHECK-LABEL: or_i64:171; CHECK-NEXT: .functype or_i64 (i32, i64) -> (i64){{$}}172; CHECK: i64.atomic.rmw.or $push0=, 0($0), $1{{$}}173; CHECK-NEXT: return $pop0{{$}}174define i64 @or_i64(ptr %p, i64 %v) {175 %old = atomicrmw or ptr %p, i64 %v seq_cst176 ret i64 %old177}178 179; CHECK-LABEL: xor_i64:180; CHECK-NEXT: .functype xor_i64 (i32, i64) -> (i64){{$}}181; CHECK: i64.atomic.rmw.xor $push0=, 0($0), $1{{$}}182; CHECK-NEXT: return $pop0{{$}}183define i64 @xor_i64(ptr %p, i64 %v) {184 %old = atomicrmw xor ptr %p, i64 %v seq_cst185 ret i64 %old186}187 188; CHECK-LABEL: xchg_i64:189; CHECK-NEXT: .functype xchg_i64 (i32, i64) -> (i64){{$}}190; CHECK: i64.atomic.rmw.xchg $push0=, 0($0), $1{{$}}191; CHECK-NEXT: return $pop0{{$}}192define i64 @xchg_i64(ptr %p, i64 %v) {193 %old = atomicrmw xchg ptr %p, i64 %v seq_cst194 ret i64 %old195}196 197; CHECK-LABEL: cmpxchg_i64_loaded_value:198; CHECK-NEXT: .functype cmpxchg_i64_loaded_value (i32, i64, i64) -> (i64){{$}}199; CHECK: i64.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}200; CHECK-NEXT: return $pop0{{$}}201define i64 @cmpxchg_i64_loaded_value(ptr %p, i64 %exp, i64 %new) {202 %pair = cmpxchg ptr %p, i64 %exp, i64 %new seq_cst seq_cst203 %old = extractvalue { i64, i1 } %pair, 0204 ret i64 %old205}206 207; CHECK-LABEL: cmpxchg_i64_success:208; CHECK-NEXT: .functype cmpxchg_i64_success (i32, i64, i64) -> (i32){{$}}209; CHECK: i64.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}210; CHECK-NEXT: i64.eq $push1=, $pop0, $1{{$}}211; CHECK-NEXT: return $pop1{{$}}212define i1 @cmpxchg_i64_success(ptr %p, i64 %exp, i64 %new) {213 %pair = cmpxchg ptr %p, i64 %exp, i64 %new seq_cst seq_cst214 %succ = extractvalue { i64, i1 } %pair, 1215 ret i1 %succ216}217 218; Unsupported instructions are expanded using cmpxchg with a loop.219 220; CHECK-LABEL: nand_i64:221; CHECK: loop222; CHECK: i64.atomic.rmw.cmpxchg223; CHECK: br_if 0224; CHECK: end_loop225define i64 @nand_i64(ptr %p, i64 %v) {226 %old = atomicrmw nand ptr %p, i64 %v seq_cst227 ret i64 %old228}229 230; CHECK-LABEL: max_i64:231; CHECK: loop232; CHECK: i64.atomic.rmw.cmpxchg233; CHECK: br_if 0234; CHECK: end_loop235define i64 @max_i64(ptr %p, i64 %v) {236 %old = atomicrmw max ptr %p, i64 %v seq_cst237 ret i64 %old238}239 240; CHECK-LABEL: min_i64:241; CHECK: loop242; CHECK: i64.atomic.rmw.cmpxchg243; CHECK: br_if 0244; CHECK: end_loop245define i64 @min_i64(ptr %p, i64 %v) {246 %old = atomicrmw min ptr %p, i64 %v seq_cst247 ret i64 %old248}249 250; CHECK-LABEL: umax_i64:251; CHECK: loop252; CHECK: i64.atomic.rmw.cmpxchg253; CHECK: br_if 0254; CHECK: end_loop255define i64 @umax_i64(ptr %p, i64 %v) {256 %old = atomicrmw umax ptr %p, i64 %v seq_cst257 ret i64 %old258}259 260; CHECK-LABEL: umin_i64:261; CHECK: loop262; CHECK: i64.atomic.rmw.cmpxchg263; CHECK: br_if 0264; CHECK: end_loop265define i64 @umin_i64(ptr %p, i64 %v) {266 %old = atomicrmw umin ptr %p, i64 %v seq_cst267 ret i64 %old268}269 270;===----------------------------------------------------------------------------271; Atomic truncating & sign-extending RMWs272;===----------------------------------------------------------------------------273 274; add275 276; CHECK-LABEL: add_sext_i8_i32:277; CHECK-NEXT: .functype add_sext_i8_i32 (i32, i32) -> (i32){{$}}278; CHECK: i32.atomic.rmw8.add_u $push0=, 0($0), $1{{$}}279; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}280; CHECK-NEXT: return $pop1{{$}}281define i32 @add_sext_i8_i32(ptr %p, i32 %v) {282 %t = trunc i32 %v to i8283 %old = atomicrmw add ptr %p, i8 %t seq_cst284 %e = sext i8 %old to i32285 ret i32 %e286}287 288; CHECK-LABEL: add_sext_i16_i32:289; CHECK-NEXT: .functype add_sext_i16_i32 (i32, i32) -> (i32){{$}}290; CHECK: i32.atomic.rmw16.add_u $push0=, 0($0), $1{{$}}291; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}292; CHECK-NEXT: return $pop1{{$}}293define i32 @add_sext_i16_i32(ptr %p, i32 %v) {294 %t = trunc i32 %v to i16295 %old = atomicrmw add ptr %p, i16 %t seq_cst296 %e = sext i16 %old to i32297 ret i32 %e298}299 300; CHECK-LABEL: add_sext_i8_i64:301; CHECK-NEXT: .functype add_sext_i8_i64 (i32, i64) -> (i64){{$}}302; CHECK: i64.atomic.rmw8.add_u $push0=, 0($0), $1{{$}}303; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}304; CHECK-NEXT: return $pop1{{$}}305define i64 @add_sext_i8_i64(ptr %p, i64 %v) {306 %t = trunc i64 %v to i8307 %old = atomicrmw add ptr %p, i8 %t seq_cst308 %e = sext i8 %old to i64309 ret i64 %e310}311 312; CHECK-LABEL: add_sext_i16_i64:313; CHECK-NEXT: .functype add_sext_i16_i64 (i32, i64) -> (i64){{$}}314; CHECK: i64.atomic.rmw16.add_u $push0=, 0($0), $1{{$}}315; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}316; CHECK-NEXT: return $pop1{{$}}317define i64 @add_sext_i16_i64(ptr %p, i64 %v) {318 %t = trunc i64 %v to i16319 %old = atomicrmw add ptr %p, i16 %t seq_cst320 %e = sext i16 %old to i64321 ret i64 %e322}323 324; 32->64 sext rmw gets selected as i32.atomic.rmw.add, i64.extend_i32_s325; CHECK-LABEL: add_sext_i32_i64:326; CHECK-NEXT: .functype add_sext_i32_i64 (i32, i64) -> (i64){{$}}327; CHECK: i32.wrap_i64 $push0=, $1{{$}}328; CHECK: i32.atomic.rmw.add $push1=, 0($0), $pop0{{$}}329; CHECK-NEXT: i64.extend_i32_s $push2=, $pop1{{$}}330; CHECK-NEXT: return $pop2{{$}}331define i64 @add_sext_i32_i64(ptr %p, i64 %v) {332 %t = trunc i64 %v to i32333 %old = atomicrmw add ptr %p, i32 %t seq_cst334 %e = sext i32 %old to i64335 ret i64 %e336}337 338; sub339 340; CHECK-LABEL: sub_sext_i8_i32:341; CHECK-NEXT: .functype sub_sext_i8_i32 (i32, i32) -> (i32){{$}}342; CHECK: i32.atomic.rmw8.sub_u $push0=, 0($0), $1{{$}}343; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}344; CHECK-NEXT: return $pop1{{$}}345define i32 @sub_sext_i8_i32(ptr %p, i32 %v) {346 %t = trunc i32 %v to i8347 %old = atomicrmw sub ptr %p, i8 %t seq_cst348 %e = sext i8 %old to i32349 ret i32 %e350}351 352; CHECK-LABEL: sub_sext_i16_i32:353; CHECK-NEXT: .functype sub_sext_i16_i32 (i32, i32) -> (i32){{$}}354; CHECK: i32.atomic.rmw16.sub_u $push0=, 0($0), $1{{$}}355; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}356; CHECK-NEXT: return $pop1{{$}}357define i32 @sub_sext_i16_i32(ptr %p, i32 %v) {358 %t = trunc i32 %v to i16359 %old = atomicrmw sub ptr %p, i16 %t seq_cst360 %e = sext i16 %old to i32361 ret i32 %e362}363 364; CHECK-LABEL: sub_sext_i8_i64:365; CHECK-NEXT: .functype sub_sext_i8_i64 (i32, i64) -> (i64){{$}}366; CHECK: i64.atomic.rmw8.sub_u $push0=, 0($0), $1{{$}}367; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}368; CHECK-NEXT: return $pop1{{$}}369define i64 @sub_sext_i8_i64(ptr %p, i64 %v) {370 %t = trunc i64 %v to i8371 %old = atomicrmw sub ptr %p, i8 %t seq_cst372 %e = sext i8 %old to i64373 ret i64 %e374}375 376; CHECK-LABEL: sub_sext_i16_i64:377; CHECK-NEXT: .functype sub_sext_i16_i64 (i32, i64) -> (i64){{$}}378; CHECK: i64.atomic.rmw16.sub_u $push0=, 0($0), $1{{$}}379; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}380; CHECK-NEXT: return $pop1{{$}}381define i64 @sub_sext_i16_i64(ptr %p, i64 %v) {382 %t = trunc i64 %v to i16383 %old = atomicrmw sub ptr %p, i16 %t seq_cst384 %e = sext i16 %old to i64385 ret i64 %e386}387 388; 32->64 sext rmw gets selected as i32.atomic.rmw.sub, i64.extend_i32_s389; CHECK-LABEL: sub_sext_i32_i64:390; CHECK-NEXT: .functype sub_sext_i32_i64 (i32, i64) -> (i64){{$}}391; CHECK: i32.wrap_i64 $push0=, $1392; CHECK: i32.atomic.rmw.sub $push1=, 0($0), $pop0{{$}}393; CHECK-NEXT: i64.extend_i32_s $push2=, $pop1{{$}}394; CHECK-NEXT: return $pop2{{$}}395define i64 @sub_sext_i32_i64(ptr %p, i64 %v) {396 %t = trunc i64 %v to i32397 %old = atomicrmw sub ptr %p, i32 %t seq_cst398 %e = sext i32 %old to i64399 ret i64 %e400}401 402; and403 404; CHECK-LABEL: and_sext_i8_i32:405; CHECK-NEXT: .functype and_sext_i8_i32 (i32, i32) -> (i32){{$}}406; CHECK: i32.atomic.rmw8.and_u $push0=, 0($0), $1{{$}}407; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}408; CHECK-NEXT: return $pop1{{$}}409define i32 @and_sext_i8_i32(ptr %p, i32 %v) {410 %t = trunc i32 %v to i8411 %old = atomicrmw and ptr %p, i8 %t seq_cst412 %e = sext i8 %old to i32413 ret i32 %e414}415 416; CHECK-LABEL: and_sext_i16_i32:417; CHECK-NEXT: .functype and_sext_i16_i32 (i32, i32) -> (i32){{$}}418; CHECK: i32.atomic.rmw16.and_u $push0=, 0($0), $1{{$}}419; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}420; CHECK-NEXT: return $pop1{{$}}421define i32 @and_sext_i16_i32(ptr %p, i32 %v) {422 %t = trunc i32 %v to i16423 %old = atomicrmw and ptr %p, i16 %t seq_cst424 %e = sext i16 %old to i32425 ret i32 %e426}427 428; CHECK-LABEL: and_sext_i8_i64:429; CHECK-NEXT: .functype and_sext_i8_i64 (i32, i64) -> (i64){{$}}430; CHECK: i64.atomic.rmw8.and_u $push0=, 0($0), $1{{$}}431; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}432; CHECK-NEXT: return $pop1{{$}}433define i64 @and_sext_i8_i64(ptr %p, i64 %v) {434 %t = trunc i64 %v to i8435 %old = atomicrmw and ptr %p, i8 %t seq_cst436 %e = sext i8 %old to i64437 ret i64 %e438}439 440; CHECK-LABEL: and_sext_i16_i64:441; CHECK-NEXT: .functype and_sext_i16_i64 (i32, i64) -> (i64){{$}}442; CHECK: i64.atomic.rmw16.and_u $push0=, 0($0), $1{{$}}443; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}444; CHECK-NEXT: return $pop1{{$}}445define i64 @and_sext_i16_i64(ptr %p, i64 %v) {446 %t = trunc i64 %v to i16447 %old = atomicrmw and ptr %p, i16 %t seq_cst448 %e = sext i16 %old to i64449 ret i64 %e450}451 452; 32->64 sext rmw gets selected as i32.atomic.rmw.and, i64.extend_i32_s453; CHECK-LABEL: and_sext_i32_i64:454; CHECK-NEXT: .functype and_sext_i32_i64 (i32, i64) -> (i64){{$}}455; CHECK: i32.wrap_i64 $push0=, $1{{$}}456; CHECK: i32.atomic.rmw.and $push1=, 0($0), $pop0{{$}}457; CHECK-NEXT: i64.extend_i32_s $push2=, $pop1{{$}}458; CHECK-NEXT: return $pop2{{$}}459define i64 @and_sext_i32_i64(ptr %p, i64 %v) {460 %t = trunc i64 %v to i32461 %old = atomicrmw and ptr %p, i32 %t seq_cst462 %e = sext i32 %old to i64463 ret i64 %e464}465 466; or467 468; CHECK-LABEL: or_sext_i8_i32:469; CHECK-NEXT: .functype or_sext_i8_i32 (i32, i32) -> (i32){{$}}470; CHECK: i32.atomic.rmw8.or_u $push0=, 0($0), $1{{$}}471; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}472; CHECK-NEXT: return $pop1{{$}}473define i32 @or_sext_i8_i32(ptr %p, i32 %v) {474 %t = trunc i32 %v to i8475 %old = atomicrmw or ptr %p, i8 %t seq_cst476 %e = sext i8 %old to i32477 ret i32 %e478}479 480; CHECK-LABEL: or_sext_i16_i32:481; CHECK-NEXT: .functype or_sext_i16_i32 (i32, i32) -> (i32){{$}}482; CHECK: i32.atomic.rmw16.or_u $push0=, 0($0), $1{{$}}483; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}484; CHECK-NEXT: return $pop1{{$}}485define i32 @or_sext_i16_i32(ptr %p, i32 %v) {486 %t = trunc i32 %v to i16487 %old = atomicrmw or ptr %p, i16 %t seq_cst488 %e = sext i16 %old to i32489 ret i32 %e490}491 492; CHECK-LABEL: or_sext_i8_i64:493; CHECK-NEXT: .functype or_sext_i8_i64 (i32, i64) -> (i64){{$}}494; CHECK: i64.atomic.rmw8.or_u $push0=, 0($0), $1{{$}}495; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}496; CHECK-NEXT: return $pop1{{$}}497define i64 @or_sext_i8_i64(ptr %p, i64 %v) {498 %t = trunc i64 %v to i8499 %old = atomicrmw or ptr %p, i8 %t seq_cst500 %e = sext i8 %old to i64501 ret i64 %e502}503 504; CHECK-LABEL: or_sext_i16_i64:505; CHECK-NEXT: .functype or_sext_i16_i64 (i32, i64) -> (i64){{$}}506; CHECK: i64.atomic.rmw16.or_u $push0=, 0($0), $1{{$}}507; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}508; CHECK-NEXT: return $pop1{{$}}509define i64 @or_sext_i16_i64(ptr %p, i64 %v) {510 %t = trunc i64 %v to i16511 %old = atomicrmw or ptr %p, i16 %t seq_cst512 %e = sext i16 %old to i64513 ret i64 %e514}515 516; 32->64 sext rmw gets selected as i32.atomic.rmw.or, i64.extend_i32_s517; CHECK-LABEL: or_sext_i32_i64:518; CHECK-NEXT: .functype or_sext_i32_i64 (i32, i64) -> (i64){{$}}519; CHECK: i32.wrap_i64 $push0=, $1{{$}}520; CHECK: i32.atomic.rmw.or $push1=, 0($0), $pop0{{$}}521; CHECK-NEXT: i64.extend_i32_s $push2=, $pop1{{$}}522; CHECK-NEXT: return $pop2{{$}}523define i64 @or_sext_i32_i64(ptr %p, i64 %v) {524 %t = trunc i64 %v to i32525 %old = atomicrmw or ptr %p, i32 %t seq_cst526 %e = sext i32 %old to i64527 ret i64 %e528}529 530; xor531 532; CHECK-LABEL: xor_sext_i8_i32:533; CHECK-NEXT: .functype xor_sext_i8_i32 (i32, i32) -> (i32){{$}}534; CHECK: i32.atomic.rmw8.xor_u $push0=, 0($0), $1{{$}}535; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}536; CHECK-NEXT: return $pop1{{$}}537define i32 @xor_sext_i8_i32(ptr %p, i32 %v) {538 %t = trunc i32 %v to i8539 %old = atomicrmw xor ptr %p, i8 %t seq_cst540 %e = sext i8 %old to i32541 ret i32 %e542}543 544; CHECK-LABEL: xor_sext_i16_i32:545; CHECK-NEXT: .functype xor_sext_i16_i32 (i32, i32) -> (i32){{$}}546; CHECK: i32.atomic.rmw16.xor_u $push0=, 0($0), $1{{$}}547; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}548; CHECK-NEXT: return $pop1{{$}}549define i32 @xor_sext_i16_i32(ptr %p, i32 %v) {550 %t = trunc i32 %v to i16551 %old = atomicrmw xor ptr %p, i16 %t seq_cst552 %e = sext i16 %old to i32553 ret i32 %e554}555 556; CHECK-LABEL: xor_sext_i8_i64:557; CHECK-NEXT: .functype xor_sext_i8_i64 (i32, i64) -> (i64){{$}}558; CHECK: i64.atomic.rmw8.xor_u $push0=, 0($0), $1{{$}}559; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}560; CHECK-NEXT: return $pop1{{$}}561define i64 @xor_sext_i8_i64(ptr %p, i64 %v) {562 %t = trunc i64 %v to i8563 %old = atomicrmw xor ptr %p, i8 %t seq_cst564 %e = sext i8 %old to i64565 ret i64 %e566}567 568; CHECK-LABEL: xor_sext_i16_i64:569; CHECK-NEXT: .functype xor_sext_i16_i64 (i32, i64) -> (i64){{$}}570; CHECK: i64.atomic.rmw16.xor_u $push0=, 0($0), $1{{$}}571; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}572; CHECK-NEXT: return $pop1{{$}}573define i64 @xor_sext_i16_i64(ptr %p, i64 %v) {574 %t = trunc i64 %v to i16575 %old = atomicrmw xor ptr %p, i16 %t seq_cst576 %e = sext i16 %old to i64577 ret i64 %e578}579 580; 32->64 sext rmw gets selected as i32.atomic.rmw.xor, i64.extend_i32_s581; CHECK-LABEL: xor_sext_i32_i64:582; CHECK-NEXT: .functype xor_sext_i32_i64 (i32, i64) -> (i64){{$}}583; CHECK: i32.wrap_i64 $push0=, $1{{$}}584; CHECK: i32.atomic.rmw.xor $push1=, 0($0), $pop0{{$}}585; CHECK-NEXT: i64.extend_i32_s $push2=, $pop1{{$}}586; CHECK-NEXT: return $pop2{{$}}587define i64 @xor_sext_i32_i64(ptr %p, i64 %v) {588 %t = trunc i64 %v to i32589 %old = atomicrmw xor ptr %p, i32 %t seq_cst590 %e = sext i32 %old to i64591 ret i64 %e592}593 594; xchg595 596; CHECK-LABEL: xchg_sext_i8_i32:597; CHECK-NEXT: .functype xchg_sext_i8_i32 (i32, i32) -> (i32){{$}}598; CHECK: i32.atomic.rmw8.xchg_u $push0=, 0($0), $1{{$}}599; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}600; CHECK-NEXT: return $pop1{{$}}601define i32 @xchg_sext_i8_i32(ptr %p, i32 %v) {602 %t = trunc i32 %v to i8603 %old = atomicrmw xchg ptr %p, i8 %t seq_cst604 %e = sext i8 %old to i32605 ret i32 %e606}607 608; CHECK-LABEL: xchg_sext_i16_i32:609; CHECK-NEXT: .functype xchg_sext_i16_i32 (i32, i32) -> (i32){{$}}610; CHECK: i32.atomic.rmw16.xchg_u $push0=, 0($0), $1{{$}}611; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}612; CHECK-NEXT: return $pop1{{$}}613define i32 @xchg_sext_i16_i32(ptr %p, i32 %v) {614 %t = trunc i32 %v to i16615 %old = atomicrmw xchg ptr %p, i16 %t seq_cst616 %e = sext i16 %old to i32617 ret i32 %e618}619 620; CHECK-LABEL: xchg_sext_i8_i64:621; CHECK-NEXT: .functype xchg_sext_i8_i64 (i32, i64) -> (i64){{$}}622; CHECK: i64.atomic.rmw8.xchg_u $push0=, 0($0), $1{{$}}623; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}624; CHECK-NEXT: return $pop1{{$}}625define i64 @xchg_sext_i8_i64(ptr %p, i64 %v) {626 %t = trunc i64 %v to i8627 %old = atomicrmw xchg ptr %p, i8 %t seq_cst628 %e = sext i8 %old to i64629 ret i64 %e630}631 632; CHECK-LABEL: xchg_sext_i16_i64:633; CHECK-NEXT: .functype xchg_sext_i16_i64 (i32, i64) -> (i64){{$}}634; CHECK: i64.atomic.rmw16.xchg_u $push0=, 0($0), $1{{$}}635; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}636; CHECK-NEXT: return $pop1{{$}}637define i64 @xchg_sext_i16_i64(ptr %p, i64 %v) {638 %t = trunc i64 %v to i16639 %old = atomicrmw xchg ptr %p, i16 %t seq_cst640 %e = sext i16 %old to i64641 ret i64 %e642}643 644; 32->64 sext rmw gets selected as i32.atomic.rmw.xchg, i64.extend_i32_s645; CHECK-LABEL: xchg_sext_i32_i64:646; CHECK-NEXT: .functype xchg_sext_i32_i64 (i32, i64) -> (i64){{$}}647; CHECK: i32.wrap_i64 $push0=, $1{{$}}648; CHECK: i32.atomic.rmw.xchg $push1=, 0($0), $pop0{{$}}649; CHECK-NEXT: i64.extend_i32_s $push2=, $pop1{{$}}650; CHECK-NEXT: return $pop2{{$}}651define i64 @xchg_sext_i32_i64(ptr %p, i64 %v) {652 %t = trunc i64 %v to i32653 %old = atomicrmw xchg ptr %p, i32 %t seq_cst654 %e = sext i32 %old to i64655 ret i64 %e656}657 658; cmpxchg659 660; CHECK-LABEL: cmpxchg_sext_i8_i32:661; CHECK-NEXT: .functype cmpxchg_sext_i8_i32 (i32, i32, i32) -> (i32){{$}}662; CHECK: i32.atomic.rmw8.cmpxchg_u $push0=, 0($0), $1, $2{{$}}663; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}664; CHECK-NEXT: return $pop1{{$}}665define i32 @cmpxchg_sext_i8_i32(ptr %p, i32 %exp, i32 %new) {666 %exp_t = trunc i32 %exp to i8667 %new_t = trunc i32 %new to i8668 %pair = cmpxchg ptr %p, i8 %exp_t, i8 %new_t seq_cst seq_cst669 %old = extractvalue { i8, i1 } %pair, 0670 %e = sext i8 %old to i32671 ret i32 %e672}673 674; CHECK-LABEL: cmpxchg_sext_i16_i32:675; CHECK-NEXT: .functype cmpxchg_sext_i16_i32 (i32, i32, i32) -> (i32){{$}}676; CHECK: i32.atomic.rmw16.cmpxchg_u $push0=, 0($0), $1, $2{{$}}677; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}678; CHECK-NEXT: return $pop1{{$}}679define i32 @cmpxchg_sext_i16_i32(ptr %p, i32 %exp, i32 %new) {680 %exp_t = trunc i32 %exp to i16681 %new_t = trunc i32 %new to i16682 %pair = cmpxchg ptr %p, i16 %exp_t, i16 %new_t seq_cst seq_cst683 %old = extractvalue { i16, i1 } %pair, 0684 %e = sext i16 %old to i32685 ret i32 %e686}687 688; CHECK-LABEL: cmpxchg_sext_i8_i64:689; CHECK-NEXT: .functype cmpxchg_sext_i8_i64 (i32, i64, i64) -> (i64){{$}}690; CHECK: i64.atomic.rmw8.cmpxchg_u $push0=, 0($0), $1, $2{{$}}691; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}692; CHECK-NEXT: return $pop1{{$}}693define i64 @cmpxchg_sext_i8_i64(ptr %p, i64 %exp, i64 %new) {694 %exp_t = trunc i64 %exp to i8695 %new_t = trunc i64 %new to i8696 %pair = cmpxchg ptr %p, i8 %exp_t, i8 %new_t seq_cst seq_cst697 %old = extractvalue { i8, i1 } %pair, 0698 %e = sext i8 %old to i64699 ret i64 %e700}701 702; CHECK-LABEL: cmpxchg_sext_i16_i64:703; CHECK-NEXT: .functype cmpxchg_sext_i16_i64 (i32, i64, i64) -> (i64){{$}}704; CHECK: i64.atomic.rmw16.cmpxchg_u $push0=, 0($0), $1, $2{{$}}705; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}706; CHECK-NEXT: return $pop1{{$}}707define i64 @cmpxchg_sext_i16_i64(ptr %p, i64 %exp, i64 %new) {708 %exp_t = trunc i64 %exp to i16709 %new_t = trunc i64 %new to i16710 %pair = cmpxchg ptr %p, i16 %exp_t, i16 %new_t seq_cst seq_cst711 %old = extractvalue { i16, i1 } %pair, 0712 %e = sext i16 %old to i64713 ret i64 %e714}715 716; 32->64 sext rmw gets selected as i32.atomic.rmw.cmpxchg, i64.extend_i32_s717; CHECK-LABEL: cmpxchg_sext_i32_i64:718; CHECK-NEXT: .functype cmpxchg_sext_i32_i64 (i32, i64, i64) -> (i64){{$}}719; CHECK: i32.wrap_i64 $push1=, $1{{$}}720; CHECK-NEXT: i32.wrap_i64 $push0=, $2{{$}}721; CHECK-NEXT: i32.atomic.rmw.cmpxchg $push2=, 0($0), $pop1, $pop0{{$}}722; CHECK-NEXT: i64.extend_i32_s $push3=, $pop2{{$}}723; CHECK-NEXT: return $pop3{{$}}724define i64 @cmpxchg_sext_i32_i64(ptr %p, i64 %exp, i64 %new) {725 %exp_t = trunc i64 %exp to i32726 %new_t = trunc i64 %new to i32727 %pair = cmpxchg ptr %p, i32 %exp_t, i32 %new_t seq_cst seq_cst728 %old = extractvalue { i32, i1 } %pair, 0729 %e = sext i32 %old to i64730 ret i64 %e731}732 733; Unsupported instructions are expanded using cmpxchg with a loop.734; Here we take a nand as an example.735 736; nand737 738; CHECK-LABEL: nand_sext_i8_i32:739; CHECK-NEXT: .functype nand_sext_i8_i32 (i32, i32) -> (i32){{$}}740; CHECK: loop741; CHECK: i32.atomic.rmw8.cmpxchg_u742; CHECK: i32.extend8_s743define i32 @nand_sext_i8_i32(ptr %p, i32 %v) {744 %t = trunc i32 %v to i8745 %old = atomicrmw nand ptr %p, i8 %t seq_cst746 %e = sext i8 %old to i32747 ret i32 %e748}749 750; CHECK-LABEL: nand_sext_i16_i32:751; CHECK-NEXT: .functype nand_sext_i16_i32 (i32, i32) -> (i32){{$}}752; CHECK: loop753; CHECK: i32.atomic.rmw16.cmpxchg_u754; CHECK: i32.extend16_s755define i32 @nand_sext_i16_i32(ptr %p, i32 %v) {756 %t = trunc i32 %v to i16757 %old = atomicrmw nand ptr %p, i16 %t seq_cst758 %e = sext i16 %old to i32759 ret i32 %e760}761 762; FIXME Currently this cannot make use of i64.atomic.rmw8.cmpxchg_u763; CHECK-LABEL: nand_sext_i8_i64:764; CHECK-NEXT: .functype nand_sext_i8_i64 (i32, i64) -> (i64){{$}}765; CHECK: loop766; CHECK: i32.atomic.rmw8.cmpxchg_u767; CHECK: i64.extend_i32_u768; CHECK: i64.extend8_s769define i64 @nand_sext_i8_i64(ptr %p, i64 %v) {770 %t = trunc i64 %v to i8771 %old = atomicrmw nand ptr %p, i8 %t seq_cst772 %e = sext i8 %old to i64773 ret i64 %e774}775 776; FIXME Currently this cannot make use of i64.atomic.rmw16.cmpxchg_u777; CHECK-LABEL: nand_sext_i16_i64:778; CHECK-NEXT: .functype nand_sext_i16_i64 (i32, i64) -> (i64){{$}}779; CHECK: loop780; CHECK: i32.atomic.rmw16.cmpxchg_u781; CHECK: i64.extend_i32_u782; CHECK: i64.extend16_s783define i64 @nand_sext_i16_i64(ptr %p, i64 %v) {784 %t = trunc i64 %v to i16785 %old = atomicrmw nand ptr %p, i16 %t seq_cst786 %e = sext i16 %old to i64787 ret i64 %e788}789 790; 32->64 sext rmw gets selected as i32.atomic.rmw.nand, i64.extend_i32_s791; CHECK-LABEL: nand_sext_i32_i64:792; CHECK-NEXT: .functype nand_sext_i32_i64 (i32, i64) -> (i64){{$}}793; CHECK: loop794; CHECK: i32.atomic.rmw.cmpxchg795; CHECK: i64.extend_i32_s796define i64 @nand_sext_i32_i64(ptr %p, i64 %v) {797 %t = trunc i64 %v to i32798 %old = atomicrmw nand ptr %p, i32 %t seq_cst799 %e = sext i32 %old to i64800 ret i64 %e801}802 803;===----------------------------------------------------------------------------804; Atomic truncating & zero-extending RMWs805;===----------------------------------------------------------------------------806 807; add808 809; CHECK-LABEL: add_zext_i8_i32:810; CHECK-NEXT: .functype add_zext_i8_i32 (i32, i32) -> (i32){{$}}811; CHECK: i32.atomic.rmw8.add_u $push0=, 0($0), $1{{$}}812; CHECK-NEXT: return $pop0{{$}}813define i32 @add_zext_i8_i32(ptr %p, i32 %v) {814 %t = trunc i32 %v to i8815 %old = atomicrmw add ptr %p, i8 %t seq_cst816 %e = zext i8 %old to i32817 ret i32 %e818}819 820; CHECK-LABEL: add_zext_i16_i32:821; CHECK-NEXT: .functype add_zext_i16_i32 (i32, i32) -> (i32){{$}}822; CHECK: i32.atomic.rmw16.add_u $push0=, 0($0), $1{{$}}823; CHECK-NEXT: return $pop0{{$}}824define i32 @add_zext_i16_i32(ptr %p, i32 %v) {825 %t = trunc i32 %v to i16826 %old = atomicrmw add ptr %p, i16 %t seq_cst827 %e = zext i16 %old to i32828 ret i32 %e829}830 831; CHECK-LABEL: add_zext_i8_i64:832; CHECK-NEXT: .functype add_zext_i8_i64 (i32, i64) -> (i64){{$}}833; CHECK: i64.atomic.rmw8.add_u $push0=, 0($0), $1{{$}}834; CHECK-NEXT: return $pop0{{$}}835define i64 @add_zext_i8_i64(ptr %p, i64 %v) {836 %t = trunc i64 %v to i8837 %old = atomicrmw add ptr %p, i8 %t seq_cst838 %e = zext i8 %old to i64839 ret i64 %e840}841 842; CHECK-LABEL: add_zext_i16_i64:843; CHECK-NEXT: .functype add_zext_i16_i64 (i32, i64) -> (i64){{$}}844; CHECK: i64.atomic.rmw16.add_u $push0=, 0($0), $1{{$}}845; CHECK-NEXT: return $pop0{{$}}846define i64 @add_zext_i16_i64(ptr %p, i64 %v) {847 %t = trunc i64 %v to i16848 %old = atomicrmw add ptr %p, i16 %t seq_cst849 %e = zext i16 %old to i64850 ret i64 %e851}852 853; CHECK-LABEL: add_zext_i32_i64:854; CHECK-NEXT: .functype add_zext_i32_i64 (i32, i64) -> (i64){{$}}855; CHECK: i64.atomic.rmw32.add_u $push0=, 0($0), $1{{$}}856; CHECK-NEXT: return $pop0{{$}}857define i64 @add_zext_i32_i64(ptr %p, i64 %v) {858 %t = trunc i64 %v to i32859 %old = atomicrmw add ptr %p, i32 %t seq_cst860 %e = zext i32 %old to i64861 ret i64 %e862}863 864; sub865 866; CHECK-LABEL: sub_zext_i8_i32:867; CHECK-NEXT: .functype sub_zext_i8_i32 (i32, i32) -> (i32){{$}}868; CHECK: i32.atomic.rmw8.sub_u $push0=, 0($0), $1{{$}}869; CHECK-NEXT: return $pop0{{$}}870define i32 @sub_zext_i8_i32(ptr %p, i32 %v) {871 %t = trunc i32 %v to i8872 %old = atomicrmw sub ptr %p, i8 %t seq_cst873 %e = zext i8 %old to i32874 ret i32 %e875}876 877; CHECK-LABEL: sub_zext_i16_i32:878; CHECK-NEXT: .functype sub_zext_i16_i32 (i32, i32) -> (i32){{$}}879; CHECK: i32.atomic.rmw16.sub_u $push0=, 0($0), $1{{$}}880; CHECK-NEXT: return $pop0{{$}}881define i32 @sub_zext_i16_i32(ptr %p, i32 %v) {882 %t = trunc i32 %v to i16883 %old = atomicrmw sub ptr %p, i16 %t seq_cst884 %e = zext i16 %old to i32885 ret i32 %e886}887 888; CHECK-LABEL: sub_zext_i8_i64:889; CHECK-NEXT: .functype sub_zext_i8_i64 (i32, i64) -> (i64){{$}}890; CHECK: i64.atomic.rmw8.sub_u $push0=, 0($0), $1{{$}}891; CHECK-NEXT: return $pop0{{$}}892define i64 @sub_zext_i8_i64(ptr %p, i64 %v) {893 %t = trunc i64 %v to i8894 %old = atomicrmw sub ptr %p, i8 %t seq_cst895 %e = zext i8 %old to i64896 ret i64 %e897}898 899; CHECK-LABEL: sub_zext_i16_i64:900; CHECK-NEXT: .functype sub_zext_i16_i64 (i32, i64) -> (i64){{$}}901; CHECK: i64.atomic.rmw16.sub_u $push0=, 0($0), $1{{$}}902; CHECK-NEXT: return $pop0{{$}}903define i64 @sub_zext_i16_i64(ptr %p, i64 %v) {904 %t = trunc i64 %v to i16905 %old = atomicrmw sub ptr %p, i16 %t seq_cst906 %e = zext i16 %old to i64907 ret i64 %e908}909 910; CHECK-LABEL: sub_zext_i32_i64:911; CHECK-NEXT: .functype sub_zext_i32_i64 (i32, i64) -> (i64){{$}}912; CHECK: i64.atomic.rmw32.sub_u $push0=, 0($0), $1{{$}}913; CHECK-NEXT: return $pop0{{$}}914define i64 @sub_zext_i32_i64(ptr %p, i64 %v) {915 %t = trunc i64 %v to i32916 %old = atomicrmw sub ptr %p, i32 %t seq_cst917 %e = zext i32 %old to i64918 ret i64 %e919}920 921; and922 923; CHECK-LABEL: and_zext_i8_i32:924; CHECK-NEXT: .functype and_zext_i8_i32 (i32, i32) -> (i32){{$}}925; CHECK: i32.atomic.rmw8.and_u $push0=, 0($0), $1{{$}}926; CHECK-NEXT: return $pop0{{$}}927define i32 @and_zext_i8_i32(ptr %p, i32 %v) {928 %t = trunc i32 %v to i8929 %old = atomicrmw and ptr %p, i8 %t seq_cst930 %e = zext i8 %old to i32931 ret i32 %e932}933 934; CHECK-LABEL: and_zext_i16_i32:935; CHECK-NEXT: .functype and_zext_i16_i32 (i32, i32) -> (i32){{$}}936; CHECK: i32.atomic.rmw16.and_u $push0=, 0($0), $1{{$}}937; CHECK-NEXT: return $pop0{{$}}938define i32 @and_zext_i16_i32(ptr %p, i32 %v) {939 %t = trunc i32 %v to i16940 %old = atomicrmw and ptr %p, i16 %t seq_cst941 %e = zext i16 %old to i32942 ret i32 %e943}944 945; CHECK-LABEL: and_zext_i8_i64:946; CHECK-NEXT: .functype and_zext_i8_i64 (i32, i64) -> (i64){{$}}947; CHECK: i64.atomic.rmw8.and_u $push0=, 0($0), $1{{$}}948; CHECK-NEXT: return $pop0{{$}}949define i64 @and_zext_i8_i64(ptr %p, i64 %v) {950 %t = trunc i64 %v to i8951 %old = atomicrmw and ptr %p, i8 %t seq_cst952 %e = zext i8 %old to i64953 ret i64 %e954}955 956; CHECK-LABEL: and_zext_i16_i64:957; CHECK-NEXT: .functype and_zext_i16_i64 (i32, i64) -> (i64){{$}}958; CHECK: i64.atomic.rmw16.and_u $push0=, 0($0), $1{{$}}959; CHECK-NEXT: return $pop0{{$}}960define i64 @and_zext_i16_i64(ptr %p, i64 %v) {961 %t = trunc i64 %v to i16962 %old = atomicrmw and ptr %p, i16 %t seq_cst963 %e = zext i16 %old to i64964 ret i64 %e965}966 967; CHECK-LABEL: and_zext_i32_i64:968; CHECK-NEXT: .functype and_zext_i32_i64 (i32, i64) -> (i64){{$}}969; CHECK: i64.atomic.rmw32.and_u $push0=, 0($0), $1{{$}}970; CHECK-NEXT: return $pop0{{$}}971define i64 @and_zext_i32_i64(ptr %p, i64 %v) {972 %t = trunc i64 %v to i32973 %old = atomicrmw and ptr %p, i32 %t seq_cst974 %e = zext i32 %old to i64975 ret i64 %e976}977 978; or979 980; CHECK-LABEL: or_zext_i8_i32:981; CHECK-NEXT: .functype or_zext_i8_i32 (i32, i32) -> (i32){{$}}982; CHECK: i32.atomic.rmw8.or_u $push0=, 0($0), $1{{$}}983; CHECK-NEXT: return $pop0{{$}}984define i32 @or_zext_i8_i32(ptr %p, i32 %v) {985 %t = trunc i32 %v to i8986 %old = atomicrmw or ptr %p, i8 %t seq_cst987 %e = zext i8 %old to i32988 ret i32 %e989}990 991; CHECK-LABEL: or_zext_i16_i32:992; CHECK-NEXT: .functype or_zext_i16_i32 (i32, i32) -> (i32){{$}}993; CHECK: i32.atomic.rmw16.or_u $push0=, 0($0), $1{{$}}994; CHECK-NEXT: return $pop0{{$}}995define i32 @or_zext_i16_i32(ptr %p, i32 %v) {996 %t = trunc i32 %v to i16997 %old = atomicrmw or ptr %p, i16 %t seq_cst998 %e = zext i16 %old to i32999 ret i32 %e1000}1001 1002; CHECK-LABEL: or_zext_i8_i64:1003; CHECK-NEXT: .functype or_zext_i8_i64 (i32, i64) -> (i64){{$}}1004; CHECK: i64.atomic.rmw8.or_u $push0=, 0($0), $1{{$}}1005; CHECK-NEXT: return $pop0{{$}}1006define i64 @or_zext_i8_i64(ptr %p, i64 %v) {1007 %t = trunc i64 %v to i81008 %old = atomicrmw or ptr %p, i8 %t seq_cst1009 %e = zext i8 %old to i641010 ret i64 %e1011}1012 1013; CHECK-LABEL: or_zext_i16_i64:1014; CHECK-NEXT: .functype or_zext_i16_i64 (i32, i64) -> (i64){{$}}1015; CHECK: i64.atomic.rmw16.or_u $push0=, 0($0), $1{{$}}1016; CHECK-NEXT: return $pop0{{$}}1017define i64 @or_zext_i16_i64(ptr %p, i64 %v) {1018 %t = trunc i64 %v to i161019 %old = atomicrmw or ptr %p, i16 %t seq_cst1020 %e = zext i16 %old to i641021 ret i64 %e1022}1023 1024; CHECK-LABEL: or_zext_i32_i64:1025; CHECK-NEXT: .functype or_zext_i32_i64 (i32, i64) -> (i64){{$}}1026; CHECK: i64.atomic.rmw32.or_u $push0=, 0($0), $1{{$}}1027; CHECK-NEXT: return $pop0{{$}}1028define i64 @or_zext_i32_i64(ptr %p, i64 %v) {1029 %t = trunc i64 %v to i321030 %old = atomicrmw or ptr %p, i32 %t seq_cst1031 %e = zext i32 %old to i641032 ret i64 %e1033}1034 1035; xor1036 1037; CHECK-LABEL: xor_zext_i8_i32:1038; CHECK-NEXT: .functype xor_zext_i8_i32 (i32, i32) -> (i32){{$}}1039; CHECK: i32.atomic.rmw8.xor_u $push0=, 0($0), $1{{$}}1040; CHECK-NEXT: return $pop0{{$}}1041define i32 @xor_zext_i8_i32(ptr %p, i32 %v) {1042 %t = trunc i32 %v to i81043 %old = atomicrmw xor ptr %p, i8 %t seq_cst1044 %e = zext i8 %old to i321045 ret i32 %e1046}1047 1048; CHECK-LABEL: xor_zext_i16_i32:1049; CHECK-NEXT: .functype xor_zext_i16_i32 (i32, i32) -> (i32){{$}}1050; CHECK: i32.atomic.rmw16.xor_u $push0=, 0($0), $1{{$}}1051; CHECK-NEXT: return $pop0{{$}}1052define i32 @xor_zext_i16_i32(ptr %p, i32 %v) {1053 %t = trunc i32 %v to i161054 %old = atomicrmw xor ptr %p, i16 %t seq_cst1055 %e = zext i16 %old to i321056 ret i32 %e1057}1058 1059; CHECK-LABEL: xor_zext_i8_i64:1060; CHECK-NEXT: .functype xor_zext_i8_i64 (i32, i64) -> (i64){{$}}1061; CHECK: i64.atomic.rmw8.xor_u $push0=, 0($0), $1{{$}}1062; CHECK-NEXT: return $pop0{{$}}1063define i64 @xor_zext_i8_i64(ptr %p, i64 %v) {1064 %t = trunc i64 %v to i81065 %old = atomicrmw xor ptr %p, i8 %t seq_cst1066 %e = zext i8 %old to i641067 ret i64 %e1068}1069 1070; CHECK-LABEL: xor_zext_i16_i64:1071; CHECK-NEXT: .functype xor_zext_i16_i64 (i32, i64) -> (i64){{$}}1072; CHECK: i64.atomic.rmw16.xor_u $push0=, 0($0), $1{{$}}1073; CHECK-NEXT: return $pop0{{$}}1074define i64 @xor_zext_i16_i64(ptr %p, i64 %v) {1075 %t = trunc i64 %v to i161076 %old = atomicrmw xor ptr %p, i16 %t seq_cst1077 %e = zext i16 %old to i641078 ret i64 %e1079}1080 1081; CHECK-LABEL: xor_zext_i32_i64:1082; CHECK-NEXT: .functype xor_zext_i32_i64 (i32, i64) -> (i64){{$}}1083; CHECK: i64.atomic.rmw32.xor_u $push0=, 0($0), $1{{$}}1084; CHECK-NEXT: return $pop0{{$}}1085define i64 @xor_zext_i32_i64(ptr %p, i64 %v) {1086 %t = trunc i64 %v to i321087 %old = atomicrmw xor ptr %p, i32 %t seq_cst1088 %e = zext i32 %old to i641089 ret i64 %e1090}1091 1092; xchg1093 1094; CHECK-LABEL: xchg_zext_i8_i32:1095; CHECK-NEXT: .functype xchg_zext_i8_i32 (i32, i32) -> (i32){{$}}1096; CHECK: i32.atomic.rmw8.xchg_u $push0=, 0($0), $1{{$}}1097; CHECK-NEXT: return $pop0{{$}}1098define i32 @xchg_zext_i8_i32(ptr %p, i32 %v) {1099 %t = trunc i32 %v to i81100 %old = atomicrmw xchg ptr %p, i8 %t seq_cst1101 %e = zext i8 %old to i321102 ret i32 %e1103}1104 1105; CHECK-LABEL: xchg_zext_i16_i32:1106; CHECK-NEXT: .functype xchg_zext_i16_i32 (i32, i32) -> (i32){{$}}1107; CHECK: i32.atomic.rmw16.xchg_u $push0=, 0($0), $1{{$}}1108; CHECK-NEXT: return $pop0{{$}}1109define i32 @xchg_zext_i16_i32(ptr %p, i32 %v) {1110 %t = trunc i32 %v to i161111 %old = atomicrmw xchg ptr %p, i16 %t seq_cst1112 %e = zext i16 %old to i321113 ret i32 %e1114}1115 1116; CHECK-LABEL: xchg_zext_i8_i64:1117; CHECK-NEXT: .functype xchg_zext_i8_i64 (i32, i64) -> (i64){{$}}1118; CHECK: i64.atomic.rmw8.xchg_u $push0=, 0($0), $1{{$}}1119; CHECK-NEXT: return $pop0{{$}}1120define i64 @xchg_zext_i8_i64(ptr %p, i64 %v) {1121 %t = trunc i64 %v to i81122 %old = atomicrmw xchg ptr %p, i8 %t seq_cst1123 %e = zext i8 %old to i641124 ret i64 %e1125}1126 1127; CHECK-LABEL: xchg_zext_i16_i64:1128; CHECK-NEXT: .functype xchg_zext_i16_i64 (i32, i64) -> (i64){{$}}1129; CHECK: i64.atomic.rmw16.xchg_u $push0=, 0($0), $1{{$}}1130; CHECK-NEXT: return $pop0{{$}}1131define i64 @xchg_zext_i16_i64(ptr %p, i64 %v) {1132 %t = trunc i64 %v to i161133 %old = atomicrmw xchg ptr %p, i16 %t seq_cst1134 %e = zext i16 %old to i641135 ret i64 %e1136}1137 1138; CHECK-LABEL: xchg_zext_i32_i64:1139; CHECK-NEXT: .functype xchg_zext_i32_i64 (i32, i64) -> (i64){{$}}1140; CHECK: i64.atomic.rmw32.xchg_u $push0=, 0($0), $1{{$}}1141; CHECK-NEXT: return $pop0{{$}}1142define i64 @xchg_zext_i32_i64(ptr %p, i64 %v) {1143 %t = trunc i64 %v to i321144 %old = atomicrmw xchg ptr %p, i32 %t seq_cst1145 %e = zext i32 %old to i641146 ret i64 %e1147}1148 1149; cmpxchg1150 1151; CHECK-LABEL: cmpxchg_zext_i8_i32:1152; CHECK-NEXT: .functype cmpxchg_zext_i8_i32 (i32, i32, i32) -> (i32){{$}}1153; CHECK: i32.atomic.rmw8.cmpxchg_u $push0=, 0($0), $1, $2{{$}}1154; CHECK-NEXT: return $pop0{{$}}1155define i32 @cmpxchg_zext_i8_i32(ptr %p, i32 %exp, i32 %new) {1156 %exp_t = trunc i32 %exp to i81157 %new_t = trunc i32 %new to i81158 %pair = cmpxchg ptr %p, i8 %exp_t, i8 %new_t seq_cst seq_cst1159 %old = extractvalue { i8, i1 } %pair, 01160 %e = zext i8 %old to i321161 ret i32 %e1162}1163 1164; CHECK-LABEL: cmpxchg_zext_i16_i32:1165; CHECK-NEXT: .functype cmpxchg_zext_i16_i32 (i32, i32, i32) -> (i32){{$}}1166; CHECK: i32.atomic.rmw16.cmpxchg_u $push0=, 0($0), $1, $2{{$}}1167; CHECK-NEXT: return $pop0{{$}}1168define i32 @cmpxchg_zext_i16_i32(ptr %p, i32 %exp, i32 %new) {1169 %exp_t = trunc i32 %exp to i161170 %new_t = trunc i32 %new to i161171 %pair = cmpxchg ptr %p, i16 %exp_t, i16 %new_t seq_cst seq_cst1172 %old = extractvalue { i16, i1 } %pair, 01173 %e = zext i16 %old to i321174 ret i32 %e1175}1176 1177; CHECK-LABEL: cmpxchg_zext_i8_i64:1178; CHECK-NEXT: .functype cmpxchg_zext_i8_i64 (i32, i64, i64) -> (i64){{$}}1179; CHECK: i64.atomic.rmw8.cmpxchg_u $push0=, 0($0), $1, $2{{$}}1180; CHECK-NEXT: return $pop0{{$}}1181define i64 @cmpxchg_zext_i8_i64(ptr %p, i64 %exp, i64 %new) {1182 %exp_t = trunc i64 %exp to i81183 %new_t = trunc i64 %new to i81184 %pair = cmpxchg ptr %p, i8 %exp_t, i8 %new_t seq_cst seq_cst1185 %old = extractvalue { i8, i1 } %pair, 01186 %e = zext i8 %old to i641187 ret i64 %e1188}1189 1190; CHECK-LABEL: cmpxchg_zext_i16_i64:1191; CHECK-NEXT: .functype cmpxchg_zext_i16_i64 (i32, i64, i64) -> (i64){{$}}1192; CHECK: i64.atomic.rmw16.cmpxchg_u $push0=, 0($0), $1, $2{{$}}1193; CHECK-NEXT: return $pop0{{$}}1194define i64 @cmpxchg_zext_i16_i64(ptr %p, i64 %exp, i64 %new) {1195 %exp_t = trunc i64 %exp to i161196 %new_t = trunc i64 %new to i161197 %pair = cmpxchg ptr %p, i16 %exp_t, i16 %new_t seq_cst seq_cst1198 %old = extractvalue { i16, i1 } %pair, 01199 %e = zext i16 %old to i641200 ret i64 %e1201}1202 1203; CHECK-LABEL: cmpxchg_zext_i32_i64:1204; CHECK-NEXT: .functype cmpxchg_zext_i32_i64 (i32, i64, i64) -> (i64){{$}}1205; CHECK: i64.atomic.rmw32.cmpxchg_u $push0=, 0($0), $1, $2{{$}}1206; CHECK-NEXT: return $pop0{{$}}1207define i64 @cmpxchg_zext_i32_i64(ptr %p, i64 %exp, i64 %new) {1208 %exp_t = trunc i64 %exp to i321209 %new_t = trunc i64 %new to i321210 %pair = cmpxchg ptr %p, i32 %exp_t, i32 %new_t seq_cst seq_cst1211 %old = extractvalue { i32, i1 } %pair, 01212 %e = zext i32 %old to i641213 ret i64 %e1214}1215 1216; Unsupported instructions are expanded using cmpxchg with a loop.1217; Here we take a nand as an example.1218 1219; nand1220 1221; CHECK-LABEL: nand_zext_i8_i32:1222; CHECK-NEXT: .functype nand_zext_i8_i32 (i32, i32) -> (i32){{$}}1223; CHECK: loop1224; CHECK: i32.atomic.rmw8.cmpxchg_u1225define i32 @nand_zext_i8_i32(ptr %p, i32 %v) {1226 %t = trunc i32 %v to i81227 %old = atomicrmw nand ptr %p, i8 %t seq_cst1228 %e = zext i8 %old to i321229 ret i32 %e1230}1231 1232; CHECK-LABEL: nand_zext_i16_i32:1233; CHECK-NEXT: .functype nand_zext_i16_i32 (i32, i32) -> (i32){{$}}1234; CHECK: loop1235; CHECK: i32.atomic.rmw16.cmpxchg_u1236define i32 @nand_zext_i16_i32(ptr %p, i32 %v) {1237 %t = trunc i32 %v to i161238 %old = atomicrmw nand ptr %p, i16 %t seq_cst1239 %e = zext i16 %old to i321240 ret i32 %e1241}1242 1243; FIXME Currently this cannot make use of i64.atomic.rmw8.cmpxchg_u1244; CHECK-LABEL: nand_zext_i8_i64:1245; CHECK-NEXT: .functype nand_zext_i8_i64 (i32, i64) -> (i64){{$}}1246; CHECK: loop1247; CHECK: i32.atomic.rmw8.cmpxchg_u1248; CHECK: i64.extend_i32_u1249define i64 @nand_zext_i8_i64(ptr %p, i64 %v) {1250 %t = trunc i64 %v to i81251 %old = atomicrmw nand ptr %p, i8 %t seq_cst1252 %e = zext i8 %old to i641253 ret i64 %e1254}1255 1256; FIXME Currently this cannot make use of i64.atomic.rmw16.cmpxchg_u1257; CHECK-LABEL: nand_zext_i16_i64:1258; CHECK-NEXT: .functype nand_zext_i16_i64 (i32, i64) -> (i64){{$}}1259; CHECK: loop1260; CHECK: i32.atomic.rmw16.cmpxchg_u1261; CHECK: i64.extend_i32_u1262define i64 @nand_zext_i16_i64(ptr %p, i64 %v) {1263 %t = trunc i64 %v to i161264 %old = atomicrmw nand ptr %p, i16 %t seq_cst1265 %e = zext i16 %old to i641266 ret i64 %e1267}1268 1269; FIXME Currently this cannot make use of i64.atomic.rmw32.cmpxchg_u1270; CHECK-LABEL: nand_zext_i32_i64:1271; CHECK-NEXT: .functype nand_zext_i32_i64 (i32, i64) -> (i64){{$}}1272; CHECK: loop1273; CHECK: i32.atomic.rmw.cmpxchg1274; CHECK: i64.extend_i32_u1275define i64 @nand_zext_i32_i64(ptr %p, i64 %v) {1276 %t = trunc i64 %v to i321277 %old = atomicrmw nand ptr %p, i32 %t seq_cst1278 %e = zext i32 %old to i641279 ret i64 %e1280}1281