[RS6000] TOC refs generated during reload
[official-gcc.git] / gcc / config / ia64 / sync.md
blob62335d76a212b89c3d0015e5526129d764ed712f
1 ;; GCC machine description for IA-64 synchronization instructions.
2 ;; Copyright (C) 2005-2016 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.
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 ;; Conversion to C++11 memory model based on
21 ;; http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
23 (define_mode_iterator IMODE [QI HI SI DI])
24 (define_mode_iterator I124MODE [QI HI SI])
25 (define_mode_iterator I48MODE [SI DI])
26 (define_mode_attr modesuffix [(QI "1") (HI "2") (SI "4") (DI "8")])
28 (define_code_iterator FETCHOP [plus minus ior xor and])
29 (define_code_attr fetchop_name
30   [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
32 (define_expand "mem_thread_fence"
33   [(match_operand:SI 0 "const_int_operand" "")]         ;; model
34   ""
36   if (is_mm_seq_cst (memmodel_from_int (INTVAL (operands[0]))))
37     emit_insn (gen_memory_barrier ());
38   DONE;
41 (define_expand "memory_barrier"
42   [(set (match_dup 0)
43         (unspec:BLK [(match_dup 0)] UNSPEC_MF))]
44   ""
46   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
47   MEM_VOLATILE_P (operands[0]) = 1;
50 (define_insn "*memory_barrier"
51   [(set (match_operand:BLK 0 "" "")
52         (unspec:BLK [(match_dup 0)] UNSPEC_MF))]
53   ""
54   "mf"
55   [(set_attr "itanium_class" "syst_m")])
57 (define_expand "atomic_load<mode>"
58   [(match_operand:IMODE 0 "gr_register_operand" "")             ;; output
59    (match_operand:IMODE 1 "memory_operand" "")                  ;; memory
60    (match_operand:SI 2 "const_int_operand" "")]                 ;; model
61   ""
63   enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
65   /* Unless the memory model is relaxed, we want to emit ld.acq, which
66      will happen automatically for volatile memories.  */
67   gcc_assert (is_mm_relaxed (model) || MEM_VOLATILE_P (operands[1]));
68   emit_move_insn (operands[0], operands[1]);
69   DONE;
72 (define_expand "atomic_store<mode>"
73   [(match_operand:IMODE 0 "memory_operand" "")                  ;; memory
74    (match_operand:IMODE 1 "gr_reg_or_0_operand" "")             ;; input
75    (match_operand:SI 2 "const_int_operand" "")]                 ;; model
76   ""
78   enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
80   /* Unless the memory model is relaxed, we want to emit st.rel, which
81      will happen automatically for volatile memories.  */
82   gcc_assert (is_mm_relaxed (model) || MEM_VOLATILE_P (operands[0]));
83   emit_move_insn (operands[0], operands[1]);
85   /* Sequentially consistent stores need a subsequent MF.  See
86      http://www.decadent.org.uk/pipermail/cpp-threads/2008-December/001952.html
87      for a discussion of why a MF is needed here, but not for atomic_load.  */
88   if (is_mm_seq_cst (model))
89     emit_insn (gen_memory_barrier ());
90   DONE;
93 (define_expand "atomic_compare_and_swap<mode>"
94   [(match_operand:DI 0 "gr_register_operand" "")                ;; bool out
95    (match_operand:IMODE 1 "gr_register_operand" "")             ;; val out
96    (match_operand:IMODE 2 "not_postinc_memory_operand" "")      ;; memory
97    (match_operand:IMODE 3 "gr_register_operand" "")             ;; expected
98    (match_operand:IMODE 4 "gr_reg_or_0_operand" "")             ;; desired
99    (match_operand:SI 5 "const_int_operand" "")                  ;; is_weak
100    (match_operand:SI 6 "const_int_operand" "")                  ;; succ model
101    (match_operand:SI 7 "const_int_operand" "")]                 ;; fail model
102   ""
104   /* No need to distinquish __sync from __atomic, so get base value.  */
105   enum memmodel model = memmodel_base (INTVAL (operands[6]));
106   rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
107   rtx dval, eval;
109   eval = gen_reg_rtx (DImode);
110   convert_move (eval, operands[3], 1);
111   emit_move_insn (ccv, eval);
113   if (<MODE>mode == DImode)
114     dval = operands[1];
115   else
116     dval = gen_reg_rtx (DImode);
118   switch (model)
119     {
120     case MEMMODEL_RELAXED:
121     case MEMMODEL_ACQUIRE:
122     case MEMMODEL_CONSUME:
123       emit_insn (gen_cmpxchg_acq_<mode> (dval, operands[2], ccv, operands[4]));
124       break;
125     case MEMMODEL_RELEASE:
126       emit_insn (gen_cmpxchg_rel_<mode> (dval, operands[2], ccv, operands[4]));
127       break;
128     case MEMMODEL_ACQ_REL:
129     case MEMMODEL_SEQ_CST:
130       emit_insn (gen_cmpxchg_rel_<mode> (dval, operands[2], ccv, operands[4]));
131       emit_insn (gen_memory_barrier ());
132       break;
133     default:
134       gcc_unreachable ();
135     }
137   if (<MODE>mode != DImode)
138     emit_move_insn (operands[1], gen_lowpart (<MODE>mode, dval));
140   emit_insn (gen_cstoredi4 (operands[0], gen_rtx_EQ (DImode, dval, eval),
141                             dval, eval));
142   DONE;
145 (define_insn "cmpxchg_acq_<mode>"
146   [(set (match_operand:DI 0 "gr_register_operand" "=r")
147         (zero_extend:DI
148           (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S")))
149    (set (match_dup 1)
150         (unspec:I124MODE
151           [(match_dup 1)
152            (match_operand:DI 2 "ar_ccv_reg_operand" "")
153            (match_operand:I124MODE 3 "gr_reg_or_0_operand" "rO")]
154           UNSPEC_CMPXCHG_ACQ))]
155   ""
156   "cmpxchg<modesuffix>.acq %0 = %1, %r3, %2"
157   [(set_attr "itanium_class" "sem")])
159 (define_insn "cmpxchg_rel_<mode>"
160   [(set (match_operand:DI 0 "gr_register_operand" "=r")
161         (zero_extend:DI
162           (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S")))
163    (set (match_dup 1)
164         (unspec:I124MODE
165           [(match_dup 1)
166            (match_operand:DI 2 "ar_ccv_reg_operand" "")
167            (match_operand:I124MODE 3 "gr_reg_or_0_operand" "rO")]
168           UNSPEC_CMPXCHG_REL))]
169   ""
170   "cmpxchg<modesuffix>.rel %0 = %1, %r3, %2"
171   [(set_attr "itanium_class" "sem")])
173 (define_insn "cmpxchg_acq_di"
174   [(set (match_operand:DI 0 "gr_register_operand" "=r")
175         (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
176    (set (match_dup 1)
177         (unspec:DI [(match_dup 1)
178                     (match_operand:DI 2 "ar_ccv_reg_operand" "")
179                     (match_operand:DI 3 "gr_reg_or_0_operand" "rO")]
180                    UNSPEC_CMPXCHG_ACQ))]
181   ""
182   "cmpxchg8.acq %0 = %1, %r3, %2"
183   [(set_attr "itanium_class" "sem")])
185 (define_insn "cmpxchg_rel_di"
186   [(set (match_operand:DI 0 "gr_register_operand" "=r")
187         (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
188    (set (match_dup 1)
189         (unspec:DI [(match_dup 1)
190                     (match_operand:DI 2 "ar_ccv_reg_operand" "")
191                     (match_operand:DI 3 "gr_reg_or_0_operand" "rO")]
192                    UNSPEC_CMPXCHG_REL))]
193   ""
194   "cmpxchg8.rel %0 = %1, %r3, %2"
195   [(set_attr "itanium_class" "sem")])
197 (define_expand "atomic_exchange<mode>"
198   [(match_operand:IMODE 0 "gr_register_operand" "")             ;; output
199    (match_operand:IMODE 1 "not_postinc_memory_operand" "")      ;; memory
200    (match_operand:IMODE 2 "gr_reg_or_0_operand" "")             ;; input
201    (match_operand:SI 3 "const_int_operand" "")]                 ;; succ model
202   ""
204   /* No need to distinquish __sync from __atomic, so get base value.  */
205   enum memmodel model = memmodel_base (INTVAL (operands[3]));
207   switch (model)
208     {
209     case MEMMODEL_RELAXED:
210     case MEMMODEL_ACQUIRE:
211     case MEMMODEL_CONSUME:
212       break;
213     case MEMMODEL_RELEASE:
214     case MEMMODEL_ACQ_REL:
215     case MEMMODEL_SEQ_CST:
216       emit_insn (gen_memory_barrier ());
217       break;
218     default:
219       gcc_unreachable ();
220     }
221   emit_insn (gen_xchg_acq_<mode> (operands[0], operands[1], operands[2]));
222   DONE;
225 ;; Note that XCHG is always memory model acquire.
226 (define_insn "xchg_acq_<mode>"
227   [(set (match_operand:IMODE 0 "gr_register_operand" "=r")
228         (match_operand:IMODE 1 "not_postinc_memory_operand" "+S"))
229    (set (match_dup 1)
230         (match_operand:IMODE 2 "gr_reg_or_0_operand" "rO"))]
231   ""
232   "xchg<modesuffix> %0 = %1, %r2"
233   [(set_attr "itanium_class" "sem")])
235 (define_expand "atomic_<fetchop_name><mode>"
236   [(set (match_operand:IMODE 0 "memory_operand" "")
237         (FETCHOP:IMODE (match_dup 0)
238           (match_operand:IMODE 1 "nonmemory_operand" "")))
239    (use (match_operand:SI 2 "const_int_operand" ""))]
240   ""
242   ia64_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL,
243                          (enum memmodel) INTVAL (operands[2]));
244   DONE;
247 (define_expand "atomic_nand<mode>"
248   [(set (match_operand:IMODE 0 "memory_operand" "")
249         (not:IMODE
250           (and:IMODE (match_dup 0)
251                      (match_operand:IMODE 1 "nonmemory_operand" ""))))
252    (use (match_operand:SI 2 "const_int_operand" ""))]
253   ""
255   ia64_expand_atomic_op (NOT, operands[0], operands[1], NULL, NULL,
256                          (enum memmodel) INTVAL (operands[2]));
257   DONE;
260 (define_expand "atomic_fetch_<fetchop_name><mode>"
261   [(set (match_operand:IMODE 0 "gr_register_operand" "")
262         (FETCHOP:IMODE 
263           (match_operand:IMODE 1 "memory_operand" "")
264           (match_operand:IMODE 2 "nonmemory_operand" "")))
265    (use (match_operand:SI 3 "const_int_operand" ""))]
266   ""
268   ia64_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL,
269                          (enum memmodel) INTVAL (operands[3]));
270   DONE;
273 (define_expand "atomic_fetch_nand<mode>"
274   [(set (match_operand:IMODE 0 "gr_register_operand" "")
275         (not:IMODE 
276           (and:IMODE (match_operand:IMODE 1 "memory_operand" "")
277                      (match_operand:IMODE 2 "nonmemory_operand" ""))))
278    (use (match_operand:SI 3 "const_int_operand" ""))]
279   ""
281   ia64_expand_atomic_op (NOT, operands[1], operands[2], operands[0], NULL,
282                          (enum memmodel) INTVAL (operands[3]));
283   DONE;
286 (define_expand "atomic_<fetchop_name>_fetch<mode>"
287   [(set (match_operand:IMODE 0 "gr_register_operand" "")
288         (FETCHOP:IMODE 
289           (match_operand:IMODE 1 "memory_operand" "")
290           (match_operand:IMODE 2 "nonmemory_operand" "")))
291    (use (match_operand:SI 3 "const_int_operand" ""))]
292   ""
294   ia64_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0],
295                          (enum memmodel) INTVAL (operands[3]));
296   DONE;
299 (define_expand "atomic_nand_fetch<mode>"
300   [(set (match_operand:IMODE 0 "gr_register_operand" "")
301         (not:IMODE 
302           (and:IMODE (match_operand:IMODE 1 "memory_operand" "")
303                      (match_operand:IMODE 2 "nonmemory_operand" ""))))
304    (use (match_operand:SI 3 "const_int_operand" ""))]
305   ""
307   ia64_expand_atomic_op (NOT, operands[1], operands[2], NULL, operands[0],
308                          (enum memmodel) INTVAL (operands[3]));
309   DONE;
312 (define_insn "fetchadd_acq_<mode>"
313   [(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
314         (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
315    (set (match_dup 1)
316         (unspec:I48MODE [(match_dup 1)
317                          (match_operand:I48MODE 2 "fetchadd_operand" "n")]
318                         UNSPEC_FETCHADD_ACQ))]
319   ""
320   "fetchadd<modesuffix>.acq %0 = %1, %2"
321   [(set_attr "itanium_class" "sem")])
323 (define_insn "fetchadd_rel_<mode>"
324   [(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
325         (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
326    (set (match_dup 1)
327         (unspec:I48MODE [(match_dup 1)
328                          (match_operand:I48MODE 2 "fetchadd_operand" "n")]
329                         UNSPEC_FETCHADD_REL))]
330   ""
331   "fetchadd<modesuffix>.rel %0 = %1, %2"
332   [(set_attr "itanium_class" "sem")])