Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/ia64/sync.md @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | b7f97abdc517 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 ;; GCC machine description for IA-64 synchronization instructions. | 1 ;; GCC machine description for IA-64 synchronization instructions. |
2 ;; Copyright (C) 2005, 2007, 2008, 2009, 2010 | 2 ;; Copyright (C) 2005-2017 Free Software Foundation, Inc. |
3 ;; Free Software Foundation, Inc. | |
4 ;; | 3 ;; |
5 ;; This file is part of GCC. | 4 ;; This file is part of GCC. |
6 ;; | 5 ;; |
7 ;; GCC is free software; you can redistribute it and/or modify | 6 ;; GCC is free software; you can redistribute it and/or modify |
8 ;; it under the terms of the GNU General Public License as published by | 7 ;; it under the terms of the GNU General Public License as published by |
16 ;; | 15 ;; |
17 ;; You should have received a copy of the GNU General Public License | 16 ;; You should have received a copy of the GNU General Public License |
18 ;; along with GCC; see the file COPYING3. If not see | 17 ;; along with GCC; see the file COPYING3. If not see |
19 ;; <http://www.gnu.org/licenses/>. | 18 ;; <http://www.gnu.org/licenses/>. |
20 | 19 |
20 ;; Conversion to C++11 memory model based on | |
21 ;; http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html | |
22 | |
21 (define_mode_iterator IMODE [QI HI SI DI]) | 23 (define_mode_iterator IMODE [QI HI SI DI]) |
22 (define_mode_iterator I124MODE [QI HI SI]) | 24 (define_mode_iterator I124MODE [QI HI SI]) |
23 (define_mode_iterator I48MODE [SI DI]) | 25 (define_mode_iterator I48MODE [SI DI]) |
24 (define_mode_attr modesuffix [(QI "1") (HI "2") (SI "4") (DI "8")]) | 26 (define_mode_attr modesuffix [(QI "1") (HI "2") (SI "4") (DI "8")]) |
25 | 27 |
26 (define_code_iterator FETCHOP [plus minus ior xor and]) | 28 (define_code_iterator FETCHOP [plus minus ior xor and]) |
27 (define_code_attr fetchop_name | 29 (define_code_attr fetchop_name |
28 [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")]) | 30 [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")]) |
31 | |
32 (define_expand "mem_thread_fence" | |
33 [(match_operand:SI 0 "const_int_operand" "")] ;; model | |
34 "" | |
35 { | |
36 if (is_mm_seq_cst (memmodel_from_int (INTVAL (operands[0])))) | |
37 emit_insn (gen_memory_barrier ()); | |
38 DONE; | |
39 }) | |
29 | 40 |
30 (define_expand "memory_barrier" | 41 (define_expand "memory_barrier" |
31 [(set (match_dup 0) | 42 [(set (match_dup 0) |
32 (unspec:BLK [(match_dup 0)] UNSPEC_MF))] | 43 (unspec:BLK [(match_dup 0)] UNSPEC_MF))] |
33 "" | 44 "" |
41 (unspec:BLK [(match_dup 0)] UNSPEC_MF))] | 52 (unspec:BLK [(match_dup 0)] UNSPEC_MF))] |
42 "" | 53 "" |
43 "mf" | 54 "mf" |
44 [(set_attr "itanium_class" "syst_m")]) | 55 [(set_attr "itanium_class" "syst_m")]) |
45 | 56 |
46 (define_insn "fetchadd_acq_<mode>" | 57 (define_expand "atomic_load<mode>" |
47 [(set (match_operand:I48MODE 0 "gr_register_operand" "=r") | 58 [(match_operand:IMODE 0 "gr_register_operand" "") ;; output |
48 (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S")) | 59 (match_operand:IMODE 1 "memory_operand" "") ;; memory |
49 (set (match_dup 1) | 60 (match_operand:SI 2 "const_int_operand" "")] ;; model |
50 (unspec:I48MODE [(match_dup 1) | 61 "" |
51 (match_operand:I48MODE 2 "fetchadd_operand" "n")] | 62 { |
52 UNSPEC_FETCHADD_ACQ))] | 63 enum memmodel model = memmodel_from_int (INTVAL (operands[2])); |
53 "" | 64 |
54 "fetchadd<modesuffix>.acq %0 = %1, %2" | 65 /* Unless the memory model is relaxed, we want to emit ld.acq, which |
55 [(set_attr "itanium_class" "sem")]) | 66 will happen automatically for volatile memories. */ |
56 | 67 gcc_assert (is_mm_relaxed (model) || MEM_VOLATILE_P (operands[1])); |
57 (define_expand "sync_<fetchop_name><mode>" | 68 emit_move_insn (operands[0], operands[1]); |
58 [(set (match_operand:IMODE 0 "memory_operand" "") | 69 DONE; |
59 (FETCHOP:IMODE (match_dup 0) | 70 }) |
60 (match_operand:IMODE 1 "general_operand" "")))] | 71 |
61 "" | 72 (define_expand "atomic_store<mode>" |
62 { | 73 [(match_operand:IMODE 0 "memory_operand" "") ;; memory |
63 ia64_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL); | 74 (match_operand:IMODE 1 "gr_reg_or_0_operand" "") ;; input |
64 DONE; | 75 (match_operand:SI 2 "const_int_operand" "")] ;; model |
65 }) | 76 "" |
66 | 77 { |
67 (define_expand "sync_nand<mode>" | 78 enum memmodel model = memmodel_from_int (INTVAL (operands[2])); |
68 [(set (match_operand:IMODE 0 "memory_operand" "") | 79 |
69 (not:IMODE | 80 /* Unless the memory model is relaxed, we want to emit st.rel, which |
70 (and:IMODE (match_dup 0) | 81 will happen automatically for volatile memories. */ |
71 (match_operand:IMODE 1 "general_operand" ""))))] | 82 gcc_assert (is_mm_relaxed (model) || MEM_VOLATILE_P (operands[0])); |
72 "" | 83 emit_move_insn (operands[0], operands[1]); |
73 { | 84 |
74 ia64_expand_atomic_op (NOT, operands[0], operands[1], NULL, NULL); | 85 /* Sequentially consistent stores need a subsequent MF. See |
75 DONE; | 86 http://www.decadent.org.uk/pipermail/cpp-threads/2008-December/001952.html |
76 }) | 87 for a discussion of why a MF is needed here, but not for atomic_load. */ |
77 | 88 if (is_mm_seq_cst (model)) |
78 (define_expand "sync_old_<fetchop_name><mode>" | 89 emit_insn (gen_memory_barrier ()); |
79 [(set (match_operand:IMODE 0 "gr_register_operand" "") | 90 DONE; |
80 (FETCHOP:IMODE | 91 }) |
81 (match_operand:IMODE 1 "memory_operand" "") | 92 |
82 (match_operand:IMODE 2 "general_operand" "")))] | 93 (define_expand "atomic_compare_and_swap<mode>" |
83 "" | 94 [(match_operand:DI 0 "gr_register_operand" "") ;; bool out |
84 { | 95 (match_operand:IMODE 1 "gr_register_operand" "") ;; val out |
85 ia64_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL); | 96 (match_operand:IMODE 2 "not_postinc_memory_operand" "") ;; memory |
86 DONE; | 97 (match_operand:IMODE 3 "gr_register_operand" "") ;; expected |
87 }) | 98 (match_operand:IMODE 4 "gr_reg_or_0_operand" "") ;; desired |
88 | 99 (match_operand:SI 5 "const_int_operand" "") ;; is_weak |
89 (define_expand "sync_old_nand<mode>" | 100 (match_operand:SI 6 "const_int_operand" "") ;; succ model |
90 [(set (match_operand:IMODE 0 "gr_register_operand" "") | 101 (match_operand:SI 7 "const_int_operand" "")] ;; fail model |
91 (not:IMODE | 102 "" |
92 (and:IMODE (match_operand:IMODE 1 "memory_operand" "") | 103 { |
93 (match_operand:IMODE 2 "general_operand" ""))))] | 104 /* No need to distinquish __sync from __atomic, so get base value. */ |
94 "" | 105 enum memmodel model = memmodel_base (INTVAL (operands[6])); |
95 { | |
96 ia64_expand_atomic_op (NOT, operands[1], operands[2], operands[0], NULL); | |
97 DONE; | |
98 }) | |
99 | |
100 (define_expand "sync_new_<fetchop_name><mode>" | |
101 [(set (match_operand:IMODE 0 "gr_register_operand" "") | |
102 (FETCHOP:IMODE | |
103 (match_operand:IMODE 1 "memory_operand" "") | |
104 (match_operand:IMODE 2 "general_operand" "")))] | |
105 "" | |
106 { | |
107 ia64_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0]); | |
108 DONE; | |
109 }) | |
110 | |
111 (define_expand "sync_new_nand<mode>" | |
112 [(set (match_operand:IMODE 0 "gr_register_operand" "") | |
113 (not:IMODE | |
114 (and:IMODE (match_operand:IMODE 1 "memory_operand" "") | |
115 (match_operand:IMODE 2 "general_operand" ""))))] | |
116 "" | |
117 { | |
118 ia64_expand_atomic_op (NOT, operands[1], operands[2], NULL, operands[0]); | |
119 DONE; | |
120 }) | |
121 | |
122 (define_expand "sync_compare_and_swap<mode>" | |
123 [(match_operand:IMODE 0 "gr_register_operand" "") | |
124 (match_operand:IMODE 1 "memory_operand" "") | |
125 (match_operand:IMODE 2 "gr_register_operand" "") | |
126 (match_operand:IMODE 3 "gr_register_operand" "")] | |
127 "" | |
128 { | |
129 rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM); | 106 rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM); |
130 rtx dst; | 107 rtx dval, eval; |
131 | 108 |
132 convert_move (ccv, operands[2], 1); | 109 eval = gen_reg_rtx (DImode); |
133 | 110 convert_move (eval, operands[3], 1); |
134 dst = operands[0]; | 111 emit_move_insn (ccv, eval); |
135 if (GET_MODE (dst) != DImode) | 112 |
136 dst = gen_reg_rtx (DImode); | 113 if (<MODE>mode == DImode) |
137 | 114 dval = operands[1]; |
138 emit_insn (gen_cmpxchg_rel_<mode> (dst, operands[1], ccv, operands[3])); | 115 else |
139 emit_insn (gen_memory_barrier ()); | 116 dval = gen_reg_rtx (DImode); |
140 | 117 |
141 if (dst != operands[0]) | 118 switch (model) |
142 emit_move_insn (operands[0], gen_lowpart (<MODE>mode, dst)); | 119 { |
143 DONE; | 120 case MEMMODEL_RELAXED: |
144 }) | 121 case MEMMODEL_ACQUIRE: |
145 | 122 case MEMMODEL_CONSUME: |
146 (define_insn "cmpxchg_rel_<mode>" | 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 } | |
136 | |
137 if (<MODE>mode != DImode) | |
138 emit_move_insn (operands[1], gen_lowpart (<MODE>mode, dval)); | |
139 | |
140 emit_insn (gen_cstoredi4 (operands[0], gen_rtx_EQ (DImode, dval, eval), | |
141 dval, eval)); | |
142 DONE; | |
143 }) | |
144 | |
145 (define_insn "cmpxchg_acq_<mode>" | |
147 [(set (match_operand:DI 0 "gr_register_operand" "=r") | 146 [(set (match_operand:DI 0 "gr_register_operand" "=r") |
148 (zero_extend:DI | 147 (zero_extend:DI |
149 (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S"))) | 148 (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S"))) |
150 (set (match_dup 1) | 149 (set (match_dup 1) |
151 (unspec:I124MODE | 150 (unspec:I124MODE |
152 [(match_dup 1) | 151 [(match_dup 1) |
153 (match_operand:DI 2 "ar_ccv_reg_operand" "") | 152 (match_operand:DI 2 "ar_ccv_reg_operand" "") |
154 (match_operand:I124MODE 3 "gr_reg_or_0_operand" "rO")] | 153 (match_operand:I124MODE 3 "gr_reg_or_0_operand" "rO")] |
155 UNSPEC_CMPXCHG_ACQ))] | 154 UNSPEC_CMPXCHG_ACQ))] |
156 "" | 155 "" |
156 "cmpxchg<modesuffix>.acq %0 = %1, %r3, %2" | |
157 [(set_attr "itanium_class" "sem")]) | |
158 | |
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 "" | |
157 "cmpxchg<modesuffix>.rel %0 = %1, %r3, %2" | 170 "cmpxchg<modesuffix>.rel %0 = %1, %r3, %2" |
158 [(set_attr "itanium_class" "sem")]) | 171 [(set_attr "itanium_class" "sem")]) |
159 | 172 |
160 (define_insn "cmpxchg_rel_di" | 173 (define_insn "cmpxchg_acq_di" |
161 [(set (match_operand:DI 0 "gr_register_operand" "=r") | 174 [(set (match_operand:DI 0 "gr_register_operand" "=r") |
162 (match_operand:DI 1 "not_postinc_memory_operand" "+S")) | 175 (match_operand:DI 1 "not_postinc_memory_operand" "+S")) |
163 (set (match_dup 1) | 176 (set (match_dup 1) |
164 (unspec:DI [(match_dup 1) | 177 (unspec:DI [(match_dup 1) |
165 (match_operand:DI 2 "ar_ccv_reg_operand" "") | 178 (match_operand:DI 2 "ar_ccv_reg_operand" "") |
166 (match_operand:DI 3 "gr_reg_or_0_operand" "rO")] | 179 (match_operand:DI 3 "gr_reg_or_0_operand" "rO")] |
167 UNSPEC_CMPXCHG_ACQ))] | 180 UNSPEC_CMPXCHG_ACQ))] |
168 "" | 181 "" |
182 "cmpxchg8.acq %0 = %1, %r3, %2" | |
183 [(set_attr "itanium_class" "sem")]) | |
184 | |
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 "" | |
169 "cmpxchg8.rel %0 = %1, %r3, %2" | 194 "cmpxchg8.rel %0 = %1, %r3, %2" |
170 [(set_attr "itanium_class" "sem")]) | 195 [(set_attr "itanium_class" "sem")]) |
171 | 196 |
172 (define_insn "sync_lock_test_and_set<mode>" | 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 "" | |
203 { | |
204 /* No need to distinquish __sync from __atomic, so get base value. */ | |
205 enum memmodel model = memmodel_base (INTVAL (operands[3])); | |
206 | |
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; | |
223 }) | |
224 | |
225 ;; Note that XCHG is always memory model acquire. | |
226 (define_insn "xchg_acq_<mode>" | |
173 [(set (match_operand:IMODE 0 "gr_register_operand" "=r") | 227 [(set (match_operand:IMODE 0 "gr_register_operand" "=r") |
174 (match_operand:IMODE 1 "not_postinc_memory_operand" "+S")) | 228 (match_operand:IMODE 1 "not_postinc_memory_operand" "+S")) |
175 (set (match_dup 1) | 229 (set (match_dup 1) |
176 (match_operand:IMODE 2 "gr_reg_or_0_operand" "rO"))] | 230 (match_operand:IMODE 2 "gr_reg_or_0_operand" "rO"))] |
177 "" | 231 "" |
178 "xchg<modesuffix> %0 = %1, %r2" | 232 "xchg<modesuffix> %0 = %1, %r2" |
179 [(set_attr "itanium_class" "sem")]) | 233 [(set_attr "itanium_class" "sem")]) |
180 | 234 |
181 (define_expand "sync_lock_release<mode>" | 235 (define_expand "atomic_<fetchop_name><mode>" |
182 [(set (match_operand:IMODE 0 "memory_operand" "") | 236 [(set (match_operand:IMODE 0 "memory_operand" "") |
183 (match_operand:IMODE 1 "gr_reg_or_0_operand" ""))] | 237 (FETCHOP:IMODE (match_dup 0) |
184 "" | 238 (match_operand:IMODE 1 "nonmemory_operand" ""))) |
185 { | 239 (use (match_operand:SI 2 "const_int_operand" ""))] |
186 gcc_assert (MEM_VOLATILE_P (operands[0])); | 240 "" |
187 }) | 241 { |
242 ia64_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL, | |
243 (enum memmodel) INTVAL (operands[2])); | |
244 DONE; | |
245 }) | |
246 | |
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 "" | |
254 { | |
255 ia64_expand_atomic_op (NOT, operands[0], operands[1], NULL, NULL, | |
256 (enum memmodel) INTVAL (operands[2])); | |
257 DONE; | |
258 }) | |
259 | |
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 "" | |
267 { | |
268 ia64_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL, | |
269 (enum memmodel) INTVAL (operands[3])); | |
270 DONE; | |
271 }) | |
272 | |
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 "" | |
280 { | |
281 ia64_expand_atomic_op (NOT, operands[1], operands[2], operands[0], NULL, | |
282 (enum memmodel) INTVAL (operands[3])); | |
283 DONE; | |
284 }) | |
285 | |
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 "" | |
293 { | |
294 ia64_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0], | |
295 (enum memmodel) INTVAL (operands[3])); | |
296 DONE; | |
297 }) | |
298 | |
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 "" | |
306 { | |
307 ia64_expand_atomic_op (NOT, operands[1], operands[2], NULL, operands[0], | |
308 (enum memmodel) INTVAL (operands[3])); | |
309 DONE; | |
310 }) | |
311 | |
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")]) | |
322 | |
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")]) |