brintos

brintos / llvm-project-archived public Read only

0
0
Text · 39.7 KiB · 047147c Raw
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