xref: /aosp_15_r20/external/llvm/lib/Target/AArch64/AArch64InstrAtomics.td (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker//=- AArch64InstrAtomics.td - AArch64 Atomic codegen support -*- tablegen -*-=//
2*9880d681SAndroid Build Coastguard Worker//
3*9880d681SAndroid Build Coastguard Worker//                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker//
5*9880d681SAndroid Build Coastguard Worker// This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker// License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker//
8*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker//
10*9880d681SAndroid Build Coastguard Worker// AArch64 Atomic operand code-gen constructs.
11*9880d681SAndroid Build Coastguard Worker//
12*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker//===----------------------------------
15*9880d681SAndroid Build Coastguard Worker// Atomic fences
16*9880d681SAndroid Build Coastguard Worker//===----------------------------------
17*9880d681SAndroid Build Coastguard Workerdef : Pat<(atomic_fence (i64 4), (imm)), (DMB (i32 0x9))>;
18*9880d681SAndroid Build Coastguard Workerdef : Pat<(atomic_fence (imm), (imm)), (DMB (i32 0xb))>;
19*9880d681SAndroid Build Coastguard Worker
20*9880d681SAndroid Build Coastguard Worker//===----------------------------------
21*9880d681SAndroid Build Coastguard Worker// Atomic loads
22*9880d681SAndroid Build Coastguard Worker//===----------------------------------
23*9880d681SAndroid Build Coastguard Worker
24*9880d681SAndroid Build Coastguard Worker// When they're actually atomic, only one addressing mode (GPR64sp) is
25*9880d681SAndroid Build Coastguard Worker// supported, but when they're relaxed and anything can be used, all the
26*9880d681SAndroid Build Coastguard Worker// standard modes would be valid and may give efficiency gains.
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Worker// A atomic load operation that actually needs acquire semantics.
29*9880d681SAndroid Build Coastguard Workerclass acquiring_load<PatFrag base>
30*9880d681SAndroid Build Coastguard Worker  : PatFrag<(ops node:$ptr), (base node:$ptr), [{
31*9880d681SAndroid Build Coastguard Worker  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getOrdering();
32*9880d681SAndroid Build Coastguard Worker  return isAcquireOrStronger(Ordering);
33*9880d681SAndroid Build Coastguard Worker}]>;
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker// An atomic load operation that does not need either acquire or release
36*9880d681SAndroid Build Coastguard Worker// semantics.
37*9880d681SAndroid Build Coastguard Workerclass relaxed_load<PatFrag base>
38*9880d681SAndroid Build Coastguard Worker  : PatFrag<(ops node:$ptr), (base node:$ptr), [{
39*9880d681SAndroid Build Coastguard Worker  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getOrdering();
40*9880d681SAndroid Build Coastguard Worker  return !isAcquireOrStronger(Ordering);
41*9880d681SAndroid Build Coastguard Worker}]>;
42*9880d681SAndroid Build Coastguard Worker
43*9880d681SAndroid Build Coastguard Worker// 8-bit loads
44*9880d681SAndroid Build Coastguard Workerdef : Pat<(acquiring_load<atomic_load_8>  GPR64sp:$ptr), (LDARB GPR64sp:$ptr)>;
45*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_8> (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
46*9880d681SAndroid Build Coastguard Worker                                                     ro_Wextend8:$offset)),
47*9880d681SAndroid Build Coastguard Worker          (LDRBBroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$offset)>;
48*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_8> (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
49*9880d681SAndroid Build Coastguard Worker                                                     ro_Xextend8:$offset)),
50*9880d681SAndroid Build Coastguard Worker          (LDRBBroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$offset)>;
51*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_8> (am_indexed8 GPR64sp:$Rn,
52*9880d681SAndroid Build Coastguard Worker                                                    uimm12s1:$offset)),
53*9880d681SAndroid Build Coastguard Worker          (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>;
54*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_8>
55*9880d681SAndroid Build Coastguard Worker               (am_unscaled8 GPR64sp:$Rn, simm9:$offset)),
56*9880d681SAndroid Build Coastguard Worker          (LDURBBi GPR64sp:$Rn, simm9:$offset)>;
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker// 16-bit loads
59*9880d681SAndroid Build Coastguard Workerdef : Pat<(acquiring_load<atomic_load_16> GPR64sp:$ptr), (LDARH GPR64sp:$ptr)>;
60*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_16> (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
61*9880d681SAndroid Build Coastguard Worker                                                       ro_Wextend16:$extend)),
62*9880d681SAndroid Build Coastguard Worker          (LDRHHroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend)>;
63*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_16> (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
64*9880d681SAndroid Build Coastguard Worker                                                       ro_Xextend16:$extend)),
65*9880d681SAndroid Build Coastguard Worker          (LDRHHroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend)>;
66*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_16> (am_indexed16 GPR64sp:$Rn,
67*9880d681SAndroid Build Coastguard Worker                                                      uimm12s2:$offset)),
68*9880d681SAndroid Build Coastguard Worker          (LDRHHui GPR64sp:$Rn, uimm12s2:$offset)>;
69*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_16>
70*9880d681SAndroid Build Coastguard Worker               (am_unscaled16 GPR64sp:$Rn, simm9:$offset)),
71*9880d681SAndroid Build Coastguard Worker          (LDURHHi GPR64sp:$Rn, simm9:$offset)>;
72*9880d681SAndroid Build Coastguard Worker
73*9880d681SAndroid Build Coastguard Worker// 32-bit loads
74*9880d681SAndroid Build Coastguard Workerdef : Pat<(acquiring_load<atomic_load_32> GPR64sp:$ptr), (LDARW GPR64sp:$ptr)>;
75*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_32> (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
76*9880d681SAndroid Build Coastguard Worker                                                       ro_Wextend32:$extend)),
77*9880d681SAndroid Build Coastguard Worker          (LDRWroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>;
78*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_32> (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
79*9880d681SAndroid Build Coastguard Worker                                                       ro_Xextend32:$extend)),
80*9880d681SAndroid Build Coastguard Worker          (LDRWroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>;
81*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_32> (am_indexed32 GPR64sp:$Rn,
82*9880d681SAndroid Build Coastguard Worker                                                      uimm12s4:$offset)),
83*9880d681SAndroid Build Coastguard Worker          (LDRWui GPR64sp:$Rn, uimm12s4:$offset)>;
84*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_32>
85*9880d681SAndroid Build Coastguard Worker               (am_unscaled32 GPR64sp:$Rn, simm9:$offset)),
86*9880d681SAndroid Build Coastguard Worker          (LDURWi GPR64sp:$Rn, simm9:$offset)>;
87*9880d681SAndroid Build Coastguard Worker
88*9880d681SAndroid Build Coastguard Worker// 64-bit loads
89*9880d681SAndroid Build Coastguard Workerdef : Pat<(acquiring_load<atomic_load_64> GPR64sp:$ptr), (LDARX GPR64sp:$ptr)>;
90*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_64> (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
91*9880d681SAndroid Build Coastguard Worker                                                       ro_Wextend64:$extend)),
92*9880d681SAndroid Build Coastguard Worker          (LDRXroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>;
93*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_64> (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
94*9880d681SAndroid Build Coastguard Worker                                                       ro_Xextend64:$extend)),
95*9880d681SAndroid Build Coastguard Worker          (LDRXroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>;
96*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_64> (am_indexed64 GPR64sp:$Rn,
97*9880d681SAndroid Build Coastguard Worker                                                      uimm12s8:$offset)),
98*9880d681SAndroid Build Coastguard Worker          (LDRXui GPR64sp:$Rn, uimm12s8:$offset)>;
99*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_load<atomic_load_64>
100*9880d681SAndroid Build Coastguard Worker               (am_unscaled64 GPR64sp:$Rn, simm9:$offset)),
101*9880d681SAndroid Build Coastguard Worker          (LDURXi GPR64sp:$Rn, simm9:$offset)>;
102*9880d681SAndroid Build Coastguard Worker
103*9880d681SAndroid Build Coastguard Worker//===----------------------------------
104*9880d681SAndroid Build Coastguard Worker// Atomic stores
105*9880d681SAndroid Build Coastguard Worker//===----------------------------------
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker// When they're actually atomic, only one addressing mode (GPR64sp) is
108*9880d681SAndroid Build Coastguard Worker// supported, but when they're relaxed and anything can be used, all the
109*9880d681SAndroid Build Coastguard Worker// standard modes would be valid and may give efficiency gains.
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker// A store operation that actually needs release semantics.
112*9880d681SAndroid Build Coastguard Workerclass releasing_store<PatFrag base>
113*9880d681SAndroid Build Coastguard Worker  : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{
114*9880d681SAndroid Build Coastguard Worker  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getOrdering();
115*9880d681SAndroid Build Coastguard Worker  assert(Ordering != AtomicOrdering::AcquireRelease &&
116*9880d681SAndroid Build Coastguard Worker         "unexpected store ordering");
117*9880d681SAndroid Build Coastguard Worker  return isReleaseOrStronger(Ordering);
118*9880d681SAndroid Build Coastguard Worker}]>;
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker// An atomic store operation that doesn't actually need to be atomic on AArch64.
121*9880d681SAndroid Build Coastguard Workerclass relaxed_store<PatFrag base>
122*9880d681SAndroid Build Coastguard Worker  : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{
123*9880d681SAndroid Build Coastguard Worker  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getOrdering();
124*9880d681SAndroid Build Coastguard Worker  return !isReleaseOrStronger(Ordering);
125*9880d681SAndroid Build Coastguard Worker}]>;
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker// 8-bit stores
128*9880d681SAndroid Build Coastguard Workerdef : Pat<(releasing_store<atomic_store_8> GPR64sp:$ptr, GPR32:$val),
129*9880d681SAndroid Build Coastguard Worker          (STLRB GPR32:$val, GPR64sp:$ptr)>;
130*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_8>
131*9880d681SAndroid Build Coastguard Worker               (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
132*9880d681SAndroid Build Coastguard Worker               GPR32:$val),
133*9880d681SAndroid Build Coastguard Worker          (STRBBroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend)>;
134*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_8>
135*9880d681SAndroid Build Coastguard Worker               (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
136*9880d681SAndroid Build Coastguard Worker               GPR32:$val),
137*9880d681SAndroid Build Coastguard Worker          (STRBBroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend)>;
138*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_8>
139*9880d681SAndroid Build Coastguard Worker               (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset), GPR32:$val),
140*9880d681SAndroid Build Coastguard Worker          (STRBBui GPR32:$val, GPR64sp:$Rn, uimm12s1:$offset)>;
141*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_8>
142*9880d681SAndroid Build Coastguard Worker               (am_unscaled8 GPR64sp:$Rn, simm9:$offset), GPR32:$val),
143*9880d681SAndroid Build Coastguard Worker          (STURBBi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>;
144*9880d681SAndroid Build Coastguard Worker
145*9880d681SAndroid Build Coastguard Worker// 16-bit stores
146*9880d681SAndroid Build Coastguard Workerdef : Pat<(releasing_store<atomic_store_16> GPR64sp:$ptr, GPR32:$val),
147*9880d681SAndroid Build Coastguard Worker          (STLRH GPR32:$val, GPR64sp:$ptr)>;
148*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_16> (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
149*9880d681SAndroid Build Coastguard Worker                                                         ro_Wextend16:$extend),
150*9880d681SAndroid Build Coastguard Worker                                          GPR32:$val),
151*9880d681SAndroid Build Coastguard Worker          (STRHHroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend)>;
152*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_16> (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
153*9880d681SAndroid Build Coastguard Worker                                                         ro_Xextend16:$extend),
154*9880d681SAndroid Build Coastguard Worker                                          GPR32:$val),
155*9880d681SAndroid Build Coastguard Worker          (STRHHroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend)>;
156*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_16>
157*9880d681SAndroid Build Coastguard Worker              (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset), GPR32:$val),
158*9880d681SAndroid Build Coastguard Worker          (STRHHui GPR32:$val, GPR64sp:$Rn, uimm12s2:$offset)>;
159*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_16>
160*9880d681SAndroid Build Coastguard Worker               (am_unscaled16 GPR64sp:$Rn, simm9:$offset), GPR32:$val),
161*9880d681SAndroid Build Coastguard Worker          (STURHHi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>;
162*9880d681SAndroid Build Coastguard Worker
163*9880d681SAndroid Build Coastguard Worker// 32-bit stores
164*9880d681SAndroid Build Coastguard Workerdef : Pat<(releasing_store<atomic_store_32> GPR64sp:$ptr, GPR32:$val),
165*9880d681SAndroid Build Coastguard Worker          (STLRW GPR32:$val, GPR64sp:$ptr)>;
166*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_32> (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
167*9880d681SAndroid Build Coastguard Worker                                                         ro_Wextend32:$extend),
168*9880d681SAndroid Build Coastguard Worker                                          GPR32:$val),
169*9880d681SAndroid Build Coastguard Worker          (STRWroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>;
170*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_32> (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
171*9880d681SAndroid Build Coastguard Worker                                                         ro_Xextend32:$extend),
172*9880d681SAndroid Build Coastguard Worker                                          GPR32:$val),
173*9880d681SAndroid Build Coastguard Worker          (STRWroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>;
174*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_32>
175*9880d681SAndroid Build Coastguard Worker              (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset), GPR32:$val),
176*9880d681SAndroid Build Coastguard Worker          (STRWui GPR32:$val, GPR64sp:$Rn, uimm12s4:$offset)>;
177*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_32>
178*9880d681SAndroid Build Coastguard Worker               (am_unscaled32 GPR64sp:$Rn, simm9:$offset), GPR32:$val),
179*9880d681SAndroid Build Coastguard Worker          (STURWi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>;
180*9880d681SAndroid Build Coastguard Worker
181*9880d681SAndroid Build Coastguard Worker// 64-bit stores
182*9880d681SAndroid Build Coastguard Workerdef : Pat<(releasing_store<atomic_store_64> GPR64sp:$ptr, GPR64:$val),
183*9880d681SAndroid Build Coastguard Worker          (STLRX GPR64:$val, GPR64sp:$ptr)>;
184*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_64> (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
185*9880d681SAndroid Build Coastguard Worker                                                         ro_Wextend16:$extend),
186*9880d681SAndroid Build Coastguard Worker                                          GPR64:$val),
187*9880d681SAndroid Build Coastguard Worker          (STRXroW GPR64:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>;
188*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_64> (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
189*9880d681SAndroid Build Coastguard Worker                                                         ro_Xextend16:$extend),
190*9880d681SAndroid Build Coastguard Worker                                          GPR64:$val),
191*9880d681SAndroid Build Coastguard Worker          (STRXroX GPR64:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>;
192*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_64>
193*9880d681SAndroid Build Coastguard Worker              (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset), GPR64:$val),
194*9880d681SAndroid Build Coastguard Worker          (STRXui GPR64:$val, GPR64sp:$Rn, uimm12s8:$offset)>;
195*9880d681SAndroid Build Coastguard Workerdef : Pat<(relaxed_store<atomic_store_64>
196*9880d681SAndroid Build Coastguard Worker               (am_unscaled64 GPR64sp:$Rn, simm9:$offset), GPR64:$val),
197*9880d681SAndroid Build Coastguard Worker          (STURXi GPR64:$val, GPR64sp:$Rn, simm9:$offset)>;
198*9880d681SAndroid Build Coastguard Worker
199*9880d681SAndroid Build Coastguard Worker//===----------------------------------
200*9880d681SAndroid Build Coastguard Worker// Low-level exclusive operations
201*9880d681SAndroid Build Coastguard Worker//===----------------------------------
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Worker// Load-exclusives.
204*9880d681SAndroid Build Coastguard Worker
205*9880d681SAndroid Build Coastguard Workerdef ldxr_1 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{
206*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
207*9880d681SAndroid Build Coastguard Worker}]>;
208*9880d681SAndroid Build Coastguard Worker
209*9880d681SAndroid Build Coastguard Workerdef ldxr_2 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{
210*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
211*9880d681SAndroid Build Coastguard Worker}]>;
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Workerdef ldxr_4 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{
214*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
215*9880d681SAndroid Build Coastguard Worker}]>;
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Workerdef ldxr_8 : PatFrag<(ops node:$ptr), (int_aarch64_ldxr node:$ptr), [{
218*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
219*9880d681SAndroid Build Coastguard Worker}]>;
220*9880d681SAndroid Build Coastguard Worker
221*9880d681SAndroid Build Coastguard Workerdef : Pat<(ldxr_1 GPR64sp:$addr),
222*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDXRB GPR64sp:$addr), sub_32)>;
223*9880d681SAndroid Build Coastguard Workerdef : Pat<(ldxr_2 GPR64sp:$addr),
224*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDXRH GPR64sp:$addr), sub_32)>;
225*9880d681SAndroid Build Coastguard Workerdef : Pat<(ldxr_4 GPR64sp:$addr),
226*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDXRW GPR64sp:$addr), sub_32)>;
227*9880d681SAndroid Build Coastguard Workerdef : Pat<(ldxr_8 GPR64sp:$addr), (LDXRX GPR64sp:$addr)>;
228*9880d681SAndroid Build Coastguard Worker
229*9880d681SAndroid Build Coastguard Workerdef : Pat<(and (ldxr_1 GPR64sp:$addr), 0xff),
230*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDXRB GPR64sp:$addr), sub_32)>;
231*9880d681SAndroid Build Coastguard Workerdef : Pat<(and (ldxr_2 GPR64sp:$addr), 0xffff),
232*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDXRH GPR64sp:$addr), sub_32)>;
233*9880d681SAndroid Build Coastguard Workerdef : Pat<(and (ldxr_4 GPR64sp:$addr), 0xffffffff),
234*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDXRW GPR64sp:$addr), sub_32)>;
235*9880d681SAndroid Build Coastguard Worker
236*9880d681SAndroid Build Coastguard Worker// Load-exclusives.
237*9880d681SAndroid Build Coastguard Worker
238*9880d681SAndroid Build Coastguard Workerdef ldaxr_1 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{
239*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
240*9880d681SAndroid Build Coastguard Worker}]>;
241*9880d681SAndroid Build Coastguard Worker
242*9880d681SAndroid Build Coastguard Workerdef ldaxr_2 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{
243*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
244*9880d681SAndroid Build Coastguard Worker}]>;
245*9880d681SAndroid Build Coastguard Worker
246*9880d681SAndroid Build Coastguard Workerdef ldaxr_4 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{
247*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
248*9880d681SAndroid Build Coastguard Worker}]>;
249*9880d681SAndroid Build Coastguard Worker
250*9880d681SAndroid Build Coastguard Workerdef ldaxr_8 : PatFrag<(ops node:$ptr), (int_aarch64_ldaxr node:$ptr), [{
251*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
252*9880d681SAndroid Build Coastguard Worker}]>;
253*9880d681SAndroid Build Coastguard Worker
254*9880d681SAndroid Build Coastguard Workerdef : Pat<(ldaxr_1 GPR64sp:$addr),
255*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDAXRB GPR64sp:$addr), sub_32)>;
256*9880d681SAndroid Build Coastguard Workerdef : Pat<(ldaxr_2 GPR64sp:$addr),
257*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDAXRH GPR64sp:$addr), sub_32)>;
258*9880d681SAndroid Build Coastguard Workerdef : Pat<(ldaxr_4 GPR64sp:$addr),
259*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDAXRW GPR64sp:$addr), sub_32)>;
260*9880d681SAndroid Build Coastguard Workerdef : Pat<(ldaxr_8 GPR64sp:$addr), (LDAXRX GPR64sp:$addr)>;
261*9880d681SAndroid Build Coastguard Worker
262*9880d681SAndroid Build Coastguard Workerdef : Pat<(and (ldaxr_1 GPR64sp:$addr), 0xff),
263*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDAXRB GPR64sp:$addr), sub_32)>;
264*9880d681SAndroid Build Coastguard Workerdef : Pat<(and (ldaxr_2 GPR64sp:$addr), 0xffff),
265*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDAXRH GPR64sp:$addr), sub_32)>;
266*9880d681SAndroid Build Coastguard Workerdef : Pat<(and (ldaxr_4 GPR64sp:$addr), 0xffffffff),
267*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (LDAXRW GPR64sp:$addr), sub_32)>;
268*9880d681SAndroid Build Coastguard Worker
269*9880d681SAndroid Build Coastguard Worker// Store-exclusives.
270*9880d681SAndroid Build Coastguard Worker
271*9880d681SAndroid Build Coastguard Workerdef stxr_1 : PatFrag<(ops node:$val, node:$ptr),
272*9880d681SAndroid Build Coastguard Worker                     (int_aarch64_stxr node:$val, node:$ptr), [{
273*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
274*9880d681SAndroid Build Coastguard Worker}]>;
275*9880d681SAndroid Build Coastguard Worker
276*9880d681SAndroid Build Coastguard Workerdef stxr_2 : PatFrag<(ops node:$val, node:$ptr),
277*9880d681SAndroid Build Coastguard Worker                     (int_aarch64_stxr node:$val, node:$ptr), [{
278*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
279*9880d681SAndroid Build Coastguard Worker}]>;
280*9880d681SAndroid Build Coastguard Worker
281*9880d681SAndroid Build Coastguard Workerdef stxr_4 : PatFrag<(ops node:$val, node:$ptr),
282*9880d681SAndroid Build Coastguard Worker                     (int_aarch64_stxr node:$val, node:$ptr), [{
283*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
284*9880d681SAndroid Build Coastguard Worker}]>;
285*9880d681SAndroid Build Coastguard Worker
286*9880d681SAndroid Build Coastguard Workerdef stxr_8 : PatFrag<(ops node:$val, node:$ptr),
287*9880d681SAndroid Build Coastguard Worker                     (int_aarch64_stxr node:$val, node:$ptr), [{
288*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
289*9880d681SAndroid Build Coastguard Worker}]>;
290*9880d681SAndroid Build Coastguard Worker
291*9880d681SAndroid Build Coastguard Worker
292*9880d681SAndroid Build Coastguard Workerdef : Pat<(stxr_1 GPR64:$val, GPR64sp:$addr),
293*9880d681SAndroid Build Coastguard Worker          (STXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
294*9880d681SAndroid Build Coastguard Workerdef : Pat<(stxr_2 GPR64:$val, GPR64sp:$addr),
295*9880d681SAndroid Build Coastguard Worker          (STXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
296*9880d681SAndroid Build Coastguard Workerdef : Pat<(stxr_4 GPR64:$val, GPR64sp:$addr),
297*9880d681SAndroid Build Coastguard Worker          (STXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
298*9880d681SAndroid Build Coastguard Workerdef : Pat<(stxr_8 GPR64:$val, GPR64sp:$addr),
299*9880d681SAndroid Build Coastguard Worker          (STXRX GPR64:$val, GPR64sp:$addr)>;
300*9880d681SAndroid Build Coastguard Worker
301*9880d681SAndroid Build Coastguard Workerdef : Pat<(stxr_1 (zext (and GPR32:$val, 0xff)), GPR64sp:$addr),
302*9880d681SAndroid Build Coastguard Worker          (STXRB GPR32:$val, GPR64sp:$addr)>;
303*9880d681SAndroid Build Coastguard Workerdef : Pat<(stxr_2 (zext (and GPR32:$val, 0xffff)), GPR64sp:$addr),
304*9880d681SAndroid Build Coastguard Worker          (STXRH GPR32:$val, GPR64sp:$addr)>;
305*9880d681SAndroid Build Coastguard Workerdef : Pat<(stxr_4 (zext GPR32:$val), GPR64sp:$addr),
306*9880d681SAndroid Build Coastguard Worker          (STXRW GPR32:$val, GPR64sp:$addr)>;
307*9880d681SAndroid Build Coastguard Worker
308*9880d681SAndroid Build Coastguard Workerdef : Pat<(stxr_1 (and GPR64:$val, 0xff), GPR64sp:$addr),
309*9880d681SAndroid Build Coastguard Worker          (STXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
310*9880d681SAndroid Build Coastguard Workerdef : Pat<(stxr_2 (and GPR64:$val, 0xffff), GPR64sp:$addr),
311*9880d681SAndroid Build Coastguard Worker          (STXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
312*9880d681SAndroid Build Coastguard Workerdef : Pat<(stxr_4 (and GPR64:$val, 0xffffffff), GPR64sp:$addr),
313*9880d681SAndroid Build Coastguard Worker          (STXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
314*9880d681SAndroid Build Coastguard Worker
315*9880d681SAndroid Build Coastguard Worker// Store-release-exclusives.
316*9880d681SAndroid Build Coastguard Worker
317*9880d681SAndroid Build Coastguard Workerdef stlxr_1 : PatFrag<(ops node:$val, node:$ptr),
318*9880d681SAndroid Build Coastguard Worker                     (int_aarch64_stlxr node:$val, node:$ptr), [{
319*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
320*9880d681SAndroid Build Coastguard Worker}]>;
321*9880d681SAndroid Build Coastguard Worker
322*9880d681SAndroid Build Coastguard Workerdef stlxr_2 : PatFrag<(ops node:$val, node:$ptr),
323*9880d681SAndroid Build Coastguard Worker                     (int_aarch64_stlxr node:$val, node:$ptr), [{
324*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
325*9880d681SAndroid Build Coastguard Worker}]>;
326*9880d681SAndroid Build Coastguard Worker
327*9880d681SAndroid Build Coastguard Workerdef stlxr_4 : PatFrag<(ops node:$val, node:$ptr),
328*9880d681SAndroid Build Coastguard Worker                     (int_aarch64_stlxr node:$val, node:$ptr), [{
329*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
330*9880d681SAndroid Build Coastguard Worker}]>;
331*9880d681SAndroid Build Coastguard Worker
332*9880d681SAndroid Build Coastguard Workerdef stlxr_8 : PatFrag<(ops node:$val, node:$ptr),
333*9880d681SAndroid Build Coastguard Worker                     (int_aarch64_stlxr node:$val, node:$ptr), [{
334*9880d681SAndroid Build Coastguard Worker  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
335*9880d681SAndroid Build Coastguard Worker}]>;
336*9880d681SAndroid Build Coastguard Worker
337*9880d681SAndroid Build Coastguard Worker
338*9880d681SAndroid Build Coastguard Workerdef : Pat<(stlxr_1 GPR64:$val, GPR64sp:$addr),
339*9880d681SAndroid Build Coastguard Worker          (STLXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
340*9880d681SAndroid Build Coastguard Workerdef : Pat<(stlxr_2 GPR64:$val, GPR64sp:$addr),
341*9880d681SAndroid Build Coastguard Worker          (STLXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
342*9880d681SAndroid Build Coastguard Workerdef : Pat<(stlxr_4 GPR64:$val, GPR64sp:$addr),
343*9880d681SAndroid Build Coastguard Worker          (STLXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
344*9880d681SAndroid Build Coastguard Workerdef : Pat<(stlxr_8 GPR64:$val, GPR64sp:$addr),
345*9880d681SAndroid Build Coastguard Worker          (STLXRX GPR64:$val, GPR64sp:$addr)>;
346*9880d681SAndroid Build Coastguard Worker
347*9880d681SAndroid Build Coastguard Workerdef : Pat<(stlxr_1 (zext (and GPR32:$val, 0xff)), GPR64sp:$addr),
348*9880d681SAndroid Build Coastguard Worker          (STLXRB GPR32:$val, GPR64sp:$addr)>;
349*9880d681SAndroid Build Coastguard Workerdef : Pat<(stlxr_2 (zext (and GPR32:$val, 0xffff)), GPR64sp:$addr),
350*9880d681SAndroid Build Coastguard Worker          (STLXRH GPR32:$val, GPR64sp:$addr)>;
351*9880d681SAndroid Build Coastguard Workerdef : Pat<(stlxr_4 (zext GPR32:$val), GPR64sp:$addr),
352*9880d681SAndroid Build Coastguard Worker          (STLXRW GPR32:$val, GPR64sp:$addr)>;
353*9880d681SAndroid Build Coastguard Worker
354*9880d681SAndroid Build Coastguard Workerdef : Pat<(stlxr_1 (and GPR64:$val, 0xff), GPR64sp:$addr),
355*9880d681SAndroid Build Coastguard Worker          (STLXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
356*9880d681SAndroid Build Coastguard Workerdef : Pat<(stlxr_2 (and GPR64:$val, 0xffff), GPR64sp:$addr),
357*9880d681SAndroid Build Coastguard Worker          (STLXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
358*9880d681SAndroid Build Coastguard Workerdef : Pat<(stlxr_4 (and GPR64:$val, 0xffffffff), GPR64sp:$addr),
359*9880d681SAndroid Build Coastguard Worker          (STLXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>;
360*9880d681SAndroid Build Coastguard Worker
361*9880d681SAndroid Build Coastguard Worker
362*9880d681SAndroid Build Coastguard Worker// And clear exclusive.
363*9880d681SAndroid Build Coastguard Worker
364*9880d681SAndroid Build Coastguard Workerdef : Pat<(int_aarch64_clrex), (CLREX 0xf)>;
365*9880d681SAndroid Build Coastguard Worker
366*9880d681SAndroid Build Coastguard Worker//===----------------------------------
367*9880d681SAndroid Build Coastguard Worker// Atomic cmpxchg for -O0
368*9880d681SAndroid Build Coastguard Worker//===----------------------------------
369*9880d681SAndroid Build Coastguard Worker
370*9880d681SAndroid Build Coastguard Worker// The fast register allocator used during -O0 inserts spills to cover any VRegs
371*9880d681SAndroid Build Coastguard Worker// live across basic block boundaries. When this happens between an LDXR and an
372*9880d681SAndroid Build Coastguard Worker// STXR it can clear the exclusive monitor, causing all cmpxchg attempts to
373*9880d681SAndroid Build Coastguard Worker// fail.
374*9880d681SAndroid Build Coastguard Worker
375*9880d681SAndroid Build Coastguard Worker// Unfortunately, this means we have to have an alternative (expanded
376*9880d681SAndroid Build Coastguard Worker// post-regalloc) path for -O0 compilations. Fortunately this path can be
377*9880d681SAndroid Build Coastguard Worker// significantly more naive than the standard expansion: we conservatively
378*9880d681SAndroid Build Coastguard Worker// assume seq_cst, strong cmpxchg and omit clrex on failure.
379*9880d681SAndroid Build Coastguard Worker
380*9880d681SAndroid Build Coastguard Workerlet Constraints = "@earlyclobber $Rd,@earlyclobber $status",
381*9880d681SAndroid Build Coastguard Worker    mayLoad = 1, mayStore = 1 in {
382*9880d681SAndroid Build Coastguard Workerdef CMP_SWAP_8 : Pseudo<(outs GPR32:$Rd, GPR32:$status),
383*9880d681SAndroid Build Coastguard Worker                        (ins GPR64:$addr, GPR32:$desired, GPR32:$new), []>,
384*9880d681SAndroid Build Coastguard Worker                 Sched<[WriteAtomic]>;
385*9880d681SAndroid Build Coastguard Worker
386*9880d681SAndroid Build Coastguard Workerdef CMP_SWAP_16 : Pseudo<(outs GPR32:$Rd, GPR32:$status),
387*9880d681SAndroid Build Coastguard Worker                         (ins GPR64:$addr, GPR32:$desired, GPR32:$new), []>,
388*9880d681SAndroid Build Coastguard Worker                  Sched<[WriteAtomic]>;
389*9880d681SAndroid Build Coastguard Worker
390*9880d681SAndroid Build Coastguard Workerdef CMP_SWAP_32 : Pseudo<(outs GPR32:$Rd, GPR32:$status),
391*9880d681SAndroid Build Coastguard Worker                         (ins GPR64:$addr, GPR32:$desired, GPR32:$new), []>,
392*9880d681SAndroid Build Coastguard Worker                  Sched<[WriteAtomic]>;
393*9880d681SAndroid Build Coastguard Worker
394*9880d681SAndroid Build Coastguard Workerdef CMP_SWAP_64 : Pseudo<(outs GPR64:$Rd, GPR32:$status),
395*9880d681SAndroid Build Coastguard Worker                         (ins GPR64:$addr, GPR64:$desired, GPR64:$new), []>,
396*9880d681SAndroid Build Coastguard Worker                  Sched<[WriteAtomic]>;
397*9880d681SAndroid Build Coastguard Worker}
398*9880d681SAndroid Build Coastguard Worker
399*9880d681SAndroid Build Coastguard Workerlet Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi,@earlyclobber $status",
400*9880d681SAndroid Build Coastguard Worker    mayLoad = 1, mayStore = 1 in
401*9880d681SAndroid Build Coastguard Workerdef CMP_SWAP_128 : Pseudo<(outs GPR64:$RdLo, GPR64:$RdHi, GPR32:$status),
402*9880d681SAndroid Build Coastguard Worker                          (ins GPR64:$addr, GPR64:$desiredLo, GPR64:$desiredHi,
403*9880d681SAndroid Build Coastguard Worker                               GPR64:$newLo, GPR64:$newHi), []>,
404*9880d681SAndroid Build Coastguard Worker                   Sched<[WriteAtomic]>;
405