1 ;; GCC machine description for i386 synchronization instructions.
2 ;; Copyright (C)
2005-
2022 Free Software Foundation, Inc.
4 ;; This file is part of GCC.
6 ;; GCC is free software; you can redistribute it and/or modify
7 ;; it under the terms of the GNU General Public License as published by
8 ;; the Free Software Foundation; either version
3, or (at your option)
11 ;; GCC is distributed in the hope that it will be useful,
12 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ;; GNU General Public License for more details.
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with GCC; see the file COPYING3. If not see
18 ;; <http://www.gnu.org/licenses/>.
20 (define_c_enum "unspec" [
36 (define_c_enum "unspecv" [
41 ;; For CMPccXADD support
48 (define_expand "sse2_lfence"
50 (unspec:BLK [(match_dup
0)] UNSPEC_LFENCE))]
53 operands[
0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
54 MEM_VOLATILE_P (operands[
0]) =
1;
57 (define_insn "*sse2_lfence"
58 [(set (match_operand:BLK
0)
59 (unspec:BLK [(match_dup
0)] UNSPEC_LFENCE))]
62 [(set_attr "type" "sse")
63 (set_attr "length_address" "
0")
64 (set_attr "atom_sse_attr" "lfence")
65 (set_attr "memory" "unknown")])
67 (define_expand "sse_sfence"
69 (unspec:BLK [(match_dup
0)] UNSPEC_SFENCE))]
70 "TARGET_SSE || TARGET_3DNOW_A"
72 operands[
0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
73 MEM_VOLATILE_P (operands[
0]) =
1;
76 (define_insn "*sse_sfence"
77 [(set (match_operand:BLK
0)
78 (unspec:BLK [(match_dup
0)] UNSPEC_SFENCE))]
79 "TARGET_SSE || TARGET_3DNOW_A"
81 [(set_attr "type" "sse")
82 (set_attr "length_address" "
0")
83 (set_attr "atom_sse_attr" "fence")
84 (set_attr "memory" "unknown")])
86 (define_expand "sse2_mfence"
88 (unspec:BLK [(match_dup
0)] UNSPEC_MFENCE))]
91 operands[
0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
92 MEM_VOLATILE_P (operands[
0]) =
1;
95 (define_insn "mfence_sse2"
96 [(set (match_operand:BLK
0)
97 (unspec:BLK [(match_dup
0)] UNSPEC_MFENCE))]
98 "TARGET_64BIT || TARGET_SSE2"
100 [(set_attr "type" "sse")
101 (set_attr "length_address" "
0")
102 (set_attr "atom_sse_attr" "fence")
103 (set_attr "memory" "unknown")])
105 (define_insn "mfence_nosse"
106 [(set (match_operand:BLK
0)
107 (unspec:BLK [(match_dup
0)] UNSPEC_MFENCE))
108 (clobber (reg:CC FLAGS_REG))]
111 rtx mem = gen_rtx_MEM (word_mode, stack_pointer_rtx);
113 output_asm_insn ("lock{%;} or%z0
\t{$
0, %
0|%
0,
0}", &mem);
116 [(set_attr "memory" "unknown")])
118 (define_expand "mem_thread_fence"
119 [(match_operand:SI
0 "const_int_operand")] ;; model
122 enum memmodel model = memmodel_from_int (INTVAL (operands[
0]));
124 /* Unless this is a SEQ_CST fence, the i386 memory model is strong
125 enough not to require barriers of any kind. */
126 if (is_mm_seq_cst (model))
128 rtx (*mfence_insn)(rtx);
131 if ((TARGET_64BIT || TARGET_SSE2)
132 && (optimize_function_for_size_p (cfun)
133 || !TARGET_AVOID_MFENCE))
134 mfence_insn = gen_mfence_sse2;
136 mfence_insn = gen_mfence_nosse;
138 mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
139 MEM_VOLATILE_P (mem) =
1;
141 emit_insn (mfence_insn (mem));
146 ;; ??? From volume
3 section
8.1.1 Guaranteed Atomic Operations,
147 ;; Only beginning at Pentium family processors do we get any guarantee of
148 ;; atomicity in aligned
64-bit quantities. Beginning at P6, we get a
149 ;; guarantee for
64-bit accesses that do not cross a cacheline boundary.
151 ;; Note that the TARGET_CMPXCHG8B test below is a stand-in for "Pentium".
153 ;; Importantly, *no* processor makes atomicity guarantees for larger
154 ;; accesses. In particular, there's no way to perform an atomic TImode
155 ;; move, despite the apparent applicability of MOVDQA et al.
157 (define_mode_iterator ATOMIC
159 (DI "TARGET_64BIT || (TARGET_CMPXCHG8B && (TARGET_80387 || TARGET_SSE))")
162 (define_expand "atomic_load<mode>"
163 [(set (match_operand:ATOMIC
0 "nonimmediate_operand")
164 (unspec:ATOMIC [(match_operand:ATOMIC
1 "memory_operand")
165 (match_operand:SI
2 "const_int_operand")]
169 /* For DImode on
32-bit, we can use the FPU to perform the load. */
170 if (<MODE>mode == DImode && !TARGET_64BIT)
171 emit_insn (gen_atomic_loaddi_fpu
172 (operands[
0], operands[
1],
173 assign_386_stack_local (DImode, SLOT_TEMP)));
176 rtx dst = operands[
0];
179 dst = gen_reg_rtx (<MODE>mode);
181 emit_move_insn (dst, operands[
1]);
183 /* Fix up the destination if needed. */
184 if (dst != operands[
0])
185 emit_move_insn (operands[
0], dst);
190 (define_insn_and_split "atomic_loaddi_fpu"
191 [(set (match_operand:DI
0 "nonimmediate_operand" "=x,m,?r")
192 (unspec:DI [(match_operand:DI
1 "memory_operand" "m,m,m")]
194 (clobber (match_operand:DI
2 "memory_operand" "=X,X,m"))
195 (clobber (match_scratch:DF
3 "=X,xf,xf"))]
196 "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)"
198 "&& reload_completed"
201 rtx dst = operands[
0], src = operands[
1];
202 rtx mem = operands[
2], tmp = operands[
3];
205 emit_move_insn (dst, src);
211 if (STACK_REG_P (tmp))
213 emit_insn (gen_loaddi_via_fpu (tmp, src));
214 emit_insn (gen_storedi_via_fpu (mem, tmp));
218 emit_insn (gen_loaddi_via_sse (tmp, src));
219 emit_insn (gen_storedi_via_sse (mem, tmp));
223 emit_move_insn (dst, mem);
228 (define_expand "atomic_store<mode>"
229 [(set (match_operand:ATOMIC
0 "memory_operand")
230 (unspec:ATOMIC [(match_operand:ATOMIC
1 "nonimmediate_operand")
231 (match_operand:SI
2 "const_int_operand")]
235 enum memmodel model = memmodel_from_int (INTVAL (operands[
2]));
237 if (<MODE>mode == DImode && !TARGET_64BIT)
239 /* For DImode on
32-bit, we can use the FPU to perform the store. */
240 /* Note that while we could perform a cmpxchg8b loop, that turns
241 out to be significantly larger than this plus a barrier. */
242 emit_insn (gen_atomic_storedi_fpu
243 (operands[
0], operands[
1],
244 assign_386_stack_local (DImode, SLOT_TEMP)));
248 operands[
1] = force_reg (<MODE>mode, operands[
1]);
250 /* For seq-cst stores, use XCHG when we lack MFENCE. */
251 if (is_mm_seq_cst (model)
252 && (!(TARGET_64BIT || TARGET_SSE2)
253 || TARGET_AVOID_MFENCE))
255 emit_insn (gen_atomic_exchange<mode> (gen_reg_rtx (<MODE>mode),
256 operands[
0], operands[
1],
261 /* Otherwise use a store. */
262 emit_insn (gen_atomic_store<mode>_1 (operands[
0], operands[
1],
265 /* ... followed by an MFENCE, if required. */
266 if (is_mm_seq_cst (model))
267 emit_insn (gen_mem_thread_fence (operands[
2]));
271 (define_insn "atomic_store<mode>_1"
272 [(set (match_operand:SWI
0 "memory_operand" "=m")
273 (unspec:SWI [(match_operand:SWI
1 "<nonmemory_operand>" "<r><i>")
274 (match_operand:SI
2 "const_int_operand")]
277 "%K2mov{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}")
279 (define_insn_and_split "atomic_storedi_fpu"
280 [(set (match_operand:DI
0 "memory_operand" "=m,m,m")
281 (unspec:DI [(match_operand:DI
1 "nonimmediate_operand" "x,m,?r")]
283 (clobber (match_operand:DI
2 "memory_operand" "=X,X,m"))
284 (clobber (match_scratch:DF
3 "=X,xf,xf"))]
285 "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)"
287 "&& reload_completed"
290 rtx dst = operands[
0], src = operands[
1];
291 rtx mem = operands[
2], tmp = operands[
3];
294 emit_move_insn (dst, src);
299 emit_move_insn (mem, src);
303 if (STACK_REG_P (tmp))
305 emit_insn (gen_loaddi_via_fpu (tmp, src));
306 emit_insn (gen_storedi_via_fpu (dst, tmp));
310 emit_insn (gen_loaddi_via_sse (tmp, src));
311 emit_insn (gen_storedi_via_sse (dst, tmp));
317 ;; ??? You'd think that we'd be able to perform this via FLOAT + FIX_TRUNC
318 ;; operations. But the fix_trunc patterns want way more setup than we want
319 ;; to provide. Note that the scratch is DFmode instead of XFmode in order
320 ;; to make it easy to allocate a scratch in either SSE or FP_REGs above.
322 (define_insn "loaddi_via_fpu"
323 [(set (match_operand:DF
0 "register_operand" "=f")
324 (unspec:DF [(match_operand:DI
1 "memory_operand" "m")]
325 UNSPEC_FILD_ATOMIC))]
328 [(set_attr "type" "fmov")
329 (set_attr "mode" "DF")
330 (set_attr "fp_int_src" "true")])
332 (define_insn "storedi_via_fpu"
333 [(set (match_operand:DI
0 "memory_operand" "=m")
334 (unspec:DI [(match_operand:DF
1 "register_operand" "f")]
335 UNSPEC_FIST_ATOMIC))]
338 gcc_assert (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != NULL_RTX);
340 return "fistp%Z0
\t%
0";
342 [(set_attr "type" "fmov")
343 (set_attr "mode" "DI")])
345 (define_insn "loaddi_via_sse"
346 [(set (match_operand:DF
0 "register_operand" "=x")
347 (unspec:DF [(match_operand:DI
1 "memory_operand" "m")]
352 return "%vmovq
\t{%
1, %
0|%
0, %
1}";
353 return "movlps
\t{%
1, %
0|%
0, %
1}";
355 [(set_attr "type" "ssemov")
356 (set_attr "mode" "DI")])
358 (define_insn "storedi_via_sse"
359 [(set (match_operand:DI
0 "memory_operand" "=m")
360 (unspec:DI [(match_operand:DF
1 "register_operand" "x")]
365 return "%vmovq
\t{%
1, %
0|%
0, %
1}";
366 return "movlps
\t{%
1, %
0|%
0, %
1}";
368 [(set_attr "type" "ssemov")
369 (set_attr "mode" "DI")])
371 (define_expand "atomic_compare_and_swap<mode>"
372 [(match_operand:QI
0 "register_operand") ;; bool success output
373 (match_operand:SWI124
1 "register_operand") ;; oldval output
374 (match_operand:SWI124
2 "memory_operand") ;; memory
375 (match_operand:SWI124
3 "register_operand") ;; expected input
376 (match_operand:SWI124
4 "register_operand") ;; newval input
377 (match_operand:SI
5 "const_int_operand") ;; is_weak
378 (match_operand:SI
6 "const_int_operand") ;; success model
379 (match_operand:SI
7 "const_int_operand")] ;; failure model
382 if (TARGET_RELAX_CMPXCHG_LOOP)
384 ix86_expand_cmpxchg_loop (&operands[
0], operands[
1], operands[
2],
385 operands[
3], operands[
4], operands[
6],
391 (gen_atomic_compare_and_swap<mode>_1
392 (operands[
1], operands[
2], operands[
3], operands[
4], operands[
6]));
393 ix86_expand_setcc (operands[
0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
399 (define_mode_iterator CASMODE
400 [(DI "TARGET_64BIT || TARGET_CMPXCHG8B")
401 (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
402 (define_mode_attr CASHMODE [(DI "SI") (TI "DI")])
404 (define_expand "atomic_compare_and_swap<mode>"
405 [(match_operand:QI
0 "register_operand") ;; bool success output
406 (match_operand:CASMODE
1 "register_operand") ;; oldval output
407 (match_operand:CASMODE
2 "memory_operand") ;; memory
408 (match_operand:CASMODE
3 "register_operand") ;; expected input
409 (match_operand:CASMODE
4 "register_operand") ;; newval input
410 (match_operand:SI
5 "const_int_operand") ;; is_weak
411 (match_operand:SI
6 "const_int_operand") ;; success model
412 (match_operand:SI
7 "const_int_operand")] ;; failure model
415 int doubleword = !(<MODE>mode == DImode && TARGET_64BIT);
416 if (TARGET_RELAX_CMPXCHG_LOOP)
418 ix86_expand_cmpxchg_loop (&operands[
0], operands[
1], operands[
2],
419 operands[
3], operands[
4], operands[
6],
427 (gen_atomic_compare_and_swapdi_1
428 (operands[
1], operands[
2], operands[
3], operands[
4], operands[
6]));
432 machine_mode hmode = <CASHMODE>mode;
435 (gen_atomic_compare_and_swap<mode>_doubleword
436 (operands[
1], operands[
2], operands[
3],
437 gen_lowpart (hmode, operands[
4]), gen_highpart (hmode, operands[
4]),
441 ix86_expand_setcc (operands[
0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
447 ;; For double-word compare and swap, we are obliged to play tricks with
448 ;; the input newval (op3:op4) because the Intel register numbering does
449 ;; not match the gcc register numbering, so the pair must be CX:BX.
451 (define_mode_attr doublemodesuffix [(SI "
8") (DI "
16")])
453 (define_insn "atomic_compare_and_swap<dwi>_doubleword"
454 [(set (match_operand:<DWI>
0 "register_operand" "=A")
455 (unspec_volatile:<DWI>
456 [(match_operand:<DWI>
1 "memory_operand" "+m")
457 (match_operand:<DWI>
2 "register_operand" "
0")
458 (match_operand:DWIH
3 "register_operand" "b")
459 (match_operand:DWIH
4 "register_operand" "c")
460 (match_operand:SI
5 "const_int_operand")]
463 (unspec_volatile:<DWI> [(const_int
0)] UNSPECV_CMPXCHG))
464 (set (reg:CCZ FLAGS_REG)
465 (unspec_volatile:CCZ [(const_int
0)] UNSPECV_CMPXCHG))]
466 "TARGET_CMPXCHG<doublemodesuffix>B"
467 "lock{%;} %K5cmpxchg<doublemodesuffix>b
\t%
1")
469 (define_insn "atomic_compare_and_swap<mode>_1"
470 [(set (match_operand:SWI
0 "register_operand" "=a")
472 [(match_operand:SWI
1 "memory_operand" "+m")
473 (match_operand:SWI
2 "register_operand" "
0")
474 (match_operand:SWI
3 "register_operand" "<r>")
475 (match_operand:SI
4 "const_int_operand")]
478 (unspec_volatile:SWI [(const_int
0)] UNSPECV_CMPXCHG))
479 (set (reg:CCZ FLAGS_REG)
480 (unspec_volatile:CCZ [(const_int
0)] UNSPECV_CMPXCHG))]
482 "lock{%;} %K4cmpxchg{<imodesuffix>}
\t{%
3, %
1|%
1, %
3}")
485 [(set (match_operand:SWI
0 "register_operand")
486 (match_operand:SWI
1 "general_operand"))
487 (parallel [(set (match_dup
0)
489 [(match_operand:SWI
2 "memory_operand")
491 (match_operand:SWI
3 "register_operand")
492 (match_operand:SI
4 "const_int_operand")]
495 (unspec_volatile:SWI [(const_int
0)] UNSPECV_CMPXCHG))
496 (set (reg:CCZ FLAGS_REG)
497 (unspec_volatile:CCZ [(const_int
0)] UNSPECV_CMPXCHG))])
498 (set (reg:CCZ FLAGS_REG)
499 (compare:CCZ (match_operand:SWI
5 "register_operand")
500 (match_operand:SWI
6 "general_operand")))]
501 "(rtx_equal_p (operands[
0], operands[
5])
502 && rtx_equal_p (operands[
1], operands[
6]))
503 || (rtx_equal_p (operands[
0], operands[
6])
504 && rtx_equal_p (operands[
1], operands[
5]))"
507 (parallel [(set (match_dup
0)
515 (unspec_volatile:SWI [(const_int
0)] UNSPECV_CMPXCHG))
516 (set (reg:CCZ FLAGS_REG)
517 (unspec_volatile:CCZ [(const_int
0)] UNSPECV_CMPXCHG))])])
520 [(parallel [(set (match_operand:SWI48
0 "register_operand")
521 (match_operand:SWI48
1 "const_int_operand"))
522 (clobber (reg:CC FLAGS_REG))])
523 (parallel [(set (match_operand:SWI
2 "register_operand")
525 [(match_operand:SWI
3 "memory_operand")
527 (match_operand:SWI
4 "register_operand")
528 (match_operand:SI
5 "const_int_operand")]
531 (unspec_volatile:SWI [(const_int
0)] UNSPECV_CMPXCHG))
532 (set (reg:CCZ FLAGS_REG)
533 (unspec_volatile:CCZ [(const_int
0)] UNSPECV_CMPXCHG))])
534 (set (reg:CCZ FLAGS_REG)
535 (compare:CCZ (match_dup
2)
537 "REGNO (operands[
0]) == REGNO (operands[
2])"
538 [(parallel [(set (match_dup
0)
540 (clobber (reg:CC FLAGS_REG))])
541 (parallel [(set (match_dup
2)
549 (unspec_volatile:SWI [(const_int
0)] UNSPECV_CMPXCHG))
550 (set (reg:CCZ FLAGS_REG)
551 (unspec_volatile:CCZ [(const_int
0)] UNSPECV_CMPXCHG))])])
553 (define_expand "atomic_fetch_<logic><mode>"
554 [(match_operand:SWI124
0 "register_operand")
556 (match_operand:SWI124
1 "memory_operand")
557 (match_operand:SWI124
2 "register_operand"))
558 (match_operand:SI
3 "const_int_operand")]
559 "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
561 ix86_expand_atomic_fetch_op_loop (operands[
0], operands[
1],
562 operands[
2], <CODE>, false,
567 (define_expand "atomic_<logic>_fetch<mode>"
568 [(match_operand:SWI124
0 "register_operand")
570 (match_operand:SWI124
1 "memory_operand")
571 (match_operand:SWI124
2 "register_operand"))
572 (match_operand:SI
3 "const_int_operand")]
573 "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
575 ix86_expand_atomic_fetch_op_loop (operands[
0], operands[
1],
576 operands[
2], <CODE>, true,
581 (define_expand "atomic_fetch_nand<mode>"
582 [(match_operand:SWI124
0 "register_operand")
583 (match_operand:SWI124
1 "memory_operand")
584 (match_operand:SWI124
2 "register_operand")
585 (match_operand:SI
3 "const_int_operand")]
586 "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
588 ix86_expand_atomic_fetch_op_loop (operands[
0], operands[
1],
589 operands[
2], NOT, false,
594 (define_expand "atomic_nand_fetch<mode>"
595 [(match_operand:SWI124
0 "register_operand")
596 (match_operand:SWI124
1 "memory_operand")
597 (match_operand:SWI124
2 "register_operand")
598 (match_operand:SI
3 "const_int_operand")]
599 "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
601 ix86_expand_atomic_fetch_op_loop (operands[
0], operands[
1],
602 operands[
2], NOT, true,
607 (define_expand "atomic_fetch_<logic><mode>"
608 [(match_operand:CASMODE
0 "register_operand")
610 (match_operand:CASMODE
1 "memory_operand")
611 (match_operand:CASMODE
2 "register_operand"))
612 (match_operand:SI
3 "const_int_operand")]
613 "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
615 bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
616 || (<MODE>mode == TImode);
617 ix86_expand_atomic_fetch_op_loop (operands[
0], operands[
1],
618 operands[
2], <CODE>, false,
623 (define_expand "atomic_<logic>_fetch<mode>"
624 [(match_operand:CASMODE
0 "register_operand")
626 (match_operand:CASMODE
1 "memory_operand")
627 (match_operand:CASMODE
2 "register_operand"))
628 (match_operand:SI
3 "const_int_operand")]
629 "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
631 bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
632 || (<MODE>mode == TImode);
633 ix86_expand_atomic_fetch_op_loop (operands[
0], operands[
1],
634 operands[
2], <CODE>, true,
639 (define_expand "atomic_fetch_nand<mode>"
640 [(match_operand:CASMODE
0 "register_operand")
641 (match_operand:CASMODE
1 "memory_operand")
642 (match_operand:CASMODE
2 "register_operand")
643 (match_operand:SI
3 "const_int_operand")]
644 "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
646 bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
647 || (<MODE>mode == TImode);
648 ix86_expand_atomic_fetch_op_loop (operands[
0], operands[
1],
649 operands[
2], NOT, false,
654 (define_expand "atomic_nand_fetch<mode>"
655 [(match_operand:CASMODE
0 "register_operand")
656 (match_operand:CASMODE
1 "memory_operand")
657 (match_operand:CASMODE
2 "register_operand")
658 (match_operand:SI
3 "const_int_operand")]
659 "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
661 bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
662 || (<MODE>mode == TImode);
663 ix86_expand_atomic_fetch_op_loop (operands[
0], operands[
1],
664 operands[
2], NOT, true,
670 ;; For operand
2 nonmemory_operand predicate is used instead of
671 ;; register_operand to allow combiner to better optimize atomic
672 ;; additions of constants.
673 (define_insn "atomic_fetch_add<mode>"
674 [(set (match_operand:SWI
0 "register_operand" "=<r>")
676 [(match_operand:SWI
1 "memory_operand" "+m")
677 (match_operand:SI
3 "const_int_operand")] ;; model
680 (plus:SWI (match_dup
1)
681 (match_operand:SWI
2 "nonmemory_operand" "
0")))
682 (clobber (reg:CC FLAGS_REG))]
684 "lock{%;} %K3xadd{<imodesuffix>}
\t{%
0, %
1|%
1, %
0}")
686 ;; This peephole2 and following insn optimize
687 ;; __sync_fetch_and_add (x, -N) == N into just lock {add,sub,inc,dec}
688 ;; followed by testing of flags instead of lock xadd and comparisons.
690 [(set (match_operand:SWI
0 "register_operand")
691 (match_operand:SWI
2 "const_int_operand"))
692 (parallel [(set (match_dup
0)
694 [(match_operand:SWI
1 "memory_operand")
695 (match_operand:SI
4 "const_int_operand")]
698 (plus:SWI (match_dup
1)
700 (clobber (reg:CC FLAGS_REG))])
701 (set (reg:CCZ FLAGS_REG)
702 (compare:CCZ (match_dup
0)
703 (match_operand:SWI
3 "const_int_operand")))]
704 "peep2_reg_dead_p (
3, operands[
0])
705 && (unsigned HOST_WIDE_INT) INTVAL (operands[
2])
706 == -(unsigned HOST_WIDE_INT) INTVAL (operands[
3])
707 && !reg_overlap_mentioned_p (operands[
0], operands[
1])"
708 [(parallel [(set (reg:CCZ FLAGS_REG)
710 (unspec_volatile:SWI [(match_dup
1) (match_dup
4)]
714 (plus:SWI (match_dup
1)
717 ;; Likewise, but for the -Os special case of *mov<mode>_or.
719 [(parallel [(set (match_operand:SWI
0 "register_operand")
720 (match_operand:SWI
2 "constm1_operand"))
721 (clobber (reg:CC FLAGS_REG))])
722 (parallel [(set (match_dup
0)
724 [(match_operand:SWI
1 "memory_operand")
725 (match_operand:SI
4 "const_int_operand")]
728 (plus:SWI (match_dup
1)
730 (clobber (reg:CC FLAGS_REG))])
731 (set (reg:CCZ FLAGS_REG)
732 (compare:CCZ (match_dup
0)
733 (match_operand:SWI
3 "const_int_operand")))]
734 "peep2_reg_dead_p (
3, operands[
0])
735 && (unsigned HOST_WIDE_INT) INTVAL (operands[
2])
736 == -(unsigned HOST_WIDE_INT) INTVAL (operands[
3])
737 && !reg_overlap_mentioned_p (operands[
0], operands[
1])"
738 [(parallel [(set (reg:CCZ FLAGS_REG)
740 (unspec_volatile:SWI [(match_dup
1) (match_dup
4)]
744 (plus:SWI (match_dup
1)
747 (define_insn "*atomic_fetch_add_cmp<mode>"
748 [(set (reg:CCZ FLAGS_REG)
751 [(match_operand:SWI
0 "memory_operand" "+m")
752 (match_operand:SI
3 "const_int_operand")] ;; model
754 (match_operand:SWI
2 "const_int_operand")))
756 (plus:SWI (match_dup
0)
757 (match_operand:SWI
1 "const_int_operand")))]
758 "(unsigned HOST_WIDE_INT) INTVAL (operands[
1])
759 == -(unsigned HOST_WIDE_INT) INTVAL (operands[
2])"
761 if (incdec_operand (operands[
1], <MODE>mode))
763 if (operands[
1] == const1_rtx)
764 return "lock{%;} %K3inc{<imodesuffix>}
\t%
0";
767 gcc_assert (operands[
1] == constm1_rtx);
768 return "lock{%;} %K3dec{<imodesuffix>}
\t%
0";
772 if (x86_maybe_negate_const_int (&operands[
1], <MODE>mode))
773 return "lock{%;} %K3sub{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}";
775 return "lock{%;} %K3add{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}";
778 ;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space.
779 ;; In addition, it is always a full barrier, so we can ignore the memory model.
780 (define_insn "atomic_exchange<mode>"
781 [(set (match_operand:SWI
0 "register_operand" "=<r>") ;; output
783 [(match_operand:SWI
1 "memory_operand" "+m") ;; memory
784 (match_operand:SI
3 "const_int_operand")] ;; model
787 (match_operand:SWI
2 "register_operand" "
0"))] ;; input
789 "%K3xchg{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}")
791 (define_code_iterator any_plus_logic [and ior xor plus])
792 (define_code_attr plus_logic [(and "and") (ior "or") (xor "xor") (plus "add")])
794 (define_insn "rao_a<plus_logic><mode>"
795 [(set (match_operand:SWI48
0 "memory_operand" "+m")
796 (unspec_volatile:SWI48
797 [(any_plus_logic:SWI48 (match_dup
0)
798 (match_operand:SWI48
1 "register_operand" "r"))
799 (const_int
0)] ;; MEMMODEL_RELAXED
802 "a<plus_logic>
\t{%
1, %
0|%
0, %
1}")
804 (define_insn "atomic_add<mode>"
805 [(set (match_operand:SWI
0 "memory_operand" "+m")
807 [(plus:SWI (match_dup
0)
808 (match_operand:SWI
1 "nonmemory_operand" "<r><i>"))
809 (match_operand:SI
2 "const_int_operand")] ;; model
811 (clobber (reg:CC FLAGS_REG))]
814 if (incdec_operand (operands[
1], <MODE>mode))
816 if (operands[
1] == const1_rtx)
817 return "lock{%;} %K2inc{<imodesuffix>}
\t%
0";
820 gcc_assert (operands[
1] == constm1_rtx);
821 return "lock{%;} %K2dec{<imodesuffix>}
\t%
0";
825 if (x86_maybe_negate_const_int (&operands[
1], <MODE>mode))
826 return "lock{%;} %K2sub{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}";
828 return "lock{%;} %K2add{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}";
831 (define_insn "atomic_sub<mode>"
832 [(set (match_operand:SWI
0 "memory_operand" "+m")
834 [(minus:SWI (match_dup
0)
835 (match_operand:SWI
1 "nonmemory_operand" "<r><i>"))
836 (match_operand:SI
2 "const_int_operand")] ;; model
838 (clobber (reg:CC FLAGS_REG))]
841 if (incdec_operand (operands[
1], <MODE>mode))
843 if (operands[
1] == const1_rtx)
844 return "lock{%;} %K2dec{<imodesuffix>}
\t%
0";
847 gcc_assert (operands[
1] == constm1_rtx);
848 return "lock{%;} %K2inc{<imodesuffix>}
\t%
0";
852 if (x86_maybe_negate_const_int (&operands[
1], <MODE>mode))
853 return "lock{%;} %K2add{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}";
855 return "lock{%;} %K2sub{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}";
858 (define_insn "atomic_<logic><mode>"
859 [(set (match_operand:SWI
0 "memory_operand" "+m")
861 [(any_logic:SWI (match_dup
0)
862 (match_operand:SWI
1 "nonmemory_operand" "<r><i>"))
863 (match_operand:SI
2 "const_int_operand")] ;; model
865 (clobber (reg:CC FLAGS_REG))]
867 "lock{%;} %K2<logic>{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}")
869 (define_expand "atomic_bit_test_and_set<mode>"
870 [(match_operand:SWI248
0 "register_operand")
871 (match_operand:SWI248
1 "memory_operand")
872 (match_operand:SWI248
2 "nonmemory_operand")
873 (match_operand:SI
3 "const_int_operand") ;; model
874 (match_operand:SI
4 "const_int_operand")]
877 emit_insn (gen_atomic_bit_test_and_set<mode>_1 (operands[
1], operands[
2],
879 rtx tem = gen_reg_rtx (QImode);
880 ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
881 rtx result = convert_modes (<MODE>mode, QImode, tem,
1);
882 if (operands[
4] == const0_rtx)
883 result = expand_simple_binop (<MODE>mode, ASHIFT, result,
884 operands[
2], operands[
0],
0, OPTAB_WIDEN);
885 if (result != operands[
0])
886 emit_move_insn (operands[
0], result);
890 (define_insn "atomic_bit_test_and_set<mode>_1"
891 [(set (reg:CCC FLAGS_REG)
893 (unspec_volatile:SWI248
894 [(match_operand:SWI248
0 "memory_operand" "+m")
895 (match_operand:SI
2 "const_int_operand")] ;; model
898 (set (zero_extract:SWI248 (match_dup
0)
900 (match_operand:SWI248
1 "nonmemory_operand" "rN"))
903 "lock{%;} %K2bts{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}")
905 (define_expand "atomic_bit_test_and_complement<mode>"
906 [(match_operand:SWI248
0 "register_operand")
907 (match_operand:SWI248
1 "memory_operand")
908 (match_operand:SWI248
2 "nonmemory_operand")
909 (match_operand:SI
3 "const_int_operand") ;; model
910 (match_operand:SI
4 "const_int_operand")]
913 emit_insn (gen_atomic_bit_test_and_complement<mode>_1 (operands[
1],
916 rtx tem = gen_reg_rtx (QImode);
917 ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
918 rtx result = convert_modes (<MODE>mode, QImode, tem,
1);
919 if (operands[
4] == const0_rtx)
920 result = expand_simple_binop (<MODE>mode, ASHIFT, result,
921 operands[
2], operands[
0],
0, OPTAB_WIDEN);
922 if (result != operands[
0])
923 emit_move_insn (operands[
0], result);
927 (define_insn "atomic_bit_test_and_complement<mode>_1"
928 [(set (reg:CCC FLAGS_REG)
930 (unspec_volatile:SWI248
931 [(match_operand:SWI248
0 "memory_operand" "+m")
932 (match_operand:SI
2 "const_int_operand")] ;; model
935 (set (zero_extract:SWI248 (match_dup
0)
937 (match_operand:SWI248
1 "nonmemory_operand" "rN"))
938 (not:SWI248 (zero_extract:SWI248 (match_dup
0)
942 "lock{%;} %K2btc{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}")
944 (define_expand "atomic_bit_test_and_reset<mode>"
945 [(match_operand:SWI248
0 "register_operand")
946 (match_operand:SWI248
1 "memory_operand")
947 (match_operand:SWI248
2 "nonmemory_operand")
948 (match_operand:SI
3 "const_int_operand") ;; model
949 (match_operand:SI
4 "const_int_operand")]
952 emit_insn (gen_atomic_bit_test_and_reset<mode>_1 (operands[
1], operands[
2],
954 rtx tem = gen_reg_rtx (QImode);
955 ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
956 rtx result = convert_modes (<MODE>mode, QImode, tem,
1);
957 if (operands[
4] == const0_rtx)
958 result = expand_simple_binop (<MODE>mode, ASHIFT, result,
959 operands[
2], operands[
0],
0, OPTAB_WIDEN);
960 if (result != operands[
0])
961 emit_move_insn (operands[
0], result);
965 (define_insn "atomic_bit_test_and_reset<mode>_1"
966 [(set (reg:CCC FLAGS_REG)
968 (unspec_volatile:SWI248
969 [(match_operand:SWI248
0 "memory_operand" "+m")
970 (match_operand:SI
2 "const_int_operand")] ;; model
973 (set (zero_extract:SWI248 (match_dup
0)
975 (match_operand:SWI248
1 "nonmemory_operand" "rN"))
978 "lock{%;} %K2btr{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}")
980 (define_expand "atomic_<plusminus_mnemonic>_fetch_cmp_0<mode>"
981 [(match_operand:QI
0 "register_operand")
982 (plusminus:SWI (match_operand:SWI
1 "memory_operand")
983 (match_operand:SWI
2 "nonmemory_operand"))
984 (match_operand:SI
3 "const_int_operand") ;; model
985 (match_operand:SI
4 "const_int_operand")]
988 if (INTVAL (operands[
4]) == GT || INTVAL (operands[
4]) == LE)
990 emit_insn (gen_atomic_<plusminus_mnemonic>_fetch_cmp_0<mode>_1 (operands[
1],
993 ix86_expand_setcc (operands[
0], (enum rtx_code) INTVAL (operands[
4]),
994 gen_rtx_REG (CCGOCmode, FLAGS_REG), const0_rtx);
998 (define_insn "atomic_add_fetch_cmp_0<mode>_1"
999 [(set (reg:CCGOC FLAGS_REG)
1002 (unspec_volatile:SWI
1003 [(match_operand:SWI
0 "memory_operand" "+m")
1004 (match_operand:SI
2 "const_int_operand")] ;; model
1006 (match_operand:SWI
1 "nonmemory_operand" "<r><i>"))
1009 (plus:SWI (match_dup
0) (match_dup
1)))]
1012 if (incdec_operand (operands[
1], <MODE>mode))
1014 if (operands[
1] == const1_rtx)
1015 return "lock{%;} %K2inc{<imodesuffix>}
\t%
0";
1017 return "lock{%;} %K2dec{<imodesuffix>}
\t%
0";
1020 if (x86_maybe_negate_const_int (&operands[
1], <MODE>mode))
1021 return "lock{%;} %K2sub{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}";
1023 return "lock{%;} %K2add{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}";
1026 (define_insn "atomic_sub_fetch_cmp_0<mode>_1"
1027 [(set (reg:CCGOC FLAGS_REG)
1030 (unspec_volatile:SWI
1031 [(match_operand:SWI
0 "memory_operand" "+m")
1032 (match_operand:SI
2 "const_int_operand")] ;; model
1034 (match_operand:SWI
1 "nonmemory_operand" "<r><i>"))
1037 (minus:SWI (match_dup
0) (match_dup
1)))]
1040 if (incdec_operand (operands[
1], <MODE>mode))
1042 if (operands[
1] != const1_rtx)
1043 return "lock{%;} %K2inc{<imodesuffix>}
\t%
0";
1045 return "lock{%;} %K2dec{<imodesuffix>}
\t%
0";
1048 if (x86_maybe_negate_const_int (&operands[
1], <MODE>mode))
1049 return "lock{%;} %K2add{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}";
1051 return "lock{%;} %K2sub{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}";
1054 (define_expand "atomic_<logic>_fetch_cmp_0<mode>"
1055 [(match_operand:QI
0 "register_operand")
1056 (any_logic:SWI (match_operand:SWI
1 "memory_operand")
1057 (match_operand:SWI
2 "nonmemory_operand"))
1058 (match_operand:SI
3 "const_int_operand") ;; model
1059 (match_operand:SI
4 "const_int_operand")]
1062 emit_insn (gen_atomic_<logic>_fetch_cmp_0<mode>_1 (operands[
1], operands[
2],
1064 ix86_expand_setcc (operands[
0], (enum rtx_code) INTVAL (operands[
4]),
1065 gen_rtx_REG (CCNOmode, FLAGS_REG), const0_rtx);
1069 (define_insn "atomic_<logic>_fetch_cmp_0<mode>_1"
1070 [(set (reg:CCNO FLAGS_REG)
1073 (unspec_volatile:SWI
1074 [(match_operand:SWI
0 "memory_operand" "+m")
1075 (match_operand:SI
2 "const_int_operand")] ;; model
1077 (match_operand:SWI
1 "nonmemory_operand" "<r><i>"))
1080 (any_logic:SWI (match_dup
0) (match_dup
1)))]
1082 "lock{%;} %K2<logic>{<imodesuffix>}
\t{%
1, %
0|%
0, %
1}")
1086 (define_insn "cmpccxadd_<mode>"
1087 [(set (match_operand:SWI48x
0 "register_operand" "=r")
1088 (unspec_volatile:SWI48x
1089 [(match_operand:SWI48x
1 "memory_operand" "+m")
1090 (match_operand:SWI48x
2 "register_operand" "
0")
1091 (match_operand:SWI48x
3 "register_operand" "r")
1092 (match_operand:SI
4 "const_0_to_15_operand" "n")]
1095 (unspec_volatile:SWI48x [(const_int
0)] UNSPECV_CMPCCXADD))
1096 (clobber (reg:CC FLAGS_REG))]
1097 "TARGET_CMPCCXADD && TARGET_64BIT"
1100 const char *ops = "cmp%sxadd
\t{%%
3, %%
0, %%
1|%%
1, %%
0, %%
3}";
1101 char const *cc[
16] = {"o" ,"no", "b", "nb", "z", "nz", "be", "nbe",
1102 "s", "ns", "p", "np", "l", "nl", "le", "nle"};
1104 snprintf (buf, sizeof (buf), ops, cc[INTVAL (operands[
4])]);
1105 output_asm_insn (buf, operands);