]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td
MFV r337027:
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / WebAssembly / WebAssemblyInstrAtomics.td
1 // WebAssemblyInstrAtomics.td-WebAssembly Atomic codegen support-*- tablegen -*-
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief WebAssembly Atomic operand code-gen constructs.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 //===----------------------------------------------------------------------===//
16 // Atomic loads
17 //===----------------------------------------------------------------------===//
18
19 let Defs = [ARGUMENTS] in {
20 def ATOMIC_LOAD_I32 : WebAssemblyLoad<I32, "i32.atomic.load", 0xfe10>;
21 def ATOMIC_LOAD_I64 : WebAssemblyLoad<I64, "i64.atomic.load", 0xfe11>;
22 } // Defs = [ARGUMENTS]
23
24 // Select loads with no constant offset.
25 let Predicates = [HasAtomics] in {
26 def : LoadPatNoOffset<i32, atomic_load_32, ATOMIC_LOAD_I32>;
27 def : LoadPatNoOffset<i64, atomic_load_64, ATOMIC_LOAD_I64>;
28
29 // Select loads with a constant offset.
30
31 // Pattern with address + immediate offset
32 def : LoadPatImmOff<i32, atomic_load_32, regPlusImm, ATOMIC_LOAD_I32>;
33 def : LoadPatImmOff<i64, atomic_load_64, regPlusImm, ATOMIC_LOAD_I64>;
34 def : LoadPatImmOff<i32, atomic_load_32, or_is_add, ATOMIC_LOAD_I32>;
35 def : LoadPatImmOff<i64, atomic_load_64, or_is_add, ATOMIC_LOAD_I64>;
36
37 def : LoadPatGlobalAddr<i32, atomic_load_32, ATOMIC_LOAD_I32>;
38 def : LoadPatGlobalAddr<i64, atomic_load_64, ATOMIC_LOAD_I64>;
39
40 def : LoadPatExternalSym<i32, atomic_load_32, ATOMIC_LOAD_I32>;
41 def : LoadPatExternalSym<i64, atomic_load_64, ATOMIC_LOAD_I64>;
42
43
44 // Select loads with just a constant offset.
45 def : LoadPatOffsetOnly<i32, atomic_load_32, ATOMIC_LOAD_I32>;
46 def : LoadPatOffsetOnly<i64, atomic_load_64, ATOMIC_LOAD_I64>;
47
48 def : LoadPatGlobalAddrOffOnly<i32, atomic_load_32, ATOMIC_LOAD_I32>;
49 def : LoadPatGlobalAddrOffOnly<i64, atomic_load_64, ATOMIC_LOAD_I64>;
50
51 def : LoadPatExternSymOffOnly<i32, atomic_load_32, ATOMIC_LOAD_I32>;
52 def : LoadPatExternSymOffOnly<i64, atomic_load_64, ATOMIC_LOAD_I64>;
53
54 } // Predicates = [HasAtomics]
55
56 // Extending loads. Note that there are only zero-extending atomic loads, no
57 // sign-extending loads.
58 let Defs = [ARGUMENTS] in {
59 def ATOMIC_LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.atomic.load8_u", 0xfe12>;
60 def ATOMIC_LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.atomic.load16_u", 0xfe13>;
61 def ATOMIC_LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.atomic.load8_u", 0xfe14>;
62 def ATOMIC_LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.atomic.load16_u", 0xfe15>;
63 def ATOMIC_LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.atomic.load32_u", 0xfe16>;
64 } // Defs = [ARGUMENTS]
65
66 // Fragments for exending loads. These are different from regular loads because
67 // the SDNodes are derived from AtomicSDNode rather than LoadSDNode and
68 // therefore don't have the extension type field. So instead of matching that,
69 // we match the patterns that the type legalizer expands them to.
70
71 // We directly match zext patterns and select the zext atomic loads.
72 // i32 (zext (i8 (atomic_load_8))) gets legalized to
73 // i32 (and (i32 (atomic_load_8)), 255)
74 // These can be selected to a single zero-extending atomic load instruction.
75 def zext_aload_8 : PatFrag<(ops node:$addr),
76                            (and (i32 (atomic_load_8 node:$addr)), 255)>;
77 def zext_aload_16 : PatFrag<(ops node:$addr),
78                             (and (i32 (atomic_load_16 node:$addr)), 65535)>;
79 // Unlike regular loads, extension to i64 is handled differently than i32.
80 // i64 (zext (i8 (atomic_load_8))) gets legalized to
81 // i64 (and (i64 (anyext (i32 (atomic_load_8)))), 255)
82 def zext_aload_8_64 :
83   PatFrag<(ops node:$addr),
84           (and (i64 (anyext (i32 (atomic_load_8 node:$addr)))), 255)>;
85 def zext_aload_16_64 :
86   PatFrag<(ops node:$addr),
87           (and (i64 (anyext (i32 (atomic_load_16 node:$addr)))), 65535)>;
88 def zext_aload_32_64 :
89   PatFrag<(ops node:$addr),
90           (zext (i32 (atomic_load node:$addr)))>;
91
92 // We don't have single sext atomic load instructions. So for sext loads, we
93 // match bare subword loads (for 32-bit results) and anyext loads (for 64-bit
94 // results) and select a zext load; the next instruction will be sext_inreg
95 // which is selected by itself.
96 def anyext_aload_8_64 :
97   PatFrag<(ops node:$addr), (anyext (i32 (atomic_load_8 node:$addr)))>;
98 def anyext_aload_16_64 :
99   PatFrag<(ops node:$addr), (anyext (i32 (atomic_load_16 node:$addr)))>;
100
101 let Predicates = [HasAtomics] in {
102 // Select zero-extending loads with no constant offset.
103 def : LoadPatNoOffset<i32, zext_aload_8, ATOMIC_LOAD8_U_I32>;
104 def : LoadPatNoOffset<i32, zext_aload_16, ATOMIC_LOAD16_U_I32>;
105 def : LoadPatNoOffset<i64, zext_aload_8_64, ATOMIC_LOAD8_U_I64>;
106 def : LoadPatNoOffset<i64, zext_aload_16_64, ATOMIC_LOAD16_U_I64>;
107 def : LoadPatNoOffset<i64, zext_aload_32_64, ATOMIC_LOAD32_U_I64>;
108
109 // Select sign-extending loads with no constant offset
110 def : LoadPatNoOffset<i32, atomic_load_8, ATOMIC_LOAD8_U_I32>;
111 def : LoadPatNoOffset<i32, atomic_load_16, ATOMIC_LOAD16_U_I32>;
112 def : LoadPatNoOffset<i64, anyext_aload_8_64, ATOMIC_LOAD8_U_I64>;
113 def : LoadPatNoOffset<i64, anyext_aload_16_64, ATOMIC_LOAD16_U_I64>;
114 // 32->64 sext load gets selected as i32.atomic.load, i64.extend_s/i64
115
116
117 // Zero-extending loads with constant offset
118 def : LoadPatImmOff<i32, zext_aload_8, regPlusImm, ATOMIC_LOAD8_U_I32>;
119 def : LoadPatImmOff<i32, zext_aload_16, regPlusImm, ATOMIC_LOAD16_U_I32>;
120 def : LoadPatImmOff<i32, zext_aload_8, or_is_add, ATOMIC_LOAD8_U_I32>;
121 def : LoadPatImmOff<i32, zext_aload_16, or_is_add, ATOMIC_LOAD16_U_I32>;
122 def : LoadPatImmOff<i64, zext_aload_8_64, regPlusImm, ATOMIC_LOAD8_U_I64>;
123 def : LoadPatImmOff<i64, zext_aload_16_64, regPlusImm, ATOMIC_LOAD16_U_I64>;
124 def : LoadPatImmOff<i64, zext_aload_32_64, regPlusImm, ATOMIC_LOAD32_U_I64>;
125 def : LoadPatImmOff<i64, zext_aload_8_64, or_is_add, ATOMIC_LOAD8_U_I64>;
126 def : LoadPatImmOff<i64, zext_aload_16_64, or_is_add, ATOMIC_LOAD16_U_I64>;
127 def : LoadPatImmOff<i64, zext_aload_32_64, or_is_add, ATOMIC_LOAD32_U_I64>;
128
129 // Sign-extending loads with constant offset
130 def : LoadPatImmOff<i32, atomic_load_8, regPlusImm, ATOMIC_LOAD8_U_I32>;
131 def : LoadPatImmOff<i32, atomic_load_16, regPlusImm, ATOMIC_LOAD16_U_I32>;
132 def : LoadPatImmOff<i32, atomic_load_8, or_is_add, ATOMIC_LOAD8_U_I32>;
133 def : LoadPatImmOff<i32, atomic_load_16, or_is_add, ATOMIC_LOAD16_U_I32>;
134 def : LoadPatImmOff<i64, anyext_aload_8_64, regPlusImm, ATOMIC_LOAD8_U_I64>;
135 def : LoadPatImmOff<i64, anyext_aload_16_64, regPlusImm, ATOMIC_LOAD16_U_I64>;
136 def : LoadPatImmOff<i64, anyext_aload_8_64, or_is_add, ATOMIC_LOAD8_U_I64>;
137 def : LoadPatImmOff<i64, anyext_aload_16_64, or_is_add, ATOMIC_LOAD16_U_I64>;
138 // No 32->64 patterns, just use i32.atomic.load and i64.extend_s/i64
139
140 def : LoadPatGlobalAddr<i32, zext_aload_8, ATOMIC_LOAD8_U_I32>;
141 def : LoadPatGlobalAddr<i32, zext_aload_16, ATOMIC_LOAD16_U_I32>;
142 def : LoadPatGlobalAddr<i64, zext_aload_8_64, ATOMIC_LOAD8_U_I64>;
143 def : LoadPatGlobalAddr<i64, zext_aload_16_64, ATOMIC_LOAD16_U_I64>;
144 def : LoadPatGlobalAddr<i64, zext_aload_32_64, ATOMIC_LOAD32_U_I64>;
145 def : LoadPatGlobalAddr<i32, atomic_load_8, ATOMIC_LOAD8_U_I32>;
146 def : LoadPatGlobalAddr<i32, atomic_load_16, ATOMIC_LOAD16_U_I32>;
147 def : LoadPatGlobalAddr<i64, anyext_aload_8_64, ATOMIC_LOAD8_U_I64>;
148 def : LoadPatGlobalAddr<i64, anyext_aload_16_64, ATOMIC_LOAD16_U_I64>;
149
150 def : LoadPatExternalSym<i32, zext_aload_8, ATOMIC_LOAD8_U_I32>;
151 def : LoadPatExternalSym<i32, zext_aload_16, ATOMIC_LOAD16_U_I32>;
152 def : LoadPatExternalSym<i64, zext_aload_8_64, ATOMIC_LOAD8_U_I64>;
153 def : LoadPatExternalSym<i64, zext_aload_16_64, ATOMIC_LOAD16_U_I64>;
154 def : LoadPatExternalSym<i64, zext_aload_32_64, ATOMIC_LOAD32_U_I64>;
155 def : LoadPatExternalSym<i32, atomic_load_8, ATOMIC_LOAD8_U_I32>;
156 def : LoadPatExternalSym<i32, atomic_load_16, ATOMIC_LOAD16_U_I32>;
157 def : LoadPatExternalSym<i64, anyext_aload_8_64, ATOMIC_LOAD8_U_I64>;
158 def : LoadPatExternalSym<i64, anyext_aload_16_64, ATOMIC_LOAD16_U_I64>;
159
160
161 // Extending loads with just a constant offset
162 def : LoadPatOffsetOnly<i32, zext_aload_8, ATOMIC_LOAD8_U_I32>;
163 def : LoadPatOffsetOnly<i32, zext_aload_16, ATOMIC_LOAD16_U_I32>;
164 def : LoadPatOffsetOnly<i64, zext_aload_8_64, ATOMIC_LOAD8_U_I64>;
165 def : LoadPatOffsetOnly<i64, zext_aload_16_64, ATOMIC_LOAD16_U_I64>;
166 def : LoadPatOffsetOnly<i64, zext_aload_32_64, ATOMIC_LOAD32_U_I64>;
167 def : LoadPatOffsetOnly<i32, atomic_load_8, ATOMIC_LOAD8_U_I32>;
168 def : LoadPatOffsetOnly<i32, atomic_load_16, ATOMIC_LOAD16_U_I32>;
169 def : LoadPatOffsetOnly<i64, anyext_aload_8_64, ATOMIC_LOAD8_U_I64>;
170 def : LoadPatOffsetOnly<i64, anyext_aload_16_64, ATOMIC_LOAD16_U_I64>;
171
172 def : LoadPatGlobalAddrOffOnly<i32, zext_aload_8, ATOMIC_LOAD8_U_I32>;
173 def : LoadPatGlobalAddrOffOnly<i32, zext_aload_16, ATOMIC_LOAD16_U_I32>;
174 def : LoadPatGlobalAddrOffOnly<i64, zext_aload_8_64, ATOMIC_LOAD8_U_I64>;
175 def : LoadPatGlobalAddrOffOnly<i64, zext_aload_16_64, ATOMIC_LOAD16_U_I64>;
176 def : LoadPatGlobalAddrOffOnly<i64, zext_aload_32_64, ATOMIC_LOAD32_U_I64>;
177 def : LoadPatGlobalAddrOffOnly<i32, atomic_load_8, ATOMIC_LOAD8_U_I32>;
178 def : LoadPatGlobalAddrOffOnly<i32, atomic_load_16, ATOMIC_LOAD16_U_I32>;
179 def : LoadPatGlobalAddrOffOnly<i64, anyext_aload_8_64, ATOMIC_LOAD8_U_I64>;
180 def : LoadPatGlobalAddrOffOnly<i64, anyext_aload_16_64, ATOMIC_LOAD16_U_I64>;
181
182 def : LoadPatExternSymOffOnly<i32, zext_aload_8, ATOMIC_LOAD8_U_I32>;
183 def : LoadPatExternSymOffOnly<i32, zext_aload_16, ATOMIC_LOAD16_U_I32>;
184 def : LoadPatExternSymOffOnly<i64, zext_aload_8_64, ATOMIC_LOAD8_U_I64>;
185 def : LoadPatExternSymOffOnly<i64, zext_aload_16_64, ATOMIC_LOAD16_U_I64>;
186 def : LoadPatExternSymOffOnly<i64, zext_aload_32_64, ATOMIC_LOAD32_U_I64>;
187 def : LoadPatExternSymOffOnly<i32, atomic_load_8, ATOMIC_LOAD8_U_I32>;
188 def : LoadPatExternSymOffOnly<i32, atomic_load_16, ATOMIC_LOAD16_U_I32>;
189 def : LoadPatExternSymOffOnly<i64, anyext_aload_8_64, ATOMIC_LOAD8_U_I64>;
190 def : LoadPatExternSymOffOnly<i64, anyext_aload_16_64, ATOMIC_LOAD16_U_I64>;
191
192
193 } // Predicates = [HasAtomics]
194
195 //===----------------------------------------------------------------------===//
196 // Atomic stores
197 //===----------------------------------------------------------------------===//
198
199 // TODO: add atomic stores here...
200
201 //===----------------------------------------------------------------------===//
202 // Low-level exclusive operations
203 //===----------------------------------------------------------------------===//
204
205 // TODO: add exclusive operations here...
206
207 // Load-exclusives.
208
209 // Store-exclusives.
210
211 // Store-release-exclusives.
212
213 // And clear exclusive.
214