annotate gcc/tree-ssa-threadedge.c @ 127:4c56639505ff

fix function.c and add CbC-example Makefile
author mir3636
date Wed, 11 Apr 2018 18:46:58 +0900
parents 04ced10e8804
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* SSA Jump Threading
111
kono
parents: 67
diff changeset
2 Copyright (C) 2005-2017 Free Software Foundation, Inc.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 Contributed by Jeff Law <law@redhat.com>
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 This file is part of GCC.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 it under the terms of the GNU General Public License as published by
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 any later version.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 GNU General Public License for more details.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 #include "config.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 #include "coretypes.h"
111
kono
parents: 67
diff changeset
24 #include "backend.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 #include "tree.h"
111
kono
parents: 67
diff changeset
26 #include "gimple.h"
kono
parents: 67
diff changeset
27 #include "predict.h"
kono
parents: 67
diff changeset
28 #include "ssa.h"
kono
parents: 67
diff changeset
29 #include "fold-const.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 #include "cfgloop.h"
111
kono
parents: 67
diff changeset
31 #include "gimple-iterator.h"
kono
parents: 67
diff changeset
32 #include "tree-cfg.h"
kono
parents: 67
diff changeset
33 #include "tree-ssa-threadupdate.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 #include "params.h"
111
kono
parents: 67
diff changeset
35 #include "tree-ssa-scopedtables.h"
kono
parents: 67
diff changeset
36 #include "tree-ssa-threadedge.h"
kono
parents: 67
diff changeset
37 #include "tree-ssa-dom.h"
kono
parents: 67
diff changeset
38 #include "gimple-fold.h"
kono
parents: 67
diff changeset
39 #include "cfganal.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 /* To avoid code explosion due to jump threading, we limit the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 number of statements we are going to copy. This variable
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 holds the number of statements currently seen that we'll have
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 to copy as part of the jump threading process. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 static int stmt_count;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
47 /* Array to record value-handles per SSA_NAME. */
111
kono
parents: 67
diff changeset
48 vec<tree> ssa_name_values;
kono
parents: 67
diff changeset
49
kono
parents: 67
diff changeset
50 typedef tree (pfn_simplify) (gimple *, gimple *,
kono
parents: 67
diff changeset
51 class avail_exprs_stack *,
kono
parents: 67
diff changeset
52 basic_block);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
53
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
54 /* Set the value for the SSA name NAME to VALUE. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
56 void
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
57 set_ssa_name_value (tree name, tree value)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
58 {
111
kono
parents: 67
diff changeset
59 if (SSA_NAME_VERSION (name) >= ssa_name_values.length ())
kono
parents: 67
diff changeset
60 ssa_name_values.safe_grow_cleared (SSA_NAME_VERSION (name) + 1);
kono
parents: 67
diff changeset
61 if (value && TREE_OVERFLOW_P (value))
kono
parents: 67
diff changeset
62 value = drop_tree_overflow (value);
kono
parents: 67
diff changeset
63 ssa_name_values[SSA_NAME_VERSION (name)] = value;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
64 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
65
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
66 /* Initialize the per SSA_NAME value-handles array. Returns it. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
67 void
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
68 threadedge_initialize_values (void)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
69 {
111
kono
parents: 67
diff changeset
70 gcc_assert (!ssa_name_values.exists ());
kono
parents: 67
diff changeset
71 ssa_name_values.create (num_ssa_names);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
72 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
73
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
74 /* Free the per SSA_NAME value-handle array. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
75 void
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
76 threadedge_finalize_values (void)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
77 {
111
kono
parents: 67
diff changeset
78 ssa_name_values.release ();
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
79 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
80
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 /* Return TRUE if we may be able to thread an incoming edge into
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 BB to an outgoing edge from BB. Return FALSE otherwise. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
83
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 potentially_threadable_block (basic_block bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 gimple_stmt_iterator gsi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88
111
kono
parents: 67
diff changeset
89 /* Special case. We can get blocks that are forwarders, but are
kono
parents: 67
diff changeset
90 not optimized away because they forward from outside a loop
kono
parents: 67
diff changeset
91 to the loop header. We want to thread through them as we can
kono
parents: 67
diff changeset
92 sometimes thread to the loop exit, which is obviously profitable.
kono
parents: 67
diff changeset
93 the interesting case here is when the block has PHIs. */
kono
parents: 67
diff changeset
94 if (gsi_end_p (gsi_start_nondebug_bb (bb))
kono
parents: 67
diff changeset
95 && !gsi_end_p (gsi_start_phis (bb)))
kono
parents: 67
diff changeset
96 return true;
kono
parents: 67
diff changeset
97
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
98 /* If BB has a single successor or a single predecessor, then
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 there is no threading opportunity. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 if (single_succ_p (bb) || single_pred_p (bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 /* If BB does not end with a conditional, switch or computed goto,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 then there is no threading opportunity. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 gsi = gsi_last_bb (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 if (gsi_end_p (gsi)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 || ! gsi_stmt (gsi)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 || (gimple_code (gsi_stmt (gsi)) != GIMPLE_COND
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 && gimple_code (gsi_stmt (gsi)) != GIMPLE_GOTO
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 && gimple_code (gsi_stmt (gsi)) != GIMPLE_SWITCH))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
115
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
116 /* Record temporary equivalences created by PHIs at the target of the
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
117 edge E. Record unwind information for the equivalences onto STACK.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
118
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 If a PHI which prevents threading is encountered, then return FALSE
111
kono
parents: 67
diff changeset
120 indicating we should not thread this edge, else return TRUE.
kono
parents: 67
diff changeset
121
kono
parents: 67
diff changeset
122 If SRC_MAP/DST_MAP exist, then mark the source and destination SSA_NAMEs
kono
parents: 67
diff changeset
123 of any equivalences recorded. We use this to make invalidation after
kono
parents: 67
diff changeset
124 traversing back edges less painful. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
125
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
126 static bool
111
kono
parents: 67
diff changeset
127 record_temporary_equivalences_from_phis (edge e, const_and_copies *const_and_copies)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
128 {
111
kono
parents: 67
diff changeset
129 gphi_iterator gsi;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
130
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
131 /* Each PHI creates a temporary equivalence, record them.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 These are context sensitive equivalences and will be removed
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 later. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 {
111
kono
parents: 67
diff changeset
136 gphi *phi = gsi.phi ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
137 tree src = PHI_ARG_DEF_FROM_EDGE (phi, e);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 tree dst = gimple_phi_result (phi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
140 /* If the desired argument is not the same as this PHI's result
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 and it is set by a PHI in E->dest, then we can not thread
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142 through E->dest. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 if (src != dst
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 && TREE_CODE (src) == SSA_NAME
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 && gimple_code (SSA_NAME_DEF_STMT (src)) == GIMPLE_PHI
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 && gimple_bb (SSA_NAME_DEF_STMT (src)) == e->dest)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
147 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
148
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 /* We consider any non-virtual PHI as a statement since it
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
150 count result in a constant assignment or copy operation. */
111
kono
parents: 67
diff changeset
151 if (!virtual_operand_p (dst))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 stmt_count++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
153
111
kono
parents: 67
diff changeset
154 const_and_copies->record_const_or_copy (dst, src);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
158
111
kono
parents: 67
diff changeset
159 /* Valueize hook for gimple_fold_stmt_to_constant_1. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
160
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 static tree
111
kono
parents: 67
diff changeset
162 threadedge_valueize (tree t)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 {
111
kono
parents: 67
diff changeset
164 if (TREE_CODE (t) == SSA_NAME)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 {
111
kono
parents: 67
diff changeset
166 tree tem = SSA_NAME_VALUE (t);
kono
parents: 67
diff changeset
167 if (tem)
kono
parents: 67
diff changeset
168 return tem;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
169 }
111
kono
parents: 67
diff changeset
170 return t;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
172
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 /* Try to simplify each statement in E->dest, ultimately leading to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 a simplification of the COND_EXPR at the end of E->dest.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
175
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 Record unwind information for temporary equivalences onto STACK.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
177
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 Use SIMPLIFY (a pointer to a callback function) to further simplify
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
179 statements using pass specific information.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
180
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
181 We might consider marking just those statements which ultimately
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 feed the COND_EXPR. It's not clear if the overhead of bookkeeping
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 would be recovered by trying to simplify fewer statements.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
184
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 If we are able to simplify a statement into the form
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
186 SSA_NAME = (SSA_NAME | gimple invariant), then we can record
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 a context sensitive equivalence which may help us simplify
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 later statements in E->dest. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
189
111
kono
parents: 67
diff changeset
190 static gimple *
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 record_temporary_equivalences_from_stmts_at_dest (edge e,
111
kono
parents: 67
diff changeset
192 const_and_copies *const_and_copies,
kono
parents: 67
diff changeset
193 avail_exprs_stack *avail_exprs_stack,
kono
parents: 67
diff changeset
194 pfn_simplify simplify)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 {
111
kono
parents: 67
diff changeset
196 gimple *stmt = NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 gimple_stmt_iterator gsi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 int max_stmt_count;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
199
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 max_stmt_count = PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
201
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 /* Walk through each statement in the block recording equivalences
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 we discover. Note any equivalences we discover are context
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 sensitive (ie, are dependent on traversing E) and must be unwound
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 when we're finished processing E. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 for (gsi = gsi_start_bb (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 tree cached_lhs = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 stmt = gsi_stmt (gsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 /* Ignore empty statements and labels. */
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
213 if (gimple_code (stmt) == GIMPLE_NOP
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
214 || gimple_code (stmt) == GIMPLE_LABEL
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
215 || is_gimple_debug (stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
217
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
218 /* If the statement has volatile operands, then we assume we
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 can not thread through this block. This is overly
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 conservative in some ways. */
111
kono
parents: 67
diff changeset
221 if (gimple_code (stmt) == GIMPLE_ASM
kono
parents: 67
diff changeset
222 && gimple_asm_volatile_p (as_a <gasm *> (stmt)))
kono
parents: 67
diff changeset
223 return NULL;
kono
parents: 67
diff changeset
224
kono
parents: 67
diff changeset
225 /* If the statement is a unique builtin, we can not thread
kono
parents: 67
diff changeset
226 through here. */
kono
parents: 67
diff changeset
227 if (gimple_code (stmt) == GIMPLE_CALL
kono
parents: 67
diff changeset
228 && gimple_call_internal_p (stmt)
kono
parents: 67
diff changeset
229 && gimple_call_internal_unique_p (stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 /* If duplicating this block is going to cause too much code
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 expansion, then do not thread through this block. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 stmt_count++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 if (stmt_count > max_stmt_count)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
237
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 /* If this is not a statement that sets an SSA_NAME to a new
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 value, then do not try to simplify this statement as it will
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 not simplify in any way that is helpful for jump threading. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 if ((gimple_code (stmt) != GIMPLE_ASSIGN
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
243 && (gimple_code (stmt) != GIMPLE_CALL
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 || gimple_call_lhs (stmt) == NULL_TREE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 || TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
248 /* The result of __builtin_object_size depends on all the arguments
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 of a phi node. Temporarily using only one edge produces invalid
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 results. For example
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
251
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 if (x < 6)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
253 goto l;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255 goto l;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 l:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 r = PHI <&w[2].a[1](2), &a.a[6](3)>
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259 __builtin_object_size (r, 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
261 The result of __builtin_object_size is defined to be the maximum of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 remaining bytes. If we use only one edge on the phi, the result will
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263 change to be the remaining bytes for the corresponding phi argument.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 Similarly for __builtin_constant_p:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 r = PHI <1(2), 2(3)>
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 __builtin_constant_p (r)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 Both PHI arguments are constant, but x ? 1 : 2 is still not
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 constant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 if (is_gimple_call (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 tree fndecl = gimple_call_fndecl (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
276 if (fndecl
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_OBJECT_SIZE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
278 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
280 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
281
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 /* At this point we have a statement which assigns an RHS to an
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 SSA_VAR on the LHS. We want to try and simplify this statement
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
284 to expose more context sensitive equivalences which in turn may
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
285 allow us to simplify the condition at the end of the loop.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
286
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 Handle simple copy operations as well as implied copies from
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
288 ASSERT_EXPRs. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
289 if (gimple_assign_single_p (stmt)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
290 && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
291 cached_lhs = gimple_assign_rhs1 (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
292 else if (gimple_assign_single_p (stmt)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
294 cached_lhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
296 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
297 /* A statement that is not a trivial copy or ASSERT_EXPR.
111
kono
parents: 67
diff changeset
298 Try to fold the new expression. Inserting the
kono
parents: 67
diff changeset
299 expression into the hash table is unlikely to help. */
kono
parents: 67
diff changeset
300 /* ??? The DOM callback below can be changed to setting
kono
parents: 67
diff changeset
301 the mprts_hook around the call to thread_across_edge,
kono
parents: 67
diff changeset
302 avoiding the use substitution. The VRP hook should be
kono
parents: 67
diff changeset
303 changed to properly valueize operands itself using
kono
parents: 67
diff changeset
304 SSA_NAME_VALUE in addition to its own lattice. */
kono
parents: 67
diff changeset
305 cached_lhs = gimple_fold_stmt_to_constant_1 (stmt,
kono
parents: 67
diff changeset
306 threadedge_valueize);
kono
parents: 67
diff changeset
307 if (NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES) != 0
kono
parents: 67
diff changeset
308 && (!cached_lhs
kono
parents: 67
diff changeset
309 || (TREE_CODE (cached_lhs) != SSA_NAME
kono
parents: 67
diff changeset
310 && !is_gimple_min_invariant (cached_lhs))))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 {
111
kono
parents: 67
diff changeset
312 /* We're going to temporarily copy propagate the operands
kono
parents: 67
diff changeset
313 and see if that allows us to simplify this statement. */
kono
parents: 67
diff changeset
314 tree *copy;
kono
parents: 67
diff changeset
315 ssa_op_iter iter;
kono
parents: 67
diff changeset
316 use_operand_p use_p;
kono
parents: 67
diff changeset
317 unsigned int num, i = 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
318
111
kono
parents: 67
diff changeset
319 num = NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES);
kono
parents: 67
diff changeset
320 copy = XALLOCAVEC (tree, num);
kono
parents: 67
diff changeset
321
kono
parents: 67
diff changeset
322 /* Make a copy of the uses & vuses into USES_COPY, then cprop into
kono
parents: 67
diff changeset
323 the operands. */
kono
parents: 67
diff changeset
324 FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
kono
parents: 67
diff changeset
325 {
kono
parents: 67
diff changeset
326 tree tmp = NULL;
kono
parents: 67
diff changeset
327 tree use = USE_FROM_PTR (use_p);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
328
111
kono
parents: 67
diff changeset
329 copy[i++] = use;
kono
parents: 67
diff changeset
330 if (TREE_CODE (use) == SSA_NAME)
kono
parents: 67
diff changeset
331 tmp = SSA_NAME_VALUE (use);
kono
parents: 67
diff changeset
332 if (tmp)
kono
parents: 67
diff changeset
333 SET_USE (use_p, tmp);
kono
parents: 67
diff changeset
334 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
335
111
kono
parents: 67
diff changeset
336 cached_lhs = (*simplify) (stmt, stmt, avail_exprs_stack, e->src);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
337
111
kono
parents: 67
diff changeset
338 /* Restore the statement's original uses/defs. */
kono
parents: 67
diff changeset
339 i = 0;
kono
parents: 67
diff changeset
340 FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
kono
parents: 67
diff changeset
341 SET_USE (use_p, copy[i++]);
kono
parents: 67
diff changeset
342 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
343 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 /* Record the context sensitive equivalence if we were able
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 to simplify this statement. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 if (cached_lhs
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348 && (TREE_CODE (cached_lhs) == SSA_NAME
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 || is_gimple_min_invariant (cached_lhs)))
111
kono
parents: 67
diff changeset
350 const_and_copies->record_const_or_copy (gimple_get_lhs (stmt),
kono
parents: 67
diff changeset
351 cached_lhs);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
353 return stmt;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
354 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
355
111
kono
parents: 67
diff changeset
356 static tree simplify_control_stmt_condition_1 (edge, gimple *,
kono
parents: 67
diff changeset
357 class avail_exprs_stack *,
kono
parents: 67
diff changeset
358 tree, enum tree_code, tree,
kono
parents: 67
diff changeset
359 gcond *, pfn_simplify,
kono
parents: 67
diff changeset
360 unsigned);
kono
parents: 67
diff changeset
361
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
362 /* Simplify the control statement at the end of the block E->dest.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
363
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
364 To avoid allocating memory unnecessarily, a scratch GIMPLE_COND
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
365 is available to use/clobber in DUMMY_COND.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
366
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
367 Use SIMPLIFY (a pointer to a callback function) to further simplify
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
368 a condition using pass specific information.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
369
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
370 Return the simplified condition or NULL if simplification could
111
kono
parents: 67
diff changeset
371 not be performed. When simplifying a GIMPLE_SWITCH, we may return
kono
parents: 67
diff changeset
372 the CASE_LABEL_EXPR that will be taken.
kono
parents: 67
diff changeset
373
kono
parents: 67
diff changeset
374 The available expression table is referenced via AVAIL_EXPRS_STACK. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
375
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
376 static tree
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
377 simplify_control_stmt_condition (edge e,
111
kono
parents: 67
diff changeset
378 gimple *stmt,
kono
parents: 67
diff changeset
379 class avail_exprs_stack *avail_exprs_stack,
kono
parents: 67
diff changeset
380 gcond *dummy_cond,
kono
parents: 67
diff changeset
381 pfn_simplify simplify)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
382 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
383 tree cond, cached_lhs;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
384 enum gimple_code code = gimple_code (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
385
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
386 /* For comparisons, we have to update both operands, then try
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
387 to simplify the comparison. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
388 if (code == GIMPLE_COND)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
389 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
390 tree op0, op1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
391 enum tree_code cond_code;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
392
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
393 op0 = gimple_cond_lhs (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
394 op1 = gimple_cond_rhs (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
395 cond_code = gimple_cond_code (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
396
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
397 /* Get the current value of both operands. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
398 if (TREE_CODE (op0) == SSA_NAME)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
399 {
111
kono
parents: 67
diff changeset
400 for (int i = 0; i < 2; i++)
kono
parents: 67
diff changeset
401 {
kono
parents: 67
diff changeset
402 if (TREE_CODE (op0) == SSA_NAME
kono
parents: 67
diff changeset
403 && SSA_NAME_VALUE (op0))
kono
parents: 67
diff changeset
404 op0 = SSA_NAME_VALUE (op0);
kono
parents: 67
diff changeset
405 else
kono
parents: 67
diff changeset
406 break;
kono
parents: 67
diff changeset
407 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
408 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
409
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
410 if (TREE_CODE (op1) == SSA_NAME)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
411 {
111
kono
parents: 67
diff changeset
412 for (int i = 0; i < 2; i++)
kono
parents: 67
diff changeset
413 {
kono
parents: 67
diff changeset
414 if (TREE_CODE (op1) == SSA_NAME
kono
parents: 67
diff changeset
415 && SSA_NAME_VALUE (op1))
kono
parents: 67
diff changeset
416 op1 = SSA_NAME_VALUE (op1);
kono
parents: 67
diff changeset
417 else
kono
parents: 67
diff changeset
418 break;
kono
parents: 67
diff changeset
419 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
420 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
421
111
kono
parents: 67
diff changeset
422 const unsigned recursion_limit = 4;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
423
111
kono
parents: 67
diff changeset
424 cached_lhs
kono
parents: 67
diff changeset
425 = simplify_control_stmt_condition_1 (e, stmt, avail_exprs_stack,
kono
parents: 67
diff changeset
426 op0, cond_code, op1,
kono
parents: 67
diff changeset
427 dummy_cond, simplify,
kono
parents: 67
diff changeset
428 recursion_limit);
kono
parents: 67
diff changeset
429
kono
parents: 67
diff changeset
430 /* If we were testing an integer/pointer against a constant, then
kono
parents: 67
diff changeset
431 we can use the FSM code to trace the value of the SSA_NAME. If
kono
parents: 67
diff changeset
432 a value is found, then the condition will collapse to a constant.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
433
111
kono
parents: 67
diff changeset
434 Return the SSA_NAME we want to trace back rather than the full
kono
parents: 67
diff changeset
435 expression and give the FSM threader a chance to find its value. */
kono
parents: 67
diff changeset
436 if (cached_lhs == NULL)
kono
parents: 67
diff changeset
437 {
kono
parents: 67
diff changeset
438 /* Recover the original operands. They may have been simplified
kono
parents: 67
diff changeset
439 using context sensitive equivalences. Those context sensitive
kono
parents: 67
diff changeset
440 equivalences may not be valid on paths found by the FSM optimizer. */
kono
parents: 67
diff changeset
441 tree op0 = gimple_cond_lhs (stmt);
kono
parents: 67
diff changeset
442 tree op1 = gimple_cond_rhs (stmt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
443
111
kono
parents: 67
diff changeset
444 if ((INTEGRAL_TYPE_P (TREE_TYPE (op0))
kono
parents: 67
diff changeset
445 || POINTER_TYPE_P (TREE_TYPE (op0)))
kono
parents: 67
diff changeset
446 && TREE_CODE (op0) == SSA_NAME
kono
parents: 67
diff changeset
447 && TREE_CODE (op1) == INTEGER_CST)
kono
parents: 67
diff changeset
448 return op0;
kono
parents: 67
diff changeset
449 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
450
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
451 return cached_lhs;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
452 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
453
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
454 if (code == GIMPLE_SWITCH)
111
kono
parents: 67
diff changeset
455 cond = gimple_switch_index (as_a <gswitch *> (stmt));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
456 else if (code == GIMPLE_GOTO)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
457 cond = gimple_goto_dest (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
458 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
459 gcc_unreachable ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
460
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
461 /* We can have conditionals which just test the state of a variable
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
462 rather than use a relational operator. These are simpler to handle. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
463 if (TREE_CODE (cond) == SSA_NAME)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
464 {
111
kono
parents: 67
diff changeset
465 tree original_lhs = cond;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
466 cached_lhs = cond;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
467
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
468 /* Get the variable's current value from the equivalence chains.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
469
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470 It is possible to get loops in the SSA_NAME_VALUE chains
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
471 (consider threading the backedge of a loop where we have
111
kono
parents: 67
diff changeset
472 a loop invariant SSA_NAME used in the condition). */
kono
parents: 67
diff changeset
473 if (cached_lhs)
kono
parents: 67
diff changeset
474 {
kono
parents: 67
diff changeset
475 for (int i = 0; i < 2; i++)
kono
parents: 67
diff changeset
476 {
kono
parents: 67
diff changeset
477 if (TREE_CODE (cached_lhs) == SSA_NAME
kono
parents: 67
diff changeset
478 && SSA_NAME_VALUE (cached_lhs))
kono
parents: 67
diff changeset
479 cached_lhs = SSA_NAME_VALUE (cached_lhs);
kono
parents: 67
diff changeset
480 else
kono
parents: 67
diff changeset
481 break;
kono
parents: 67
diff changeset
482 }
kono
parents: 67
diff changeset
483 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
484
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
485 /* If we haven't simplified to an invariant yet, then use the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
486 pass specific callback to try and simplify it further. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
487 if (cached_lhs && ! is_gimple_min_invariant (cached_lhs))
111
kono
parents: 67
diff changeset
488 {
kono
parents: 67
diff changeset
489 if (code == GIMPLE_SWITCH)
kono
parents: 67
diff changeset
490 {
kono
parents: 67
diff changeset
491 /* Replace the index operand of the GIMPLE_SWITCH with any LHS
kono
parents: 67
diff changeset
492 we found before handing off to VRP. If simplification is
kono
parents: 67
diff changeset
493 possible, the simplified value will be a CASE_LABEL_EXPR of
kono
parents: 67
diff changeset
494 the label that is proven to be taken. */
kono
parents: 67
diff changeset
495 gswitch *dummy_switch = as_a<gswitch *> (gimple_copy (stmt));
kono
parents: 67
diff changeset
496 gimple_switch_set_index (dummy_switch, cached_lhs);
kono
parents: 67
diff changeset
497 cached_lhs = (*simplify) (dummy_switch, stmt,
kono
parents: 67
diff changeset
498 avail_exprs_stack, e->src);
kono
parents: 67
diff changeset
499 ggc_free (dummy_switch);
kono
parents: 67
diff changeset
500 }
kono
parents: 67
diff changeset
501 else
kono
parents: 67
diff changeset
502 cached_lhs = (*simplify) (stmt, stmt, avail_exprs_stack, e->src);
kono
parents: 67
diff changeset
503 }
kono
parents: 67
diff changeset
504
kono
parents: 67
diff changeset
505 /* We couldn't find an invariant. But, callers of this
kono
parents: 67
diff changeset
506 function may be able to do something useful with the
kono
parents: 67
diff changeset
507 unmodified destination. */
kono
parents: 67
diff changeset
508 if (!cached_lhs)
kono
parents: 67
diff changeset
509 cached_lhs = original_lhs;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
510 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
511 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
512 cached_lhs = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
513
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
514 return cached_lhs;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
515 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
516
111
kono
parents: 67
diff changeset
517 /* Recursive helper for simplify_control_stmt_condition. */
kono
parents: 67
diff changeset
518
kono
parents: 67
diff changeset
519 static tree
kono
parents: 67
diff changeset
520 simplify_control_stmt_condition_1 (edge e,
kono
parents: 67
diff changeset
521 gimple *stmt,
kono
parents: 67
diff changeset
522 class avail_exprs_stack *avail_exprs_stack,
kono
parents: 67
diff changeset
523 tree op0,
kono
parents: 67
diff changeset
524 enum tree_code cond_code,
kono
parents: 67
diff changeset
525 tree op1,
kono
parents: 67
diff changeset
526 gcond *dummy_cond,
kono
parents: 67
diff changeset
527 pfn_simplify simplify,
kono
parents: 67
diff changeset
528 unsigned limit)
kono
parents: 67
diff changeset
529 {
kono
parents: 67
diff changeset
530 if (limit == 0)
kono
parents: 67
diff changeset
531 return NULL_TREE;
kono
parents: 67
diff changeset
532
kono
parents: 67
diff changeset
533 /* We may need to canonicalize the comparison. For
kono
parents: 67
diff changeset
534 example, op0 might be a constant while op1 is an
kono
parents: 67
diff changeset
535 SSA_NAME. Failure to canonicalize will cause us to
kono
parents: 67
diff changeset
536 miss threading opportunities. */
kono
parents: 67
diff changeset
537 if (tree_swap_operands_p (op0, op1))
kono
parents: 67
diff changeset
538 {
kono
parents: 67
diff changeset
539 cond_code = swap_tree_comparison (cond_code);
kono
parents: 67
diff changeset
540 std::swap (op0, op1);
kono
parents: 67
diff changeset
541 }
kono
parents: 67
diff changeset
542
kono
parents: 67
diff changeset
543 /* If the condition has the form (A & B) CMP 0 or (A | B) CMP 0 then
kono
parents: 67
diff changeset
544 recurse into the LHS to see if there is a dominating ASSERT_EXPR
kono
parents: 67
diff changeset
545 of A or of B that makes this condition always true or always false
kono
parents: 67
diff changeset
546 along the edge E. */
kono
parents: 67
diff changeset
547 if ((cond_code == EQ_EXPR || cond_code == NE_EXPR)
kono
parents: 67
diff changeset
548 && TREE_CODE (op0) == SSA_NAME
kono
parents: 67
diff changeset
549 && integer_zerop (op1))
kono
parents: 67
diff changeset
550 {
kono
parents: 67
diff changeset
551 gimple *def_stmt = SSA_NAME_DEF_STMT (op0);
kono
parents: 67
diff changeset
552 if (gimple_code (def_stmt) != GIMPLE_ASSIGN)
kono
parents: 67
diff changeset
553 ;
kono
parents: 67
diff changeset
554 else if (gimple_assign_rhs_code (def_stmt) == BIT_AND_EXPR
kono
parents: 67
diff changeset
555 || gimple_assign_rhs_code (def_stmt) == BIT_IOR_EXPR)
kono
parents: 67
diff changeset
556 {
kono
parents: 67
diff changeset
557 enum tree_code rhs_code = gimple_assign_rhs_code (def_stmt);
kono
parents: 67
diff changeset
558 const tree rhs1 = gimple_assign_rhs1 (def_stmt);
kono
parents: 67
diff changeset
559 const tree rhs2 = gimple_assign_rhs2 (def_stmt);
kono
parents: 67
diff changeset
560
kono
parents: 67
diff changeset
561 /* Is A != 0 ? */
kono
parents: 67
diff changeset
562 const tree res1
kono
parents: 67
diff changeset
563 = simplify_control_stmt_condition_1 (e, def_stmt, avail_exprs_stack,
kono
parents: 67
diff changeset
564 rhs1, NE_EXPR, op1,
kono
parents: 67
diff changeset
565 dummy_cond, simplify,
kono
parents: 67
diff changeset
566 limit - 1);
kono
parents: 67
diff changeset
567 if (res1 == NULL_TREE)
kono
parents: 67
diff changeset
568 ;
kono
parents: 67
diff changeset
569 else if (rhs_code == BIT_AND_EXPR && integer_zerop (res1))
kono
parents: 67
diff changeset
570 {
kono
parents: 67
diff changeset
571 /* If A == 0 then (A & B) != 0 is always false. */
kono
parents: 67
diff changeset
572 if (cond_code == NE_EXPR)
kono
parents: 67
diff changeset
573 return boolean_false_node;
kono
parents: 67
diff changeset
574 /* If A == 0 then (A & B) == 0 is always true. */
kono
parents: 67
diff changeset
575 if (cond_code == EQ_EXPR)
kono
parents: 67
diff changeset
576 return boolean_true_node;
kono
parents: 67
diff changeset
577 }
kono
parents: 67
diff changeset
578 else if (rhs_code == BIT_IOR_EXPR && integer_nonzerop (res1))
kono
parents: 67
diff changeset
579 {
kono
parents: 67
diff changeset
580 /* If A != 0 then (A | B) != 0 is always true. */
kono
parents: 67
diff changeset
581 if (cond_code == NE_EXPR)
kono
parents: 67
diff changeset
582 return boolean_true_node;
kono
parents: 67
diff changeset
583 /* If A != 0 then (A | B) == 0 is always false. */
kono
parents: 67
diff changeset
584 if (cond_code == EQ_EXPR)
kono
parents: 67
diff changeset
585 return boolean_false_node;
kono
parents: 67
diff changeset
586 }
kono
parents: 67
diff changeset
587
kono
parents: 67
diff changeset
588 /* Is B != 0 ? */
kono
parents: 67
diff changeset
589 const tree res2
kono
parents: 67
diff changeset
590 = simplify_control_stmt_condition_1 (e, def_stmt, avail_exprs_stack,
kono
parents: 67
diff changeset
591 rhs2, NE_EXPR, op1,
kono
parents: 67
diff changeset
592 dummy_cond, simplify,
kono
parents: 67
diff changeset
593 limit - 1);
kono
parents: 67
diff changeset
594 if (res2 == NULL_TREE)
kono
parents: 67
diff changeset
595 ;
kono
parents: 67
diff changeset
596 else if (rhs_code == BIT_AND_EXPR && integer_zerop (res2))
kono
parents: 67
diff changeset
597 {
kono
parents: 67
diff changeset
598 /* If B == 0 then (A & B) != 0 is always false. */
kono
parents: 67
diff changeset
599 if (cond_code == NE_EXPR)
kono
parents: 67
diff changeset
600 return boolean_false_node;
kono
parents: 67
diff changeset
601 /* If B == 0 then (A & B) == 0 is always true. */
kono
parents: 67
diff changeset
602 if (cond_code == EQ_EXPR)
kono
parents: 67
diff changeset
603 return boolean_true_node;
kono
parents: 67
diff changeset
604 }
kono
parents: 67
diff changeset
605 else if (rhs_code == BIT_IOR_EXPR && integer_nonzerop (res2))
kono
parents: 67
diff changeset
606 {
kono
parents: 67
diff changeset
607 /* If B != 0 then (A | B) != 0 is always true. */
kono
parents: 67
diff changeset
608 if (cond_code == NE_EXPR)
kono
parents: 67
diff changeset
609 return boolean_true_node;
kono
parents: 67
diff changeset
610 /* If B != 0 then (A | B) == 0 is always false. */
kono
parents: 67
diff changeset
611 if (cond_code == EQ_EXPR)
kono
parents: 67
diff changeset
612 return boolean_false_node;
kono
parents: 67
diff changeset
613 }
kono
parents: 67
diff changeset
614
kono
parents: 67
diff changeset
615 if (res1 != NULL_TREE && res2 != NULL_TREE)
kono
parents: 67
diff changeset
616 {
kono
parents: 67
diff changeset
617 if (rhs_code == BIT_AND_EXPR
kono
parents: 67
diff changeset
618 && TYPE_PRECISION (TREE_TYPE (op0)) == 1
kono
parents: 67
diff changeset
619 && integer_nonzerop (res1)
kono
parents: 67
diff changeset
620 && integer_nonzerop (res2))
kono
parents: 67
diff changeset
621 {
kono
parents: 67
diff changeset
622 /* If A != 0 and B != 0 then (bool)(A & B) != 0 is true. */
kono
parents: 67
diff changeset
623 if (cond_code == NE_EXPR)
kono
parents: 67
diff changeset
624 return boolean_true_node;
kono
parents: 67
diff changeset
625 /* If A != 0 and B != 0 then (bool)(A & B) == 0 is false. */
kono
parents: 67
diff changeset
626 if (cond_code == EQ_EXPR)
kono
parents: 67
diff changeset
627 return boolean_false_node;
kono
parents: 67
diff changeset
628 }
kono
parents: 67
diff changeset
629
kono
parents: 67
diff changeset
630 if (rhs_code == BIT_IOR_EXPR
kono
parents: 67
diff changeset
631 && integer_zerop (res1)
kono
parents: 67
diff changeset
632 && integer_zerop (res2))
kono
parents: 67
diff changeset
633 {
kono
parents: 67
diff changeset
634 /* If A == 0 and B == 0 then (A | B) != 0 is false. */
kono
parents: 67
diff changeset
635 if (cond_code == NE_EXPR)
kono
parents: 67
diff changeset
636 return boolean_false_node;
kono
parents: 67
diff changeset
637 /* If A == 0 and B == 0 then (A | B) == 0 is true. */
kono
parents: 67
diff changeset
638 if (cond_code == EQ_EXPR)
kono
parents: 67
diff changeset
639 return boolean_true_node;
kono
parents: 67
diff changeset
640 }
kono
parents: 67
diff changeset
641 }
kono
parents: 67
diff changeset
642 }
kono
parents: 67
diff changeset
643 /* Handle (A CMP B) CMP 0. */
kono
parents: 67
diff changeset
644 else if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt))
kono
parents: 67
diff changeset
645 == tcc_comparison)
kono
parents: 67
diff changeset
646 {
kono
parents: 67
diff changeset
647 tree rhs1 = gimple_assign_rhs1 (def_stmt);
kono
parents: 67
diff changeset
648 tree rhs2 = gimple_assign_rhs2 (def_stmt);
kono
parents: 67
diff changeset
649
kono
parents: 67
diff changeset
650 tree_code new_cond = gimple_assign_rhs_code (def_stmt);
kono
parents: 67
diff changeset
651 if (cond_code == EQ_EXPR)
kono
parents: 67
diff changeset
652 new_cond = invert_tree_comparison (new_cond, false);
kono
parents: 67
diff changeset
653
kono
parents: 67
diff changeset
654 tree res
kono
parents: 67
diff changeset
655 = simplify_control_stmt_condition_1 (e, def_stmt, avail_exprs_stack,
kono
parents: 67
diff changeset
656 rhs1, new_cond, rhs2,
kono
parents: 67
diff changeset
657 dummy_cond, simplify,
kono
parents: 67
diff changeset
658 limit - 1);
kono
parents: 67
diff changeset
659 if (res != NULL_TREE && is_gimple_min_invariant (res))
kono
parents: 67
diff changeset
660 return res;
kono
parents: 67
diff changeset
661 }
kono
parents: 67
diff changeset
662 }
kono
parents: 67
diff changeset
663
kono
parents: 67
diff changeset
664 gimple_cond_set_code (dummy_cond, cond_code);
kono
parents: 67
diff changeset
665 gimple_cond_set_lhs (dummy_cond, op0);
kono
parents: 67
diff changeset
666 gimple_cond_set_rhs (dummy_cond, op1);
kono
parents: 67
diff changeset
667
kono
parents: 67
diff changeset
668 /* We absolutely do not care about any type conversions
kono
parents: 67
diff changeset
669 we only care about a zero/nonzero value. */
kono
parents: 67
diff changeset
670 fold_defer_overflow_warnings ();
kono
parents: 67
diff changeset
671
kono
parents: 67
diff changeset
672 tree res = fold_binary (cond_code, boolean_type_node, op0, op1);
kono
parents: 67
diff changeset
673 if (res)
kono
parents: 67
diff changeset
674 while (CONVERT_EXPR_P (res))
kono
parents: 67
diff changeset
675 res = TREE_OPERAND (res, 0);
kono
parents: 67
diff changeset
676
kono
parents: 67
diff changeset
677 fold_undefer_overflow_warnings ((res && is_gimple_min_invariant (res)),
kono
parents: 67
diff changeset
678 stmt, WARN_STRICT_OVERFLOW_CONDITIONAL);
kono
parents: 67
diff changeset
679
kono
parents: 67
diff changeset
680 /* If we have not simplified the condition down to an invariant,
kono
parents: 67
diff changeset
681 then use the pass specific callback to simplify the condition. */
kono
parents: 67
diff changeset
682 if (!res
kono
parents: 67
diff changeset
683 || !is_gimple_min_invariant (res))
kono
parents: 67
diff changeset
684 res = (*simplify) (dummy_cond, stmt, avail_exprs_stack, e->src);
kono
parents: 67
diff changeset
685
kono
parents: 67
diff changeset
686 return res;
kono
parents: 67
diff changeset
687 }
kono
parents: 67
diff changeset
688
kono
parents: 67
diff changeset
689 /* Copy debug stmts from DEST's chain of single predecessors up to
kono
parents: 67
diff changeset
690 SRC, so that we don't lose the bindings as PHI nodes are introduced
kono
parents: 67
diff changeset
691 when DEST gains new predecessors. */
kono
parents: 67
diff changeset
692 void
kono
parents: 67
diff changeset
693 propagate_threaded_block_debug_into (basic_block dest, basic_block src)
kono
parents: 67
diff changeset
694 {
kono
parents: 67
diff changeset
695 if (!MAY_HAVE_DEBUG_STMTS)
kono
parents: 67
diff changeset
696 return;
kono
parents: 67
diff changeset
697
kono
parents: 67
diff changeset
698 if (!single_pred_p (dest))
kono
parents: 67
diff changeset
699 return;
kono
parents: 67
diff changeset
700
kono
parents: 67
diff changeset
701 gcc_checking_assert (dest != src);
kono
parents: 67
diff changeset
702
kono
parents: 67
diff changeset
703 gimple_stmt_iterator gsi = gsi_after_labels (dest);
kono
parents: 67
diff changeset
704 int i = 0;
kono
parents: 67
diff changeset
705 const int alloc_count = 16; // ?? Should this be a PARAM?
kono
parents: 67
diff changeset
706
kono
parents: 67
diff changeset
707 /* Estimate the number of debug vars overridden in the beginning of
kono
parents: 67
diff changeset
708 DEST, to tell how many we're going to need to begin with. */
kono
parents: 67
diff changeset
709 for (gimple_stmt_iterator si = gsi;
kono
parents: 67
diff changeset
710 i * 4 <= alloc_count * 3 && !gsi_end_p (si); gsi_next (&si))
kono
parents: 67
diff changeset
711 {
kono
parents: 67
diff changeset
712 gimple *stmt = gsi_stmt (si);
kono
parents: 67
diff changeset
713 if (!is_gimple_debug (stmt))
kono
parents: 67
diff changeset
714 break;
kono
parents: 67
diff changeset
715 i++;
kono
parents: 67
diff changeset
716 }
kono
parents: 67
diff changeset
717
kono
parents: 67
diff changeset
718 auto_vec<tree, alloc_count> fewvars;
kono
parents: 67
diff changeset
719 hash_set<tree> *vars = NULL;
kono
parents: 67
diff changeset
720
kono
parents: 67
diff changeset
721 /* If we're already starting with 3/4 of alloc_count, go for a
kono
parents: 67
diff changeset
722 hash_set, otherwise start with an unordered stack-allocated
kono
parents: 67
diff changeset
723 VEC. */
kono
parents: 67
diff changeset
724 if (i * 4 > alloc_count * 3)
kono
parents: 67
diff changeset
725 vars = new hash_set<tree>;
kono
parents: 67
diff changeset
726
kono
parents: 67
diff changeset
727 /* Now go through the initial debug stmts in DEST again, this time
kono
parents: 67
diff changeset
728 actually inserting in VARS or FEWVARS. Don't bother checking for
kono
parents: 67
diff changeset
729 duplicates in FEWVARS. */
kono
parents: 67
diff changeset
730 for (gimple_stmt_iterator si = gsi; !gsi_end_p (si); gsi_next (&si))
kono
parents: 67
diff changeset
731 {
kono
parents: 67
diff changeset
732 gimple *stmt = gsi_stmt (si);
kono
parents: 67
diff changeset
733 if (!is_gimple_debug (stmt))
kono
parents: 67
diff changeset
734 break;
kono
parents: 67
diff changeset
735
kono
parents: 67
diff changeset
736 tree var;
kono
parents: 67
diff changeset
737
kono
parents: 67
diff changeset
738 if (gimple_debug_bind_p (stmt))
kono
parents: 67
diff changeset
739 var = gimple_debug_bind_get_var (stmt);
kono
parents: 67
diff changeset
740 else if (gimple_debug_source_bind_p (stmt))
kono
parents: 67
diff changeset
741 var = gimple_debug_source_bind_get_var (stmt);
kono
parents: 67
diff changeset
742 else
kono
parents: 67
diff changeset
743 gcc_unreachable ();
kono
parents: 67
diff changeset
744
kono
parents: 67
diff changeset
745 if (vars)
kono
parents: 67
diff changeset
746 vars->add (var);
kono
parents: 67
diff changeset
747 else
kono
parents: 67
diff changeset
748 fewvars.quick_push (var);
kono
parents: 67
diff changeset
749 }
kono
parents: 67
diff changeset
750
kono
parents: 67
diff changeset
751 basic_block bb = dest;
kono
parents: 67
diff changeset
752
kono
parents: 67
diff changeset
753 do
kono
parents: 67
diff changeset
754 {
kono
parents: 67
diff changeset
755 bb = single_pred (bb);
kono
parents: 67
diff changeset
756 for (gimple_stmt_iterator si = gsi_last_bb (bb);
kono
parents: 67
diff changeset
757 !gsi_end_p (si); gsi_prev (&si))
kono
parents: 67
diff changeset
758 {
kono
parents: 67
diff changeset
759 gimple *stmt = gsi_stmt (si);
kono
parents: 67
diff changeset
760 if (!is_gimple_debug (stmt))
kono
parents: 67
diff changeset
761 continue;
kono
parents: 67
diff changeset
762
kono
parents: 67
diff changeset
763 tree var;
kono
parents: 67
diff changeset
764
kono
parents: 67
diff changeset
765 if (gimple_debug_bind_p (stmt))
kono
parents: 67
diff changeset
766 var = gimple_debug_bind_get_var (stmt);
kono
parents: 67
diff changeset
767 else if (gimple_debug_source_bind_p (stmt))
kono
parents: 67
diff changeset
768 var = gimple_debug_source_bind_get_var (stmt);
kono
parents: 67
diff changeset
769 else
kono
parents: 67
diff changeset
770 gcc_unreachable ();
kono
parents: 67
diff changeset
771
kono
parents: 67
diff changeset
772 /* Discard debug bind overlaps. ??? Unlike stmts from src,
kono
parents: 67
diff changeset
773 copied into a new block that will precede BB, debug bind
kono
parents: 67
diff changeset
774 stmts in bypassed BBs may actually be discarded if
kono
parents: 67
diff changeset
775 they're overwritten by subsequent debug bind stmts, which
kono
parents: 67
diff changeset
776 might be a problem once we introduce stmt frontier notes
kono
parents: 67
diff changeset
777 or somesuch. Adding `&& bb == src' to the condition
kono
parents: 67
diff changeset
778 below will preserve all potentially relevant debug
kono
parents: 67
diff changeset
779 notes. */
kono
parents: 67
diff changeset
780 if (vars && vars->add (var))
kono
parents: 67
diff changeset
781 continue;
kono
parents: 67
diff changeset
782 else if (!vars)
kono
parents: 67
diff changeset
783 {
kono
parents: 67
diff changeset
784 int i = fewvars.length ();
kono
parents: 67
diff changeset
785 while (i--)
kono
parents: 67
diff changeset
786 if (fewvars[i] == var)
kono
parents: 67
diff changeset
787 break;
kono
parents: 67
diff changeset
788 if (i >= 0)
kono
parents: 67
diff changeset
789 continue;
kono
parents: 67
diff changeset
790
kono
parents: 67
diff changeset
791 if (fewvars.length () < (unsigned) alloc_count)
kono
parents: 67
diff changeset
792 fewvars.quick_push (var);
kono
parents: 67
diff changeset
793 else
kono
parents: 67
diff changeset
794 {
kono
parents: 67
diff changeset
795 vars = new hash_set<tree>;
kono
parents: 67
diff changeset
796 for (i = 0; i < alloc_count; i++)
kono
parents: 67
diff changeset
797 vars->add (fewvars[i]);
kono
parents: 67
diff changeset
798 fewvars.release ();
kono
parents: 67
diff changeset
799 vars->add (var);
kono
parents: 67
diff changeset
800 }
kono
parents: 67
diff changeset
801 }
kono
parents: 67
diff changeset
802
kono
parents: 67
diff changeset
803 stmt = gimple_copy (stmt);
kono
parents: 67
diff changeset
804 /* ??? Should we drop the location of the copy to denote
kono
parents: 67
diff changeset
805 they're artificial bindings? */
kono
parents: 67
diff changeset
806 gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
kono
parents: 67
diff changeset
807 }
kono
parents: 67
diff changeset
808 }
kono
parents: 67
diff changeset
809 while (bb != src && single_pred_p (bb));
kono
parents: 67
diff changeset
810
kono
parents: 67
diff changeset
811 if (vars)
kono
parents: 67
diff changeset
812 delete vars;
kono
parents: 67
diff changeset
813 else if (fewvars.exists ())
kono
parents: 67
diff changeset
814 fewvars.release ();
kono
parents: 67
diff changeset
815 }
kono
parents: 67
diff changeset
816
kono
parents: 67
diff changeset
817 /* See if TAKEN_EDGE->dest is a threadable block with no side effecs (ie, it
kono
parents: 67
diff changeset
818 need not be duplicated as part of the CFG/SSA updating process).
kono
parents: 67
diff changeset
819
kono
parents: 67
diff changeset
820 If it is threadable, add it to PATH and VISITED and recurse, ultimately
kono
parents: 67
diff changeset
821 returning TRUE from the toplevel call. Otherwise do nothing and
kono
parents: 67
diff changeset
822 return false.
kono
parents: 67
diff changeset
823
kono
parents: 67
diff changeset
824 DUMMY_COND, SIMPLIFY are used to try and simplify the condition at the
kono
parents: 67
diff changeset
825 end of TAKEN_EDGE->dest.
kono
parents: 67
diff changeset
826
kono
parents: 67
diff changeset
827 The available expression table is referenced via AVAIL_EXPRS_STACK. */
kono
parents: 67
diff changeset
828
kono
parents: 67
diff changeset
829 static bool
kono
parents: 67
diff changeset
830 thread_around_empty_blocks (edge taken_edge,
kono
parents: 67
diff changeset
831 gcond *dummy_cond,
kono
parents: 67
diff changeset
832 class avail_exprs_stack *avail_exprs_stack,
kono
parents: 67
diff changeset
833 pfn_simplify simplify,
kono
parents: 67
diff changeset
834 bitmap visited,
kono
parents: 67
diff changeset
835 vec<jump_thread_edge *> *path)
kono
parents: 67
diff changeset
836 {
kono
parents: 67
diff changeset
837 basic_block bb = taken_edge->dest;
kono
parents: 67
diff changeset
838 gimple_stmt_iterator gsi;
kono
parents: 67
diff changeset
839 gimple *stmt;
kono
parents: 67
diff changeset
840 tree cond;
kono
parents: 67
diff changeset
841
kono
parents: 67
diff changeset
842 /* The key property of these blocks is that they need not be duplicated
kono
parents: 67
diff changeset
843 when threading. Thus they can not have visible side effects such
kono
parents: 67
diff changeset
844 as PHI nodes. */
kono
parents: 67
diff changeset
845 if (!gsi_end_p (gsi_start_phis (bb)))
kono
parents: 67
diff changeset
846 return false;
kono
parents: 67
diff changeset
847
kono
parents: 67
diff changeset
848 /* Skip over DEBUG statements at the start of the block. */
kono
parents: 67
diff changeset
849 gsi = gsi_start_nondebug_bb (bb);
kono
parents: 67
diff changeset
850
kono
parents: 67
diff changeset
851 /* If the block has no statements, but does have a single successor, then
kono
parents: 67
diff changeset
852 it's just a forwarding block and we can thread through it trivially.
kono
parents: 67
diff changeset
853
kono
parents: 67
diff changeset
854 However, note that just threading through empty blocks with single
kono
parents: 67
diff changeset
855 successors is not inherently profitable. For the jump thread to
kono
parents: 67
diff changeset
856 be profitable, we must avoid a runtime conditional.
kono
parents: 67
diff changeset
857
kono
parents: 67
diff changeset
858 By taking the return value from the recursive call, we get the
kono
parents: 67
diff changeset
859 desired effect of returning TRUE when we found a profitable jump
kono
parents: 67
diff changeset
860 threading opportunity and FALSE otherwise.
kono
parents: 67
diff changeset
861
kono
parents: 67
diff changeset
862 This is particularly important when this routine is called after
kono
parents: 67
diff changeset
863 processing a joiner block. Returning TRUE too aggressively in
kono
parents: 67
diff changeset
864 that case results in pointless duplication of the joiner block. */
kono
parents: 67
diff changeset
865 if (gsi_end_p (gsi))
kono
parents: 67
diff changeset
866 {
kono
parents: 67
diff changeset
867 if (single_succ_p (bb))
kono
parents: 67
diff changeset
868 {
kono
parents: 67
diff changeset
869 taken_edge = single_succ_edge (bb);
kono
parents: 67
diff changeset
870
kono
parents: 67
diff changeset
871 if ((taken_edge->flags & EDGE_DFS_BACK) != 0)
kono
parents: 67
diff changeset
872 return false;
kono
parents: 67
diff changeset
873
kono
parents: 67
diff changeset
874 if (!bitmap_bit_p (visited, taken_edge->dest->index))
kono
parents: 67
diff changeset
875 {
kono
parents: 67
diff changeset
876 jump_thread_edge *x
kono
parents: 67
diff changeset
877 = new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
kono
parents: 67
diff changeset
878 path->safe_push (x);
kono
parents: 67
diff changeset
879 bitmap_set_bit (visited, taken_edge->dest->index);
kono
parents: 67
diff changeset
880 return thread_around_empty_blocks (taken_edge,
kono
parents: 67
diff changeset
881 dummy_cond,
kono
parents: 67
diff changeset
882 avail_exprs_stack,
kono
parents: 67
diff changeset
883 simplify,
kono
parents: 67
diff changeset
884 visited,
kono
parents: 67
diff changeset
885 path);
kono
parents: 67
diff changeset
886 }
kono
parents: 67
diff changeset
887 }
kono
parents: 67
diff changeset
888
kono
parents: 67
diff changeset
889 /* We have a block with no statements, but multiple successors? */
kono
parents: 67
diff changeset
890 return false;
kono
parents: 67
diff changeset
891 }
kono
parents: 67
diff changeset
892
kono
parents: 67
diff changeset
893 /* The only real statements this block can have are a control
kono
parents: 67
diff changeset
894 flow altering statement. Anything else stops the thread. */
kono
parents: 67
diff changeset
895 stmt = gsi_stmt (gsi);
kono
parents: 67
diff changeset
896 if (gimple_code (stmt) != GIMPLE_COND
kono
parents: 67
diff changeset
897 && gimple_code (stmt) != GIMPLE_GOTO
kono
parents: 67
diff changeset
898 && gimple_code (stmt) != GIMPLE_SWITCH)
kono
parents: 67
diff changeset
899 return false;
kono
parents: 67
diff changeset
900
kono
parents: 67
diff changeset
901 /* Extract and simplify the condition. */
kono
parents: 67
diff changeset
902 cond = simplify_control_stmt_condition (taken_edge, stmt,
kono
parents: 67
diff changeset
903 avail_exprs_stack, dummy_cond,
kono
parents: 67
diff changeset
904 simplify);
kono
parents: 67
diff changeset
905
kono
parents: 67
diff changeset
906 /* If the condition can be statically computed and we have not already
kono
parents: 67
diff changeset
907 visited the destination edge, then add the taken edge to our thread
kono
parents: 67
diff changeset
908 path. */
kono
parents: 67
diff changeset
909 if (cond != NULL_TREE
kono
parents: 67
diff changeset
910 && (is_gimple_min_invariant (cond)
kono
parents: 67
diff changeset
911 || TREE_CODE (cond) == CASE_LABEL_EXPR))
kono
parents: 67
diff changeset
912 {
kono
parents: 67
diff changeset
913 if (TREE_CODE (cond) == CASE_LABEL_EXPR)
kono
parents: 67
diff changeset
914 taken_edge = find_edge (bb, label_to_block (CASE_LABEL (cond)));
kono
parents: 67
diff changeset
915 else
kono
parents: 67
diff changeset
916 taken_edge = find_taken_edge (bb, cond);
kono
parents: 67
diff changeset
917
kono
parents: 67
diff changeset
918 if ((taken_edge->flags & EDGE_DFS_BACK) != 0)
kono
parents: 67
diff changeset
919 return false;
kono
parents: 67
diff changeset
920
kono
parents: 67
diff changeset
921 if (bitmap_bit_p (visited, taken_edge->dest->index))
kono
parents: 67
diff changeset
922 return false;
kono
parents: 67
diff changeset
923 bitmap_set_bit (visited, taken_edge->dest->index);
kono
parents: 67
diff changeset
924
kono
parents: 67
diff changeset
925 jump_thread_edge *x
kono
parents: 67
diff changeset
926 = new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
kono
parents: 67
diff changeset
927 path->safe_push (x);
kono
parents: 67
diff changeset
928
kono
parents: 67
diff changeset
929 thread_around_empty_blocks (taken_edge,
kono
parents: 67
diff changeset
930 dummy_cond,
kono
parents: 67
diff changeset
931 avail_exprs_stack,
kono
parents: 67
diff changeset
932 simplify,
kono
parents: 67
diff changeset
933 visited,
kono
parents: 67
diff changeset
934 path);
kono
parents: 67
diff changeset
935 return true;
kono
parents: 67
diff changeset
936 }
kono
parents: 67
diff changeset
937
kono
parents: 67
diff changeset
938 return false;
kono
parents: 67
diff changeset
939 }
kono
parents: 67
diff changeset
940
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
941 /* We are exiting E->src, see if E->dest ends with a conditional
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
942 jump which has a known value when reached via E.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
943
111
kono
parents: 67
diff changeset
944 E->dest can have arbitrary side effects which, if threading is
kono
parents: 67
diff changeset
945 successful, will be maintained.
kono
parents: 67
diff changeset
946
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
947 Special care is necessary if E is a back edge in the CFG as we
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
948 may have already recorded equivalences for E->dest into our
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
949 various tables, including the result of the conditional at
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
950 the end of E->dest. Threading opportunities are severely
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
951 limited in that case to avoid short-circuiting the loop
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
952 incorrectly.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
953
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
954 DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
955 to avoid allocating memory.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
956
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
957 STACK is used to undo temporary equivalences created during the walk of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
958 E->dest.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
959
111
kono
parents: 67
diff changeset
960 SIMPLIFY is a pass-specific function used to simplify statements.
kono
parents: 67
diff changeset
961
kono
parents: 67
diff changeset
962 Our caller is responsible for restoring the state of the expression
kono
parents: 67
diff changeset
963 and const_and_copies stacks.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
964
111
kono
parents: 67
diff changeset
965 Positive return value is success. Zero return value is failure, but
kono
parents: 67
diff changeset
966 the block can still be duplicated as a joiner in a jump thread path,
kono
parents: 67
diff changeset
967 negative indicates the block should not be duplicated and thus is not
kono
parents: 67
diff changeset
968 suitable for a joiner in a jump threading path. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
969
111
kono
parents: 67
diff changeset
970 static int
kono
parents: 67
diff changeset
971 thread_through_normal_block (edge e,
kono
parents: 67
diff changeset
972 gcond *dummy_cond,
kono
parents: 67
diff changeset
973 const_and_copies *const_and_copies,
kono
parents: 67
diff changeset
974 avail_exprs_stack *avail_exprs_stack,
kono
parents: 67
diff changeset
975 pfn_simplify simplify,
kono
parents: 67
diff changeset
976 vec<jump_thread_edge *> *path,
kono
parents: 67
diff changeset
977 bitmap visited)
kono
parents: 67
diff changeset
978 {
kono
parents: 67
diff changeset
979 /* We want to record any equivalences created by traversing E. */
kono
parents: 67
diff changeset
980 record_temporary_equivalences (e, const_and_copies, avail_exprs_stack);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
981
111
kono
parents: 67
diff changeset
982 /* PHIs create temporary equivalences.
kono
parents: 67
diff changeset
983 Note that if we found a PHI that made the block non-threadable, then
kono
parents: 67
diff changeset
984 we need to bubble that up to our caller in the same manner we do
kono
parents: 67
diff changeset
985 when we prematurely stop processing statements below. */
kono
parents: 67
diff changeset
986 if (!record_temporary_equivalences_from_phis (e, const_and_copies))
kono
parents: 67
diff changeset
987 return -1;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
988
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
989 /* Now walk each statement recording any context sensitive
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
990 temporary equivalences we can detect. */
111
kono
parents: 67
diff changeset
991 gimple *stmt
kono
parents: 67
diff changeset
992 = record_temporary_equivalences_from_stmts_at_dest (e, const_and_copies,
kono
parents: 67
diff changeset
993 avail_exprs_stack,
kono
parents: 67
diff changeset
994 simplify);
kono
parents: 67
diff changeset
995
kono
parents: 67
diff changeset
996 /* There's two reasons STMT might be null, and distinguishing
kono
parents: 67
diff changeset
997 between them is important.
kono
parents: 67
diff changeset
998
kono
parents: 67
diff changeset
999 First the block may not have had any statements. For example, it
kono
parents: 67
diff changeset
1000 might have some PHIs and unconditionally transfer control elsewhere.
kono
parents: 67
diff changeset
1001 Such blocks are suitable for jump threading, particularly as a
kono
parents: 67
diff changeset
1002 joiner block.
kono
parents: 67
diff changeset
1003
kono
parents: 67
diff changeset
1004 The second reason would be if we did not process all the statements
kono
parents: 67
diff changeset
1005 in the block (because there were too many to make duplicating the
kono
parents: 67
diff changeset
1006 block profitable. If we did not look at all the statements, then
kono
parents: 67
diff changeset
1007 we may not have invalidated everything needing invalidation. Thus
kono
parents: 67
diff changeset
1008 we must signal to our caller that this block is not suitable for
kono
parents: 67
diff changeset
1009 use as a joiner in a threading path. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1010 if (!stmt)
111
kono
parents: 67
diff changeset
1011 {
kono
parents: 67
diff changeset
1012 /* First case. The statement simply doesn't have any instructions, but
kono
parents: 67
diff changeset
1013 does have PHIs. */
kono
parents: 67
diff changeset
1014 if (gsi_end_p (gsi_start_nondebug_bb (e->dest))
kono
parents: 67
diff changeset
1015 && !gsi_end_p (gsi_start_phis (e->dest)))
kono
parents: 67
diff changeset
1016 return 0;
kono
parents: 67
diff changeset
1017
kono
parents: 67
diff changeset
1018 /* Second case. */
kono
parents: 67
diff changeset
1019 return -1;
kono
parents: 67
diff changeset
1020 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1021
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1022 /* If we stopped at a COND_EXPR or SWITCH_EXPR, see if we know which arm
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1023 will be taken. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1024 if (gimple_code (stmt) == GIMPLE_COND
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1025 || gimple_code (stmt) == GIMPLE_GOTO
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1026 || gimple_code (stmt) == GIMPLE_SWITCH)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1027 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1028 tree cond;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1029
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1030 /* Extract and simplify the condition. */
111
kono
parents: 67
diff changeset
1031 cond = simplify_control_stmt_condition (e, stmt, avail_exprs_stack,
kono
parents: 67
diff changeset
1032 dummy_cond, simplify);
kono
parents: 67
diff changeset
1033
kono
parents: 67
diff changeset
1034 if (!cond)
kono
parents: 67
diff changeset
1035 return 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1036
111
kono
parents: 67
diff changeset
1037 if (is_gimple_min_invariant (cond)
kono
parents: 67
diff changeset
1038 || TREE_CODE (cond) == CASE_LABEL_EXPR)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1039 {
111
kono
parents: 67
diff changeset
1040 edge taken_edge;
kono
parents: 67
diff changeset
1041 if (TREE_CODE (cond) == CASE_LABEL_EXPR)
kono
parents: 67
diff changeset
1042 taken_edge = find_edge (e->dest,
kono
parents: 67
diff changeset
1043 label_to_block (CASE_LABEL (cond)));
kono
parents: 67
diff changeset
1044 else
kono
parents: 67
diff changeset
1045 taken_edge = find_taken_edge (e->dest, cond);
kono
parents: 67
diff changeset
1046
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1047 basic_block dest = (taken_edge ? taken_edge->dest : NULL);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1048
111
kono
parents: 67
diff changeset
1049 /* DEST could be NULL for a computed jump to an absolute
kono
parents: 67
diff changeset
1050 address. */
kono
parents: 67
diff changeset
1051 if (dest == NULL
kono
parents: 67
diff changeset
1052 || dest == e->dest
kono
parents: 67
diff changeset
1053 || (taken_edge->flags & EDGE_DFS_BACK) != 0
kono
parents: 67
diff changeset
1054 || bitmap_bit_p (visited, dest->index))
kono
parents: 67
diff changeset
1055 return 0;
kono
parents: 67
diff changeset
1056
kono
parents: 67
diff changeset
1057 /* Only push the EDGE_START_JUMP_THREAD marker if this is
kono
parents: 67
diff changeset
1058 first edge on the path. */
kono
parents: 67
diff changeset
1059 if (path->length () == 0)
kono
parents: 67
diff changeset
1060 {
kono
parents: 67
diff changeset
1061 jump_thread_edge *x
kono
parents: 67
diff changeset
1062 = new jump_thread_edge (e, EDGE_START_JUMP_THREAD);
kono
parents: 67
diff changeset
1063 path->safe_push (x);
kono
parents: 67
diff changeset
1064 }
kono
parents: 67
diff changeset
1065
kono
parents: 67
diff changeset
1066 jump_thread_edge *x
kono
parents: 67
diff changeset
1067 = new jump_thread_edge (taken_edge, EDGE_COPY_SRC_BLOCK);
kono
parents: 67
diff changeset
1068 path->safe_push (x);
kono
parents: 67
diff changeset
1069
kono
parents: 67
diff changeset
1070 /* See if we can thread through DEST as well, this helps capture
kono
parents: 67
diff changeset
1071 secondary effects of threading without having to re-run DOM or
kono
parents: 67
diff changeset
1072 VRP.
kono
parents: 67
diff changeset
1073
kono
parents: 67
diff changeset
1074 We don't want to thread back to a block we have already
kono
parents: 67
diff changeset
1075 visited. This may be overly conservative. */
kono
parents: 67
diff changeset
1076 bitmap_set_bit (visited, dest->index);
kono
parents: 67
diff changeset
1077 bitmap_set_bit (visited, e->dest->index);
kono
parents: 67
diff changeset
1078 thread_around_empty_blocks (taken_edge,
kono
parents: 67
diff changeset
1079 dummy_cond,
kono
parents: 67
diff changeset
1080 avail_exprs_stack,
kono
parents: 67
diff changeset
1081 simplify,
kono
parents: 67
diff changeset
1082 visited,
kono
parents: 67
diff changeset
1083 path);
kono
parents: 67
diff changeset
1084 return 1;
kono
parents: 67
diff changeset
1085 }
kono
parents: 67
diff changeset
1086 }
kono
parents: 67
diff changeset
1087 return 0;
kono
parents: 67
diff changeset
1088 }
kono
parents: 67
diff changeset
1089
kono
parents: 67
diff changeset
1090 /* We are exiting E->src, see if E->dest ends with a conditional
kono
parents: 67
diff changeset
1091 jump which has a known value when reached via E.
kono
parents: 67
diff changeset
1092
kono
parents: 67
diff changeset
1093 DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
kono
parents: 67
diff changeset
1094 to avoid allocating memory.
kono
parents: 67
diff changeset
1095
kono
parents: 67
diff changeset
1096 CONST_AND_COPIES is used to undo temporary equivalences created during the
kono
parents: 67
diff changeset
1097 walk of E->dest.
kono
parents: 67
diff changeset
1098
kono
parents: 67
diff changeset
1099 The available expression table is referenced vai AVAIL_EXPRS_STACK.
kono
parents: 67
diff changeset
1100
kono
parents: 67
diff changeset
1101 SIMPLIFY is a pass-specific function used to simplify statements. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1102
111
kono
parents: 67
diff changeset
1103 static void
kono
parents: 67
diff changeset
1104 thread_across_edge (gcond *dummy_cond,
kono
parents: 67
diff changeset
1105 edge e,
kono
parents: 67
diff changeset
1106 class const_and_copies *const_and_copies,
kono
parents: 67
diff changeset
1107 class avail_exprs_stack *avail_exprs_stack,
kono
parents: 67
diff changeset
1108 pfn_simplify simplify)
kono
parents: 67
diff changeset
1109 {
kono
parents: 67
diff changeset
1110 bitmap visited = BITMAP_ALLOC (NULL);
kono
parents: 67
diff changeset
1111
kono
parents: 67
diff changeset
1112 const_and_copies->push_marker ();
kono
parents: 67
diff changeset
1113 avail_exprs_stack->push_marker ();
kono
parents: 67
diff changeset
1114
kono
parents: 67
diff changeset
1115 stmt_count = 0;
kono
parents: 67
diff changeset
1116
kono
parents: 67
diff changeset
1117 vec<jump_thread_edge *> *path = new vec<jump_thread_edge *> ();
kono
parents: 67
diff changeset
1118 bitmap_clear (visited);
kono
parents: 67
diff changeset
1119 bitmap_set_bit (visited, e->src->index);
kono
parents: 67
diff changeset
1120 bitmap_set_bit (visited, e->dest->index);
kono
parents: 67
diff changeset
1121
kono
parents: 67
diff changeset
1122 int threaded;
kono
parents: 67
diff changeset
1123 if ((e->flags & EDGE_DFS_BACK) == 0)
kono
parents: 67
diff changeset
1124 threaded = thread_through_normal_block (e, dummy_cond,
kono
parents: 67
diff changeset
1125 const_and_copies,
kono
parents: 67
diff changeset
1126 avail_exprs_stack,
kono
parents: 67
diff changeset
1127 simplify, path,
kono
parents: 67
diff changeset
1128 visited);
kono
parents: 67
diff changeset
1129 else
kono
parents: 67
diff changeset
1130 threaded = 0;
kono
parents: 67
diff changeset
1131
kono
parents: 67
diff changeset
1132 if (threaded > 0)
kono
parents: 67
diff changeset
1133 {
kono
parents: 67
diff changeset
1134 propagate_threaded_block_debug_into (path->last ()->e->dest,
kono
parents: 67
diff changeset
1135 e->dest);
kono
parents: 67
diff changeset
1136 const_and_copies->pop_to_marker ();
kono
parents: 67
diff changeset
1137 avail_exprs_stack->pop_to_marker ();
kono
parents: 67
diff changeset
1138 BITMAP_FREE (visited);
kono
parents: 67
diff changeset
1139 register_jump_thread (path);
kono
parents: 67
diff changeset
1140 return;
kono
parents: 67
diff changeset
1141 }
kono
parents: 67
diff changeset
1142 else
kono
parents: 67
diff changeset
1143 {
kono
parents: 67
diff changeset
1144 /* Negative and zero return values indicate no threading was possible,
kono
parents: 67
diff changeset
1145 thus there should be no edges on the thread path and no need to walk
kono
parents: 67
diff changeset
1146 through the vector entries. */
kono
parents: 67
diff changeset
1147 gcc_assert (path->length () == 0);
kono
parents: 67
diff changeset
1148 path->release ();
kono
parents: 67
diff changeset
1149 delete path;
kono
parents: 67
diff changeset
1150
kono
parents: 67
diff changeset
1151 /* A negative status indicates the target block was deemed too big to
kono
parents: 67
diff changeset
1152 duplicate. Just quit now rather than trying to use the block as
kono
parents: 67
diff changeset
1153 a joiner in a jump threading path.
kono
parents: 67
diff changeset
1154
kono
parents: 67
diff changeset
1155 This prevents unnecessary code growth, but more importantly if we
kono
parents: 67
diff changeset
1156 do not look at all the statements in the block, then we may have
kono
parents: 67
diff changeset
1157 missed some invalidations if we had traversed a backedge! */
kono
parents: 67
diff changeset
1158 if (threaded < 0)
kono
parents: 67
diff changeset
1159 {
kono
parents: 67
diff changeset
1160 BITMAP_FREE (visited);
kono
parents: 67
diff changeset
1161 const_and_copies->pop_to_marker ();
kono
parents: 67
diff changeset
1162 avail_exprs_stack->pop_to_marker ();
kono
parents: 67
diff changeset
1163 return;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1164 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1165 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1166
111
kono
parents: 67
diff changeset
1167 /* We were unable to determine what out edge from E->dest is taken. However,
kono
parents: 67
diff changeset
1168 we might still be able to thread through successors of E->dest. This
kono
parents: 67
diff changeset
1169 often occurs when E->dest is a joiner block which then fans back out
kono
parents: 67
diff changeset
1170 based on redundant tests.
kono
parents: 67
diff changeset
1171
kono
parents: 67
diff changeset
1172 If so, we'll copy E->dest and redirect the appropriate predecessor to
kono
parents: 67
diff changeset
1173 the copy. Within the copy of E->dest, we'll thread one or more edges
kono
parents: 67
diff changeset
1174 to points deeper in the CFG.
kono
parents: 67
diff changeset
1175
kono
parents: 67
diff changeset
1176 This is a stopgap until we have a more structured approach to path
kono
parents: 67
diff changeset
1177 isolation. */
kono
parents: 67
diff changeset
1178 {
kono
parents: 67
diff changeset
1179 edge taken_edge;
kono
parents: 67
diff changeset
1180 edge_iterator ei;
kono
parents: 67
diff changeset
1181 bool found;
kono
parents: 67
diff changeset
1182
kono
parents: 67
diff changeset
1183 /* If E->dest has abnormal outgoing edges, then there's no guarantee
kono
parents: 67
diff changeset
1184 we can safely redirect any of the edges. Just punt those cases. */
kono
parents: 67
diff changeset
1185 FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
kono
parents: 67
diff changeset
1186 if (taken_edge->flags & EDGE_ABNORMAL)
kono
parents: 67
diff changeset
1187 {
kono
parents: 67
diff changeset
1188 const_and_copies->pop_to_marker ();
kono
parents: 67
diff changeset
1189 avail_exprs_stack->pop_to_marker ();
kono
parents: 67
diff changeset
1190 BITMAP_FREE (visited);
kono
parents: 67
diff changeset
1191 return;
kono
parents: 67
diff changeset
1192 }
kono
parents: 67
diff changeset
1193
kono
parents: 67
diff changeset
1194 /* Look at each successor of E->dest to see if we can thread through it. */
kono
parents: 67
diff changeset
1195 FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
kono
parents: 67
diff changeset
1196 {
kono
parents: 67
diff changeset
1197 if ((e->flags & EDGE_DFS_BACK) != 0
kono
parents: 67
diff changeset
1198 || (taken_edge->flags & EDGE_DFS_BACK) != 0)
kono
parents: 67
diff changeset
1199 continue;
kono
parents: 67
diff changeset
1200
kono
parents: 67
diff changeset
1201 /* Push a fresh marker so we can unwind the equivalences created
kono
parents: 67
diff changeset
1202 for each of E->dest's successors. */
kono
parents: 67
diff changeset
1203 const_and_copies->push_marker ();
kono
parents: 67
diff changeset
1204 avail_exprs_stack->push_marker ();
kono
parents: 67
diff changeset
1205
kono
parents: 67
diff changeset
1206 /* Avoid threading to any block we have already visited. */
kono
parents: 67
diff changeset
1207 bitmap_clear (visited);
kono
parents: 67
diff changeset
1208 bitmap_set_bit (visited, e->src->index);
kono
parents: 67
diff changeset
1209 bitmap_set_bit (visited, e->dest->index);
kono
parents: 67
diff changeset
1210 bitmap_set_bit (visited, taken_edge->dest->index);
kono
parents: 67
diff changeset
1211 vec<jump_thread_edge *> *path = new vec<jump_thread_edge *> ();
kono
parents: 67
diff changeset
1212
kono
parents: 67
diff changeset
1213 /* Record whether or not we were able to thread through a successor
kono
parents: 67
diff changeset
1214 of E->dest. */
kono
parents: 67
diff changeset
1215 jump_thread_edge *x = new jump_thread_edge (e, EDGE_START_JUMP_THREAD);
kono
parents: 67
diff changeset
1216 path->safe_push (x);
kono
parents: 67
diff changeset
1217
kono
parents: 67
diff changeset
1218 x = new jump_thread_edge (taken_edge, EDGE_COPY_SRC_JOINER_BLOCK);
kono
parents: 67
diff changeset
1219 path->safe_push (x);
kono
parents: 67
diff changeset
1220 found = false;
kono
parents: 67
diff changeset
1221 found = thread_around_empty_blocks (taken_edge,
kono
parents: 67
diff changeset
1222 dummy_cond,
kono
parents: 67
diff changeset
1223 avail_exprs_stack,
kono
parents: 67
diff changeset
1224 simplify,
kono
parents: 67
diff changeset
1225 visited,
kono
parents: 67
diff changeset
1226 path);
kono
parents: 67
diff changeset
1227
kono
parents: 67
diff changeset
1228 if (!found)
kono
parents: 67
diff changeset
1229 found = thread_through_normal_block (path->last ()->e, dummy_cond,
kono
parents: 67
diff changeset
1230 const_and_copies,
kono
parents: 67
diff changeset
1231 avail_exprs_stack,
kono
parents: 67
diff changeset
1232 simplify, path,
kono
parents: 67
diff changeset
1233 visited) > 0;
kono
parents: 67
diff changeset
1234
kono
parents: 67
diff changeset
1235 /* If we were able to thread through a successor of E->dest, then
kono
parents: 67
diff changeset
1236 record the jump threading opportunity. */
kono
parents: 67
diff changeset
1237 if (found)
kono
parents: 67
diff changeset
1238 {
kono
parents: 67
diff changeset
1239 propagate_threaded_block_debug_into (path->last ()->e->dest,
kono
parents: 67
diff changeset
1240 taken_edge->dest);
kono
parents: 67
diff changeset
1241 register_jump_thread (path);
kono
parents: 67
diff changeset
1242 }
kono
parents: 67
diff changeset
1243 else
kono
parents: 67
diff changeset
1244 delete_jump_thread_path (path);
kono
parents: 67
diff changeset
1245
kono
parents: 67
diff changeset
1246 /* And unwind the equivalence table. */
kono
parents: 67
diff changeset
1247 avail_exprs_stack->pop_to_marker ();
kono
parents: 67
diff changeset
1248 const_and_copies->pop_to_marker ();
kono
parents: 67
diff changeset
1249 }
kono
parents: 67
diff changeset
1250 BITMAP_FREE (visited);
kono
parents: 67
diff changeset
1251 }
kono
parents: 67
diff changeset
1252
kono
parents: 67
diff changeset
1253 const_and_copies->pop_to_marker ();
kono
parents: 67
diff changeset
1254 avail_exprs_stack->pop_to_marker ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1255 }
111
kono
parents: 67
diff changeset
1256
kono
parents: 67
diff changeset
1257 /* Examine the outgoing edges from BB and conditionally
kono
parents: 67
diff changeset
1258 try to thread them.
kono
parents: 67
diff changeset
1259
kono
parents: 67
diff changeset
1260 DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
kono
parents: 67
diff changeset
1261 to avoid allocating memory.
kono
parents: 67
diff changeset
1262
kono
parents: 67
diff changeset
1263 CONST_AND_COPIES is used to undo temporary equivalences created during the
kono
parents: 67
diff changeset
1264 walk of E->dest.
kono
parents: 67
diff changeset
1265
kono
parents: 67
diff changeset
1266 The available expression table is referenced vai AVAIL_EXPRS_STACK.
kono
parents: 67
diff changeset
1267
kono
parents: 67
diff changeset
1268 SIMPLIFY is a pass-specific function used to simplify statements. */
kono
parents: 67
diff changeset
1269
kono
parents: 67
diff changeset
1270 void
kono
parents: 67
diff changeset
1271 thread_outgoing_edges (basic_block bb, gcond *dummy_cond,
kono
parents: 67
diff changeset
1272 class const_and_copies *const_and_copies,
kono
parents: 67
diff changeset
1273 class avail_exprs_stack *avail_exprs_stack,
kono
parents: 67
diff changeset
1274 tree (*simplify) (gimple *, gimple *,
kono
parents: 67
diff changeset
1275 class avail_exprs_stack *,
kono
parents: 67
diff changeset
1276 basic_block))
kono
parents: 67
diff changeset
1277 {
kono
parents: 67
diff changeset
1278 int flags = (EDGE_IGNORE | EDGE_COMPLEX | EDGE_ABNORMAL);
kono
parents: 67
diff changeset
1279 gimple *last;
kono
parents: 67
diff changeset
1280
kono
parents: 67
diff changeset
1281 /* If we have an outgoing edge to a block with multiple incoming and
kono
parents: 67
diff changeset
1282 outgoing edges, then we may be able to thread the edge, i.e., we
kono
parents: 67
diff changeset
1283 may be able to statically determine which of the outgoing edges
kono
parents: 67
diff changeset
1284 will be traversed when the incoming edge from BB is traversed. */
kono
parents: 67
diff changeset
1285 if (single_succ_p (bb)
kono
parents: 67
diff changeset
1286 && (single_succ_edge (bb)->flags & flags) == 0
kono
parents: 67
diff changeset
1287 && potentially_threadable_block (single_succ (bb)))
kono
parents: 67
diff changeset
1288 {
kono
parents: 67
diff changeset
1289 thread_across_edge (dummy_cond, single_succ_edge (bb),
kono
parents: 67
diff changeset
1290 const_and_copies, avail_exprs_stack,
kono
parents: 67
diff changeset
1291 simplify);
kono
parents: 67
diff changeset
1292 }
kono
parents: 67
diff changeset
1293 else if ((last = last_stmt (bb))
kono
parents: 67
diff changeset
1294 && gimple_code (last) == GIMPLE_COND
kono
parents: 67
diff changeset
1295 && EDGE_COUNT (bb->succs) == 2
kono
parents: 67
diff changeset
1296 && (EDGE_SUCC (bb, 0)->flags & flags) == 0
kono
parents: 67
diff changeset
1297 && (EDGE_SUCC (bb, 1)->flags & flags) == 0)
kono
parents: 67
diff changeset
1298 {
kono
parents: 67
diff changeset
1299 edge true_edge, false_edge;
kono
parents: 67
diff changeset
1300
kono
parents: 67
diff changeset
1301 extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
kono
parents: 67
diff changeset
1302
kono
parents: 67
diff changeset
1303 /* Only try to thread the edge if it reaches a target block with
kono
parents: 67
diff changeset
1304 more than one predecessor and more than one successor. */
kono
parents: 67
diff changeset
1305 if (potentially_threadable_block (true_edge->dest))
kono
parents: 67
diff changeset
1306 thread_across_edge (dummy_cond, true_edge,
kono
parents: 67
diff changeset
1307 const_and_copies, avail_exprs_stack, simplify);
kono
parents: 67
diff changeset
1308
kono
parents: 67
diff changeset
1309 /* Similarly for the ELSE arm. */
kono
parents: 67
diff changeset
1310 if (potentially_threadable_block (false_edge->dest))
kono
parents: 67
diff changeset
1311 thread_across_edge (dummy_cond, false_edge,
kono
parents: 67
diff changeset
1312 const_and_copies, avail_exprs_stack, simplify);
kono
parents: 67
diff changeset
1313 }
kono
parents: 67
diff changeset
1314 }