Branch data Line data Source code
1 : : /* Routines for reading GIMPLE from a file stream.
2 : :
3 : : Copyright (C) 2011-2025 Free Software Foundation, Inc.
4 : : Contributed by Diego Novillo <dnovillo@google.com>
5 : :
6 : : This file is part of GCC.
7 : :
8 : : GCC is free software; you can redistribute it and/or modify it under
9 : : the terms of the GNU General Public License as published by the Free
10 : : Software Foundation; either version 3, or (at your option) any later
11 : : version.
12 : :
13 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : : for more details.
17 : :
18 : : You should have received a copy of the GNU General Public License
19 : : along with GCC; see the file COPYING3. If not see
20 : : <http://www.gnu.org/licenses/>. */
21 : :
22 : : #include "config.h"
23 : : #include "system.h"
24 : : #include "coretypes.h"
25 : : #include "backend.h"
26 : : #include "tree.h"
27 : : #include "gimple.h"
28 : : #include "ssa.h"
29 : : #include "gimple-streamer.h"
30 : : #include "tree-eh.h"
31 : : #include "gimple-iterator.h"
32 : : #include "cgraph.h"
33 : : #include "value-prof.h"
34 : :
35 : : /* Read a PHI function for basic block BB in function FN. DATA_IN is
36 : : the file being read. IB is the input block to use for reading. */
37 : :
38 : : static gphi *
39 : 68559 : input_phi (class lto_input_block *ib, basic_block bb, class data_in *data_in,
40 : : struct function *fn)
41 : : {
42 : 68559 : unsigned HOST_WIDE_INT ix;
43 : 68559 : tree phi_result;
44 : 68559 : int i, len;
45 : 68559 : gphi *result;
46 : :
47 : 68559 : ix = streamer_read_uhwi (ib);
48 : 68559 : phi_result = (*SSANAMES (fn))[ix];
49 : 68559 : len = EDGE_COUNT (bb->preds);
50 : 68559 : result = create_phi_node (phi_result, bb);
51 : :
52 : : /* We have to go through a lookup process here because the preds in the
53 : : reconstructed graph are generally in a different order than they
54 : : were in the original program. */
55 : 246403 : for (i = 0; i < len; i++)
56 : : {
57 : 177844 : tree def = stream_read_tree (ib, data_in);
58 : 177844 : int src_index = streamer_read_uhwi (ib);
59 : 177844 : bitpack_d bp = streamer_read_bitpack (ib);
60 : 177844 : basic_block sbb = BASIC_BLOCK_FOR_FN (fn, src_index);
61 : 177844 : edge e = NULL;
62 : 177844 : int j;
63 : :
64 : 2947556 : for (j = 0; j < len; j++)
65 : 2947556 : if (EDGE_PRED (bb, j)->src == sbb)
66 : : {
67 : : e = EDGE_PRED (bb, j);
68 : : break;
69 : : }
70 : :
71 : 177844 : add_phi_arg (result, def, e, UNKNOWN_LOCATION);
72 : : /* Read location and lexical block information. */
73 : 177844 : location_t *arg_locp = gimple_phi_arg_location_ptr (result, e->dest_idx);
74 : 177844 : data_in->location_cache.input_location_and_block (arg_locp, &bp, ib,
75 : : data_in);
76 : : }
77 : :
78 : 68559 : return result;
79 : : }
80 : :
81 : :
82 : : /* Read a statement with tag TAG in function FN from block IB using
83 : : descriptors in DATA_IN. */
84 : :
85 : : static gimple *
86 : 1384565 : input_gimple_stmt (class lto_input_block *ib, class data_in *data_in,
87 : : enum LTO_tags tag)
88 : : {
89 : 1384565 : gimple *stmt;
90 : 1384565 : enum gimple_code code;
91 : 1384565 : unsigned HOST_WIDE_INT num_ops;
92 : 1384565 : size_t i;
93 : 1384565 : struct bitpack_d bp;
94 : 1384565 : bool has_hist;
95 : :
96 : 1384565 : code = lto_tag_to_gimple_code (tag);
97 : :
98 : : /* Read the tuple header. */
99 : 1384565 : bp = streamer_read_bitpack (ib);
100 : 1384565 : num_ops = bp_unpack_var_len_unsigned (&bp);
101 : 1384565 : stmt = gimple_alloc (code, num_ops);
102 : 1384565 : stmt->no_warning = bp_unpack_value (&bp, 1);
103 : 1384565 : if (is_gimple_assign (stmt))
104 : 608967 : stmt->nontemporal_move = bp_unpack_value (&bp, 1);
105 : 1384565 : stmt->has_volatile_ops = bp_unpack_value (&bp, 1);
106 : 1384565 : has_hist = bp_unpack_value (&bp, 1);
107 : 1384565 : stmt->subcode = bp_unpack_var_len_unsigned (&bp);
108 : :
109 : : /* Read location and lexical block information. */
110 : 1384565 : data_in->location_cache.input_location_and_block (gimple_location_ptr (stmt),
111 : : &bp, ib, data_in);
112 : :
113 : : /* Read in all the operands. */
114 : 1384565 : switch (code)
115 : : {
116 : 2097 : case GIMPLE_RESX:
117 : 2097 : gimple_resx_set_region (as_a <gresx *> (stmt),
118 : 2097 : streamer_read_hwi (ib));
119 : 2097 : break;
120 : :
121 : 0 : case GIMPLE_EH_MUST_NOT_THROW:
122 : 0 : gimple_eh_must_not_throw_set_fndecl (
123 : : as_a <geh_mnt *> (stmt),
124 : 0 : stream_read_tree (ib, data_in));
125 : 0 : break;
126 : :
127 : 179 : case GIMPLE_EH_DISPATCH:
128 : 179 : gimple_eh_dispatch_set_region (as_a <geh_dispatch *> (stmt),
129 : 179 : streamer_read_hwi (ib));
130 : 179 : break;
131 : :
132 : 5475 : case GIMPLE_ASM:
133 : 5475 : {
134 : : /* FIXME lto. Move most of this into a new gimple_asm_set_string(). */
135 : 5475 : gasm *asm_stmt = as_a <gasm *> (stmt);
136 : 5475 : tree str;
137 : 5475 : asm_stmt->ni = streamer_read_uhwi (ib);
138 : 5475 : asm_stmt->no = streamer_read_uhwi (ib);
139 : 5475 : asm_stmt->nc = streamer_read_uhwi (ib);
140 : 5475 : asm_stmt->nl = streamer_read_uhwi (ib);
141 : 5475 : str = streamer_read_string_cst (data_in, ib);
142 : 5475 : asm_stmt->string = TREE_STRING_POINTER (str);
143 : : }
144 : : /* Fallthru */
145 : :
146 : : case GIMPLE_ASSIGN:
147 : : case GIMPLE_CALL:
148 : : case GIMPLE_RETURN:
149 : : case GIMPLE_SWITCH:
150 : : case GIMPLE_LABEL:
151 : : case GIMPLE_COND:
152 : : case GIMPLE_GOTO:
153 : : case GIMPLE_DEBUG:
154 : 5713481 : for (i = 0; i < num_ops; i++)
155 : : {
156 : 4370471 : tree *opp, op = stream_read_tree (ib, data_in);
157 : 4370471 : gimple_set_op (stmt, i, op);
158 : 4370471 : if (!op)
159 : 1237635 : continue;
160 : :
161 : 3132836 : opp = gimple_op_ptr (stmt, i);
162 : 3132836 : if (TREE_CODE (*opp) == ADDR_EXPR)
163 : 553923 : opp = &TREE_OPERAND (*opp, 0);
164 : 3289019 : while (handled_component_p (*opp))
165 : 156183 : opp = &TREE_OPERAND (*opp, 0);
166 : : /* At LTO output time we wrap all global decls in MEM_REFs to
167 : : allow seamless replacement with prevailing decls. Undo this
168 : : here if the prevailing decl allows for this.
169 : : ??? Maybe we should simply fold all stmts. */
170 : 3132836 : if (TREE_CODE (*opp) == MEM_REF
171 : 300833 : && TREE_CODE (TREE_OPERAND (*opp, 0)) == ADDR_EXPR
172 : 231055 : && integer_zerop (TREE_OPERAND (*opp, 1))
173 : 453134 : && (TREE_THIS_VOLATILE (*opp)
174 : 226567 : == TREE_THIS_VOLATILE
175 : : (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0)))
176 : 226534 : && !TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (*opp, 1)))
177 : 226107 : && (TREE_TYPE (*opp)
178 : 226107 : == TREE_TYPE (TREE_TYPE (TREE_OPERAND (*opp, 1))))
179 : 3358363 : && (TREE_TYPE (*opp)
180 : 225527 : == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0))))
181 : 224504 : *opp = TREE_OPERAND (TREE_OPERAND (*opp, 0), 0);
182 : : }
183 : 1343010 : if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
184 : : {
185 : 378802 : if (gimple_call_internal_p (call_stmt))
186 : 33764 : gimple_call_set_internal_fn
187 : 33764 : (call_stmt, streamer_read_enum (ib, internal_fn, IFN_LAST));
188 : : else
189 : 345038 : gimple_call_set_fntype (call_stmt, stream_read_tree (ib, data_in));
190 : : }
191 : : break;
192 : :
193 : : case GIMPLE_NOP:
194 : : case GIMPLE_PREDICT:
195 : : break;
196 : :
197 : 1 : case GIMPLE_TRANSACTION:
198 : 1 : gimple_transaction_set_label_norm (as_a <gtransaction *> (stmt),
199 : 1 : stream_read_tree (ib, data_in));
200 : 1 : gimple_transaction_set_label_uninst (as_a <gtransaction *> (stmt),
201 : 1 : stream_read_tree (ib, data_in));
202 : 1 : gimple_transaction_set_label_over (as_a <gtransaction *> (stmt),
203 : 1 : stream_read_tree (ib, data_in));
204 : 1 : break;
205 : :
206 : 0 : default:
207 : 0 : internal_error ("bytecode stream: unknown GIMPLE statement tag %s",
208 : : lto_tag_name (tag));
209 : : }
210 : :
211 : : /* Update the properties of symbols, SSA names and labels associated
212 : : with STMT. */
213 : 1384565 : if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
214 : : {
215 : 987769 : tree lhs = gimple_get_lhs (stmt);
216 : 987769 : if (lhs && TREE_CODE (lhs) == SSA_NAME)
217 : 652759 : SSA_NAME_DEF_STMT (lhs) = stmt;
218 : : }
219 : 396796 : else if (code == GIMPLE_ASM)
220 : : {
221 : 5475 : gasm *asm_stmt = as_a <gasm *> (stmt);
222 : 5475 : unsigned i;
223 : :
224 : 15037 : for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
225 : : {
226 : 9562 : tree op = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
227 : 9562 : if (TREE_CODE (op) == SSA_NAME)
228 : 9322 : SSA_NAME_DEF_STMT (op) = stmt;
229 : : }
230 : : }
231 : :
232 : : /* Reset alias information. */
233 : 1384565 : if (code == GIMPLE_CALL)
234 : 378802 : gimple_call_reset_alias_info (as_a <gcall *> (stmt));
235 : :
236 : : /* Mark the statement modified so its operand vectors can be filled in. */
237 : 1384565 : gimple_set_modified (stmt, true);
238 : 1384565 : if (has_hist)
239 : 1 : stream_in_histogram_value (ib, stmt);
240 : :
241 : 1384565 : return stmt;
242 : : }
243 : :
244 : :
245 : : /* Read a basic block with tag TAG from DATA_IN using input block IB.
246 : : FN is the function being processed. */
247 : :
248 : : void
249 : 741264 : input_bb (class lto_input_block *ib, enum LTO_tags tag,
250 : : class data_in *data_in, struct function *fn,
251 : : int count_materialization_scale)
252 : : {
253 : 741264 : unsigned int index;
254 : 741264 : basic_block bb;
255 : 741264 : gimple_stmt_iterator bsi;
256 : :
257 : : /* This routine assumes that CFUN is set to FN, as it needs to call
258 : : basic GIMPLE routines that use CFUN. */
259 : 741264 : gcc_assert (cfun == fn);
260 : :
261 : 741264 : index = streamer_read_uhwi (ib);
262 : 741264 : bb = BASIC_BLOCK_FOR_FN (fn, index);
263 : :
264 : 741264 : bb->count = profile_count::stream_in (ib);
265 : 741264 : if (count_materialization_scale != REG_BR_PROB_BASE
266 : 741264 : && bb->count.ipa ().nonzero_p ())
267 : 0 : bb->count
268 : 0 : = bb->count.apply_scale (count_materialization_scale, REG_BR_PROB_BASE);
269 : 741264 : bb->flags = streamer_read_hwi (ib);
270 : :
271 : : /* LTO_bb1 has statements. LTO_bb0 does not. */
272 : 741264 : if (tag == LTO_bb0)
273 : 199843 : return;
274 : :
275 : 541421 : bsi = gsi_start_bb (bb);
276 : 541421 : tag = streamer_read_record_start (ib);
277 : 1925986 : while (tag)
278 : : {
279 : 1384565 : gimple *stmt = input_gimple_stmt (ib, data_in, tag);
280 : 1384565 : gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
281 : :
282 : : /* After the statement, expect a 0 delimiter or the EH region
283 : : that the previous statement belongs to. */
284 : 1384565 : tag = streamer_read_record_start (ib);
285 : 1384565 : lto_tag_check_set (tag, 2, LTO_eh_region, LTO_null);
286 : :
287 : 1384565 : if (tag == LTO_eh_region)
288 : : {
289 : 4627 : HOST_WIDE_INT region = streamer_read_hwi (ib);
290 : 4627 : gcc_assert (region == (int) region);
291 : 4627 : add_stmt_to_eh_lp (stmt, region);
292 : : }
293 : :
294 : 1384565 : tag = streamer_read_record_start (ib);
295 : : }
296 : :
297 : 541421 : tag = streamer_read_record_start (ib);
298 : 609980 : while (tag)
299 : : {
300 : 68559 : input_phi (ib, bb, data_in, fn);
301 : 68559 : tag = streamer_read_record_start (ib);
302 : : }
303 : : }
|