Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-ssa-phiopt.c @ 143:76e1cf5455ef
add cbc_gc test
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 23 Dec 2018 19:24:05 +0900 |
parents | 84e7813d76e9 |
children | 1830386684a0 |
rev | line source |
---|---|
0 | 1 /* Optimization of PHI nodes by converting them into straightline code. |
131 | 2 Copyright (C) 2004-2018 Free Software Foundation, Inc. |
0 | 3 |
4 This file is part of GCC. | |
5 | |
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. | |
10 | |
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. | |
15 | |
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" |
24 #include "insn-codes.h" | |
25 #include "rtl.h" | |
0 | 26 #include "tree.h" |
111 | 27 #include "gimple.h" |
28 #include "cfghooks.h" | |
0 | 29 #include "tree-pass.h" |
111 | 30 #include "ssa.h" |
31 #include "optabs-tree.h" | |
32 #include "insn-config.h" | |
33 #include "gimple-pretty-print.h" | |
34 #include "fold-const.h" | |
35 #include "stor-layout.h" | |
36 #include "cfganal.h" | |
37 #include "gimplify.h" | |
38 #include "gimple-iterator.h" | |
39 #include "gimplify-me.h" | |
40 #include "tree-cfg.h" | |
41 #include "tree-dfa.h" | |
0 | 42 #include "domwalk.h" |
111 | 43 #include "cfgloop.h" |
44 #include "tree-data-ref.h" | |
45 #include "tree-scalar-evolution.h" | |
46 #include "tree-inline.h" | |
47 #include "params.h" | |
131 | 48 #include "case-cfn-macros.h" |
49 | |
50 static unsigned int tree_ssa_phiopt_worker (bool, bool, bool); | |
0 | 51 static bool conditional_replacement (basic_block, basic_block, |
111 | 52 edge, edge, gphi *, tree, tree); |
53 static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree, | |
54 gimple *); | |
55 static int value_replacement (basic_block, basic_block, | |
56 edge, edge, gimple *, tree, tree); | |
0 | 57 static bool minmax_replacement (basic_block, basic_block, |
111 | 58 edge, edge, gimple *, tree, tree); |
0 | 59 static bool abs_replacement (basic_block, basic_block, |
111 | 60 edge, edge, gimple *, tree, tree); |
131 | 61 static bool cond_removal_in_popcount_pattern (basic_block, basic_block, |
62 edge, edge, gimple *, tree, tree); | |
0 | 63 static bool cond_store_replacement (basic_block, basic_block, edge, edge, |
111 | 64 hash_set<tree> *); |
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
|
65 static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block); |
111 | 66 static hash_set<tree> * get_non_trapping (); |
67 static void replace_phi_edge_with_variable (basic_block, edge, gimple *, tree); | |
68 static void hoist_adjacent_loads (basic_block, basic_block, | |
69 basic_block, basic_block); | |
70 static bool gate_hoist_loads (void); | |
0 | 71 |
72 /* This pass tries to transform conditional stores into unconditional | |
73 ones, enabling further simplifications with the simpler then and else | |
74 blocks. In particular it replaces this: | |
75 | |
76 bb0: | |
77 if (cond) goto bb2; else goto bb1; | |
78 bb1: | |
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
|
79 *p = RHS; |
0 | 80 bb2: |
81 | |
82 with | |
83 | |
84 bb0: | |
85 if (cond) goto bb1; else goto bb2; | |
86 bb1: | |
87 condtmp' = *p; | |
88 bb2: | |
89 condtmp = PHI <RHS, condtmp'> | |
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
|
90 *p = condtmp; |
0 | 91 |
92 This transformation can only be done under several constraints, | |
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
|
93 documented below. It also replaces: |
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
|
94 |
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
|
95 bb0: |
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
|
96 if (cond) goto bb2; else goto bb1; |
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
|
97 bb1: |
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
|
98 *p = RHS1; |
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
|
99 goto bb3; |
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
|
100 bb2: |
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
|
101 *p = RHS2; |
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
|
102 bb3: |
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
|
103 |
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
|
104 with |
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
|
105 |
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
|
106 bb0: |
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
|
107 if (cond) goto bb3; else goto bb1; |
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
|
108 bb1: |
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
|
109 bb3: |
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
|
110 condtmp = PHI <RHS1, RHS2> |
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
|
111 *p = condtmp; */ |
0 | 112 |
113 static unsigned int | |
114 tree_ssa_cs_elim (void) | |
115 { | |
111 | 116 unsigned todo; |
117 /* ??? We are not interested in loop related info, but the following | |
118 will create it, ICEing as we didn't init loops with pre-headers. | |
119 An interfacing issue of find_data_references_in_bb. */ | |
120 loop_optimizer_init (LOOPS_NORMAL); | |
121 scev_initialize (); | |
131 | 122 todo = tree_ssa_phiopt_worker (true, false, false); |
111 | 123 scev_finalize (); |
124 loop_optimizer_finalize (); | |
125 return todo; | |
0 | 126 } |
127 | |
111 | 128 /* Return the singleton PHI in the SEQ of PHIs for edges E0 and E1. */ |
129 | |
130 static gphi * | |
131 single_non_singleton_phi_for_edges (gimple_seq seq, edge e0, edge e1) | |
132 { | |
133 gimple_stmt_iterator i; | |
134 gphi *phi = NULL; | |
135 if (gimple_seq_singleton_p (seq)) | |
136 return as_a <gphi *> (gsi_stmt (gsi_start (seq))); | |
137 for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i)) | |
138 { | |
139 gphi *p = as_a <gphi *> (gsi_stmt (i)); | |
140 /* If the PHI arguments are equal then we can skip this PHI. */ | |
141 if (operand_equal_for_phi_arg_p (gimple_phi_arg_def (p, e0->dest_idx), | |
142 gimple_phi_arg_def (p, e1->dest_idx))) | |
143 continue; | |
144 | |
145 /* If we already have a PHI that has the two edge arguments are | |
146 different, then return it is not a singleton for these PHIs. */ | |
147 if (phi) | |
148 return NULL; | |
149 | |
150 phi = p; | |
151 } | |
152 return phi; | |
153 } | |
0 | 154 |
155 /* The core routine of conditional store replacement and normal | |
156 phi optimizations. Both share much of the infrastructure in how | |
157 to match applicable basic block patterns. DO_STORE_ELIM is true | |
111 | 158 when we want to do conditional store replacement, false otherwise. |
159 DO_HOIST_LOADS is true when we want to hoist adjacent loads out | |
160 of diamond control flow patterns, false otherwise. */ | |
0 | 161 static unsigned int |
131 | 162 tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p) |
0 | 163 { |
164 basic_block bb; | |
165 basic_block *bb_order; | |
166 unsigned n, i; | |
167 bool cfgchanged = false; | |
111 | 168 hash_set<tree> *nontrap = 0; |
0 | 169 |
170 if (do_store_elim) | |
111 | 171 /* Calculate the set of non-trapping memory accesses. */ |
172 nontrap = get_non_trapping (); | |
0 | 173 |
174 /* Search every basic block for COND_EXPR we may be able to optimize. | |
175 | |
176 We walk the blocks in order that guarantees that a block with | |
177 a single predecessor is processed before the predecessor. | |
178 This ensures that we collapse inner ifs before visiting the | |
179 outer ones, and also that we do not try to visit a removed | |
180 block. */ | |
111 | 181 bb_order = single_pred_before_succ_order (); |
182 n = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS; | |
0 | 183 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
184 for (i = 0; i < n; i++) |
0 | 185 { |
111 | 186 gimple *cond_stmt; |
187 gphi *phi; | |
0 | 188 basic_block bb1, bb2; |
189 edge e1, e2; | |
190 tree arg0, arg1; | |
191 | |
192 bb = bb_order[i]; | |
193 | |
194 cond_stmt = last_stmt (bb); | |
195 /* Check to see if the last statement is a GIMPLE_COND. */ | |
196 if (!cond_stmt | |
197 || gimple_code (cond_stmt) != GIMPLE_COND) | |
198 continue; | |
199 | |
200 e1 = EDGE_SUCC (bb, 0); | |
201 bb1 = e1->dest; | |
202 e2 = EDGE_SUCC (bb, 1); | |
203 bb2 = e2->dest; | |
204 | |
205 /* We cannot do the optimization on abnormal edges. */ | |
206 if ((e1->flags & EDGE_ABNORMAL) != 0 | |
207 || (e2->flags & EDGE_ABNORMAL) != 0) | |
208 continue; | |
209 | |
210 /* If either bb1's succ or bb2 or bb2's succ is non NULL. */ | |
211 if (EDGE_COUNT (bb1->succs) == 0 | |
212 || bb2 == NULL | |
213 || EDGE_COUNT (bb2->succs) == 0) | |
214 continue; | |
215 | |
216 /* Find the bb which is the fall through to the other. */ | |
217 if (EDGE_SUCC (bb1, 0)->dest == bb2) | |
218 ; | |
219 else if (EDGE_SUCC (bb2, 0)->dest == bb1) | |
220 { | |
111 | 221 std::swap (bb1, bb2); |
222 std::swap (e1, e2); | |
0 | 223 } |
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
|
224 else if (do_store_elim |
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
|
225 && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->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
|
226 { |
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
|
227 basic_block bb3 = EDGE_SUCC (bb1, 0)->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
|
228 |
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
|
229 if (!single_succ_p (bb1) |
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
|
230 || (EDGE_SUCC (bb1, 0)->flags & EDGE_FALLTHRU) == 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
|
231 || !single_succ_p (bb2) |
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
|
232 || (EDGE_SUCC (bb2, 0)->flags & EDGE_FALLTHRU) == 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
|
233 || EDGE_COUNT (bb3->preds) != 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
|
234 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
|
235 if (cond_if_else_store_replacement (bb1, bb2, bb3)) |
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
|
236 cfgchanged = true; |
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
|
237 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
|
238 } |
111 | 239 else if (do_hoist_loads |
240 && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest) | |
241 { | |
242 basic_block bb3 = EDGE_SUCC (bb1, 0)->dest; | |
243 | |
244 if (!FLOAT_TYPE_P (TREE_TYPE (gimple_cond_lhs (cond_stmt))) | |
245 && single_succ_p (bb1) | |
246 && single_succ_p (bb2) | |
247 && single_pred_p (bb1) | |
248 && single_pred_p (bb2) | |
249 && EDGE_COUNT (bb->succs) == 2 | |
250 && EDGE_COUNT (bb3->preds) == 2 | |
251 /* If one edge or the other is dominant, a conditional move | |
252 is likely to perform worse than the well-predicted branch. */ | |
253 && !predictable_edge_p (EDGE_SUCC (bb, 0)) | |
254 && !predictable_edge_p (EDGE_SUCC (bb, 1))) | |
255 hoist_adjacent_loads (bb, bb1, bb2, bb3); | |
256 continue; | |
257 } | |
0 | 258 else |
111 | 259 continue; |
0 | 260 |
261 e1 = EDGE_SUCC (bb1, 0); | |
262 | |
263 /* Make sure that bb1 is just a fall through. */ | |
264 if (!single_succ_p (bb1) | |
265 || (e1->flags & EDGE_FALLTHRU) == 0) | |
266 continue; | |
267 | |
268 /* Also make sure that bb1 only have one predecessor and that it | |
269 is bb. */ | |
270 if (!single_pred_p (bb1) | |
271 || single_pred (bb1) != bb) | |
272 continue; | |
273 | |
274 if (do_store_elim) | |
275 { | |
276 /* bb1 is the middle block, bb2 the join block, bb the split block, | |
277 e1 the fallthrough edge from bb1 to bb2. We can't do the | |
278 optimization if the join block has more than two predecessors. */ | |
279 if (EDGE_COUNT (bb2->preds) > 2) | |
280 continue; | |
281 if (cond_store_replacement (bb1, bb2, e1, e2, nontrap)) | |
282 cfgchanged = true; | |
283 } | |
284 else | |
285 { | |
286 gimple_seq phis = phi_nodes (bb2); | |
111 | 287 gimple_stmt_iterator gsi; |
288 bool candorest = true; | |
289 | |
290 /* Value replacement can work with more than one PHI | |
291 so try that first. */ | |
131 | 292 if (!early_p) |
293 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi)) | |
294 { | |
295 phi = as_a <gphi *> (gsi_stmt (gsi)); | |
296 arg0 = gimple_phi_arg_def (phi, e1->dest_idx); | |
297 arg1 = gimple_phi_arg_def (phi, e2->dest_idx); | |
298 if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1) == 2) | |
299 { | |
300 candorest = false; | |
301 cfgchanged = true; | |
302 break; | |
303 } | |
304 } | |
111 | 305 |
306 if (!candorest) | |
0 | 307 continue; |
308 | |
111 | 309 phi = single_non_singleton_phi_for_edges (phis, e1, e2); |
310 if (!phi) | |
311 continue; | |
312 | |
0 | 313 arg0 = gimple_phi_arg_def (phi, e1->dest_idx); |
314 arg1 = gimple_phi_arg_def (phi, e2->dest_idx); | |
315 | |
316 /* Something is wrong if we cannot find the arguments in the PHI | |
317 node. */ | |
111 | 318 gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE); |
319 | |
320 gphi *newphi = factor_out_conditional_conversion (e1, e2, phi, | |
321 arg0, arg1, | |
322 cond_stmt); | |
323 if (newphi != NULL) | |
324 { | |
325 phi = newphi; | |
326 /* factor_out_conditional_conversion may create a new PHI in | |
327 BB2 and eliminate an existing PHI in BB2. Recompute values | |
328 that may be affected by that change. */ | |
329 arg0 = gimple_phi_arg_def (phi, e1->dest_idx); | |
330 arg1 = gimple_phi_arg_def (phi, e2->dest_idx); | |
331 gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE); | |
332 } | |
0 | 333 |
334 /* Do the replacement of conditional if it can be done. */ | |
131 | 335 if (!early_p |
336 && conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) | |
0 | 337 cfgchanged = true; |
338 else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) | |
339 cfgchanged = true; | |
131 | 340 else if (!early_p |
341 && cond_removal_in_popcount_pattern (bb, bb1, e1, e2, | |
342 phi, arg0, arg1)) | |
343 cfgchanged = true; | |
0 | 344 else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) |
345 cfgchanged = true; | |
346 } | |
347 } | |
348 | |
349 free (bb_order); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
350 |
0 | 351 if (do_store_elim) |
111 | 352 delete nontrap; |
0 | 353 /* If the CFG has changed, we should cleanup the CFG. */ |
354 if (cfgchanged && do_store_elim) | |
355 { | |
356 /* In cond-store replacement we have added some loads on edges | |
357 and new VOPS (as we moved the store, and created a load). */ | |
358 gsi_commit_edge_inserts (); | |
359 return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals; | |
360 } | |
361 else if (cfgchanged) | |
362 return TODO_cleanup_cfg; | |
363 return 0; | |
364 } | |
365 | |
366 /* Replace PHI node element whose edge is E in block BB with variable NEW. | |
367 Remove the edge from COND_BLOCK which does not lead to BB (COND_BLOCK | |
368 is known to have two edges, one of which must reach BB). */ | |
369 | |
370 static void | |
371 replace_phi_edge_with_variable (basic_block cond_block, | |
111 | 372 edge e, gimple *phi, tree new_tree) |
0 | 373 { |
374 basic_block bb = gimple_bb (phi); | |
375 basic_block block_to_remove; | |
376 gimple_stmt_iterator gsi; | |
377 | |
378 /* Change the PHI argument to new. */ | |
379 SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new_tree); | |
380 | |
381 /* Remove the empty basic block. */ | |
382 if (EDGE_SUCC (cond_block, 0)->dest == bb) | |
383 { | |
384 EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU; | |
385 EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); | |
111 | 386 EDGE_SUCC (cond_block, 0)->probability = profile_probability::always (); |
0 | 387 |
388 block_to_remove = EDGE_SUCC (cond_block, 1)->dest; | |
389 } | |
390 else | |
391 { | |
392 EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU; | |
393 EDGE_SUCC (cond_block, 1)->flags | |
394 &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); | |
111 | 395 EDGE_SUCC (cond_block, 1)->probability = profile_probability::always (); |
0 | 396 |
397 block_to_remove = EDGE_SUCC (cond_block, 0)->dest; | |
398 } | |
399 delete_basic_block (block_to_remove); | |
400 | |
401 /* Eliminate the COND_EXPR at the end of COND_BLOCK. */ | |
402 gsi = gsi_last_bb (cond_block); | |
403 gsi_remove (&gsi, true); | |
404 | |
405 if (dump_file && (dump_flags & TDF_DETAILS)) | |
406 fprintf (dump_file, | |
407 "COND_EXPR in block %d and PHI in block %d converted to straightline code.\n", | |
408 cond_block->index, | |
409 bb->index); | |
410 } | |
411 | |
111 | 412 /* PR66726: Factor conversion out of COND_EXPR. If the arguments of the PHI |
413 stmt are CONVERT_STMT, factor out the conversion and perform the conversion | |
414 to the result of PHI stmt. COND_STMT is the controlling predicate. | |
415 Return the newly-created PHI, if any. */ | |
416 | |
417 static gphi * | |
418 factor_out_conditional_conversion (edge e0, edge e1, gphi *phi, | |
419 tree arg0, tree arg1, gimple *cond_stmt) | |
420 { | |
421 gimple *arg0_def_stmt = NULL, *arg1_def_stmt = NULL, *new_stmt; | |
422 tree new_arg0 = NULL_TREE, new_arg1 = NULL_TREE; | |
423 tree temp, result; | |
424 gphi *newphi; | |
425 gimple_stmt_iterator gsi, gsi_for_def; | |
426 source_location locus = gimple_location (phi); | |
427 enum tree_code convert_code; | |
428 | |
429 /* Handle only PHI statements with two arguments. TODO: If all | |
430 other arguments to PHI are INTEGER_CST or if their defining | |
431 statement have the same unary operation, we can handle more | |
432 than two arguments too. */ | |
433 if (gimple_phi_num_args (phi) != 2) | |
434 return NULL; | |
435 | |
436 /* First canonicalize to simplify tests. */ | |
437 if (TREE_CODE (arg0) != SSA_NAME) | |
438 { | |
439 std::swap (arg0, arg1); | |
440 std::swap (e0, e1); | |
441 } | |
442 | |
443 if (TREE_CODE (arg0) != SSA_NAME | |
444 || (TREE_CODE (arg1) != SSA_NAME | |
445 && TREE_CODE (arg1) != INTEGER_CST)) | |
446 return NULL; | |
447 | |
448 /* Check if arg0 is an SSA_NAME and the stmt which defines arg0 is | |
449 a conversion. */ | |
450 arg0_def_stmt = SSA_NAME_DEF_STMT (arg0); | |
451 if (!gimple_assign_cast_p (arg0_def_stmt)) | |
452 return NULL; | |
453 | |
454 /* Use the RHS as new_arg0. */ | |
455 convert_code = gimple_assign_rhs_code (arg0_def_stmt); | |
456 new_arg0 = gimple_assign_rhs1 (arg0_def_stmt); | |
457 if (convert_code == VIEW_CONVERT_EXPR) | |
458 { | |
459 new_arg0 = TREE_OPERAND (new_arg0, 0); | |
460 if (!is_gimple_reg_type (TREE_TYPE (new_arg0))) | |
461 return NULL; | |
462 } | |
463 | |
464 if (TREE_CODE (arg1) == SSA_NAME) | |
465 { | |
466 /* Check if arg1 is an SSA_NAME and the stmt which defines arg1 | |
467 is a conversion. */ | |
468 arg1_def_stmt = SSA_NAME_DEF_STMT (arg1); | |
469 if (!is_gimple_assign (arg1_def_stmt) | |
470 || gimple_assign_rhs_code (arg1_def_stmt) != convert_code) | |
471 return NULL; | |
472 | |
473 /* Use the RHS as new_arg1. */ | |
474 new_arg1 = gimple_assign_rhs1 (arg1_def_stmt); | |
475 if (convert_code == VIEW_CONVERT_EXPR) | |
476 new_arg1 = TREE_OPERAND (new_arg1, 0); | |
477 } | |
478 else | |
479 { | |
480 /* If arg1 is an INTEGER_CST, fold it to new type. */ | |
481 if (INTEGRAL_TYPE_P (TREE_TYPE (new_arg0)) | |
482 && int_fits_type_p (arg1, TREE_TYPE (new_arg0))) | |
483 { | |
484 if (gimple_assign_cast_p (arg0_def_stmt)) | |
485 { | |
486 /* For the INTEGER_CST case, we are just moving the | |
487 conversion from one place to another, which can often | |
488 hurt as the conversion moves further away from the | |
489 statement that computes the value. So, perform this | |
490 only if new_arg0 is an operand of COND_STMT, or | |
491 if arg0_def_stmt is the only non-debug stmt in | |
492 its basic block, because then it is possible this | |
493 could enable further optimizations (minmax replacement | |
494 etc.). See PR71016. */ | |
495 if (new_arg0 != gimple_cond_lhs (cond_stmt) | |
496 && new_arg0 != gimple_cond_rhs (cond_stmt) | |
497 && gimple_bb (arg0_def_stmt) == e0->src) | |
498 { | |
499 gsi = gsi_for_stmt (arg0_def_stmt); | |
500 gsi_prev_nondebug (&gsi); | |
501 if (!gsi_end_p (gsi)) | |
502 return NULL; | |
503 gsi = gsi_for_stmt (arg0_def_stmt); | |
504 gsi_next_nondebug (&gsi); | |
505 if (!gsi_end_p (gsi)) | |
506 return NULL; | |
507 } | |
508 new_arg1 = fold_convert (TREE_TYPE (new_arg0), arg1); | |
509 } | |
510 else | |
511 return NULL; | |
512 } | |
513 else | |
514 return NULL; | |
515 } | |
516 | |
517 /* If arg0/arg1 have > 1 use, then this transformation actually increases | |
518 the number of expressions evaluated at runtime. */ | |
519 if (!has_single_use (arg0) | |
520 || (arg1_def_stmt && !has_single_use (arg1))) | |
521 return NULL; | |
522 | |
523 /* If types of new_arg0 and new_arg1 are different bailout. */ | |
524 if (!types_compatible_p (TREE_TYPE (new_arg0), TREE_TYPE (new_arg1))) | |
525 return NULL; | |
526 | |
527 /* Create a new PHI stmt. */ | |
528 result = PHI_RESULT (phi); | |
529 temp = make_ssa_name (TREE_TYPE (new_arg0), NULL); | |
530 newphi = create_phi_node (temp, gimple_bb (phi)); | |
531 | |
532 if (dump_file && (dump_flags & TDF_DETAILS)) | |
533 { | |
534 fprintf (dump_file, "PHI "); | |
535 print_generic_expr (dump_file, gimple_phi_result (phi)); | |
536 fprintf (dump_file, | |
537 " changed to factor conversion out from COND_EXPR.\n"); | |
538 fprintf (dump_file, "New stmt with CAST that defines "); | |
539 print_generic_expr (dump_file, result); | |
540 fprintf (dump_file, ".\n"); | |
541 } | |
542 | |
543 /* Remove the old cast(s) that has single use. */ | |
544 gsi_for_def = gsi_for_stmt (arg0_def_stmt); | |
545 gsi_remove (&gsi_for_def, true); | |
546 release_defs (arg0_def_stmt); | |
547 | |
548 if (arg1_def_stmt) | |
549 { | |
550 gsi_for_def = gsi_for_stmt (arg1_def_stmt); | |
551 gsi_remove (&gsi_for_def, true); | |
552 release_defs (arg1_def_stmt); | |
553 } | |
554 | |
555 add_phi_arg (newphi, new_arg0, e0, locus); | |
556 add_phi_arg (newphi, new_arg1, e1, locus); | |
557 | |
558 /* Create the conversion stmt and insert it. */ | |
559 if (convert_code == VIEW_CONVERT_EXPR) | |
131 | 560 { |
561 temp = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (result), temp); | |
562 new_stmt = gimple_build_assign (result, temp); | |
563 } | |
564 else | |
565 new_stmt = gimple_build_assign (result, convert_code, temp); | |
111 | 566 gsi = gsi_after_labels (gimple_bb (phi)); |
567 gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT); | |
568 | |
569 /* Remove the original PHI stmt. */ | |
570 gsi = gsi_for_stmt (phi); | |
571 gsi_remove (&gsi, true); | |
572 return newphi; | |
573 } | |
574 | |
0 | 575 /* The function conditional_replacement does the main work of doing the |
576 conditional replacement. Return true if the replacement is done. | |
577 Otherwise return false. | |
578 BB is the basic block where the replacement is going to be done on. ARG0 | |
579 is argument 0 from PHI. Likewise for ARG1. */ | |
580 | |
581 static bool | |
582 conditional_replacement (basic_block cond_bb, basic_block middle_bb, | |
111 | 583 edge e0, edge e1, gphi *phi, |
0 | 584 tree arg0, tree arg1) |
585 { | |
586 tree result; | |
111 | 587 gimple *stmt; |
588 gassign *new_stmt; | |
0 | 589 tree cond; |
590 gimple_stmt_iterator gsi; | |
591 edge true_edge, false_edge; | |
592 tree new_var, new_var2; | |
111 | 593 bool neg; |
0 | 594 |
595 /* FIXME: Gimplification of complex type is too hard for now. */ | |
111 | 596 /* We aren't prepared to handle vectors either (and it is a question |
597 if it would be worthwhile anyway). */ | |
598 if (!(INTEGRAL_TYPE_P (TREE_TYPE (arg0)) | |
599 || POINTER_TYPE_P (TREE_TYPE (arg0))) | |
600 || !(INTEGRAL_TYPE_P (TREE_TYPE (arg1)) | |
601 || POINTER_TYPE_P (TREE_TYPE (arg1)))) | |
0 | 602 return false; |
603 | |
111 | 604 /* The PHI arguments have the constants 0 and 1, or 0 and -1, then |
605 convert it to the conditional. */ | |
0 | 606 if ((integer_zerop (arg0) && integer_onep (arg1)) |
607 || (integer_zerop (arg1) && integer_onep (arg0))) | |
111 | 608 neg = false; |
609 else if ((integer_zerop (arg0) && integer_all_onesp (arg1)) | |
610 || (integer_zerop (arg1) && integer_all_onesp (arg0))) | |
611 neg = true; | |
0 | 612 else |
613 return false; | |
614 | |
615 if (!empty_block_p (middle_bb)) | |
616 return false; | |
617 | |
618 /* At this point we know we have a GIMPLE_COND with two successors. | |
619 One successor is BB, the other successor is an empty block which | |
620 falls through into BB. | |
621 | |
622 There is a single PHI node at the join point (BB) and its arguments | |
111 | 623 are constants (0, 1) or (0, -1). |
0 | 624 |
625 So, given the condition COND, and the two PHI arguments, we can | |
626 rewrite this PHI into non-branching code: | |
627 | |
628 dest = (COND) or dest = COND' | |
629 | |
630 We use the condition as-is if the argument associated with the | |
631 true edge has the value one or the argument associated with the | |
632 false edge as the value zero. Note that those conditions are not | |
633 the same since only one of the outgoing edges from the GIMPLE_COND | |
634 will directly reach BB and thus be associated with an argument. */ | |
635 | |
636 stmt = last_stmt (cond_bb); | |
637 result = PHI_RESULT (phi); | |
638 | |
639 /* To handle special cases like floating point comparison, it is easier and | |
640 less error-prone to build a tree and gimplify it on the fly though it is | |
641 less efficient. */ | |
111 | 642 cond = fold_build2_loc (gimple_location (stmt), |
643 gimple_cond_code (stmt), boolean_type_node, | |
644 gimple_cond_lhs (stmt), gimple_cond_rhs (stmt)); | |
0 | 645 |
646 /* We need to know which is the true edge and which is the false | |
647 edge so that we know when to invert the condition below. */ | |
648 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge); | |
649 if ((e0 == true_edge && integer_zerop (arg0)) | |
111 | 650 || (e0 == false_edge && !integer_zerop (arg0)) |
0 | 651 || (e1 == true_edge && integer_zerop (arg1)) |
111 | 652 || (e1 == false_edge && !integer_zerop (arg1))) |
653 cond = fold_build1_loc (gimple_location (stmt), | |
654 TRUTH_NOT_EXPR, TREE_TYPE (cond), cond); | |
655 | |
656 if (neg) | |
657 { | |
658 cond = fold_convert_loc (gimple_location (stmt), | |
659 TREE_TYPE (result), cond); | |
660 cond = fold_build1_loc (gimple_location (stmt), | |
661 NEGATE_EXPR, TREE_TYPE (cond), cond); | |
662 } | |
0 | 663 |
664 /* Insert our new statements at the end of conditional block before the | |
665 COND_STMT. */ | |
666 gsi = gsi_for_stmt (stmt); | |
667 new_var = force_gimple_operand_gsi (&gsi, cond, true, NULL, true, | |
668 GSI_SAME_STMT); | |
669 | |
670 if (!useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (new_var))) | |
671 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
672 source_location locus_0, locus_1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
673 |
111 | 674 new_var2 = make_ssa_name (TREE_TYPE (result)); |
675 new_stmt = gimple_build_assign (new_var2, CONVERT_EXPR, new_var); | |
0 | 676 gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT); |
677 new_var = new_var2; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
678 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
679 /* Set the locus to the first argument, unless is doesn't have one. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
680 locus_0 = gimple_phi_arg_location (phi, 0); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
681 locus_1 = gimple_phi_arg_location (phi, 1); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
682 if (locus_0 == UNKNOWN_LOCATION) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
683 locus_0 = locus_1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
684 gimple_set_location (new_stmt, locus_0); |
0 | 685 } |
686 | |
687 replace_phi_edge_with_variable (cond_bb, e1, phi, new_var); | |
688 | |
689 /* Note that we optimized this PHI. */ | |
690 return true; | |
691 } | |
692 | |
111 | 693 /* Update *ARG which is defined in STMT so that it contains the |
694 computed value if that seems profitable. Return true if the | |
695 statement is made dead by that rewriting. */ | |
696 | |
697 static bool | |
698 jump_function_from_stmt (tree *arg, gimple *stmt) | |
699 { | |
700 enum tree_code code = gimple_assign_rhs_code (stmt); | |
701 if (code == ADDR_EXPR) | |
702 { | |
703 /* For arg = &p->i transform it to p, if possible. */ | |
704 tree rhs1 = gimple_assign_rhs1 (stmt); | |
131 | 705 poly_int64 offset; |
111 | 706 tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (rhs1, 0), |
707 &offset); | |
708 if (tem | |
709 && TREE_CODE (tem) == MEM_REF | |
131 | 710 && known_eq (mem_ref_offset (tem) + offset, 0)) |
111 | 711 { |
712 *arg = TREE_OPERAND (tem, 0); | |
713 return true; | |
714 } | |
715 } | |
716 /* TODO: Much like IPA-CP jump-functions we want to handle constant | |
717 additions symbolically here, and we'd need to update the comparison | |
718 code that compares the arg + cst tuples in our caller. For now the | |
719 code above exactly handles the VEC_BASE pattern from vec.h. */ | |
720 return false; | |
721 } | |
722 | |
723 /* RHS is a source argument in a BIT_AND_EXPR which feeds a conditional | |
724 of the form SSA_NAME NE 0. | |
725 | |
726 If RHS is fed by a simple EQ_EXPR comparison of two values, see if | |
727 the two input values of the EQ_EXPR match arg0 and arg1. | |
728 | |
729 If so update *code and return TRUE. Otherwise return FALSE. */ | |
730 | |
731 static bool | |
732 rhs_is_fed_for_value_replacement (const_tree arg0, const_tree arg1, | |
733 enum tree_code *code, const_tree rhs) | |
734 { | |
735 /* Obviously if RHS is not an SSA_NAME, we can't look at the defining | |
736 statement. */ | |
737 if (TREE_CODE (rhs) == SSA_NAME) | |
738 { | |
739 gimple *def1 = SSA_NAME_DEF_STMT (rhs); | |
740 | |
741 /* Verify the defining statement has an EQ_EXPR on the RHS. */ | |
742 if (is_gimple_assign (def1) && gimple_assign_rhs_code (def1) == EQ_EXPR) | |
743 { | |
744 /* Finally verify the source operands of the EQ_EXPR are equal | |
745 to arg0 and arg1. */ | |
746 tree op0 = gimple_assign_rhs1 (def1); | |
747 tree op1 = gimple_assign_rhs2 (def1); | |
748 if ((operand_equal_for_phi_arg_p (arg0, op0) | |
749 && operand_equal_for_phi_arg_p (arg1, op1)) | |
750 || (operand_equal_for_phi_arg_p (arg0, op1) | |
751 && operand_equal_for_phi_arg_p (arg1, op0))) | |
752 { | |
753 /* We will perform the optimization. */ | |
754 *code = gimple_assign_rhs_code (def1); | |
755 return true; | |
756 } | |
757 } | |
758 } | |
759 return false; | |
760 } | |
761 | |
762 /* Return TRUE if arg0/arg1 are equal to the rhs/lhs or lhs/rhs of COND. | |
763 | |
764 Also return TRUE if arg0/arg1 are equal to the source arguments of a | |
765 an EQ comparison feeding a BIT_AND_EXPR which feeds COND. | |
766 | |
767 Return FALSE otherwise. */ | |
0 | 768 |
769 static bool | |
111 | 770 operand_equal_for_value_replacement (const_tree arg0, const_tree arg1, |
771 enum tree_code *code, gimple *cond) | |
772 { | |
773 gimple *def; | |
774 tree lhs = gimple_cond_lhs (cond); | |
775 tree rhs = gimple_cond_rhs (cond); | |
776 | |
777 if ((operand_equal_for_phi_arg_p (arg0, lhs) | |
778 && operand_equal_for_phi_arg_p (arg1, rhs)) | |
779 || (operand_equal_for_phi_arg_p (arg1, lhs) | |
780 && operand_equal_for_phi_arg_p (arg0, rhs))) | |
781 return true; | |
782 | |
783 /* Now handle more complex case where we have an EQ comparison | |
784 which feeds a BIT_AND_EXPR which feeds COND. | |
785 | |
786 First verify that COND is of the form SSA_NAME NE 0. */ | |
787 if (*code != NE_EXPR || !integer_zerop (rhs) | |
788 || TREE_CODE (lhs) != SSA_NAME) | |
789 return false; | |
790 | |
791 /* Now ensure that SSA_NAME is set by a BIT_AND_EXPR. */ | |
792 def = SSA_NAME_DEF_STMT (lhs); | |
793 if (!is_gimple_assign (def) || gimple_assign_rhs_code (def) != BIT_AND_EXPR) | |
794 return false; | |
795 | |
796 /* Now verify arg0/arg1 correspond to the source arguments of an | |
797 EQ comparison feeding the BIT_AND_EXPR. */ | |
798 | |
799 tree tmp = gimple_assign_rhs1 (def); | |
800 if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp)) | |
801 return true; | |
802 | |
803 tmp = gimple_assign_rhs2 (def); | |
804 if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp)) | |
805 return true; | |
806 | |
807 return false; | |
808 } | |
809 | |
810 /* Returns true if ARG is a neutral element for operation CODE | |
811 on the RIGHT side. */ | |
812 | |
813 static bool | |
814 neutral_element_p (tree_code code, tree arg, bool right) | |
815 { | |
816 switch (code) | |
817 { | |
818 case PLUS_EXPR: | |
819 case BIT_IOR_EXPR: | |
820 case BIT_XOR_EXPR: | |
821 return integer_zerop (arg); | |
822 | |
823 case LROTATE_EXPR: | |
824 case RROTATE_EXPR: | |
825 case LSHIFT_EXPR: | |
826 case RSHIFT_EXPR: | |
827 case MINUS_EXPR: | |
828 case POINTER_PLUS_EXPR: | |
829 return right && integer_zerop (arg); | |
830 | |
831 case MULT_EXPR: | |
832 return integer_onep (arg); | |
833 | |
834 case TRUNC_DIV_EXPR: | |
835 case CEIL_DIV_EXPR: | |
836 case FLOOR_DIV_EXPR: | |
837 case ROUND_DIV_EXPR: | |
838 case EXACT_DIV_EXPR: | |
839 return right && integer_onep (arg); | |
840 | |
841 case BIT_AND_EXPR: | |
842 return integer_all_onesp (arg); | |
843 | |
844 default: | |
845 return false; | |
846 } | |
847 } | |
848 | |
849 /* Returns true if ARG is an absorbing element for operation CODE. */ | |
850 | |
851 static bool | |
852 absorbing_element_p (tree_code code, tree arg, bool right, tree rval) | |
853 { | |
854 switch (code) | |
855 { | |
856 case BIT_IOR_EXPR: | |
857 return integer_all_onesp (arg); | |
858 | |
859 case MULT_EXPR: | |
860 case BIT_AND_EXPR: | |
861 return integer_zerop (arg); | |
862 | |
863 case LSHIFT_EXPR: | |
864 case RSHIFT_EXPR: | |
865 case LROTATE_EXPR: | |
866 case RROTATE_EXPR: | |
867 return !right && integer_zerop (arg); | |
868 | |
869 case TRUNC_DIV_EXPR: | |
870 case CEIL_DIV_EXPR: | |
871 case FLOOR_DIV_EXPR: | |
872 case ROUND_DIV_EXPR: | |
873 case EXACT_DIV_EXPR: | |
874 case TRUNC_MOD_EXPR: | |
875 case CEIL_MOD_EXPR: | |
876 case FLOOR_MOD_EXPR: | |
877 case ROUND_MOD_EXPR: | |
878 return (!right | |
879 && integer_zerop (arg) | |
880 && tree_single_nonzero_warnv_p (rval, NULL)); | |
881 | |
882 default: | |
883 return false; | |
884 } | |
885 } | |
886 | |
887 /* The function value_replacement does the main work of doing the value | |
888 replacement. Return non-zero if the replacement is done. Otherwise return | |
889 0. If we remove the middle basic block, return 2. | |
890 BB is the basic block where the replacement is going to be done on. ARG0 | |
891 is argument 0 from the PHI. Likewise for ARG1. */ | |
892 | |
893 static int | |
0 | 894 value_replacement (basic_block cond_bb, basic_block middle_bb, |
111 | 895 edge e0, edge e1, gimple *phi, |
0 | 896 tree arg0, tree arg1) |
897 { | |
111 | 898 gimple_stmt_iterator gsi; |
899 gimple *cond; | |
0 | 900 edge true_edge, false_edge; |
901 enum tree_code code; | |
111 | 902 bool emtpy_or_with_defined_p = true; |
0 | 903 |
904 /* If the type says honor signed zeros we cannot do this | |
905 optimization. */ | |
111 | 906 if (HONOR_SIGNED_ZEROS (arg1)) |
907 return 0; | |
908 | |
909 /* If there is a statement in MIDDLE_BB that defines one of the PHI | |
910 arguments, then adjust arg0 or arg1. */ | |
911 gsi = gsi_start_nondebug_after_labels_bb (middle_bb); | |
912 while (!gsi_end_p (gsi)) | |
913 { | |
914 gimple *stmt = gsi_stmt (gsi); | |
915 tree lhs; | |
916 gsi_next_nondebug (&gsi); | |
917 if (!is_gimple_assign (stmt)) | |
918 { | |
131 | 919 if (gimple_code (stmt) != GIMPLE_PREDICT |
920 && gimple_code (stmt) != GIMPLE_NOP) | |
921 emtpy_or_with_defined_p = false; | |
111 | 922 continue; |
923 } | |
924 /* Now try to adjust arg0 or arg1 according to the computation | |
925 in the statement. */ | |
926 lhs = gimple_assign_lhs (stmt); | |
927 if (!(lhs == arg0 | |
928 && jump_function_from_stmt (&arg0, stmt)) | |
929 || (lhs == arg1 | |
930 && jump_function_from_stmt (&arg1, stmt))) | |
931 emtpy_or_with_defined_p = false; | |
932 } | |
0 | 933 |
934 cond = last_stmt (cond_bb); | |
935 code = gimple_cond_code (cond); | |
936 | |
937 /* This transformation is only valid for equality comparisons. */ | |
938 if (code != NE_EXPR && code != EQ_EXPR) | |
111 | 939 return 0; |
0 | 940 |
941 /* We need to know which is the true edge and which is the false | |
942 edge so that we know if have abs or negative abs. */ | |
943 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge); | |
944 | |
945 /* At this point we know we have a COND_EXPR with two successors. | |
946 One successor is BB, the other successor is an empty block which | |
947 falls through into BB. | |
948 | |
949 The condition for the COND_EXPR is known to be NE_EXPR or EQ_EXPR. | |
950 | |
951 There is a single PHI node at the join point (BB) with two arguments. | |
952 | |
953 We now need to verify that the two arguments in the PHI node match | |
954 the two arguments to the equality comparison. */ | |
955 | |
111 | 956 if (operand_equal_for_value_replacement (arg0, arg1, &code, cond)) |
0 | 957 { |
958 edge e; | |
959 tree arg; | |
960 | |
961 /* For NE_EXPR, we want to build an assignment result = arg where | |
962 arg is the PHI argument associated with the true edge. For | |
963 EQ_EXPR we want the PHI argument associated with the false edge. */ | |
964 e = (code == NE_EXPR ? true_edge : false_edge); | |
965 | |
966 /* Unfortunately, E may not reach BB (it may instead have gone to | |
967 OTHER_BLOCK). If that is the case, then we want the single outgoing | |
968 edge from OTHER_BLOCK which reaches BB and represents the desired | |
969 path from COND_BLOCK. */ | |
970 if (e->dest == middle_bb) | |
971 e = single_succ_edge (e->dest); | |
972 | |
973 /* Now we know the incoming edge to BB that has the argument for the | |
974 RHS of our new assignment statement. */ | |
975 if (e0 == e) | |
976 arg = arg0; | |
977 else | |
978 arg = arg1; | |
979 | |
111 | 980 /* If the middle basic block was empty or is defining the |
981 PHI arguments and this is a single phi where the args are different | |
982 for the edges e0 and e1 then we can remove the middle basic block. */ | |
983 if (emtpy_or_with_defined_p | |
984 && single_non_singleton_phi_for_edges (phi_nodes (gimple_bb (phi)), | |
985 e0, e1) == phi) | |
986 { | |
987 replace_phi_edge_with_variable (cond_bb, e1, phi, arg); | |
988 /* Note that we optimized this PHI. */ | |
989 return 2; | |
990 } | |
991 else | |
992 { | |
993 /* Replace the PHI arguments with arg. */ | |
994 SET_PHI_ARG_DEF (phi, e0->dest_idx, arg); | |
995 SET_PHI_ARG_DEF (phi, e1->dest_idx, arg); | |
996 if (dump_file && (dump_flags & TDF_DETAILS)) | |
997 { | |
998 fprintf (dump_file, "PHI "); | |
999 print_generic_expr (dump_file, gimple_phi_result (phi)); | |
1000 fprintf (dump_file, " reduced for COND_EXPR in block %d to ", | |
1001 cond_bb->index); | |
1002 print_generic_expr (dump_file, arg); | |
1003 fprintf (dump_file, ".\n"); | |
1004 } | |
1005 return 1; | |
1006 } | |
1007 | |
0 | 1008 } |
111 | 1009 |
1010 /* Now optimize (x != 0) ? x + y : y to just x + y. */ | |
1011 gsi = gsi_last_nondebug_bb (middle_bb); | |
1012 if (gsi_end_p (gsi)) | |
1013 return 0; | |
1014 | |
1015 gimple *assign = gsi_stmt (gsi); | |
1016 if (!is_gimple_assign (assign) | |
1017 || gimple_assign_rhs_class (assign) != GIMPLE_BINARY_RHS | |
1018 || (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)) | |
1019 && !POINTER_TYPE_P (TREE_TYPE (arg0)))) | |
1020 return 0; | |
1021 | |
1022 /* Punt if there are (degenerate) PHIs in middle_bb, there should not be. */ | |
1023 if (!gimple_seq_empty_p (phi_nodes (middle_bb))) | |
1024 return 0; | |
1025 | |
1026 /* Allow up to 2 cheap preparation statements that prepare argument | |
1027 for assign, e.g.: | |
1028 if (y_4 != 0) | |
1029 goto <bb 3>; | |
1030 else | |
1031 goto <bb 4>; | |
1032 <bb 3>: | |
1033 _1 = (int) y_4; | |
1034 iftmp.0_6 = x_5(D) r<< _1; | |
1035 <bb 4>: | |
1036 # iftmp.0_2 = PHI <iftmp.0_6(3), x_5(D)(2)> | |
1037 or: | |
1038 if (y_3(D) == 0) | |
1039 goto <bb 4>; | |
1040 else | |
1041 goto <bb 3>; | |
1042 <bb 3>: | |
1043 y_4 = y_3(D) & 31; | |
1044 _1 = (int) y_4; | |
1045 _6 = x_5(D) r<< _1; | |
1046 <bb 4>: | |
1047 # _2 = PHI <x_5(D)(2), _6(3)> */ | |
1048 gimple *prep_stmt[2] = { NULL, NULL }; | |
1049 int prep_cnt; | |
1050 for (prep_cnt = 0; ; prep_cnt++) | |
1051 { | |
1052 gsi_prev_nondebug (&gsi); | |
1053 if (gsi_end_p (gsi)) | |
1054 break; | |
1055 | |
1056 gimple *g = gsi_stmt (gsi); | |
1057 if (gimple_code (g) == GIMPLE_LABEL) | |
1058 break; | |
1059 | |
1060 if (prep_cnt == 2 || !is_gimple_assign (g)) | |
1061 return 0; | |
1062 | |
1063 tree lhs = gimple_assign_lhs (g); | |
1064 tree rhs1 = gimple_assign_rhs1 (g); | |
1065 use_operand_p use_p; | |
1066 gimple *use_stmt; | |
1067 if (TREE_CODE (lhs) != SSA_NAME | |
1068 || TREE_CODE (rhs1) != SSA_NAME | |
1069 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs)) | |
1070 || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1)) | |
1071 || !single_imm_use (lhs, &use_p, &use_stmt) | |
1072 || use_stmt != (prep_cnt ? prep_stmt[prep_cnt - 1] : assign)) | |
1073 return 0; | |
1074 switch (gimple_assign_rhs_code (g)) | |
1075 { | |
1076 CASE_CONVERT: | |
1077 break; | |
1078 case PLUS_EXPR: | |
1079 case BIT_AND_EXPR: | |
1080 case BIT_IOR_EXPR: | |
1081 case BIT_XOR_EXPR: | |
1082 if (TREE_CODE (gimple_assign_rhs2 (g)) != INTEGER_CST) | |
1083 return 0; | |
1084 break; | |
1085 default: | |
1086 return 0; | |
1087 } | |
1088 prep_stmt[prep_cnt] = g; | |
1089 } | |
1090 | |
1091 /* Only transform if it removes the condition. */ | |
1092 if (!single_non_singleton_phi_for_edges (phi_nodes (gimple_bb (phi)), e0, e1)) | |
1093 return 0; | |
1094 | |
1095 /* Size-wise, this is always profitable. */ | |
1096 if (optimize_bb_for_speed_p (cond_bb) | |
1097 /* The special case is useless if it has a low probability. */ | |
1098 && profile_status_for_fn (cfun) != PROFILE_ABSENT | |
1099 && EDGE_PRED (middle_bb, 0)->probability < profile_probability::even () | |
1100 /* If assign is cheap, there is no point avoiding it. */ | |
1101 && estimate_num_insns (bb_seq (middle_bb), &eni_time_weights) | |
1102 >= 3 * estimate_num_insns (cond, &eni_time_weights)) | |
1103 return 0; | |
1104 | |
1105 tree lhs = gimple_assign_lhs (assign); | |
1106 tree rhs1 = gimple_assign_rhs1 (assign); | |
1107 tree rhs2 = gimple_assign_rhs2 (assign); | |
1108 enum tree_code code_def = gimple_assign_rhs_code (assign); | |
1109 tree cond_lhs = gimple_cond_lhs (cond); | |
1110 tree cond_rhs = gimple_cond_rhs (cond); | |
1111 | |
1112 /* Propagate the cond_rhs constant through preparation stmts, | |
1113 make sure UB isn't invoked while doing that. */ | |
1114 for (int i = prep_cnt - 1; i >= 0; --i) | |
1115 { | |
1116 gimple *g = prep_stmt[i]; | |
1117 tree grhs1 = gimple_assign_rhs1 (g); | |
1118 if (!operand_equal_for_phi_arg_p (cond_lhs, grhs1)) | |
1119 return 0; | |
1120 cond_lhs = gimple_assign_lhs (g); | |
1121 cond_rhs = fold_convert (TREE_TYPE (grhs1), cond_rhs); | |
1122 if (TREE_CODE (cond_rhs) != INTEGER_CST | |
1123 || TREE_OVERFLOW (cond_rhs)) | |
1124 return 0; | |
1125 if (gimple_assign_rhs_class (g) == GIMPLE_BINARY_RHS) | |
1126 { | |
1127 cond_rhs = int_const_binop (gimple_assign_rhs_code (g), cond_rhs, | |
1128 gimple_assign_rhs2 (g)); | |
1129 if (TREE_OVERFLOW (cond_rhs)) | |
1130 return 0; | |
1131 } | |
1132 cond_rhs = fold_convert (TREE_TYPE (cond_lhs), cond_rhs); | |
1133 if (TREE_CODE (cond_rhs) != INTEGER_CST | |
1134 || TREE_OVERFLOW (cond_rhs)) | |
1135 return 0; | |
1136 } | |
1137 | |
1138 if (((code == NE_EXPR && e1 == false_edge) | |
1139 || (code == EQ_EXPR && e1 == true_edge)) | |
1140 && arg0 == lhs | |
1141 && ((arg1 == rhs1 | |
1142 && operand_equal_for_phi_arg_p (rhs2, cond_lhs) | |
1143 && neutral_element_p (code_def, cond_rhs, true)) | |
1144 || (arg1 == rhs2 | |
1145 && operand_equal_for_phi_arg_p (rhs1, cond_lhs) | |
1146 && neutral_element_p (code_def, cond_rhs, false)) | |
1147 || (operand_equal_for_phi_arg_p (arg1, cond_rhs) | |
1148 && ((operand_equal_for_phi_arg_p (rhs2, cond_lhs) | |
1149 && absorbing_element_p (code_def, cond_rhs, true, rhs2)) | |
1150 || (operand_equal_for_phi_arg_p (rhs1, cond_lhs) | |
1151 && absorbing_element_p (code_def, | |
1152 cond_rhs, false, rhs2)))))) | |
1153 { | |
1154 gsi = gsi_for_stmt (cond); | |
131 | 1155 /* Moving ASSIGN might change VR of lhs, e.g. when moving u_6 |
1156 def-stmt in: | |
1157 if (n_5 != 0) | |
1158 goto <bb 3>; | |
1159 else | |
1160 goto <bb 4>; | |
1161 | |
1162 <bb 3>: | |
1163 # RANGE [0, 4294967294] | |
1164 u_6 = n_5 + 4294967295; | |
1165 | |
1166 <bb 4>: | |
1167 # u_3 = PHI <u_6(3), 4294967295(2)> */ | |
1168 reset_flow_sensitive_info (lhs); | |
111 | 1169 if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))) |
1170 { | |
1171 /* If available, we can use VR of phi result at least. */ | |
1172 tree phires = gimple_phi_result (phi); | |
1173 struct range_info_def *phires_range_info | |
1174 = SSA_NAME_RANGE_INFO (phires); | |
1175 if (phires_range_info) | |
1176 duplicate_ssa_name_range_info (lhs, SSA_NAME_RANGE_TYPE (phires), | |
1177 phires_range_info); | |
1178 } | |
1179 gimple_stmt_iterator gsi_from; | |
1180 for (int i = prep_cnt - 1; i >= 0; --i) | |
1181 { | |
1182 tree plhs = gimple_assign_lhs (prep_stmt[i]); | |
131 | 1183 reset_flow_sensitive_info (plhs); |
111 | 1184 gsi_from = gsi_for_stmt (prep_stmt[i]); |
1185 gsi_move_before (&gsi_from, &gsi); | |
1186 } | |
1187 gsi_from = gsi_for_stmt (assign); | |
1188 gsi_move_before (&gsi_from, &gsi); | |
1189 replace_phi_edge_with_variable (cond_bb, e1, phi, lhs); | |
1190 return 2; | |
1191 } | |
1192 | |
1193 return 0; | |
0 | 1194 } |
1195 | |
1196 /* The function minmax_replacement does the main work of doing the minmax | |
1197 replacement. Return true if the replacement is done. Otherwise return | |
1198 false. | |
1199 BB is the basic block where the replacement is going to be done on. ARG0 | |
1200 is argument 0 from the PHI. Likewise for ARG1. */ | |
1201 | |
1202 static bool | |
1203 minmax_replacement (basic_block cond_bb, basic_block middle_bb, | |
111 | 1204 edge e0, edge e1, gimple *phi, |
0 | 1205 tree arg0, tree arg1) |
1206 { | |
1207 tree result, type; | |
111 | 1208 gcond *cond; |
1209 gassign *new_stmt; | |
0 | 1210 edge true_edge, false_edge; |
1211 enum tree_code cmp, minmax, ass_code; | |
111 | 1212 tree smaller, alt_smaller, larger, alt_larger, arg_true, arg_false; |
0 | 1213 gimple_stmt_iterator gsi, gsi_from; |
1214 | |
1215 type = TREE_TYPE (PHI_RESULT (phi)); | |
1216 | |
1217 /* The optimization may be unsafe due to NaNs. */ | |
111 | 1218 if (HONOR_NANS (type) || HONOR_SIGNED_ZEROS (type)) |
0 | 1219 return false; |
1220 | |
111 | 1221 cond = as_a <gcond *> (last_stmt (cond_bb)); |
0 | 1222 cmp = gimple_cond_code (cond); |
1223 | |
1224 /* This transformation is only valid for order comparisons. Record which | |
1225 operand is smaller/larger if the result of the comparison is true. */ | |
111 | 1226 alt_smaller = NULL_TREE; |
1227 alt_larger = NULL_TREE; | |
0 | 1228 if (cmp == LT_EXPR || cmp == LE_EXPR) |
1229 { | |
1230 smaller = gimple_cond_lhs (cond); | |
1231 larger = gimple_cond_rhs (cond); | |
111 | 1232 /* If we have smaller < CST it is equivalent to smaller <= CST-1. |
1233 Likewise smaller <= CST is equivalent to smaller < CST+1. */ | |
1234 if (TREE_CODE (larger) == INTEGER_CST) | |
1235 { | |
1236 if (cmp == LT_EXPR) | |
1237 { | |
131 | 1238 wi::overflow_type overflow; |
111 | 1239 wide_int alt = wi::sub (wi::to_wide (larger), 1, |
1240 TYPE_SIGN (TREE_TYPE (larger)), | |
1241 &overflow); | |
1242 if (! overflow) | |
1243 alt_larger = wide_int_to_tree (TREE_TYPE (larger), alt); | |
1244 } | |
1245 else | |
1246 { | |
131 | 1247 wi::overflow_type overflow; |
111 | 1248 wide_int alt = wi::add (wi::to_wide (larger), 1, |
1249 TYPE_SIGN (TREE_TYPE (larger)), | |
1250 &overflow); | |
1251 if (! overflow) | |
1252 alt_larger = wide_int_to_tree (TREE_TYPE (larger), alt); | |
1253 } | |
1254 } | |
0 | 1255 } |
1256 else if (cmp == GT_EXPR || cmp == GE_EXPR) | |
1257 { | |
1258 smaller = gimple_cond_rhs (cond); | |
1259 larger = gimple_cond_lhs (cond); | |
111 | 1260 /* If we have larger > CST it is equivalent to larger >= CST+1. |
1261 Likewise larger >= CST is equivalent to larger > CST-1. */ | |
1262 if (TREE_CODE (smaller) == INTEGER_CST) | |
1263 { | |
131 | 1264 wi::overflow_type overflow; |
111 | 1265 if (cmp == GT_EXPR) |
1266 { | |
1267 wide_int alt = wi::add (wi::to_wide (smaller), 1, | |
1268 TYPE_SIGN (TREE_TYPE (smaller)), | |
1269 &overflow); | |
1270 if (! overflow) | |
1271 alt_smaller = wide_int_to_tree (TREE_TYPE (smaller), alt); | |
1272 } | |
1273 else | |
1274 { | |
1275 wide_int alt = wi::sub (wi::to_wide (smaller), 1, | |
1276 TYPE_SIGN (TREE_TYPE (smaller)), | |
1277 &overflow); | |
1278 if (! overflow) | |
1279 alt_smaller = wide_int_to_tree (TREE_TYPE (smaller), alt); | |
1280 } | |
1281 } | |
0 | 1282 } |
1283 else | |
1284 return false; | |
1285 | |
1286 /* We need to know which is the true edge and which is the false | |
1287 edge so that we know if have abs or negative abs. */ | |
1288 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge); | |
1289 | |
1290 /* Forward the edges over the middle basic block. */ | |
1291 if (true_edge->dest == middle_bb) | |
1292 true_edge = EDGE_SUCC (true_edge->dest, 0); | |
1293 if (false_edge->dest == middle_bb) | |
1294 false_edge = EDGE_SUCC (false_edge->dest, 0); | |
1295 | |
1296 if (true_edge == e0) | |
1297 { | |
1298 gcc_assert (false_edge == e1); | |
1299 arg_true = arg0; | |
1300 arg_false = arg1; | |
1301 } | |
1302 else | |
1303 { | |
1304 gcc_assert (false_edge == e0); | |
1305 gcc_assert (true_edge == e1); | |
1306 arg_true = arg1; | |
1307 arg_false = arg0; | |
1308 } | |
1309 | |
1310 if (empty_block_p (middle_bb)) | |
1311 { | |
111 | 1312 if ((operand_equal_for_phi_arg_p (arg_true, smaller) |
1313 || (alt_smaller | |
1314 && operand_equal_for_phi_arg_p (arg_true, alt_smaller))) | |
1315 && (operand_equal_for_phi_arg_p (arg_false, larger) | |
1316 || (alt_larger | |
1317 && operand_equal_for_phi_arg_p (arg_true, alt_larger)))) | |
0 | 1318 { |
1319 /* Case | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1320 |
0 | 1321 if (smaller < larger) |
1322 rslt = smaller; | |
1323 else | |
1324 rslt = larger; */ | |
1325 minmax = MIN_EXPR; | |
1326 } | |
111 | 1327 else if ((operand_equal_for_phi_arg_p (arg_false, smaller) |
1328 || (alt_smaller | |
1329 && operand_equal_for_phi_arg_p (arg_false, alt_smaller))) | |
1330 && (operand_equal_for_phi_arg_p (arg_true, larger) | |
1331 || (alt_larger | |
1332 && operand_equal_for_phi_arg_p (arg_true, alt_larger)))) | |
0 | 1333 minmax = MAX_EXPR; |
1334 else | |
1335 return false; | |
1336 } | |
1337 else | |
1338 { | |
1339 /* Recognize the following case, assuming d <= u: | |
1340 | |
1341 if (a <= u) | |
1342 b = MAX (a, d); | |
1343 x = PHI <b, u> | |
1344 | |
1345 This is equivalent to | |
1346 | |
1347 b = MAX (a, d); | |
1348 x = MIN (b, u); */ | |
1349 | |
111 | 1350 gimple *assign = last_and_only_stmt (middle_bb); |
0 | 1351 tree lhs, op0, op1, bound; |
1352 | |
1353 if (!assign | |
1354 || gimple_code (assign) != GIMPLE_ASSIGN) | |
1355 return false; | |
1356 | |
1357 lhs = gimple_assign_lhs (assign); | |
1358 ass_code = gimple_assign_rhs_code (assign); | |
1359 if (ass_code != MAX_EXPR && ass_code != MIN_EXPR) | |
1360 return false; | |
1361 op0 = gimple_assign_rhs1 (assign); | |
1362 op1 = gimple_assign_rhs2 (assign); | |
1363 | |
1364 if (true_edge->src == middle_bb) | |
1365 { | |
1366 /* We got here if the condition is true, i.e., SMALLER < LARGER. */ | |
1367 if (!operand_equal_for_phi_arg_p (lhs, arg_true)) | |
1368 return false; | |
1369 | |
111 | 1370 if (operand_equal_for_phi_arg_p (arg_false, larger) |
1371 || (alt_larger | |
1372 && operand_equal_for_phi_arg_p (arg_false, alt_larger))) | |
0 | 1373 { |
1374 /* Case | |
1375 | |
1376 if (smaller < larger) | |
1377 { | |
1378 r' = MAX_EXPR (smaller, bound) | |
1379 } | |
1380 r = PHI <r', larger> --> to be turned to MIN_EXPR. */ | |
1381 if (ass_code != MAX_EXPR) | |
1382 return false; | |
1383 | |
1384 minmax = MIN_EXPR; | |
111 | 1385 if (operand_equal_for_phi_arg_p (op0, smaller) |
1386 || (alt_smaller | |
1387 && operand_equal_for_phi_arg_p (op0, alt_smaller))) | |
0 | 1388 bound = op1; |
111 | 1389 else if (operand_equal_for_phi_arg_p (op1, smaller) |
1390 || (alt_smaller | |
1391 && operand_equal_for_phi_arg_p (op1, alt_smaller))) | |
0 | 1392 bound = op0; |
1393 else | |
1394 return false; | |
1395 | |
1396 /* We need BOUND <= LARGER. */ | |
1397 if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node, | |
1398 bound, larger))) | |
1399 return false; | |
1400 } | |
111 | 1401 else if (operand_equal_for_phi_arg_p (arg_false, smaller) |
1402 || (alt_smaller | |
1403 && operand_equal_for_phi_arg_p (arg_false, alt_smaller))) | |
0 | 1404 { |
1405 /* Case | |
1406 | |
1407 if (smaller < larger) | |
1408 { | |
1409 r' = MIN_EXPR (larger, bound) | |
1410 } | |
1411 r = PHI <r', smaller> --> to be turned to MAX_EXPR. */ | |
1412 if (ass_code != MIN_EXPR) | |
1413 return false; | |
1414 | |
1415 minmax = MAX_EXPR; | |
111 | 1416 if (operand_equal_for_phi_arg_p (op0, larger) |
1417 || (alt_larger | |
1418 && operand_equal_for_phi_arg_p (op0, alt_larger))) | |
0 | 1419 bound = op1; |
111 | 1420 else if (operand_equal_for_phi_arg_p (op1, larger) |
1421 || (alt_larger | |
1422 && operand_equal_for_phi_arg_p (op1, alt_larger))) | |
0 | 1423 bound = op0; |
1424 else | |
1425 return false; | |
1426 | |
1427 /* We need BOUND >= SMALLER. */ | |
1428 if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node, | |
1429 bound, smaller))) | |
1430 return false; | |
1431 } | |
1432 else | |
1433 return false; | |
1434 } | |
1435 else | |
1436 { | |
1437 /* We got here if the condition is false, i.e., SMALLER > LARGER. */ | |
1438 if (!operand_equal_for_phi_arg_p (lhs, arg_false)) | |
1439 return false; | |
1440 | |
111 | 1441 if (operand_equal_for_phi_arg_p (arg_true, larger) |
1442 || (alt_larger | |
1443 && operand_equal_for_phi_arg_p (arg_true, alt_larger))) | |
0 | 1444 { |
1445 /* Case | |
1446 | |
1447 if (smaller > larger) | |
1448 { | |
1449 r' = MIN_EXPR (smaller, bound) | |
1450 } | |
1451 r = PHI <r', larger> --> to be turned to MAX_EXPR. */ | |
1452 if (ass_code != MIN_EXPR) | |
1453 return false; | |
1454 | |
1455 minmax = MAX_EXPR; | |
111 | 1456 if (operand_equal_for_phi_arg_p (op0, smaller) |
1457 || (alt_smaller | |
1458 && operand_equal_for_phi_arg_p (op0, alt_smaller))) | |
0 | 1459 bound = op1; |
111 | 1460 else if (operand_equal_for_phi_arg_p (op1, smaller) |
1461 || (alt_smaller | |
1462 && operand_equal_for_phi_arg_p (op1, alt_smaller))) | |
0 | 1463 bound = op0; |
1464 else | |
1465 return false; | |
1466 | |
1467 /* We need BOUND >= LARGER. */ | |
1468 if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node, | |
1469 bound, larger))) | |
1470 return false; | |
1471 } | |
111 | 1472 else if (operand_equal_for_phi_arg_p (arg_true, smaller) |
1473 || (alt_smaller | |
1474 && operand_equal_for_phi_arg_p (arg_true, alt_smaller))) | |
0 | 1475 { |
1476 /* Case | |
1477 | |
1478 if (smaller > larger) | |
1479 { | |
1480 r' = MAX_EXPR (larger, bound) | |
1481 } | |
1482 r = PHI <r', smaller> --> to be turned to MIN_EXPR. */ | |
1483 if (ass_code != MAX_EXPR) | |
1484 return false; | |
1485 | |
1486 minmax = MIN_EXPR; | |
1487 if (operand_equal_for_phi_arg_p (op0, larger)) | |
1488 bound = op1; | |
1489 else if (operand_equal_for_phi_arg_p (op1, larger)) | |
1490 bound = op0; | |
1491 else | |
1492 return false; | |
1493 | |
1494 /* We need BOUND <= SMALLER. */ | |
1495 if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node, | |
1496 bound, smaller))) | |
1497 return false; | |
1498 } | |
1499 else | |
1500 return false; | |
1501 } | |
1502 | |
1503 /* Move the statement from the middle block. */ | |
1504 gsi = gsi_last_bb (cond_bb); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1505 gsi_from = gsi_last_nondebug_bb (middle_bb); |
131 | 1506 reset_flow_sensitive_info (SINGLE_SSA_TREE_OPERAND (gsi_stmt (gsi_from), |
1507 SSA_OP_DEF)); | |
0 | 1508 gsi_move_before (&gsi_from, &gsi); |
1509 } | |
1510 | |
111 | 1511 /* Create an SSA var to hold the min/max result. If we're the only |
1512 things setting the target PHI, then we can clone the PHI | |
1513 variable. Otherwise we must create a new one. */ | |
1514 result = PHI_RESULT (phi); | |
1515 if (EDGE_COUNT (gimple_bb (phi)->preds) == 2) | |
1516 result = duplicate_ssa_name (result, NULL); | |
1517 else | |
1518 result = make_ssa_name (TREE_TYPE (result)); | |
1519 | |
0 | 1520 /* Emit the statement to compute min/max. */ |
111 | 1521 new_stmt = gimple_build_assign (result, minmax, arg0, arg1); |
0 | 1522 gsi = gsi_last_bb (cond_bb); |
1523 gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT); | |
1524 | |
1525 replace_phi_edge_with_variable (cond_bb, e1, phi, result); | |
131 | 1526 |
1527 return true; | |
1528 } | |
1529 | |
1530 /* Convert | |
1531 | |
1532 <bb 2> | |
1533 if (b_4(D) != 0) | |
1534 goto <bb 3> | |
1535 else | |
1536 goto <bb 4> | |
1537 | |
1538 <bb 3> | |
1539 _2 = (unsigned long) b_4(D); | |
1540 _9 = __builtin_popcountl (_2); | |
1541 OR | |
1542 _9 = __builtin_popcountl (b_4(D)); | |
1543 | |
1544 <bb 4> | |
1545 c_12 = PHI <0(2), _9(3)> | |
1546 | |
1547 Into | |
1548 <bb 2> | |
1549 _2 = (unsigned long) b_4(D); | |
1550 _9 = __builtin_popcountl (_2); | |
1551 OR | |
1552 _9 = __builtin_popcountl (b_4(D)); | |
1553 | |
1554 <bb 4> | |
1555 c_12 = PHI <_9(2)> | |
1556 */ | |
1557 | |
1558 static bool | |
1559 cond_removal_in_popcount_pattern (basic_block cond_bb, basic_block middle_bb, | |
1560 edge e1, edge e2, | |
1561 gimple *phi, tree arg0, tree arg1) | |
1562 { | |
1563 gimple *cond; | |
1564 gimple_stmt_iterator gsi, gsi_from; | |
1565 gimple *popcount; | |
1566 gimple *cast = NULL; | |
1567 tree lhs, arg; | |
1568 | |
1569 /* Check that | |
1570 _2 = (unsigned long) b_4(D); | |
1571 _9 = __builtin_popcountl (_2); | |
1572 OR | |
1573 _9 = __builtin_popcountl (b_4(D)); | |
1574 are the only stmts in the middle_bb. */ | |
1575 | |
1576 gsi = gsi_start_nondebug_after_labels_bb (middle_bb); | |
1577 if (gsi_end_p (gsi)) | |
1578 return false; | |
1579 cast = gsi_stmt (gsi); | |
1580 gsi_next_nondebug (&gsi); | |
1581 if (!gsi_end_p (gsi)) | |
1582 { | |
1583 popcount = gsi_stmt (gsi); | |
1584 gsi_next_nondebug (&gsi); | |
1585 if (!gsi_end_p (gsi)) | |
1586 return false; | |
1587 } | |
1588 else | |
1589 { | |
1590 popcount = cast; | |
1591 cast = NULL; | |
1592 } | |
1593 | |
1594 /* Check that we have a popcount builtin. */ | |
1595 if (!is_gimple_call (popcount)) | |
1596 return false; | |
1597 combined_fn cfn = gimple_call_combined_fn (popcount); | |
1598 switch (cfn) | |
1599 { | |
1600 CASE_CFN_POPCOUNT: | |
1601 break; | |
1602 default: | |
1603 return false; | |
1604 } | |
1605 | |
1606 arg = gimple_call_arg (popcount, 0); | |
1607 lhs = gimple_get_lhs (popcount); | |
1608 | |
1609 if (cast) | |
1610 { | |
1611 /* We have a cast stmt feeding popcount builtin. */ | |
1612 /* Check that we have a cast prior to that. */ | |
1613 if (gimple_code (cast) != GIMPLE_ASSIGN | |
1614 || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (cast))) | |
1615 return false; | |
1616 /* Result of the cast stmt is the argument to the builtin. */ | |
1617 if (arg != gimple_assign_lhs (cast)) | |
1618 return false; | |
1619 arg = gimple_assign_rhs1 (cast); | |
1620 } | |
1621 | |
1622 cond = last_stmt (cond_bb); | |
1623 | |
1624 /* Cond_bb has a check for b_4 [!=|==] 0 before calling the popcount | |
1625 builtin. */ | |
1626 if (gimple_code (cond) != GIMPLE_COND | |
1627 || (gimple_cond_code (cond) != NE_EXPR | |
1628 && gimple_cond_code (cond) != EQ_EXPR) | |
1629 || !integer_zerop (gimple_cond_rhs (cond)) | |
1630 || arg != gimple_cond_lhs (cond)) | |
1631 return false; | |
1632 | |
1633 /* Canonicalize. */ | |
1634 if ((e2->flags & EDGE_TRUE_VALUE | |
1635 && gimple_cond_code (cond) == NE_EXPR) | |
1636 || (e1->flags & EDGE_TRUE_VALUE | |
1637 && gimple_cond_code (cond) == EQ_EXPR)) | |
1638 { | |
1639 std::swap (arg0, arg1); | |
1640 std::swap (e1, e2); | |
1641 } | |
1642 | |
1643 /* Check PHI arguments. */ | |
1644 if (lhs != arg0 || !integer_zerop (arg1)) | |
1645 return false; | |
1646 | |
1647 /* And insert the popcount builtin and cast stmt before the cond_bb. */ | |
1648 gsi = gsi_last_bb (cond_bb); | |
1649 if (cast) | |
1650 { | |
1651 gsi_from = gsi_for_stmt (cast); | |
1652 gsi_move_before (&gsi_from, &gsi); | |
1653 reset_flow_sensitive_info (gimple_get_lhs (cast)); | |
1654 } | |
1655 gsi_from = gsi_for_stmt (popcount); | |
1656 gsi_move_before (&gsi_from, &gsi); | |
1657 reset_flow_sensitive_info (gimple_get_lhs (popcount)); | |
1658 | |
1659 /* Now update the PHI and remove unneeded bbs. */ | |
1660 replace_phi_edge_with_variable (cond_bb, e2, phi, lhs); | |
0 | 1661 return true; |
1662 } | |
1663 | |
1664 /* The function absolute_replacement does the main work of doing the absolute | |
1665 replacement. Return true if the replacement is done. Otherwise return | |
1666 false. | |
1667 bb is the basic block where the replacement is going to be done on. arg0 | |
1668 is argument 0 from the phi. Likewise for arg1. */ | |
1669 | |
1670 static bool | |
1671 abs_replacement (basic_block cond_bb, basic_block middle_bb, | |
1672 edge e0 ATTRIBUTE_UNUSED, edge e1, | |
111 | 1673 gimple *phi, tree arg0, tree arg1) |
0 | 1674 { |
1675 tree result; | |
111 | 1676 gassign *new_stmt; |
1677 gimple *cond; | |
0 | 1678 gimple_stmt_iterator gsi; |
1679 edge true_edge, false_edge; | |
111 | 1680 gimple *assign; |
0 | 1681 edge e; |
1682 tree rhs, lhs; | |
1683 bool negate; | |
1684 enum tree_code cond_code; | |
1685 | |
1686 /* If the type says honor signed zeros we cannot do this | |
1687 optimization. */ | |
111 | 1688 if (HONOR_SIGNED_ZEROS (arg1)) |
0 | 1689 return false; |
1690 | |
1691 /* OTHER_BLOCK must have only one executable statement which must have the | |
1692 form arg0 = -arg1 or arg1 = -arg0. */ | |
1693 | |
1694 assign = last_and_only_stmt (middle_bb); | |
1695 /* If we did not find the proper negation assignment, then we can not | |
1696 optimize. */ | |
1697 if (assign == NULL) | |
1698 return false; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1699 |
0 | 1700 /* If we got here, then we have found the only executable statement |
1701 in OTHER_BLOCK. If it is anything other than arg = -arg1 or | |
1702 arg1 = -arg0, then we can not optimize. */ | |
1703 if (gimple_code (assign) != GIMPLE_ASSIGN) | |
1704 return false; | |
1705 | |
1706 lhs = gimple_assign_lhs (assign); | |
1707 | |
1708 if (gimple_assign_rhs_code (assign) != NEGATE_EXPR) | |
1709 return false; | |
1710 | |
1711 rhs = gimple_assign_rhs1 (assign); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1712 |
0 | 1713 /* The assignment has to be arg0 = -arg1 or arg1 = -arg0. */ |
1714 if (!(lhs == arg0 && rhs == arg1) | |
1715 && !(lhs == arg1 && rhs == arg0)) | |
1716 return false; | |
1717 | |
1718 cond = last_stmt (cond_bb); | |
1719 result = PHI_RESULT (phi); | |
1720 | |
1721 /* Only relationals comparing arg[01] against zero are interesting. */ | |
1722 cond_code = gimple_cond_code (cond); | |
1723 if (cond_code != GT_EXPR && cond_code != GE_EXPR | |
1724 && cond_code != LT_EXPR && cond_code != LE_EXPR) | |
1725 return false; | |
1726 | |
1727 /* Make sure the conditional is arg[01] OP y. */ | |
1728 if (gimple_cond_lhs (cond) != rhs) | |
1729 return false; | |
1730 | |
1731 if (FLOAT_TYPE_P (TREE_TYPE (gimple_cond_rhs (cond))) | |
1732 ? real_zerop (gimple_cond_rhs (cond)) | |
1733 : integer_zerop (gimple_cond_rhs (cond))) | |
1734 ; | |
1735 else | |
1736 return false; | |
1737 | |
1738 /* We need to know which is the true edge and which is the false | |
1739 edge so that we know if have abs or negative abs. */ | |
1740 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge); | |
1741 | |
1742 /* For GT_EXPR/GE_EXPR, if the true edge goes to OTHER_BLOCK, then we | |
1743 will need to negate the result. Similarly for LT_EXPR/LE_EXPR if | |
1744 the false edge goes to OTHER_BLOCK. */ | |
1745 if (cond_code == GT_EXPR || cond_code == GE_EXPR) | |
1746 e = true_edge; | |
1747 else | |
1748 e = false_edge; | |
1749 | |
1750 if (e->dest == middle_bb) | |
1751 negate = true; | |
1752 else | |
1753 negate = false; | |
1754 | |
111 | 1755 /* If the code negates only iff positive then make sure to not |
1756 introduce undefined behavior when negating or computing the absolute. | |
1757 ??? We could use range info if present to check for arg1 == INT_MIN. */ | |
1758 if (negate | |
1759 && (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg1)) | |
1760 && ! TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1)))) | |
1761 return false; | |
1762 | |
0 | 1763 result = duplicate_ssa_name (result, NULL); |
1764 | |
1765 if (negate) | |
111 | 1766 lhs = make_ssa_name (TREE_TYPE (result)); |
0 | 1767 else |
1768 lhs = result; | |
1769 | |
1770 /* Build the modify expression with abs expression. */ | |
111 | 1771 new_stmt = gimple_build_assign (lhs, ABS_EXPR, rhs); |
0 | 1772 |
1773 gsi = gsi_last_bb (cond_bb); | |
1774 gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT); | |
1775 | |
1776 if (negate) | |
1777 { | |
1778 /* Get the right GSI. We want to insert after the recently | |
1779 added ABS_EXPR statement (which we know is the first statement | |
1780 in the block. */ | |
111 | 1781 new_stmt = gimple_build_assign (result, NEGATE_EXPR, lhs); |
0 | 1782 |
1783 gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT); | |
1784 } | |
1785 | |
1786 replace_phi_edge_with_variable (cond_bb, e1, phi, result); | |
1787 | |
1788 /* Note that we optimized this PHI. */ | |
1789 return true; | |
1790 } | |
1791 | |
1792 /* Auxiliary functions to determine the set of memory accesses which | |
1793 can't trap because they are preceded by accesses to the same memory | |
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
|
1794 portion. We do that for MEM_REFs, so we only need to track |
0 | 1795 the SSA_NAME of the pointer indirectly referenced. The algorithm |
1796 simply is a walk over all instructions in dominator order. When | |
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
|
1797 we see an MEM_REF we determine if we've already seen a same |
0 | 1798 ref anywhere up to the root of the dominator tree. If we do the |
1799 current access can't trap. If we don't see any dominating access | |
1800 the current access might trap, but might also make later accesses | |
1801 non-trapping, so we remember it. We need to be careful with loads | |
1802 or stores, for instance a load might not trap, while a store would, | |
1803 so if we see a dominating read access this doesn't mean that a later | |
1804 write access would not trap. Hence we also need to differentiate the | |
1805 type of access(es) seen. | |
1806 | |
1807 ??? We currently are very conservative and assume that a load might | |
1808 trap even if a store doesn't (write-only memory). This probably is | |
1809 overly conservative. */ | |
1810 | |
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
|
1811 /* A hash-table of SSA_NAMEs, and in which basic block an MEM_REF |
0 | 1812 through it was seen, which would constitute a no-trap region for |
1813 same accesses. */ | |
1814 struct name_to_bb | |
1815 { | |
111 | 1816 unsigned int ssa_name_ver; |
1817 unsigned int phase; | |
1818 bool store; | |
1819 HOST_WIDE_INT offset, size; | |
0 | 1820 basic_block bb; |
111 | 1821 }; |
1822 | |
1823 /* Hashtable helpers. */ | |
1824 | |
1825 struct ssa_names_hasher : free_ptr_hash <name_to_bb> | |
1826 { | |
1827 static inline hashval_t hash (const name_to_bb *); | |
1828 static inline bool equal (const name_to_bb *, const name_to_bb *); | |
0 | 1829 }; |
1830 | |
111 | 1831 /* Used for quick clearing of the hash-table when we see calls. |
1832 Hash entries with phase < nt_call_phase are invalid. */ | |
1833 static unsigned int nt_call_phase; | |
1834 | |
1835 /* The hash function. */ | |
1836 | |
1837 inline hashval_t | |
1838 ssa_names_hasher::hash (const name_to_bb *n) | |
1839 { | |
1840 return n->ssa_name_ver ^ (((hashval_t) n->store) << 31) | |
1841 ^ (n->offset << 6) ^ (n->size << 3); | |
1842 } | |
1843 | |
1844 /* The equality function of *P1 and *P2. */ | |
1845 | |
1846 inline bool | |
1847 ssa_names_hasher::equal (const name_to_bb *n1, const name_to_bb *n2) | |
1848 { | |
1849 return n1->ssa_name_ver == n2->ssa_name_ver | |
1850 && n1->store == n2->store | |
1851 && n1->offset == n2->offset | |
1852 && n1->size == n2->size; | |
1853 } | |
1854 | |
1855 class nontrapping_dom_walker : public dom_walker | |
0 | 1856 { |
111 | 1857 public: |
1858 nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps) | |
1859 : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {} | |
1860 | |
1861 virtual edge before_dom_children (basic_block); | |
1862 virtual void after_dom_children (basic_block); | |
1863 | |
1864 private: | |
1865 | |
1866 /* We see the expression EXP in basic block BB. If it's an interesting | |
1867 expression (an MEM_REF through an SSA_NAME) possibly insert the | |
1868 expression into the set NONTRAP or the hash table of seen expressions. | |
1869 STORE is true if this expression is on the LHS, otherwise it's on | |
1870 the RHS. */ | |
1871 void add_or_mark_expr (basic_block, tree, bool); | |
1872 | |
1873 hash_set<tree> *m_nontrapping; | |
1874 | |
1875 /* The hash table for remembering what we've seen. */ | |
1876 hash_table<ssa_names_hasher> m_seen_ssa_names; | |
1877 }; | |
1878 | |
1879 /* Called by walk_dominator_tree, when entering the block BB. */ | |
1880 edge | |
1881 nontrapping_dom_walker::before_dom_children (basic_block bb) | |
1882 { | |
1883 edge e; | |
1884 edge_iterator ei; | |
1885 gimple_stmt_iterator gsi; | |
1886 | |
1887 /* If we haven't seen all our predecessors, clear the hash-table. */ | |
1888 FOR_EACH_EDGE (e, ei, bb->preds) | |
1889 if ((((size_t)e->src->aux) & 2) == 0) | |
1890 { | |
1891 nt_call_phase++; | |
1892 break; | |
1893 } | |
1894 | |
1895 /* Mark this BB as being on the path to dominator root and as visited. */ | |
1896 bb->aux = (void*)(1 | 2); | |
1897 | |
1898 /* And walk the statements in order. */ | |
1899 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | |
1900 { | |
1901 gimple *stmt = gsi_stmt (gsi); | |
1902 | |
1903 if ((gimple_code (stmt) == GIMPLE_ASM && gimple_vdef (stmt)) | |
1904 || (is_gimple_call (stmt) | |
1905 && (!nonfreeing_call_p (stmt) || !nonbarrier_call_p (stmt)))) | |
1906 nt_call_phase++; | |
1907 else if (gimple_assign_single_p (stmt) && !gimple_has_volatile_ops (stmt)) | |
1908 { | |
1909 add_or_mark_expr (bb, gimple_assign_lhs (stmt), true); | |
1910 add_or_mark_expr (bb, gimple_assign_rhs1 (stmt), false); | |
1911 } | |
1912 } | |
1913 return NULL; | |
0 | 1914 } |
1915 | |
111 | 1916 /* Called by walk_dominator_tree, when basic block BB is exited. */ |
1917 void | |
1918 nontrapping_dom_walker::after_dom_children (basic_block bb) | |
0 | 1919 { |
111 | 1920 /* This BB isn't on the path to dominator root anymore. */ |
1921 bb->aux = (void*)2; | |
0 | 1922 } |
1923 | |
1924 /* We see the expression EXP in basic block BB. If it's an interesting | |
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
|
1925 expression (an MEM_REF through an SSA_NAME) possibly insert the |
0 | 1926 expression into the set NONTRAP or the hash table of seen expressions. |
1927 STORE is true if this expression is on the LHS, otherwise it's on | |
1928 the RHS. */ | |
111 | 1929 void |
1930 nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store) | |
0 | 1931 { |
111 | 1932 HOST_WIDE_INT size; |
1933 | |
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
|
1934 if (TREE_CODE (exp) == MEM_REF |
111 | 1935 && TREE_CODE (TREE_OPERAND (exp, 0)) == SSA_NAME |
1936 && tree_fits_shwi_p (TREE_OPERAND (exp, 1)) | |
1937 && (size = int_size_in_bytes (TREE_TYPE (exp))) > 0) | |
0 | 1938 { |
1939 tree name = TREE_OPERAND (exp, 0); | |
1940 struct name_to_bb map; | |
111 | 1941 name_to_bb **slot; |
0 | 1942 struct name_to_bb *n2bb; |
1943 basic_block found_bb = 0; | |
1944 | |
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
|
1945 /* Try to find the last seen MEM_REF through the same |
0 | 1946 SSA_NAME, which can trap. */ |
111 | 1947 map.ssa_name_ver = SSA_NAME_VERSION (name); |
1948 map.phase = 0; | |
0 | 1949 map.bb = 0; |
1950 map.store = store; | |
111 | 1951 map.offset = tree_to_shwi (TREE_OPERAND (exp, 1)); |
1952 map.size = size; | |
1953 | |
1954 slot = m_seen_ssa_names.find_slot (&map, INSERT); | |
1955 n2bb = *slot; | |
1956 if (n2bb && n2bb->phase >= nt_call_phase) | |
0 | 1957 found_bb = n2bb->bb; |
1958 | |
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
|
1959 /* If we've found a trapping MEM_REF, _and_ it dominates EXP |
0 | 1960 (it's in a basic block on the path from us to the dominator root) |
1961 then we can't trap. */ | |
111 | 1962 if (found_bb && (((size_t)found_bb->aux) & 1) == 1) |
0 | 1963 { |
111 | 1964 m_nontrapping->add (exp); |
0 | 1965 } |
1966 else | |
1967 { | |
1968 /* EXP might trap, so insert it into the hash table. */ | |
1969 if (n2bb) | |
1970 { | |
111 | 1971 n2bb->phase = nt_call_phase; |
0 | 1972 n2bb->bb = bb; |
1973 } | |
1974 else | |
1975 { | |
1976 n2bb = XNEW (struct name_to_bb); | |
111 | 1977 n2bb->ssa_name_ver = SSA_NAME_VERSION (name); |
1978 n2bb->phase = nt_call_phase; | |
0 | 1979 n2bb->bb = bb; |
1980 n2bb->store = store; | |
111 | 1981 n2bb->offset = map.offset; |
1982 n2bb->size = size; | |
0 | 1983 *slot = n2bb; |
1984 } | |
1985 } | |
1986 } | |
1987 } | |
1988 | |
1989 /* This is the entry point of gathering non trapping memory accesses. | |
1990 It will do a dominator walk over the whole function, and it will | |
1991 make use of the bb->aux pointers. It returns a set of trees | |
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
|
1992 (the MEM_REFs itself) which can't trap. */ |
111 | 1993 static hash_set<tree> * |
0 | 1994 get_non_trapping (void) |
1995 { | |
111 | 1996 nt_call_phase = 0; |
1997 hash_set<tree> *nontrap = new hash_set<tree>; | |
0 | 1998 /* We're going to do a dominator walk, so ensure that we have |
1999 dominance information. */ | |
2000 calculate_dominance_info (CDI_DOMINATORS); | |
2001 | |
111 | 2002 nontrapping_dom_walker (CDI_DOMINATORS, nontrap) |
2003 .walk (cfun->cfg->x_entry_block_ptr); | |
2004 | |
2005 clear_aux_for_blocks (); | |
0 | 2006 return nontrap; |
2007 } | |
2008 | |
2009 /* Do the main work of conditional store replacement. We already know | |
2010 that the recognized pattern looks like so: | |
2011 | |
2012 split: | |
2013 if (cond) goto MIDDLE_BB; else goto JOIN_BB (edge E1) | |
2014 MIDDLE_BB: | |
2015 something | |
2016 fallthrough (edge E0) | |
2017 JOIN_BB: | |
2018 some more | |
2019 | |
2020 We check that MIDDLE_BB contains only one store, that that store | |
2021 doesn't trap (not via NOTRAP, but via checking if an access to the same | |
2022 memory location dominates us) and that the store has a "simple" RHS. */ | |
2023 | |
2024 static bool | |
2025 cond_store_replacement (basic_block middle_bb, basic_block join_bb, | |
111 | 2026 edge e0, edge e1, hash_set<tree> *nontrap) |
0 | 2027 { |
111 | 2028 gimple *assign = last_and_only_stmt (middle_bb); |
2029 tree lhs, rhs, name, name2; | |
2030 gphi *newphi; | |
2031 gassign *new_stmt; | |
0 | 2032 gimple_stmt_iterator gsi; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2033 source_location locus; |
0 | 2034 |
2035 /* Check if middle_bb contains of only one store. */ | |
2036 if (!assign | |
111 | 2037 || !gimple_assign_single_p (assign) |
2038 || gimple_has_volatile_ops (assign)) | |
0 | 2039 return false; |
2040 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2041 locus = gimple_location (assign); |
0 | 2042 lhs = gimple_assign_lhs (assign); |
2043 rhs = gimple_assign_rhs1 (assign); | |
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
|
2044 if (TREE_CODE (lhs) != MEM_REF |
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
|
2045 || TREE_CODE (TREE_OPERAND (lhs, 0)) != SSA_NAME |
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
|
2046 || !is_gimple_reg_type (TREE_TYPE (lhs))) |
0 | 2047 return false; |
2048 | |
2049 /* Prove that we can move the store down. We could also check | |
2050 TREE_THIS_NOTRAP here, but in that case we also could move stores, | |
2051 whose value is not available readily, which we want to avoid. */ | |
111 | 2052 if (!nontrap->contains (lhs)) |
0 | 2053 return false; |
2054 | |
2055 /* Now we've checked the constraints, so do the transformation: | |
2056 1) Remove the single store. */ | |
2057 gsi = gsi_for_stmt (assign); | |
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
|
2058 unlink_stmt_vdef (assign); |
0 | 2059 gsi_remove (&gsi, true); |
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
|
2060 release_defs (assign); |
0 | 2061 |
111 | 2062 /* Make both store and load use alias-set zero as we have to |
2063 deal with the case of the store being a conditional change | |
2064 of the dynamic type. */ | |
2065 lhs = unshare_expr (lhs); | |
2066 tree *basep = &lhs; | |
2067 while (handled_component_p (*basep)) | |
2068 basep = &TREE_OPERAND (*basep, 0); | |
2069 if (TREE_CODE (*basep) == MEM_REF | |
2070 || TREE_CODE (*basep) == TARGET_MEM_REF) | |
2071 TREE_OPERAND (*basep, 1) | |
2072 = fold_convert (ptr_type_node, TREE_OPERAND (*basep, 1)); | |
2073 else | |
2074 *basep = build2 (MEM_REF, TREE_TYPE (*basep), | |
2075 build_fold_addr_expr (*basep), | |
2076 build_zero_cst (ptr_type_node)); | |
2077 | |
2078 /* 2) Insert a load from the memory of the store to the temporary | |
0 | 2079 on the edge which did not contain the store. */ |
111 | 2080 name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore"); |
2081 new_stmt = gimple_build_assign (name, lhs); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2082 gimple_set_location (new_stmt, locus); |
0 | 2083 gsi_insert_on_edge (e1, new_stmt); |
2084 | |
111 | 2085 /* 3) Create a PHI node at the join block, with one argument |
0 | 2086 holding the old RHS, and the other holding the temporary |
2087 where we stored the old memory contents. */ | |
111 | 2088 name2 = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore"); |
2089 newphi = create_phi_node (name2, join_bb); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2090 add_phi_arg (newphi, rhs, e0, locus); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2091 add_phi_arg (newphi, name, e1, locus); |
0 | 2092 |
2093 lhs = unshare_expr (lhs); | |
2094 new_stmt = gimple_build_assign (lhs, PHI_RESULT (newphi)); | |
2095 | |
111 | 2096 /* 4) Insert that PHI node. */ |
0 | 2097 gsi = gsi_after_labels (join_bb); |
2098 if (gsi_end_p (gsi)) | |
2099 { | |
2100 gsi = gsi_last_bb (join_bb); | |
2101 gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT); | |
2102 } | |
2103 else | |
2104 gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT); | |
2105 | |
2106 return true; | |
2107 } | |
2108 | |
111 | 2109 /* Do the main work of conditional store replacement. */ |
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
|
2110 |
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
|
2111 static bool |
111 | 2112 cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, |
2113 basic_block join_bb, gimple *then_assign, | |
2114 gimple *else_assign) | |
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
|
2115 { |
111 | 2116 tree lhs_base, lhs, then_rhs, else_rhs, name; |
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
|
2117 source_location then_locus, else_locus; |
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
|
2118 gimple_stmt_iterator gsi; |
111 | 2119 gphi *newphi; |
2120 gassign *new_stmt; | |
2121 | |
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
|
2122 if (then_assign == NULL |
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
|
2123 || !gimple_assign_single_p (then_assign) |
111 | 2124 || gimple_clobber_p (then_assign) |
2125 || gimple_has_volatile_ops (then_assign) | |
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
|
2126 || else_assign == NULL |
111 | 2127 || !gimple_assign_single_p (else_assign) |
2128 || gimple_clobber_p (else_assign) | |
2129 || gimple_has_volatile_ops (else_assign)) | |
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
|
2130 return 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
|
2131 |
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
|
2132 lhs = gimple_assign_lhs (then_assign); |
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
|
2133 if (!is_gimple_reg_type (TREE_TYPE (lhs)) |
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
|
2134 || !operand_equal_p (lhs, gimple_assign_lhs (else_assign), 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
|
2135 return 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
|
2136 |
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
|
2137 lhs_base = get_base_address (lhs); |
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
|
2138 if (lhs_base == 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
|
2139 || (!DECL_P (lhs_base) && TREE_CODE (lhs_base) != MEM_REF)) |
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
|
2140 return 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
|
2141 |
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
|
2142 then_rhs = gimple_assign_rhs1 (then_assign); |
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
|
2143 else_rhs = gimple_assign_rhs1 (else_assign); |
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
|
2144 then_locus = gimple_location (then_assign); |
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
|
2145 else_locus = gimple_location (else_assign); |
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
|
2146 |
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
|
2147 /* Now we've checked the constraints, so do the transformation: |
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
|
2148 1) Remove the stores. */ |
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
|
2149 gsi = gsi_for_stmt (then_assign); |
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
|
2150 unlink_stmt_vdef (then_assign); |
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
|
2151 gsi_remove (&gsi, true); |
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
|
2152 release_defs (then_assign); |
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
|
2153 |
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
|
2154 gsi = gsi_for_stmt (else_assign); |
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
|
2155 unlink_stmt_vdef (else_assign); |
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
|
2156 gsi_remove (&gsi, true); |
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
|
2157 release_defs (else_assign); |
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
|
2158 |
111 | 2159 /* 2) Create a PHI node at the join block, with one argument |
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
|
2160 holding the old RHS, and the other holding the temporary |
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
|
2161 where we stored the old memory contents. */ |
111 | 2162 name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore"); |
2163 newphi = create_phi_node (name, join_bb); | |
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
|
2164 add_phi_arg (newphi, then_rhs, EDGE_SUCC (then_bb, 0), then_locus); |
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
|
2165 add_phi_arg (newphi, else_rhs, EDGE_SUCC (else_bb, 0), else_locus); |
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
|
2166 |
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
|
2167 new_stmt = gimple_build_assign (lhs, PHI_RESULT (newphi)); |
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
|
2168 |
111 | 2169 /* 3) Insert that PHI node. */ |
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
|
2170 gsi = gsi_after_labels (join_bb); |
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
|
2171 if (gsi_end_p (gsi)) |
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
|
2172 { |
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
|
2173 gsi = gsi_last_bb (join_bb); |
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
|
2174 gsi_insert_after (&gsi, new_stmt, GSI_NEW_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
|
2175 } |
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
|
2176 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
|
2177 gsi_insert_before (&gsi, new_stmt, GSI_NEW_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
|
2178 |
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
|
2179 return true; |
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
|
2180 } |
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
|
2181 |
131 | 2182 /* Return the single store in BB with VDEF or NULL if there are |
2183 other stores in the BB or loads following the store. */ | |
2184 | |
2185 static gimple * | |
2186 single_trailing_store_in_bb (basic_block bb, tree vdef) | |
2187 { | |
2188 if (SSA_NAME_IS_DEFAULT_DEF (vdef)) | |
2189 return NULL; | |
2190 gimple *store = SSA_NAME_DEF_STMT (vdef); | |
2191 if (gimple_bb (store) != bb | |
2192 || gimple_code (store) == GIMPLE_PHI) | |
2193 return NULL; | |
2194 | |
2195 /* Verify there is no other store in this BB. */ | |
2196 if (!SSA_NAME_IS_DEFAULT_DEF (gimple_vuse (store)) | |
2197 && gimple_bb (SSA_NAME_DEF_STMT (gimple_vuse (store))) == bb | |
2198 && gimple_code (SSA_NAME_DEF_STMT (gimple_vuse (store))) != GIMPLE_PHI) | |
2199 return NULL; | |
2200 | |
2201 /* Verify there is no load or store after the store. */ | |
2202 use_operand_p use_p; | |
2203 imm_use_iterator imm_iter; | |
2204 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_vdef (store)) | |
2205 if (USE_STMT (use_p) != store | |
2206 && gimple_bb (USE_STMT (use_p)) == bb) | |
2207 return NULL; | |
2208 | |
2209 return store; | |
2210 } | |
2211 | |
111 | 2212 /* Conditional store replacement. We already know |
2213 that the recognized pattern looks like so: | |
2214 | |
2215 split: | |
2216 if (cond) goto THEN_BB; else goto ELSE_BB (edge E1) | |
2217 THEN_BB: | |
2218 ... | |
2219 X = Y; | |
2220 ... | |
2221 goto JOIN_BB; | |
2222 ELSE_BB: | |
2223 ... | |
2224 X = Z; | |
2225 ... | |
2226 fallthrough (edge E0) | |
2227 JOIN_BB: | |
2228 some more | |
2229 | |
2230 We check that it is safe to sink the store to JOIN_BB by verifying that | |
2231 there are no read-after-write or write-after-write dependencies in | |
2232 THEN_BB and ELSE_BB. */ | |
2233 | |
0 | 2234 static bool |
111 | 2235 cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, |
2236 basic_block join_bb) | |
0 | 2237 { |
111 | 2238 vec<data_reference_p> then_datarefs, else_datarefs; |
2239 vec<ddr_p> then_ddrs, else_ddrs; | |
2240 gimple *then_store, *else_store; | |
2241 bool found, ok = false, res; | |
2242 struct data_dependence_relation *ddr; | |
2243 data_reference_p then_dr, else_dr; | |
2244 int i, j; | |
2245 tree then_lhs, else_lhs; | |
2246 basic_block blocks[3]; | |
2247 | |
131 | 2248 /* Handle the case with single store in THEN_BB and ELSE_BB. That is |
2249 cheap enough to always handle as it allows us to elide dependence | |
2250 checking. */ | |
2251 gphi *vphi = NULL; | |
2252 for (gphi_iterator si = gsi_start_phis (join_bb); !gsi_end_p (si); | |
2253 gsi_next (&si)) | |
2254 if (virtual_operand_p (gimple_phi_result (si.phi ()))) | |
2255 { | |
2256 vphi = si.phi (); | |
2257 break; | |
2258 } | |
2259 if (!vphi) | |
2260 return false; | |
2261 tree then_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (then_bb)); | |
2262 tree else_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (else_bb)); | |
2263 gimple *then_assign = single_trailing_store_in_bb (then_bb, then_vdef); | |
2264 if (then_assign) | |
2265 { | |
2266 gimple *else_assign = single_trailing_store_in_bb (else_bb, else_vdef); | |
2267 if (else_assign) | |
2268 return cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb, | |
2269 then_assign, else_assign); | |
2270 } | |
2271 | |
111 | 2272 if (MAX_STORES_TO_SINK == 0) |
2273 return false; | |
2274 | |
2275 /* Find data references. */ | |
2276 then_datarefs.create (1); | |
2277 else_datarefs.create (1); | |
2278 if ((find_data_references_in_bb (NULL, then_bb, &then_datarefs) | |
2279 == chrec_dont_know) | |
2280 || !then_datarefs.length () | |
2281 || (find_data_references_in_bb (NULL, else_bb, &else_datarefs) | |
2282 == chrec_dont_know) | |
2283 || !else_datarefs.length ()) | |
2284 { | |
2285 free_data_refs (then_datarefs); | |
2286 free_data_refs (else_datarefs); | |
2287 return false; | |
2288 } | |
2289 | |
2290 /* Find pairs of stores with equal LHS. */ | |
2291 auto_vec<gimple *, 1> then_stores, else_stores; | |
2292 FOR_EACH_VEC_ELT (then_datarefs, i, then_dr) | |
2293 { | |
2294 if (DR_IS_READ (then_dr)) | |
2295 continue; | |
2296 | |
2297 then_store = DR_STMT (then_dr); | |
2298 then_lhs = gimple_get_lhs (then_store); | |
2299 if (then_lhs == NULL_TREE) | |
2300 continue; | |
2301 found = false; | |
2302 | |
2303 FOR_EACH_VEC_ELT (else_datarefs, j, else_dr) | |
2304 { | |
2305 if (DR_IS_READ (else_dr)) | |
2306 continue; | |
2307 | |
2308 else_store = DR_STMT (else_dr); | |
2309 else_lhs = gimple_get_lhs (else_store); | |
2310 if (else_lhs == NULL_TREE) | |
2311 continue; | |
2312 | |
2313 if (operand_equal_p (then_lhs, else_lhs, 0)) | |
2314 { | |
2315 found = true; | |
2316 break; | |
2317 } | |
2318 } | |
2319 | |
2320 if (!found) | |
2321 continue; | |
2322 | |
2323 then_stores.safe_push (then_store); | |
2324 else_stores.safe_push (else_store); | |
2325 } | |
2326 | |
2327 /* No pairs of stores found. */ | |
2328 if (!then_stores.length () | |
2329 || then_stores.length () > (unsigned) MAX_STORES_TO_SINK) | |
2330 { | |
2331 free_data_refs (then_datarefs); | |
2332 free_data_refs (else_datarefs); | |
2333 return false; | |
2334 } | |
2335 | |
2336 /* Compute and check data dependencies in both basic blocks. */ | |
2337 then_ddrs.create (1); | |
2338 else_ddrs.create (1); | |
2339 if (!compute_all_dependences (then_datarefs, &then_ddrs, | |
2340 vNULL, false) | |
2341 || !compute_all_dependences (else_datarefs, &else_ddrs, | |
2342 vNULL, false)) | |
2343 { | |
2344 free_dependence_relations (then_ddrs); | |
2345 free_dependence_relations (else_ddrs); | |
2346 free_data_refs (then_datarefs); | |
2347 free_data_refs (else_datarefs); | |
2348 return false; | |
2349 } | |
2350 blocks[0] = then_bb; | |
2351 blocks[1] = else_bb; | |
2352 blocks[2] = join_bb; | |
2353 renumber_gimple_stmt_uids_in_blocks (blocks, 3); | |
2354 | |
2355 /* Check that there are no read-after-write or write-after-write dependencies | |
2356 in THEN_BB. */ | |
2357 FOR_EACH_VEC_ELT (then_ddrs, i, ddr) | |
2358 { | |
2359 struct data_reference *dra = DDR_A (ddr); | |
2360 struct data_reference *drb = DDR_B (ddr); | |
2361 | |
2362 if (DDR_ARE_DEPENDENT (ddr) != chrec_known | |
2363 && ((DR_IS_READ (dra) && DR_IS_WRITE (drb) | |
2364 && gimple_uid (DR_STMT (dra)) > gimple_uid (DR_STMT (drb))) | |
2365 || (DR_IS_READ (drb) && DR_IS_WRITE (dra) | |
2366 && gimple_uid (DR_STMT (drb)) > gimple_uid (DR_STMT (dra))) | |
2367 || (DR_IS_WRITE (dra) && DR_IS_WRITE (drb)))) | |
2368 { | |
2369 free_dependence_relations (then_ddrs); | |
2370 free_dependence_relations (else_ddrs); | |
2371 free_data_refs (then_datarefs); | |
2372 free_data_refs (else_datarefs); | |
2373 return false; | |
2374 } | |
2375 } | |
2376 | |
2377 /* Check that there are no read-after-write or write-after-write dependencies | |
2378 in ELSE_BB. */ | |
2379 FOR_EACH_VEC_ELT (else_ddrs, i, ddr) | |
2380 { | |
2381 struct data_reference *dra = DDR_A (ddr); | |
2382 struct data_reference *drb = DDR_B (ddr); | |
2383 | |
2384 if (DDR_ARE_DEPENDENT (ddr) != chrec_known | |
2385 && ((DR_IS_READ (dra) && DR_IS_WRITE (drb) | |
2386 && gimple_uid (DR_STMT (dra)) > gimple_uid (DR_STMT (drb))) | |
2387 || (DR_IS_READ (drb) && DR_IS_WRITE (dra) | |
2388 && gimple_uid (DR_STMT (drb)) > gimple_uid (DR_STMT (dra))) | |
2389 || (DR_IS_WRITE (dra) && DR_IS_WRITE (drb)))) | |
2390 { | |
2391 free_dependence_relations (then_ddrs); | |
2392 free_dependence_relations (else_ddrs); | |
2393 free_data_refs (then_datarefs); | |
2394 free_data_refs (else_datarefs); | |
2395 return false; | |
2396 } | |
2397 } | |
2398 | |
2399 /* Sink stores with same LHS. */ | |
2400 FOR_EACH_VEC_ELT (then_stores, i, then_store) | |
2401 { | |
2402 else_store = else_stores[i]; | |
2403 res = cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb, | |
2404 then_store, else_store); | |
2405 ok = ok || res; | |
2406 } | |
2407 | |
2408 free_dependence_relations (then_ddrs); | |
2409 free_dependence_relations (else_ddrs); | |
2410 free_data_refs (then_datarefs); | |
2411 free_data_refs (else_datarefs); | |
2412 | |
2413 return ok; | |
2414 } | |
2415 | |
2416 /* Return TRUE if STMT has a VUSE whose corresponding VDEF is in BB. */ | |
0 | 2417 |
2418 static bool | |
111 | 2419 local_mem_dependence (gimple *stmt, basic_block bb) |
2420 { | |
2421 tree vuse = gimple_vuse (stmt); | |
2422 gimple *def; | |
2423 | |
2424 if (!vuse) | |
2425 return false; | |
2426 | |
2427 def = SSA_NAME_DEF_STMT (vuse); | |
2428 return (def && gimple_bb (def) == bb); | |
2429 } | |
2430 | |
2431 /* Given a "diamond" control-flow pattern where BB0 tests a condition, | |
2432 BB1 and BB2 are "then" and "else" blocks dependent on this test, | |
2433 and BB3 rejoins control flow following BB1 and BB2, look for | |
2434 opportunities to hoist loads as follows. If BB3 contains a PHI of | |
2435 two loads, one each occurring in BB1 and BB2, and the loads are | |
2436 provably of adjacent fields in the same structure, then move both | |
2437 loads into BB0. Of course this can only be done if there are no | |
2438 dependencies preventing such motion. | |
2439 | |
2440 One of the hoisted loads will always be speculative, so the | |
2441 transformation is currently conservative: | |
2442 | |
2443 - The fields must be strictly adjacent. | |
2444 - The two fields must occupy a single memory block that is | |
2445 guaranteed to not cross a page boundary. | |
2446 | |
2447 The last is difficult to prove, as such memory blocks should be | |
2448 aligned on the minimum of the stack alignment boundary and the | |
2449 alignment guaranteed by heap allocation interfaces. Thus we rely | |
2450 on a parameter for the alignment value. | |
2451 | |
2452 Provided a good value is used for the last case, the first | |
2453 restriction could possibly be relaxed. */ | |
2454 | |
2455 static void | |
2456 hoist_adjacent_loads (basic_block bb0, basic_block bb1, | |
2457 basic_block bb2, basic_block bb3) | |
0 | 2458 { |
111 | 2459 int param_align = PARAM_VALUE (PARAM_L1_CACHE_LINE_SIZE); |
2460 unsigned param_align_bits = (unsigned) (param_align * BITS_PER_UNIT); | |
2461 gphi_iterator gsi; | |
2462 | |
2463 /* Walk the phis in bb3 looking for an opportunity. We are looking | |
2464 for phis of two SSA names, one each of which is defined in bb1 and | |
2465 bb2. */ | |
2466 for (gsi = gsi_start_phis (bb3); !gsi_end_p (gsi); gsi_next (&gsi)) | |
2467 { | |
2468 gphi *phi_stmt = gsi.phi (); | |
2469 gimple *def1, *def2; | |
2470 tree arg1, arg2, ref1, ref2, field1, field2; | |
2471 tree tree_offset1, tree_offset2, tree_size2, next; | |
2472 int offset1, offset2, size2; | |
2473 unsigned align1; | |
2474 gimple_stmt_iterator gsi2; | |
2475 basic_block bb_for_def1, bb_for_def2; | |
2476 | |
2477 if (gimple_phi_num_args (phi_stmt) != 2 | |
2478 || virtual_operand_p (gimple_phi_result (phi_stmt))) | |
2479 continue; | |
2480 | |
2481 arg1 = gimple_phi_arg_def (phi_stmt, 0); | |
2482 arg2 = gimple_phi_arg_def (phi_stmt, 1); | |
2483 | |
2484 if (TREE_CODE (arg1) != SSA_NAME | |
2485 || TREE_CODE (arg2) != SSA_NAME | |
2486 || SSA_NAME_IS_DEFAULT_DEF (arg1) | |
2487 || SSA_NAME_IS_DEFAULT_DEF (arg2)) | |
2488 continue; | |
2489 | |
2490 def1 = SSA_NAME_DEF_STMT (arg1); | |
2491 def2 = SSA_NAME_DEF_STMT (arg2); | |
2492 | |
2493 if ((gimple_bb (def1) != bb1 || gimple_bb (def2) != bb2) | |
2494 && (gimple_bb (def2) != bb1 || gimple_bb (def1) != bb2)) | |
2495 continue; | |
2496 | |
2497 /* Check the mode of the arguments to be sure a conditional move | |
2498 can be generated for it. */ | |
2499 if (optab_handler (movcc_optab, TYPE_MODE (TREE_TYPE (arg1))) | |
2500 == CODE_FOR_nothing) | |
2501 continue; | |
2502 | |
2503 /* Both statements must be assignments whose RHS is a COMPONENT_REF. */ | |
2504 if (!gimple_assign_single_p (def1) | |
2505 || !gimple_assign_single_p (def2) | |
2506 || gimple_has_volatile_ops (def1) | |
2507 || gimple_has_volatile_ops (def2)) | |
2508 continue; | |
2509 | |
2510 ref1 = gimple_assign_rhs1 (def1); | |
2511 ref2 = gimple_assign_rhs1 (def2); | |
2512 | |
2513 if (TREE_CODE (ref1) != COMPONENT_REF | |
2514 || TREE_CODE (ref2) != COMPONENT_REF) | |
2515 continue; | |
2516 | |
2517 /* The zeroth operand of the two component references must be | |
2518 identical. It is not sufficient to compare get_base_address of | |
2519 the two references, because this could allow for different | |
2520 elements of the same array in the two trees. It is not safe to | |
2521 assume that the existence of one array element implies the | |
2522 existence of a different one. */ | |
2523 if (!operand_equal_p (TREE_OPERAND (ref1, 0), TREE_OPERAND (ref2, 0), 0)) | |
2524 continue; | |
2525 | |
2526 field1 = TREE_OPERAND (ref1, 1); | |
2527 field2 = TREE_OPERAND (ref2, 1); | |
2528 | |
2529 /* Check for field adjacency, and ensure field1 comes first. */ | |
2530 for (next = DECL_CHAIN (field1); | |
2531 next && TREE_CODE (next) != FIELD_DECL; | |
2532 next = DECL_CHAIN (next)) | |
2533 ; | |
2534 | |
2535 if (next != field2) | |
2536 { | |
2537 for (next = DECL_CHAIN (field2); | |
2538 next && TREE_CODE (next) != FIELD_DECL; | |
2539 next = DECL_CHAIN (next)) | |
2540 ; | |
2541 | |
2542 if (next != field1) | |
2543 continue; | |
2544 | |
2545 std::swap (field1, field2); | |
2546 std::swap (def1, def2); | |
2547 } | |
2548 | |
2549 bb_for_def1 = gimple_bb (def1); | |
2550 bb_for_def2 = gimple_bb (def2); | |
2551 | |
2552 /* Check for proper alignment of the first field. */ | |
2553 tree_offset1 = bit_position (field1); | |
2554 tree_offset2 = bit_position (field2); | |
2555 tree_size2 = DECL_SIZE (field2); | |
2556 | |
2557 if (!tree_fits_uhwi_p (tree_offset1) | |
2558 || !tree_fits_uhwi_p (tree_offset2) | |
2559 || !tree_fits_uhwi_p (tree_size2)) | |
2560 continue; | |
2561 | |
2562 offset1 = tree_to_uhwi (tree_offset1); | |
2563 offset2 = tree_to_uhwi (tree_offset2); | |
2564 size2 = tree_to_uhwi (tree_size2); | |
2565 align1 = DECL_ALIGN (field1) % param_align_bits; | |
2566 | |
2567 if (offset1 % BITS_PER_UNIT != 0) | |
2568 continue; | |
2569 | |
2570 /* For profitability, the two field references should fit within | |
2571 a single cache line. */ | |
2572 if (align1 + offset2 - offset1 + size2 > param_align_bits) | |
2573 continue; | |
2574 | |
2575 /* The two expressions cannot be dependent upon vdefs defined | |
2576 in bb1/bb2. */ | |
2577 if (local_mem_dependence (def1, bb_for_def1) | |
2578 || local_mem_dependence (def2, bb_for_def2)) | |
2579 continue; | |
2580 | |
2581 /* The conditions are satisfied; hoist the loads from bb1 and bb2 into | |
2582 bb0. We hoist the first one first so that a cache miss is handled | |
2583 efficiently regardless of hardware cache-fill policy. */ | |
2584 gsi2 = gsi_for_stmt (def1); | |
2585 gsi_move_to_bb_end (&gsi2, bb0); | |
2586 gsi2 = gsi_for_stmt (def2); | |
2587 gsi_move_to_bb_end (&gsi2, bb0); | |
2588 | |
2589 if (dump_file && (dump_flags & TDF_DETAILS)) | |
2590 { | |
2591 fprintf (dump_file, | |
2592 "\nHoisting adjacent loads from %d and %d into %d: \n", | |
2593 bb_for_def1->index, bb_for_def2->index, bb0->index); | |
2594 print_gimple_stmt (dump_file, def1, 0, TDF_VOPS|TDF_MEMSYMS); | |
2595 print_gimple_stmt (dump_file, def2, 0, TDF_VOPS|TDF_MEMSYMS); | |
2596 } | |
2597 } | |
0 | 2598 } |
2599 | |
111 | 2600 /* Determine whether we should attempt to hoist adjacent loads out of |
2601 diamond patterns in pass_phiopt. Always hoist loads if | |
2602 -fhoist-adjacent-loads is specified and the target machine has | |
2603 both a conditional move instruction and a defined cache line size. */ | |
2604 | |
2605 static bool | |
2606 gate_hoist_loads (void) | |
0 | 2607 { |
111 | 2608 return (flag_hoist_adjacent_loads == 1 |
2609 && PARAM_VALUE (PARAM_L1_CACHE_LINE_SIZE) | |
2610 && HAVE_conditional_move); | |
2611 } | |
2612 | |
2613 /* This pass tries to replaces an if-then-else block with an | |
2614 assignment. We have four kinds of transformations. Some of these | |
2615 transformations are also performed by the ifcvt RTL optimizer. | |
2616 | |
2617 Conditional Replacement | |
2618 ----------------------- | |
2619 | |
2620 This transformation, implemented in conditional_replacement, | |
2621 replaces | |
2622 | |
2623 bb0: | |
2624 if (cond) goto bb2; else goto bb1; | |
2625 bb1: | |
2626 bb2: | |
2627 x = PHI <0 (bb1), 1 (bb0), ...>; | |
2628 | |
2629 with | |
2630 | |
2631 bb0: | |
2632 x' = cond; | |
2633 goto bb2; | |
2634 bb2: | |
2635 x = PHI <x' (bb0), ...>; | |
2636 | |
2637 We remove bb1 as it becomes unreachable. This occurs often due to | |
2638 gimplification of conditionals. | |
2639 | |
2640 Value Replacement | |
2641 ----------------- | |
2642 | |
2643 This transformation, implemented in value_replacement, replaces | |
2644 | |
2645 bb0: | |
2646 if (a != b) goto bb2; else goto bb1; | |
2647 bb1: | |
2648 bb2: | |
2649 x = PHI <a (bb1), b (bb0), ...>; | |
2650 | |
2651 with | |
2652 | |
2653 bb0: | |
2654 bb2: | |
2655 x = PHI <b (bb0), ...>; | |
2656 | |
2657 This opportunity can sometimes occur as a result of other | |
2658 optimizations. | |
2659 | |
2660 | |
2661 Another case caught by value replacement looks like this: | |
2662 | |
2663 bb0: | |
2664 t1 = a == CONST; | |
2665 t2 = b > c; | |
2666 t3 = t1 & t2; | |
2667 if (t3 != 0) goto bb1; else goto bb2; | |
2668 bb1: | |
2669 bb2: | |
2670 x = PHI (CONST, a) | |
2671 | |
2672 Gets replaced with: | |
2673 bb0: | |
2674 bb2: | |
2675 t1 = a == CONST; | |
2676 t2 = b > c; | |
2677 t3 = t1 & t2; | |
2678 x = a; | |
2679 | |
2680 ABS Replacement | |
2681 --------------- | |
2682 | |
2683 This transformation, implemented in abs_replacement, replaces | |
2684 | |
2685 bb0: | |
2686 if (a >= 0) goto bb2; else goto bb1; | |
2687 bb1: | |
2688 x = -a; | |
2689 bb2: | |
2690 x = PHI <x (bb1), a (bb0), ...>; | |
2691 | |
2692 with | |
2693 | |
2694 bb0: | |
2695 x' = ABS_EXPR< a >; | |
2696 bb2: | |
2697 x = PHI <x' (bb0), ...>; | |
2698 | |
2699 MIN/MAX Replacement | |
2700 ------------------- | |
2701 | |
2702 This transformation, minmax_replacement replaces | |
2703 | |
2704 bb0: | |
2705 if (a <= b) goto bb2; else goto bb1; | |
2706 bb1: | |
2707 bb2: | |
2708 x = PHI <b (bb1), a (bb0), ...>; | |
2709 | |
2710 with | |
2711 | |
2712 bb0: | |
2713 x' = MIN_EXPR (a, b) | |
2714 bb2: | |
2715 x = PHI <x' (bb0), ...>; | |
2716 | |
2717 A similar transformation is done for MAX_EXPR. | |
2718 | |
2719 | |
2720 This pass also performs a fifth transformation of a slightly different | |
2721 flavor. | |
2722 | |
2723 Factor conversion in COND_EXPR | |
2724 ------------------------------ | |
2725 | |
2726 This transformation factors the conversion out of COND_EXPR with | |
2727 factor_out_conditional_conversion. | |
2728 | |
2729 For example: | |
2730 if (a <= CST) goto <bb 3>; else goto <bb 4>; | |
2731 <bb 3>: | |
2732 tmp = (int) a; | |
2733 <bb 4>: | |
2734 tmp = PHI <tmp, CST> | |
2735 | |
2736 Into: | |
2737 if (a <= CST) goto <bb 3>; else goto <bb 4>; | |
2738 <bb 3>: | |
2739 <bb 4>: | |
2740 a = PHI <a, CST> | |
2741 tmp = (int) a; | |
2742 | |
2743 Adjacent Load Hoisting | |
2744 ---------------------- | |
2745 | |
2746 This transformation replaces | |
2747 | |
2748 bb0: | |
2749 if (...) goto bb2; else goto bb1; | |
2750 bb1: | |
2751 x1 = (<expr>).field1; | |
2752 goto bb3; | |
2753 bb2: | |
2754 x2 = (<expr>).field2; | |
2755 bb3: | |
2756 # x = PHI <x1, x2>; | |
2757 | |
2758 with | |
2759 | |
2760 bb0: | |
2761 x1 = (<expr>).field1; | |
2762 x2 = (<expr>).field2; | |
2763 if (...) goto bb2; else goto bb1; | |
2764 bb1: | |
2765 goto bb3; | |
2766 bb2: | |
2767 bb3: | |
2768 # x = PHI <x1, x2>; | |
2769 | |
2770 The purpose of this transformation is to enable generation of conditional | |
2771 move instructions such as Intel CMOVE or PowerPC ISEL. Because one of | |
2772 the loads is speculative, the transformation is restricted to very | |
2773 specific cases to avoid introducing a page fault. We are looking for | |
2774 the common idiom: | |
2775 | |
2776 if (...) | |
2777 x = y->left; | |
2778 else | |
2779 x = y->right; | |
2780 | |
2781 where left and right are typically adjacent pointers in a tree structure. */ | |
2782 | |
2783 namespace { | |
2784 | |
2785 const pass_data pass_data_phiopt = | |
2786 { | |
2787 GIMPLE_PASS, /* type */ | |
2788 "phiopt", /* name */ | |
2789 OPTGROUP_NONE, /* optinfo_flags */ | |
2790 TV_TREE_PHIOPT, /* tv_id */ | |
2791 ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
2792 0, /* properties_provided */ | |
2793 0, /* properties_destroyed */ | |
2794 0, /* todo_flags_start */ | |
2795 0, /* todo_flags_finish */ | |
0 | 2796 }; |
111 | 2797 |
2798 class pass_phiopt : public gimple_opt_pass | |
2799 { | |
2800 public: | |
2801 pass_phiopt (gcc::context *ctxt) | |
131 | 2802 : gimple_opt_pass (pass_data_phiopt, ctxt), early_p (false) |
111 | 2803 {} |
2804 | |
2805 /* opt_pass methods: */ | |
2806 opt_pass * clone () { return new pass_phiopt (m_ctxt); } | |
131 | 2807 void set_pass_param (unsigned n, bool param) |
2808 { | |
2809 gcc_assert (n == 0); | |
2810 early_p = param; | |
2811 } | |
111 | 2812 virtual bool gate (function *) { return flag_ssa_phiopt; } |
2813 virtual unsigned int execute (function *) | |
2814 { | |
131 | 2815 return tree_ssa_phiopt_worker (false, |
2816 !early_p ? gate_hoist_loads () : false, | |
2817 early_p); | |
111 | 2818 } |
2819 | |
131 | 2820 private: |
2821 bool early_p; | |
111 | 2822 }; // class pass_phiopt |
2823 | |
2824 } // anon namespace | |
2825 | |
2826 gimple_opt_pass * | |
2827 make_pass_phiopt (gcc::context *ctxt) | |
2828 { | |
2829 return new pass_phiopt (ctxt); | |
2830 } | |
2831 | |
2832 namespace { | |
2833 | |
2834 const pass_data pass_data_cselim = | |
2835 { | |
2836 GIMPLE_PASS, /* type */ | |
2837 "cselim", /* name */ | |
2838 OPTGROUP_NONE, /* optinfo_flags */ | |
2839 TV_TREE_PHIOPT, /* tv_id */ | |
2840 ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
2841 0, /* properties_provided */ | |
2842 0, /* properties_destroyed */ | |
2843 0, /* todo_flags_start */ | |
2844 0, /* todo_flags_finish */ | |
2845 }; | |
2846 | |
2847 class pass_cselim : public gimple_opt_pass | |
2848 { | |
2849 public: | |
2850 pass_cselim (gcc::context *ctxt) | |
2851 : gimple_opt_pass (pass_data_cselim, ctxt) | |
2852 {} | |
2853 | |
2854 /* opt_pass methods: */ | |
2855 virtual bool gate (function *) { return flag_tree_cselim; } | |
2856 virtual unsigned int execute (function *) { return tree_ssa_cs_elim (); } | |
2857 | |
2858 }; // class pass_cselim | |
2859 | |
2860 } // anon namespace | |
2861 | |
2862 gimple_opt_pass * | |
2863 make_pass_cselim (gcc::context *ctxt) | |
2864 { | |
2865 return new pass_cselim (ctxt); | |
2866 } |