sync.md revision 1.5 1 1.1 mrg ;; GCC machine description for i386 synchronization instructions.
2 1.5 mrg ;; Copyright (C) 2005-2015 Free Software Foundation, Inc.
3 1.1 mrg ;;
4 1.1 mrg ;; This file is part of GCC.
5 1.1 mrg ;;
6 1.1 mrg ;; GCC is free software; you can redistribute it and/or modify
7 1.1 mrg ;; it under the terms of the GNU General Public License as published by
8 1.1 mrg ;; the Free Software Foundation; either version 3, or (at your option)
9 1.1 mrg ;; any later version.
10 1.1 mrg ;;
11 1.1 mrg ;; GCC is distributed in the hope that it will be useful,
12 1.1 mrg ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 mrg ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 mrg ;; GNU General Public License for more details.
15 1.1 mrg ;;
16 1.1 mrg ;; You should have received a copy of the GNU General Public License
17 1.1 mrg ;; along with GCC; see the file COPYING3. If not see
18 1.1 mrg ;; <http://www.gnu.org/licenses/>.
19 1.1 mrg
20 1.3 mrg (define_c_enum "unspec" [
21 1.3 mrg UNSPEC_LFENCE
22 1.3 mrg UNSPEC_SFENCE
23 1.3 mrg UNSPEC_MFENCE
24 1.5 mrg
25 1.5 mrg UNSPEC_FILD_ATOMIC
26 1.5 mrg UNSPEC_FIST_ATOMIC
27 1.5 mrg
28 1.5 mrg ;; __atomic support
29 1.3 mrg UNSPEC_LDA
30 1.3 mrg UNSPEC_STA
31 1.3 mrg ])
32 1.3 mrg
33 1.3 mrg (define_c_enum "unspecv" [
34 1.3 mrg UNSPECV_CMPXCHG
35 1.3 mrg UNSPECV_XCHG
36 1.3 mrg UNSPECV_LOCK
37 1.3 mrg ])
38 1.3 mrg
39 1.3 mrg (define_expand "sse2_lfence"
40 1.3 mrg [(set (match_dup 0)
41 1.3 mrg (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
42 1.3 mrg "TARGET_SSE2"
43 1.3 mrg {
44 1.3 mrg operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
45 1.3 mrg MEM_VOLATILE_P (operands[0]) = 1;
46 1.3 mrg })
47 1.3 mrg
48 1.3 mrg (define_insn "*sse2_lfence"
49 1.3 mrg [(set (match_operand:BLK 0)
50 1.3 mrg (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
51 1.3 mrg "TARGET_SSE2"
52 1.3 mrg "lfence"
53 1.3 mrg [(set_attr "type" "sse")
54 1.3 mrg (set_attr "length_address" "0")
55 1.3 mrg (set_attr "atom_sse_attr" "lfence")
56 1.3 mrg (set_attr "memory" "unknown")])
57 1.3 mrg
58 1.3 mrg (define_expand "sse_sfence"
59 1.3 mrg [(set (match_dup 0)
60 1.3 mrg (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
61 1.3 mrg "TARGET_SSE || TARGET_3DNOW_A"
62 1.3 mrg {
63 1.3 mrg operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
64 1.3 mrg MEM_VOLATILE_P (operands[0]) = 1;
65 1.3 mrg })
66 1.3 mrg
67 1.3 mrg (define_insn "*sse_sfence"
68 1.3 mrg [(set (match_operand:BLK 0)
69 1.3 mrg (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
70 1.3 mrg "TARGET_SSE || TARGET_3DNOW_A"
71 1.3 mrg "sfence"
72 1.3 mrg [(set_attr "type" "sse")
73 1.3 mrg (set_attr "length_address" "0")
74 1.3 mrg (set_attr "atom_sse_attr" "fence")
75 1.3 mrg (set_attr "memory" "unknown")])
76 1.1 mrg
77 1.3 mrg (define_expand "sse2_mfence"
78 1.1 mrg [(set (match_dup 0)
79 1.1 mrg (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
80 1.3 mrg "TARGET_SSE2"
81 1.1 mrg {
82 1.1 mrg operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
83 1.1 mrg MEM_VOLATILE_P (operands[0]) = 1;
84 1.3 mrg })
85 1.1 mrg
86 1.3 mrg (define_insn "mfence_sse2"
87 1.3 mrg [(set (match_operand:BLK 0)
88 1.3 mrg (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
89 1.3 mrg "TARGET_64BIT || TARGET_SSE2"
90 1.3 mrg "mfence"
91 1.3 mrg [(set_attr "type" "sse")
92 1.3 mrg (set_attr "length_address" "0")
93 1.3 mrg (set_attr "atom_sse_attr" "fence")
94 1.3 mrg (set_attr "memory" "unknown")])
95 1.1 mrg
96 1.3 mrg (define_insn "mfence_nosse"
97 1.3 mrg [(set (match_operand:BLK 0)
98 1.1 mrg (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))
99 1.1 mrg (clobber (reg:CC FLAGS_REG))]
100 1.1 mrg "!(TARGET_64BIT || TARGET_SSE2)"
101 1.1 mrg "lock{%;} or{l}\t{$0, (%%esp)|DWORD PTR [esp], 0}"
102 1.1 mrg [(set_attr "memory" "unknown")])
103 1.1 mrg
104 1.3 mrg (define_expand "mem_thread_fence"
105 1.3 mrg [(match_operand:SI 0 "const_int_operand")] ;; model
106 1.3 mrg ""
107 1.3 mrg {
108 1.5 mrg enum memmodel model = memmodel_from_int (INTVAL (operands[0]));
109 1.3 mrg
110 1.3 mrg /* Unless this is a SEQ_CST fence, the i386 memory model is strong
111 1.3 mrg enough not to require barriers of any kind. */
112 1.5 mrg if (is_mm_seq_cst (model))
113 1.3 mrg {
114 1.3 mrg rtx (*mfence_insn)(rtx);
115 1.3 mrg rtx mem;
116 1.3 mrg
117 1.3 mrg if (TARGET_64BIT || TARGET_SSE2)
118 1.3 mrg mfence_insn = gen_mfence_sse2;
119 1.3 mrg else
120 1.3 mrg mfence_insn = gen_mfence_nosse;
121 1.3 mrg
122 1.3 mrg mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
123 1.3 mrg MEM_VOLATILE_P (mem) = 1;
124 1.3 mrg
125 1.3 mrg emit_insn (mfence_insn (mem));
126 1.3 mrg }
127 1.3 mrg DONE;
128 1.3 mrg })
129 1.3 mrg
130 1.3 mrg ;; ??? From volume 3 section 8.1.1 Guaranteed Atomic Operations,
131 1.3 mrg ;; Only beginning at Pentium family processors do we get any guarantee of
132 1.3 mrg ;; atomicity in aligned 64-bit quantities. Beginning at P6, we get a
133 1.3 mrg ;; guarantee for 64-bit accesses that do not cross a cacheline boundary.
134 1.3 mrg ;;
135 1.3 mrg ;; Note that the TARGET_CMPXCHG8B test below is a stand-in for "Pentium".
136 1.3 mrg ;;
137 1.3 mrg ;; Importantly, *no* processor makes atomicity guarantees for larger
138 1.3 mrg ;; accesses. In particular, there's no way to perform an atomic TImode
139 1.3 mrg ;; move, despite the apparent applicability of MOVDQA et al.
140 1.3 mrg
141 1.3 mrg (define_mode_iterator ATOMIC
142 1.3 mrg [QI HI SI
143 1.3 mrg (DI "TARGET_64BIT || (TARGET_CMPXCHG8B && (TARGET_80387 || TARGET_SSE))")
144 1.3 mrg ])
145 1.3 mrg
146 1.3 mrg (define_expand "atomic_load<mode>"
147 1.5 mrg [(set (match_operand:ATOMIC 0 "nonimmediate_operand")
148 1.3 mrg (unspec:ATOMIC [(match_operand:ATOMIC 1 "memory_operand")
149 1.3 mrg (match_operand:SI 2 "const_int_operand")]
150 1.5 mrg UNSPEC_LDA))]
151 1.3 mrg ""
152 1.3 mrg {
153 1.3 mrg /* For DImode on 32-bit, we can use the FPU to perform the load. */
154 1.3 mrg if (<MODE>mode == DImode && !TARGET_64BIT)
155 1.3 mrg emit_insn (gen_atomic_loaddi_fpu
156 1.3 mrg (operands[0], operands[1],
157 1.3 mrg assign_386_stack_local (DImode, SLOT_TEMP)));
158 1.3 mrg else
159 1.5 mrg {
160 1.5 mrg rtx dst = operands[0];
161 1.5 mrg
162 1.5 mrg if (MEM_P (dst))
163 1.5 mrg dst = gen_reg_rtx (<MODE>mode);
164 1.5 mrg
165 1.5 mrg emit_move_insn (dst, operands[1]);
166 1.5 mrg
167 1.5 mrg /* Fix up the destination if needed. */
168 1.5 mrg if (dst != operands[0])
169 1.5 mrg emit_move_insn (operands[0], dst);
170 1.5 mrg }
171 1.3 mrg DONE;
172 1.3 mrg })
173 1.3 mrg
174 1.3 mrg (define_insn_and_split "atomic_loaddi_fpu"
175 1.3 mrg [(set (match_operand:DI 0 "nonimmediate_operand" "=x,m,?r")
176 1.3 mrg (unspec:DI [(match_operand:DI 1 "memory_operand" "m,m,m")]
177 1.5 mrg UNSPEC_LDA))
178 1.3 mrg (clobber (match_operand:DI 2 "memory_operand" "=X,X,m"))
179 1.3 mrg (clobber (match_scratch:DF 3 "=X,xf,xf"))]
180 1.3 mrg "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)"
181 1.3 mrg "#"
182 1.3 mrg "&& reload_completed"
183 1.3 mrg [(const_int 0)]
184 1.3 mrg {
185 1.3 mrg rtx dst = operands[0], src = operands[1];
186 1.3 mrg rtx mem = operands[2], tmp = operands[3];
187 1.3 mrg
188 1.3 mrg if (SSE_REG_P (dst))
189 1.3 mrg emit_move_insn (dst, src);
190 1.3 mrg else
191 1.3 mrg {
192 1.3 mrg if (MEM_P (dst))
193 1.3 mrg mem = dst;
194 1.3 mrg
195 1.3 mrg if (STACK_REG_P (tmp))
196 1.3 mrg {
197 1.3 mrg emit_insn (gen_loaddi_via_fpu (tmp, src));
198 1.3 mrg emit_insn (gen_storedi_via_fpu (mem, tmp));
199 1.3 mrg }
200 1.3 mrg else
201 1.3 mrg {
202 1.3 mrg adjust_reg_mode (tmp, DImode);
203 1.3 mrg emit_move_insn (tmp, src);
204 1.3 mrg emit_move_insn (mem, tmp);
205 1.3 mrg }
206 1.3 mrg
207 1.3 mrg if (mem != dst)
208 1.3 mrg emit_move_insn (dst, mem);
209 1.3 mrg }
210 1.3 mrg DONE;
211 1.3 mrg })
212 1.3 mrg
213 1.3 mrg (define_expand "atomic_store<mode>"
214 1.3 mrg [(set (match_operand:ATOMIC 0 "memory_operand")
215 1.5 mrg (unspec:ATOMIC [(match_operand:ATOMIC 1 "nonimmediate_operand")
216 1.3 mrg (match_operand:SI 2 "const_int_operand")]
217 1.5 mrg UNSPEC_STA))]
218 1.3 mrg ""
219 1.3 mrg {
220 1.5 mrg enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
221 1.3 mrg
222 1.3 mrg if (<MODE>mode == DImode && !TARGET_64BIT)
223 1.3 mrg {
224 1.3 mrg /* For DImode on 32-bit, we can use the FPU to perform the store. */
225 1.3 mrg /* Note that while we could perform a cmpxchg8b loop, that turns
226 1.3 mrg out to be significantly larger than this plus a barrier. */
227 1.3 mrg emit_insn (gen_atomic_storedi_fpu
228 1.3 mrg (operands[0], operands[1],
229 1.3 mrg assign_386_stack_local (DImode, SLOT_TEMP)));
230 1.3 mrg }
231 1.3 mrg else
232 1.3 mrg {
233 1.5 mrg operands[1] = force_reg (<MODE>mode, operands[1]);
234 1.5 mrg
235 1.3 mrg /* For seq-cst stores, when we lack MFENCE, use XCHG. */
236 1.5 mrg if (is_mm_seq_cst (model) && !(TARGET_64BIT || TARGET_SSE2))
237 1.3 mrg {
238 1.3 mrg emit_insn (gen_atomic_exchange<mode> (gen_reg_rtx (<MODE>mode),
239 1.3 mrg operands[0], operands[1],
240 1.3 mrg operands[2]));
241 1.3 mrg DONE;
242 1.3 mrg }
243 1.3 mrg
244 1.3 mrg /* Otherwise use a store. */
245 1.3 mrg emit_insn (gen_atomic_store<mode>_1 (operands[0], operands[1],
246 1.3 mrg operands[2]));
247 1.3 mrg }
248 1.3 mrg /* ... followed by an MFENCE, if required. */
249 1.5 mrg if (is_mm_seq_cst (model))
250 1.3 mrg emit_insn (gen_mem_thread_fence (operands[2]));
251 1.3 mrg DONE;
252 1.3 mrg })
253 1.3 mrg
254 1.3 mrg (define_insn "atomic_store<mode>_1"
255 1.3 mrg [(set (match_operand:SWI 0 "memory_operand" "=m")
256 1.3 mrg (unspec:SWI [(match_operand:SWI 1 "<nonmemory_operand>" "<r><i>")
257 1.3 mrg (match_operand:SI 2 "const_int_operand")]
258 1.5 mrg UNSPEC_STA))]
259 1.3 mrg ""
260 1.3 mrg "%K2mov{<imodesuffix>}\t{%1, %0|%0, %1}")
261 1.3 mrg
262 1.3 mrg (define_insn_and_split "atomic_storedi_fpu"
263 1.3 mrg [(set (match_operand:DI 0 "memory_operand" "=m,m,m")
264 1.5 mrg (unspec:DI [(match_operand:DI 1 "nonimmediate_operand" "x,m,?r")]
265 1.5 mrg UNSPEC_STA))
266 1.3 mrg (clobber (match_operand:DI 2 "memory_operand" "=X,X,m"))
267 1.3 mrg (clobber (match_scratch:DF 3 "=X,xf,xf"))]
268 1.3 mrg "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)"
269 1.3 mrg "#"
270 1.3 mrg "&& reload_completed"
271 1.3 mrg [(const_int 0)]
272 1.3 mrg {
273 1.3 mrg rtx dst = operands[0], src = operands[1];
274 1.3 mrg rtx mem = operands[2], tmp = operands[3];
275 1.3 mrg
276 1.3 mrg if (!SSE_REG_P (src))
277 1.3 mrg {
278 1.3 mrg if (REG_P (src))
279 1.3 mrg {
280 1.3 mrg emit_move_insn (mem, src);
281 1.3 mrg src = mem;
282 1.3 mrg }
283 1.3 mrg
284 1.3 mrg if (STACK_REG_P (tmp))
285 1.3 mrg {
286 1.3 mrg emit_insn (gen_loaddi_via_fpu (tmp, src));
287 1.3 mrg emit_insn (gen_storedi_via_fpu (dst, tmp));
288 1.3 mrg DONE;
289 1.3 mrg }
290 1.3 mrg else
291 1.3 mrg {
292 1.3 mrg adjust_reg_mode (tmp, DImode);
293 1.5 mrg emit_move_insn (tmp, src);
294 1.3 mrg src = tmp;
295 1.3 mrg }
296 1.3 mrg }
297 1.3 mrg emit_move_insn (dst, src);
298 1.3 mrg DONE;
299 1.3 mrg })
300 1.3 mrg
301 1.3 mrg ;; ??? You'd think that we'd be able to perform this via FLOAT + FIX_TRUNC
302 1.3 mrg ;; operations. But the fix_trunc patterns want way more setup than we want
303 1.3 mrg ;; to provide. Note that the scratch is DFmode instead of XFmode in order
304 1.3 mrg ;; to make it easy to allocate a scratch in either SSE or FP_REGs above.
305 1.3 mrg
306 1.3 mrg (define_insn "loaddi_via_fpu"
307 1.3 mrg [(set (match_operand:DF 0 "register_operand" "=f")
308 1.5 mrg (unspec:DF [(match_operand:DI 1 "memory_operand" "m")]
309 1.5 mrg UNSPEC_FILD_ATOMIC))]
310 1.3 mrg "TARGET_80387"
311 1.3 mrg "fild%Z1\t%1"
312 1.3 mrg [(set_attr "type" "fmov")
313 1.3 mrg (set_attr "mode" "DF")
314 1.3 mrg (set_attr "fp_int_src" "true")])
315 1.3 mrg
316 1.3 mrg (define_insn "storedi_via_fpu"
317 1.3 mrg [(set (match_operand:DI 0 "memory_operand" "=m")
318 1.5 mrg (unspec:DI [(match_operand:DF 1 "register_operand" "f")]
319 1.5 mrg UNSPEC_FIST_ATOMIC))]
320 1.3 mrg "TARGET_80387"
321 1.3 mrg {
322 1.3 mrg gcc_assert (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != NULL_RTX);
323 1.3 mrg
324 1.3 mrg return "fistp%Z0\t%0";
325 1.3 mrg }
326 1.3 mrg [(set_attr "type" "fmov")
327 1.3 mrg (set_attr "mode" "DI")])
328 1.3 mrg
329 1.3 mrg (define_expand "atomic_compare_and_swap<mode>"
330 1.3 mrg [(match_operand:QI 0 "register_operand") ;; bool success output
331 1.3 mrg (match_operand:SWI124 1 "register_operand") ;; oldval output
332 1.3 mrg (match_operand:SWI124 2 "memory_operand") ;; memory
333 1.3 mrg (match_operand:SWI124 3 "register_operand") ;; expected input
334 1.3 mrg (match_operand:SWI124 4 "register_operand") ;; newval input
335 1.3 mrg (match_operand:SI 5 "const_int_operand") ;; is_weak
336 1.3 mrg (match_operand:SI 6 "const_int_operand") ;; success model
337 1.3 mrg (match_operand:SI 7 "const_int_operand")] ;; failure model
338 1.3 mrg "TARGET_CMPXCHG"
339 1.3 mrg {
340 1.3 mrg emit_insn
341 1.3 mrg (gen_atomic_compare_and_swap<mode>_1
342 1.3 mrg (operands[1], operands[2], operands[3], operands[4], operands[6]));
343 1.3 mrg ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
344 1.3 mrg const0_rtx);
345 1.3 mrg DONE;
346 1.3 mrg })
347 1.3 mrg
348 1.3 mrg (define_mode_iterator CASMODE
349 1.3 mrg [(DI "TARGET_64BIT || TARGET_CMPXCHG8B")
350 1.3 mrg (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
351 1.3 mrg (define_mode_attr CASHMODE [(DI "SI") (TI "DI")])
352 1.3 mrg
353 1.3 mrg (define_expand "atomic_compare_and_swap<mode>"
354 1.3 mrg [(match_operand:QI 0 "register_operand") ;; bool success output
355 1.3 mrg (match_operand:CASMODE 1 "register_operand") ;; oldval output
356 1.3 mrg (match_operand:CASMODE 2 "memory_operand") ;; memory
357 1.3 mrg (match_operand:CASMODE 3 "register_operand") ;; expected input
358 1.3 mrg (match_operand:CASMODE 4 "register_operand") ;; newval input
359 1.3 mrg (match_operand:SI 5 "const_int_operand") ;; is_weak
360 1.3 mrg (match_operand:SI 6 "const_int_operand") ;; success model
361 1.3 mrg (match_operand:SI 7 "const_int_operand")] ;; failure model
362 1.1 mrg "TARGET_CMPXCHG"
363 1.1 mrg {
364 1.3 mrg if (<MODE>mode == DImode && TARGET_64BIT)
365 1.3 mrg {
366 1.3 mrg emit_insn
367 1.3 mrg (gen_atomic_compare_and_swapdi_1
368 1.3 mrg (operands[1], operands[2], operands[3], operands[4], operands[6]));
369 1.3 mrg }
370 1.3 mrg else
371 1.1 mrg {
372 1.5 mrg machine_mode hmode = <CASHMODE>mode;
373 1.3 mrg
374 1.3 mrg emit_insn
375 1.3 mrg (gen_atomic_compare_and_swap<mode>_doubleword
376 1.5 mrg (operands[1], operands[2], operands[3],
377 1.5 mrg gen_lowpart (hmode, operands[4]), gen_highpart (hmode, operands[4]),
378 1.5 mrg operands[6]));
379 1.1 mrg }
380 1.3 mrg
381 1.3 mrg ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
382 1.3 mrg const0_rtx);
383 1.3 mrg DONE;
384 1.1 mrg })
385 1.1 mrg
386 1.5 mrg ;; For double-word compare and swap, we are obliged to play tricks with
387 1.5 mrg ;; the input newval (op3:op4) because the Intel register numbering does
388 1.5 mrg ;; not match the gcc register numbering, so the pair must be CX:BX.
389 1.5 mrg
390 1.5 mrg (define_mode_attr doublemodesuffix [(SI "8") (DI "16")])
391 1.5 mrg
392 1.5 mrg (define_insn "atomic_compare_and_swap<dwi>_doubleword"
393 1.5 mrg [(set (match_operand:<DWI> 0 "register_operand" "=A")
394 1.5 mrg (unspec_volatile:<DWI>
395 1.5 mrg [(match_operand:<DWI> 1 "memory_operand" "+m")
396 1.5 mrg (match_operand:<DWI> 2 "register_operand" "0")
397 1.5 mrg (match_operand:DWIH 3 "register_operand" "b")
398 1.5 mrg (match_operand:DWIH 4 "register_operand" "c")
399 1.5 mrg (match_operand:SI 5 "const_int_operand")]
400 1.5 mrg UNSPECV_CMPXCHG))
401 1.5 mrg (set (match_dup 1)
402 1.5 mrg (unspec_volatile:<DWI> [(const_int 0)] UNSPECV_CMPXCHG))
403 1.5 mrg (set (reg:CCZ FLAGS_REG)
404 1.5 mrg (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))]
405 1.5 mrg "TARGET_CMPXCHG<doublemodesuffix>B"
406 1.5 mrg "lock{%;} %K5cmpxchg<doublemodesuffix>b\t%1")
407 1.5 mrg
408 1.3 mrg (define_insn "atomic_compare_and_swap<mode>_1"
409 1.1 mrg [(set (match_operand:SWI 0 "register_operand" "=a")
410 1.1 mrg (unspec_volatile:SWI
411 1.3 mrg [(match_operand:SWI 1 "memory_operand" "+m")
412 1.3 mrg (match_operand:SWI 2 "register_operand" "0")
413 1.3 mrg (match_operand:SWI 3 "register_operand" "<r>")
414 1.3 mrg (match_operand:SI 4 "const_int_operand")]
415 1.1 mrg UNSPECV_CMPXCHG))
416 1.3 mrg (set (match_dup 1)
417 1.3 mrg (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
418 1.1 mrg (set (reg:CCZ FLAGS_REG)
419 1.3 mrg (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))]
420 1.1 mrg "TARGET_CMPXCHG"
421 1.3 mrg "lock{%;} %K4cmpxchg{<imodesuffix>}\t{%3, %1|%1, %3}")
422 1.1 mrg
423 1.3 mrg ;; For operand 2 nonmemory_operand predicate is used instead of
424 1.3 mrg ;; register_operand to allow combiner to better optimize atomic
425 1.3 mrg ;; additions of constants.
426 1.3 mrg (define_insn "atomic_fetch_add<mode>"
427 1.1 mrg [(set (match_operand:SWI 0 "register_operand" "=<r>")
428 1.1 mrg (unspec_volatile:SWI
429 1.3 mrg [(match_operand:SWI 1 "memory_operand" "+m")
430 1.3 mrg (match_operand:SI 3 "const_int_operand")] ;; model
431 1.3 mrg UNSPECV_XCHG))
432 1.1 mrg (set (match_dup 1)
433 1.1 mrg (plus:SWI (match_dup 1)
434 1.3 mrg (match_operand:SWI 2 "nonmemory_operand" "0")))
435 1.1 mrg (clobber (reg:CC FLAGS_REG))]
436 1.1 mrg "TARGET_XADD"
437 1.3 mrg "lock{%;} %K3xadd{<imodesuffix>}\t{%0, %1|%1, %0}")
438 1.3 mrg
439 1.3 mrg ;; This peephole2 and following insn optimize
440 1.3 mrg ;; __sync_fetch_and_add (x, -N) == N into just lock {add,sub,inc,dec}
441 1.3 mrg ;; followed by testing of flags instead of lock xadd and comparisons.
442 1.3 mrg (define_peephole2
443 1.3 mrg [(set (match_operand:SWI 0 "register_operand")
444 1.3 mrg (match_operand:SWI 2 "const_int_operand"))
445 1.3 mrg (parallel [(set (match_dup 0)
446 1.3 mrg (unspec_volatile:SWI
447 1.3 mrg [(match_operand:SWI 1 "memory_operand")
448 1.3 mrg (match_operand:SI 4 "const_int_operand")]
449 1.3 mrg UNSPECV_XCHG))
450 1.3 mrg (set (match_dup 1)
451 1.3 mrg (plus:SWI (match_dup 1)
452 1.3 mrg (match_dup 0)))
453 1.3 mrg (clobber (reg:CC FLAGS_REG))])
454 1.3 mrg (set (reg:CCZ FLAGS_REG)
455 1.3 mrg (compare:CCZ (match_dup 0)
456 1.3 mrg (match_operand:SWI 3 "const_int_operand")))]
457 1.3 mrg "peep2_reg_dead_p (3, operands[0])
458 1.3 mrg && (unsigned HOST_WIDE_INT) INTVAL (operands[2])
459 1.3 mrg == -(unsigned HOST_WIDE_INT) INTVAL (operands[3])
460 1.3 mrg && !reg_overlap_mentioned_p (operands[0], operands[1])"
461 1.3 mrg [(parallel [(set (reg:CCZ FLAGS_REG)
462 1.3 mrg (compare:CCZ
463 1.3 mrg (unspec_volatile:SWI [(match_dup 1) (match_dup 4)]
464 1.3 mrg UNSPECV_XCHG)
465 1.3 mrg (match_dup 3)))
466 1.3 mrg (set (match_dup 1)
467 1.3 mrg (plus:SWI (match_dup 1)
468 1.3 mrg (match_dup 2)))])])
469 1.3 mrg
470 1.3 mrg (define_insn "*atomic_fetch_add_cmp<mode>"
471 1.3 mrg [(set (reg:CCZ FLAGS_REG)
472 1.3 mrg (compare:CCZ
473 1.3 mrg (unspec_volatile:SWI
474 1.3 mrg [(match_operand:SWI 0 "memory_operand" "+m")
475 1.3 mrg (match_operand:SI 3 "const_int_operand")] ;; model
476 1.3 mrg UNSPECV_XCHG)
477 1.3 mrg (match_operand:SWI 2 "const_int_operand" "i")))
478 1.3 mrg (set (match_dup 0)
479 1.3 mrg (plus:SWI (match_dup 0)
480 1.3 mrg (match_operand:SWI 1 "const_int_operand" "i")))]
481 1.3 mrg "(unsigned HOST_WIDE_INT) INTVAL (operands[1])
482 1.3 mrg == -(unsigned HOST_WIDE_INT) INTVAL (operands[2])"
483 1.3 mrg {
484 1.3 mrg if (incdec_operand (operands[1], <MODE>mode))
485 1.3 mrg {
486 1.3 mrg if (operands[1] == const1_rtx)
487 1.3 mrg return "lock{%;} %K3inc{<imodesuffix>}\t%0";
488 1.3 mrg else
489 1.3 mrg {
490 1.3 mrg gcc_assert (operands[1] == constm1_rtx);
491 1.3 mrg return "lock{%;} %K3dec{<imodesuffix>}\t%0";
492 1.3 mrg }
493 1.3 mrg }
494 1.3 mrg
495 1.3 mrg if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
496 1.3 mrg return "lock{%;} %K3sub{<imodesuffix>}\t{%1, %0|%0, %1}";
497 1.3 mrg
498 1.3 mrg return "lock{%;} %K3add{<imodesuffix>}\t{%1, %0|%0, %1}";
499 1.3 mrg })
500 1.1 mrg
501 1.1 mrg ;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space.
502 1.3 mrg ;; In addition, it is always a full barrier, so we can ignore the memory model.
503 1.3 mrg (define_insn "atomic_exchange<mode>"
504 1.3 mrg [(set (match_operand:SWI 0 "register_operand" "=<r>") ;; output
505 1.1 mrg (unspec_volatile:SWI
506 1.3 mrg [(match_operand:SWI 1 "memory_operand" "+m") ;; memory
507 1.3 mrg (match_operand:SI 3 "const_int_operand")] ;; model
508 1.3 mrg UNSPECV_XCHG))
509 1.1 mrg (set (match_dup 1)
510 1.3 mrg (match_operand:SWI 2 "register_operand" "0"))] ;; input
511 1.1 mrg ""
512 1.3 mrg "%K3xchg{<imodesuffix>}\t{%1, %0|%0, %1}")
513 1.1 mrg
514 1.3 mrg (define_insn "atomic_add<mode>"
515 1.1 mrg [(set (match_operand:SWI 0 "memory_operand" "+m")
516 1.1 mrg (unspec_volatile:SWI
517 1.1 mrg [(plus:SWI (match_dup 0)
518 1.3 mrg (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
519 1.3 mrg (match_operand:SI 2 "const_int_operand")] ;; model
520 1.1 mrg UNSPECV_LOCK))
521 1.1 mrg (clobber (reg:CC FLAGS_REG))]
522 1.1 mrg ""
523 1.1 mrg {
524 1.3 mrg if (incdec_operand (operands[1], <MODE>mode))
525 1.1 mrg {
526 1.1 mrg if (operands[1] == const1_rtx)
527 1.3 mrg return "lock{%;} %K2inc{<imodesuffix>}\t%0";
528 1.3 mrg else
529 1.3 mrg {
530 1.3 mrg gcc_assert (operands[1] == constm1_rtx);
531 1.3 mrg return "lock{%;} %K2dec{<imodesuffix>}\t%0";
532 1.3 mrg }
533 1.1 mrg }
534 1.1 mrg
535 1.3 mrg if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
536 1.3 mrg return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
537 1.3 mrg
538 1.3 mrg return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
539 1.1 mrg })
540 1.1 mrg
541 1.3 mrg (define_insn "atomic_sub<mode>"
542 1.1 mrg [(set (match_operand:SWI 0 "memory_operand" "+m")
543 1.1 mrg (unspec_volatile:SWI
544 1.1 mrg [(minus:SWI (match_dup 0)
545 1.3 mrg (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
546 1.3 mrg (match_operand:SI 2 "const_int_operand")] ;; model
547 1.1 mrg UNSPECV_LOCK))
548 1.1 mrg (clobber (reg:CC FLAGS_REG))]
549 1.1 mrg ""
550 1.1 mrg {
551 1.3 mrg if (incdec_operand (operands[1], <MODE>mode))
552 1.1 mrg {
553 1.1 mrg if (operands[1] == const1_rtx)
554 1.3 mrg return "lock{%;} %K2dec{<imodesuffix>}\t%0";
555 1.3 mrg else
556 1.3 mrg {
557 1.3 mrg gcc_assert (operands[1] == constm1_rtx);
558 1.3 mrg return "lock{%;} %K2inc{<imodesuffix>}\t%0";
559 1.3 mrg }
560 1.1 mrg }
561 1.1 mrg
562 1.3 mrg if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
563 1.3 mrg return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
564 1.3 mrg
565 1.3 mrg return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
566 1.1 mrg })
567 1.1 mrg
568 1.3 mrg (define_insn "atomic_<logic><mode>"
569 1.1 mrg [(set (match_operand:SWI 0 "memory_operand" "+m")
570 1.1 mrg (unspec_volatile:SWI
571 1.1 mrg [(any_logic:SWI (match_dup 0)
572 1.3 mrg (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
573 1.3 mrg (match_operand:SI 2 "const_int_operand")] ;; model
574 1.1 mrg UNSPECV_LOCK))
575 1.1 mrg (clobber (reg:CC FLAGS_REG))]
576 1.1 mrg ""
577 1.3 mrg "lock{%;} %K2<logic>{<imodesuffix>}\t{%1, %0|%0, %1}")
578