annotate gcc/tree-ssa-loop-unswitch.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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Loop unswitching.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
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
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
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
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 under the terms of the GNU General Public License as published by the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 Free Software Foundation; either version 3, or (at your option) any
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
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
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
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
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 #include "config.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #include "coretypes.h"
111
kono
parents: 67
diff changeset
23 #include "backend.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 #include "tree.h"
111
kono
parents: 67
diff changeset
25 #include "gimple.h"
kono
parents: 67
diff changeset
26 #include "tree-pass.h"
kono
parents: 67
diff changeset
27 #include "ssa.h"
kono
parents: 67
diff changeset
28 #include "fold-const.h"
kono
parents: 67
diff changeset
29 #include "gimplify.h"
kono
parents: 67
diff changeset
30 #include "tree-cfg.h"
kono
parents: 67
diff changeset
31 #include "tree-ssa.h"
kono
parents: 67
diff changeset
32 #include "tree-ssa-loop-niter.h"
kono
parents: 67
diff changeset
33 #include "tree-ssa-loop.h"
kono
parents: 67
diff changeset
34 #include "tree-into-ssa.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 #include "cfgloop.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 #include "tree-inline.h"
111
kono
parents: 67
diff changeset
37 #include "gimple-iterator.h"
kono
parents: 67
diff changeset
38 #include "cfghooks.h"
kono
parents: 67
diff changeset
39 #include "tree-ssa-loop-manip.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 /* This file implements the loop unswitching, i.e. transformation of loops like
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 while (A)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 if (inv)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 B;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 X;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 if (!inv)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 C;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 where inv is the loop invariant, into
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 if (inv)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 while (A)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 B;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 X;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 while (A)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68 X;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 C;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 Inv is considered invariant iff the values it compares are both invariant;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 tree-ssa-loop-im.c ensures that all the suitable conditions are in this
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 shape. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
77 static class loop *tree_unswitch_loop (class loop *, basic_block, tree);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
78 static bool tree_unswitch_single_loop (class loop *, int);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
79 static tree tree_may_unswitch_on (basic_block, class loop *);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
80 static bool tree_unswitch_outer_loop (class loop *);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
81 static edge find_loop_guard (class loop *);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
82 static bool empty_bb_without_guard_p (class loop *, basic_block);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
83 static bool used_outside_loop_p (class loop *, tree);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
84 static void hoist_guard (class loop *, edge);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
85 static bool check_exit_phi (class loop *);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
86 static tree get_vop_from_header (class loop *);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 /* Main entry point. Perform loop unswitching on all suitable loops. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
89
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
90 unsigned int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 tree_ssa_unswitch_loops (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
93 class loop *loop;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
94 bool changed = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
95
111
kono
parents: 67
diff changeset
96 /* Go through all loops starting from innermost. */
kono
parents: 67
diff changeset
97 FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
98 {
111
kono
parents: 67
diff changeset
99 if (!loop->inner)
kono
parents: 67
diff changeset
100 /* Unswitch innermost loop. */
kono
parents: 67
diff changeset
101 changed |= tree_unswitch_single_loop (loop, 0);
kono
parents: 67
diff changeset
102 else
kono
parents: 67
diff changeset
103 changed |= tree_unswitch_outer_loop (loop);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 if (changed)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 return TODO_cleanup_cfg;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 return 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110
111
kono
parents: 67
diff changeset
111 /* Return TRUE if an SSA_NAME maybe undefined and is therefore
kono
parents: 67
diff changeset
112 unsuitable for unswitching. STMT is the statement we are
kono
parents: 67
diff changeset
113 considering for unswitching and LOOP is the loop it appears in. */
kono
parents: 67
diff changeset
114
kono
parents: 67
diff changeset
115 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
116 is_maybe_undefined (const tree name, gimple *stmt, class loop *loop)
111
kono
parents: 67
diff changeset
117 {
kono
parents: 67
diff changeset
118 /* The loop header is the only block we can trivially determine that
kono
parents: 67
diff changeset
119 will always be executed. If the comparison is in the loop
kono
parents: 67
diff changeset
120 header, we know it's OK to unswitch on it. */
kono
parents: 67
diff changeset
121 if (gimple_bb (stmt) == loop->header)
kono
parents: 67
diff changeset
122 return false;
kono
parents: 67
diff changeset
123
kono
parents: 67
diff changeset
124 auto_bitmap visited_ssa;
kono
parents: 67
diff changeset
125 auto_vec<tree> worklist;
kono
parents: 67
diff changeset
126 worklist.safe_push (name);
kono
parents: 67
diff changeset
127 bitmap_set_bit (visited_ssa, SSA_NAME_VERSION (name));
kono
parents: 67
diff changeset
128 while (!worklist.is_empty ())
kono
parents: 67
diff changeset
129 {
kono
parents: 67
diff changeset
130 tree t = worklist.pop ();
kono
parents: 67
diff changeset
131
kono
parents: 67
diff changeset
132 /* If it's obviously undefined, avoid further computations. */
kono
parents: 67
diff changeset
133 if (ssa_undefined_value_p (t, true))
kono
parents: 67
diff changeset
134 return true;
kono
parents: 67
diff changeset
135
kono
parents: 67
diff changeset
136 if (ssa_defined_default_def_p (t))
kono
parents: 67
diff changeset
137 continue;
kono
parents: 67
diff changeset
138
kono
parents: 67
diff changeset
139 gimple *def = SSA_NAME_DEF_STMT (t);
kono
parents: 67
diff changeset
140
kono
parents: 67
diff changeset
141 /* Check that all the PHI args are fully defined. */
kono
parents: 67
diff changeset
142 if (gphi *phi = dyn_cast <gphi *> (def))
kono
parents: 67
diff changeset
143 {
kono
parents: 67
diff changeset
144 for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
kono
parents: 67
diff changeset
145 {
kono
parents: 67
diff changeset
146 tree t = gimple_phi_arg_def (phi, i);
kono
parents: 67
diff changeset
147 /* If an SSA has already been seen, it may be a loop,
kono
parents: 67
diff changeset
148 but we can continue and ignore this use. Otherwise,
kono
parents: 67
diff changeset
149 add the SSA_NAME to the queue and visit it later. */
kono
parents: 67
diff changeset
150 if (TREE_CODE (t) == SSA_NAME
kono
parents: 67
diff changeset
151 && bitmap_set_bit (visited_ssa, SSA_NAME_VERSION (t)))
kono
parents: 67
diff changeset
152 worklist.safe_push (t);
kono
parents: 67
diff changeset
153 }
kono
parents: 67
diff changeset
154 continue;
kono
parents: 67
diff changeset
155 }
kono
parents: 67
diff changeset
156
kono
parents: 67
diff changeset
157 /* Uses in stmts always executed when the region header executes
kono
parents: 67
diff changeset
158 are fine. */
kono
parents: 67
diff changeset
159 if (dominated_by_p (CDI_DOMINATORS, loop->header, gimple_bb (def)))
kono
parents: 67
diff changeset
160 continue;
kono
parents: 67
diff changeset
161
kono
parents: 67
diff changeset
162 /* Handle calls and memory loads conservatively. */
kono
parents: 67
diff changeset
163 if (!is_gimple_assign (def)
kono
parents: 67
diff changeset
164 || (gimple_assign_single_p (def)
kono
parents: 67
diff changeset
165 && gimple_vuse (def)))
kono
parents: 67
diff changeset
166 return true;
kono
parents: 67
diff changeset
167
kono
parents: 67
diff changeset
168 /* Check that any SSA names used to define NAME are also fully
kono
parents: 67
diff changeset
169 defined. */
kono
parents: 67
diff changeset
170 use_operand_p use_p;
kono
parents: 67
diff changeset
171 ssa_op_iter iter;
kono
parents: 67
diff changeset
172 FOR_EACH_SSA_USE_OPERAND (use_p, def, iter, SSA_OP_USE)
kono
parents: 67
diff changeset
173 {
kono
parents: 67
diff changeset
174 tree t = USE_FROM_PTR (use_p);
kono
parents: 67
diff changeset
175 /* If an SSA has already been seen, it may be a loop,
kono
parents: 67
diff changeset
176 but we can continue and ignore this use. Otherwise,
kono
parents: 67
diff changeset
177 add the SSA_NAME to the queue and visit it later. */
kono
parents: 67
diff changeset
178 if (bitmap_set_bit (visited_ssa, SSA_NAME_VERSION (t)))
kono
parents: 67
diff changeset
179 worklist.safe_push (t);
kono
parents: 67
diff changeset
180 }
kono
parents: 67
diff changeset
181 }
kono
parents: 67
diff changeset
182 return false;
kono
parents: 67
diff changeset
183 }
kono
parents: 67
diff changeset
184
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 /* Checks whether we can unswitch LOOP on condition at end of BB -- one of its
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
186 basic blocks (for what it means see comments below). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
187
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 static tree
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
189 tree_may_unswitch_on (basic_block bb, class loop *loop)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
190 {
111
kono
parents: 67
diff changeset
191 gimple *last, *def;
kono
parents: 67
diff changeset
192 gcond *stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 tree cond, use;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 basic_block def_bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 ssa_op_iter iter;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
196
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 /* BB must end in a simple conditional jump. */
111
kono
parents: 67
diff changeset
198 last = last_stmt (bb);
kono
parents: 67
diff changeset
199 if (!last || gimple_code (last) != GIMPLE_COND)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 return NULL_TREE;
111
kono
parents: 67
diff changeset
201 stmt = as_a <gcond *> (last);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202
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
203 /* To keep the things simple, we do not directly remove the conditions,
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
204 but just replace tests with 0 != 0 resp. 1 != 0. Prevent the infinite
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
205 loop where we would unswitch again on such a condition. */
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
206 if (gimple_cond_true_p (stmt) || gimple_cond_false_p (stmt))
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
207 return NULL_TREE;
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
208
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 /* Condition must be invariant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 def = SSA_NAME_DEF_STMT (use);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 def_bb = gimple_bb (def);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 if (def_bb
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
215 && flow_bb_inside_loop_p (loop, def_bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 return NULL_TREE;
111
kono
parents: 67
diff changeset
217 /* Unswitching on undefined values would introduce undefined
kono
parents: 67
diff changeset
218 behavior that the original program might never exercise. */
kono
parents: 67
diff changeset
219 if (is_maybe_undefined (use, stmt, loop))
kono
parents: 67
diff changeset
220 return NULL_TREE;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
221 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
222
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 cond = build2 (gimple_cond_code (stmt), boolean_type_node,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
224 gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
225
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
226 return cond;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
227 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
228
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 /* Simplifies COND using checks in front of the entry of the LOOP. Just very
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 simplish (sufficient to prevent us from duplicating loop in unswitching
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231 unnecessarily). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 static tree
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
234 simplify_using_entry_checks (class loop *loop, tree cond)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 edge e = loop_preheader_edge (loop);
111
kono
parents: 67
diff changeset
237 gimple *stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
238
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 while (1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 stmt = last_stmt (e->src);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 if (stmt
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
243 && gimple_code (stmt) == GIMPLE_COND
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 && gimple_cond_code (stmt) == TREE_CODE (cond)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 && operand_equal_p (gimple_cond_lhs (stmt),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 TREE_OPERAND (cond, 0), 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 && operand_equal_p (gimple_cond_rhs (stmt),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
248 TREE_OPERAND (cond, 1), 0))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 return (e->flags & EDGE_TRUE_VALUE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 ? boolean_true_node
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
251 : boolean_false_node);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
252
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
253 if (!single_pred_p (e->src))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 return cond;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256 e = single_pred_edge (e->src);
111
kono
parents: 67
diff changeset
257 if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 return cond;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
261
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 /* Unswitch single LOOP. NUM is number of unswitchings done; we do not allow
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263 it to grow too much, it is too easy to create example on that the code would
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 grow exponentially. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
267 tree_unswitch_single_loop (class loop *loop, int num)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269 basic_block *bbs;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
270 class loop *nloop;
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
271 unsigned i, found;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 tree cond = NULL_TREE;
111
kono
parents: 67
diff changeset
273 gimple *stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 bool changed = false;
111
kono
parents: 67
diff changeset
275 HOST_WIDE_INT iterations;
kono
parents: 67
diff changeset
276
kono
parents: 67
diff changeset
277 /* Perform initial tests if unswitch is eligible. */
kono
parents: 67
diff changeset
278 if (num == 0)
kono
parents: 67
diff changeset
279 {
kono
parents: 67
diff changeset
280 /* Do not unswitch in cold regions. */
kono
parents: 67
diff changeset
281 if (optimize_loop_for_size_p (loop))
kono
parents: 67
diff changeset
282 {
kono
parents: 67
diff changeset
283 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
284 fprintf (dump_file, ";; Not unswitching cold loops\n");
kono
parents: 67
diff changeset
285 return false;
kono
parents: 67
diff changeset
286 }
kono
parents: 67
diff changeset
287
kono
parents: 67
diff changeset
288 /* The loop should not be too large, to limit code growth. */
kono
parents: 67
diff changeset
289 if (tree_num_loop_insns (loop, &eni_size_weights)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
290 > (unsigned) param_max_unswitch_insns)
111
kono
parents: 67
diff changeset
291 {
kono
parents: 67
diff changeset
292 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
293 fprintf (dump_file, ";; Not unswitching, loop too big\n");
kono
parents: 67
diff changeset
294 return false;
kono
parents: 67
diff changeset
295 }
kono
parents: 67
diff changeset
296
kono
parents: 67
diff changeset
297 /* If the loop is not expected to iterate, there is no need
kono
parents: 67
diff changeset
298 for unswitching. */
kono
parents: 67
diff changeset
299 iterations = estimated_loop_iterations_int (loop);
kono
parents: 67
diff changeset
300 if (iterations < 0)
kono
parents: 67
diff changeset
301 iterations = likely_max_loop_iterations_int (loop);
kono
parents: 67
diff changeset
302 if (iterations >= 0 && iterations <= 1)
kono
parents: 67
diff changeset
303 {
kono
parents: 67
diff changeset
304 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
305 fprintf (dump_file, ";; Not unswitching, loop is not expected"
kono
parents: 67
diff changeset
306 " to iterate\n");
kono
parents: 67
diff changeset
307 return false;
kono
parents: 67
diff changeset
308 }
kono
parents: 67
diff changeset
309 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
310
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 i = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 bbs = get_loop_body (loop);
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
313 found = loop->num_nodes;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
314
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315 while (1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 /* Find a bb to unswitch on. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 for (; i < loop->num_nodes; i++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
319 if ((cond = tree_may_unswitch_on (bbs[i], loop)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
320 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
321
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
322 if (i == loop->num_nodes)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
323 {
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
324 if (dump_file
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
325 && num > param_max_unswitch_level
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
326 && (dump_flags & TDF_DETAILS))
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
327 fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
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
328
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
329 if (found == loop->num_nodes)
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
330 {
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
331 free (bbs);
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
332 return changed;
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
333 }
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
334 break;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
335 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
336
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 cond = simplify_using_entry_checks (loop, cond);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
338 stmt = last_stmt (bbs[i]);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
339 if (integer_nonzerop (cond))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
340 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
341 /* Remove false path. */
111
kono
parents: 67
diff changeset
342 gimple_cond_set_condition_from_tree (as_a <gcond *> (stmt),
kono
parents: 67
diff changeset
343 boolean_true_node);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 changed = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 else if (integer_zerop (cond))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348 /* Remove true path. */
111
kono
parents: 67
diff changeset
349 gimple_cond_set_condition_from_tree (as_a <gcond *> (stmt),
kono
parents: 67
diff changeset
350 boolean_false_node);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 changed = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 }
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
353 /* Do not unswitch too much. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
354 else if (num > param_max_unswitch_level)
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
355 {
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
356 i++;
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
357 continue;
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
358 }
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
359 /* In nested tree_unswitch_single_loop first optimize all conditions
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
360 using entry checks, then discover still reachable blocks in the
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
361 loop and find the condition only among those still reachable bbs. */
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
362 else if (num != 0)
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
363 {
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
364 if (found == loop->num_nodes)
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
365 found = i;
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
366 i++;
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
367 continue;
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
368 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
369 else
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
370 {
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
371 found = i;
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
372 break;
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
373 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
374
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
375 update_stmt (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
376 i++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
377 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
378
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
379 if (num != 0)
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
380 {
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
381 basic_block *tos, *worklist;
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
382
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
383 /* When called recursively, first do a quick discovery
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
384 of reachable bbs after the above changes and only
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
385 consider conditions in still reachable bbs. */
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
386 tos = worklist = XNEWVEC (basic_block, loop->num_nodes);
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
387
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
388 for (i = 0; i < loop->num_nodes; i++)
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
389 bbs[i]->flags &= ~BB_REACHABLE;
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
390
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
391 /* Start with marking header. */
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
392 *tos++ = bbs[0];
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
393 bbs[0]->flags |= BB_REACHABLE;
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
394
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
395 /* Iterate: find everything reachable from what we've already seen
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
396 within the same innermost loop. Don't look through false edges
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
397 if condition is always true or true edges if condition is
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
398 always false. */
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
399 while (tos != worklist)
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
400 {
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
401 basic_block b = *--tos;
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
402 edge e;
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
403 edge_iterator ei;
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
404 int flags = 0;
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
405
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
406 if (EDGE_COUNT (b->succs) == 2)
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
407 {
111
kono
parents: 67
diff changeset
408 gimple *stmt = last_stmt (b);
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
409 if (stmt
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
410 && gimple_code (stmt) == GIMPLE_COND)
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
411 {
111
kono
parents: 67
diff changeset
412 gcond *cond_stmt = as_a <gcond *> (stmt);
kono
parents: 67
diff changeset
413 if (gimple_cond_true_p (cond_stmt))
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
414 flags = EDGE_FALSE_VALUE;
111
kono
parents: 67
diff changeset
415 else if (gimple_cond_false_p (cond_stmt))
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
416 flags = EDGE_TRUE_VALUE;
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
417 }
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
418 }
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
419
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
420 FOR_EACH_EDGE (e, ei, b->succs)
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
421 {
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
422 basic_block dest = e->dest;
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
423
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
424 if (dest->loop_father == loop
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
425 && !(dest->flags & BB_REACHABLE)
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
426 && !(e->flags & flags))
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
427 {
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
428 *tos++ = dest;
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
429 dest->flags |= BB_REACHABLE;
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
430 }
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
431 }
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
432 }
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
433
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
434 free (worklist);
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
435
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
436 /* Find a bb to unswitch on. */
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
437 for (; found < loop->num_nodes; found++)
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
438 if ((bbs[found]->flags & BB_REACHABLE)
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
439 && (cond = tree_may_unswitch_on (bbs[found], loop)))
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
440 break;
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
441
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
442 if (found == loop->num_nodes)
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
443 {
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
444 free (bbs);
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
445 return changed;
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
446 }
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
447 }
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
448
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
449 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
450 fprintf (dump_file, ";; Unswitching loop\n");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
451
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
452 initialize_original_copy_tables ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
453 /* Unswitch the loop on this condition. */
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
454 nloop = tree_unswitch_loop (loop, bbs[found], cond);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
455 if (!nloop)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
456 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
457 free_original_copy_tables ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
458 free (bbs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
459 return changed;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
460 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
461
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
462 /* Update the SSA form after unswitching. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
463 update_ssa (TODO_update_ssa);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
464 free_original_copy_tables ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
465
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
466 /* Invoke itself on modified loops. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
467 tree_unswitch_single_loop (nloop, num + 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
468 tree_unswitch_single_loop (loop, num + 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
469 free (bbs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
471 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
472
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
473 /* Unswitch a LOOP w.r. to given basic block UNSWITCH_ON. We only support
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
474 unswitching of innermost loops. COND is the condition determining which
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
475 loop is entered -- the new loop is entered if COND is true. Returns NULL
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
476 if impossible, new loop otherwise. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
477
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
478 static class loop *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
479 tree_unswitch_loop (class loop *loop,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
480 basic_block unswitch_on, tree cond)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
481 {
111
kono
parents: 67
diff changeset
482 profile_probability prob_true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
483 edge edge_true, edge_false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
484
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
485 /* Some sanity checking. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
486 gcc_assert (flow_bb_inside_loop_p (loop, unswitch_on));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
487 gcc_assert (EDGE_COUNT (unswitch_on->succs) == 2);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
488 gcc_assert (loop->inner == NULL);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
489
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
490 extract_true_false_edges_from_block (unswitch_on, &edge_true, &edge_false);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
491 prob_true = edge_true->probability;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
492 return loop_version (loop, unshare_expr (cond),
111
kono
parents: 67
diff changeset
493 NULL, prob_true,
kono
parents: 67
diff changeset
494 prob_true.invert (),
kono
parents: 67
diff changeset
495 prob_true, prob_true.invert (),
kono
parents: 67
diff changeset
496 false);
kono
parents: 67
diff changeset
497 }
kono
parents: 67
diff changeset
498
kono
parents: 67
diff changeset
499 /* Unswitch outer loops by hoisting invariant guard on
kono
parents: 67
diff changeset
500 inner loop without code duplication. */
kono
parents: 67
diff changeset
501 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
502 tree_unswitch_outer_loop (class loop *loop)
111
kono
parents: 67
diff changeset
503 {
kono
parents: 67
diff changeset
504 edge exit, guard;
kono
parents: 67
diff changeset
505 HOST_WIDE_INT iterations;
kono
parents: 67
diff changeset
506
kono
parents: 67
diff changeset
507 gcc_assert (loop->inner);
kono
parents: 67
diff changeset
508 if (loop->inner->next)
kono
parents: 67
diff changeset
509 return false;
kono
parents: 67
diff changeset
510 /* Accept loops with single exit only which is not from inner loop. */
kono
parents: 67
diff changeset
511 exit = single_exit (loop);
kono
parents: 67
diff changeset
512 if (!exit || exit->src->loop_father != loop)
kono
parents: 67
diff changeset
513 return false;
kono
parents: 67
diff changeset
514 /* Check that phi argument of exit edge is not defined inside loop. */
kono
parents: 67
diff changeset
515 if (!check_exit_phi (loop))
kono
parents: 67
diff changeset
516 return false;
kono
parents: 67
diff changeset
517 /* If the loop is not expected to iterate, there is no need
kono
parents: 67
diff changeset
518 for unswitching. */
kono
parents: 67
diff changeset
519 iterations = estimated_loop_iterations_int (loop);
kono
parents: 67
diff changeset
520 if (iterations < 0)
kono
parents: 67
diff changeset
521 iterations = likely_max_loop_iterations_int (loop);
kono
parents: 67
diff changeset
522 if (iterations >= 0 && iterations <= 1)
kono
parents: 67
diff changeset
523 {
kono
parents: 67
diff changeset
524 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
525 fprintf (dump_file, ";; Not unswitching, loop is not expected"
kono
parents: 67
diff changeset
526 " to iterate\n");
kono
parents: 67
diff changeset
527 return false;
kono
parents: 67
diff changeset
528 }
kono
parents: 67
diff changeset
529
kono
parents: 67
diff changeset
530 bool changed = false;
kono
parents: 67
diff changeset
531 while ((guard = find_loop_guard (loop)))
kono
parents: 67
diff changeset
532 {
kono
parents: 67
diff changeset
533 if (! changed)
kono
parents: 67
diff changeset
534 rewrite_virtuals_into_loop_closed_ssa (loop);
kono
parents: 67
diff changeset
535 hoist_guard (loop, guard);
kono
parents: 67
diff changeset
536 changed = true;
kono
parents: 67
diff changeset
537 }
kono
parents: 67
diff changeset
538 return changed;
kono
parents: 67
diff changeset
539 }
kono
parents: 67
diff changeset
540
kono
parents: 67
diff changeset
541 /* Checks if the body of the LOOP is within an invariant guard. If this
kono
parents: 67
diff changeset
542 is the case, returns the edge that jumps over the real body of the loop,
kono
parents: 67
diff changeset
543 otherwise returns NULL. */
kono
parents: 67
diff changeset
544
kono
parents: 67
diff changeset
545 static edge
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
546 find_loop_guard (class loop *loop)
111
kono
parents: 67
diff changeset
547 {
kono
parents: 67
diff changeset
548 basic_block header = loop->header;
kono
parents: 67
diff changeset
549 edge guard_edge, te, fe;
kono
parents: 67
diff changeset
550 basic_block *body = NULL;
kono
parents: 67
diff changeset
551 unsigned i;
kono
parents: 67
diff changeset
552 tree use;
kono
parents: 67
diff changeset
553 ssa_op_iter iter;
kono
parents: 67
diff changeset
554
kono
parents: 67
diff changeset
555 /* We check for the following situation:
kono
parents: 67
diff changeset
556
kono
parents: 67
diff changeset
557 while (1)
kono
parents: 67
diff changeset
558 {
kono
parents: 67
diff changeset
559 [header]]
kono
parents: 67
diff changeset
560 loop_phi_nodes;
kono
parents: 67
diff changeset
561 something1;
kono
parents: 67
diff changeset
562 if (cond1)
kono
parents: 67
diff changeset
563 body;
kono
parents: 67
diff changeset
564 nvar = phi(orig, bvar) ... for all variables changed in body;
kono
parents: 67
diff changeset
565 [guard_end]
kono
parents: 67
diff changeset
566 something2;
kono
parents: 67
diff changeset
567 if (cond2)
kono
parents: 67
diff changeset
568 break;
kono
parents: 67
diff changeset
569 something3;
kono
parents: 67
diff changeset
570 }
kono
parents: 67
diff changeset
571
kono
parents: 67
diff changeset
572 where:
kono
parents: 67
diff changeset
573
kono
parents: 67
diff changeset
574 1) cond1 is loop invariant
kono
parents: 67
diff changeset
575 2) If cond1 is false, then the loop is essentially empty; i.e.,
kono
parents: 67
diff changeset
576 a) nothing in something1, something2 and something3 has side
kono
parents: 67
diff changeset
577 effects
kono
parents: 67
diff changeset
578 b) anything defined in something1, something2 and something3
kono
parents: 67
diff changeset
579 is not used outside of the loop. */
kono
parents: 67
diff changeset
580
kono
parents: 67
diff changeset
581 gcond *cond;
kono
parents: 67
diff changeset
582 do
kono
parents: 67
diff changeset
583 {
kono
parents: 67
diff changeset
584 basic_block next = NULL;
kono
parents: 67
diff changeset
585 if (single_succ_p (header))
kono
parents: 67
diff changeset
586 next = single_succ (header);
kono
parents: 67
diff changeset
587 else
kono
parents: 67
diff changeset
588 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
589 cond = safe_dyn_cast <gcond *> (last_stmt (header));
111
kono
parents: 67
diff changeset
590 if (! cond)
kono
parents: 67
diff changeset
591 return NULL;
kono
parents: 67
diff changeset
592 extract_true_false_edges_from_block (header, &te, &fe);
kono
parents: 67
diff changeset
593 /* Make sure to skip earlier hoisted guards that are left
kono
parents: 67
diff changeset
594 in place as if (true). */
kono
parents: 67
diff changeset
595 if (gimple_cond_true_p (cond))
kono
parents: 67
diff changeset
596 next = te->dest;
kono
parents: 67
diff changeset
597 else if (gimple_cond_false_p (cond))
kono
parents: 67
diff changeset
598 next = fe->dest;
kono
parents: 67
diff changeset
599 else
kono
parents: 67
diff changeset
600 break;
kono
parents: 67
diff changeset
601 }
kono
parents: 67
diff changeset
602 /* Never traverse a backedge. */
kono
parents: 67
diff changeset
603 if (header->loop_father->header == next)
kono
parents: 67
diff changeset
604 return NULL;
kono
parents: 67
diff changeset
605 header = next;
kono
parents: 67
diff changeset
606 }
kono
parents: 67
diff changeset
607 while (1);
kono
parents: 67
diff changeset
608 if (!flow_bb_inside_loop_p (loop, te->dest)
kono
parents: 67
diff changeset
609 || !flow_bb_inside_loop_p (loop, fe->dest))
kono
parents: 67
diff changeset
610 return NULL;
kono
parents: 67
diff changeset
611
kono
parents: 67
diff changeset
612 if (just_once_each_iteration_p (loop, te->dest)
kono
parents: 67
diff changeset
613 || (single_succ_p (te->dest)
kono
parents: 67
diff changeset
614 && just_once_each_iteration_p (loop, single_succ (te->dest))))
kono
parents: 67
diff changeset
615 {
kono
parents: 67
diff changeset
616 if (just_once_each_iteration_p (loop, fe->dest))
kono
parents: 67
diff changeset
617 return NULL;
kono
parents: 67
diff changeset
618 guard_edge = te;
kono
parents: 67
diff changeset
619 }
kono
parents: 67
diff changeset
620 else if (just_once_each_iteration_p (loop, fe->dest)
kono
parents: 67
diff changeset
621 || (single_succ_p (fe->dest)
kono
parents: 67
diff changeset
622 && just_once_each_iteration_p (loop, single_succ (fe->dest))))
kono
parents: 67
diff changeset
623 guard_edge = fe;
kono
parents: 67
diff changeset
624 else
kono
parents: 67
diff changeset
625 return NULL;
kono
parents: 67
diff changeset
626
kono
parents: 67
diff changeset
627 /* Guard edge must skip inner loop. */
kono
parents: 67
diff changeset
628 if (!dominated_by_p (CDI_DOMINATORS, loop->inner->header,
kono
parents: 67
diff changeset
629 guard_edge == fe ? te->dest : fe->dest))
kono
parents: 67
diff changeset
630 {
kono
parents: 67
diff changeset
631 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
632 fprintf (dump_file, "Guard edge %d --> %d is not around the loop!\n",
kono
parents: 67
diff changeset
633 guard_edge->src->index, guard_edge->dest->index);
kono
parents: 67
diff changeset
634 return NULL;
kono
parents: 67
diff changeset
635 }
kono
parents: 67
diff changeset
636 if (guard_edge->dest == loop->latch)
kono
parents: 67
diff changeset
637 {
kono
parents: 67
diff changeset
638 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
639 fprintf (dump_file, "Guard edge destination is loop latch.\n");
kono
parents: 67
diff changeset
640 return NULL;
kono
parents: 67
diff changeset
641 }
kono
parents: 67
diff changeset
642
kono
parents: 67
diff changeset
643 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
644 fprintf (dump_file,
kono
parents: 67
diff changeset
645 "Considering guard %d -> %d in loop %d\n",
kono
parents: 67
diff changeset
646 guard_edge->src->index, guard_edge->dest->index, loop->num);
kono
parents: 67
diff changeset
647 /* Check if condition operands do not have definitions inside loop since
kono
parents: 67
diff changeset
648 any bb copying is not performed. */
kono
parents: 67
diff changeset
649 FOR_EACH_SSA_TREE_OPERAND (use, cond, iter, SSA_OP_USE)
kono
parents: 67
diff changeset
650 {
kono
parents: 67
diff changeset
651 gimple *def = SSA_NAME_DEF_STMT (use);
kono
parents: 67
diff changeset
652 basic_block def_bb = gimple_bb (def);
kono
parents: 67
diff changeset
653 if (def_bb
kono
parents: 67
diff changeset
654 && flow_bb_inside_loop_p (loop, def_bb))
kono
parents: 67
diff changeset
655 {
kono
parents: 67
diff changeset
656 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
657 fprintf (dump_file, " guard operands have definitions"
kono
parents: 67
diff changeset
658 " inside loop\n");
kono
parents: 67
diff changeset
659 return NULL;
kono
parents: 67
diff changeset
660 }
kono
parents: 67
diff changeset
661 }
kono
parents: 67
diff changeset
662
kono
parents: 67
diff changeset
663 body = get_loop_body (loop);
kono
parents: 67
diff changeset
664 for (i = 0; i < loop->num_nodes; i++)
kono
parents: 67
diff changeset
665 {
kono
parents: 67
diff changeset
666 basic_block bb = body[i];
kono
parents: 67
diff changeset
667 if (bb->loop_father != loop)
kono
parents: 67
diff changeset
668 continue;
kono
parents: 67
diff changeset
669 if (bb->flags & BB_IRREDUCIBLE_LOOP)
kono
parents: 67
diff changeset
670 {
kono
parents: 67
diff changeset
671 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
672 fprintf (dump_file, "Block %d is marked as irreducible in loop\n",
kono
parents: 67
diff changeset
673 bb->index);
kono
parents: 67
diff changeset
674 guard_edge = NULL;
kono
parents: 67
diff changeset
675 goto end;
kono
parents: 67
diff changeset
676 }
kono
parents: 67
diff changeset
677 if (!empty_bb_without_guard_p (loop, bb))
kono
parents: 67
diff changeset
678 {
kono
parents: 67
diff changeset
679 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
680 fprintf (dump_file, " block %d has side effects\n", bb->index);
kono
parents: 67
diff changeset
681 guard_edge = NULL;
kono
parents: 67
diff changeset
682 goto end;
kono
parents: 67
diff changeset
683 }
kono
parents: 67
diff changeset
684 }
kono
parents: 67
diff changeset
685
kono
parents: 67
diff changeset
686 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
687 fprintf (dump_file, " suitable to hoist\n");
kono
parents: 67
diff changeset
688 end:
kono
parents: 67
diff changeset
689 if (body)
kono
parents: 67
diff changeset
690 free (body);
kono
parents: 67
diff changeset
691 return guard_edge;
kono
parents: 67
diff changeset
692 }
kono
parents: 67
diff changeset
693
kono
parents: 67
diff changeset
694 /* Returns true if
kono
parents: 67
diff changeset
695 1) no statement in BB has side effects
kono
parents: 67
diff changeset
696 2) assuming that edge GUARD is always taken, all definitions in BB
kono
parents: 67
diff changeset
697 are noy used outside of the loop.
kono
parents: 67
diff changeset
698 KNOWN_INVARIANTS is a set of ssa names we know to be invariant, and
kono
parents: 67
diff changeset
699 PROCESSED is a set of ssa names for that we already tested whether they
kono
parents: 67
diff changeset
700 are invariant or not. */
kono
parents: 67
diff changeset
701
kono
parents: 67
diff changeset
702 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
703 empty_bb_without_guard_p (class loop *loop, basic_block bb)
111
kono
parents: 67
diff changeset
704 {
kono
parents: 67
diff changeset
705 basic_block exit_bb = single_exit (loop)->src;
kono
parents: 67
diff changeset
706 bool may_be_used_outside = (bb == exit_bb
kono
parents: 67
diff changeset
707 || !dominated_by_p (CDI_DOMINATORS, bb, exit_bb));
kono
parents: 67
diff changeset
708 tree name;
kono
parents: 67
diff changeset
709 ssa_op_iter op_iter;
kono
parents: 67
diff changeset
710
kono
parents: 67
diff changeset
711 /* Phi nodes do not have side effects, but their results might be used
kono
parents: 67
diff changeset
712 outside of the loop. */
kono
parents: 67
diff changeset
713 if (may_be_used_outside)
kono
parents: 67
diff changeset
714 {
kono
parents: 67
diff changeset
715 for (gphi_iterator gsi = gsi_start_phis (bb);
kono
parents: 67
diff changeset
716 !gsi_end_p (gsi); gsi_next (&gsi))
kono
parents: 67
diff changeset
717 {
kono
parents: 67
diff changeset
718 gphi *phi = gsi.phi ();
kono
parents: 67
diff changeset
719 name = PHI_RESULT (phi);
kono
parents: 67
diff changeset
720 if (virtual_operand_p (name))
kono
parents: 67
diff changeset
721 continue;
kono
parents: 67
diff changeset
722
kono
parents: 67
diff changeset
723 if (used_outside_loop_p (loop, name))
kono
parents: 67
diff changeset
724 return false;
kono
parents: 67
diff changeset
725 }
kono
parents: 67
diff changeset
726 }
kono
parents: 67
diff changeset
727
kono
parents: 67
diff changeset
728 for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
kono
parents: 67
diff changeset
729 !gsi_end_p (gsi); gsi_next (&gsi))
kono
parents: 67
diff changeset
730 {
kono
parents: 67
diff changeset
731 gimple *stmt = gsi_stmt (gsi);
kono
parents: 67
diff changeset
732 if (gimple_has_side_effects (stmt))
kono
parents: 67
diff changeset
733 return false;
kono
parents: 67
diff changeset
734
kono
parents: 67
diff changeset
735 if (gimple_vdef(stmt))
kono
parents: 67
diff changeset
736 return false;
kono
parents: 67
diff changeset
737
kono
parents: 67
diff changeset
738 FOR_EACH_SSA_TREE_OPERAND (name, stmt, op_iter, SSA_OP_DEF)
kono
parents: 67
diff changeset
739 {
kono
parents: 67
diff changeset
740 if (may_be_used_outside
kono
parents: 67
diff changeset
741 && used_outside_loop_p (loop, name))
kono
parents: 67
diff changeset
742 return false;
kono
parents: 67
diff changeset
743 }
kono
parents: 67
diff changeset
744 }
kono
parents: 67
diff changeset
745 return true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
746 }
111
kono
parents: 67
diff changeset
747
kono
parents: 67
diff changeset
748 /* Return true if NAME is used outside of LOOP. */
kono
parents: 67
diff changeset
749
kono
parents: 67
diff changeset
750 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
751 used_outside_loop_p (class loop *loop, tree name)
111
kono
parents: 67
diff changeset
752 {
kono
parents: 67
diff changeset
753 imm_use_iterator it;
kono
parents: 67
diff changeset
754 use_operand_p use;
kono
parents: 67
diff changeset
755
kono
parents: 67
diff changeset
756 FOR_EACH_IMM_USE_FAST (use, it, name)
kono
parents: 67
diff changeset
757 {
kono
parents: 67
diff changeset
758 gimple *stmt = USE_STMT (use);
kono
parents: 67
diff changeset
759 if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
kono
parents: 67
diff changeset
760 return true;
kono
parents: 67
diff changeset
761 }
kono
parents: 67
diff changeset
762
kono
parents: 67
diff changeset
763 return false;
kono
parents: 67
diff changeset
764 }
kono
parents: 67
diff changeset
765
kono
parents: 67
diff changeset
766 /* Return argument for loop preheader edge in header virtual phi if any. */
kono
parents: 67
diff changeset
767
kono
parents: 67
diff changeset
768 static tree
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
769 get_vop_from_header (class loop *loop)
111
kono
parents: 67
diff changeset
770 {
kono
parents: 67
diff changeset
771 for (gphi_iterator gsi = gsi_start_phis (loop->header);
kono
parents: 67
diff changeset
772 !gsi_end_p (gsi); gsi_next (&gsi))
kono
parents: 67
diff changeset
773 {
kono
parents: 67
diff changeset
774 gphi *phi = gsi.phi ();
kono
parents: 67
diff changeset
775 if (!virtual_operand_p (gimple_phi_result (phi)))
kono
parents: 67
diff changeset
776 continue;
kono
parents: 67
diff changeset
777 return PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
kono
parents: 67
diff changeset
778 }
kono
parents: 67
diff changeset
779 return NULL_TREE;
kono
parents: 67
diff changeset
780 }
kono
parents: 67
diff changeset
781
kono
parents: 67
diff changeset
782 /* Move the check of GUARD outside of LOOP. */
kono
parents: 67
diff changeset
783
kono
parents: 67
diff changeset
784 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
785 hoist_guard (class loop *loop, edge guard)
111
kono
parents: 67
diff changeset
786 {
kono
parents: 67
diff changeset
787 edge exit = single_exit (loop);
kono
parents: 67
diff changeset
788 edge preh = loop_preheader_edge (loop);
kono
parents: 67
diff changeset
789 basic_block pre_header = preh->src;
kono
parents: 67
diff changeset
790 basic_block bb;
kono
parents: 67
diff changeset
791 edge te, fe, e, new_edge;
kono
parents: 67
diff changeset
792 gimple *stmt;
kono
parents: 67
diff changeset
793 basic_block guard_bb = guard->src;
kono
parents: 67
diff changeset
794 edge not_guard;
kono
parents: 67
diff changeset
795 gimple_stmt_iterator gsi;
kono
parents: 67
diff changeset
796 int flags = 0;
kono
parents: 67
diff changeset
797 bool fix_dom_of_exit;
kono
parents: 67
diff changeset
798 gcond *cond_stmt, *new_cond_stmt;
kono
parents: 67
diff changeset
799
kono
parents: 67
diff changeset
800 bb = get_immediate_dominator (CDI_DOMINATORS, exit->dest);
kono
parents: 67
diff changeset
801 fix_dom_of_exit = flow_bb_inside_loop_p (loop, bb);
kono
parents: 67
diff changeset
802 gsi = gsi_last_bb (guard_bb);
kono
parents: 67
diff changeset
803 stmt = gsi_stmt (gsi);
kono
parents: 67
diff changeset
804 gcc_assert (gimple_code (stmt) == GIMPLE_COND);
kono
parents: 67
diff changeset
805 cond_stmt = as_a <gcond *> (stmt);
kono
parents: 67
diff changeset
806 extract_true_false_edges_from_block (guard_bb, &te, &fe);
kono
parents: 67
diff changeset
807 /* Insert guard to PRE_HEADER. */
kono
parents: 67
diff changeset
808 if (!empty_block_p (pre_header))
kono
parents: 67
diff changeset
809 gsi = gsi_last_bb (pre_header);
kono
parents: 67
diff changeset
810 else
kono
parents: 67
diff changeset
811 gsi = gsi_start_bb (pre_header);
kono
parents: 67
diff changeset
812 /* Create copy of COND_STMT. */
kono
parents: 67
diff changeset
813 new_cond_stmt = gimple_build_cond (gimple_cond_code (cond_stmt),
kono
parents: 67
diff changeset
814 gimple_cond_lhs (cond_stmt),
kono
parents: 67
diff changeset
815 gimple_cond_rhs (cond_stmt),
kono
parents: 67
diff changeset
816 NULL_TREE, NULL_TREE);
kono
parents: 67
diff changeset
817 gsi_insert_after (&gsi, new_cond_stmt, GSI_NEW_STMT);
kono
parents: 67
diff changeset
818 /* Convert COND_STMT to true/false conditional. */
kono
parents: 67
diff changeset
819 if (guard == te)
kono
parents: 67
diff changeset
820 gimple_cond_make_false (cond_stmt);
kono
parents: 67
diff changeset
821 else
kono
parents: 67
diff changeset
822 gimple_cond_make_true (cond_stmt);
kono
parents: 67
diff changeset
823 update_stmt (cond_stmt);
kono
parents: 67
diff changeset
824 /* Create new loop pre-header. */
kono
parents: 67
diff changeset
825 e = split_block (pre_header, last_stmt (pre_header));
kono
parents: 67
diff changeset
826 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
827 {
kono
parents: 67
diff changeset
828 fprintf (dump_file, " Moving guard %i->%i (prob ",
kono
parents: 67
diff changeset
829 guard->src->index, guard->dest->index);
kono
parents: 67
diff changeset
830 guard->probability.dump (dump_file);
kono
parents: 67
diff changeset
831 fprintf (dump_file, ") to bb %i, new preheader is %i\n",
kono
parents: 67
diff changeset
832 e->src->index, e->dest->index);
kono
parents: 67
diff changeset
833 }
kono
parents: 67
diff changeset
834
kono
parents: 67
diff changeset
835 gcc_assert (loop_preheader_edge (loop)->src == e->dest);
kono
parents: 67
diff changeset
836
kono
parents: 67
diff changeset
837 if (guard == fe)
kono
parents: 67
diff changeset
838 {
kono
parents: 67
diff changeset
839 e->flags = EDGE_TRUE_VALUE;
kono
parents: 67
diff changeset
840 flags |= EDGE_FALSE_VALUE;
kono
parents: 67
diff changeset
841 not_guard = te;
kono
parents: 67
diff changeset
842 }
kono
parents: 67
diff changeset
843 else
kono
parents: 67
diff changeset
844 {
kono
parents: 67
diff changeset
845 e->flags = EDGE_FALSE_VALUE;
kono
parents: 67
diff changeset
846 flags |= EDGE_TRUE_VALUE;
kono
parents: 67
diff changeset
847 not_guard = fe;
kono
parents: 67
diff changeset
848 }
kono
parents: 67
diff changeset
849 new_edge = make_edge (pre_header, exit->dest, flags);
kono
parents: 67
diff changeset
850
kono
parents: 67
diff changeset
851 /* Determine the probability that we skip the loop. Assume that loop has
kono
parents: 67
diff changeset
852 same average number of iterations regardless outcome of guard. */
kono
parents: 67
diff changeset
853 new_edge->probability = guard->probability;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
854 profile_count skip_count = guard->src->count.nonzero_p ()
111
kono
parents: 67
diff changeset
855 ? guard->count ().apply_scale (pre_header->count,
kono
parents: 67
diff changeset
856 guard->src->count)
kono
parents: 67
diff changeset
857 : guard->count ().apply_probability (new_edge->probability);
kono
parents: 67
diff changeset
858
kono
parents: 67
diff changeset
859 if (skip_count > e->count ())
kono
parents: 67
diff changeset
860 {
kono
parents: 67
diff changeset
861 fprintf (dump_file, " Capping count; expect profile inconsistency\n");
kono
parents: 67
diff changeset
862 skip_count = e->count ();
kono
parents: 67
diff changeset
863 }
kono
parents: 67
diff changeset
864 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
865 {
kono
parents: 67
diff changeset
866 fprintf (dump_file, " Estimated probability of skipping loop is ");
kono
parents: 67
diff changeset
867 new_edge->probability.dump (dump_file);
kono
parents: 67
diff changeset
868 fprintf (dump_file, "\n");
kono
parents: 67
diff changeset
869 }
kono
parents: 67
diff changeset
870
kono
parents: 67
diff changeset
871 /* Update profile after the transform:
kono
parents: 67
diff changeset
872
kono
parents: 67
diff changeset
873 First decrease count of path from newly hoisted loop guard
kono
parents: 67
diff changeset
874 to loop header... */
kono
parents: 67
diff changeset
875 e->probability = new_edge->probability.invert ();
kono
parents: 67
diff changeset
876 e->dest->count = e->count ();
kono
parents: 67
diff changeset
877
kono
parents: 67
diff changeset
878 /* ... now update profile to represent that original guard will be optimized
kono
parents: 67
diff changeset
879 away ... */
kono
parents: 67
diff changeset
880 guard->probability = profile_probability::never ();
kono
parents: 67
diff changeset
881 not_guard->probability = profile_probability::always ();
kono
parents: 67
diff changeset
882
kono
parents: 67
diff changeset
883 /* ... finally scale everything in the loop except for guarded basic blocks
kono
parents: 67
diff changeset
884 where profile does not change. */
kono
parents: 67
diff changeset
885 basic_block *body = get_loop_body (loop);
kono
parents: 67
diff changeset
886
kono
parents: 67
diff changeset
887 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
888 fprintf (dump_file, " Scaling nonguarded BBs in loop:");
kono
parents: 67
diff changeset
889 for (unsigned int i = 0; i < loop->num_nodes; i++)
kono
parents: 67
diff changeset
890 {
kono
parents: 67
diff changeset
891 basic_block bb = body[i];
kono
parents: 67
diff changeset
892 if (!dominated_by_p (CDI_DOMINATORS, bb, not_guard->dest))
kono
parents: 67
diff changeset
893 {
kono
parents: 67
diff changeset
894 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
895 fprintf (dump_file, " %i", bb->index);
kono
parents: 67
diff changeset
896 if (e->probability.initialized_p ())
kono
parents: 67
diff changeset
897 scale_bbs_frequencies (&bb, 1, e->probability);
kono
parents: 67
diff changeset
898 }
kono
parents: 67
diff changeset
899 }
kono
parents: 67
diff changeset
900
kono
parents: 67
diff changeset
901 if (fix_dom_of_exit)
kono
parents: 67
diff changeset
902 set_immediate_dominator (CDI_DOMINATORS, exit->dest, pre_header);
kono
parents: 67
diff changeset
903 /* Add NEW_ADGE argument for all phi in post-header block. */
kono
parents: 67
diff changeset
904 bb = exit->dest;
kono
parents: 67
diff changeset
905 for (gphi_iterator gsi = gsi_start_phis (bb);
kono
parents: 67
diff changeset
906 !gsi_end_p (gsi); gsi_next (&gsi))
kono
parents: 67
diff changeset
907 {
kono
parents: 67
diff changeset
908 gphi *phi = gsi.phi ();
kono
parents: 67
diff changeset
909 tree arg;
kono
parents: 67
diff changeset
910 if (virtual_operand_p (gimple_phi_result (phi)))
kono
parents: 67
diff changeset
911 {
kono
parents: 67
diff changeset
912 arg = get_vop_from_header (loop);
kono
parents: 67
diff changeset
913 if (arg == NULL_TREE)
kono
parents: 67
diff changeset
914 /* Use exit edge argument. */
kono
parents: 67
diff changeset
915 arg = PHI_ARG_DEF_FROM_EDGE (phi, exit);
kono
parents: 67
diff changeset
916 add_phi_arg (phi, arg, new_edge, UNKNOWN_LOCATION);
kono
parents: 67
diff changeset
917 }
kono
parents: 67
diff changeset
918 else
kono
parents: 67
diff changeset
919 {
kono
parents: 67
diff changeset
920 /* Use exit edge argument. */
kono
parents: 67
diff changeset
921 arg = PHI_ARG_DEF_FROM_EDGE (phi, exit);
kono
parents: 67
diff changeset
922 add_phi_arg (phi, arg, new_edge, UNKNOWN_LOCATION);
kono
parents: 67
diff changeset
923 }
kono
parents: 67
diff changeset
924 }
kono
parents: 67
diff changeset
925
kono
parents: 67
diff changeset
926 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
927 fprintf (dump_file, "\n guard hoisted.\n");
kono
parents: 67
diff changeset
928
kono
parents: 67
diff changeset
929 free (body);
kono
parents: 67
diff changeset
930 }
kono
parents: 67
diff changeset
931
kono
parents: 67
diff changeset
932 /* Return true if phi argument for exit edge can be used
kono
parents: 67
diff changeset
933 for edge around loop. */
kono
parents: 67
diff changeset
934
kono
parents: 67
diff changeset
935 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
936 check_exit_phi (class loop *loop)
111
kono
parents: 67
diff changeset
937 {
kono
parents: 67
diff changeset
938 edge exit = single_exit (loop);
kono
parents: 67
diff changeset
939 basic_block pre_header = loop_preheader_edge (loop)->src;
kono
parents: 67
diff changeset
940
kono
parents: 67
diff changeset
941 for (gphi_iterator gsi = gsi_start_phis (exit->dest);
kono
parents: 67
diff changeset
942 !gsi_end_p (gsi); gsi_next (&gsi))
kono
parents: 67
diff changeset
943 {
kono
parents: 67
diff changeset
944 gphi *phi = gsi.phi ();
kono
parents: 67
diff changeset
945 tree arg;
kono
parents: 67
diff changeset
946 gimple *def;
kono
parents: 67
diff changeset
947 basic_block def_bb;
kono
parents: 67
diff changeset
948 if (virtual_operand_p (gimple_phi_result (phi)))
kono
parents: 67
diff changeset
949 continue;
kono
parents: 67
diff changeset
950 arg = PHI_ARG_DEF_FROM_EDGE (phi, exit);
kono
parents: 67
diff changeset
951 if (TREE_CODE (arg) != SSA_NAME)
kono
parents: 67
diff changeset
952 continue;
kono
parents: 67
diff changeset
953 def = SSA_NAME_DEF_STMT (arg);
kono
parents: 67
diff changeset
954 if (!def)
kono
parents: 67
diff changeset
955 continue;
kono
parents: 67
diff changeset
956 def_bb = gimple_bb (def);
kono
parents: 67
diff changeset
957 if (!def_bb)
kono
parents: 67
diff changeset
958 continue;
kono
parents: 67
diff changeset
959 if (!dominated_by_p (CDI_DOMINATORS, pre_header, def_bb))
kono
parents: 67
diff changeset
960 /* Definition inside loop! */
kono
parents: 67
diff changeset
961 return false;
kono
parents: 67
diff changeset
962 /* Check loop closed phi invariant. */
kono
parents: 67
diff changeset
963 if (!flow_bb_inside_loop_p (def_bb->loop_father, pre_header))
kono
parents: 67
diff changeset
964 return false;
kono
parents: 67
diff changeset
965 }
kono
parents: 67
diff changeset
966 return true;
kono
parents: 67
diff changeset
967 }
kono
parents: 67
diff changeset
968
kono
parents: 67
diff changeset
969 /* Loop unswitching pass. */
kono
parents: 67
diff changeset
970
kono
parents: 67
diff changeset
971 namespace {
kono
parents: 67
diff changeset
972
kono
parents: 67
diff changeset
973 const pass_data pass_data_tree_unswitch =
kono
parents: 67
diff changeset
974 {
kono
parents: 67
diff changeset
975 GIMPLE_PASS, /* type */
kono
parents: 67
diff changeset
976 "unswitch", /* name */
kono
parents: 67
diff changeset
977 OPTGROUP_LOOP, /* optinfo_flags */
kono
parents: 67
diff changeset
978 TV_TREE_LOOP_UNSWITCH, /* tv_id */
kono
parents: 67
diff changeset
979 PROP_cfg, /* properties_required */
kono
parents: 67
diff changeset
980 0, /* properties_provided */
kono
parents: 67
diff changeset
981 0, /* properties_destroyed */
kono
parents: 67
diff changeset
982 0, /* todo_flags_start */
kono
parents: 67
diff changeset
983 0, /* todo_flags_finish */
kono
parents: 67
diff changeset
984 };
kono
parents: 67
diff changeset
985
kono
parents: 67
diff changeset
986 class pass_tree_unswitch : public gimple_opt_pass
kono
parents: 67
diff changeset
987 {
kono
parents: 67
diff changeset
988 public:
kono
parents: 67
diff changeset
989 pass_tree_unswitch (gcc::context *ctxt)
kono
parents: 67
diff changeset
990 : gimple_opt_pass (pass_data_tree_unswitch, ctxt)
kono
parents: 67
diff changeset
991 {}
kono
parents: 67
diff changeset
992
kono
parents: 67
diff changeset
993 /* opt_pass methods: */
kono
parents: 67
diff changeset
994 virtual bool gate (function *) { return flag_unswitch_loops != 0; }
kono
parents: 67
diff changeset
995 virtual unsigned int execute (function *);
kono
parents: 67
diff changeset
996
kono
parents: 67
diff changeset
997 }; // class pass_tree_unswitch
kono
parents: 67
diff changeset
998
kono
parents: 67
diff changeset
999 unsigned int
kono
parents: 67
diff changeset
1000 pass_tree_unswitch::execute (function *fun)
kono
parents: 67
diff changeset
1001 {
kono
parents: 67
diff changeset
1002 if (number_of_loops (fun) <= 1)
kono
parents: 67
diff changeset
1003 return 0;
kono
parents: 67
diff changeset
1004
kono
parents: 67
diff changeset
1005 return tree_ssa_unswitch_loops ();
kono
parents: 67
diff changeset
1006 }
kono
parents: 67
diff changeset
1007
kono
parents: 67
diff changeset
1008 } // anon namespace
kono
parents: 67
diff changeset
1009
kono
parents: 67
diff changeset
1010 gimple_opt_pass *
kono
parents: 67
diff changeset
1011 make_pass_tree_unswitch (gcc::context *ctxt)
kono
parents: 67
diff changeset
1012 {
kono
parents: 67
diff changeset
1013 return new pass_tree_unswitch (ctxt);
kono
parents: 67
diff changeset
1014 }
kono
parents: 67
diff changeset
1015
kono
parents: 67
diff changeset
1016