]>
Commit | Line | Data |
---|---|---|
058e97ec | 1 | /* IRA conflict builder. |
8d9254fc | 2 | Copyright (C) 2006-2020 Free Software Foundation, Inc. |
058e97ec VM |
3 | Contributed by Vladimir Makarov <vmakarov@redhat.com>. |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 3, or (at your option) any later | |
10 | version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GCC; see the file COPYING3. If not see | |
19 | <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
c7131fb2 | 24 | #include "backend.h" |
957060b5 | 25 | #include "target.h" |
058e97ec | 26 | #include "rtl.h" |
957060b5 | 27 | #include "predict.h" |
4d0cdd0c | 28 | #include "memmodel.h" |
058e97ec | 29 | #include "tm_p.h" |
058e97ec | 30 | #include "insn-config.h" |
957060b5 AM |
31 | #include "regs.h" |
32 | #include "ira.h" | |
33 | #include "ira-int.h" | |
058e97ec | 34 | #include "sparseset.h" |
9c7c70ee | 35 | #include "addresses.h" |
058e97ec VM |
36 | |
37 | /* This file contains code responsible for allocno conflict creation, | |
38 | allocno copy creation and allocno info accumulation on upper level | |
39 | regions. */ | |
40 | ||
41 | /* ira_allocnos_num array of arrays of bits, recording whether two | |
42 | allocno's conflict (can't go in the same hardware register). | |
43 | ||
44 | Some arrays will be used as conflict bit vector of the | |
ac0ab4f7 | 45 | corresponding allocnos see function build_object_conflicts. */ |
058e97ec VM |
46 | static IRA_INT_TYPE **conflicts; |
47 | ||
a49ae217 | 48 | /* Macro to test a conflict of C1 and C2 in `conflicts'. */ |
ac0ab4f7 | 49 | #define OBJECTS_CONFLICT_P(C1, C2) \ |
a49ae217 BS |
50 | (OBJECT_MIN (C1) <= OBJECT_CONFLICT_ID (C2) \ |
51 | && OBJECT_CONFLICT_ID (C2) <= OBJECT_MAX (C1) \ | |
52 | && TEST_MINMAX_SET_BIT (conflicts[OBJECT_CONFLICT_ID (C1)], \ | |
53 | OBJECT_CONFLICT_ID (C2), \ | |
54 | OBJECT_MIN (C1), OBJECT_MAX (C1))) | |
058e97ec VM |
55 | |
56 | \f | |
ac0ab4f7 BS |
57 | /* Record a conflict between objects OBJ1 and OBJ2. If necessary, |
58 | canonicalize the conflict by recording it for lower-order subobjects | |
2b9c63a2 | 59 | of the corresponding allocnos. */ |
ac0ab4f7 BS |
60 | static void |
61 | record_object_conflict (ira_object_t obj1, ira_object_t obj2) | |
62 | { | |
63 | ira_allocno_t a1 = OBJECT_ALLOCNO (obj1); | |
64 | ira_allocno_t a2 = OBJECT_ALLOCNO (obj2); | |
65 | int w1 = OBJECT_SUBWORD (obj1); | |
66 | int w2 = OBJECT_SUBWORD (obj2); | |
67 | int id1, id2; | |
68 | ||
69 | /* Canonicalize the conflict. If two identically-numbered words | |
70 | conflict, always record this as a conflict between words 0. That | |
71 | is the only information we need, and it is easier to test for if | |
72 | it is collected in each allocno's lowest-order object. */ | |
73 | if (w1 == w2 && w1 > 0) | |
74 | { | |
75 | obj1 = ALLOCNO_OBJECT (a1, 0); | |
76 | obj2 = ALLOCNO_OBJECT (a2, 0); | |
77 | } | |
78 | id1 = OBJECT_CONFLICT_ID (obj1); | |
79 | id2 = OBJECT_CONFLICT_ID (obj2); | |
80 | ||
81 | SET_MINMAX_SET_BIT (conflicts[id1], id2, OBJECT_MIN (obj1), | |
82 | OBJECT_MAX (obj1)); | |
83 | SET_MINMAX_SET_BIT (conflicts[id2], id1, OBJECT_MIN (obj2), | |
84 | OBJECT_MAX (obj2)); | |
85 | } | |
86 | ||
311aab06 VM |
87 | /* Build allocno conflict table by processing allocno live ranges. |
88 | Return true if the table was built. The table is not built if it | |
89 | is too big. */ | |
90 | static bool | |
058e97ec VM |
91 | build_conflict_bit_table (void) |
92 | { | |
a49ae217 | 93 | int i; |
058e97ec | 94 | unsigned int j; |
1756cb66 | 95 | enum reg_class aclass; |
a49ae217 | 96 | int object_set_words, allocated_words_num, conflict_bit_vec_words_num; |
b14151b5 | 97 | live_range_t r; |
a49ae217 | 98 | ira_allocno_t allocno; |
058e97ec | 99 | ira_allocno_iterator ai; |
a49ae217 | 100 | sparseset objects_live; |
ac0ab4f7 BS |
101 | ira_object_t obj; |
102 | ira_allocno_object_iterator aoi; | |
058e97ec | 103 | |
311aab06 VM |
104 | allocated_words_num = 0; |
105 | FOR_EACH_ALLOCNO (allocno, ai) | |
ac0ab4f7 BS |
106 | FOR_EACH_ALLOCNO_OBJECT (allocno, obj, aoi) |
107 | { | |
108 | if (OBJECT_MAX (obj) < OBJECT_MIN (obj)) | |
311aab06 | 109 | continue; |
ac0ab4f7 BS |
110 | conflict_bit_vec_words_num |
111 | = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS) | |
112 | / IRA_INT_BITS); | |
113 | allocated_words_num += conflict_bit_vec_words_num; | |
a9243bfc | 114 | if ((uint64_t) allocated_words_num * sizeof (IRA_INT_TYPE) |
028d4092 | 115 | > (uint64_t) param_ira_max_conflict_table_size * 1024 * 1024) |
ac0ab4f7 BS |
116 | { |
117 | if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL) | |
118 | fprintf | |
119 | (ira_dump_file, | |
120 | "+++Conflict table will be too big(>%dMB) -- don't use it\n", | |
028d4092 | 121 | param_ira_max_conflict_table_size); |
ac0ab4f7 BS |
122 | return false; |
123 | } | |
124 | } | |
a49ae217 | 125 | |
058e97ec | 126 | conflicts = (IRA_INT_TYPE **) ira_allocate (sizeof (IRA_INT_TYPE *) |
a49ae217 | 127 | * ira_objects_num); |
058e97ec VM |
128 | allocated_words_num = 0; |
129 | FOR_EACH_ALLOCNO (allocno, ai) | |
ac0ab4f7 BS |
130 | FOR_EACH_ALLOCNO_OBJECT (allocno, obj, aoi) |
131 | { | |
132 | int id = OBJECT_CONFLICT_ID (obj); | |
133 | if (OBJECT_MAX (obj) < OBJECT_MIN (obj)) | |
134 | { | |
135 | conflicts[id] = NULL; | |
136 | continue; | |
137 | } | |
138 | conflict_bit_vec_words_num | |
139 | = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS) | |
140 | / IRA_INT_BITS); | |
141 | allocated_words_num += conflict_bit_vec_words_num; | |
142 | conflicts[id] | |
143 | = (IRA_INT_TYPE *) ira_allocate (sizeof (IRA_INT_TYPE) | |
144 | * conflict_bit_vec_words_num); | |
145 | memset (conflicts[id], 0, | |
146 | sizeof (IRA_INT_TYPE) * conflict_bit_vec_words_num); | |
147 | } | |
a49ae217 BS |
148 | |
149 | object_set_words = (ira_objects_num + IRA_INT_BITS - 1) / IRA_INT_BITS; | |
058e97ec VM |
150 | if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL) |
151 | fprintf | |
152 | (ira_dump_file, | |
153 | "+++Allocating %ld bytes for conflict table (uncompressed size %ld)\n", | |
154 | (long) allocated_words_num * sizeof (IRA_INT_TYPE), | |
a49ae217 BS |
155 | (long) object_set_words * ira_objects_num * sizeof (IRA_INT_TYPE)); |
156 | ||
157 | objects_live = sparseset_alloc (ira_objects_num); | |
058e97ec VM |
158 | for (i = 0; i < ira_max_point; i++) |
159 | { | |
160 | for (r = ira_start_point_ranges[i]; r != NULL; r = r->start_next) | |
161 | { | |
9140d27b BS |
162 | ira_object_t obj = r->object; |
163 | ira_allocno_t allocno = OBJECT_ALLOCNO (obj); | |
a49ae217 BS |
164 | int id = OBJECT_CONFLICT_ID (obj); |
165 | ||
ac0ab4f7 BS |
166 | gcc_assert (id < ira_objects_num); |
167 | ||
1756cb66 | 168 | aclass = ALLOCNO_CLASS (allocno); |
a49ae217 | 169 | EXECUTE_IF_SET_IN_SPARSESET (objects_live, j) |
058e97ec | 170 | { |
ac0ab4f7 BS |
171 | ira_object_t live_obj = ira_object_id_map[j]; |
172 | ira_allocno_t live_a = OBJECT_ALLOCNO (live_obj); | |
1756cb66 | 173 | enum reg_class live_aclass = ALLOCNO_CLASS (live_a); |
a49ae217 | 174 | |
1756cb66 | 175 | if (ira_reg_classes_intersect_p[aclass][live_aclass] |
058e97ec | 176 | /* Don't set up conflict for the allocno with itself. */ |
ac0ab4f7 | 177 | && live_a != allocno) |
058e97ec | 178 | { |
ac0ab4f7 | 179 | record_object_conflict (obj, live_obj); |
058e97ec VM |
180 | } |
181 | } | |
60408d8b | 182 | sparseset_set_bit (objects_live, id); |
058e97ec | 183 | } |
b8698a0f | 184 | |
058e97ec | 185 | for (r = ira_finish_point_ranges[i]; r != NULL; r = r->finish_next) |
ac0ab4f7 | 186 | sparseset_clear_bit (objects_live, OBJECT_CONFLICT_ID (r->object)); |
058e97ec | 187 | } |
a49ae217 | 188 | sparseset_free (objects_live); |
311aab06 | 189 | return true; |
058e97ec | 190 | } |
058e97ec | 191 | \f |
a49ae217 BS |
192 | /* Return true iff allocnos A1 and A2 cannot be allocated to the same |
193 | register due to conflicts. */ | |
194 | ||
195 | static bool | |
ac0ab4f7 | 196 | allocnos_conflict_for_copy_p (ira_allocno_t a1, ira_allocno_t a2) |
a49ae217 | 197 | { |
ac0ab4f7 BS |
198 | /* Due to the fact that we canonicalize conflicts (see |
199 | record_object_conflict), we only need to test for conflicts of | |
200 | the lowest order words. */ | |
201 | ira_object_t obj1 = ALLOCNO_OBJECT (a1, 0); | |
202 | ira_object_t obj2 = ALLOCNO_OBJECT (a2, 0); | |
1756cb66 | 203 | |
a49ae217 BS |
204 | return OBJECTS_CONFLICT_P (obj1, obj2); |
205 | } | |
058e97ec | 206 | |
a7f32992 VM |
207 | /* Check that X is REG or SUBREG of REG. */ |
208 | #define REG_SUBREG_P(x) \ | |
209 | (REG_P (x) || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x)))) | |
210 | ||
211 | /* Return X if X is a REG, otherwise it should be SUBREG of REG and | |
212 | the function returns the reg in this case. *OFFSET will be set to | |
213 | 0 in the first case or the regno offset in the first case. */ | |
214 | static rtx | |
215 | go_through_subreg (rtx x, int *offset) | |
216 | { | |
217 | rtx reg; | |
218 | ||
219 | *offset = 0; | |
220 | if (REG_P (x)) | |
221 | return x; | |
222 | ira_assert (GET_CODE (x) == SUBREG); | |
223 | reg = SUBREG_REG (x); | |
224 | ira_assert (REG_P (reg)); | |
225 | if (REGNO (reg) < FIRST_PSEUDO_REGISTER) | |
226 | *offset = subreg_regno_offset (REGNO (reg), GET_MODE (reg), | |
227 | SUBREG_BYTE (x), GET_MODE (x)); | |
91914e56 RS |
228 | else if (!can_div_trunc_p (SUBREG_BYTE (x), |
229 | REGMODE_NATURAL_SIZE (GET_MODE (x)), offset)) | |
230 | /* Checked by validate_subreg. We must know at compile time which | |
231 | inner hard registers are being accessed. */ | |
232 | gcc_unreachable (); | |
a7f32992 VM |
233 | return reg; |
234 | } | |
235 | ||
058e97ec VM |
236 | /* Process registers REG1 and REG2 in move INSN with execution |
237 | frequency FREQ. The function also processes the registers in a | |
238 | potential move insn (INSN == NULL in this case) with frequency | |
239 | FREQ. The function can modify hard register costs of the | |
240 | corresponding allocnos or create a copy involving the corresponding | |
241 | allocnos. The function does nothing if the both registers are hard | |
242 | registers. When nothing is changed, the function returns | |
243 | FALSE. */ | |
244 | static bool | |
548a6322 | 245 | process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p, |
070a1983 | 246 | rtx_insn *insn, int freq) |
058e97ec | 247 | { |
496071ca | 248 | int allocno_preferenced_hard_regno, cost, index, offset1, offset2; |
a7f32992 | 249 | bool only_regs_p; |
058e97ec | 250 | ira_allocno_t a; |
a8c44c52 | 251 | reg_class_t rclass, aclass; |
ef4bddc2 | 252 | machine_mode mode; |
058e97ec VM |
253 | ira_copy_t cp; |
254 | ||
a7f32992 VM |
255 | gcc_assert (REG_SUBREG_P (reg1) && REG_SUBREG_P (reg2)); |
256 | only_regs_p = REG_P (reg1) && REG_P (reg2); | |
257 | reg1 = go_through_subreg (reg1, &offset1); | |
258 | reg2 = go_through_subreg (reg2, &offset2); | |
496071ca VM |
259 | /* Set up hard regno preferenced by allocno. If allocno gets the |
260 | hard regno the copy (or potential move) insn will be removed. */ | |
058e97ec VM |
261 | if (HARD_REGISTER_P (reg1)) |
262 | { | |
263 | if (HARD_REGISTER_P (reg2)) | |
264 | return false; | |
496071ca | 265 | allocno_preferenced_hard_regno = REGNO (reg1) + offset1 - offset2; |
058e97ec VM |
266 | a = ira_curr_regno_allocno_map[REGNO (reg2)]; |
267 | } | |
268 | else if (HARD_REGISTER_P (reg2)) | |
269 | { | |
496071ca | 270 | allocno_preferenced_hard_regno = REGNO (reg2) + offset2 - offset1; |
058e97ec VM |
271 | a = ira_curr_regno_allocno_map[REGNO (reg1)]; |
272 | } | |
a49ae217 | 273 | else |
058e97ec | 274 | { |
a49ae217 BS |
275 | ira_allocno_t a1 = ira_curr_regno_allocno_map[REGNO (reg1)]; |
276 | ira_allocno_t a2 = ira_curr_regno_allocno_map[REGNO (reg2)]; | |
2608d841 | 277 | |
ac0ab4f7 | 278 | if (!allocnos_conflict_for_copy_p (a1, a2) && offset1 == offset2) |
a49ae217 BS |
279 | { |
280 | cp = ira_add_allocno_copy (a1, a2, freq, constraint_p, insn, | |
281 | ira_curr_loop_tree_node); | |
282 | bitmap_set_bit (ira_curr_loop_tree_node->local_copies, cp->num); | |
283 | return true; | |
284 | } | |
285 | else | |
286 | return false; | |
058e97ec | 287 | } |
a49ae217 | 288 | |
1756cb66 VM |
289 | if (! IN_RANGE (allocno_preferenced_hard_regno, |
290 | 0, FIRST_PSEUDO_REGISTER - 1)) | |
67914693 | 291 | /* Cannot be tied. */ |
496071ca VM |
292 | return false; |
293 | rclass = REGNO_REG_CLASS (allocno_preferenced_hard_regno); | |
058e97ec | 294 | mode = ALLOCNO_MODE (a); |
1756cb66 | 295 | aclass = ALLOCNO_CLASS (a); |
4cda38d5 | 296 | if (only_regs_p && insn != NULL_RTX |
a8c44c52 | 297 | && reg_class_size[rclass] <= ira_reg_class_max_nregs [rclass][mode]) |
058e97ec VM |
298 | /* It is already taken into account in ira-costs.c. */ |
299 | return false; | |
1756cb66 | 300 | index = ira_class_hard_reg_index[aclass][allocno_preferenced_hard_regno]; |
058e97ec | 301 | if (index < 0) |
67914693 | 302 | /* Cannot be tied. It is not in the allocno class. */ |
058e97ec | 303 | return false; |
1756cb66 | 304 | ira_init_register_move_cost_if_necessary (mode); |
058e97ec | 305 | if (HARD_REGISTER_P (reg1)) |
1756cb66 | 306 | cost = ira_register_move_cost[mode][aclass][rclass] * freq; |
058e97ec | 307 | else |
1756cb66 | 308 | cost = ira_register_move_cost[mode][rclass][aclass] * freq; |
029da7d4 | 309 | do |
cb1ca6ac VM |
310 | { |
311 | ira_allocate_and_set_costs | |
1756cb66 VM |
312 | (&ALLOCNO_HARD_REG_COSTS (a), aclass, |
313 | ALLOCNO_CLASS_COST (a)); | |
cb1ca6ac | 314 | ira_allocate_and_set_costs |
1756cb66 | 315 | (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), aclass, 0); |
cb1ca6ac VM |
316 | ALLOCNO_HARD_REG_COSTS (a)[index] -= cost; |
317 | ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost; | |
1756cb66 VM |
318 | if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a)) |
319 | ALLOCNO_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index]; | |
3b6d1699 | 320 | ira_add_allocno_pref (a, allocno_preferenced_hard_regno, freq); |
029da7d4 | 321 | a = ira_parent_or_cap_allocno (a); |
cb1ca6ac | 322 | } |
029da7d4 | 323 | while (a != NULL); |
058e97ec VM |
324 | return true; |
325 | } | |
326 | ||
9f635bd1 RS |
327 | /* Return true if output operand OUTPUT and input operand INPUT of |
328 | INSN can use the same register class for at least one alternative. | |
329 | INSN is already described in recog_data and recog_op_alt. */ | |
330 | static bool | |
331 | can_use_same_reg_p (rtx_insn *insn, int output, int input) | |
332 | { | |
333 | alternative_mask preferred = get_preferred_alternatives (insn); | |
334 | for (int nalt = 0; nalt < recog_data.n_alternatives; nalt++) | |
335 | { | |
336 | if (!TEST_BIT (preferred, nalt)) | |
337 | continue; | |
338 | ||
339 | const operand_alternative *op_alt | |
340 | = &recog_op_alt[nalt * recog_data.n_operands]; | |
341 | if (op_alt[input].matches == output) | |
342 | return true; | |
343 | ||
344 | if (ira_reg_class_intersect[op_alt[input].cl][op_alt[output].cl] | |
345 | != NO_REGS) | |
346 | return true; | |
347 | } | |
348 | return false; | |
349 | } | |
350 | ||
351 | /* Process all of the output registers of the current insn (INSN) which | |
352 | are not bound (BOUND_P) and the input register REG (its operand number | |
b09495c1 VM |
353 | OP_NUM) which dies in the insn as if there were a move insn between |
354 | them with frequency FREQ. */ | |
058e97ec | 355 | static void |
9f635bd1 RS |
356 | process_reg_shuffles (rtx_insn *insn, rtx reg, int op_num, int freq, |
357 | bool *bound_p) | |
058e97ec VM |
358 | { |
359 | int i; | |
360 | rtx another_reg; | |
361 | ||
a7f32992 | 362 | gcc_assert (REG_SUBREG_P (reg)); |
058e97ec VM |
363 | for (i = 0; i < recog_data.n_operands; i++) |
364 | { | |
365 | another_reg = recog_data.operand[i]; | |
b8698a0f | 366 | |
a7f32992 | 367 | if (!REG_SUBREG_P (another_reg) || op_num == i |
b09495c1 | 368 | || recog_data.operand_type[i] != OP_OUT |
9f635bd1 RS |
369 | || bound_p[i] |
370 | || (!can_use_same_reg_p (insn, i, op_num) | |
371 | && (recog_data.constraints[op_num][0] != '%' | |
372 | || !can_use_same_reg_p (insn, i, op_num + 1)) | |
373 | && (op_num == 0 | |
374 | || recog_data.constraints[op_num - 1][0] != '%' | |
375 | || !can_use_same_reg_p (insn, i, op_num - 1)))) | |
058e97ec | 376 | continue; |
b8698a0f | 377 | |
070a1983 | 378 | process_regs_for_copy (reg, another_reg, false, NULL, freq); |
058e97ec VM |
379 | } |
380 | } | |
381 | ||
382 | /* Process INSN and create allocno copies if necessary. For example, | |
383 | it might be because INSN is a pseudo-register move or INSN is two | |
384 | operand insn. */ | |
385 | static void | |
070a1983 | 386 | add_insn_allocno_copies (rtx_insn *insn) |
058e97ec | 387 | { |
56592e03 | 388 | rtx set, operand, dup; |
3b6d1699 VM |
389 | bool bound_p[MAX_RECOG_OPERANDS]; |
390 | int i, n, freq; | |
73bb8fe9 | 391 | alternative_mask alts; |
a49ae217 | 392 | |
058e97ec VM |
393 | freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)); |
394 | if (freq == 0) | |
395 | freq = 1; | |
396 | if ((set = single_set (insn)) != NULL_RTX | |
a7f32992 | 397 | && REG_SUBREG_P (SET_DEST (set)) && REG_SUBREG_P (SET_SRC (set)) |
058e97ec | 398 | && ! side_effects_p (set) |
a7f32992 VM |
399 | && find_reg_note (insn, REG_DEAD, |
400 | REG_P (SET_SRC (set)) | |
401 | ? SET_SRC (set) | |
402 | : SUBREG_REG (SET_SRC (set))) != NULL_RTX) | |
058e97ec | 403 | { |
3b6d1699 | 404 | process_regs_for_copy (SET_SRC (set), SET_DEST (set), |
1756cb66 | 405 | false, insn, freq); |
b09495c1 VM |
406 | return; |
407 | } | |
56592e03 VM |
408 | /* Fast check of possibility of constraint or shuffle copies. If |
409 | there are no dead registers, there will be no such copies. */ | |
410 | if (! find_reg_note (insn, REG_DEAD, NULL_RTX)) | |
b09495c1 | 411 | return; |
73bb8fe9 | 412 | alts = ira_setup_alts (insn); |
b09495c1 VM |
413 | for (i = 0; i < recog_data.n_operands; i++) |
414 | bound_p[i] = false; | |
415 | for (i = 0; i < recog_data.n_operands; i++) | |
416 | { | |
417 | operand = recog_data.operand[i]; | |
418 | if (! REG_SUBREG_P (operand)) | |
419 | continue; | |
3b6d1699 VM |
420 | if ((n = ira_get_dup_out_num (i, alts)) >= 0) |
421 | { | |
422 | bound_p[n] = true; | |
423 | dup = recog_data.operand[n]; | |
424 | if (REG_SUBREG_P (dup) | |
425 | && find_reg_note (insn, REG_DEAD, | |
426 | REG_P (operand) | |
427 | ? operand | |
428 | : SUBREG_REG (operand)) != NULL_RTX) | |
070a1983 | 429 | process_regs_for_copy (operand, dup, true, NULL, |
3b6d1699 VM |
430 | freq); |
431 | } | |
b09495c1 VM |
432 | } |
433 | for (i = 0; i < recog_data.n_operands; i++) | |
434 | { | |
435 | operand = recog_data.operand[i]; | |
436 | if (REG_SUBREG_P (operand) | |
437 | && find_reg_note (insn, REG_DEAD, | |
438 | REG_P (operand) | |
439 | ? operand : SUBREG_REG (operand)) != NULL_RTX) | |
440 | /* If an operand dies, prefer its hard register for the output | |
441 | operands by decreasing the hard register cost or creating | |
442 | the corresponding allocno copies. The cost will not | |
443 | correspond to a real move insn cost, so make the frequency | |
444 | smaller. */ | |
9f635bd1 RS |
445 | process_reg_shuffles (insn, operand, i, freq < 8 ? 1 : freq / 8, |
446 | bound_p); | |
058e97ec VM |
447 | } |
448 | } | |
449 | ||
450 | /* Add copies originated from BB given by LOOP_TREE_NODE. */ | |
451 | static void | |
452 | add_copies (ira_loop_tree_node_t loop_tree_node) | |
453 | { | |
454 | basic_block bb; | |
070a1983 | 455 | rtx_insn *insn; |
058e97ec VM |
456 | |
457 | bb = loop_tree_node->bb; | |
458 | if (bb == NULL) | |
459 | return; | |
460 | FOR_BB_INSNS (bb, insn) | |
b5b8b0ac | 461 | if (NONDEBUG_INSN_P (insn)) |
058e97ec VM |
462 | add_insn_allocno_copies (insn); |
463 | } | |
464 | ||
465 | /* Propagate copies the corresponding allocnos on upper loop tree | |
466 | level. */ | |
467 | static void | |
468 | propagate_copies (void) | |
469 | { | |
470 | ira_copy_t cp; | |
471 | ira_copy_iterator ci; | |
472 | ira_allocno_t a1, a2, parent_a1, parent_a2; | |
058e97ec VM |
473 | |
474 | FOR_EACH_COPY (cp, ci) | |
475 | { | |
476 | a1 = cp->first; | |
477 | a2 = cp->second; | |
478 | if (ALLOCNO_LOOP_TREE_NODE (a1) == ira_loop_tree_root) | |
479 | continue; | |
480 | ira_assert ((ALLOCNO_LOOP_TREE_NODE (a2) != ira_loop_tree_root)); | |
029da7d4 BS |
481 | parent_a1 = ira_parent_or_cap_allocno (a1); |
482 | parent_a2 = ira_parent_or_cap_allocno (a2); | |
058e97ec | 483 | ira_assert (parent_a1 != NULL && parent_a2 != NULL); |
ac0ab4f7 | 484 | if (! allocnos_conflict_for_copy_p (parent_a1, parent_a2)) |
548a6322 VM |
485 | ira_add_allocno_copy (parent_a1, parent_a2, cp->freq, |
486 | cp->constraint_p, cp->insn, cp->loop_tree_node); | |
058e97ec VM |
487 | } |
488 | } | |
489 | ||
058e97ec | 490 | /* Array used to collect all conflict allocnos for given allocno. */ |
a49ae217 | 491 | static ira_object_t *collected_conflict_objects; |
058e97ec VM |
492 | |
493 | /* Build conflict vectors or bit conflict vectors (whatever is more | |
ac0ab4f7 | 494 | profitable) for object OBJ from the conflict table. */ |
058e97ec | 495 | static void |
ac0ab4f7 | 496 | build_object_conflicts (ira_object_t obj) |
058e97ec VM |
497 | { |
498 | int i, px, parent_num; | |
a49ae217 | 499 | ira_allocno_t parent_a, another_parent_a; |
ac0ab4f7 BS |
500 | ira_object_t parent_obj; |
501 | ira_allocno_t a = OBJECT_ALLOCNO (obj); | |
502 | IRA_INT_TYPE *object_conflicts; | |
42ce1cc4 | 503 | minmax_set_iterator asi; |
5c82436e | 504 | int parent_min, parent_max ATTRIBUTE_UNUSED; |
058e97ec | 505 | |
ac0ab4f7 | 506 | object_conflicts = conflicts[OBJECT_CONFLICT_ID (obj)]; |
058e97ec | 507 | px = 0; |
ac0ab4f7 | 508 | FOR_EACH_BIT_IN_MINMAX_SET (object_conflicts, |
a49ae217 | 509 | OBJECT_MIN (obj), OBJECT_MAX (obj), i, asi) |
058e97ec | 510 | { |
a49ae217 BS |
511 | ira_object_t another_obj = ira_object_id_map[i]; |
512 | ira_allocno_t another_a = OBJECT_ALLOCNO (obj); | |
1756cb66 | 513 | |
7db7ed3c | 514 | ira_assert (ira_reg_classes_intersect_p |
1756cb66 | 515 | [ALLOCNO_CLASS (a)][ALLOCNO_CLASS (another_a)]); |
a49ae217 | 516 | collected_conflict_objects[px++] = another_obj; |
058e97ec | 517 | } |
a49ae217 | 518 | if (ira_conflict_vector_profitable_p (obj, px)) |
058e97ec | 519 | { |
ac0ab4f7 | 520 | ira_object_t *vec; |
a49ae217 BS |
521 | ira_allocate_conflict_vec (obj, px); |
522 | vec = OBJECT_CONFLICT_VEC (obj); | |
523 | memcpy (vec, collected_conflict_objects, sizeof (ira_object_t) * px); | |
058e97ec | 524 | vec[px] = NULL; |
a49ae217 | 525 | OBJECT_NUM_CONFLICTS (obj) = px; |
058e97ec VM |
526 | } |
527 | else | |
528 | { | |
ac0ab4f7 | 529 | int conflict_bit_vec_words_num; |
1756cb66 | 530 | |
ac0ab4f7 | 531 | OBJECT_CONFLICT_ARRAY (obj) = object_conflicts; |
a49ae217 | 532 | if (OBJECT_MAX (obj) < OBJECT_MIN (obj)) |
058e97ec VM |
533 | conflict_bit_vec_words_num = 0; |
534 | else | |
535 | conflict_bit_vec_words_num | |
a49ae217 | 536 | = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS) |
058e97ec | 537 | / IRA_INT_BITS); |
a49ae217 | 538 | OBJECT_CONFLICT_ARRAY_SIZE (obj) |
058e97ec VM |
539 | = conflict_bit_vec_words_num * sizeof (IRA_INT_TYPE); |
540 | } | |
ac0ab4f7 | 541 | |
029da7d4 BS |
542 | parent_a = ira_parent_or_cap_allocno (a); |
543 | if (parent_a == NULL) | |
058e97ec | 544 | return; |
1756cb66 | 545 | ira_assert (ALLOCNO_CLASS (a) == ALLOCNO_CLASS (parent_a)); |
ac0ab4f7 BS |
546 | ira_assert (ALLOCNO_NUM_OBJECTS (a) == ALLOCNO_NUM_OBJECTS (parent_a)); |
547 | parent_obj = ALLOCNO_OBJECT (parent_a, OBJECT_SUBWORD (obj)); | |
a49ae217 | 548 | parent_num = OBJECT_CONFLICT_ID (parent_obj); |
1756cb66 VM |
549 | parent_min = OBJECT_MIN (parent_obj); |
550 | parent_max = OBJECT_MAX (parent_obj); | |
ac0ab4f7 | 551 | FOR_EACH_BIT_IN_MINMAX_SET (object_conflicts, |
a49ae217 | 552 | OBJECT_MIN (obj), OBJECT_MAX (obj), i, asi) |
058e97ec | 553 | { |
a49ae217 BS |
554 | ira_object_t another_obj = ira_object_id_map[i]; |
555 | ira_allocno_t another_a = OBJECT_ALLOCNO (another_obj); | |
ac0ab4f7 | 556 | int another_word = OBJECT_SUBWORD (another_obj); |
a49ae217 | 557 | |
7db7ed3c | 558 | ira_assert (ira_reg_classes_intersect_p |
1756cb66 | 559 | [ALLOCNO_CLASS (a)][ALLOCNO_CLASS (another_a)]); |
ac0ab4f7 | 560 | |
029da7d4 BS |
561 | another_parent_a = ira_parent_or_cap_allocno (another_a); |
562 | if (another_parent_a == NULL) | |
058e97ec VM |
563 | continue; |
564 | ira_assert (ALLOCNO_NUM (another_parent_a) >= 0); | |
1756cb66 VM |
565 | ira_assert (ALLOCNO_CLASS (another_a) |
566 | == ALLOCNO_CLASS (another_parent_a)); | |
ac0ab4f7 BS |
567 | ira_assert (ALLOCNO_NUM_OBJECTS (another_a) |
568 | == ALLOCNO_NUM_OBJECTS (another_parent_a)); | |
42ce1cc4 | 569 | SET_MINMAX_SET_BIT (conflicts[parent_num], |
ac0ab4f7 | 570 | OBJECT_CONFLICT_ID (ALLOCNO_OBJECT (another_parent_a, |
1756cb66 VM |
571 | another_word)), |
572 | parent_min, parent_max); | |
058e97ec VM |
573 | } |
574 | } | |
575 | ||
576 | /* Build conflict vectors or bit conflict vectors (whatever is more | |
577 | profitable) of all allocnos from the conflict table. */ | |
578 | static void | |
579 | build_conflicts (void) | |
580 | { | |
581 | int i; | |
582 | ira_allocno_t a, cap; | |
583 | ||
a49ae217 BS |
584 | collected_conflict_objects |
585 | = (ira_object_t *) ira_allocate (sizeof (ira_object_t) | |
586 | * ira_objects_num); | |
058e97ec VM |
587 | for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--) |
588 | for (a = ira_regno_allocno_map[i]; | |
589 | a != NULL; | |
590 | a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) | |
591 | { | |
ac0ab4f7 BS |
592 | int j, nregs = ALLOCNO_NUM_OBJECTS (a); |
593 | for (j = 0; j < nregs; j++) | |
594 | { | |
595 | ira_object_t obj = ALLOCNO_OBJECT (a, j); | |
596 | build_object_conflicts (obj); | |
597 | for (cap = ALLOCNO_CAP (a); cap != NULL; cap = ALLOCNO_CAP (cap)) | |
598 | { | |
599 | ira_object_t cap_obj = ALLOCNO_OBJECT (cap, j); | |
600 | gcc_assert (ALLOCNO_NUM_OBJECTS (cap) == ALLOCNO_NUM_OBJECTS (a)); | |
601 | build_object_conflicts (cap_obj); | |
602 | } | |
603 | } | |
058e97ec | 604 | } |
a49ae217 | 605 | ira_free (collected_conflict_objects); |
058e97ec VM |
606 | } |
607 | ||
608 | \f | |
609 | ||
610 | /* Print hard reg set SET with TITLE to FILE. */ | |
611 | static void | |
612 | print_hard_reg_set (FILE *file, const char *title, HARD_REG_SET set) | |
613 | { | |
a5e3dd5d | 614 | int i, start, end; |
058e97ec | 615 | |
edb30094 | 616 | fputs (title, file); |
a5e3dd5d | 617 | for (start = end = -1, i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
058e97ec | 618 | { |
a5e3dd5d HPN |
619 | bool reg_included = TEST_HARD_REG_BIT (set, i); |
620 | ||
621 | if (reg_included) | |
058e97ec | 622 | { |
a5e3dd5d | 623 | if (start == -1) |
058e97ec | 624 | start = i; |
a5e3dd5d | 625 | end = i; |
058e97ec | 626 | } |
a5e3dd5d | 627 | if (start >= 0 && (!reg_included || i == FIRST_PSEUDO_REGISTER - 1)) |
058e97ec | 628 | { |
a5e3dd5d | 629 | if (start == end) |
058e97ec | 630 | fprintf (file, " %d", start); |
a5e3dd5d HPN |
631 | else if (start == end + 1) |
632 | fprintf (file, " %d %d", start, end); | |
058e97ec | 633 | else |
a5e3dd5d | 634 | fprintf (file, " %d-%d", start, end); |
058e97ec VM |
635 | start = -1; |
636 | } | |
637 | } | |
edb30094 | 638 | putc ('\n', file); |
058e97ec VM |
639 | } |
640 | ||
058e97ec | 641 | static void |
e4f36d31 | 642 | print_allocno_conflicts (FILE * file, bool reg_p, ira_allocno_t a) |
058e97ec | 643 | { |
058e97ec | 644 | HARD_REG_SET conflicting_hard_regs; |
e4f36d31 | 645 | basic_block bb; |
ac0ab4f7 | 646 | int n, i; |
058e97ec | 647 | |
e4f36d31 JL |
648 | if (reg_p) |
649 | fprintf (file, ";; r%d", ALLOCNO_REGNO (a)); | |
650 | else | |
058e97ec | 651 | { |
e4f36d31 JL |
652 | fprintf (file, ";; a%d(r%d,", ALLOCNO_NUM (a), ALLOCNO_REGNO (a)); |
653 | if ((bb = ALLOCNO_LOOP_TREE_NODE (a)->bb) != NULL) | |
654 | fprintf (file, "b%d", bb->index); | |
058e97ec | 655 | else |
2608d841 | 656 | fprintf (file, "l%d", ALLOCNO_LOOP_TREE_NODE (a)->loop_num); |
e4f36d31 JL |
657 | putc (')', file); |
658 | } | |
a49ae217 | 659 | |
e4f36d31 | 660 | fputs (" conflicts:", file); |
ac0ab4f7 BS |
661 | n = ALLOCNO_NUM_OBJECTS (a); |
662 | for (i = 0; i < n; i++) | |
663 | { | |
664 | ira_object_t obj = ALLOCNO_OBJECT (a, i); | |
665 | ira_object_t conflict_obj; | |
666 | ira_object_conflict_iterator oci; | |
667 | ||
668 | if (OBJECT_CONFLICT_ARRAY (obj) == NULL) | |
38de8b39 PB |
669 | { |
670 | fprintf (file, "\n;; total conflict hard regs:\n"); | |
671 | fprintf (file, ";; conflict hard regs:\n\n"); | |
672 | continue; | |
673 | } | |
674 | ||
ac0ab4f7 BS |
675 | if (n > 1) |
676 | fprintf (file, "\n;; subobject %d:", i); | |
677 | FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci) | |
678 | { | |
679 | ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj); | |
680 | if (reg_p) | |
681 | fprintf (file, " r%d,", ALLOCNO_REGNO (conflict_a)); | |
682 | else | |
683 | { | |
684 | fprintf (file, " a%d(r%d", ALLOCNO_NUM (conflict_a), | |
685 | ALLOCNO_REGNO (conflict_a)); | |
686 | if (ALLOCNO_NUM_OBJECTS (conflict_a) > 1) | |
687 | fprintf (file, ",w%d", OBJECT_SUBWORD (conflict_obj)); | |
688 | if ((bb = ALLOCNO_LOOP_TREE_NODE (conflict_a)->bb) != NULL) | |
689 | fprintf (file, ",b%d", bb->index); | |
690 | else | |
691 | fprintf (file, ",l%d", | |
2608d841 | 692 | ALLOCNO_LOOP_TREE_NODE (conflict_a)->loop_num); |
ac0ab4f7 BS |
693 | putc (')', file); |
694 | } | |
695 | } | |
d15e5131 RS |
696 | conflicting_hard_regs = (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) |
697 | & ~ira_no_alloc_regs | |
698 | & reg_class_contents[ALLOCNO_CLASS (a)]); | |
ac0ab4f7 BS |
699 | print_hard_reg_set (file, "\n;; total conflict hard regs:", |
700 | conflicting_hard_regs); | |
701 | ||
d15e5131 RS |
702 | conflicting_hard_regs = (OBJECT_CONFLICT_HARD_REGS (obj) |
703 | & ~ira_no_alloc_regs | |
704 | & reg_class_contents[ALLOCNO_CLASS (a)]); | |
ac0ab4f7 BS |
705 | print_hard_reg_set (file, ";; conflict hard regs:", |
706 | conflicting_hard_regs); | |
707 | putc ('\n', file); | |
708 | } | |
a49ae217 | 709 | |
058e97ec VM |
710 | } |
711 | ||
e4f36d31 JL |
712 | /* Print information about allocno or only regno (if REG_P) conflicts |
713 | to FILE. */ | |
714 | static void | |
715 | print_conflicts (FILE *file, bool reg_p) | |
716 | { | |
717 | ira_allocno_t a; | |
718 | ira_allocno_iterator ai; | |
719 | ||
720 | FOR_EACH_ALLOCNO (a, ai) | |
721 | print_allocno_conflicts (file, reg_p, a); | |
38de8b39 | 722 | putc ('\n', file); |
e4f36d31 JL |
723 | } |
724 | ||
058e97ec VM |
725 | /* Print information about allocno or only regno (if REG_P) conflicts |
726 | to stderr. */ | |
727 | void | |
728 | ira_debug_conflicts (bool reg_p) | |
729 | { | |
730 | print_conflicts (stderr, reg_p); | |
731 | } | |
732 | ||
733 | \f | |
734 | ||
735 | /* Entry function which builds allocno conflicts and allocno copies | |
736 | and accumulate some allocno info on upper level regions. */ | |
737 | void | |
738 | ira_build_conflicts (void) | |
739 | { | |
86fc3d06 | 740 | enum reg_class base; |
058e97ec VM |
741 | ira_allocno_t a; |
742 | ira_allocno_iterator ai; | |
7db7ed3c | 743 | HARD_REG_SET temp_hard_reg_set; |
058e97ec | 744 | |
311aab06 | 745 | if (ira_conflicts_p) |
058e97ec | 746 | { |
311aab06 VM |
747 | ira_conflicts_p = build_conflict_bit_table (); |
748 | if (ira_conflicts_p) | |
058e97ec | 749 | { |
a49ae217 BS |
750 | ira_object_t obj; |
751 | ira_object_iterator oi; | |
752 | ||
311aab06 | 753 | build_conflicts (); |
e6a7da82 | 754 | ira_traverse_loop_tree (true, ira_loop_tree_root, add_copies, NULL); |
311aab06 VM |
755 | /* We need finished conflict table for the subsequent call. */ |
756 | if (flag_ira_region == IRA_REGION_ALL | |
757 | || flag_ira_region == IRA_REGION_MIXED) | |
758 | propagate_copies (); | |
a49ae217 | 759 | |
311aab06 | 760 | /* Now we can free memory for the conflict table (see function |
ac0ab4f7 | 761 | build_object_conflicts for details). */ |
a49ae217 | 762 | FOR_EACH_OBJECT (obj, oi) |
311aab06 | 763 | { |
a49ae217 BS |
764 | if (OBJECT_CONFLICT_ARRAY (obj) != conflicts[OBJECT_CONFLICT_ID (obj)]) |
765 | ira_free (conflicts[OBJECT_CONFLICT_ID (obj)]); | |
311aab06 VM |
766 | } |
767 | ira_free (conflicts); | |
058e97ec | 768 | } |
058e97ec | 769 | } |
86fc3d06 UW |
770 | base = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, ADDRESS, SCRATCH); |
771 | if (! targetm.class_likely_spilled_p (base)) | |
7db7ed3c VM |
772 | CLEAR_HARD_REG_SET (temp_hard_reg_set); |
773 | else | |
6c476222 | 774 | temp_hard_reg_set = reg_class_contents[base] & ~ira_no_alloc_regs; |
058e97ec VM |
775 | FOR_EACH_ALLOCNO (a, ai) |
776 | { | |
ac0ab4f7 | 777 | int i, n = ALLOCNO_NUM_OBJECTS (a); |
1756cb66 | 778 | |
ac0ab4f7 | 779 | for (i = 0; i < n; i++) |
058e97ec | 780 | { |
ac0ab4f7 | 781 | ira_object_t obj = ALLOCNO_OBJECT (a, i); |
e6d46b5a | 782 | rtx allocno_reg = regno_reg_rtx [ALLOCNO_REGNO (a)]; |
ac0ab4f7 | 783 | |
6c476222 RS |
784 | /* For debugging purposes don't put user defined variables in |
785 | callee-clobbered registers. However, do allow parameters | |
786 | in callee-clobbered registers to improve debugging. This | |
787 | is a bit of a fragile hack. */ | |
788 | if (optimize == 0 | |
789 | && REG_USERVAR_P (allocno_reg) | |
790 | && ! reg_is_parm_p (allocno_reg)) | |
ac0ab4f7 | 791 | { |
6c476222 RS |
792 | HARD_REG_SET new_conflict_regs = crtl->abi->full_reg_clobbers (); |
793 | OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) |= new_conflict_regs; | |
794 | OBJECT_CONFLICT_HARD_REGS (obj) |= new_conflict_regs; | |
ac0ab4f7 | 795 | } |
6c476222 RS |
796 | |
797 | if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0) | |
ac0ab4f7 | 798 | { |
6c476222 RS |
799 | HARD_REG_SET new_conflict_regs = ira_need_caller_save_regs (a); |
800 | if (flag_caller_saves) | |
801 | new_conflict_regs &= (~savable_regs | temp_hard_reg_set); | |
802 | OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) |= new_conflict_regs; | |
803 | OBJECT_CONFLICT_HARD_REGS (obj) |= new_conflict_regs; | |
ac0ab4f7 | 804 | } |
0644953e | 805 | |
d1bb282e DS |
806 | /* Now we deal with paradoxical subreg cases where certain registers |
807 | cannot be accessed in the widest mode. */ | |
ef4bddc2 RS |
808 | machine_mode outer_mode = ALLOCNO_WMODE (a); |
809 | machine_mode inner_mode = ALLOCNO_MODE (a); | |
03a95621 | 810 | if (paradoxical_subreg_p (outer_mode, inner_mode)) |
d1bb282e DS |
811 | { |
812 | enum reg_class aclass = ALLOCNO_CLASS (a); | |
813 | for (int j = ira_class_hard_regs_num[aclass] - 1; j >= 0; --j) | |
814 | { | |
815 | int inner_regno = ira_class_hard_regs[aclass][j]; | |
816 | int outer_regno = simplify_subreg_regno (inner_regno, | |
817 | inner_mode, 0, | |
818 | outer_mode); | |
819 | if (outer_regno < 0 | |
820 | || !in_hard_reg_set_p (reg_class_contents[aclass], | |
821 | outer_mode, outer_regno)) | |
31b61548 VM |
822 | { |
823 | SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), | |
824 | inner_regno); | |
825 | SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), | |
826 | inner_regno); | |
827 | } | |
d1bb282e DS |
828 | } |
829 | } | |
058e97ec VM |
830 | } |
831 | } | |
311aab06 VM |
832 | if (optimize && ira_conflicts_p |
833 | && internal_flag_ira_verbose > 2 && ira_dump_file != NULL) | |
058e97ec VM |
834 | print_conflicts (ira_dump_file, false); |
835 | } |