1 /* Routines for reading GIMPLE from a file stream. 2 3 Copyright (C) 2011-2020 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 input_phi (class lto_input_block *ib, basic_block bb, class data_in *data_in, 40 struct function *fn) 41 { 42 unsigned HOST_WIDE_INT ix; 43 tree phi_result; 44 int i, len; 45 gphi *result; 46 47 ix = streamer_read_uhwi (ib); 48 phi_result = (*SSANAMES (fn))[ix]; 49 len = EDGE_COUNT (bb->preds); 50 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 for (i = 0; i < len; i++) 56 { 57 tree def = stream_read_tree (ib, data_in); 58 int src_index = streamer_read_uhwi (ib); 59 bitpack_d bp = streamer_read_bitpack (ib); 60 basic_block sbb = BASIC_BLOCK_FOR_FN (fn, src_index); 61 edge e = NULL; 62 int j; 63 64 for (j = 0; j < len; j++) 65 if (EDGE_PRED (bb, j)->src == sbb) 66 { 67 e = EDGE_PRED (bb, j); 68 break; 69 } 70 71 add_phi_arg (result, def, e, UNKNOWN_LOCATION); 72 /* Read location and lexical block information. */ 73 location_t *arg_locp = gimple_phi_arg_location_ptr (result, e->dest_idx); 74 data_in->location_cache.input_location_and_block (arg_locp, &bp, ib, 75 data_in); 76 } 77 78 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 input_gimple_stmt (class lto_input_block *ib, class data_in *data_in, 87 enum LTO_tags tag) 88 { 89 gimple *stmt; 90 enum gimple_code code; 91 unsigned HOST_WIDE_INT num_ops; 92 size_t i; 93 struct bitpack_d bp; 94 bool has_hist; 95 96 code = lto_tag_to_gimple_code (tag); 97 98 /* Read the tuple header. */ 99 bp = streamer_read_bitpack (ib); 100 num_ops = bp_unpack_var_len_unsigned (&bp); 101 stmt = gimple_alloc (code, num_ops); 102 stmt->no_warning = bp_unpack_value (&bp, 1); 103 if (is_gimple_assign (stmt)) 104 stmt->nontemporal_move = bp_unpack_value (&bp, 1); 105 stmt->has_volatile_ops = bp_unpack_value (&bp, 1); 106 has_hist = bp_unpack_value (&bp, 1); 107 stmt->subcode = bp_unpack_var_len_unsigned (&bp); 108 109 /* Read location and lexical block information. */ 110 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 switch (code) 115 { 116 case GIMPLE_RESX: 117 gimple_resx_set_region (as_a <gresx *> (stmt), 118 streamer_read_hwi (ib)); 119 break; 120 121 case GIMPLE_EH_MUST_NOT_THROW: 122 gimple_eh_must_not_throw_set_fndecl ( 123 as_a <geh_mnt *> (stmt), 124 stream_read_tree (ib, data_in)); 125 break; 126 127 case GIMPLE_EH_DISPATCH: 128 gimple_eh_dispatch_set_region (as_a <geh_dispatch *> (stmt), 129 streamer_read_hwi (ib)); 130 break; 131 132 case GIMPLE_ASM: 133 { 134 /* FIXME lto. Move most of this into a new gimple_asm_set_string(). */ 135 gasm *asm_stmt = as_a <gasm *> (stmt); 136 tree str; 137 asm_stmt->ni = streamer_read_uhwi (ib); 138 asm_stmt->no = streamer_read_uhwi (ib); 139 asm_stmt->nc = streamer_read_uhwi (ib); 140 asm_stmt->nl = streamer_read_uhwi (ib); 141 str = streamer_read_string_cst (data_in, ib); 142 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 for (i = 0; i < num_ops; i++) 155 { 156 tree *opp, op = stream_read_tree (ib, data_in); 157 gimple_set_op (stmt, i, op); 158 if (!op) 159 continue; 160 161 opp = gimple_op_ptr (stmt, i); 162 if (TREE_CODE (*opp) == ADDR_EXPR) 163 opp = &TREE_OPERAND (*opp, 0); 164 while (handled_component_p (*opp)) 165 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 if (TREE_CODE (*opp) == MEM_REF 171 && TREE_CODE (TREE_OPERAND (*opp, 0)) == ADDR_EXPR 172 && integer_zerop (TREE_OPERAND (*opp, 1)) 173 && (TREE_THIS_VOLATILE (*opp) 174 == TREE_THIS_VOLATILE 175 (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0))) 176 && !TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (*opp, 1))) 177 && (TREE_TYPE (*opp) 178 == TREE_TYPE (TREE_TYPE (TREE_OPERAND (*opp, 1)))) 179 && (TREE_TYPE (*opp) 180 == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0)))) 181 *opp = TREE_OPERAND (TREE_OPERAND (*opp, 0), 0); 182 } 183 if (gcall *call_stmt = dyn_cast <gcall *> (stmt)) 184 { 185 if (gimple_call_internal_p (call_stmt)) 186 gimple_call_set_internal_fn 187 (call_stmt, streamer_read_enum (ib, internal_fn, IFN_LAST)); 188 else 189 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 case GIMPLE_TRANSACTION: 198 gimple_transaction_set_label_norm (as_a <gtransaction *> (stmt), 199 stream_read_tree (ib, data_in)); 200 gimple_transaction_set_label_uninst (as_a <gtransaction *> (stmt), 201 stream_read_tree (ib, data_in)); 202 gimple_transaction_set_label_over (as_a <gtransaction *> (stmt), 203 stream_read_tree (ib, data_in)); 204 break; 205 206 default: 207 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 if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL) 214 { 215 tree lhs = gimple_get_lhs (stmt); 216 if (lhs && TREE_CODE (lhs) == SSA_NAME) 217 SSA_NAME_DEF_STMT (lhs) = stmt; 218 } 219 else if (code == GIMPLE_ASM) 220 { 221 gasm *asm_stmt = as_a <gasm *> (stmt); 222 unsigned i; 223 224 for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++) 225 { 226 tree op = TREE_VALUE (gimple_asm_output_op (asm_stmt, i)); 227 if (TREE_CODE (op) == SSA_NAME) 228 SSA_NAME_DEF_STMT (op) = stmt; 229 } 230 } 231 232 /* Reset alias information. */ 233 if (code == GIMPLE_CALL) 234 gimple_call_reset_alias_info (as_a <gcall *> (stmt)); 235 236 /* Mark the statement modified so its operand vectors can be filled in. */ 237 gimple_set_modified (stmt, true); 238 if (has_hist) 239 stream_in_histogram_value (ib, stmt); 240 241 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 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 unsigned int index; 254 basic_block bb; 255 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 gcc_assert (cfun == fn); 260 261 index = streamer_read_uhwi (ib); 262 bb = BASIC_BLOCK_FOR_FN (fn, index); 263 264 bb->count = profile_count::stream_in (ib); 265 if (count_materialization_scale != REG_BR_PROB_BASE 266 && bb->count.ipa ().nonzero_p ()) 267 bb->count 268 = bb->count.apply_scale (count_materialization_scale, REG_BR_PROB_BASE); 269 bb->flags = streamer_read_hwi (ib); 270 bb->discriminator = streamer_read_hwi (ib); 271 272 /* LTO_bb1 has statements. LTO_bb0 does not. */ 273 if (tag == LTO_bb0) 274 return; 275 276 bsi = gsi_start_bb (bb); 277 tag = streamer_read_record_start (ib); 278 while (tag) 279 { 280 gimple *stmt = input_gimple_stmt (ib, data_in, tag); 281 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT); 282 283 /* After the statement, expect a 0 delimiter or the EH region 284 that the previous statement belongs to. */ 285 tag = streamer_read_record_start (ib); 286 lto_tag_check_set (tag, 2, LTO_eh_region, LTO_null); 287 288 if (tag == LTO_eh_region) 289 { 290 HOST_WIDE_INT region = streamer_read_hwi (ib); 291 gcc_assert (region == (int) region); 292 add_stmt_to_eh_lp (stmt, region); 293 } 294 295 tag = streamer_read_record_start (ib); 296 } 297 298 tag = streamer_read_record_start (ib); 299 while (tag) 300 { 301 input_phi (ib, bb, data_in, fn); 302 tag = streamer_read_record_start (ib); 303 } 304 } 305