comparison gcc/tree-ssa-phiprop.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents 58ad6c70ea60
children b7f97abdc517
comparison
equal deleted inserted replaced
52:c156f1bd5cd9 55:77e2b8dfacca
88 local analysis and stores the result for use by transformations on 88 local analysis and stores the result for use by transformations on
89 dominated basic-blocks. */ 89 dominated basic-blocks. */
90 90
91 91
92 /* Structure to keep track of the value of a dereferenced PHI result 92 /* Structure to keep track of the value of a dereferenced PHI result
93 and the set of virtual operands used for that dereference. */ 93 and the virtual operand used for that dereference. */
94 94
95 struct phiprop_d 95 struct phiprop_d
96 { 96 {
97 tree value; 97 tree value;
98 gimple vop_stmt; 98 tree vuse;
99 }; 99 };
100 100
101 /* Verify if the value recorded for NAME in PHIVN is still valid at 101 /* Verify if the value recorded for NAME in PHIVN is still valid at
102 the start of basic block BB. */ 102 the start of basic block BB. */
103 103
104 static bool 104 static bool
105 phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb) 105 phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb)
106 { 106 {
107 gimple vop_stmt = phivn[SSA_NAME_VERSION (name)].vop_stmt; 107 tree vuse = phivn[SSA_NAME_VERSION (name)].vuse;
108 ssa_op_iter ui; 108 gimple use_stmt;
109 tree vuse; 109 imm_use_iterator ui2;
110 110 bool ok = true;
111 /* The def stmts of all virtual uses need to be post-dominated 111
112 by bb. */ 112 /* The def stmts of the virtual uses need to be dominated by bb. */
113 FOR_EACH_SSA_TREE_OPERAND (vuse, vop_stmt, ui, SSA_OP_VUSE) 113 gcc_assert (vuse != NULL_TREE);
114
115 FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse)
114 { 116 {
115 gimple use_stmt; 117 /* If BB does not dominate a VDEF, the value is invalid. */
116 imm_use_iterator ui2; 118 if ((gimple_vdef (use_stmt) != NULL_TREE
117 bool ok = true; 119 || gimple_code (use_stmt) == GIMPLE_PHI)
118 120 && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
119 FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse) 121 {
120 { 122 ok = false;
121 /* If BB does not dominate a VDEF, the value is invalid. */ 123 BREAK_FROM_IMM_USE_STMT (ui2);
122 if ((!ZERO_SSA_OPERANDS (use_stmt, SSA_OP_VDEF) 124 }
123 || gimple_code (use_stmt) == GIMPLE_PHI)
124 && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
125 {
126 ok = false;
127 BREAK_FROM_IMM_USE_STMT (ui2);
128 }
129 }
130 if (!ok)
131 return false;
132 } 125 }
133 126
134 return true; 127 return ok;
135 } 128 }
136 129
137 /* Insert a new phi node for the dereference of PHI at basic_block 130 /* Insert a new phi node for the dereference of PHI at basic_block
138 BB with the virtual operands from USE_STMT. */ 131 BB with the virtual operands from USE_STMT. */
139 132
151 144
152 /* Build a new PHI node to replace the definition of 145 /* Build a new PHI node to replace the definition of
153 the indirect reference lhs. */ 146 the indirect reference lhs. */
154 res = gimple_assign_lhs (use_stmt); 147 res = gimple_assign_lhs (use_stmt);
155 SSA_NAME_DEF_STMT (res) = new_phi = create_phi_node (res, bb); 148 SSA_NAME_DEF_STMT (res) = new_phi = create_phi_node (res, bb);
149
150 if (dump_file && (dump_flags & TDF_DETAILS))
151 {
152 fprintf (dump_file, "Inserting PHI for result of load ");
153 print_gimple_stmt (dump_file, use_stmt, 0, 0);
154 }
156 155
157 /* Add PHI arguments for each edge inserting loads of the 156 /* Add PHI arguments for each edge inserting loads of the
158 addressable operands. */ 157 addressable operands. */
159 FOR_EACH_EDGE (e, ei, bb->preds) 158 FOR_EACH_EDGE (e, ei, bb->preds)
160 { 159 {
161 tree old_arg, new_var; 160 tree old_arg, new_var;
162 gimple tmp; 161 gimple tmp;
162 source_location locus;
163 163
164 old_arg = PHI_ARG_DEF_FROM_EDGE (phi, e); 164 old_arg = PHI_ARG_DEF_FROM_EDGE (phi, e);
165 locus = gimple_phi_arg_location_from_edge (phi, e);
165 while (TREE_CODE (old_arg) == SSA_NAME 166 while (TREE_CODE (old_arg) == SSA_NAME
166 && (SSA_NAME_VERSION (old_arg) >= n 167 && (SSA_NAME_VERSION (old_arg) >= n
167 || phivn[SSA_NAME_VERSION (old_arg)].value == NULL_TREE)) 168 || phivn[SSA_NAME_VERSION (old_arg)].value == NULL_TREE))
168 { 169 {
169 gimple def_stmt = SSA_NAME_DEF_STMT (old_arg); 170 gimple def_stmt = SSA_NAME_DEF_STMT (old_arg);
170 old_arg = gimple_assign_rhs1 (def_stmt); 171 old_arg = gimple_assign_rhs1 (def_stmt);
172 locus = gimple_location (def_stmt);
171 } 173 }
172 174
173 if (TREE_CODE (old_arg) == SSA_NAME) 175 if (TREE_CODE (old_arg) == SSA_NAME)
174 /* Reuse a formerly created dereference. */ 176 {
175 new_var = phivn[SSA_NAME_VERSION (old_arg)].value; 177 if (dump_file && (dump_flags & TDF_DETAILS))
178 {
179 fprintf (dump_file, " for edge defining ");
180 print_generic_expr (dump_file, PHI_ARG_DEF_FROM_EDGE (phi, e), 0);
181 fprintf (dump_file, " reusing PHI result ");
182 print_generic_expr (dump_file,
183 phivn[SSA_NAME_VERSION (old_arg)].value, 0);
184 fprintf (dump_file, "\n");
185 }
186 /* Reuse a formerly created dereference. */
187 new_var = phivn[SSA_NAME_VERSION (old_arg)].value;
188 }
176 else 189 else
177 { 190 {
178 gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR); 191 gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR);
179 old_arg = TREE_OPERAND (old_arg, 0); 192 old_arg = TREE_OPERAND (old_arg, 0);
180 new_var = create_tmp_var (TREE_TYPE (old_arg), NULL); 193 new_var = create_tmp_var (TREE_TYPE (old_arg), NULL);
184 DECL_GIMPLE_REG_P (new_var) = 1; 197 DECL_GIMPLE_REG_P (new_var) = 1;
185 gcc_assert (is_gimple_reg (new_var)); 198 gcc_assert (is_gimple_reg (new_var));
186 add_referenced_var (new_var); 199 add_referenced_var (new_var);
187 new_var = make_ssa_name (new_var, tmp); 200 new_var = make_ssa_name (new_var, tmp);
188 gimple_assign_set_lhs (tmp, new_var); 201 gimple_assign_set_lhs (tmp, new_var);
202 gimple_set_location (tmp, locus);
189 203
190 gsi_insert_on_edge (e, tmp); 204 gsi_insert_on_edge (e, tmp);
191
192 update_stmt (tmp); 205 update_stmt (tmp);
193 mark_symbols_for_renaming (tmp); 206
194 } 207 if (dump_file && (dump_flags & TDF_DETAILS))
195 208 {
196 add_phi_arg (new_phi, new_var, e); 209 fprintf (dump_file, " for edge defining ");
210 print_generic_expr (dump_file, PHI_ARG_DEF_FROM_EDGE (phi, e), 0);
211 fprintf (dump_file, " inserting load ");
212 print_gimple_stmt (dump_file, tmp, 0, 0);
213 }
214 }
215
216 add_phi_arg (new_phi, new_var, e, locus);
197 } 217 }
198 218
199 update_stmt (new_phi); 219 update_stmt (new_phi);
220
221 if (dump_file && (dump_flags & TDF_DETAILS))
222 print_gimple_stmt (dump_file, new_phi, 0, 0);
200 223
201 return res; 224 return res;
202 } 225 }
203 226
204 /* Propagate between the phi node arguments of PHI in BB and phi result 227 /* Propagate between the phi node arguments of PHI in BB and phi result
226 imm_use_iterator ui; 249 imm_use_iterator ui;
227 use_operand_p arg_p, use; 250 use_operand_p arg_p, use;
228 ssa_op_iter i; 251 ssa_op_iter i;
229 bool phi_inserted; 252 bool phi_inserted;
230 253
231 if (MTAG_P (SSA_NAME_VAR (ptr)) 254 if (!POINTER_TYPE_P (TREE_TYPE (ptr))
232 || !POINTER_TYPE_P (TREE_TYPE (ptr))
233 || !is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr)))) 255 || !is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr))))
234 return false; 256 return false;
235 257
236 /* Check if we can "cheaply" dereference all phi arguments. */ 258 /* Check if we can "cheaply" dereference all phi arguments. */
237 FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_USE) 259 FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_USE)
252 } 274 }
253 if ((TREE_CODE (arg) != ADDR_EXPR 275 if ((TREE_CODE (arg) != ADDR_EXPR
254 /* Avoid to have to decay *&a to a[0] later. */ 276 /* Avoid to have to decay *&a to a[0] later. */
255 || !is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (arg, 0)))) 277 || !is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (arg, 0))))
256 && !(TREE_CODE (arg) == SSA_NAME 278 && !(TREE_CODE (arg) == SSA_NAME
279 && SSA_NAME_VERSION (arg) < n
257 && phivn[SSA_NAME_VERSION (arg)].value != NULL_TREE 280 && phivn[SSA_NAME_VERSION (arg)].value != NULL_TREE
258 && phivn_valid_p (phivn, arg, bb))) 281 && phivn_valid_p (phivn, arg, bb)))
259 return false; 282 return false;
260 } 283 }
261 284
268 /* Replace the first dereference of *ptr if there is one and if we 291 /* Replace the first dereference of *ptr if there is one and if we
269 can move the loads to the place of the ptr phi node. */ 292 can move the loads to the place of the ptr phi node. */
270 phi_inserted = false; 293 phi_inserted = false;
271 FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr) 294 FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr)
272 { 295 {
273 ssa_op_iter ui2; 296 gimple def_stmt;
274 tree vuse; 297 tree vuse;
275 298
276 /* Check whether this is a load of *ptr. */ 299 /* Check whether this is a load of *ptr. */
277 if (!(is_gimple_assign (use_stmt) 300 if (!(is_gimple_assign (use_stmt)
278 && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME 301 && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME
279 && gimple_assign_rhs_code (use_stmt) == INDIRECT_REF 302 && gimple_assign_rhs_code (use_stmt) == INDIRECT_REF
280 && TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == ptr 303 && TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == ptr
281 /* We cannot replace a load that may throw or is volatile. */ 304 /* We cannot replace a load that may throw or is volatile. */
282 && !stmt_can_throw_internal (use_stmt))) 305 && !stmt_can_throw_internal (use_stmt)))
283 continue; 306 continue;
284 307
285 /* Check if we can move the loads. The def stmts of all virtual uses 308 /* Check if we can move the loads. The def stmt of the virtual use
286 need to be post-dominated by bb. */ 309 needs to be in a different basic block dominating bb. */
287 FOR_EACH_SSA_TREE_OPERAND (vuse, use_stmt, ui2, SSA_OP_VUSE) 310 vuse = gimple_vuse (use_stmt);
288 { 311 def_stmt = SSA_NAME_DEF_STMT (vuse);
289 gimple def_stmt = SSA_NAME_DEF_STMT (vuse); 312 if (!SSA_NAME_IS_DEFAULT_DEF (vuse)
290 if (!SSA_NAME_IS_DEFAULT_DEF (vuse) 313 && (gimple_bb (def_stmt) == bb
291 && (gimple_bb (def_stmt) == bb 314 || !dominated_by_p (CDI_DOMINATORS,
292 || !dominated_by_p (CDI_DOMINATORS, 315 bb, gimple_bb (def_stmt))))
293 bb, gimple_bb (def_stmt)))) 316 goto next;
294 goto next;
295 }
296 317
297 /* Found a proper dereference. Insert a phi node if this 318 /* Found a proper dereference. Insert a phi node if this
298 is the first load transformation. */ 319 is the first load transformation. */
299 if (!phi_inserted) 320 if (!phi_inserted)
300 { 321 {
301 res = phiprop_insert_phi (bb, phi, use_stmt, phivn, n); 322 res = phiprop_insert_phi (bb, phi, use_stmt, phivn, n);
302 323
303 /* Remember the value we created for *ptr. */ 324 /* Remember the value we created for *ptr. */
304 phivn[SSA_NAME_VERSION (ptr)].value = res; 325 phivn[SSA_NAME_VERSION (ptr)].value = res;
305 phivn[SSA_NAME_VERSION (ptr)].vop_stmt = use_stmt; 326 phivn[SSA_NAME_VERSION (ptr)].vuse = vuse;
306 327
307 /* Remove old stmt. The phi is taken care of by DCE, if we 328 /* Remove old stmt. The phi is taken care of by DCE, if we
308 want to delete it here we also have to delete all intermediate 329 want to delete it here we also have to delete all intermediate
309 copies. */ 330 copies. */
310 gsi = gsi_for_stmt (use_stmt); 331 gsi = gsi_for_stmt (use_stmt);
325 } 346 }
326 347
327 return phi_inserted; 348 return phi_inserted;
328 } 349 }
329 350
330 /* Helper walking the dominator tree starting from BB and processing
331 phi nodes with global data PHIVN and N. */
332
333 static bool
334 tree_ssa_phiprop_1 (basic_block bb, struct phiprop_d *phivn, size_t n)
335 {
336 bool did_something = false;
337 basic_block son;
338 gimple_stmt_iterator gsi;
339
340 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
341 did_something |= propagate_with_phi (bb, gsi_stmt (gsi), phivn, n);
342
343 for (son = first_dom_son (CDI_DOMINATORS, bb);
344 son;
345 son = next_dom_son (CDI_DOMINATORS, son))
346 did_something |= tree_ssa_phiprop_1 (son, phivn, n);
347
348 return did_something;
349 }
350
351 /* Main entry for phiprop pass. */ 351 /* Main entry for phiprop pass. */
352 352
353 static unsigned int 353 static unsigned int
354 tree_ssa_phiprop (void) 354 tree_ssa_phiprop (void)
355 { 355 {
356 VEC(basic_block, heap) *bbs;
356 struct phiprop_d *phivn; 357 struct phiprop_d *phivn;
358 bool did_something = false;
359 basic_block bb;
360 gimple_stmt_iterator gsi;
361 unsigned i;
362 size_t n;
357 363
358 calculate_dominance_info (CDI_DOMINATORS); 364 calculate_dominance_info (CDI_DOMINATORS);
359 365
360 phivn = XCNEWVEC (struct phiprop_d, num_ssa_names); 366 n = num_ssa_names;
361 367 phivn = XCNEWVEC (struct phiprop_d, n);
362 if (tree_ssa_phiprop_1 (ENTRY_BLOCK_PTR, phivn, num_ssa_names)) 368
369 /* Walk the dominator tree in preorder. */
370 bbs = get_all_dominated_blocks (CDI_DOMINATORS,
371 single_succ (ENTRY_BLOCK_PTR));
372 for (i = 0; VEC_iterate (basic_block, bbs, i, bb); ++i)
373 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
374 did_something |= propagate_with_phi (bb, gsi_stmt (gsi), phivn, n);
375
376 if (did_something)
363 gsi_commit_edge_inserts (); 377 gsi_commit_edge_inserts ();
364 378
379 VEC_free (basic_block, heap, bbs);
365 free (phivn); 380 free (phivn);
366 381
367 return 0; 382 return 0;
368 } 383 }
369 384
370 static bool 385 static bool
371 gate_phiprop (void) 386 gate_phiprop (void)
372 { 387 {
373 return 1; 388 return flag_tree_phiprop;
374 } 389 }
375 390
376 struct gimple_opt_pass pass_phiprop = 391 struct gimple_opt_pass pass_phiprop =
377 { 392 {
378 { 393 {
379 GIMPLE_PASS, 394 GIMPLE_PASS,
380 "phiprop", /* name */ 395 "phiprop", /* name */
381 gate_phiprop, /* gate */ 396 gate_phiprop, /* gate */