Line data Source code
1 : /* Copyright The GNU Toolchain Authors
2 :
3 : This file is part of GCC.
4 :
5 : GCC is free software; you can redistribute it and/or modify it under
6 : the terms of the GNU General Public License as published by the Free
7 : Software Foundation; either version 3, or (at your option) any later
8 : version.
9 :
10 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : for more details.
14 :
15 : You should have received a copy of the GNU General Public License
16 : along with GCC; see the file COPYING3. If not see
17 : <http://www.gnu.org/licenses/>. */
18 :
19 : #include "config.h"
20 : #include "system.h"
21 : #include "coretypes.h"
22 : #include "backend.h"
23 : #include "tree.h"
24 : #include "gimple.h"
25 : #include "tree-pass.h"
26 : #include "ssa.h"
27 : #include "gimple-iterator.h"
28 : #include "tree-cfg.h"
29 : #include "cfgloop.h"
30 : #include "hierarchical_discriminator.h"
31 : #include "cfghooks.h"
32 : #include "diagnostic-core.h"
33 : #include "function.h"
34 : #include "rtl.h"
35 : #include "basic-block.h"
36 :
37 : /* Helper to update a location with new discriminator components. If
38 : multiplicity_factor is non-zero, multiply existing multiplicity.
39 : If copyid is non-zero, set it (otherwise preserve existing). */
40 :
41 : static location_t
42 11775973 : update_location_discriminator (location_t loc,
43 : unsigned int multiplicity_factor,
44 : unsigned int copyid)
45 : {
46 11775973 : if (loc == UNKNOWN_LOCATION)
47 : return loc;
48 :
49 11775973 : discriminator_components comp = get_discriminator_components_from_loc (loc);
50 :
51 : /* Multiply existing multiplicity if requested. */
52 11775973 : if (multiplicity_factor > 0)
53 : {
54 2 : unsigned int new_mult = (comp.multiplicity == 0)
55 611666 : ? multiplicity_factor
56 : : comp.multiplicity * multiplicity_factor;
57 611666 : if (new_mult > DISCR_MULTIPLICITY_MAX)
58 : new_mult = DISCR_MULTIPLICITY_MAX;
59 611666 : comp.multiplicity = new_mult;
60 : }
61 :
62 : /* Update copyid if requested. */
63 11775973 : if (copyid > 0)
64 11775973 : comp.copyid = copyid;
65 :
66 11775973 : return location_with_discriminator_components (loc, comp);
67 : }
68 :
69 : /* Assign discriminators to a statement
70 : Updates the multiplicity and/or copyid discriminator components for
71 : all statements in the given basic block, while preserving the base
72 : discriminator.
73 :
74 : If multiplicity_factor > 0, multiply existing multiplicity by this factor.
75 : If copyid > 0, set it to this value. */
76 :
77 : void
78 36228 : assign_discriminators_to_stmt (gimple* stmt,
79 : unsigned int multiplicity_factor,
80 : unsigned int copyid)
81 : {
82 36228 : location_t loc = gimple_location (stmt);
83 :
84 36228 : if (loc != UNKNOWN_LOCATION)
85 : {
86 36219 : location_t new_loc
87 36219 : = update_location_discriminator (loc,
88 : multiplicity_factor,
89 : copyid);
90 72438 : gimple_set_location (stmt, new_loc);
91 : }
92 36228 : }
93 :
94 :
95 : /* Assign discriminators to all statements in a basic block. This
96 : function updates the multiplicity and/or copyid discriminator components for
97 : all statements in the given basic block, while preserving the base
98 : discriminator.
99 :
100 : If multiplicity_factor > 0, multiply existing multiplicity by this factor.
101 : If copyid > 0, set it to this value. */
102 :
103 : void
104 4738302 : assign_discriminators_to_bb (basic_block bb,
105 : unsigned int multiplicity_factor,
106 : unsigned int copyid)
107 : {
108 4738302 : if (current_ir_type () != IR_GIMPLE)
109 : {
110 709066 : rtx_insn *insn;
111 5497256 : FOR_BB_INSNS (bb, insn)
112 : {
113 4788190 : if (!INSN_P (insn) || !INSN_HAS_LOCATION (insn))
114 1638929 : continue;
115 3149261 : location_t loc = INSN_LOCATION (insn);
116 6298522 : INSN_LOCATION (insn)
117 3149261 : = update_location_discriminator (loc, multiplicity_factor, copyid);
118 : }
119 709066 : return;
120 : }
121 :
122 4029236 : gimple_stmt_iterator gsi;
123 4029236 : gphi_iterator phi_gsi;
124 4029236 : edge e;
125 4029236 : edge_iterator ei;
126 :
127 : /* Update PHI statements. */
128 9402250 : for (phi_gsi = gsi_start_phis (bb); !gsi_end_p (phi_gsi);
129 5373014 : gsi_next (&phi_gsi))
130 : {
131 5373014 : gphi *phi = phi_gsi.phi ();
132 5373014 : location_t loc = gimple_location (phi);
133 :
134 5373014 : if (loc != UNKNOWN_LOCATION)
135 : {
136 0 : location_t new_loc
137 0 : = update_location_discriminator (loc,
138 : multiplicity_factor,
139 : copyid);
140 0 : gimple_set_location (phi, new_loc);
141 : }
142 : }
143 :
144 : /* Update regular statements. */
145 33234075 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
146 : {
147 25175603 : gimple *stmt = gsi_stmt (gsi);
148 :
149 25175603 : if (is_gimple_debug (stmt))
150 16172175 : continue;
151 :
152 9003428 : location_t loc = gimple_location (stmt);
153 9003428 : if (loc != UNKNOWN_LOCATION)
154 : {
155 8583309 : location_t new_loc
156 8583309 : = update_location_discriminator (loc,
157 : multiplicity_factor,
158 : copyid);
159 17166618 : gimple_set_location (stmt, new_loc);
160 : }
161 : }
162 :
163 : /* Update goto/edge locations. */
164 11351775 : FOR_EACH_EDGE (e, ei, bb->succs)
165 : {
166 7322539 : location_t loc = e->goto_locus;
167 7322539 : if (loc != UNKNOWN_LOCATION)
168 : {
169 7184 : location_t new_loc
170 7184 : = update_location_discriminator (loc,
171 : multiplicity_factor,
172 : copyid);
173 7184 : e->goto_locus = new_loc;
174 : }
175 : }
176 : }
177 :
178 : /* Assign discriminators to all basic blocks in a loop. This function is
179 : used by loop versioning passes to assign version IDs and vectorization
180 : factors to all statements in a loop version. */
181 :
182 : void
183 52597 : assign_discriminators_to_loop (class loop *loop,
184 : unsigned int multiplicity_factor,
185 : unsigned int copyid)
186 : {
187 52597 : basic_block *bbs;
188 52597 : unsigned int i;
189 :
190 : /* Get all basic blocks in the loop. */
191 52597 : bbs = get_loop_body (loop);
192 :
193 : /* Assign discriminators to all blocks in the loop. */
194 212510 : for (i = 0; i < loop->num_nodes; i++)
195 107316 : assign_discriminators_to_bb (bbs[i], multiplicity_factor, copyid);
196 :
197 52597 : free (bbs);
198 52597 : }
199 :
200 :
201 : /* Helper to update the copyid allocator map with a location's existing copyid.
202 : If the location has a non-zero copyid, record that we need to start
203 : allocating from copyid+1 for this location. */
204 :
205 : static void
206 93440873 : record_existing_copyid (location_t loc, struct function *fn)
207 : {
208 93440873 : if (loc == UNKNOWN_LOCATION)
209 93424527 : return;
210 :
211 68186283 : location_t pure_loc = get_pure_location (loc);
212 68186283 : unsigned int discr = get_discriminator_from_loc (loc);
213 68186283 : if (discr == 0)
214 : return;
215 :
216 : /* Extract copyid from discriminator. */
217 24585598 : unsigned int copyid = (discr >> DISCR_COPYID_SHIFT) & DISCR_COPYID_MASK;
218 24585598 : if (copyid == 0)
219 : return;
220 :
221 : /* Update max copyid for this location. */
222 16346 : unsigned int next_copyid = copyid + 1;
223 16346 : if (next_copyid > DISCR_COPYID_MAX)
224 0 : next_copyid = DISCR_COPYID_MAX;
225 :
226 16346 : unsigned int *existing = fn->copyid_alloc->location_map->get (pure_loc);
227 16346 : if (!existing || *existing <= copyid)
228 9260 : fn->copyid_alloc->location_map->put (pure_loc, next_copyid);
229 : }
230 :
231 : /* Initialize the per-function copyid allocator. Walks the function
232 : body to find existing max copyids per location. */
233 :
234 : static void
235 3160989 : init_copyid_allocator (struct function *fn)
236 : {
237 3160989 : if (!fn)
238 : return;
239 :
240 3160989 : if (fn->copyid_alloc && fn->copyid_alloc->initialized)
241 : return; /* Already initialized. */
242 :
243 388445 : if (!fn->copyid_alloc)
244 : {
245 388445 : fn->copyid_alloc = XNEW (struct copyid_allocator);
246 776890 : fn->copyid_alloc->location_map
247 388445 : = new hash_map<int_hash<location_t, UNKNOWN_LOCATION,
248 : UNKNOWN_LOCATION>, unsigned int>;
249 388445 : fn->copyid_alloc->initialized = false;
250 : }
251 :
252 : /* Only walk the body if not yet initialized. */
253 388445 : if (fn->copyid_alloc->initialized)
254 : return;
255 :
256 : /* Walk the function body to find existing max copyids per location.
257 : This ensures we don't reuse copyids that were allocated in previous
258 : passes, during LTO, or brought in by inlining. */
259 388445 : basic_block bb;
260 11319852 : FOR_EACH_BB_FN (bb, fn)
261 : {
262 10931407 : if (current_ir_type () == IR_GIMPLE)
263 : {
264 : /* Process PHI nodes. */
265 10253240 : gphi_iterator phi_gsi;
266 14191541 : for (phi_gsi = gsi_start_phis (bb); !gsi_end_p (phi_gsi);
267 3938301 : gsi_next (&phi_gsi))
268 3938301 : record_existing_copyid (gimple_location (phi_gsi.phi ()), fn);
269 :
270 : /* Process regular statements. */
271 10253240 : gimple_stmt_iterator gsi;
272 90989199 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
273 70482719 : record_existing_copyid (gimple_location (gsi_stmt (gsi)), fn);
274 :
275 : /* Process edge goto_locus locations. */
276 10253240 : edge e;
277 10253240 : edge_iterator ei;
278 25230925 : FOR_EACH_EDGE (e, ei, bb->succs)
279 14977685 : record_existing_copyid (e->goto_locus, fn);
280 : }
281 : else
282 : {
283 : /* For RTL mode. */
284 678167 : rtx_insn *insn;
285 6228132 : FOR_BB_INSNS (bb, insn)
286 : {
287 5549965 : if (INSN_P (insn))
288 4042168 : record_existing_copyid (INSN_LOCATION (insn), fn);
289 : }
290 : }
291 : }
292 :
293 388445 : fn->copyid_alloc->initialized = true;
294 : }
295 :
296 : /* Allocate a unique copy_id base for the given location.
297 : STRIDE indicates how many copy_ids to reserve (for unrolling N times,
298 : use stride=N). Returns the base copy_id. */
299 :
300 : unsigned int
301 3160989 : allocate_copyid_base (location_t loc, unsigned int stride)
302 : {
303 : /* Need current function context. */
304 3160989 : if (!cfun)
305 : return 1; /* No function context, return default. */
306 :
307 3160989 : init_copyid_allocator (cfun);
308 :
309 3160989 : loc = get_pure_location (loc);
310 :
311 : /* Cannot allocate copyid for unknown location. */
312 3160989 : if (loc == UNKNOWN_LOCATION)
313 : return 1; /* Return default base copyid. */
314 :
315 : /* Check if this location has been seen before. */
316 3160768 : unsigned int *existing = cfun->copyid_alloc->location_map->get (loc);
317 3160768 : if (existing)
318 : {
319 : /* Location already duplicated before. Allocate next copy_id for it. */
320 1889357 : unsigned int base = *existing;
321 1889357 : *existing += stride; /* Update for next duplication. */
322 :
323 : /* Clamp to maximum. */
324 1889357 : if (*existing > DISCR_COPYID_MAX)
325 0 : *existing = DISCR_COPYID_MAX;
326 : return base;
327 : }
328 : else
329 : {
330 : /* First duplication at this location in this function.
331 : Start at 1 (not 0, which means "no copyid"). */
332 1271411 : unsigned int base = 1;
333 1271411 : unsigned int next = base + stride;
334 1271411 : if (next > DISCR_COPYID_MAX)
335 0 : next = DISCR_COPYID_MAX;
336 : /* Record this location for future duplications. */
337 1271411 : cfun->copyid_alloc->location_map->put (loc, next);
338 :
339 1271411 : return base;
340 : }
341 : }
342 :
343 : /* Free the copy_id allocator for a function. Called when the function
344 : is being destroyed. */
345 :
346 : void
347 1742678 : free_copyid_allocator (struct function *fn)
348 : {
349 1742678 : if (fn && fn->copyid_alloc)
350 : {
351 683678 : delete fn->copyid_alloc->location_map;
352 341839 : XDELETE (fn->copyid_alloc);
353 341839 : fn->copyid_alloc = NULL;
354 : }
355 1742678 : }
|