Mercurial > hg > CbC > CbC_gcc
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 */ |