Home | History | Annotate | Line # | Download | only in i386
sync.md revision 1.12
      1 ;; GCC machine description for i386 synchronization instructions.
      2 ;; Copyright (C) 2005-2022 Free Software Foundation, Inc.
      3 ;;
      4 ;; This file is part of GCC.
      5 ;;
      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)
      9 ;; any later version.
     10 ;;
     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.
     15 ;;
     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/>.
     19 
     20 (define_c_enum "unspec" [
     21   UNSPEC_LFENCE
     22   UNSPEC_SFENCE
     23   UNSPEC_MFENCE
     24 
     25   UNSPEC_FILD_ATOMIC
     26   UNSPEC_FIST_ATOMIC
     27 
     28   UNSPEC_LDX_ATOMIC
     29   UNSPEC_STX_ATOMIC
     30 
     31   ;; __atomic support
     32   UNSPEC_LDA
     33   UNSPEC_STA
     34 ])
     35 
     36 (define_c_enum "unspecv" [
     37   UNSPECV_CMPXCHG
     38   UNSPECV_XCHG
     39   UNSPECV_LOCK
     40 ])
     41 
     42 (define_expand "sse2_lfence"
     43   [(set (match_dup 0)
     44 	(unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
     45   "TARGET_SSE2"
     46 {
     47   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
     48   MEM_VOLATILE_P (operands[0]) = 1;
     49 })
     50 
     51 (define_insn "*sse2_lfence"
     52   [(set (match_operand:BLK 0)
     53 	(unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
     54   "TARGET_SSE2"
     55   "lfence"
     56   [(set_attr "type" "sse")
     57    (set_attr "length_address" "0")
     58    (set_attr "atom_sse_attr" "lfence")
     59    (set_attr "memory" "unknown")])
     60 
     61 (define_expand "sse_sfence"
     62   [(set (match_dup 0)
     63 	(unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
     64   "TARGET_SSE || TARGET_3DNOW_A"
     65 {
     66   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
     67   MEM_VOLATILE_P (operands[0]) = 1;
     68 })
     69 
     70 (define_insn "*sse_sfence"
     71   [(set (match_operand:BLK 0)
     72 	(unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
     73   "TARGET_SSE || TARGET_3DNOW_A"
     74   "sfence"
     75   [(set_attr "type" "sse")
     76    (set_attr "length_address" "0")
     77    (set_attr "atom_sse_attr" "fence")
     78    (set_attr "memory" "unknown")])
     79 
     80 (define_expand "sse2_mfence"
     81   [(set (match_dup 0)
     82 	(unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
     83   "TARGET_SSE2"
     84 {
     85   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
     86   MEM_VOLATILE_P (operands[0]) = 1;
     87 })
     88 
     89 (define_insn "mfence_sse2"
     90   [(set (match_operand:BLK 0)
     91 	(unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
     92   "TARGET_64BIT || TARGET_SSE2"
     93   "mfence"
     94   [(set_attr "type" "sse")
     95    (set_attr "length_address" "0")
     96    (set_attr "atom_sse_attr" "fence")
     97    (set_attr "memory" "unknown")])
     98 
     99 (define_insn "mfence_nosse"
    100   [(set (match_operand:BLK 0)
    101 	(unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))
    102    (clobber (reg:CC FLAGS_REG))]
    103   ""
    104 {
    105   rtx mem = gen_rtx_MEM (word_mode, stack_pointer_rtx);
    106 
    107   output_asm_insn ("lock{%;} or%z0\t{$0, %0|%0, 0}", &mem);
    108   return "";
    109 }
    110   [(set_attr "memory" "unknown")])
    111 
    112 (define_expand "mem_thread_fence"
    113   [(match_operand:SI 0 "const_int_operand")]		;; model
    114   ""
    115 {
    116   enum memmodel model = memmodel_from_int (INTVAL (operands[0]));
    117 
    118   /* Unless this is a SEQ_CST fence, the i386 memory model is strong
    119      enough not to require barriers of any kind.  */
    120   if (is_mm_seq_cst (model))
    121     {
    122       rtx (*mfence_insn)(rtx);
    123       rtx mem;
    124 
    125       if ((TARGET_64BIT || TARGET_SSE2)
    126 	  && (optimize_function_for_size_p (cfun)
    127 	      || !TARGET_AVOID_MFENCE))
    128 	mfence_insn = gen_mfence_sse2;
    129       else
    130 	mfence_insn = gen_mfence_nosse;
    131 
    132       mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
    133       MEM_VOLATILE_P (mem) = 1;
    134 
    135       emit_insn (mfence_insn (mem));
    136     }
    137   DONE;
    138 })
    139 
    140 ;; ??? From volume 3 section 8.1.1 Guaranteed Atomic Operations,
    141 ;; Only beginning at Pentium family processors do we get any guarantee of
    142 ;; atomicity in aligned 64-bit quantities.  Beginning at P6, we get a
    143 ;; guarantee for 64-bit accesses that do not cross a cacheline boundary.
    144 ;;
    145 ;; Note that the TARGET_CMPXCHG8B test below is a stand-in for "Pentium".
    146 ;;
    147 ;; Importantly, *no* processor makes atomicity guarantees for larger
    148 ;; accesses.  In particular, there's no way to perform an atomic TImode
    149 ;; move, despite the apparent applicability of MOVDQA et al.
    150 
    151 (define_mode_iterator ATOMIC
    152    [QI HI SI
    153     (DI "TARGET_64BIT || (TARGET_CMPXCHG8B && (TARGET_80387 || TARGET_SSE))")
    154    ])
    155 
    156 (define_expand "atomic_load<mode>"
    157   [(set (match_operand:ATOMIC 0 "nonimmediate_operand")
    158 	(unspec:ATOMIC [(match_operand:ATOMIC 1 "memory_operand")
    159 			(match_operand:SI 2 "const_int_operand")]
    160 		       UNSPEC_LDA))]
    161   ""
    162 {
    163   /* For DImode on 32-bit, we can use the FPU to perform the load.  */
    164   if (<MODE>mode == DImode && !TARGET_64BIT)
    165     emit_insn (gen_atomic_loaddi_fpu
    166 	       (operands[0], operands[1],
    167 	        assign_386_stack_local (DImode, SLOT_TEMP)));
    168   else
    169     {
    170       rtx dst = operands[0];
    171 
    172       if (MEM_P (dst))
    173 	dst = gen_reg_rtx (<MODE>mode);
    174 
    175       emit_move_insn (dst, operands[1]);
    176 
    177       /* Fix up the destination if needed.  */
    178       if (dst != operands[0])
    179 	emit_move_insn (operands[0], dst);
    180     }
    181   DONE;
    182 })
    183 
    184 (define_insn_and_split "atomic_loaddi_fpu"
    185   [(set (match_operand:DI 0 "nonimmediate_operand" "=x,m,?r")
    186 	(unspec:DI [(match_operand:DI 1 "memory_operand" "m,m,m")]
    187 		   UNSPEC_LDA))
    188    (clobber (match_operand:DI 2 "memory_operand" "=X,X,m"))
    189    (clobber (match_scratch:DF 3 "=X,xf,xf"))]
    190   "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)"
    191   "#"
    192   "&& reload_completed"
    193   [(const_int 0)]
    194 {
    195   rtx dst = operands[0], src = operands[1];
    196   rtx mem = operands[2], tmp = operands[3];
    197 
    198   if (SSE_REG_P (dst))
    199     emit_move_insn (dst, src);
    200   else
    201     {
    202       if (MEM_P (dst))
    203 	mem = dst;
    204 
    205       if (STACK_REG_P (tmp))
    206         {
    207 	  emit_insn (gen_loaddi_via_fpu (tmp, src));
    208 	  emit_insn (gen_storedi_via_fpu (mem, tmp));
    209 	}
    210       else
    211 	{
    212 	  emit_insn (gen_loaddi_via_sse (tmp, src));
    213 	  emit_insn (gen_storedi_via_sse (mem, tmp));
    214 	}
    215 
    216       if (mem != dst)
    217 	emit_move_insn (dst, mem);
    218     }
    219   DONE;
    220 })
    221 
    222 (define_expand "atomic_store<mode>"
    223   [(set (match_operand:ATOMIC 0 "memory_operand")
    224 	(unspec:ATOMIC [(match_operand:ATOMIC 1 "nonimmediate_operand")
    225 			(match_operand:SI 2 "const_int_operand")]
    226 		       UNSPEC_STA))]
    227   ""
    228 {
    229   enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
    230 
    231   if (<MODE>mode == DImode && !TARGET_64BIT)
    232     {
    233       /* For DImode on 32-bit, we can use the FPU to perform the store.  */
    234       /* Note that while we could perform a cmpxchg8b loop, that turns
    235 	 out to be significantly larger than this plus a barrier.  */
    236       emit_insn (gen_atomic_storedi_fpu
    237 		 (operands[0], operands[1],
    238 	          assign_386_stack_local (DImode, SLOT_TEMP)));
    239     }
    240   else
    241     {
    242       operands[1] = force_reg (<MODE>mode, operands[1]);
    243 
    244       /* For seq-cst stores, use XCHG when we lack MFENCE.  */
    245       if (is_mm_seq_cst (model)
    246 	  && (!(TARGET_64BIT || TARGET_SSE2)
    247 	      || TARGET_AVOID_MFENCE))
    248 	{
    249 	  emit_insn (gen_atomic_exchange<mode> (gen_reg_rtx (<MODE>mode),
    250 						operands[0], operands[1],
    251 						operands[2]));
    252 	  DONE;
    253 	}
    254 
    255       /* Otherwise use a store.  */
    256       emit_insn (gen_atomic_store<mode>_1 (operands[0], operands[1],
    257 					   operands[2]));
    258     }
    259   /* ... followed by an MFENCE, if required.  */
    260   if (is_mm_seq_cst (model))
    261     emit_insn (gen_mem_thread_fence (operands[2]));
    262   DONE;
    263 })
    264 
    265 (define_insn "atomic_store<mode>_1"
    266   [(set (match_operand:SWI 0 "memory_operand" "=m")
    267 	(unspec:SWI [(match_operand:SWI 1 "<nonmemory_operand>" "<r><i>")
    268 		     (match_operand:SI 2 "const_int_operand")]
    269 		    UNSPEC_STA))]
    270   ""
    271   "%K2mov{<imodesuffix>}\t{%1, %0|%0, %1}")
    272 
    273 (define_insn_and_split "atomic_storedi_fpu"
    274   [(set (match_operand:DI 0 "memory_operand" "=m,m,m")
    275 	(unspec:DI [(match_operand:DI 1 "nonimmediate_operand" "x,m,?r")]
    276 		   UNSPEC_STA))
    277    (clobber (match_operand:DI 2 "memory_operand" "=X,X,m"))
    278    (clobber (match_scratch:DF 3 "=X,xf,xf"))]
    279   "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)"
    280   "#"
    281   "&& reload_completed"
    282   [(const_int 0)]
    283 {
    284   rtx dst = operands[0], src = operands[1];
    285   rtx mem = operands[2], tmp = operands[3];
    286 
    287   if (SSE_REG_P (src))
    288     emit_move_insn (dst, src);
    289   else
    290     {
    291       if (REG_P (src))
    292 	{
    293 	  emit_move_insn (mem, src);
    294 	  src = mem;
    295 	}
    296 
    297       if (STACK_REG_P (tmp))
    298 	{
    299 	  emit_insn (gen_loaddi_via_fpu (tmp, src));
    300 	  emit_insn (gen_storedi_via_fpu (dst, tmp));
    301 	}
    302       else
    303 	{
    304 	  emit_insn (gen_loaddi_via_sse (tmp, src));
    305 	  emit_insn (gen_storedi_via_sse (dst, tmp));
    306 	}
    307     }
    308   DONE;
    309 })
    310 
    311 ;; ??? You'd think that we'd be able to perform this via FLOAT + FIX_TRUNC
    312 ;; operations.  But the fix_trunc patterns want way more setup than we want
    313 ;; to provide.  Note that the scratch is DFmode instead of XFmode in order
    314 ;; to make it easy to allocate a scratch in either SSE or FP_REGs above.
    315 
    316 (define_insn "loaddi_via_fpu"
    317   [(set (match_operand:DF 0 "register_operand" "=f")
    318 	(unspec:DF [(match_operand:DI 1 "memory_operand" "m")]
    319 		   UNSPEC_FILD_ATOMIC))]
    320   "TARGET_80387"
    321   "fild%Z1\t%1"
    322   [(set_attr "type" "fmov")
    323    (set_attr "mode" "DF")
    324    (set_attr "fp_int_src" "true")])
    325 
    326 (define_insn "storedi_via_fpu"
    327   [(set (match_operand:DI 0 "memory_operand" "=m")
    328 	(unspec:DI [(match_operand:DF 1 "register_operand" "f")]
    329 		   UNSPEC_FIST_ATOMIC))]
    330   "TARGET_80387"
    331 {
    332   gcc_assert (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != NULL_RTX);
    333 
    334   return "fistp%Z0\t%0";
    335 }
    336   [(set_attr "type" "fmov")
    337    (set_attr "mode" "DI")])
    338 
    339 (define_insn "loaddi_via_sse"
    340   [(set (match_operand:DF 0 "register_operand" "=x")
    341 	(unspec:DF [(match_operand:DI 1 "memory_operand" "m")]
    342 		   UNSPEC_LDX_ATOMIC))]
    343   "TARGET_SSE"
    344 {
    345   if (TARGET_SSE2)
    346     return "%vmovq\t{%1, %0|%0, %1}";
    347   return "movlps\t{%1, %0|%0, %1}";
    348 }
    349   [(set_attr "type" "ssemov")
    350    (set_attr "mode" "DI")])
    351 
    352 (define_insn "storedi_via_sse"
    353   [(set (match_operand:DI 0 "memory_operand" "=m")
    354 	(unspec:DI [(match_operand:DF 1 "register_operand" "x")]
    355 		   UNSPEC_STX_ATOMIC))]
    356   "TARGET_SSE"
    357 {
    358   if (TARGET_SSE2)
    359     return "%vmovq\t{%1, %0|%0, %1}";
    360   return "movlps\t{%1, %0|%0, %1}";
    361 }
    362   [(set_attr "type" "ssemov")
    363    (set_attr "mode" "DI")])
    364 
    365 (define_expand "atomic_compare_and_swap<mode>"
    366   [(match_operand:QI 0 "register_operand")	;; bool success output
    367    (match_operand:SWI124 1 "register_operand")	;; oldval output
    368    (match_operand:SWI124 2 "memory_operand")	;; memory
    369    (match_operand:SWI124 3 "register_operand")	;; expected input
    370    (match_operand:SWI124 4 "register_operand")	;; newval input
    371    (match_operand:SI 5 "const_int_operand")	;; is_weak
    372    (match_operand:SI 6 "const_int_operand")	;; success model
    373    (match_operand:SI 7 "const_int_operand")]	;; failure model
    374   "TARGET_CMPXCHG"
    375 {
    376   if (TARGET_RELAX_CMPXCHG_LOOP)
    377   {
    378     ix86_expand_cmpxchg_loop (&operands[0], operands[1], operands[2],
    379 			      operands[3], operands[4], operands[6],
    380 			      false, NULL);
    381   }
    382   else
    383   {
    384     emit_insn
    385       (gen_atomic_compare_and_swap<mode>_1
    386 	(operands[1], operands[2], operands[3], operands[4], operands[6]));
    387       ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
    388 			const0_rtx);
    389   }
    390   DONE;
    391 })
    392 
    393 (define_mode_iterator CASMODE
    394   [(DI "TARGET_64BIT || TARGET_CMPXCHG8B")
    395    (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
    396 (define_mode_attr CASHMODE [(DI "SI") (TI "DI")])
    397 
    398 (define_expand "atomic_compare_and_swap<mode>"
    399   [(match_operand:QI 0 "register_operand")	;; bool success output
    400    (match_operand:CASMODE 1 "register_operand")	;; oldval output
    401    (match_operand:CASMODE 2 "memory_operand")	;; memory
    402    (match_operand:CASMODE 3 "register_operand")	;; expected input
    403    (match_operand:CASMODE 4 "register_operand")	;; newval input
    404    (match_operand:SI 5 "const_int_operand")	;; is_weak
    405    (match_operand:SI 6 "const_int_operand")	;; success model
    406    (match_operand:SI 7 "const_int_operand")]	;; failure model
    407   "TARGET_CMPXCHG"
    408 {
    409   int doubleword = !(<MODE>mode == DImode && TARGET_64BIT);
    410   if (TARGET_RELAX_CMPXCHG_LOOP)
    411   {
    412     ix86_expand_cmpxchg_loop (&operands[0], operands[1], operands[2],
    413 			      operands[3], operands[4], operands[6],
    414 			      doubleword, NULL);
    415   }
    416   else
    417   {
    418     if (!doubleword)
    419       {
    420 	emit_insn
    421 	  (gen_atomic_compare_and_swapdi_1
    422 	   (operands[1], operands[2], operands[3], operands[4], operands[6]));
    423       }
    424     else
    425       {
    426 	machine_mode hmode = <CASHMODE>mode;
    427 
    428 	emit_insn
    429 	  (gen_atomic_compare_and_swap<mode>_doubleword
    430 	   (operands[1], operands[2], operands[3],
    431 	    gen_lowpart (hmode, operands[4]), gen_highpart (hmode, operands[4]),
    432 	    operands[6]));
    433       }
    434 
    435     ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
    436 		       const0_rtx);
    437   }
    438   DONE;
    439 })
    440 
    441 ;; For double-word compare and swap, we are obliged to play tricks with
    442 ;; the input newval (op3:op4) because the Intel register numbering does
    443 ;; not match the gcc register numbering, so the pair must be CX:BX.
    444 
    445 (define_mode_attr doublemodesuffix [(SI "8") (DI "16")])
    446 
    447 (define_insn "atomic_compare_and_swap<dwi>_doubleword"
    448   [(set (match_operand:<DWI> 0 "register_operand" "=A")
    449 	(unspec_volatile:<DWI>
    450 	  [(match_operand:<DWI> 1 "memory_operand" "+m")
    451 	   (match_operand:<DWI> 2 "register_operand" "0")
    452 	   (match_operand:DWIH 3 "register_operand" "b")
    453 	   (match_operand:DWIH 4 "register_operand" "c")
    454 	   (match_operand:SI 5 "const_int_operand")]
    455 	  UNSPECV_CMPXCHG))
    456    (set (match_dup 1)
    457 	(unspec_volatile:<DWI> [(const_int 0)] UNSPECV_CMPXCHG))
    458    (set (reg:CCZ FLAGS_REG)
    459         (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))]
    460   "TARGET_CMPXCHG<doublemodesuffix>B"
    461   "lock{%;} %K5cmpxchg<doublemodesuffix>b\t%1")
    462 
    463 (define_insn "atomic_compare_and_swap<mode>_1"
    464   [(set (match_operand:SWI 0 "register_operand" "=a")
    465 	(unspec_volatile:SWI
    466 	  [(match_operand:SWI 1 "memory_operand" "+m")
    467 	   (match_operand:SWI 2 "register_operand" "0")
    468 	   (match_operand:SWI 3 "register_operand" "<r>")
    469 	   (match_operand:SI 4 "const_int_operand")]
    470 	  UNSPECV_CMPXCHG))
    471    (set (match_dup 1)
    472 	(unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    473    (set (reg:CCZ FLAGS_REG)
    474         (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))]
    475   "TARGET_CMPXCHG"
    476   "lock{%;} %K4cmpxchg{<imodesuffix>}\t{%3, %1|%1, %3}")
    477 
    478 (define_peephole2
    479   [(set (match_operand:SWI 0 "register_operand")
    480 	(match_operand:SWI 1 "general_operand"))
    481    (parallel [(set (match_dup 0)
    482 		   (unspec_volatile:SWI
    483 		     [(match_operand:SWI 2 "memory_operand")
    484 		      (match_dup 0)
    485 		      (match_operand:SWI 3 "register_operand")
    486 		      (match_operand:SI 4 "const_int_operand")]
    487 		     UNSPECV_CMPXCHG))
    488 	      (set (match_dup 2)
    489 		   (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    490 	      (set (reg:CCZ FLAGS_REG)
    491 		   (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))])
    492    (set (reg:CCZ FLAGS_REG)
    493 	(compare:CCZ (match_operand:SWI 5 "register_operand")
    494 		     (match_operand:SWI 6 "general_operand")))]
    495   "(rtx_equal_p (operands[0], operands[5])
    496     && rtx_equal_p (operands[1], operands[6]))
    497    || (rtx_equal_p (operands[0], operands[6])
    498        && rtx_equal_p (operands[1], operands[5]))"
    499   [(set (match_dup 0)
    500 	(match_dup 1))
    501    (parallel [(set (match_dup 0)
    502 		   (unspec_volatile:SWI
    503 		     [(match_dup 2)
    504 		      (match_dup 0)
    505 		      (match_dup 3)
    506 		      (match_dup 4)]
    507 		     UNSPECV_CMPXCHG))
    508 	      (set (match_dup 2)
    509 		   (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    510 	      (set (reg:CCZ FLAGS_REG)
    511 		   (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))])])
    512 
    513 (define_peephole2
    514   [(parallel [(set (match_operand:SWI48 0 "register_operand")
    515 		   (match_operand:SWI48 1 "const_int_operand"))
    516 	      (clobber (reg:CC FLAGS_REG))])
    517    (parallel [(set (match_operand:SWI 2 "register_operand")
    518 		   (unspec_volatile:SWI
    519 		     [(match_operand:SWI 3 "memory_operand")
    520 		      (match_dup 2)
    521 		      (match_operand:SWI 4 "register_operand")
    522 		      (match_operand:SI 5 "const_int_operand")]
    523 		     UNSPECV_CMPXCHG))
    524 	      (set (match_dup 3)
    525 		   (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    526 	      (set (reg:CCZ FLAGS_REG)
    527 		   (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))])
    528    (set (reg:CCZ FLAGS_REG)
    529 	(compare:CCZ (match_dup 2)
    530 		     (match_dup 1)))]
    531   "REGNO (operands[0]) == REGNO (operands[2])"
    532   [(parallel [(set (match_dup 0)
    533 		   (match_dup 1))
    534 	      (clobber (reg:CC FLAGS_REG))])
    535    (parallel [(set (match_dup 2)
    536 		   (unspec_volatile:SWI
    537 		     [(match_dup 3)
    538 		      (match_dup 2)
    539 		      (match_dup 4)
    540 		      (match_dup 5)]
    541 		     UNSPECV_CMPXCHG))
    542 	      (set (match_dup 3)
    543 		   (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    544 	      (set (reg:CCZ FLAGS_REG)
    545 		   (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))])])
    546 
    547 (define_expand "atomic_fetch_<logic><mode>"
    548   [(match_operand:SWI124 0 "register_operand")
    549    (any_logic:SWI124
    550     (match_operand:SWI124 1 "memory_operand")
    551     (match_operand:SWI124 2 "register_operand"))
    552    (match_operand:SI 3 "const_int_operand")]
    553   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    554 {
    555   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    556 				    operands[2], <CODE>, false,
    557 				    false);
    558   DONE;
    559 })
    560 
    561 (define_expand "atomic_<logic>_fetch<mode>"
    562   [(match_operand:SWI124 0 "register_operand")
    563    (any_logic:SWI124
    564     (match_operand:SWI124 1 "memory_operand")
    565     (match_operand:SWI124 2 "register_operand"))
    566    (match_operand:SI 3 "const_int_operand")]
    567   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    568 {
    569   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    570 				    operands[2], <CODE>, true,
    571 				    false);
    572   DONE;
    573 })
    574 
    575 (define_expand "atomic_fetch_nand<mode>"
    576   [(match_operand:SWI124 0 "register_operand")
    577    (match_operand:SWI124 1 "memory_operand")
    578    (match_operand:SWI124 2 "register_operand")
    579    (match_operand:SI 3 "const_int_operand")]
    580   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    581 {
    582   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    583 				    operands[2], NOT, false,
    584 				    false);
    585   DONE;
    586 })
    587 
    588 (define_expand "atomic_nand_fetch<mode>"
    589   [(match_operand:SWI124 0 "register_operand")
    590    (match_operand:SWI124 1 "memory_operand")
    591    (match_operand:SWI124 2 "register_operand")
    592    (match_operand:SI 3 "const_int_operand")]
    593   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    594 {
    595   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    596 				    operands[2], NOT, true,
    597 				    false);
    598   DONE;
    599 })
    600 
    601 (define_expand "atomic_fetch_<logic><mode>"
    602   [(match_operand:CASMODE 0 "register_operand")
    603    (any_logic:CASMODE
    604     (match_operand:CASMODE 1 "memory_operand")
    605     (match_operand:CASMODE 2 "register_operand"))
    606    (match_operand:SI 3 "const_int_operand")]
    607   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    608 {
    609   bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
    610 		    || (<MODE>mode == TImode);
    611   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    612 				    operands[2], <CODE>, false,
    613 				    doubleword);
    614   DONE;
    615 })
    616 
    617 (define_expand "atomic_<logic>_fetch<mode>"
    618   [(match_operand:CASMODE 0 "register_operand")
    619    (any_logic:CASMODE
    620     (match_operand:CASMODE 1 "memory_operand")
    621     (match_operand:CASMODE 2 "register_operand"))
    622    (match_operand:SI 3 "const_int_operand")]
    623   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    624 {
    625   bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
    626 		    || (<MODE>mode == TImode);
    627   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    628 				    operands[2], <CODE>, true,
    629 				    doubleword);
    630   DONE;
    631 })
    632 
    633 (define_expand "atomic_fetch_nand<mode>"
    634   [(match_operand:CASMODE 0 "register_operand")
    635    (match_operand:CASMODE 1 "memory_operand")
    636    (match_operand:CASMODE 2 "register_operand")
    637    (match_operand:SI 3 "const_int_operand")]
    638   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    639 {
    640   bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
    641 		    || (<MODE>mode == TImode);
    642   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    643 				    operands[2], NOT, false,
    644 				    doubleword);
    645   DONE;
    646 })
    647 
    648 (define_expand "atomic_nand_fetch<mode>"
    649   [(match_operand:CASMODE 0 "register_operand")
    650    (match_operand:CASMODE 1 "memory_operand")
    651    (match_operand:CASMODE 2 "register_operand")
    652    (match_operand:SI 3 "const_int_operand")]
    653   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    654 {
    655   bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
    656 		    || (<MODE>mode == TImode);
    657   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    658 				    operands[2], NOT, true,
    659 				    doubleword);
    660   DONE;
    661 })
    662 
    663 
    664 ;; For operand 2 nonmemory_operand predicate is used instead of
    665 ;; register_operand to allow combiner to better optimize atomic
    666 ;; additions of constants.
    667 (define_insn "atomic_fetch_add<mode>"
    668   [(set (match_operand:SWI 0 "register_operand" "=<r>")
    669 	(unspec_volatile:SWI
    670 	  [(match_operand:SWI 1 "memory_operand" "+m")
    671 	   (match_operand:SI 3 "const_int_operand")]		;; model
    672 	  UNSPECV_XCHG))
    673    (set (match_dup 1)
    674 	(plus:SWI (match_dup 1)
    675 		  (match_operand:SWI 2 "nonmemory_operand" "0")))
    676    (clobber (reg:CC FLAGS_REG))]
    677   "TARGET_XADD"
    678   "lock{%;} %K3xadd{<imodesuffix>}\t{%0, %1|%1, %0}")
    679 
    680 ;; This peephole2 and following insn optimize
    681 ;; __sync_fetch_and_add (x, -N) == N into just lock {add,sub,inc,dec}
    682 ;; followed by testing of flags instead of lock xadd and comparisons.
    683 (define_peephole2
    684   [(set (match_operand:SWI 0 "register_operand")
    685 	(match_operand:SWI 2 "const_int_operand"))
    686    (parallel [(set (match_dup 0)
    687 		   (unspec_volatile:SWI
    688 		     [(match_operand:SWI 1 "memory_operand")
    689 		      (match_operand:SI 4 "const_int_operand")]
    690 		     UNSPECV_XCHG))
    691 	      (set (match_dup 1)
    692 		   (plus:SWI (match_dup 1)
    693 			     (match_dup 0)))
    694 	      (clobber (reg:CC FLAGS_REG))])
    695    (set (reg:CCZ FLAGS_REG)
    696 	(compare:CCZ (match_dup 0)
    697 		     (match_operand:SWI 3 "const_int_operand")))]
    698   "peep2_reg_dead_p (3, operands[0])
    699    && (unsigned HOST_WIDE_INT) INTVAL (operands[2])
    700       == -(unsigned HOST_WIDE_INT) INTVAL (operands[3])
    701    && !reg_overlap_mentioned_p (operands[0], operands[1])"
    702   [(parallel [(set (reg:CCZ FLAGS_REG)
    703 		   (compare:CCZ
    704 		     (unspec_volatile:SWI [(match_dup 1) (match_dup 4)]
    705 					  UNSPECV_XCHG)
    706 		     (match_dup 3)))
    707 	      (set (match_dup 1)
    708 		   (plus:SWI (match_dup 1)
    709 			     (match_dup 2)))])])
    710 
    711 ;; Likewise, but for the -Os special case of *mov<mode>_or.
    712 (define_peephole2
    713   [(parallel [(set (match_operand:SWI 0 "register_operand")
    714 		   (match_operand:SWI 2 "constm1_operand"))
    715 	      (clobber (reg:CC FLAGS_REG))])
    716    (parallel [(set (match_dup 0)
    717 		   (unspec_volatile:SWI
    718 		     [(match_operand:SWI 1 "memory_operand")
    719 		      (match_operand:SI 4 "const_int_operand")]
    720 		     UNSPECV_XCHG))
    721 	      (set (match_dup 1)
    722 		   (plus:SWI (match_dup 1)
    723 			     (match_dup 0)))
    724 	      (clobber (reg:CC FLAGS_REG))])
    725    (set (reg:CCZ FLAGS_REG)
    726 	(compare:CCZ (match_dup 0)
    727 		     (match_operand:SWI 3 "const_int_operand")))]
    728   "peep2_reg_dead_p (3, operands[0])
    729    && (unsigned HOST_WIDE_INT) INTVAL (operands[2])
    730       == -(unsigned HOST_WIDE_INT) INTVAL (operands[3])
    731    && !reg_overlap_mentioned_p (operands[0], operands[1])"
    732   [(parallel [(set (reg:CCZ FLAGS_REG)
    733 		   (compare:CCZ
    734 		     (unspec_volatile:SWI [(match_dup 1) (match_dup 4)]
    735 					  UNSPECV_XCHG)
    736 		     (match_dup 3)))
    737 	      (set (match_dup 1)
    738 		   (plus:SWI (match_dup 1)
    739 			     (match_dup 2)))])])
    740 
    741 (define_insn "*atomic_fetch_add_cmp<mode>"
    742   [(set (reg:CCZ FLAGS_REG)
    743 	(compare:CCZ
    744 	  (unspec_volatile:SWI
    745 	    [(match_operand:SWI 0 "memory_operand" "+m")
    746 	     (match_operand:SI 3 "const_int_operand")]		;; model
    747 	    UNSPECV_XCHG)
    748 	  (match_operand:SWI 2 "const_int_operand" "i")))
    749    (set (match_dup 0)
    750 	(plus:SWI (match_dup 0)
    751 		  (match_operand:SWI 1 "const_int_operand" "i")))]
    752   "(unsigned HOST_WIDE_INT) INTVAL (operands[1])
    753    == -(unsigned HOST_WIDE_INT) INTVAL (operands[2])"
    754 {
    755   if (incdec_operand (operands[1], <MODE>mode))
    756     {
    757       if (operands[1] == const1_rtx)
    758 	return "lock{%;} %K3inc{<imodesuffix>}\t%0";
    759       else
    760 	{
    761 	  gcc_assert (operands[1] == constm1_rtx);
    762 	  return "lock{%;} %K3dec{<imodesuffix>}\t%0";
    763 	}
    764     }
    765 
    766   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
    767     return "lock{%;} %K3sub{<imodesuffix>}\t{%1, %0|%0, %1}";
    768 
    769   return "lock{%;} %K3add{<imodesuffix>}\t{%1, %0|%0, %1}";
    770 })
    771 
    772 ;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space.
    773 ;; In addition, it is always a full barrier, so we can ignore the memory model.
    774 (define_insn "atomic_exchange<mode>"
    775   [(set (match_operand:SWI 0 "register_operand" "=<r>")		;; output
    776 	(unspec_volatile:SWI
    777 	  [(match_operand:SWI 1 "memory_operand" "+m")		;; memory
    778 	   (match_operand:SI 3 "const_int_operand")]		;; model
    779 	  UNSPECV_XCHG))
    780    (set (match_dup 1)
    781 	(match_operand:SWI 2 "register_operand" "0"))]		;; input
    782   ""
    783   "%K3xchg{<imodesuffix>}\t{%1, %0|%0, %1}")
    784 
    785 (define_insn "atomic_add<mode>"
    786   [(set (match_operand:SWI 0 "memory_operand" "+m")
    787 	(unspec_volatile:SWI
    788 	  [(plus:SWI (match_dup 0)
    789 		     (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    790 	   (match_operand:SI 2 "const_int_operand")]		;; model
    791 	  UNSPECV_LOCK))
    792    (clobber (reg:CC FLAGS_REG))]
    793   ""
    794 {
    795   if (incdec_operand (operands[1], <MODE>mode))
    796     {
    797       if (operands[1] == const1_rtx)
    798 	return "lock{%;} %K2inc{<imodesuffix>}\t%0";
    799       else
    800 	{
    801 	  gcc_assert (operands[1] == constm1_rtx);
    802 	  return "lock{%;} %K2dec{<imodesuffix>}\t%0";
    803 	}
    804     }
    805 
    806   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
    807     return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
    808 
    809   return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
    810 })
    811 
    812 (define_insn "atomic_sub<mode>"
    813   [(set (match_operand:SWI 0 "memory_operand" "+m")
    814 	(unspec_volatile:SWI
    815 	  [(minus:SWI (match_dup 0)
    816 		      (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    817 	   (match_operand:SI 2 "const_int_operand")]		;; model
    818 	  UNSPECV_LOCK))
    819    (clobber (reg:CC FLAGS_REG))]
    820   ""
    821 {
    822   if (incdec_operand (operands[1], <MODE>mode))
    823     {
    824       if (operands[1] == const1_rtx)
    825 	return "lock{%;} %K2dec{<imodesuffix>}\t%0";
    826       else
    827 	{
    828 	  gcc_assert (operands[1] == constm1_rtx);
    829 	  return "lock{%;} %K2inc{<imodesuffix>}\t%0";
    830 	}
    831     }
    832 
    833   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
    834     return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
    835 
    836   return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
    837 })
    838 
    839 (define_insn "atomic_<logic><mode>"
    840   [(set (match_operand:SWI 0 "memory_operand" "+m")
    841 	(unspec_volatile:SWI
    842 	  [(any_logic:SWI (match_dup 0)
    843 			  (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    844 	   (match_operand:SI 2 "const_int_operand")]		;; model
    845 	  UNSPECV_LOCK))
    846    (clobber (reg:CC FLAGS_REG))]
    847   ""
    848   "lock{%;} %K2<logic>{<imodesuffix>}\t{%1, %0|%0, %1}")
    849 
    850 (define_expand "atomic_bit_test_and_set<mode>"
    851   [(match_operand:SWI248 0 "register_operand")
    852    (match_operand:SWI248 1 "memory_operand")
    853    (match_operand:SWI248 2 "nonmemory_operand")
    854    (match_operand:SI 3 "const_int_operand") ;; model
    855    (match_operand:SI 4 "const_int_operand")]
    856   ""
    857 {
    858   emit_insn (gen_atomic_bit_test_and_set<mode>_1 (operands[1], operands[2],
    859 						  operands[3]));
    860   rtx tem = gen_reg_rtx (QImode);
    861   ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
    862   rtx result = convert_modes (<MODE>mode, QImode, tem, 1);
    863   if (operands[4] == const0_rtx)
    864     result = expand_simple_binop (<MODE>mode, ASHIFT, result,
    865 				  operands[2], operands[0], 0, OPTAB_WIDEN);
    866   if (result != operands[0])
    867     emit_move_insn (operands[0], result);
    868   DONE;
    869 })
    870 
    871 (define_insn "atomic_bit_test_and_set<mode>_1"
    872   [(set (reg:CCC FLAGS_REG)
    873 	(compare:CCC
    874 	  (unspec_volatile:SWI248
    875 	    [(match_operand:SWI248 0 "memory_operand" "+m")
    876 	     (match_operand:SI 2 "const_int_operand")]		;; model
    877 	    UNSPECV_XCHG)
    878 	  (const_int 0)))
    879    (set (zero_extract:SWI248 (match_dup 0)
    880 			     (const_int 1)
    881 			     (match_operand:SWI248 1 "nonmemory_operand" "rN"))
    882 	(const_int 1))]
    883   ""
    884   "lock{%;} %K2bts{<imodesuffix>}\t{%1, %0|%0, %1}")
    885 
    886 (define_expand "atomic_bit_test_and_complement<mode>"
    887   [(match_operand:SWI248 0 "register_operand")
    888    (match_operand:SWI248 1 "memory_operand")
    889    (match_operand:SWI248 2 "nonmemory_operand")
    890    (match_operand:SI 3 "const_int_operand") ;; model
    891    (match_operand:SI 4 "const_int_operand")]
    892   ""
    893 {
    894   emit_insn (gen_atomic_bit_test_and_complement<mode>_1 (operands[1],
    895 							 operands[2],
    896 							 operands[3]));
    897   rtx tem = gen_reg_rtx (QImode);
    898   ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
    899   rtx result = convert_modes (<MODE>mode, QImode, tem, 1);
    900   if (operands[4] == const0_rtx)
    901     result = expand_simple_binop (<MODE>mode, ASHIFT, result,
    902 				  operands[2], operands[0], 0, OPTAB_WIDEN);
    903   if (result != operands[0])
    904     emit_move_insn (operands[0], result);
    905   DONE;
    906 })
    907 
    908 (define_insn "atomic_bit_test_and_complement<mode>_1"
    909   [(set (reg:CCC FLAGS_REG)
    910 	(compare:CCC
    911 	  (unspec_volatile:SWI248
    912 	    [(match_operand:SWI248 0 "memory_operand" "+m")
    913 	     (match_operand:SI 2 "const_int_operand")]		;; model
    914 	    UNSPECV_XCHG)
    915 	  (const_int 0)))
    916    (set (zero_extract:SWI248 (match_dup 0)
    917 			     (const_int 1)
    918 			     (match_operand:SWI248 1 "nonmemory_operand" "rN"))
    919 	(not:SWI248 (zero_extract:SWI248 (match_dup 0)
    920 					 (const_int 1)
    921 					 (match_dup 1))))]
    922   ""
    923   "lock{%;} %K2btc{<imodesuffix>}\t{%1, %0|%0, %1}")
    924 
    925 (define_expand "atomic_bit_test_and_reset<mode>"
    926   [(match_operand:SWI248 0 "register_operand")
    927    (match_operand:SWI248 1 "memory_operand")
    928    (match_operand:SWI248 2 "nonmemory_operand")
    929    (match_operand:SI 3 "const_int_operand") ;; model
    930    (match_operand:SI 4 "const_int_operand")]
    931   ""
    932 {
    933   emit_insn (gen_atomic_bit_test_and_reset<mode>_1 (operands[1], operands[2],
    934 						    operands[3]));
    935   rtx tem = gen_reg_rtx (QImode);
    936   ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
    937   rtx result = convert_modes (<MODE>mode, QImode, tem, 1);
    938   if (operands[4] == const0_rtx)
    939     result = expand_simple_binop (<MODE>mode, ASHIFT, result,
    940 				  operands[2], operands[0], 0, OPTAB_WIDEN);
    941   if (result != operands[0])
    942     emit_move_insn (operands[0], result);
    943   DONE;
    944 })
    945 
    946 (define_insn "atomic_bit_test_and_reset<mode>_1"
    947   [(set (reg:CCC FLAGS_REG)
    948 	(compare:CCC
    949 	  (unspec_volatile:SWI248
    950 	    [(match_operand:SWI248 0 "memory_operand" "+m")
    951 	     (match_operand:SI 2 "const_int_operand")]		;; model
    952 	    UNSPECV_XCHG)
    953 	  (const_int 0)))
    954    (set (zero_extract:SWI248 (match_dup 0)
    955 			     (const_int 1)
    956 			     (match_operand:SWI248 1 "nonmemory_operand" "rN"))
    957 	(const_int 0))]
    958   ""
    959   "lock{%;} %K2btr{<imodesuffix>}\t{%1, %0|%0, %1}")
    960 
    961 (define_expand "atomic_<plusminus_mnemonic>_fetch_cmp_0<mode>"
    962   [(match_operand:QI 0 "register_operand")
    963    (plusminus:SWI (match_operand:SWI 1 "memory_operand")
    964 		  (match_operand:SWI 2 "nonmemory_operand"))
    965    (match_operand:SI 3 "const_int_operand") ;; model
    966    (match_operand:SI 4 "const_int_operand")]
    967   ""
    968 {
    969   if (INTVAL (operands[4]) == GT || INTVAL (operands[4]) == LE)
    970     FAIL;
    971   emit_insn (gen_atomic_<plusminus_mnemonic>_fetch_cmp_0<mode>_1 (operands[1],
    972 								  operands[2],
    973 								  operands[3]));
    974   ix86_expand_setcc (operands[0], (enum rtx_code) INTVAL (operands[4]),
    975 		     gen_rtx_REG (CCGOCmode, FLAGS_REG), const0_rtx);
    976   DONE;
    977 })
    978 
    979 (define_insn "atomic_add_fetch_cmp_0<mode>_1"
    980   [(set (reg:CCGOC FLAGS_REG)
    981 	(compare:CCGOC
    982 	  (plus:SWI
    983 	    (unspec_volatile:SWI
    984 	      [(match_operand:SWI 0 "memory_operand" "+m")
    985 	       (match_operand:SI 2 "const_int_operand")]		;; model
    986 	      UNSPECV_XCHG)
    987 	    (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    988 	  (const_int 0)))
    989    (set (match_dup 0)
    990 	(plus:SWI (match_dup 0) (match_dup 1)))]
    991   ""
    992 {
    993   if (incdec_operand (operands[1], <MODE>mode))
    994     {
    995       if (operands[1] == const1_rtx)
    996 	return "lock{%;} %K2inc{<imodesuffix>}\t%0";
    997       else
    998 	return "lock{%;} %K2dec{<imodesuffix>}\t%0";
    999     }
   1000 
   1001   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
   1002     return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
   1003 
   1004   return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
   1005 })
   1006 
   1007 (define_insn "atomic_sub_fetch_cmp_0<mode>_1"
   1008   [(set (reg:CCGOC FLAGS_REG)
   1009 	(compare:CCGOC
   1010 	  (minus:SWI
   1011 	    (unspec_volatile:SWI
   1012 	      [(match_operand:SWI 0 "memory_operand" "+m")
   1013 	       (match_operand:SI 2 "const_int_operand")]		;; model
   1014 	      UNSPECV_XCHG)
   1015 	    (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
   1016 	  (const_int 0)))
   1017    (set (match_dup 0)
   1018 	(minus:SWI (match_dup 0) (match_dup 1)))]
   1019   ""
   1020 {
   1021   if (incdec_operand (operands[1], <MODE>mode))
   1022     {
   1023       if (operands[1] != const1_rtx)
   1024 	return "lock{%;} %K2inc{<imodesuffix>}\t%0";
   1025       else
   1026 	return "lock{%;} %K2dec{<imodesuffix>}\t%0";
   1027     }
   1028 
   1029   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
   1030     return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
   1031 
   1032   return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
   1033 })
   1034 
   1035 (define_expand "atomic_<logic>_fetch_cmp_0<mode>"
   1036   [(match_operand:QI 0 "register_operand")
   1037    (any_logic:SWI (match_operand:SWI 1 "memory_operand")
   1038 		  (match_operand:SWI 2 "nonmemory_operand"))
   1039    (match_operand:SI 3 "const_int_operand") ;; model
   1040    (match_operand:SI 4 "const_int_operand")]
   1041   ""
   1042 {
   1043   emit_insn (gen_atomic_<logic>_fetch_cmp_0<mode>_1 (operands[1], operands[2],
   1044 						     operands[3]));
   1045   ix86_expand_setcc (operands[0], (enum rtx_code) INTVAL (operands[4]),
   1046 		     gen_rtx_REG (CCNOmode, FLAGS_REG), const0_rtx);
   1047   DONE;
   1048 })
   1049 
   1050 (define_insn "atomic_<logic>_fetch_cmp_0<mode>_1"
   1051   [(set (reg:CCNO FLAGS_REG)
   1052 	(compare:CCNO
   1053 	  (any_logic:SWI
   1054 	    (unspec_volatile:SWI
   1055 	      [(match_operand:SWI 0 "memory_operand" "+m")
   1056 	       (match_operand:SI 2 "const_int_operand")]		;; model
   1057 	      UNSPECV_XCHG)
   1058 	    (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
   1059 	  (const_int 0)))
   1060    (set (match_dup 0)
   1061 	(any_logic:SWI (match_dup 0) (match_dup 1)))]
   1062   ""
   1063   "lock{%;} %K2<logic>{<imodesuffix>}\t{%1, %0|%0, %1}")
   1064