1*0b57cec5SDimitry Andric// WebAssemblyInstrAtomics.td-WebAssembly Atomic codegen support-*- tablegen -*- 2*0b57cec5SDimitry Andric// 3*0b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric// 7*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric/// 9*0b57cec5SDimitry Andric/// \file 10*0b57cec5SDimitry Andric/// WebAssembly Atomic operand code-gen constructs. 11*0b57cec5SDimitry Andric/// 12*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andriclet UseNamedOperandTable = 1 in 15*0b57cec5SDimitry Andricmulticlass ATOMIC_I<dag oops_r, dag iops_r, dag oops_s, dag iops_s, 16*0b57cec5SDimitry Andric list<dag> pattern_r, string asmstr_r = "", 17*0b57cec5SDimitry Andric string asmstr_s = "", bits<32> atomic_op = -1> { 18*0b57cec5SDimitry Andric defm "" : I<oops_r, iops_r, oops_s, iops_s, pattern_r, asmstr_r, asmstr_s, 19*0b57cec5SDimitry Andric !or(0xfe00, !and(0xff, atomic_op))>, 20*0b57cec5SDimitry Andric Requires<[HasAtomics]>; 21*0b57cec5SDimitry Andric} 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andricmulticlass ATOMIC_NRI<dag oops, dag iops, list<dag> pattern, string asmstr = "", 24*0b57cec5SDimitry Andric bits<32> atomic_op = -1> { 25*0b57cec5SDimitry Andric defm "" : NRI<oops, iops, pattern, asmstr, 26*0b57cec5SDimitry Andric !or(0xfe00, !and(0xff, atomic_op))>, 27*0b57cec5SDimitry Andric Requires<[HasAtomics]>; 28*0b57cec5SDimitry Andric} 29*0b57cec5SDimitry Andric 30*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 31*0b57cec5SDimitry Andric// Atomic wait / notify 32*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andriclet hasSideEffects = 1 in { 35*0b57cec5SDimitry Andricdefm ATOMIC_NOTIFY : 36*0b57cec5SDimitry Andric ATOMIC_I<(outs I32:$dst), 37*0b57cec5SDimitry Andric (ins P2Align:$p2align, offset32_op:$off, I32:$addr, I32:$count), 38*0b57cec5SDimitry Andric (outs), (ins P2Align:$p2align, offset32_op:$off), [], 39*0b57cec5SDimitry Andric "atomic.notify \t$dst, ${off}(${addr})${p2align}, $count", 40*0b57cec5SDimitry Andric "atomic.notify \t${off}${p2align}", 0x00>; 41*0b57cec5SDimitry Andriclet mayLoad = 1 in { 42*0b57cec5SDimitry Andricdefm ATOMIC_WAIT_I32 : 43*0b57cec5SDimitry Andric ATOMIC_I<(outs I32:$dst), 44*0b57cec5SDimitry Andric (ins P2Align:$p2align, offset32_op:$off, I32:$addr, I32:$exp, 45*0b57cec5SDimitry Andric I64:$timeout), 46*0b57cec5SDimitry Andric (outs), (ins P2Align:$p2align, offset32_op:$off), [], 47*0b57cec5SDimitry Andric "i32.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout", 48*0b57cec5SDimitry Andric "i32.atomic.wait \t${off}${p2align}", 0x01>; 49*0b57cec5SDimitry Andricdefm ATOMIC_WAIT_I64 : 50*0b57cec5SDimitry Andric ATOMIC_I<(outs I32:$dst), 51*0b57cec5SDimitry Andric (ins P2Align:$p2align, offset32_op:$off, I32:$addr, I64:$exp, 52*0b57cec5SDimitry Andric I64:$timeout), 53*0b57cec5SDimitry Andric (outs), (ins P2Align:$p2align, offset32_op:$off), [], 54*0b57cec5SDimitry Andric "i64.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout", 55*0b57cec5SDimitry Andric "i64.atomic.wait \t${off}${p2align}", 0x02>; 56*0b57cec5SDimitry Andric} // mayLoad = 1 57*0b57cec5SDimitry Andric} // hasSideEffects = 1 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andriclet Predicates = [HasAtomics] in { 60*0b57cec5SDimitry Andric// Select notifys with no constant offset. 61*0b57cec5SDimitry Andricdef NotifyPatNoOffset : 62*0b57cec5SDimitry Andric Pat<(i32 (int_wasm_atomic_notify I32:$addr, I32:$count)), 63*0b57cec5SDimitry Andric (ATOMIC_NOTIFY 0, 0, I32:$addr, I32:$count)>; 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric// Select notifys with a constant offset. 66*0b57cec5SDimitry Andric 67*0b57cec5SDimitry Andric// Pattern with address + immediate offset 68*0b57cec5SDimitry Andricclass NotifyPatImmOff<PatFrag operand> : 69*0b57cec5SDimitry Andric Pat<(i32 (int_wasm_atomic_notify (operand I32:$addr, imm:$off), I32:$count)), 70*0b57cec5SDimitry Andric (ATOMIC_NOTIFY 0, imm:$off, I32:$addr, I32:$count)>; 71*0b57cec5SDimitry Andricdef : NotifyPatImmOff<regPlusImm>; 72*0b57cec5SDimitry Andricdef : NotifyPatImmOff<or_is_add>; 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andricdef NotifyPatGlobalAddr : 75*0b57cec5SDimitry Andric Pat<(i32 (int_wasm_atomic_notify (regPlusGA I32:$addr, 76*0b57cec5SDimitry Andric (WebAssemblywrapper tglobaladdr:$off)), 77*0b57cec5SDimitry Andric I32:$count)), 78*0b57cec5SDimitry Andric (ATOMIC_NOTIFY 0, tglobaladdr:$off, I32:$addr, I32:$count)>; 79*0b57cec5SDimitry Andric 80*0b57cec5SDimitry Andric// Select notifys with just a constant offset. 81*0b57cec5SDimitry Andricdef NotifyPatOffsetOnly : 82*0b57cec5SDimitry Andric Pat<(i32 (int_wasm_atomic_notify imm:$off, I32:$count)), 83*0b57cec5SDimitry Andric (ATOMIC_NOTIFY 0, imm:$off, (CONST_I32 0), I32:$count)>; 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andricdef NotifyPatGlobalAddrOffOnly : 86*0b57cec5SDimitry Andric Pat<(i32 (int_wasm_atomic_notify (WebAssemblywrapper tglobaladdr:$off), 87*0b57cec5SDimitry Andric I32:$count)), 88*0b57cec5SDimitry Andric (ATOMIC_NOTIFY 0, tglobaladdr:$off, (CONST_I32 0), I32:$count)>; 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric// Select waits with no constant offset. 91*0b57cec5SDimitry Andricclass WaitPatNoOffset<ValueType ty, Intrinsic kind, NI inst> : 92*0b57cec5SDimitry Andric Pat<(i32 (kind I32:$addr, ty:$exp, I64:$timeout)), 93*0b57cec5SDimitry Andric (inst 0, 0, I32:$addr, ty:$exp, I64:$timeout)>; 94*0b57cec5SDimitry Andricdef : WaitPatNoOffset<i32, int_wasm_atomic_wait_i32, ATOMIC_WAIT_I32>; 95*0b57cec5SDimitry Andricdef : WaitPatNoOffset<i64, int_wasm_atomic_wait_i64, ATOMIC_WAIT_I64>; 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric// Select waits with a constant offset. 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric// Pattern with address + immediate offset 100*0b57cec5SDimitry Andricclass WaitPatImmOff<ValueType ty, Intrinsic kind, PatFrag operand, NI inst> : 101*0b57cec5SDimitry Andric Pat<(i32 (kind (operand I32:$addr, imm:$off), ty:$exp, I64:$timeout)), 102*0b57cec5SDimitry Andric (inst 0, imm:$off, I32:$addr, ty:$exp, I64:$timeout)>; 103*0b57cec5SDimitry Andricdef : WaitPatImmOff<i32, int_wasm_atomic_wait_i32, regPlusImm, ATOMIC_WAIT_I32>; 104*0b57cec5SDimitry Andricdef : WaitPatImmOff<i32, int_wasm_atomic_wait_i32, or_is_add, ATOMIC_WAIT_I32>; 105*0b57cec5SDimitry Andricdef : WaitPatImmOff<i64, int_wasm_atomic_wait_i64, regPlusImm, ATOMIC_WAIT_I64>; 106*0b57cec5SDimitry Andricdef : WaitPatImmOff<i64, int_wasm_atomic_wait_i64, or_is_add, ATOMIC_WAIT_I64>; 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andricclass WaitPatGlobalAddr<ValueType ty, Intrinsic kind, NI inst> : 109*0b57cec5SDimitry Andric Pat<(i32 (kind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)), 110*0b57cec5SDimitry Andric ty:$exp, I64:$timeout)), 111*0b57cec5SDimitry Andric (inst 0, tglobaladdr:$off, I32:$addr, ty:$exp, I64:$timeout)>; 112*0b57cec5SDimitry Andricdef : WaitPatGlobalAddr<i32, int_wasm_atomic_wait_i32, ATOMIC_WAIT_I32>; 113*0b57cec5SDimitry Andricdef : WaitPatGlobalAddr<i64, int_wasm_atomic_wait_i64, ATOMIC_WAIT_I64>; 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric// Select wait_i32, ATOMIC_WAIT_I32s with just a constant offset. 116*0b57cec5SDimitry Andricclass WaitPatOffsetOnly<ValueType ty, Intrinsic kind, NI inst> : 117*0b57cec5SDimitry Andric Pat<(i32 (kind imm:$off, ty:$exp, I64:$timeout)), 118*0b57cec5SDimitry Andric (inst 0, imm:$off, (CONST_I32 0), ty:$exp, I64:$timeout)>; 119*0b57cec5SDimitry Andricdef : WaitPatOffsetOnly<i32, int_wasm_atomic_wait_i32, ATOMIC_WAIT_I32>; 120*0b57cec5SDimitry Andricdef : WaitPatOffsetOnly<i64, int_wasm_atomic_wait_i64, ATOMIC_WAIT_I64>; 121*0b57cec5SDimitry Andric 122*0b57cec5SDimitry Andricclass WaitPatGlobalAddrOffOnly<ValueType ty, Intrinsic kind, NI inst> : 123*0b57cec5SDimitry Andric Pat<(i32 (kind (WebAssemblywrapper tglobaladdr:$off), ty:$exp, I64:$timeout)), 124*0b57cec5SDimitry Andric (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$exp, I64:$timeout)>; 125*0b57cec5SDimitry Andricdef : WaitPatGlobalAddrOffOnly<i32, int_wasm_atomic_wait_i32, ATOMIC_WAIT_I32>; 126*0b57cec5SDimitry Andricdef : WaitPatGlobalAddrOffOnly<i64, int_wasm_atomic_wait_i64, ATOMIC_WAIT_I64>; 127*0b57cec5SDimitry Andric} // Predicates = [HasAtomics] 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 130*0b57cec5SDimitry Andric// Atomic loads 131*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 132*0b57cec5SDimitry Andric 133*0b57cec5SDimitry Andricmulticlass AtomicLoad<WebAssemblyRegClass rc, string name, int atomic_op> { 134*0b57cec5SDimitry Andric defm "" : WebAssemblyLoad<rc, name, !or(0xfe00, !and(0xff, atomic_op))>, 135*0b57cec5SDimitry Andric Requires<[HasAtomics]>; 136*0b57cec5SDimitry Andric} 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andricdefm ATOMIC_LOAD_I32 : AtomicLoad<I32, "i32.atomic.load", 0x10>; 139*0b57cec5SDimitry Andricdefm ATOMIC_LOAD_I64 : AtomicLoad<I64, "i64.atomic.load", 0x11>; 140*0b57cec5SDimitry Andric 141*0b57cec5SDimitry Andric// Select loads with no constant offset. 142*0b57cec5SDimitry Andriclet Predicates = [HasAtomics] in { 143*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i32, atomic_load_32, ATOMIC_LOAD_I32>; 144*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i64, atomic_load_64, ATOMIC_LOAD_I64>; 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric// Select loads with a constant offset. 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric// Pattern with address + immediate offset 149*0b57cec5SDimitry Andricdef : LoadPatImmOff<i32, atomic_load_32, regPlusImm, ATOMIC_LOAD_I32>; 150*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, atomic_load_64, regPlusImm, ATOMIC_LOAD_I64>; 151*0b57cec5SDimitry Andricdef : LoadPatImmOff<i32, atomic_load_32, or_is_add, ATOMIC_LOAD_I32>; 152*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, atomic_load_64, or_is_add, ATOMIC_LOAD_I64>; 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i32, atomic_load_32, ATOMIC_LOAD_I32>; 155*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i64, atomic_load_64, ATOMIC_LOAD_I64>; 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric// Select loads with just a constant offset. 158*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i32, atomic_load_32, ATOMIC_LOAD_I32>; 159*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i64, atomic_load_64, ATOMIC_LOAD_I64>; 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i32, atomic_load_32, ATOMIC_LOAD_I32>; 162*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i64, atomic_load_64, ATOMIC_LOAD_I64>; 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric} // Predicates = [HasAtomics] 165*0b57cec5SDimitry Andric 166*0b57cec5SDimitry Andric// Extending loads. Note that there are only zero-extending atomic loads, no 167*0b57cec5SDimitry Andric// sign-extending loads. 168*0b57cec5SDimitry Andricdefm ATOMIC_LOAD8_U_I32 : AtomicLoad<I32, "i32.atomic.load8_u", 0x12>; 169*0b57cec5SDimitry Andricdefm ATOMIC_LOAD16_U_I32 : AtomicLoad<I32, "i32.atomic.load16_u", 0x13>; 170*0b57cec5SDimitry Andricdefm ATOMIC_LOAD8_U_I64 : AtomicLoad<I64, "i64.atomic.load8_u", 0x14>; 171*0b57cec5SDimitry Andricdefm ATOMIC_LOAD16_U_I64 : AtomicLoad<I64, "i64.atomic.load16_u", 0x15>; 172*0b57cec5SDimitry Andricdefm ATOMIC_LOAD32_U_I64 : AtomicLoad<I64, "i64.atomic.load32_u", 0x16>; 173*0b57cec5SDimitry Andric 174*0b57cec5SDimitry Andric// Fragments for extending loads. These are different from regular loads because 175*0b57cec5SDimitry Andric// the SDNodes are derived from AtomicSDNode rather than LoadSDNode and 176*0b57cec5SDimitry Andric// therefore don't have the extension type field. So instead of matching that, 177*0b57cec5SDimitry Andric// we match the patterns that the type legalizer expands them to. 178*0b57cec5SDimitry Andric 179*0b57cec5SDimitry Andric// We directly match zext patterns and select the zext atomic loads. 180*0b57cec5SDimitry Andric// i32 (zext (i8 (atomic_load_8))) gets legalized to 181*0b57cec5SDimitry Andric// i32 (and (i32 (atomic_load_8)), 255) 182*0b57cec5SDimitry Andric// These can be selected to a single zero-extending atomic load instruction. 183*0b57cec5SDimitry Andricdef zext_aload_8_32 : 184*0b57cec5SDimitry Andric PatFrag<(ops node:$addr), (and (i32 (atomic_load_8 node:$addr)), 255)>; 185*0b57cec5SDimitry Andricdef zext_aload_16_32 : 186*0b57cec5SDimitry Andric PatFrag<(ops node:$addr), (and (i32 (atomic_load_16 node:$addr)), 65535)>; 187*0b57cec5SDimitry Andric// Unlike regular loads, extension to i64 is handled differently than i32. 188*0b57cec5SDimitry Andric// i64 (zext (i8 (atomic_load_8))) gets legalized to 189*0b57cec5SDimitry Andric// i64 (and (i64 (anyext (i32 (atomic_load_8)))), 255) 190*0b57cec5SDimitry Andricdef zext_aload_8_64 : 191*0b57cec5SDimitry Andric PatFrag<(ops node:$addr), 192*0b57cec5SDimitry Andric (and (i64 (anyext (i32 (atomic_load_8 node:$addr)))), 255)>; 193*0b57cec5SDimitry Andricdef zext_aload_16_64 : 194*0b57cec5SDimitry Andric PatFrag<(ops node:$addr), 195*0b57cec5SDimitry Andric (and (i64 (anyext (i32 (atomic_load_16 node:$addr)))), 65535)>; 196*0b57cec5SDimitry Andricdef zext_aload_32_64 : 197*0b57cec5SDimitry Andric PatFrag<(ops node:$addr), 198*0b57cec5SDimitry Andric (zext (i32 (atomic_load node:$addr)))>; 199*0b57cec5SDimitry Andric 200*0b57cec5SDimitry Andric// We don't have single sext atomic load instructions. So for sext loads, we 201*0b57cec5SDimitry Andric// match bare subword loads (for 32-bit results) and anyext loads (for 64-bit 202*0b57cec5SDimitry Andric// results) and select a zext load; the next instruction will be sext_inreg 203*0b57cec5SDimitry Andric// which is selected by itself. 204*0b57cec5SDimitry Andricdef sext_aload_8_64 : 205*0b57cec5SDimitry Andric PatFrag<(ops node:$addr), (anyext (i32 (atomic_load_8 node:$addr)))>; 206*0b57cec5SDimitry Andricdef sext_aload_16_64 : 207*0b57cec5SDimitry Andric PatFrag<(ops node:$addr), (anyext (i32 (atomic_load_16 node:$addr)))>; 208*0b57cec5SDimitry Andric 209*0b57cec5SDimitry Andriclet Predicates = [HasAtomics] in { 210*0b57cec5SDimitry Andric// Select zero-extending loads with no constant offset. 211*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i32, zext_aload_8_32, ATOMIC_LOAD8_U_I32>; 212*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i32, zext_aload_16_32, ATOMIC_LOAD16_U_I32>; 213*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i64, zext_aload_8_64, ATOMIC_LOAD8_U_I64>; 214*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i64, zext_aload_16_64, ATOMIC_LOAD16_U_I64>; 215*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i64, zext_aload_32_64, ATOMIC_LOAD32_U_I64>; 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric// Select sign-extending loads with no constant offset 218*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i32, atomic_load_8, ATOMIC_LOAD8_U_I32>; 219*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i32, atomic_load_16, ATOMIC_LOAD16_U_I32>; 220*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i64, sext_aload_8_64, ATOMIC_LOAD8_U_I64>; 221*0b57cec5SDimitry Andricdef : LoadPatNoOffset<i64, sext_aload_16_64, ATOMIC_LOAD16_U_I64>; 222*0b57cec5SDimitry Andric// 32->64 sext load gets selected as i32.atomic.load, i64.extend_i32_s 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric// Zero-extending loads with constant offset 225*0b57cec5SDimitry Andricdef : LoadPatImmOff<i32, zext_aload_8_32, regPlusImm, ATOMIC_LOAD8_U_I32>; 226*0b57cec5SDimitry Andricdef : LoadPatImmOff<i32, zext_aload_16_32, regPlusImm, ATOMIC_LOAD16_U_I32>; 227*0b57cec5SDimitry Andricdef : LoadPatImmOff<i32, zext_aload_8_32, or_is_add, ATOMIC_LOAD8_U_I32>; 228*0b57cec5SDimitry Andricdef : LoadPatImmOff<i32, zext_aload_16_32, or_is_add, ATOMIC_LOAD16_U_I32>; 229*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, zext_aload_8_64, regPlusImm, ATOMIC_LOAD8_U_I64>; 230*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, zext_aload_16_64, regPlusImm, ATOMIC_LOAD16_U_I64>; 231*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, zext_aload_32_64, regPlusImm, ATOMIC_LOAD32_U_I64>; 232*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, zext_aload_8_64, or_is_add, ATOMIC_LOAD8_U_I64>; 233*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, zext_aload_16_64, or_is_add, ATOMIC_LOAD16_U_I64>; 234*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, zext_aload_32_64, or_is_add, ATOMIC_LOAD32_U_I64>; 235*0b57cec5SDimitry Andric 236*0b57cec5SDimitry Andric// Sign-extending loads with constant offset 237*0b57cec5SDimitry Andricdef : LoadPatImmOff<i32, atomic_load_8, regPlusImm, ATOMIC_LOAD8_U_I32>; 238*0b57cec5SDimitry Andricdef : LoadPatImmOff<i32, atomic_load_16, regPlusImm, ATOMIC_LOAD16_U_I32>; 239*0b57cec5SDimitry Andricdef : LoadPatImmOff<i32, atomic_load_8, or_is_add, ATOMIC_LOAD8_U_I32>; 240*0b57cec5SDimitry Andricdef : LoadPatImmOff<i32, atomic_load_16, or_is_add, ATOMIC_LOAD16_U_I32>; 241*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, sext_aload_8_64, regPlusImm, ATOMIC_LOAD8_U_I64>; 242*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, sext_aload_16_64, regPlusImm, ATOMIC_LOAD16_U_I64>; 243*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, sext_aload_8_64, or_is_add, ATOMIC_LOAD8_U_I64>; 244*0b57cec5SDimitry Andricdef : LoadPatImmOff<i64, sext_aload_16_64, or_is_add, ATOMIC_LOAD16_U_I64>; 245*0b57cec5SDimitry Andric// No 32->64 patterns, just use i32.atomic.load and i64.extend_s/i64 246*0b57cec5SDimitry Andric 247*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i32, zext_aload_8_32, ATOMIC_LOAD8_U_I32>; 248*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i32, zext_aload_16_32, ATOMIC_LOAD16_U_I32>; 249*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i64, zext_aload_8_64, ATOMIC_LOAD8_U_I64>; 250*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i64, zext_aload_16_64, ATOMIC_LOAD16_U_I64>; 251*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i64, zext_aload_32_64, ATOMIC_LOAD32_U_I64>; 252*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i32, atomic_load_8, ATOMIC_LOAD8_U_I32>; 253*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i32, atomic_load_16, ATOMIC_LOAD16_U_I32>; 254*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i64, sext_aload_8_64, ATOMIC_LOAD8_U_I64>; 255*0b57cec5SDimitry Andricdef : LoadPatGlobalAddr<i64, sext_aload_16_64, ATOMIC_LOAD16_U_I64>; 256*0b57cec5SDimitry Andric 257*0b57cec5SDimitry Andric// Extending loads with just a constant offset 258*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i32, zext_aload_8_32, ATOMIC_LOAD8_U_I32>; 259*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i32, zext_aload_16_32, ATOMIC_LOAD16_U_I32>; 260*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i64, zext_aload_8_64, ATOMIC_LOAD8_U_I64>; 261*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i64, zext_aload_16_64, ATOMIC_LOAD16_U_I64>; 262*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i64, zext_aload_32_64, ATOMIC_LOAD32_U_I64>; 263*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i32, atomic_load_8, ATOMIC_LOAD8_U_I32>; 264*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i32, atomic_load_16, ATOMIC_LOAD16_U_I32>; 265*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i64, sext_aload_8_64, ATOMIC_LOAD8_U_I64>; 266*0b57cec5SDimitry Andricdef : LoadPatOffsetOnly<i64, sext_aload_16_64, ATOMIC_LOAD16_U_I64>; 267*0b57cec5SDimitry Andric 268*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i32, zext_aload_8_32, ATOMIC_LOAD8_U_I32>; 269*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i32, zext_aload_16_32, ATOMIC_LOAD16_U_I32>; 270*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i64, zext_aload_8_64, ATOMIC_LOAD8_U_I64>; 271*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i64, zext_aload_16_64, ATOMIC_LOAD16_U_I64>; 272*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i64, zext_aload_32_64, ATOMIC_LOAD32_U_I64>; 273*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i32, atomic_load_8, ATOMIC_LOAD8_U_I32>; 274*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i32, atomic_load_16, ATOMIC_LOAD16_U_I32>; 275*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i64, sext_aload_8_64, ATOMIC_LOAD8_U_I64>; 276*0b57cec5SDimitry Andricdef : LoadPatGlobalAddrOffOnly<i64, sext_aload_16_64, ATOMIC_LOAD16_U_I64>; 277*0b57cec5SDimitry Andric 278*0b57cec5SDimitry Andric} // Predicates = [HasAtomics] 279*0b57cec5SDimitry Andric 280*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 281*0b57cec5SDimitry Andric// Atomic stores 282*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 283*0b57cec5SDimitry Andric 284*0b57cec5SDimitry Andricmulticlass AtomicStore<WebAssemblyRegClass rc, string name, int atomic_op> { 285*0b57cec5SDimitry Andric defm "" : WebAssemblyStore<rc, name, !or(0xfe00, !and(0xff, atomic_op))>, 286*0b57cec5SDimitry Andric Requires<[HasAtomics]>; 287*0b57cec5SDimitry Andric} 288*0b57cec5SDimitry Andric 289*0b57cec5SDimitry Andricdefm ATOMIC_STORE_I32 : AtomicStore<I32, "i32.atomic.store", 0x17>; 290*0b57cec5SDimitry Andricdefm ATOMIC_STORE_I64 : AtomicStore<I64, "i64.atomic.store", 0x18>; 291*0b57cec5SDimitry Andric 292*0b57cec5SDimitry Andric// We need an 'atomic' version of store patterns because store and atomic_store 293*0b57cec5SDimitry Andric// nodes have different operand orders: 294*0b57cec5SDimitry Andric// store: (store $val, $ptr) 295*0b57cec5SDimitry Andric// atomic_store: (store $ptr, $val) 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andriclet Predicates = [HasAtomics] in { 298*0b57cec5SDimitry Andric 299*0b57cec5SDimitry Andric// Select stores with no constant offset. 300*0b57cec5SDimitry Andricclass AStorePatNoOffset<ValueType ty, PatFrag kind, NI inst> : 301*0b57cec5SDimitry Andric Pat<(kind I32:$addr, ty:$val), (inst 0, 0, I32:$addr, ty:$val)>; 302*0b57cec5SDimitry Andricdef : AStorePatNoOffset<i32, atomic_store_32, ATOMIC_STORE_I32>; 303*0b57cec5SDimitry Andricdef : AStorePatNoOffset<i64, atomic_store_64, ATOMIC_STORE_I64>; 304*0b57cec5SDimitry Andric 305*0b57cec5SDimitry Andric// Select stores with a constant offset. 306*0b57cec5SDimitry Andric 307*0b57cec5SDimitry Andric// Pattern with address + immediate offset 308*0b57cec5SDimitry Andricclass AStorePatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> : 309*0b57cec5SDimitry Andric Pat<(kind (operand I32:$addr, imm:$off), ty:$val), 310*0b57cec5SDimitry Andric (inst 0, imm:$off, I32:$addr, ty:$val)>; 311*0b57cec5SDimitry Andricdef : AStorePatImmOff<i32, atomic_store_32, regPlusImm, ATOMIC_STORE_I32>; 312*0b57cec5SDimitry Andricdef : AStorePatImmOff<i64, atomic_store_64, regPlusImm, ATOMIC_STORE_I64>; 313*0b57cec5SDimitry Andricdef : AStorePatImmOff<i32, atomic_store_32, or_is_add, ATOMIC_STORE_I32>; 314*0b57cec5SDimitry Andricdef : AStorePatImmOff<i64, atomic_store_64, or_is_add, ATOMIC_STORE_I64>; 315*0b57cec5SDimitry Andric 316*0b57cec5SDimitry Andricclass AStorePatGlobalAddr<ValueType ty, PatFrag kind, NI inst> : 317*0b57cec5SDimitry Andric Pat<(kind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)), 318*0b57cec5SDimitry Andric ty:$val), 319*0b57cec5SDimitry Andric (inst 0, tglobaladdr:$off, I32:$addr, ty:$val)>; 320*0b57cec5SDimitry Andricdef : AStorePatGlobalAddr<i32, atomic_store_32, ATOMIC_STORE_I32>; 321*0b57cec5SDimitry Andricdef : AStorePatGlobalAddr<i64, atomic_store_64, ATOMIC_STORE_I64>; 322*0b57cec5SDimitry Andric 323*0b57cec5SDimitry Andric// Select stores with just a constant offset. 324*0b57cec5SDimitry Andricclass AStorePatOffsetOnly<ValueType ty, PatFrag kind, NI inst> : 325*0b57cec5SDimitry Andric Pat<(kind imm:$off, ty:$val), (inst 0, imm:$off, (CONST_I32 0), ty:$val)>; 326*0b57cec5SDimitry Andricdef : AStorePatOffsetOnly<i32, atomic_store_32, ATOMIC_STORE_I32>; 327*0b57cec5SDimitry Andricdef : AStorePatOffsetOnly<i64, atomic_store_64, ATOMIC_STORE_I64>; 328*0b57cec5SDimitry Andric 329*0b57cec5SDimitry Andricclass AStorePatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> : 330*0b57cec5SDimitry Andric Pat<(kind (WebAssemblywrapper tglobaladdr:$off), ty:$val), 331*0b57cec5SDimitry Andric (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>; 332*0b57cec5SDimitry Andricdef : AStorePatGlobalAddrOffOnly<i32, atomic_store_32, ATOMIC_STORE_I32>; 333*0b57cec5SDimitry Andricdef : AStorePatGlobalAddrOffOnly<i64, atomic_store_64, ATOMIC_STORE_I64>; 334*0b57cec5SDimitry Andric 335*0b57cec5SDimitry Andric} // Predicates = [HasAtomics] 336*0b57cec5SDimitry Andric 337*0b57cec5SDimitry Andric// Truncating stores. 338*0b57cec5SDimitry Andricdefm ATOMIC_STORE8_I32 : AtomicStore<I32, "i32.atomic.store8", 0x19>; 339*0b57cec5SDimitry Andricdefm ATOMIC_STORE16_I32 : AtomicStore<I32, "i32.atomic.store16", 0x1a>; 340*0b57cec5SDimitry Andricdefm ATOMIC_STORE8_I64 : AtomicStore<I64, "i64.atomic.store8", 0x1b>; 341*0b57cec5SDimitry Andricdefm ATOMIC_STORE16_I64 : AtomicStore<I64, "i64.atomic.store16", 0x1c>; 342*0b57cec5SDimitry Andricdefm ATOMIC_STORE32_I64 : AtomicStore<I64, "i64.atomic.store32", 0x1d>; 343*0b57cec5SDimitry Andric 344*0b57cec5SDimitry Andric// Fragments for truncating stores. 345*0b57cec5SDimitry Andric 346*0b57cec5SDimitry Andric// We don't have single truncating atomic store instructions. For 32-bit 347*0b57cec5SDimitry Andric// instructions, we just need to match bare atomic stores. On the other hand, 348*0b57cec5SDimitry Andric// truncating stores from i64 values are once truncated to i32 first. 349*0b57cec5SDimitry Andricclass trunc_astore_64<PatFrag kind> : 350*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$val), 351*0b57cec5SDimitry Andric (kind node:$addr, (i32 (trunc (i64 node:$val))))>; 352*0b57cec5SDimitry Andricdef trunc_astore_8_64 : trunc_astore_64<atomic_store_8>; 353*0b57cec5SDimitry Andricdef trunc_astore_16_64 : trunc_astore_64<atomic_store_16>; 354*0b57cec5SDimitry Andricdef trunc_astore_32_64 : trunc_astore_64<atomic_store_32>; 355*0b57cec5SDimitry Andric 356*0b57cec5SDimitry Andriclet Predicates = [HasAtomics] in { 357*0b57cec5SDimitry Andric 358*0b57cec5SDimitry Andric// Truncating stores with no constant offset 359*0b57cec5SDimitry Andricdef : AStorePatNoOffset<i32, atomic_store_8, ATOMIC_STORE8_I32>; 360*0b57cec5SDimitry Andricdef : AStorePatNoOffset<i32, atomic_store_16, ATOMIC_STORE16_I32>; 361*0b57cec5SDimitry Andricdef : AStorePatNoOffset<i64, trunc_astore_8_64, ATOMIC_STORE8_I64>; 362*0b57cec5SDimitry Andricdef : AStorePatNoOffset<i64, trunc_astore_16_64, ATOMIC_STORE16_I64>; 363*0b57cec5SDimitry Andricdef : AStorePatNoOffset<i64, trunc_astore_32_64, ATOMIC_STORE32_I64>; 364*0b57cec5SDimitry Andric 365*0b57cec5SDimitry Andric// Truncating stores with a constant offset 366*0b57cec5SDimitry Andricdef : AStorePatImmOff<i32, atomic_store_8, regPlusImm, ATOMIC_STORE8_I32>; 367*0b57cec5SDimitry Andricdef : AStorePatImmOff<i32, atomic_store_16, regPlusImm, ATOMIC_STORE16_I32>; 368*0b57cec5SDimitry Andricdef : AStorePatImmOff<i64, trunc_astore_8_64, regPlusImm, ATOMIC_STORE8_I64>; 369*0b57cec5SDimitry Andricdef : AStorePatImmOff<i64, trunc_astore_16_64, regPlusImm, ATOMIC_STORE16_I64>; 370*0b57cec5SDimitry Andricdef : AStorePatImmOff<i64, trunc_astore_32_64, regPlusImm, ATOMIC_STORE32_I64>; 371*0b57cec5SDimitry Andricdef : AStorePatImmOff<i32, atomic_store_8, or_is_add, ATOMIC_STORE8_I32>; 372*0b57cec5SDimitry Andricdef : AStorePatImmOff<i32, atomic_store_16, or_is_add, ATOMIC_STORE16_I32>; 373*0b57cec5SDimitry Andricdef : AStorePatImmOff<i64, trunc_astore_8_64, or_is_add, ATOMIC_STORE8_I64>; 374*0b57cec5SDimitry Andricdef : AStorePatImmOff<i64, trunc_astore_16_64, or_is_add, ATOMIC_STORE16_I64>; 375*0b57cec5SDimitry Andricdef : AStorePatImmOff<i64, trunc_astore_32_64, or_is_add, ATOMIC_STORE32_I64>; 376*0b57cec5SDimitry Andric 377*0b57cec5SDimitry Andricdef : AStorePatGlobalAddr<i32, atomic_store_8, ATOMIC_STORE8_I32>; 378*0b57cec5SDimitry Andricdef : AStorePatGlobalAddr<i32, atomic_store_16, ATOMIC_STORE16_I32>; 379*0b57cec5SDimitry Andricdef : AStorePatGlobalAddr<i64, trunc_astore_8_64, ATOMIC_STORE8_I64>; 380*0b57cec5SDimitry Andricdef : AStorePatGlobalAddr<i64, trunc_astore_16_64, ATOMIC_STORE16_I64>; 381*0b57cec5SDimitry Andricdef : AStorePatGlobalAddr<i64, trunc_astore_32_64, ATOMIC_STORE32_I64>; 382*0b57cec5SDimitry Andric 383*0b57cec5SDimitry Andric// Truncating stores with just a constant offset 384*0b57cec5SDimitry Andricdef : AStorePatOffsetOnly<i32, atomic_store_8, ATOMIC_STORE8_I32>; 385*0b57cec5SDimitry Andricdef : AStorePatOffsetOnly<i32, atomic_store_16, ATOMIC_STORE16_I32>; 386*0b57cec5SDimitry Andricdef : AStorePatOffsetOnly<i64, trunc_astore_8_64, ATOMIC_STORE8_I64>; 387*0b57cec5SDimitry Andricdef : AStorePatOffsetOnly<i64, trunc_astore_16_64, ATOMIC_STORE16_I64>; 388*0b57cec5SDimitry Andricdef : AStorePatOffsetOnly<i64, trunc_astore_32_64, ATOMIC_STORE32_I64>; 389*0b57cec5SDimitry Andric 390*0b57cec5SDimitry Andricdef : AStorePatGlobalAddrOffOnly<i32, atomic_store_8, ATOMIC_STORE8_I32>; 391*0b57cec5SDimitry Andricdef : AStorePatGlobalAddrOffOnly<i32, atomic_store_16, ATOMIC_STORE16_I32>; 392*0b57cec5SDimitry Andricdef : AStorePatGlobalAddrOffOnly<i64, trunc_astore_8_64, ATOMIC_STORE8_I64>; 393*0b57cec5SDimitry Andricdef : AStorePatGlobalAddrOffOnly<i64, trunc_astore_16_64, ATOMIC_STORE16_I64>; 394*0b57cec5SDimitry Andricdef : AStorePatGlobalAddrOffOnly<i64, trunc_astore_32_64, ATOMIC_STORE32_I64>; 395*0b57cec5SDimitry Andric 396*0b57cec5SDimitry Andric} // Predicates = [HasAtomics] 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 399*0b57cec5SDimitry Andric// Atomic binary read-modify-writes 400*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 401*0b57cec5SDimitry Andric 402*0b57cec5SDimitry Andricmulticlass WebAssemblyBinRMW<WebAssemblyRegClass rc, string name, 403*0b57cec5SDimitry Andric int atomic_op> { 404*0b57cec5SDimitry Andric defm "" : 405*0b57cec5SDimitry Andric ATOMIC_I<(outs rc:$dst), 406*0b57cec5SDimitry Andric (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val), 407*0b57cec5SDimitry Andric (outs), (ins P2Align:$p2align, offset32_op:$off), [], 408*0b57cec5SDimitry Andric !strconcat(name, "\t$dst, ${off}(${addr})${p2align}, $val"), 409*0b57cec5SDimitry Andric !strconcat(name, "\t${off}${p2align}"), atomic_op>; 410*0b57cec5SDimitry Andric} 411*0b57cec5SDimitry Andric 412*0b57cec5SDimitry Andricdefm ATOMIC_RMW_ADD_I32 : WebAssemblyBinRMW<I32, "i32.atomic.rmw.add", 0x1e>; 413*0b57cec5SDimitry Andricdefm ATOMIC_RMW_ADD_I64 : WebAssemblyBinRMW<I64, "i64.atomic.rmw.add", 0x1f>; 414*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_ADD_I32 : 415*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw8.add_u", 0x20>; 416*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_ADD_I32 : 417*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw16.add_u", 0x21>; 418*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_ADD_I64 : 419*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw8.add_u", 0x22>; 420*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_ADD_I64 : 421*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw16.add_u", 0x23>; 422*0b57cec5SDimitry Andricdefm ATOMIC_RMW32_U_ADD_I64 : 423*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw32.add_u", 0x24>; 424*0b57cec5SDimitry Andric 425*0b57cec5SDimitry Andricdefm ATOMIC_RMW_SUB_I32 : WebAssemblyBinRMW<I32, "i32.atomic.rmw.sub", 0x25>; 426*0b57cec5SDimitry Andricdefm ATOMIC_RMW_SUB_I64 : WebAssemblyBinRMW<I64, "i64.atomic.rmw.sub", 0x26>; 427*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_SUB_I32 : 428*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw8.sub_u", 0x27>; 429*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_SUB_I32 : 430*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw16.sub_u", 0x28>; 431*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_SUB_I64 : 432*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw8.sub_u", 0x29>; 433*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_SUB_I64 : 434*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw16.sub_u", 0x2a>; 435*0b57cec5SDimitry Andricdefm ATOMIC_RMW32_U_SUB_I64 : 436*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw32.sub_u", 0x2b>; 437*0b57cec5SDimitry Andric 438*0b57cec5SDimitry Andricdefm ATOMIC_RMW_AND_I32 : WebAssemblyBinRMW<I32, "i32.atomic.rmw.and", 0x2c>; 439*0b57cec5SDimitry Andricdefm ATOMIC_RMW_AND_I64 : WebAssemblyBinRMW<I64, "i64.atomic.rmw.and", 0x2d>; 440*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_AND_I32 : 441*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw8.and_u", 0x2e>; 442*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_AND_I32 : 443*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw16.and_u", 0x2f>; 444*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_AND_I64 : 445*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw8.and_u", 0x30>; 446*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_AND_I64 : 447*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw16.and_u", 0x31>; 448*0b57cec5SDimitry Andricdefm ATOMIC_RMW32_U_AND_I64 : 449*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw32.and_u", 0x32>; 450*0b57cec5SDimitry Andric 451*0b57cec5SDimitry Andricdefm ATOMIC_RMW_OR_I32 : WebAssemblyBinRMW<I32, "i32.atomic.rmw.or", 0x33>; 452*0b57cec5SDimitry Andricdefm ATOMIC_RMW_OR_I64 : WebAssemblyBinRMW<I64, "i64.atomic.rmw.or", 0x34>; 453*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_OR_I32 : 454*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw8.or_u", 0x35>; 455*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_OR_I32 : 456*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw16.or_u", 0x36>; 457*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_OR_I64 : 458*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw8.or_u", 0x37>; 459*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_OR_I64 : 460*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw16.or_u", 0x38>; 461*0b57cec5SDimitry Andricdefm ATOMIC_RMW32_U_OR_I64 : 462*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw32.or_u", 0x39>; 463*0b57cec5SDimitry Andric 464*0b57cec5SDimitry Andricdefm ATOMIC_RMW_XOR_I32 : WebAssemblyBinRMW<I32, "i32.atomic.rmw.xor", 0x3a>; 465*0b57cec5SDimitry Andricdefm ATOMIC_RMW_XOR_I64 : WebAssemblyBinRMW<I64, "i64.atomic.rmw.xor", 0x3b>; 466*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_XOR_I32 : 467*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw8.xor_u", 0x3c>; 468*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_XOR_I32 : 469*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw16.xor_u", 0x3d>; 470*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_XOR_I64 : 471*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw8.xor_u", 0x3e>; 472*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_XOR_I64 : 473*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw16.xor_u", 0x3f>; 474*0b57cec5SDimitry Andricdefm ATOMIC_RMW32_U_XOR_I64 : 475*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw32.xor_u", 0x40>; 476*0b57cec5SDimitry Andric 477*0b57cec5SDimitry Andricdefm ATOMIC_RMW_XCHG_I32 : 478*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw.xchg", 0x41>; 479*0b57cec5SDimitry Andricdefm ATOMIC_RMW_XCHG_I64 : 480*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw.xchg", 0x42>; 481*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_XCHG_I32 : 482*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw8.xchg_u", 0x43>; 483*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_XCHG_I32 : 484*0b57cec5SDimitry Andric WebAssemblyBinRMW<I32, "i32.atomic.rmw16.xchg_u", 0x44>; 485*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_XCHG_I64 : 486*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw8.xchg_u", 0x45>; 487*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_XCHG_I64 : 488*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw16.xchg_u", 0x46>; 489*0b57cec5SDimitry Andricdefm ATOMIC_RMW32_U_XCHG_I64 : 490*0b57cec5SDimitry Andric WebAssemblyBinRMW<I64, "i64.atomic.rmw32.xchg_u", 0x47>; 491*0b57cec5SDimitry Andric 492*0b57cec5SDimitry Andric// Select binary RMWs with no constant offset. 493*0b57cec5SDimitry Andricclass BinRMWPatNoOffset<ValueType ty, PatFrag kind, NI inst> : 494*0b57cec5SDimitry Andric Pat<(ty (kind I32:$addr, ty:$val)), (inst 0, 0, I32:$addr, ty:$val)>; 495*0b57cec5SDimitry Andric 496*0b57cec5SDimitry Andric// Select binary RMWs with a constant offset. 497*0b57cec5SDimitry Andric 498*0b57cec5SDimitry Andric// Pattern with address + immediate offset 499*0b57cec5SDimitry Andricclass BinRMWPatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> : 500*0b57cec5SDimitry Andric Pat<(ty (kind (operand I32:$addr, imm:$off), ty:$val)), 501*0b57cec5SDimitry Andric (inst 0, imm:$off, I32:$addr, ty:$val)>; 502*0b57cec5SDimitry Andric 503*0b57cec5SDimitry Andricclass BinRMWPatGlobalAddr<ValueType ty, PatFrag kind, NI inst> : 504*0b57cec5SDimitry Andric Pat<(ty (kind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)), 505*0b57cec5SDimitry Andric ty:$val)), 506*0b57cec5SDimitry Andric (inst 0, tglobaladdr:$off, I32:$addr, ty:$val)>; 507*0b57cec5SDimitry Andric 508*0b57cec5SDimitry Andric// Select binary RMWs with just a constant offset. 509*0b57cec5SDimitry Andricclass BinRMWPatOffsetOnly<ValueType ty, PatFrag kind, NI inst> : 510*0b57cec5SDimitry Andric Pat<(ty (kind imm:$off, ty:$val)), 511*0b57cec5SDimitry Andric (inst 0, imm:$off, (CONST_I32 0), ty:$val)>; 512*0b57cec5SDimitry Andric 513*0b57cec5SDimitry Andricclass BinRMWPatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> : 514*0b57cec5SDimitry Andric Pat<(ty (kind (WebAssemblywrapper tglobaladdr:$off), ty:$val)), 515*0b57cec5SDimitry Andric (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>; 516*0b57cec5SDimitry Andric 517*0b57cec5SDimitry Andric// Patterns for various addressing modes. 518*0b57cec5SDimitry Andricmulticlass BinRMWPattern<PatFrag rmw_32, PatFrag rmw_64, NI inst_32, 519*0b57cec5SDimitry Andric NI inst_64> { 520*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i32, rmw_32, inst_32>; 521*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i64, rmw_64, inst_64>; 522*0b57cec5SDimitry Andric 523*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i32, rmw_32, regPlusImm, inst_32>; 524*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, rmw_64, regPlusImm, inst_64>; 525*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i32, rmw_32, or_is_add, inst_32>; 526*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, rmw_64, or_is_add, inst_64>; 527*0b57cec5SDimitry Andric 528*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i32, rmw_32, inst_32>; 529*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i64, rmw_64, inst_64>; 530*0b57cec5SDimitry Andric 531*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i32, rmw_32, inst_32>; 532*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i64, rmw_64, inst_64>; 533*0b57cec5SDimitry Andric 534*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i32, rmw_32, inst_32>; 535*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i64, rmw_64, inst_64>; 536*0b57cec5SDimitry Andric} 537*0b57cec5SDimitry Andric 538*0b57cec5SDimitry Andriclet Predicates = [HasAtomics] in { 539*0b57cec5SDimitry Andricdefm : BinRMWPattern<atomic_load_add_32, atomic_load_add_64, ATOMIC_RMW_ADD_I32, 540*0b57cec5SDimitry Andric ATOMIC_RMW_ADD_I64>; 541*0b57cec5SDimitry Andricdefm : BinRMWPattern<atomic_load_sub_32, atomic_load_sub_64, ATOMIC_RMW_SUB_I32, 542*0b57cec5SDimitry Andric ATOMIC_RMW_SUB_I64>; 543*0b57cec5SDimitry Andricdefm : BinRMWPattern<atomic_load_and_32, atomic_load_and_64, ATOMIC_RMW_AND_I32, 544*0b57cec5SDimitry Andric ATOMIC_RMW_AND_I64>; 545*0b57cec5SDimitry Andricdefm : BinRMWPattern<atomic_load_or_32, atomic_load_or_64, ATOMIC_RMW_OR_I32, 546*0b57cec5SDimitry Andric ATOMIC_RMW_OR_I64>; 547*0b57cec5SDimitry Andricdefm : BinRMWPattern<atomic_load_xor_32, atomic_load_xor_64, ATOMIC_RMW_XOR_I32, 548*0b57cec5SDimitry Andric ATOMIC_RMW_XOR_I64>; 549*0b57cec5SDimitry Andricdefm : BinRMWPattern<atomic_swap_32, atomic_swap_64, ATOMIC_RMW_XCHG_I32, 550*0b57cec5SDimitry Andric ATOMIC_RMW_XCHG_I64>; 551*0b57cec5SDimitry Andric} // Predicates = [HasAtomics] 552*0b57cec5SDimitry Andric 553*0b57cec5SDimitry Andric// Truncating & zero-extending binary RMW patterns. 554*0b57cec5SDimitry Andric// These are combined patterns of truncating store patterns and zero-extending 555*0b57cec5SDimitry Andric// load patterns above. 556*0b57cec5SDimitry Andricclass zext_bin_rmw_8_32<PatFrag kind> : 557*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$val), 558*0b57cec5SDimitry Andric (and (i32 (kind node:$addr, node:$val)), 255)>; 559*0b57cec5SDimitry Andricclass zext_bin_rmw_16_32<PatFrag kind> : 560*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$val), 561*0b57cec5SDimitry Andric (and (i32 (kind node:$addr, node:$val)), 65535)>; 562*0b57cec5SDimitry Andricclass zext_bin_rmw_8_64<PatFrag kind> : 563*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$val), 564*0b57cec5SDimitry Andric (and (i64 (anyext (i32 (kind node:$addr, 565*0b57cec5SDimitry Andric (i32 (trunc (i64 node:$val))))))), 255)>; 566*0b57cec5SDimitry Andricclass zext_bin_rmw_16_64<PatFrag kind> : 567*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$val), 568*0b57cec5SDimitry Andric (and (i64 (anyext (i32 (kind node:$addr, 569*0b57cec5SDimitry Andric (i32 (trunc (i64 node:$val))))))), 65535)>; 570*0b57cec5SDimitry Andricclass zext_bin_rmw_32_64<PatFrag kind> : 571*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$val), 572*0b57cec5SDimitry Andric (zext (i32 (kind node:$addr, (i32 (trunc (i64 node:$val))))))>; 573*0b57cec5SDimitry Andric 574*0b57cec5SDimitry Andric// Truncating & sign-extending binary RMW patterns. 575*0b57cec5SDimitry Andric// These are combined patterns of truncating store patterns and sign-extending 576*0b57cec5SDimitry Andric// load patterns above. We match subword RMWs (for 32-bit) and anyext RMWs (for 577*0b57cec5SDimitry Andric// 64-bit) and select a zext RMW; the next instruction will be sext_inreg which 578*0b57cec5SDimitry Andric// is selected by itself. 579*0b57cec5SDimitry Andricclass sext_bin_rmw_8_32<PatFrag kind> : 580*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$val), (kind node:$addr, node:$val)>; 581*0b57cec5SDimitry Andricclass sext_bin_rmw_16_32<PatFrag kind> : sext_bin_rmw_8_32<kind>; 582*0b57cec5SDimitry Andricclass sext_bin_rmw_8_64<PatFrag kind> : 583*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$val), 584*0b57cec5SDimitry Andric (anyext (i32 (kind node:$addr, (i32 (trunc (i64 node:$val))))))>; 585*0b57cec5SDimitry Andricclass sext_bin_rmw_16_64<PatFrag kind> : sext_bin_rmw_8_64<kind>; 586*0b57cec5SDimitry Andric// 32->64 sext RMW gets selected as i32.atomic.rmw.***, i64.extend_i32_s 587*0b57cec5SDimitry Andric 588*0b57cec5SDimitry Andric// Patterns for various addressing modes for truncating-extending binary RMWs. 589*0b57cec5SDimitry Andricmulticlass BinRMWTruncExtPattern< 590*0b57cec5SDimitry Andric PatFrag rmw_8, PatFrag rmw_16, PatFrag rmw_32, PatFrag rmw_64, 591*0b57cec5SDimitry Andric NI inst8_32, NI inst16_32, NI inst8_64, NI inst16_64, NI inst32_64> { 592*0b57cec5SDimitry Andric // Truncating-extending binary RMWs with no constant offset 593*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>; 594*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>; 595*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>; 596*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>; 597*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>; 598*0b57cec5SDimitry Andric 599*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>; 600*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>; 601*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>; 602*0b57cec5SDimitry Andric def : BinRMWPatNoOffset<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>; 603*0b57cec5SDimitry Andric 604*0b57cec5SDimitry Andric // Truncating-extending binary RMWs with a constant offset 605*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i32, zext_bin_rmw_8_32<rmw_8>, regPlusImm, inst8_32>; 606*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i32, zext_bin_rmw_16_32<rmw_16>, regPlusImm, inst16_32>; 607*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, zext_bin_rmw_8_64<rmw_8>, regPlusImm, inst8_64>; 608*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, zext_bin_rmw_16_64<rmw_16>, regPlusImm, inst16_64>; 609*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, zext_bin_rmw_32_64<rmw_32>, regPlusImm, inst32_64>; 610*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i32, zext_bin_rmw_8_32<rmw_8>, or_is_add, inst8_32>; 611*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i32, zext_bin_rmw_16_32<rmw_16>, or_is_add, inst16_32>; 612*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, zext_bin_rmw_8_64<rmw_8>, or_is_add, inst8_64>; 613*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, zext_bin_rmw_16_64<rmw_16>, or_is_add, inst16_64>; 614*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, zext_bin_rmw_32_64<rmw_32>, or_is_add, inst32_64>; 615*0b57cec5SDimitry Andric 616*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i32, sext_bin_rmw_8_32<rmw_8>, regPlusImm, inst8_32>; 617*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i32, sext_bin_rmw_16_32<rmw_16>, regPlusImm, inst16_32>; 618*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, sext_bin_rmw_8_64<rmw_8>, regPlusImm, inst8_64>; 619*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, sext_bin_rmw_16_64<rmw_16>, regPlusImm, inst16_64>; 620*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i32, sext_bin_rmw_8_32<rmw_8>, or_is_add, inst8_32>; 621*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i32, sext_bin_rmw_16_32<rmw_16>, or_is_add, inst16_32>; 622*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, sext_bin_rmw_8_64<rmw_8>, or_is_add, inst8_64>; 623*0b57cec5SDimitry Andric def : BinRMWPatImmOff<i64, sext_bin_rmw_16_64<rmw_16>, or_is_add, inst16_64>; 624*0b57cec5SDimitry Andric 625*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>; 626*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>; 627*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>; 628*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>; 629*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>; 630*0b57cec5SDimitry Andric 631*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>; 632*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>; 633*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>; 634*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddr<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>; 635*0b57cec5SDimitry Andric 636*0b57cec5SDimitry Andric // Truncating-extending binary RMWs with just a constant offset 637*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>; 638*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>; 639*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>; 640*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>; 641*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>; 642*0b57cec5SDimitry Andric 643*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>; 644*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>; 645*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>; 646*0b57cec5SDimitry Andric def : BinRMWPatOffsetOnly<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>; 647*0b57cec5SDimitry Andric 648*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>; 649*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>; 650*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>; 651*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>; 652*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>; 653*0b57cec5SDimitry Andric 654*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>; 655*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>; 656*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>; 657*0b57cec5SDimitry Andric def : BinRMWPatGlobalAddrOffOnly<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>; 658*0b57cec5SDimitry Andric} 659*0b57cec5SDimitry Andric 660*0b57cec5SDimitry Andriclet Predicates = [HasAtomics] in { 661*0b57cec5SDimitry Andricdefm : BinRMWTruncExtPattern< 662*0b57cec5SDimitry Andric atomic_load_add_8, atomic_load_add_16, atomic_load_add_32, atomic_load_add_64, 663*0b57cec5SDimitry Andric ATOMIC_RMW8_U_ADD_I32, ATOMIC_RMW16_U_ADD_I32, 664*0b57cec5SDimitry Andric ATOMIC_RMW8_U_ADD_I64, ATOMIC_RMW16_U_ADD_I64, ATOMIC_RMW32_U_ADD_I64>; 665*0b57cec5SDimitry Andricdefm : BinRMWTruncExtPattern< 666*0b57cec5SDimitry Andric atomic_load_sub_8, atomic_load_sub_16, atomic_load_sub_32, atomic_load_sub_64, 667*0b57cec5SDimitry Andric ATOMIC_RMW8_U_SUB_I32, ATOMIC_RMW16_U_SUB_I32, 668*0b57cec5SDimitry Andric ATOMIC_RMW8_U_SUB_I64, ATOMIC_RMW16_U_SUB_I64, ATOMIC_RMW32_U_SUB_I64>; 669*0b57cec5SDimitry Andricdefm : BinRMWTruncExtPattern< 670*0b57cec5SDimitry Andric atomic_load_and_8, atomic_load_and_16, atomic_load_and_32, atomic_load_and_64, 671*0b57cec5SDimitry Andric ATOMIC_RMW8_U_AND_I32, ATOMIC_RMW16_U_AND_I32, 672*0b57cec5SDimitry Andric ATOMIC_RMW8_U_AND_I64, ATOMIC_RMW16_U_AND_I64, ATOMIC_RMW32_U_AND_I64>; 673*0b57cec5SDimitry Andricdefm : BinRMWTruncExtPattern< 674*0b57cec5SDimitry Andric atomic_load_or_8, atomic_load_or_16, atomic_load_or_32, atomic_load_or_64, 675*0b57cec5SDimitry Andric ATOMIC_RMW8_U_OR_I32, ATOMIC_RMW16_U_OR_I32, 676*0b57cec5SDimitry Andric ATOMIC_RMW8_U_OR_I64, ATOMIC_RMW16_U_OR_I64, ATOMIC_RMW32_U_OR_I64>; 677*0b57cec5SDimitry Andricdefm : BinRMWTruncExtPattern< 678*0b57cec5SDimitry Andric atomic_load_xor_8, atomic_load_xor_16, atomic_load_xor_32, atomic_load_xor_64, 679*0b57cec5SDimitry Andric ATOMIC_RMW8_U_XOR_I32, ATOMIC_RMW16_U_XOR_I32, 680*0b57cec5SDimitry Andric ATOMIC_RMW8_U_XOR_I64, ATOMIC_RMW16_U_XOR_I64, ATOMIC_RMW32_U_XOR_I64>; 681*0b57cec5SDimitry Andricdefm : BinRMWTruncExtPattern< 682*0b57cec5SDimitry Andric atomic_swap_8, atomic_swap_16, atomic_swap_32, atomic_swap_64, 683*0b57cec5SDimitry Andric ATOMIC_RMW8_U_XCHG_I32, ATOMIC_RMW16_U_XCHG_I32, 684*0b57cec5SDimitry Andric ATOMIC_RMW8_U_XCHG_I64, ATOMIC_RMW16_U_XCHG_I64, ATOMIC_RMW32_U_XCHG_I64>; 685*0b57cec5SDimitry Andric} // Predicates = [HasAtomics] 686*0b57cec5SDimitry Andric 687*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 688*0b57cec5SDimitry Andric// Atomic ternary read-modify-writes 689*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 690*0b57cec5SDimitry Andric 691*0b57cec5SDimitry Andric// TODO LLVM IR's cmpxchg instruction returns a pair of {loaded value, success 692*0b57cec5SDimitry Andric// flag}. When we use the success flag or both values, we can't make use of i64 693*0b57cec5SDimitry Andric// truncate/extend versions of instructions for now, which is suboptimal. 694*0b57cec5SDimitry Andric// Consider adding a pass after instruction selection that optimizes this case 695*0b57cec5SDimitry Andric// if it is frequent. 696*0b57cec5SDimitry Andric 697*0b57cec5SDimitry Andricmulticlass WebAssemblyTerRMW<WebAssemblyRegClass rc, string name, 698*0b57cec5SDimitry Andric int atomic_op> { 699*0b57cec5SDimitry Andric defm "" : 700*0b57cec5SDimitry Andric ATOMIC_I<(outs rc:$dst), 701*0b57cec5SDimitry Andric (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$exp, 702*0b57cec5SDimitry Andric rc:$new_), 703*0b57cec5SDimitry Andric (outs), (ins P2Align:$p2align, offset32_op:$off), [], 704*0b57cec5SDimitry Andric !strconcat(name, "\t$dst, ${off}(${addr})${p2align}, $exp, $new_"), 705*0b57cec5SDimitry Andric !strconcat(name, "\t${off}${p2align}"), atomic_op>; 706*0b57cec5SDimitry Andric} 707*0b57cec5SDimitry Andric 708*0b57cec5SDimitry Andricdefm ATOMIC_RMW_CMPXCHG_I32 : 709*0b57cec5SDimitry Andric WebAssemblyTerRMW<I32, "i32.atomic.rmw.cmpxchg", 0x48>; 710*0b57cec5SDimitry Andricdefm ATOMIC_RMW_CMPXCHG_I64 : 711*0b57cec5SDimitry Andric WebAssemblyTerRMW<I64, "i64.atomic.rmw.cmpxchg", 0x49>; 712*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_CMPXCHG_I32 : 713*0b57cec5SDimitry Andric WebAssemblyTerRMW<I32, "i32.atomic.rmw8.cmpxchg_u", 0x4a>; 714*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_CMPXCHG_I32 : 715*0b57cec5SDimitry Andric WebAssemblyTerRMW<I32, "i32.atomic.rmw16.cmpxchg_u", 0x4b>; 716*0b57cec5SDimitry Andricdefm ATOMIC_RMW8_U_CMPXCHG_I64 : 717*0b57cec5SDimitry Andric WebAssemblyTerRMW<I64, "i64.atomic.rmw8.cmpxchg_u", 0x4c>; 718*0b57cec5SDimitry Andricdefm ATOMIC_RMW16_U_CMPXCHG_I64 : 719*0b57cec5SDimitry Andric WebAssemblyTerRMW<I64, "i64.atomic.rmw16.cmpxchg_u", 0x4d>; 720*0b57cec5SDimitry Andricdefm ATOMIC_RMW32_U_CMPXCHG_I64 : 721*0b57cec5SDimitry Andric WebAssemblyTerRMW<I64, "i64.atomic.rmw32.cmpxchg_u", 0x4e>; 722*0b57cec5SDimitry Andric 723*0b57cec5SDimitry Andric// Select ternary RMWs with no constant offset. 724*0b57cec5SDimitry Andricclass TerRMWPatNoOffset<ValueType ty, PatFrag kind, NI inst> : 725*0b57cec5SDimitry Andric Pat<(ty (kind I32:$addr, ty:$exp, ty:$new)), 726*0b57cec5SDimitry Andric (inst 0, 0, I32:$addr, ty:$exp, ty:$new)>; 727*0b57cec5SDimitry Andric 728*0b57cec5SDimitry Andric// Select ternary RMWs with a constant offset. 729*0b57cec5SDimitry Andric 730*0b57cec5SDimitry Andric// Pattern with address + immediate offset 731*0b57cec5SDimitry Andricclass TerRMWPatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> : 732*0b57cec5SDimitry Andric Pat<(ty (kind (operand I32:$addr, imm:$off), ty:$exp, ty:$new)), 733*0b57cec5SDimitry Andric (inst 0, imm:$off, I32:$addr, ty:$exp, ty:$new)>; 734*0b57cec5SDimitry Andric 735*0b57cec5SDimitry Andricclass TerRMWPatGlobalAddr<ValueType ty, PatFrag kind, NI inst> : 736*0b57cec5SDimitry Andric Pat<(ty (kind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)), 737*0b57cec5SDimitry Andric ty:$exp, ty:$new)), 738*0b57cec5SDimitry Andric (inst 0, tglobaladdr:$off, I32:$addr, ty:$exp, ty:$new)>; 739*0b57cec5SDimitry Andric 740*0b57cec5SDimitry Andric// Select ternary RMWs with just a constant offset. 741*0b57cec5SDimitry Andricclass TerRMWPatOffsetOnly<ValueType ty, PatFrag kind, NI inst> : 742*0b57cec5SDimitry Andric Pat<(ty (kind imm:$off, ty:$exp, ty:$new)), 743*0b57cec5SDimitry Andric (inst 0, imm:$off, (CONST_I32 0), ty:$exp, ty:$new)>; 744*0b57cec5SDimitry Andric 745*0b57cec5SDimitry Andricclass TerRMWPatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> : 746*0b57cec5SDimitry Andric Pat<(ty (kind (WebAssemblywrapper tglobaladdr:$off), ty:$exp, ty:$new)), 747*0b57cec5SDimitry Andric (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$exp, ty:$new)>; 748*0b57cec5SDimitry Andric 749*0b57cec5SDimitry Andric// Patterns for various addressing modes. 750*0b57cec5SDimitry Andricmulticlass TerRMWPattern<PatFrag rmw_32, PatFrag rmw_64, NI inst_32, 751*0b57cec5SDimitry Andric NI inst_64> { 752*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i32, rmw_32, inst_32>; 753*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i64, rmw_64, inst_64>; 754*0b57cec5SDimitry Andric 755*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i32, rmw_32, regPlusImm, inst_32>; 756*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, rmw_64, regPlusImm, inst_64>; 757*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i32, rmw_32, or_is_add, inst_32>; 758*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, rmw_64, or_is_add, inst_64>; 759*0b57cec5SDimitry Andric 760*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i32, rmw_32, inst_32>; 761*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i64, rmw_64, inst_64>; 762*0b57cec5SDimitry Andric 763*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i32, rmw_32, inst_32>; 764*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i64, rmw_64, inst_64>; 765*0b57cec5SDimitry Andric 766*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i32, rmw_32, inst_32>; 767*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i64, rmw_64, inst_64>; 768*0b57cec5SDimitry Andric} 769*0b57cec5SDimitry Andric 770*0b57cec5SDimitry Andriclet Predicates = [HasAtomics] in 771*0b57cec5SDimitry Andricdefm : TerRMWPattern<atomic_cmp_swap_32, atomic_cmp_swap_64, 772*0b57cec5SDimitry Andric ATOMIC_RMW_CMPXCHG_I32, ATOMIC_RMW_CMPXCHG_I64>; 773*0b57cec5SDimitry Andric 774*0b57cec5SDimitry Andric// Truncating & zero-extending ternary RMW patterns. 775*0b57cec5SDimitry Andric// DAG legalization & optimization before instruction selection may introduce 776*0b57cec5SDimitry Andric// additional nodes such as anyext or assertzext depending on operand types. 777*0b57cec5SDimitry Andricclass zext_ter_rmw_8_32<PatFrag kind> : 778*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$exp, node:$new), 779*0b57cec5SDimitry Andric (and (i32 (kind node:$addr, node:$exp, node:$new)), 255)>; 780*0b57cec5SDimitry Andricclass zext_ter_rmw_16_32<PatFrag kind> : 781*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$exp, node:$new), 782*0b57cec5SDimitry Andric (and (i32 (kind node:$addr, node:$exp, node:$new)), 65535)>; 783*0b57cec5SDimitry Andricclass zext_ter_rmw_8_64<PatFrag kind> : 784*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$exp, node:$new), 785*0b57cec5SDimitry Andric (zext (i32 (assertzext (i32 (kind node:$addr, 786*0b57cec5SDimitry Andric (i32 (trunc (i64 node:$exp))), 787*0b57cec5SDimitry Andric (i32 (trunc (i64 node:$new))))))))>; 788*0b57cec5SDimitry Andricclass zext_ter_rmw_16_64<PatFrag kind> : zext_ter_rmw_8_64<kind>; 789*0b57cec5SDimitry Andricclass zext_ter_rmw_32_64<PatFrag kind> : 790*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$exp, node:$new), 791*0b57cec5SDimitry Andric (zext (i32 (kind node:$addr, 792*0b57cec5SDimitry Andric (i32 (trunc (i64 node:$exp))), 793*0b57cec5SDimitry Andric (i32 (trunc (i64 node:$new))))))>; 794*0b57cec5SDimitry Andric 795*0b57cec5SDimitry Andric// Truncating & sign-extending ternary RMW patterns. 796*0b57cec5SDimitry Andric// We match subword RMWs (for 32-bit) and anyext RMWs (for 64-bit) and select a 797*0b57cec5SDimitry Andric// zext RMW; the next instruction will be sext_inreg which is selected by 798*0b57cec5SDimitry Andric// itself. 799*0b57cec5SDimitry Andricclass sext_ter_rmw_8_32<PatFrag kind> : 800*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$exp, node:$new), 801*0b57cec5SDimitry Andric (kind node:$addr, node:$exp, node:$new)>; 802*0b57cec5SDimitry Andricclass sext_ter_rmw_16_32<PatFrag kind> : sext_ter_rmw_8_32<kind>; 803*0b57cec5SDimitry Andricclass sext_ter_rmw_8_64<PatFrag kind> : 804*0b57cec5SDimitry Andric PatFrag<(ops node:$addr, node:$exp, node:$new), 805*0b57cec5SDimitry Andric (anyext (i32 (assertzext (i32 806*0b57cec5SDimitry Andric (kind node:$addr, 807*0b57cec5SDimitry Andric (i32 (trunc (i64 node:$exp))), 808*0b57cec5SDimitry Andric (i32 (trunc (i64 node:$new))))))))>; 809*0b57cec5SDimitry Andricclass sext_ter_rmw_16_64<PatFrag kind> : sext_ter_rmw_8_64<kind>; 810*0b57cec5SDimitry Andric// 32->64 sext RMW gets selected as i32.atomic.rmw.***, i64.extend_i32_s 811*0b57cec5SDimitry Andric 812*0b57cec5SDimitry Andric// Patterns for various addressing modes for truncating-extending ternary RMWs. 813*0b57cec5SDimitry Andricmulticlass TerRMWTruncExtPattern< 814*0b57cec5SDimitry Andric PatFrag rmw_8, PatFrag rmw_16, PatFrag rmw_32, PatFrag rmw_64, 815*0b57cec5SDimitry Andric NI inst8_32, NI inst16_32, NI inst8_64, NI inst16_64, NI inst32_64> { 816*0b57cec5SDimitry Andric // Truncating-extending ternary RMWs with no constant offset 817*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i32, zext_ter_rmw_8_32<rmw_8>, inst8_32>; 818*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i32, zext_ter_rmw_16_32<rmw_16>, inst16_32>; 819*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i64, zext_ter_rmw_8_64<rmw_8>, inst8_64>; 820*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i64, zext_ter_rmw_16_64<rmw_16>, inst16_64>; 821*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i64, zext_ter_rmw_32_64<rmw_32>, inst32_64>; 822*0b57cec5SDimitry Andric 823*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i32, sext_ter_rmw_8_32<rmw_8>, inst8_32>; 824*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i32, sext_ter_rmw_16_32<rmw_16>, inst16_32>; 825*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i64, sext_ter_rmw_8_64<rmw_8>, inst8_64>; 826*0b57cec5SDimitry Andric def : TerRMWPatNoOffset<i64, sext_ter_rmw_16_64<rmw_16>, inst16_64>; 827*0b57cec5SDimitry Andric 828*0b57cec5SDimitry Andric // Truncating-extending ternary RMWs with a constant offset 829*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i32, zext_ter_rmw_8_32<rmw_8>, regPlusImm, inst8_32>; 830*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i32, zext_ter_rmw_16_32<rmw_16>, regPlusImm, inst16_32>; 831*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, zext_ter_rmw_8_64<rmw_8>, regPlusImm, inst8_64>; 832*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, zext_ter_rmw_16_64<rmw_16>, regPlusImm, inst16_64>; 833*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, zext_ter_rmw_32_64<rmw_32>, regPlusImm, inst32_64>; 834*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i32, zext_ter_rmw_8_32<rmw_8>, or_is_add, inst8_32>; 835*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i32, zext_ter_rmw_16_32<rmw_16>, or_is_add, inst16_32>; 836*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, zext_ter_rmw_8_64<rmw_8>, or_is_add, inst8_64>; 837*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, zext_ter_rmw_16_64<rmw_16>, or_is_add, inst16_64>; 838*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, zext_ter_rmw_32_64<rmw_32>, or_is_add, inst32_64>; 839*0b57cec5SDimitry Andric 840*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i32, sext_ter_rmw_8_32<rmw_8>, regPlusImm, inst8_32>; 841*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i32, sext_ter_rmw_16_32<rmw_16>, regPlusImm, inst16_32>; 842*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, sext_ter_rmw_8_64<rmw_8>, regPlusImm, inst8_64>; 843*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, sext_ter_rmw_16_64<rmw_16>, regPlusImm, inst16_64>; 844*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i32, sext_ter_rmw_8_32<rmw_8>, or_is_add, inst8_32>; 845*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i32, sext_ter_rmw_16_32<rmw_16>, or_is_add, inst16_32>; 846*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, sext_ter_rmw_8_64<rmw_8>, or_is_add, inst8_64>; 847*0b57cec5SDimitry Andric def : TerRMWPatImmOff<i64, sext_ter_rmw_16_64<rmw_16>, or_is_add, inst16_64>; 848*0b57cec5SDimitry Andric 849*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i32, zext_ter_rmw_8_32<rmw_8>, inst8_32>; 850*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i32, zext_ter_rmw_16_32<rmw_16>, inst16_32>; 851*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i64, zext_ter_rmw_8_64<rmw_8>, inst8_64>; 852*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i64, zext_ter_rmw_16_64<rmw_16>, inst16_64>; 853*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i64, zext_ter_rmw_32_64<rmw_32>, inst32_64>; 854*0b57cec5SDimitry Andric 855*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i32, sext_ter_rmw_8_32<rmw_8>, inst8_32>; 856*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i32, sext_ter_rmw_16_32<rmw_16>, inst16_32>; 857*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i64, sext_ter_rmw_8_64<rmw_8>, inst8_64>; 858*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddr<i64, sext_ter_rmw_16_64<rmw_16>, inst16_64>; 859*0b57cec5SDimitry Andric 860*0b57cec5SDimitry Andric // Truncating-extending ternary RMWs with just a constant offset 861*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i32, zext_ter_rmw_8_32<rmw_8>, inst8_32>; 862*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i32, zext_ter_rmw_16_32<rmw_16>, inst16_32>; 863*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i64, zext_ter_rmw_8_64<rmw_8>, inst8_64>; 864*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i64, zext_ter_rmw_16_64<rmw_16>, inst16_64>; 865*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i64, zext_ter_rmw_32_64<rmw_32>, inst32_64>; 866*0b57cec5SDimitry Andric 867*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i32, sext_ter_rmw_8_32<rmw_8>, inst8_32>; 868*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i32, sext_ter_rmw_16_32<rmw_16>, inst16_32>; 869*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i64, sext_ter_rmw_8_64<rmw_8>, inst8_64>; 870*0b57cec5SDimitry Andric def : TerRMWPatOffsetOnly<i64, sext_ter_rmw_16_64<rmw_16>, inst16_64>; 871*0b57cec5SDimitry Andric 872*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i32, zext_ter_rmw_8_32<rmw_8>, inst8_32>; 873*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i32, zext_ter_rmw_16_32<rmw_16>, inst16_32>; 874*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i64, zext_ter_rmw_8_64<rmw_8>, inst8_64>; 875*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i64, zext_ter_rmw_16_64<rmw_16>, inst16_64>; 876*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i64, zext_ter_rmw_32_64<rmw_32>, inst32_64>; 877*0b57cec5SDimitry Andric 878*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i32, sext_ter_rmw_8_32<rmw_8>, inst8_32>; 879*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i32, sext_ter_rmw_16_32<rmw_16>, inst16_32>; 880*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i64, sext_ter_rmw_8_64<rmw_8>, inst8_64>; 881*0b57cec5SDimitry Andric def : TerRMWPatGlobalAddrOffOnly<i64, sext_ter_rmw_16_64<rmw_16>, inst16_64>; 882*0b57cec5SDimitry Andric} 883*0b57cec5SDimitry Andric 884*0b57cec5SDimitry Andriclet Predicates = [HasAtomics] in 885*0b57cec5SDimitry Andricdefm : TerRMWTruncExtPattern< 886*0b57cec5SDimitry Andric atomic_cmp_swap_8, atomic_cmp_swap_16, atomic_cmp_swap_32, atomic_cmp_swap_64, 887*0b57cec5SDimitry Andric ATOMIC_RMW8_U_CMPXCHG_I32, ATOMIC_RMW16_U_CMPXCHG_I32, 888*0b57cec5SDimitry Andric ATOMIC_RMW8_U_CMPXCHG_I64, ATOMIC_RMW16_U_CMPXCHG_I64, 889*0b57cec5SDimitry Andric ATOMIC_RMW32_U_CMPXCHG_I64>; 890*0b57cec5SDimitry Andric 891*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 892*0b57cec5SDimitry Andric// Atomic fences 893*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 894*0b57cec5SDimitry Andric 895*0b57cec5SDimitry Andric// A compiler fence instruction that prevents reordering of instructions. 896*0b57cec5SDimitry Andriclet Defs = [ARGUMENTS] in { 897*0b57cec5SDimitry Andriclet isPseudo = 1, hasSideEffects = 1 in 898*0b57cec5SDimitry Andricdefm COMPILER_FENCE : ATOMIC_NRI<(outs), (ins), [], "compiler_fence">; 899*0b57cec5SDimitry Andric} // Defs = [ARGUMENTS] 900