Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-ssa-loop-manip.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
0 | 1 /* High-level loop manipulation functions. |
145 | 2 Copyright (C) 2004-2020 Free Software Foundation, Inc. |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3 |
0 | 4 This file is part of GCC. |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
5 |
0 | 6 GCC is free software; you can redistribute it and/or modify it |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 3, or (at your option) any | |
9 later version. | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
10 |
0 | 11 GCC is distributed in the hope that it will be useful, but WITHOUT |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
15 |
0 | 16 You should have received a copy of the GNU General Public License |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
111 | 23 #include "backend.h" |
0 | 24 #include "tree.h" |
111 | 25 #include "gimple.h" |
26 #include "cfghooks.h" | |
27 #include "tree-pass.h" /* ??? for TODO_update_ssa but this isn't a pass. */ | |
28 #include "ssa.h" | |
29 #include "gimple-pretty-print.h" | |
30 #include "fold-const.h" | |
31 #include "cfganal.h" | |
32 #include "gimplify.h" | |
33 #include "gimple-iterator.h" | |
34 #include "gimplify-me.h" | |
35 #include "tree-cfg.h" | |
36 #include "tree-ssa-loop-ivopts.h" | |
37 #include "tree-ssa-loop-manip.h" | |
38 #include "tree-ssa-loop-niter.h" | |
39 #include "tree-ssa-loop.h" | |
40 #include "tree-into-ssa.h" | |
41 #include "tree-ssa.h" | |
0 | 42 #include "cfgloop.h" |
43 #include "tree-scalar-evolution.h" | |
44 #include "tree-inline.h" | |
111 | 45 |
46 /* All bitmaps for rewriting into loop-closed SSA go on this obstack, | |
47 so that we can free them all at once. */ | |
48 static bitmap_obstack loop_renamer_obstack; | |
0 | 49 |
50 /* Creates an induction variable with value BASE + STEP * iteration in LOOP. | |
51 It is expected that neither BASE nor STEP are shared with other expressions | |
52 (unless the sharing rules allow this). Use VAR as a base var_decl for it | |
53 (if NULL, a new temporary will be created). The increment will occur at | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
54 INCR_POS (after it if AFTER is true, before it otherwise). INCR_POS and |
0 | 55 AFTER can be computed using standard_iv_increment_position. The ssa versions |
56 of the variable before and after increment will be stored in VAR_BEFORE and | |
57 VAR_AFTER (unless they are NULL). */ | |
58 | |
59 void | |
145 | 60 create_iv (tree base, tree step, tree var, class loop *loop, |
0 | 61 gimple_stmt_iterator *incr_pos, bool after, |
62 tree *var_before, tree *var_after) | |
63 { | |
111 | 64 gassign *stmt; |
65 gphi *phi; | |
0 | 66 tree initial, step1; |
67 gimple_seq stmts; | |
68 tree vb, va; | |
69 enum tree_code incr_op = PLUS_EXPR; | |
70 edge pe = loop_preheader_edge (loop); | |
71 | |
111 | 72 if (var != NULL_TREE) |
0 | 73 { |
111 | 74 vb = make_ssa_name (var); |
75 va = make_ssa_name (var); | |
0 | 76 } |
111 | 77 else |
78 { | |
79 vb = make_temp_ssa_name (TREE_TYPE (base), NULL, "ivtmp"); | |
80 va = make_temp_ssa_name (TREE_TYPE (base), NULL, "ivtmp"); | |
81 } | |
0 | 82 if (var_before) |
83 *var_before = vb; | |
84 if (var_after) | |
85 *var_after = va; | |
86 | |
87 /* For easier readability of the created code, produce MINUS_EXPRs | |
88 when suitable. */ | |
89 if (TREE_CODE (step) == INTEGER_CST) | |
90 { | |
91 if (TYPE_UNSIGNED (TREE_TYPE (step))) | |
92 { | |
93 step1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (step), step); | |
94 if (tree_int_cst_lt (step1, step)) | |
95 { | |
96 incr_op = MINUS_EXPR; | |
97 step = step1; | |
98 } | |
99 } | |
100 else | |
101 { | |
102 bool ovf; | |
103 | |
104 if (!tree_expr_nonnegative_warnv_p (step, &ovf) | |
105 && may_negate_without_overflow_p (step)) | |
106 { | |
107 incr_op = MINUS_EXPR; | |
108 step = fold_build1 (NEGATE_EXPR, TREE_TYPE (step), step); | |
109 } | |
110 } | |
111 } | |
112 if (POINTER_TYPE_P (TREE_TYPE (base))) | |
113 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
114 if (TREE_CODE (base) == ADDR_EXPR) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
115 mark_addressable (TREE_OPERAND (base, 0)); |
111 | 116 step = convert_to_ptrofftype (step); |
0 | 117 if (incr_op == MINUS_EXPR) |
111 | 118 step = fold_build1 (NEGATE_EXPR, TREE_TYPE (step), step); |
0 | 119 incr_op = POINTER_PLUS_EXPR; |
120 } | |
121 /* Gimplify the step if necessary. We put the computations in front of the | |
122 loop (i.e. the step should be loop invariant). */ | |
123 step = force_gimple_operand (step, &stmts, true, NULL_TREE); | |
124 if (stmts) | |
125 gsi_insert_seq_on_edge_immediate (pe, stmts); | |
126 | |
111 | 127 stmt = gimple_build_assign (va, incr_op, vb, step); |
145 | 128 /* Prevent the increment from inheriting a bogus location if it is not put |
129 immediately after a statement whose location is known. */ | |
0 | 130 if (after) |
145 | 131 { |
132 if (gsi_end_p (*incr_pos)) | |
133 { | |
134 edge e = single_succ_edge (gsi_bb (*incr_pos)); | |
135 gimple_set_location (stmt, e->goto_locus); | |
136 } | |
137 gsi_insert_after (incr_pos, stmt, GSI_NEW_STMT); | |
138 } | |
0 | 139 else |
145 | 140 { |
141 if (!gsi_end_p (*incr_pos)) | |
142 gimple_set_location (stmt, gimple_location (gsi_stmt (*incr_pos))); | |
143 gsi_insert_before (incr_pos, stmt, GSI_NEW_STMT); | |
144 } | |
0 | 145 |
146 initial = force_gimple_operand (base, &stmts, true, var); | |
147 if (stmts) | |
148 gsi_insert_seq_on_edge_immediate (pe, stmts); | |
149 | |
111 | 150 phi = create_phi_node (vb, loop->header); |
151 add_phi_arg (phi, initial, loop_preheader_edge (loop), UNKNOWN_LOCATION); | |
152 add_phi_arg (phi, va, loop_latch_edge (loop), UNKNOWN_LOCATION); | |
153 } | |
154 | |
155 /* Return the innermost superloop LOOP of USE_LOOP that is a superloop of | |
156 both DEF_LOOP and USE_LOOP. */ | |
157 | |
145 | 158 static inline class loop * |
159 find_sibling_superloop (class loop *use_loop, class loop *def_loop) | |
111 | 160 { |
161 unsigned ud = loop_depth (use_loop); | |
162 unsigned dd = loop_depth (def_loop); | |
163 gcc_assert (ud > 0 && dd > 0); | |
164 if (ud > dd) | |
165 use_loop = superloop_at_depth (use_loop, dd); | |
166 if (ud < dd) | |
167 def_loop = superloop_at_depth (def_loop, ud); | |
168 while (loop_outer (use_loop) != loop_outer (def_loop)) | |
169 { | |
170 use_loop = loop_outer (use_loop); | |
171 def_loop = loop_outer (def_loop); | |
172 gcc_assert (use_loop && def_loop); | |
173 } | |
174 return use_loop; | |
0 | 175 } |
176 | |
111 | 177 /* DEF_BB is a basic block containing a DEF that needs rewriting into |
178 loop-closed SSA form. USE_BLOCKS is the set of basic blocks containing | |
179 uses of DEF that "escape" from the loop containing DEF_BB (i.e. blocks in | |
180 USE_BLOCKS are dominated by DEF_BB but not in the loop father of DEF_B). | |
181 ALL_EXITS[I] is the set of all basic blocks that exit loop I. | |
182 | |
183 Compute the subset of LOOP_EXITS that exit the loop containing DEF_BB | |
184 or one of its loop fathers, in which DEF is live. This set is returned | |
185 in the bitmap LIVE_EXITS. | |
186 | |
187 Instead of computing the complete livein set of the def, we use the loop | |
188 nesting tree as a form of poor man's structure analysis. This greatly | |
189 speeds up the analysis, which is important because this function may be | |
190 called on all SSA names that need rewriting, one at a time. */ | |
0 | 191 |
192 static void | |
111 | 193 compute_live_loop_exits (bitmap live_exits, bitmap use_blocks, |
194 bitmap *loop_exits, basic_block def_bb) | |
0 | 195 { |
111 | 196 unsigned i; |
197 bitmap_iterator bi; | |
145 | 198 class loop *def_loop = def_bb->loop_father; |
111 | 199 unsigned def_loop_depth = loop_depth (def_loop); |
200 bitmap def_loop_exits; | |
201 | |
202 /* Normally the work list size is bounded by the number of basic | |
203 blocks in the largest loop. We don't know this number, but we | |
204 can be fairly sure that it will be relatively small. */ | |
205 auto_vec<basic_block> worklist (MAX (8, n_basic_blocks_for_fn (cfun) / 128)); | |
206 | |
207 EXECUTE_IF_SET_IN_BITMAP (use_blocks, 0, i, bi) | |
208 { | |
209 basic_block use_bb = BASIC_BLOCK_FOR_FN (cfun, i); | |
145 | 210 class loop *use_loop = use_bb->loop_father; |
111 | 211 gcc_checking_assert (def_loop != use_loop |
212 && ! flow_loop_nested_p (def_loop, use_loop)); | |
213 if (! flow_loop_nested_p (use_loop, def_loop)) | |
214 use_bb = find_sibling_superloop (use_loop, def_loop)->header; | |
215 if (bitmap_set_bit (live_exits, use_bb->index)) | |
216 worklist.safe_push (use_bb); | |
217 } | |
218 | |
219 /* Iterate until the worklist is empty. */ | |
220 while (! worklist.is_empty ()) | |
221 { | |
222 edge e; | |
223 edge_iterator ei; | |
224 | |
225 /* Pull a block off the worklist. */ | |
226 basic_block bb = worklist.pop (); | |
227 | |
228 /* Make sure we have at least enough room in the work list | |
229 for all predecessors of this block. */ | |
230 worklist.reserve (EDGE_COUNT (bb->preds)); | |
231 | |
232 /* For each predecessor block. */ | |
233 FOR_EACH_EDGE (e, ei, bb->preds) | |
234 { | |
235 basic_block pred = e->src; | |
145 | 236 class loop *pred_loop = pred->loop_father; |
111 | 237 unsigned pred_loop_depth = loop_depth (pred_loop); |
238 bool pred_visited; | |
239 | |
240 /* We should have met DEF_BB along the way. */ | |
241 gcc_assert (pred != ENTRY_BLOCK_PTR_FOR_FN (cfun)); | |
242 | |
243 if (pred_loop_depth >= def_loop_depth) | |
244 { | |
245 if (pred_loop_depth > def_loop_depth) | |
246 pred_loop = superloop_at_depth (pred_loop, def_loop_depth); | |
247 /* If we've reached DEF_LOOP, our train ends here. */ | |
248 if (pred_loop == def_loop) | |
249 continue; | |
250 } | |
251 else if (! flow_loop_nested_p (pred_loop, def_loop)) | |
252 pred = find_sibling_superloop (pred_loop, def_loop)->header; | |
253 | |
254 /* Add PRED to the LIVEIN set. PRED_VISITED is true if | |
255 we had already added PRED to LIVEIN before. */ | |
256 pred_visited = !bitmap_set_bit (live_exits, pred->index); | |
257 | |
258 /* If we have visited PRED before, don't add it to the worklist. | |
259 If BB dominates PRED, then we're probably looking at a loop. | |
260 We're only interested in looking up in the dominance tree | |
261 because DEF_BB dominates all the uses. */ | |
262 if (pred_visited || dominated_by_p (CDI_DOMINATORS, pred, bb)) | |
263 continue; | |
264 | |
265 worklist.quick_push (pred); | |
266 } | |
267 } | |
268 | |
269 def_loop_exits = BITMAP_ALLOC (&loop_renamer_obstack); | |
145 | 270 for (class loop *loop = def_loop; |
111 | 271 loop != current_loops->tree_root; |
272 loop = loop_outer (loop)) | |
273 bitmap_ior_into (def_loop_exits, loop_exits[loop->num]); | |
274 bitmap_and_into (live_exits, def_loop_exits); | |
275 BITMAP_FREE (def_loop_exits); | |
276 } | |
277 | |
278 /* Add a loop-closing PHI for VAR in basic block EXIT. */ | |
279 | |
280 static void | |
281 add_exit_phi (basic_block exit, tree var) | |
282 { | |
283 gphi *phi; | |
0 | 284 edge e; |
285 edge_iterator ei; | |
286 | |
111 | 287 /* Check that at least one of the edges entering the EXIT block exits |
288 the loop, or a superloop of that loop, that VAR is defined in. */ | |
289 if (flag_checking) | |
0 | 290 { |
111 | 291 gimple *def_stmt = SSA_NAME_DEF_STMT (var); |
292 basic_block def_bb = gimple_bb (def_stmt); | |
293 FOR_EACH_EDGE (e, ei, exit->preds) | |
294 { | |
145 | 295 class loop *aloop = find_common_loop (def_bb->loop_father, |
111 | 296 e->src->loop_father); |
297 if (!flow_bb_inside_loop_p (aloop, e->dest)) | |
298 break; | |
299 } | |
300 gcc_assert (e); | |
0 | 301 } |
302 | |
111 | 303 phi = create_phi_node (NULL_TREE, exit); |
304 create_new_def_for (var, phi, gimple_phi_result_ptr (phi)); | |
305 FOR_EACH_EDGE (e, ei, exit->preds) | |
306 add_phi_arg (phi, var, e, UNKNOWN_LOCATION); | |
0 | 307 |
111 | 308 if (dump_file && (dump_flags & TDF_DETAILS)) |
309 { | |
310 fprintf (dump_file, ";; Created LCSSA PHI: "); | |
311 print_gimple_stmt (dump_file, phi, 0, dump_flags); | |
312 } | |
0 | 313 } |
314 | |
315 /* Add exit phis for VAR that is used in LIVEIN. | |
111 | 316 Exits of the loops are stored in LOOP_EXITS. */ |
0 | 317 |
318 static void | |
111 | 319 add_exit_phis_var (tree var, bitmap use_blocks, bitmap *loop_exits) |
0 | 320 { |
321 unsigned index; | |
111 | 322 bitmap_iterator bi; |
0 | 323 basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (var)); |
111 | 324 bitmap live_exits = BITMAP_ALLOC (&loop_renamer_obstack); |
325 | |
326 gcc_checking_assert (! bitmap_bit_p (use_blocks, def_bb->index)); | |
0 | 327 |
111 | 328 compute_live_loop_exits (live_exits, use_blocks, loop_exits, def_bb); |
0 | 329 |
111 | 330 EXECUTE_IF_SET_IN_BITMAP (live_exits, 0, index, bi) |
331 { | |
332 add_exit_phi (BASIC_BLOCK_FOR_FN (cfun, index), var); | |
333 } | |
0 | 334 |
111 | 335 BITMAP_FREE (live_exits); |
0 | 336 } |
337 | |
338 /* Add exit phis for the names marked in NAMES_TO_RENAME. | |
339 Exits of the loops are stored in EXITS. Sets of blocks where the ssa | |
340 names are used are stored in USE_BLOCKS. */ | |
341 | |
342 static void | |
111 | 343 add_exit_phis (bitmap names_to_rename, bitmap *use_blocks, bitmap *loop_exits) |
0 | 344 { |
345 unsigned i; | |
346 bitmap_iterator bi; | |
347 | |
348 EXECUTE_IF_SET_IN_BITMAP (names_to_rename, 0, i, bi) | |
349 { | |
350 add_exit_phis_var (ssa_name (i), use_blocks[i], loop_exits); | |
351 } | |
352 } | |
353 | |
111 | 354 /* Fill the array of bitmaps LOOP_EXITS with all loop exit edge targets. */ |
0 | 355 |
111 | 356 static void |
357 get_loops_exits (bitmap *loop_exits) | |
0 | 358 { |
145 | 359 class loop *loop; |
111 | 360 unsigned j; |
0 | 361 edge e; |
362 | |
111 | 363 FOR_EACH_LOOP (loop, 0) |
0 | 364 { |
111 | 365 vec<edge> exit_edges = get_loop_exit_edges (loop); |
366 loop_exits[loop->num] = BITMAP_ALLOC (&loop_renamer_obstack); | |
367 FOR_EACH_VEC_ELT (exit_edges, j, e) | |
368 bitmap_set_bit (loop_exits[loop->num], e->dest->index); | |
369 exit_edges.release (); | |
0 | 370 } |
371 } | |
372 | |
373 /* For USE in BB, if it is used outside of the loop it is defined in, | |
374 mark it for rewrite. Record basic block BB where it is used | |
111 | 375 to USE_BLOCKS. Record the ssa name index to NEED_PHIS bitmap. |
376 Note that for USEs in phis, BB should be the src of the edge corresponding to | |
377 the use, rather than the bb containing the phi. */ | |
0 | 378 |
379 static void | |
380 find_uses_to_rename_use (basic_block bb, tree use, bitmap *use_blocks, | |
381 bitmap need_phis) | |
382 { | |
383 unsigned ver; | |
384 basic_block def_bb; | |
145 | 385 class loop *def_loop; |
0 | 386 |
387 if (TREE_CODE (use) != SSA_NAME) | |
388 return; | |
389 | |
390 ver = SSA_NAME_VERSION (use); | |
391 def_bb = gimple_bb (SSA_NAME_DEF_STMT (use)); | |
392 if (!def_bb) | |
393 return; | |
394 def_loop = def_bb->loop_father; | |
395 | |
396 /* If the definition is not inside a loop, it is not interesting. */ | |
397 if (!loop_outer (def_loop)) | |
398 return; | |
399 | |
400 /* If the use is not outside of the loop it is defined in, it is not | |
401 interesting. */ | |
402 if (flow_bb_inside_loop_p (def_loop, bb)) | |
403 return; | |
404 | |
111 | 405 /* If we're seeing VER for the first time, we still have to allocate |
406 a bitmap for its uses. */ | |
407 if (bitmap_set_bit (need_phis, ver)) | |
408 use_blocks[ver] = BITMAP_ALLOC (&loop_renamer_obstack); | |
0 | 409 bitmap_set_bit (use_blocks[ver], bb->index); |
410 } | |
411 | |
111 | 412 /* For uses matching USE_FLAGS in STMT, mark names that are used outside of the |
413 loop they are defined to rewrite. Record the set of blocks in which the ssa | |
414 names are used to USE_BLOCKS, and the ssa names themselves to NEED_PHIS. */ | |
0 | 415 |
416 static void | |
111 | 417 find_uses_to_rename_stmt (gimple *stmt, bitmap *use_blocks, bitmap need_phis, |
418 int use_flags) | |
0 | 419 { |
420 ssa_op_iter iter; | |
421 tree var; | |
422 basic_block bb = gimple_bb (stmt); | |
423 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
424 if (is_gimple_debug (stmt)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
425 return; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
426 |
111 | 427 /* FOR_EACH_SSA_TREE_OPERAND iterator does not allows SSA_OP_VIRTUAL_USES |
428 only. */ | |
429 if (use_flags == SSA_OP_VIRTUAL_USES) | |
430 { | |
431 tree vuse = gimple_vuse (stmt); | |
432 if (vuse != NULL_TREE) | |
433 find_uses_to_rename_use (bb, gimple_vuse (stmt), use_blocks, need_phis); | |
434 } | |
435 else | |
436 FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, use_flags) | |
437 find_uses_to_rename_use (bb, var, use_blocks, need_phis); | |
0 | 438 } |
439 | |
111 | 440 /* Marks names matching USE_FLAGS that are used in BB and outside of the loop |
441 they are defined in for rewrite. Records the set of blocks in which the ssa | |
442 names are used to USE_BLOCKS. Record the SSA names that will | |
0 | 443 need exit PHIs in NEED_PHIS. */ |
444 | |
445 static void | |
111 | 446 find_uses_to_rename_bb (basic_block bb, bitmap *use_blocks, bitmap need_phis, |
447 int use_flags) | |
0 | 448 { |
449 edge e; | |
450 edge_iterator ei; | |
111 | 451 bool do_virtuals = (use_flags & SSA_OP_VIRTUAL_USES) != 0; |
452 bool do_nonvirtuals = (use_flags & SSA_OP_USE) != 0; | |
0 | 453 |
454 FOR_EACH_EDGE (e, ei, bb->succs) | |
111 | 455 for (gphi_iterator bsi = gsi_start_phis (e->dest); !gsi_end_p (bsi); |
456 gsi_next (&bsi)) | |
457 { | |
458 gphi *phi = bsi.phi (); | |
459 bool virtual_p = virtual_operand_p (gimple_phi_result (phi)); | |
460 if ((virtual_p && do_virtuals) | |
461 || (!virtual_p && do_nonvirtuals)) | |
462 find_uses_to_rename_use (bb, PHI_ARG_DEF_FROM_EDGE (phi, e), | |
463 use_blocks, need_phis); | |
464 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
465 |
111 | 466 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); |
467 gsi_next (&bsi)) | |
468 find_uses_to_rename_stmt (gsi_stmt (bsi), use_blocks, need_phis, | |
469 use_flags); | |
0 | 470 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
471 |
111 | 472 /* Marks names matching USE_FLAGS that are used outside of the loop they are |
473 defined in for rewrite. Records the set of blocks in which the ssa names are | |
474 used to USE_BLOCKS. Record the SSA names that will need exit PHIs in | |
475 NEED_PHIS. If CHANGED_BBS is not NULL, scan only blocks in this set. */ | |
0 | 476 |
477 static void | |
111 | 478 find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks, bitmap need_phis, |
479 int use_flags) | |
0 | 480 { |
481 basic_block bb; | |
482 unsigned index; | |
483 bitmap_iterator bi; | |
484 | |
111 | 485 if (changed_bbs) |
486 EXECUTE_IF_SET_IN_BITMAP (changed_bbs, 0, index, bi) | |
487 { | |
488 bb = BASIC_BLOCK_FOR_FN (cfun, index); | |
489 if (bb) | |
490 find_uses_to_rename_bb (bb, use_blocks, need_phis, use_flags); | |
491 } | |
492 else | |
493 FOR_EACH_BB_FN (bb, cfun) | |
494 find_uses_to_rename_bb (bb, use_blocks, need_phis, use_flags); | |
495 } | |
496 | |
497 /* Mark uses of DEF that are used outside of the loop they are defined in for | |
498 rewrite. Record the set of blocks in which the ssa names are used to | |
499 USE_BLOCKS. Record the SSA names that will need exit PHIs in NEED_PHIS. */ | |
500 | |
501 static void | |
502 find_uses_to_rename_def (tree def, bitmap *use_blocks, bitmap need_phis) | |
503 { | |
504 gimple *use_stmt; | |
505 imm_use_iterator imm_iter; | |
506 | |
507 FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def) | |
0 | 508 { |
111 | 509 if (is_gimple_debug (use_stmt)) |
510 continue; | |
511 | |
512 basic_block use_bb = gimple_bb (use_stmt); | |
513 | |
514 use_operand_p use_p; | |
515 FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) | |
0 | 516 { |
111 | 517 if (gimple_code (use_stmt) == GIMPLE_PHI) |
518 { | |
519 edge e = gimple_phi_arg_edge (as_a <gphi *> (use_stmt), | |
520 PHI_ARG_INDEX_FROM_USE (use_p)); | |
521 use_bb = e->src; | |
522 } | |
523 find_uses_to_rename_use (use_bb, USE_FROM_PTR (use_p), use_blocks, | |
524 need_phis); | |
0 | 525 } |
526 } | |
111 | 527 } |
528 | |
529 /* Marks names matching USE_FLAGS that are defined in LOOP and used outside of | |
530 it for rewrite. Records the set of blocks in which the ssa names are used to | |
531 USE_BLOCKS. Record the SSA names that will need exit PHIs in NEED_PHIS. */ | |
532 | |
533 static void | |
145 | 534 find_uses_to_rename_in_loop (class loop *loop, bitmap *use_blocks, |
111 | 535 bitmap need_phis, int use_flags) |
536 { | |
537 bool do_virtuals = (use_flags & SSA_OP_VIRTUAL_USES) != 0; | |
538 bool do_nonvirtuals = (use_flags & SSA_OP_USE) != 0; | |
539 int def_flags = ((do_virtuals ? SSA_OP_VIRTUAL_DEFS : 0) | |
540 | (do_nonvirtuals ? SSA_OP_DEF : 0)); | |
541 | |
542 | |
543 basic_block *bbs = get_loop_body (loop); | |
544 | |
545 for (unsigned int i = 0; i < loop->num_nodes; i++) | |
0 | 546 { |
111 | 547 basic_block bb = bbs[i]; |
548 | |
549 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi); | |
550 gsi_next (&bsi)) | |
551 { | |
552 gphi *phi = bsi.phi (); | |
553 tree res = gimple_phi_result (phi); | |
554 bool virtual_p = virtual_operand_p (res); | |
555 if ((virtual_p && do_virtuals) | |
556 || (!virtual_p && do_nonvirtuals)) | |
557 find_uses_to_rename_def (res, use_blocks, need_phis); | |
558 } | |
559 | |
560 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); | |
561 gsi_next (&bsi)) | |
0 | 562 { |
111 | 563 gimple *stmt = gsi_stmt (bsi); |
564 /* FOR_EACH_SSA_TREE_OPERAND iterator does not allows | |
565 SSA_OP_VIRTUAL_DEFS only. */ | |
566 if (def_flags == SSA_OP_VIRTUAL_DEFS) | |
567 { | |
568 tree vdef = gimple_vdef (stmt); | |
569 if (vdef != NULL) | |
570 find_uses_to_rename_def (vdef, use_blocks, need_phis); | |
571 } | |
572 else | |
573 { | |
574 tree var; | |
575 ssa_op_iter iter; | |
576 FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, def_flags) | |
577 find_uses_to_rename_def (var, use_blocks, need_phis); | |
578 } | |
0 | 579 } |
580 } | |
111 | 581 |
582 XDELETEVEC (bbs); | |
0 | 583 } |
584 | |
585 /* Rewrites the program into a loop closed ssa form -- i.e. inserts extra | |
586 phi nodes to ensure that no variable is used outside the loop it is | |
587 defined in. | |
588 | |
589 This strengthening of the basic ssa form has several advantages: | |
590 | |
591 1) Updating it during unrolling/peeling/versioning is trivial, since | |
592 we do not need to care about the uses outside of the loop. | |
111 | 593 The same applies to virtual operands which are also rewritten into |
594 loop closed SSA form. Note that virtual operands are always live | |
595 until function exit. | |
0 | 596 2) The behavior of all uses of an induction variable is the same. |
597 Without this, you need to distinguish the case when the variable | |
598 is used outside of the loop it is defined in, for example | |
599 | |
600 for (i = 0; i < 100; i++) | |
601 { | |
602 for (j = 0; j < 100; j++) | |
603 { | |
604 k = i + j; | |
605 use1 (k); | |
606 } | |
607 use2 (k); | |
608 } | |
609 | |
610 Looking from the outer loop with the normal SSA form, the first use of k | |
611 is not well-behaved, while the second one is an induction variable with | |
612 base 99 and step 1. | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
613 |
111 | 614 If LOOP is non-null, only rewrite uses that have defs in LOOP. Otherwise, |
615 if CHANGED_BBS is not NULL, we look for uses outside loops only in the | |
616 basic blocks in this set. | |
617 | |
618 USE_FLAGS allows us to specify whether we want virtual, non-virtual or | |
619 both variables rewritten. | |
0 | 620 |
621 UPDATE_FLAG is used in the call to update_ssa. See | |
622 TODO_update_ssa* for documentation. */ | |
623 | |
624 void | |
111 | 625 rewrite_into_loop_closed_ssa_1 (bitmap changed_bbs, unsigned update_flag, |
145 | 626 int use_flags, class loop *loop) |
0 | 627 { |
628 bitmap *use_blocks; | |
629 bitmap names_to_rename; | |
630 | |
631 loops_state_set (LOOP_CLOSED_SSA); | |
111 | 632 if (number_of_loops (cfun) <= 1) |
0 | 633 return; |
634 | |
635 /* If the pass has caused the SSA form to be out-of-date, update it | |
636 now. */ | |
111 | 637 if (update_flag != 0) |
638 update_ssa (update_flag); | |
639 else if (flag_checking) | |
640 verify_ssa (true, true); | |
641 | |
642 bitmap_obstack_initialize (&loop_renamer_obstack); | |
0 | 643 |
111 | 644 names_to_rename = BITMAP_ALLOC (&loop_renamer_obstack); |
0 | 645 |
111 | 646 /* Uses of names to rename. We don't have to initialize this array, |
647 because we know that we will only have entries for the SSA names | |
648 in NAMES_TO_RENAME. */ | |
649 use_blocks = XNEWVEC (bitmap, num_ssa_names); | |
0 | 650 |
111 | 651 if (loop != NULL) |
652 { | |
653 gcc_assert (changed_bbs == NULL); | |
654 find_uses_to_rename_in_loop (loop, use_blocks, names_to_rename, | |
655 use_flags); | |
656 } | |
657 else | |
658 { | |
659 gcc_assert (loop == NULL); | |
660 find_uses_to_rename (changed_bbs, use_blocks, names_to_rename, use_flags); | |
661 } | |
0 | 662 |
111 | 663 if (!bitmap_empty_p (names_to_rename)) |
664 { | |
665 /* An array of bitmaps where LOOP_EXITS[I] is the set of basic blocks | |
666 that are the destination of an edge exiting loop number I. */ | |
667 bitmap *loop_exits = XNEWVEC (bitmap, number_of_loops (cfun)); | |
668 get_loops_exits (loop_exits); | |
669 | |
670 /* Add the PHI nodes on exits of the loops for the names we need to | |
671 rewrite. */ | |
672 add_exit_phis (names_to_rename, use_blocks, loop_exits); | |
673 | |
674 free (loop_exits); | |
675 | |
676 /* Fix up all the names found to be used outside their original | |
677 loops. */ | |
678 update_ssa (TODO_update_ssa); | |
679 } | |
680 | |
681 bitmap_obstack_release (&loop_renamer_obstack); | |
0 | 682 free (use_blocks); |
683 } | |
684 | |
111 | 685 /* Rewrites the non-virtual defs and uses into a loop closed ssa form. If |
686 CHANGED_BBS is not NULL, we look for uses outside loops only in the basic | |
687 blocks in this set. UPDATE_FLAG is used in the call to update_ssa. See | |
688 TODO_update_ssa* for documentation. */ | |
689 | |
690 void | |
691 rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag) | |
692 { | |
693 rewrite_into_loop_closed_ssa_1 (changed_bbs, update_flag, SSA_OP_USE, NULL); | |
694 } | |
695 | |
696 /* Rewrites virtual defs and uses with def in LOOP into loop closed ssa | |
697 form. */ | |
698 | |
699 void | |
145 | 700 rewrite_virtuals_into_loop_closed_ssa (class loop *loop) |
111 | 701 { |
702 rewrite_into_loop_closed_ssa_1 (NULL, 0, SSA_OP_VIRTUAL_USES, loop); | |
703 } | |
704 | |
705 /* Check invariants of the loop closed ssa form for the def in DEF_BB. */ | |
0 | 706 |
707 static void | |
111 | 708 check_loop_closed_ssa_def (basic_block def_bb, tree def) |
0 | 709 { |
111 | 710 use_operand_p use_p; |
711 imm_use_iterator iterator; | |
712 FOR_EACH_IMM_USE_FAST (use_p, iterator, def) | |
713 { | |
714 if (is_gimple_debug (USE_STMT (use_p))) | |
715 continue; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
716 |
111 | 717 basic_block use_bb = gimple_bb (USE_STMT (use_p)); |
718 if (is_a <gphi *> (USE_STMT (use_p))) | |
719 use_bb = EDGE_PRED (use_bb, PHI_ARG_INDEX_FROM_USE (use_p))->src; | |
0 | 720 |
111 | 721 gcc_assert (flow_bb_inside_loop_p (def_bb->loop_father, use_bb)); |
722 } | |
0 | 723 } |
724 | |
111 | 725 /* Checks invariants of loop closed ssa form in BB. */ |
0 | 726 |
727 static void | |
111 | 728 check_loop_closed_ssa_bb (basic_block bb) |
0 | 729 { |
111 | 730 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi); |
731 gsi_next (&bsi)) | |
732 { | |
733 gphi *phi = bsi.phi (); | |
734 | |
735 if (!virtual_operand_p (PHI_RESULT (phi))) | |
736 check_loop_closed_ssa_def (bb, PHI_RESULT (phi)); | |
737 } | |
0 | 738 |
111 | 739 for (gimple_stmt_iterator bsi = gsi_start_nondebug_bb (bb); !gsi_end_p (bsi); |
740 gsi_next_nondebug (&bsi)) | |
741 { | |
742 ssa_op_iter iter; | |
743 tree var; | |
744 gimple *stmt = gsi_stmt (bsi); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
745 |
111 | 746 FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_DEF) |
747 check_loop_closed_ssa_def (bb, var); | |
748 } | |
0 | 749 } |
750 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
751 /* Checks that invariants of the loop closed ssa form are preserved. |
111 | 752 Call verify_ssa when VERIFY_SSA_P is true. Note all loops are checked |
753 if LOOP is NULL, otherwise, only LOOP is checked. */ | |
0 | 754 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
755 DEBUG_FUNCTION void |
145 | 756 verify_loop_closed_ssa (bool verify_ssa_p, class loop *loop) |
0 | 757 { |
111 | 758 if (number_of_loops (cfun) <= 1) |
0 | 759 return; |
760 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
761 if (verify_ssa_p) |
111 | 762 verify_ssa (false, true); |
0 | 763 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
764 timevar_push (TV_VERIFY_LOOP_CLOSED); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
765 |
111 | 766 if (loop == NULL) |
0 | 767 { |
111 | 768 basic_block bb; |
0 | 769 |
111 | 770 FOR_EACH_BB_FN (bb, cfun) |
771 if (bb->loop_father && bb->loop_father->num > 0) | |
772 check_loop_closed_ssa_bb (bb); | |
773 } | |
774 else | |
775 { | |
776 basic_block *bbs = get_loop_body (loop); | |
777 | |
778 for (unsigned i = 0; i < loop->num_nodes; ++i) | |
779 check_loop_closed_ssa_bb (bbs[i]); | |
780 | |
781 free (bbs); | |
0 | 782 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
783 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
784 timevar_pop (TV_VERIFY_LOOP_CLOSED); |
0 | 785 } |
786 | |
787 /* Split loop exit edge EXIT. The things are a bit complicated by a need to | |
145 | 788 preserve the loop closed ssa form. If COPY_CONSTANTS_P is true then |
789 forwarder PHIs are also created for constant arguments. | |
790 The newly created block is returned. */ | |
0 | 791 |
792 basic_block | |
145 | 793 split_loop_exit_edge (edge exit, bool copy_constants_p) |
0 | 794 { |
795 basic_block dest = exit->dest; | |
796 basic_block bb = split_edge (exit); | |
111 | 797 gphi *phi, *new_phi; |
0 | 798 tree new_name, name; |
799 use_operand_p op_p; | |
111 | 800 gphi_iterator psi; |
145 | 801 location_t locus; |
0 | 802 |
803 for (psi = gsi_start_phis (dest); !gsi_end_p (psi); gsi_next (&psi)) | |
804 { | |
111 | 805 phi = psi.phi (); |
0 | 806 op_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (bb)); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
807 locus = gimple_phi_arg_location_from_edge (phi, single_succ_edge (bb)); |
0 | 808 |
809 name = USE_FROM_PTR (op_p); | |
810 | |
811 /* If the argument of the PHI node is a constant, we do not need | |
812 to keep it inside loop. */ | |
145 | 813 if (TREE_CODE (name) != SSA_NAME |
814 && !copy_constants_p) | |
0 | 815 continue; |
816 | |
817 /* Otherwise create an auxiliary phi node that will copy the value | |
818 of the SSA name out of the loop. */ | |
145 | 819 new_name = duplicate_ssa_name (PHI_RESULT (phi), NULL); |
0 | 820 new_phi = create_phi_node (new_name, bb); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
821 add_phi_arg (new_phi, name, exit, locus); |
0 | 822 SET_USE (op_p, new_name); |
823 } | |
824 | |
825 return bb; | |
826 } | |
827 | |
828 /* Returns the basic block in that statements should be emitted for induction | |
829 variables incremented at the end of the LOOP. */ | |
830 | |
831 basic_block | |
145 | 832 ip_end_pos (class loop *loop) |
0 | 833 { |
834 return loop->latch; | |
835 } | |
836 | |
837 /* Returns the basic block in that statements should be emitted for induction | |
838 variables incremented just before exit condition of a LOOP. */ | |
839 | |
840 basic_block | |
145 | 841 ip_normal_pos (class loop *loop) |
0 | 842 { |
111 | 843 gimple *last; |
0 | 844 basic_block bb; |
845 edge exit; | |
846 | |
847 if (!single_pred_p (loop->latch)) | |
848 return NULL; | |
849 | |
850 bb = single_pred (loop->latch); | |
851 last = last_stmt (bb); | |
852 if (!last | |
853 || gimple_code (last) != GIMPLE_COND) | |
854 return NULL; | |
855 | |
856 exit = EDGE_SUCC (bb, 0); | |
857 if (exit->dest == loop->latch) | |
858 exit = EDGE_SUCC (bb, 1); | |
859 | |
860 if (flow_bb_inside_loop_p (loop, exit->dest)) | |
861 return NULL; | |
862 | |
863 return bb; | |
864 } | |
865 | |
866 /* Stores the standard position for induction variable increment in LOOP | |
867 (just before the exit condition if it is available and latch block is empty, | |
868 end of the latch block otherwise) to BSI. INSERT_AFTER is set to true if | |
869 the increment should be inserted after *BSI. */ | |
870 | |
871 void | |
145 | 872 standard_iv_increment_position (class loop *loop, gimple_stmt_iterator *bsi, |
0 | 873 bool *insert_after) |
874 { | |
875 basic_block bb = ip_normal_pos (loop), latch = ip_end_pos (loop); | |
111 | 876 gimple *last = last_stmt (latch); |
0 | 877 |
878 if (!bb | |
879 || (last && gimple_code (last) != GIMPLE_LABEL)) | |
880 { | |
881 *bsi = gsi_last_bb (latch); | |
882 *insert_after = true; | |
883 } | |
884 else | |
885 { | |
886 *bsi = gsi_last_bb (bb); | |
887 *insert_after = false; | |
888 } | |
889 } | |
890 | |
891 /* Copies phi node arguments for duplicated blocks. The index of the first | |
892 duplicated block is FIRST_NEW_BLOCK. */ | |
893 | |
894 static void | |
895 copy_phi_node_args (unsigned first_new_block) | |
896 { | |
897 unsigned i; | |
898 | |
111 | 899 for (i = first_new_block; i < (unsigned) last_basic_block_for_fn (cfun); i++) |
900 BASIC_BLOCK_FOR_FN (cfun, i)->flags |= BB_DUPLICATED; | |
0 | 901 |
111 | 902 for (i = first_new_block; i < (unsigned) last_basic_block_for_fn (cfun); i++) |
903 add_phi_args_after_copy_bb (BASIC_BLOCK_FOR_FN (cfun, i)); | |
0 | 904 |
111 | 905 for (i = first_new_block; i < (unsigned) last_basic_block_for_fn (cfun); i++) |
906 BASIC_BLOCK_FOR_FN (cfun, i)->flags &= ~BB_DUPLICATED; | |
0 | 907 } |
908 | |
909 | |
910 /* The same as cfgloopmanip.c:duplicate_loop_to_header_edge, but also | |
911 updates the PHI nodes at start of the copied region. In order to | |
912 achieve this, only loops whose exits all lead to the same location | |
913 are handled. | |
914 | |
915 Notice that we do not completely update the SSA web after | |
916 duplication. The caller is responsible for calling update_ssa | |
917 after the loop has been duplicated. */ | |
918 | |
919 bool | |
145 | 920 gimple_duplicate_loop_to_header_edge (class loop *loop, edge e, |
0 | 921 unsigned int ndupl, sbitmap wont_exit, |
111 | 922 edge orig, vec<edge> *to_remove, |
0 | 923 int flags) |
924 { | |
925 unsigned first_new_block; | |
926 | |
927 if (!loops_state_satisfies_p (LOOPS_HAVE_SIMPLE_LATCHES)) | |
928 return false; | |
929 if (!loops_state_satisfies_p (LOOPS_HAVE_PREHEADERS)) | |
930 return false; | |
931 | |
111 | 932 first_new_block = last_basic_block_for_fn (cfun); |
0 | 933 if (!duplicate_loop_to_header_edge (loop, e, ndupl, wont_exit, |
934 orig, to_remove, flags)) | |
935 return false; | |
936 | |
937 /* Readd the removed phi args for e. */ | |
938 flush_pending_stmts (e); | |
939 | |
940 /* Copy the phi node arguments. */ | |
941 copy_phi_node_args (first_new_block); | |
942 | |
943 scev_reset (); | |
944 | |
945 return true; | |
946 } | |
947 | |
948 /* Returns true if we can unroll LOOP FACTOR times. Number | |
949 of iterations of the loop is returned in NITER. */ | |
950 | |
951 bool | |
145 | 952 can_unroll_loop_p (class loop *loop, unsigned factor, |
953 class tree_niter_desc *niter) | |
0 | 954 { |
955 edge exit; | |
956 | |
957 /* Check whether unrolling is possible. We only want to unroll loops | |
958 for that we are able to determine number of iterations. We also | |
959 want to split the extra iterations of the loop from its end, | |
960 therefore we require that the loop has precisely one | |
961 exit. */ | |
962 | |
963 exit = single_dom_exit (loop); | |
964 if (!exit) | |
965 return false; | |
966 | |
967 if (!number_of_iterations_exit (loop, exit, niter, false) | |
968 || niter->cmp == ERROR_MARK | |
969 /* Scalar evolutions analysis might have copy propagated | |
970 the abnormal ssa names into these expressions, hence | |
971 emitting the computations based on them during loop | |
972 unrolling might create overlapping life ranges for | |
973 them, and failures in out-of-ssa. */ | |
974 || contains_abnormal_ssa_name_p (niter->may_be_zero) | |
975 || contains_abnormal_ssa_name_p (niter->control.base) | |
976 || contains_abnormal_ssa_name_p (niter->control.step) | |
977 || contains_abnormal_ssa_name_p (niter->bound)) | |
978 return false; | |
979 | |
980 /* And of course, we must be able to duplicate the loop. */ | |
981 if (!can_duplicate_loop_p (loop)) | |
982 return false; | |
983 | |
984 /* The final loop should be small enough. */ | |
985 if (tree_num_loop_insns (loop, &eni_size_weights) * factor | |
145 | 986 > (unsigned) param_max_unrolled_insns) |
0 | 987 return false; |
988 | |
989 return true; | |
990 } | |
991 | |
992 /* Determines the conditions that control execution of LOOP unrolled FACTOR | |
993 times. DESC is number of iterations of LOOP. ENTER_COND is set to | |
994 condition that must be true if the main loop can be entered. | |
995 EXIT_BASE, EXIT_STEP, EXIT_CMP and EXIT_BOUND are set to values describing | |
996 how the exit from the unrolled loop should be controlled. */ | |
997 | |
998 static void | |
145 | 999 determine_exit_conditions (class loop *loop, class tree_niter_desc *desc, |
0 | 1000 unsigned factor, tree *enter_cond, |
1001 tree *exit_base, tree *exit_step, | |
1002 enum tree_code *exit_cmp, tree *exit_bound) | |
1003 { | |
1004 gimple_seq stmts; | |
1005 tree base = desc->control.base; | |
1006 tree step = desc->control.step; | |
1007 tree bound = desc->bound; | |
1008 tree type = TREE_TYPE (step); | |
1009 tree bigstep, delta; | |
1010 tree min = lower_bound_in_type (type, type); | |
1011 tree max = upper_bound_in_type (type, type); | |
1012 enum tree_code cmp = desc->cmp; | |
1013 tree cond = boolean_true_node, assum; | |
1014 | |
111 | 1015 /* For pointers, do the arithmetics in the type of step. */ |
0 | 1016 base = fold_convert (type, base); |
1017 bound = fold_convert (type, bound); | |
1018 | |
1019 *enter_cond = boolean_false_node; | |
1020 *exit_base = NULL_TREE; | |
1021 *exit_step = NULL_TREE; | |
1022 *exit_cmp = ERROR_MARK; | |
1023 *exit_bound = NULL_TREE; | |
1024 gcc_assert (cmp != ERROR_MARK); | |
1025 | |
1026 /* We only need to be correct when we answer question | |
1027 "Do at least FACTOR more iterations remain?" in the unrolled loop. | |
1028 Thus, transforming BASE + STEP * i <> BOUND to | |
1029 BASE + STEP * i < BOUND is ok. */ | |
1030 if (cmp == NE_EXPR) | |
1031 { | |
1032 if (tree_int_cst_sign_bit (step)) | |
1033 cmp = GT_EXPR; | |
1034 else | |
1035 cmp = LT_EXPR; | |
1036 } | |
1037 else if (cmp == LT_EXPR) | |
1038 { | |
1039 gcc_assert (!tree_int_cst_sign_bit (step)); | |
1040 } | |
1041 else if (cmp == GT_EXPR) | |
1042 { | |
1043 gcc_assert (tree_int_cst_sign_bit (step)); | |
1044 } | |
1045 else | |
1046 gcc_unreachable (); | |
1047 | |
1048 /* The main body of the loop may be entered iff: | |
1049 | |
1050 1) desc->may_be_zero is false. | |
1051 2) it is possible to check that there are at least FACTOR iterations | |
1052 of the loop, i.e., BOUND - step * FACTOR does not overflow. | |
1053 3) # of iterations is at least FACTOR */ | |
1054 | |
1055 if (!integer_zerop (desc->may_be_zero)) | |
1056 cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, | |
1057 invert_truthvalue (desc->may_be_zero), | |
1058 cond); | |
1059 | |
1060 bigstep = fold_build2 (MULT_EXPR, type, step, | |
1061 build_int_cst_type (type, factor)); | |
1062 delta = fold_build2 (MINUS_EXPR, type, bigstep, step); | |
1063 if (cmp == LT_EXPR) | |
1064 assum = fold_build2 (GE_EXPR, boolean_type_node, | |
1065 bound, | |
1066 fold_build2 (PLUS_EXPR, type, min, delta)); | |
1067 else | |
1068 assum = fold_build2 (LE_EXPR, boolean_type_node, | |
1069 bound, | |
1070 fold_build2 (PLUS_EXPR, type, max, delta)); | |
1071 cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, assum, cond); | |
1072 | |
1073 bound = fold_build2 (MINUS_EXPR, type, bound, delta); | |
1074 assum = fold_build2 (cmp, boolean_type_node, base, bound); | |
1075 cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, assum, cond); | |
1076 | |
1077 cond = force_gimple_operand (unshare_expr (cond), &stmts, false, NULL_TREE); | |
1078 if (stmts) | |
1079 gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); | |
1080 /* cond now may be a gimple comparison, which would be OK, but also any | |
1081 other gimple rhs (say a && b). In this case we need to force it to | |
1082 operand. */ | |
1083 if (!is_gimple_condexpr (cond)) | |
1084 { | |
1085 cond = force_gimple_operand (cond, &stmts, true, NULL_TREE); | |
1086 if (stmts) | |
1087 gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); | |
1088 } | |
1089 *enter_cond = cond; | |
1090 | |
1091 base = force_gimple_operand (unshare_expr (base), &stmts, true, NULL_TREE); | |
1092 if (stmts) | |
1093 gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); | |
1094 bound = force_gimple_operand (unshare_expr (bound), &stmts, true, NULL_TREE); | |
1095 if (stmts) | |
1096 gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); | |
1097 | |
1098 *exit_base = base; | |
1099 *exit_step = bigstep; | |
1100 *exit_cmp = cmp; | |
1101 *exit_bound = bound; | |
1102 } | |
1103 | |
1104 /* Scales the frequencies of all basic blocks in LOOP that are strictly | |
1105 dominated by BB by NUM/DEN. */ | |
1106 | |
1107 static void | |
145 | 1108 scale_dominated_blocks_in_loop (class loop *loop, basic_block bb, |
131 | 1109 profile_count num, profile_count den) |
0 | 1110 { |
1111 basic_block son; | |
1112 | |
131 | 1113 if (!den.nonzero_p () && !(num == profile_count::zero ())) |
0 | 1114 return; |
1115 | |
1116 for (son = first_dom_son (CDI_DOMINATORS, bb); | |
1117 son; | |
1118 son = next_dom_son (CDI_DOMINATORS, son)) | |
1119 { | |
1120 if (!flow_bb_inside_loop_p (loop, son)) | |
1121 continue; | |
131 | 1122 scale_bbs_frequencies_profile_count (&son, 1, num, den); |
0 | 1123 scale_dominated_blocks_in_loop (loop, son, num, den); |
1124 } | |
1125 } | |
1126 | |
111 | 1127 /* Return estimated niter for LOOP after unrolling by FACTOR times. */ |
1128 | |
1129 gcov_type | |
145 | 1130 niter_for_unrolled_loop (class loop *loop, unsigned factor) |
111 | 1131 { |
1132 gcc_assert (factor != 0); | |
1133 bool profile_p = false; | |
1134 gcov_type est_niter = expected_loop_iterations_unbounded (loop, &profile_p); | |
1135 /* Note that this is really CEIL (est_niter + 1, factor) - 1, where the | |
1136 "+ 1" converts latch iterations to loop iterations and the "- 1" | |
1137 converts back. */ | |
1138 gcov_type new_est_niter = est_niter / factor; | |
1139 | |
131 | 1140 if (est_niter == -1) |
1141 return -1; | |
1142 | |
111 | 1143 /* Without profile feedback, loops for which we do not know a better estimate |
1144 are assumed to roll 10 times. When we unroll such loop, it appears to | |
1145 roll too little, and it may even seem to be cold. To avoid this, we | |
1146 ensure that the created loop appears to roll at least 5 times (but at | |
1147 most as many times as before unrolling). Don't do adjustment if profile | |
1148 feedback is present. */ | |
1149 if (new_est_niter < 5 && !profile_p) | |
1150 { | |
1151 if (est_niter < 5) | |
1152 new_est_niter = est_niter; | |
1153 else | |
1154 new_est_niter = 5; | |
1155 } | |
1156 | |
1157 if (loop->any_upper_bound) | |
1158 { | |
1159 /* As above, this is really CEIL (upper_bound + 1, factor) - 1. */ | |
1160 widest_int bound = wi::udiv_floor (loop->nb_iterations_upper_bound, | |
1161 factor); | |
1162 if (wi::ltu_p (bound, new_est_niter)) | |
1163 new_est_niter = bound.to_uhwi (); | |
1164 } | |
1165 | |
1166 return new_est_niter; | |
1167 } | |
1168 | |
0 | 1169 /* Unroll LOOP FACTOR times. DESC describes number of iterations of LOOP. |
1170 EXIT is the exit of the loop to that DESC corresponds. | |
1171 | |
1172 If N is number of iterations of the loop and MAY_BE_ZERO is the condition | |
1173 under that loop exits in the first iteration even if N != 0, | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1174 |
0 | 1175 while (1) |
1176 { | |
1177 x = phi (init, next); | |
1178 | |
1179 pre; | |
1180 if (st) | |
1181 break; | |
1182 post; | |
1183 } | |
1184 | |
1185 becomes (with possibly the exit conditions formulated a bit differently, | |
1186 avoiding the need to create a new iv): | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1187 |
0 | 1188 if (MAY_BE_ZERO || N < FACTOR) |
1189 goto rest; | |
1190 | |
1191 do | |
1192 { | |
1193 x = phi (init, next); | |
1194 | |
1195 pre; | |
1196 post; | |
1197 pre; | |
1198 post; | |
1199 ... | |
1200 pre; | |
1201 post; | |
1202 N -= FACTOR; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1203 |
0 | 1204 } while (N >= FACTOR); |
1205 | |
1206 rest: | |
1207 init' = phi (init, x); | |
1208 | |
1209 while (1) | |
1210 { | |
1211 x = phi (init', next); | |
1212 | |
1213 pre; | |
1214 if (st) | |
1215 break; | |
1216 post; | |
1217 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1218 |
0 | 1219 Before the loop is unrolled, TRANSFORM is called for it (only for the |
1220 unrolled loop, but not for its versioned copy). DATA is passed to | |
1221 TRANSFORM. */ | |
1222 | |
1223 /* Probability in % that the unrolled loop is entered. Just a guess. */ | |
1224 #define PROB_UNROLLED_LOOP_ENTERED 90 | |
1225 | |
1226 void | |
145 | 1227 tree_transform_and_unroll_loop (class loop *loop, unsigned factor, |
1228 edge exit, class tree_niter_desc *desc, | |
0 | 1229 transform_callback transform, |
1230 void *data) | |
1231 { | |
111 | 1232 gcond *exit_if; |
0 | 1233 tree ctr_before, ctr_after; |
1234 tree enter_main_cond, exit_base, exit_step, exit_bound; | |
1235 enum tree_code exit_cmp; | |
111 | 1236 gphi *phi_old_loop, *phi_new_loop, *phi_rest; |
1237 gphi_iterator psi_old_loop, psi_new_loop; | |
1238 tree init, next, new_init; | |
145 | 1239 class loop *new_loop; |
0 | 1240 basic_block rest, exit_bb; |
1241 edge old_entry, new_entry, old_latch, precond_edge, new_exit; | |
1242 edge new_nonexit, e; | |
1243 gimple_stmt_iterator bsi; | |
1244 use_operand_p op; | |
1245 bool ok; | |
111 | 1246 unsigned i; |
1247 profile_probability prob, prob_entry, scale_unrolled; | |
1248 profile_count freq_e, freq_h; | |
1249 gcov_type new_est_niter = niter_for_unrolled_loop (loop, factor); | |
0 | 1250 unsigned irr = loop_preheader_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP; |
111 | 1251 auto_vec<edge> to_remove; |
0 | 1252 |
1253 determine_exit_conditions (loop, desc, factor, | |
1254 &enter_main_cond, &exit_base, &exit_step, | |
1255 &exit_cmp, &exit_bound); | |
1256 | |
1257 /* Let us assume that the unrolled loop is quite likely to be entered. */ | |
1258 if (integer_nonzerop (enter_main_cond)) | |
111 | 1259 prob_entry = profile_probability::always (); |
0 | 1260 else |
111 | 1261 prob_entry = profile_probability::guessed_always () |
1262 .apply_scale (PROB_UNROLLED_LOOP_ENTERED, 100); | |
0 | 1263 |
1264 /* The values for scales should keep profile consistent, and somewhat close | |
1265 to correct. | |
1266 | |
1267 TODO: The current value of SCALE_REST makes it appear that the loop that | |
1268 is created by splitting the remaining iterations of the unrolled loop is | |
1269 executed the same number of times as the original loop, and with the same | |
1270 frequencies, which is obviously wrong. This does not appear to cause | |
1271 problems, so we do not bother with fixing it for now. To make the profile | |
1272 correct, we would need to change the probability of the exit edge of the | |
1273 loop, and recompute the distribution of frequencies in its body because | |
1274 of this change (scale the frequencies of blocks before and after the exit | |
1275 by appropriate factors). */ | |
1276 scale_unrolled = prob_entry; | |
1277 | |
111 | 1278 new_loop = loop_version (loop, enter_main_cond, NULL, prob_entry, |
1279 prob_entry.invert (), scale_unrolled, | |
1280 profile_probability::guessed_always (), | |
1281 true); | |
0 | 1282 gcc_assert (new_loop != NULL); |
1283 update_ssa (TODO_update_ssa); | |
1284 | |
1285 /* Prepare the cfg and update the phi nodes. Move the loop exit to the | |
1286 loop latch (and make its condition dummy, for the moment). */ | |
1287 rest = loop_preheader_edge (new_loop)->src; | |
1288 precond_edge = single_pred_edge (rest); | |
1289 split_edge (loop_latch_edge (loop)); | |
1290 exit_bb = single_pred (loop->latch); | |
1291 | |
1292 /* Since the exit edge will be removed, the frequency of all the blocks | |
1293 in the loop that are dominated by it must be scaled by | |
1294 1 / (1 - exit->probability). */ | |
111 | 1295 if (exit->probability.initialized_p ()) |
1296 scale_dominated_blocks_in_loop (loop, exit->src, | |
1297 /* We are scaling up here so probability | |
1298 does not fit. */ | |
131 | 1299 loop->header->count, |
1300 loop->header->count | |
1301 - loop->header->count.apply_probability | |
1302 (exit->probability)); | |
0 | 1303 |
1304 bsi = gsi_last_bb (exit_bb); | |
1305 exit_if = gimple_build_cond (EQ_EXPR, integer_zero_node, | |
1306 integer_zero_node, | |
1307 NULL_TREE, NULL_TREE); | |
1308 | |
1309 gsi_insert_after (&bsi, exit_if, GSI_NEW_STMT); | |
1310 new_exit = make_edge (exit_bb, rest, EDGE_FALSE_VALUE | irr); | |
1311 rescan_loop_exit (new_exit, true, false); | |
1312 | |
1313 /* Set the probability of new exit to the same of the old one. Fix | |
1314 the frequency of the latch block, by scaling it back by | |
1315 1 - exit->probability. */ | |
1316 new_exit->probability = exit->probability; | |
1317 new_nonexit = single_pred_edge (loop->latch); | |
111 | 1318 new_nonexit->probability = exit->probability.invert (); |
0 | 1319 new_nonexit->flags = EDGE_TRUE_VALUE; |
111 | 1320 if (new_nonexit->probability.initialized_p ()) |
1321 scale_bbs_frequencies (&loop->latch, 1, new_nonexit->probability); | |
0 | 1322 |
1323 old_entry = loop_preheader_edge (loop); | |
1324 new_entry = loop_preheader_edge (new_loop); | |
1325 old_latch = loop_latch_edge (loop); | |
1326 for (psi_old_loop = gsi_start_phis (loop->header), | |
1327 psi_new_loop = gsi_start_phis (new_loop->header); | |
1328 !gsi_end_p (psi_old_loop); | |
1329 gsi_next (&psi_old_loop), gsi_next (&psi_new_loop)) | |
1330 { | |
111 | 1331 phi_old_loop = psi_old_loop.phi (); |
1332 phi_new_loop = psi_new_loop.phi (); | |
0 | 1333 |
1334 init = PHI_ARG_DEF_FROM_EDGE (phi_old_loop, old_entry); | |
1335 op = PHI_ARG_DEF_PTR_FROM_EDGE (phi_new_loop, new_entry); | |
1336 gcc_assert (operand_equal_for_phi_arg_p (init, USE_FROM_PTR (op))); | |
1337 next = PHI_ARG_DEF_FROM_EDGE (phi_old_loop, old_latch); | |
1338 | |
1339 /* Prefer using original variable as a base for the new ssa name. | |
1340 This is necessary for virtual ops, and useful in order to avoid | |
1341 losing debug info for real ops. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1342 if (TREE_CODE (next) == SSA_NAME |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1343 && useless_type_conversion_p (TREE_TYPE (next), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1344 TREE_TYPE (init))) |
111 | 1345 new_init = copy_ssa_name (next); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1346 else if (TREE_CODE (init) == SSA_NAME |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1347 && useless_type_conversion_p (TREE_TYPE (init), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1348 TREE_TYPE (next))) |
111 | 1349 new_init = copy_ssa_name (init); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1350 else if (useless_type_conversion_p (TREE_TYPE (next), TREE_TYPE (init))) |
111 | 1351 new_init = make_temp_ssa_name (TREE_TYPE (next), NULL, "unrinittmp"); |
0 | 1352 else |
111 | 1353 new_init = make_temp_ssa_name (TREE_TYPE (init), NULL, "unrinittmp"); |
0 | 1354 |
1355 phi_rest = create_phi_node (new_init, rest); | |
1356 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1357 add_phi_arg (phi_rest, init, precond_edge, UNKNOWN_LOCATION); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1358 add_phi_arg (phi_rest, next, new_exit, UNKNOWN_LOCATION); |
0 | 1359 SET_USE (op, new_init); |
1360 } | |
1361 | |
1362 remove_path (exit); | |
1363 | |
1364 /* Transform the loop. */ | |
1365 if (transform) | |
1366 (*transform) (loop, data); | |
1367 | |
1368 /* Unroll the loop and remove the exits in all iterations except for the | |
1369 last one. */ | |
111 | 1370 auto_sbitmap wont_exit (factor); |
1371 bitmap_ones (wont_exit); | |
1372 bitmap_clear_bit (wont_exit, factor - 1); | |
0 | 1373 |
1374 ok = gimple_duplicate_loop_to_header_edge | |
1375 (loop, loop_latch_edge (loop), factor - 1, | |
1376 wont_exit, new_exit, &to_remove, DLTHE_FLAG_UPDATE_FREQ); | |
1377 gcc_assert (ok); | |
1378 | |
111 | 1379 FOR_EACH_VEC_ELT (to_remove, i, e) |
0 | 1380 { |
1381 ok = remove_path (e); | |
1382 gcc_assert (ok); | |
1383 } | |
1384 update_ssa (TODO_update_ssa); | |
1385 | |
1386 /* Ensure that the frequencies in the loop match the new estimated | |
1387 number of iterations, and change the probability of the new | |
1388 exit edge. */ | |
111 | 1389 |
1390 freq_h = loop->header->count; | |
1391 freq_e = (loop_preheader_edge (loop))->count (); | |
131 | 1392 if (freq_h.nonzero_p ()) |
111 | 1393 { |
1394 /* Avoid dropping loop body profile counter to 0 because of zero count | |
1395 in loop's preheader. */ | |
131 | 1396 if (freq_h.nonzero_p () && !(freq_e == profile_count::zero ())) |
1397 freq_e = freq_e.force_nonzero (); | |
111 | 1398 scale_loop_frequencies (loop, freq_e.probability_in (freq_h)); |
1399 } | |
0 | 1400 |
1401 exit_bb = single_pred (loop->latch); | |
1402 new_exit = find_edge (exit_bb, rest); | |
111 | 1403 new_exit->probability = profile_probability::always () |
1404 .apply_scale (1, new_est_niter + 1); | |
0 | 1405 |
111 | 1406 rest->count += new_exit->count (); |
0 | 1407 |
1408 new_nonexit = single_pred_edge (loop->latch); | |
1409 prob = new_nonexit->probability; | |
111 | 1410 new_nonexit->probability = new_exit->probability.invert (); |
1411 prob = new_nonexit->probability / prob; | |
1412 if (prob.initialized_p ()) | |
1413 scale_bbs_frequencies (&loop->latch, 1, prob); | |
0 | 1414 |
1415 /* Finally create the new counter for number of iterations and add the new | |
1416 exit instruction. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1417 bsi = gsi_last_nondebug_bb (exit_bb); |
111 | 1418 exit_if = as_a <gcond *> (gsi_stmt (bsi)); |
0 | 1419 create_iv (exit_base, exit_step, NULL_TREE, loop, |
1420 &bsi, false, &ctr_before, &ctr_after); | |
1421 gimple_cond_set_code (exit_if, exit_cmp); | |
1422 gimple_cond_set_lhs (exit_if, ctr_after); | |
1423 gimple_cond_set_rhs (exit_if, exit_bound); | |
1424 update_stmt (exit_if); | |
1425 | |
111 | 1426 checking_verify_flow_info (); |
1427 checking_verify_loop_structure (); | |
1428 checking_verify_loop_closed_ssa (true, loop); | |
1429 checking_verify_loop_closed_ssa (true, new_loop); | |
0 | 1430 } |
1431 | |
1432 /* Wrapper over tree_transform_and_unroll_loop for case we do not | |
1433 want to transform the loop before unrolling. The meaning | |
1434 of the arguments is the same as for tree_transform_and_unroll_loop. */ | |
1435 | |
1436 void | |
145 | 1437 tree_unroll_loop (class loop *loop, unsigned factor, |
1438 edge exit, class tree_niter_desc *desc) | |
0 | 1439 { |
1440 tree_transform_and_unroll_loop (loop, factor, exit, desc, | |
1441 NULL, NULL); | |
1442 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1443 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1444 /* Rewrite the phi node at position PSI in function of the main |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1445 induction variable MAIN_IV and insert the generated code at GSI. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1446 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1447 static void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1448 rewrite_phi_with_iv (loop_p loop, |
111 | 1449 gphi_iterator *psi, |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1450 gimple_stmt_iterator *gsi, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1451 tree main_iv) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1452 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1453 affine_iv iv; |
111 | 1454 gassign *stmt; |
1455 gphi *phi = psi->phi (); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1456 tree atype, mtype, val, res = PHI_RESULT (phi); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1457 |
111 | 1458 if (virtual_operand_p (res) || res == main_iv) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1459 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1460 gsi_next (psi); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1461 return; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1462 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1463 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1464 if (!simple_iv (loop, loop, res, &iv, true)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1465 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1466 gsi_next (psi); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1467 return; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1468 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1469 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1470 remove_phi_node (psi, false); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1471 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1472 atype = TREE_TYPE (res); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1473 mtype = POINTER_TYPE_P (atype) ? sizetype : atype; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1474 val = fold_build2 (MULT_EXPR, mtype, unshare_expr (iv.step), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1475 fold_convert (mtype, main_iv)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1476 val = fold_build2 (POINTER_TYPE_P (atype) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1477 ? POINTER_PLUS_EXPR : PLUS_EXPR, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1478 atype, unshare_expr (iv.base), val); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1479 val = force_gimple_operand_gsi (gsi, val, false, NULL_TREE, true, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1480 GSI_SAME_STMT); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1481 stmt = gimple_build_assign (res, val); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1482 gsi_insert_before (gsi, stmt, GSI_SAME_STMT); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1483 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1484 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1485 /* Rewrite all the phi nodes of LOOP in function of the main induction |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1486 variable MAIN_IV. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1487 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1488 static void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1489 rewrite_all_phi_nodes_with_iv (loop_p loop, tree main_iv) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1490 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1491 unsigned i; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1492 basic_block *bbs = get_loop_body_in_dom_order (loop); |
111 | 1493 gphi_iterator psi; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1494 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1495 for (i = 0; i < loop->num_nodes; i++) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1496 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1497 basic_block bb = bbs[i]; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1498 gimple_stmt_iterator gsi = gsi_after_labels (bb); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1499 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1500 if (bb->loop_father != loop) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1501 continue; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1502 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1503 for (psi = gsi_start_phis (bb); !gsi_end_p (psi); ) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1504 rewrite_phi_with_iv (loop, &psi, &gsi, main_iv); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1505 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1506 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1507 free (bbs); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1508 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1509 |
111 | 1510 /* Bases all the induction variables in LOOP on a single induction variable |
1511 (with base 0 and step 1), whose final value is compared with *NIT. When the | |
1512 IV type precision has to be larger than *NIT type precision, *NIT is | |
1513 converted to the larger type, the conversion code is inserted before the | |
1514 loop, and *NIT is updated to the new definition. When BUMP_IN_LATCH is true, | |
1515 the induction variable is incremented in the loop latch, otherwise it is | |
1516 incremented in the loop header. Return the induction variable that was | |
1517 created. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1518 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1519 tree |
145 | 1520 canonicalize_loop_ivs (class loop *loop, tree *nit, bool bump_in_latch) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1521 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1522 unsigned precision = TYPE_PRECISION (TREE_TYPE (*nit)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1523 unsigned original_precision = precision; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1524 tree type, var_before; |
111 | 1525 gimple_stmt_iterator gsi; |
1526 gphi_iterator psi; | |
1527 gcond *stmt; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1528 edge exit = single_dom_exit (loop); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1529 gimple_seq stmts; |
111 | 1530 bool unsigned_p = false; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1531 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1532 for (psi = gsi_start_phis (loop->header); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1533 !gsi_end_p (psi); gsi_next (&psi)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1534 { |
111 | 1535 gphi *phi = psi.phi (); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1536 tree res = PHI_RESULT (phi); |
111 | 1537 bool uns; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1538 |
111 | 1539 type = TREE_TYPE (res); |
1540 if (virtual_operand_p (res) | |
1541 || (!INTEGRAL_TYPE_P (type) | |
1542 && !POINTER_TYPE_P (type)) | |
1543 || TYPE_PRECISION (type) < precision) | |
1544 continue; | |
1545 | |
1546 uns = POINTER_TYPE_P (type) | TYPE_UNSIGNED (type); | |
1547 | |
1548 if (TYPE_PRECISION (type) > precision) | |
1549 unsigned_p = uns; | |
1550 else | |
1551 unsigned_p |= uns; | |
1552 | |
1553 precision = TYPE_PRECISION (type); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1554 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1555 |
111 | 1556 scalar_int_mode mode = smallest_int_mode_for_size (precision); |
1557 precision = GET_MODE_PRECISION (mode); | |
1558 type = build_nonstandard_integer_type (precision, unsigned_p); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1559 |
131 | 1560 if (original_precision != precision |
1561 || TYPE_UNSIGNED (TREE_TYPE (*nit)) != unsigned_p) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1562 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1563 *nit = fold_convert (type, *nit); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1564 *nit = force_gimple_operand (*nit, &stmts, true, NULL_TREE); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1565 if (stmts) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1566 gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1567 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1568 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1569 if (bump_in_latch) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1570 gsi = gsi_last_bb (loop->latch); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1571 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1572 gsi = gsi_last_nondebug_bb (loop->header); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1573 create_iv (build_int_cst_type (type, 0), build_int_cst (type, 1), NULL_TREE, |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1574 loop, &gsi, bump_in_latch, &var_before, NULL); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1575 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1576 rewrite_all_phi_nodes_with_iv (loop, var_before); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1577 |
111 | 1578 stmt = as_a <gcond *> (last_stmt (exit->src)); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1579 /* Make the loop exit if the control condition is not satisfied. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1580 if (exit->flags & EDGE_TRUE_VALUE) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1581 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1582 edge te, fe; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1583 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1584 extract_true_false_edges_from_block (exit->src, &te, &fe); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1585 te->flags = EDGE_FALSE_VALUE; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1586 fe->flags = EDGE_TRUE_VALUE; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1587 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1588 gimple_cond_set_code (stmt, LT_EXPR); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1589 gimple_cond_set_lhs (stmt, var_before); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1590 gimple_cond_set_rhs (stmt, *nit); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1591 update_stmt (stmt); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1592 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1593 return var_before; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1594 } |