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 3475088 : update_location_discriminator (location_t loc,
43 : unsigned int multiplicity_factor,
44 : unsigned int copyid)
45 : {
46 3475088 : if (loc == UNKNOWN_LOCATION)
47 : return loc;
48 :
49 3475088 : discriminator_components comp = get_discriminator_components_from_loc (loc);
50 :
51 : /* Multiply existing multiplicity if requested. */
52 3475088 : if (multiplicity_factor > 0)
53 : {
54 2 : unsigned int new_mult = (comp.multiplicity == 0)
55 590375 : ? multiplicity_factor
56 : : comp.multiplicity * multiplicity_factor;
57 590375 : if (new_mult > DISCR_MULTIPLICITY_MAX)
58 : new_mult = DISCR_MULTIPLICITY_MAX;
59 590375 : comp.multiplicity = new_mult;
60 : }
61 :
62 : /* Update copyid if requested. */
63 3475088 : if (copyid > 0)
64 3475088 : comp.copyid = copyid;
65 :
66 3475088 : 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 0 : assign_discriminators_to_stmt (gimple* stmt,
79 : unsigned int multiplicity_factor,
80 : unsigned int copyid)
81 : {
82 0 : location_t loc = gimple_location (stmt);
83 :
84 0 : if (loc != UNKNOWN_LOCATION)
85 : {
86 0 : location_t new_loc
87 0 : = update_location_discriminator (loc,
88 : multiplicity_factor,
89 : copyid);
90 0 : gimple_set_location (stmt, new_loc);
91 : }
92 0 : }
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 1015021 : assign_discriminators_to_bb (basic_block bb,
105 : unsigned int multiplicity_factor,
106 : unsigned int copyid)
107 : {
108 1015021 : gimple_stmt_iterator gsi;
109 1015021 : gphi_iterator phi_gsi;
110 1015021 : edge e;
111 1015021 : edge_iterator ei;
112 :
113 : /* Update PHI statements. */
114 2027667 : for (phi_gsi = gsi_start_phis (bb); !gsi_end_p (phi_gsi);
115 1012646 : gsi_next (&phi_gsi))
116 : {
117 1012646 : gphi *phi = phi_gsi.phi ();
118 1012646 : location_t loc = gimple_location (phi);
119 :
120 1012646 : if (loc != UNKNOWN_LOCATION)
121 : {
122 0 : location_t new_loc
123 0 : = update_location_discriminator (loc,
124 : multiplicity_factor,
125 : copyid);
126 0 : gimple_set_location (phi, new_loc);
127 : }
128 : }
129 :
130 : /* Update regular statements. */
131 6316023 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
132 : {
133 4285981 : gimple *stmt = gsi_stmt (gsi);
134 :
135 4285981 : if (is_gimple_debug (stmt))
136 651225 : continue;
137 :
138 3634756 : location_t loc = gimple_location (stmt);
139 3634756 : if (loc != UNKNOWN_LOCATION)
140 : {
141 3467049 : location_t new_loc
142 3467049 : = update_location_discriminator (loc,
143 : multiplicity_factor,
144 : copyid);
145 6934098 : gimple_set_location (stmt, new_loc);
146 : }
147 : }
148 :
149 : /* Update goto/edge locations. */
150 2600851 : FOR_EACH_EDGE (e, ei, bb->succs)
151 : {
152 1585830 : location_t loc = e->goto_locus;
153 1585830 : if (loc != UNKNOWN_LOCATION)
154 : {
155 8039 : location_t new_loc
156 8039 : = update_location_discriminator (loc,
157 : multiplicity_factor,
158 : copyid);
159 8039 : e->goto_locus = new_loc;
160 : }
161 : }
162 1015021 : }
163 :
164 : /* Assign discriminators to all basic blocks in a loop. This function is
165 : used by loop versioning passes to assign version IDs and vectorization
166 : factors to all statements in a loop version. */
167 :
168 : void
169 77920 : assign_discriminators_to_loop (class loop *loop,
170 : unsigned int multiplicity_factor,
171 : unsigned int copyid)
172 : {
173 77920 : basic_block *bbs;
174 77920 : unsigned int i;
175 :
176 : /* Get all basic blocks in the loop. */
177 77920 : bbs = get_loop_body (loop);
178 :
179 : /* Assign discriminators to all blocks in the loop. */
180 325048 : for (i = 0; i < loop->num_nodes; i++)
181 169208 : assign_discriminators_to_bb (bbs[i], multiplicity_factor, copyid);
182 :
183 77920 : free (bbs);
184 77920 : }
185 :
186 :
187 : /* Helper to update the copyid allocator map with a location's existing copyid.
188 : If the location has a non-zero copyid, record that we need to start
189 : allocating from copyid+1 for this location. */
190 :
191 : static void
192 23238885 : record_existing_copyid (location_t loc, struct function *fn)
193 : {
194 23238885 : if (loc == UNKNOWN_LOCATION)
195 23238885 : return;
196 :
197 16944474 : location_t pure_loc = get_pure_location (loc);
198 16944474 : unsigned int discr = get_discriminator_from_loc (loc);
199 16944474 : if (discr == 0)
200 : return;
201 :
202 : /* Extract copyid from discriminator. */
203 6482537 : unsigned int copyid = (discr >> DISCR_COPYID_SHIFT) & DISCR_COPYID_MASK;
204 6482537 : if (copyid == 0)
205 : return;
206 :
207 : /* Update max copyid for this location. */
208 0 : unsigned int next_copyid = copyid + 1;
209 0 : if (next_copyid > DISCR_COPYID_MAX)
210 0 : next_copyid = DISCR_COPYID_MAX;
211 :
212 0 : unsigned int *existing = fn->copyid_alloc->location_map->get (pure_loc);
213 0 : if (!existing || *existing <= copyid)
214 0 : fn->copyid_alloc->location_map->put (pure_loc, next_copyid);
215 : }
216 :
217 : /* Initialize the per-function copyid allocator. Walks the function
218 : body to find existing max copyids per location. */
219 :
220 : static void
221 324895 : init_copyid_allocator (struct function *fn)
222 : {
223 324895 : if (!fn)
224 : return;
225 :
226 324895 : if (fn->copyid_alloc && fn->copyid_alloc->initialized)
227 : return; /* Already initialized. */
228 :
229 71065 : if (!fn->copyid_alloc)
230 : {
231 71065 : fn->copyid_alloc = XNEW (struct copyid_allocator);
232 142130 : fn->copyid_alloc->location_map
233 71065 : = new hash_map<int_hash<location_t, UNKNOWN_LOCATION,
234 : UNKNOWN_LOCATION>, unsigned int>;
235 71065 : fn->copyid_alloc->initialized = false;
236 : }
237 :
238 : /* Only walk the body if not yet initialized. */
239 71065 : if (fn->copyid_alloc->initialized)
240 : return;
241 :
242 : /* Walk the function body to find existing max copyids per location.
243 : This ensures we don't reuse copyids that were allocated in previous
244 : passes, during LTO, or brought in by inlining. */
245 71065 : basic_block bb;
246 2876799 : FOR_EACH_BB_FN (bb, fn)
247 : {
248 2805734 : if (current_ir_type () == IR_GIMPLE)
249 : {
250 : /* Process PHI nodes. */
251 2166072 : gphi_iterator phi_gsi;
252 3545979 : for (phi_gsi = gsi_start_phis (bb); !gsi_end_p (phi_gsi);
253 1379907 : gsi_next (&phi_gsi))
254 1379907 : record_existing_copyid (gimple_location (phi_gsi.phi ()), fn);
255 :
256 : /* Process regular statements. */
257 2166072 : gimple_stmt_iterator gsi;
258 18352987 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
259 14020843 : record_existing_copyid (gimple_location (gsi_stmt (gsi)), fn);
260 :
261 : /* Process edge goto_locus locations. */
262 2166072 : edge e;
263 2166072 : edge_iterator ei;
264 5142724 : FOR_EACH_EDGE (e, ei, bb->succs)
265 2976652 : record_existing_copyid (e->goto_locus, fn);
266 : }
267 : else
268 : {
269 : /* For RTL mode. */
270 639662 : rtx_insn *insn;
271 6528384 : FOR_BB_INSNS (bb, insn)
272 : {
273 5888722 : if (INSN_P (insn))
274 4861483 : record_existing_copyid (INSN_LOCATION (insn), fn);
275 : }
276 : }
277 : }
278 :
279 71065 : fn->copyid_alloc->initialized = true;
280 : }
281 :
282 : /* Allocate a unique copy_id base for the given location.
283 : STRIDE indicates how many copy_ids to reserve (for unrolling N times,
284 : use stride=N). Returns the base copy_id. */
285 :
286 : unsigned int
287 324895 : allocate_copyid_base (location_t loc, unsigned int stride)
288 : {
289 : /* Need current function context. */
290 324895 : if (!cfun)
291 : return 1; /* No function context, return default. */
292 :
293 324895 : init_copyid_allocator (cfun);
294 :
295 324895 : loc = get_pure_location (loc);
296 :
297 : /* Cannot allocate copyid for unknown location. */
298 324895 : if (loc == UNKNOWN_LOCATION)
299 : return 1; /* Return default base copyid. */
300 :
301 : /* Check if this location has been seen before. */
302 324872 : unsigned int *existing = cfun->copyid_alloc->location_map->get (loc);
303 324872 : if (existing)
304 : {
305 : /* Location already duplicated before. Allocate next copy_id for it. */
306 174659 : unsigned int base = *existing;
307 174659 : *existing += stride; /* Update for next duplication. */
308 :
309 : /* Clamp to maximum. */
310 174659 : if (*existing > DISCR_COPYID_MAX)
311 0 : *existing = DISCR_COPYID_MAX;
312 174659 : return base;
313 : }
314 : else
315 : {
316 : /* First duplication at this location in this function.
317 : Start at 1 (not 0, which means "no copyid"). */
318 150213 : unsigned int base = 1;
319 150213 : unsigned int next = base + stride;
320 150213 : if (next > DISCR_COPYID_MAX)
321 0 : next = DISCR_COPYID_MAX;
322 : /* Record this location for future duplications. */
323 150213 : cfun->copyid_alloc->location_map->put (loc, next);
324 :
325 150213 : return base;
326 : }
327 : }
328 :
329 : /* Free the copy_id allocator for a function. Called when the function
330 : is being destroyed. */
331 :
332 : void
333 0 : free_copyid_allocator (struct function *fn)
334 : {
335 0 : if (fn && fn->copyid_alloc)
336 : {
337 0 : delete fn->copyid_alloc->location_map;
338 0 : XDELETE (fn->copyid_alloc);
339 0 : fn->copyid_alloc = NULL;
340 : }
341 0 : }
|