annotate gcc/tree-ssa-scopedtables.c @ 132:d34655255c78

update gcc-8.2
author mir3636
date Thu, 25 Oct 2018 10:21:07 +0900
parents 84e7813d76e9
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Header file for SSA dominator optimizations.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 Copyright (C) 2013-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of GCC.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
9 version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
14 for more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 #include "config.h"
kono
parents:
diff changeset
21 #include "system.h"
kono
parents:
diff changeset
22 #include "coretypes.h"
kono
parents:
diff changeset
23 #include "function.h"
kono
parents:
diff changeset
24 #include "basic-block.h"
kono
parents:
diff changeset
25 #include "tree.h"
kono
parents:
diff changeset
26 #include "gimple.h"
kono
parents:
diff changeset
27 #include "tree-pass.h"
kono
parents:
diff changeset
28 #include "tree-pretty-print.h"
kono
parents:
diff changeset
29 #include "tree-ssa-scopedtables.h"
kono
parents:
diff changeset
30 #include "tree-ssa-threadedge.h"
kono
parents:
diff changeset
31 #include "stor-layout.h"
kono
parents:
diff changeset
32 #include "fold-const.h"
kono
parents:
diff changeset
33 #include "tree-eh.h"
kono
parents:
diff changeset
34 #include "internal-fn.h"
kono
parents:
diff changeset
35 #include "tree-dfa.h"
kono
parents:
diff changeset
36 #include "options.h"
kono
parents:
diff changeset
37 #include "params.h"
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 static bool hashable_expr_equal_p (const struct hashable_expr *,
kono
parents:
diff changeset
40 const struct hashable_expr *);
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 /* Initialize local stacks for this optimizer and record equivalences
kono
parents:
diff changeset
43 upon entry to BB. Equivalences can come from the edge traversed to
kono
parents:
diff changeset
44 reach BB or they may come from PHI nodes at the start of BB. */
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 /* Pop items off the unwinding stack, removing each from the hash table
kono
parents:
diff changeset
47 until a marker is encountered. */
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 void
kono
parents:
diff changeset
50 avail_exprs_stack::pop_to_marker ()
kono
parents:
diff changeset
51 {
kono
parents:
diff changeset
52 /* Remove all the expressions made available in this block. */
kono
parents:
diff changeset
53 while (m_stack.length () > 0)
kono
parents:
diff changeset
54 {
kono
parents:
diff changeset
55 std::pair<expr_hash_elt_t, expr_hash_elt_t> victim = m_stack.pop ();
kono
parents:
diff changeset
56 expr_hash_elt **slot;
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 if (victim.first == NULL)
kono
parents:
diff changeset
59 break;
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 /* This must precede the actual removal from the hash table,
kono
parents:
diff changeset
62 as ELEMENT and the table entry may share a call argument
kono
parents:
diff changeset
63 vector which will be freed during removal. */
kono
parents:
diff changeset
64 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
65 {
kono
parents:
diff changeset
66 fprintf (dump_file, "<<<< ");
kono
parents:
diff changeset
67 victim.first->print (dump_file);
kono
parents:
diff changeset
68 }
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 slot = m_avail_exprs->find_slot (victim.first, NO_INSERT);
kono
parents:
diff changeset
71 gcc_assert (slot && *slot == victim.first);
kono
parents:
diff changeset
72 if (victim.second != NULL)
kono
parents:
diff changeset
73 {
kono
parents:
diff changeset
74 delete *slot;
kono
parents:
diff changeset
75 *slot = victim.second;
kono
parents:
diff changeset
76 }
kono
parents:
diff changeset
77 else
kono
parents:
diff changeset
78 m_avail_exprs->clear_slot (slot);
kono
parents:
diff changeset
79 }
kono
parents:
diff changeset
80 }
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 /* Add <ELT1,ELT2> to the unwinding stack so they can be later removed
kono
parents:
diff changeset
83 from the hash table. */
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 void
kono
parents:
diff changeset
86 avail_exprs_stack::record_expr (class expr_hash_elt *elt1,
kono
parents:
diff changeset
87 class expr_hash_elt *elt2,
kono
parents:
diff changeset
88 char type)
kono
parents:
diff changeset
89 {
kono
parents:
diff changeset
90 if (elt1 && dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
91 {
kono
parents:
diff changeset
92 fprintf (dump_file, "%c>>> ", type);
kono
parents:
diff changeset
93 elt1->print (dump_file);
kono
parents:
diff changeset
94 }
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96 m_stack.safe_push (std::pair<expr_hash_elt_t, expr_hash_elt_t> (elt1, elt2));
kono
parents:
diff changeset
97 }
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 /* Helper for walk_non_aliased_vuses. Determine if we arrived at
kono
parents:
diff changeset
100 the desired memory state. */
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 static void *
kono
parents:
diff changeset
103 vuse_eq (ao_ref *, tree vuse1, unsigned int cnt, void *data)
kono
parents:
diff changeset
104 {
kono
parents:
diff changeset
105 tree vuse2 = (tree) data;
kono
parents:
diff changeset
106 if (vuse1 == vuse2)
kono
parents:
diff changeset
107 return data;
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 /* This bounds the stmt walks we perform on reference lookups
kono
parents:
diff changeset
110 to O(1) instead of O(N) where N is the number of dominating
kono
parents:
diff changeset
111 stores leading to a candidate. We re-use the SCCVN param
kono
parents:
diff changeset
112 for this as it is basically the same complexity. */
kono
parents:
diff changeset
113 if (cnt > (unsigned) PARAM_VALUE (PARAM_SCCVN_MAX_ALIAS_QUERIES_PER_ACCESS))
kono
parents:
diff changeset
114 return (void *)-1;
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 return NULL;
kono
parents:
diff changeset
117 }
kono
parents:
diff changeset
118
kono
parents:
diff changeset
119 /* We looked for STMT in the hash table, but did not find it.
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 If STMT is an assignment from a binary operator, we may know something
kono
parents:
diff changeset
122 about the operands relationship to each other which would allow
kono
parents:
diff changeset
123 us to derive a constant value for the RHS of STMT. */
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 tree
kono
parents:
diff changeset
126 avail_exprs_stack::simplify_binary_operation (gimple *stmt,
kono
parents:
diff changeset
127 class expr_hash_elt element)
kono
parents:
diff changeset
128 {
kono
parents:
diff changeset
129 if (is_gimple_assign (stmt))
kono
parents:
diff changeset
130 {
kono
parents:
diff changeset
131 struct hashable_expr *expr = element.expr ();
kono
parents:
diff changeset
132 if (expr->kind == EXPR_BINARY)
kono
parents:
diff changeset
133 {
kono
parents:
diff changeset
134 enum tree_code code = expr->ops.binary.op;
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136 switch (code)
kono
parents:
diff changeset
137 {
kono
parents:
diff changeset
138 /* For these cases, if we know the operands
kono
parents:
diff changeset
139 are equal, then we know the result. */
kono
parents:
diff changeset
140 case MIN_EXPR:
kono
parents:
diff changeset
141 case MAX_EXPR:
kono
parents:
diff changeset
142 case BIT_IOR_EXPR:
kono
parents:
diff changeset
143 case BIT_AND_EXPR:
kono
parents:
diff changeset
144 case BIT_XOR_EXPR:
kono
parents:
diff changeset
145 case MINUS_EXPR:
kono
parents:
diff changeset
146 case TRUNC_DIV_EXPR:
kono
parents:
diff changeset
147 case CEIL_DIV_EXPR:
kono
parents:
diff changeset
148 case FLOOR_DIV_EXPR:
kono
parents:
diff changeset
149 case ROUND_DIV_EXPR:
kono
parents:
diff changeset
150 case EXACT_DIV_EXPR:
kono
parents:
diff changeset
151 case TRUNC_MOD_EXPR:
kono
parents:
diff changeset
152 case CEIL_MOD_EXPR:
kono
parents:
diff changeset
153 case FLOOR_MOD_EXPR:
kono
parents:
diff changeset
154 case ROUND_MOD_EXPR:
kono
parents:
diff changeset
155 {
kono
parents:
diff changeset
156 /* Build a simple equality expr and query the hash table
kono
parents:
diff changeset
157 for it. */
kono
parents:
diff changeset
158 struct hashable_expr expr;
kono
parents:
diff changeset
159 expr.type = boolean_type_node;
kono
parents:
diff changeset
160 expr.kind = EXPR_BINARY;
kono
parents:
diff changeset
161 expr.ops.binary.op = EQ_EXPR;
kono
parents:
diff changeset
162 expr.ops.binary.opnd0 = gimple_assign_rhs1 (stmt);
kono
parents:
diff changeset
163 expr.ops.binary.opnd1 = gimple_assign_rhs2 (stmt);
kono
parents:
diff changeset
164 class expr_hash_elt element2 (&expr, NULL_TREE);
kono
parents:
diff changeset
165 expr_hash_elt **slot
kono
parents:
diff changeset
166 = m_avail_exprs->find_slot (&element2, NO_INSERT);
kono
parents:
diff changeset
167 tree result_type = TREE_TYPE (gimple_assign_lhs (stmt));
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 /* If the query was successful and returned a nonzero
kono
parents:
diff changeset
170 result, then we know that the operands of the binary
kono
parents:
diff changeset
171 expression are the same. In many cases this allows
kono
parents:
diff changeset
172 us to compute a constant result of the expression
kono
parents:
diff changeset
173 at compile time, even if we do not know the exact
kono
parents:
diff changeset
174 values of the operands. */
kono
parents:
diff changeset
175 if (slot && *slot && integer_onep ((*slot)->lhs ()))
kono
parents:
diff changeset
176 {
kono
parents:
diff changeset
177 switch (code)
kono
parents:
diff changeset
178 {
kono
parents:
diff changeset
179 case MIN_EXPR:
kono
parents:
diff changeset
180 case MAX_EXPR:
kono
parents:
diff changeset
181 case BIT_IOR_EXPR:
kono
parents:
diff changeset
182 case BIT_AND_EXPR:
kono
parents:
diff changeset
183 return gimple_assign_rhs1 (stmt);
kono
parents:
diff changeset
184
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
185 case MINUS_EXPR:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
186 /* This is unsafe for certain floats even in non-IEEE
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
187 formats. In IEEE, it is unsafe because it does
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
188 wrong for NaNs. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
189 if (FLOAT_TYPE_P (result_type)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
190 && HONOR_NANS (result_type))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
191 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
192 /* FALLTHRU */
111
kono
parents:
diff changeset
193 case BIT_XOR_EXPR:
kono
parents:
diff changeset
194 case TRUNC_MOD_EXPR:
kono
parents:
diff changeset
195 case CEIL_MOD_EXPR:
kono
parents:
diff changeset
196 case FLOOR_MOD_EXPR:
kono
parents:
diff changeset
197 case ROUND_MOD_EXPR:
kono
parents:
diff changeset
198 return build_zero_cst (result_type);
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 case TRUNC_DIV_EXPR:
kono
parents:
diff changeset
201 case CEIL_DIV_EXPR:
kono
parents:
diff changeset
202 case FLOOR_DIV_EXPR:
kono
parents:
diff changeset
203 case ROUND_DIV_EXPR:
kono
parents:
diff changeset
204 case EXACT_DIV_EXPR:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
205 /* Avoid _Fract types where we can't build 1. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
206 if (ALL_FRACT_MODE_P (TYPE_MODE (result_type)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
207 break;
111
kono
parents:
diff changeset
208 return build_one_cst (result_type);
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 default:
kono
parents:
diff changeset
211 gcc_unreachable ();
kono
parents:
diff changeset
212 }
kono
parents:
diff changeset
213 }
kono
parents:
diff changeset
214 break;
kono
parents:
diff changeset
215 }
kono
parents:
diff changeset
216
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
217 default:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
218 break;
111
kono
parents:
diff changeset
219 }
kono
parents:
diff changeset
220 }
kono
parents:
diff changeset
221 }
kono
parents:
diff changeset
222 return NULL_TREE;
kono
parents:
diff changeset
223 }
kono
parents:
diff changeset
224
kono
parents:
diff changeset
225 /* Search for an existing instance of STMT in the AVAIL_EXPRS_STACK table.
kono
parents:
diff changeset
226 If found, return its LHS. Otherwise insert STMT in the table and
kono
parents:
diff changeset
227 return NULL_TREE.
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229 Also, when an expression is first inserted in the table, it is also
kono
parents:
diff changeset
230 is also added to AVAIL_EXPRS_STACK, so that it can be removed when
kono
parents:
diff changeset
231 we finish processing this block and its children. */
kono
parents:
diff changeset
232
kono
parents:
diff changeset
233 tree
kono
parents:
diff changeset
234 avail_exprs_stack::lookup_avail_expr (gimple *stmt, bool insert, bool tbaa_p)
kono
parents:
diff changeset
235 {
kono
parents:
diff changeset
236 expr_hash_elt **slot;
kono
parents:
diff changeset
237 tree lhs;
kono
parents:
diff changeset
238
kono
parents:
diff changeset
239 /* Get LHS of phi, assignment, or call; else NULL_TREE. */
kono
parents:
diff changeset
240 if (gimple_code (stmt) == GIMPLE_PHI)
kono
parents:
diff changeset
241 lhs = gimple_phi_result (stmt);
kono
parents:
diff changeset
242 else
kono
parents:
diff changeset
243 lhs = gimple_get_lhs (stmt);
kono
parents:
diff changeset
244
kono
parents:
diff changeset
245 class expr_hash_elt element (stmt, lhs);
kono
parents:
diff changeset
246
kono
parents:
diff changeset
247 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
248 {
kono
parents:
diff changeset
249 fprintf (dump_file, "LKUP ");
kono
parents:
diff changeset
250 element.print (dump_file);
kono
parents:
diff changeset
251 }
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 /* Don't bother remembering constant assignments and copy operations.
kono
parents:
diff changeset
254 Constants and copy operations are handled by the constant/copy propagator
kono
parents:
diff changeset
255 in optimize_stmt. */
kono
parents:
diff changeset
256 if (element.expr()->kind == EXPR_SINGLE
kono
parents:
diff changeset
257 && (TREE_CODE (element.expr()->ops.single.rhs) == SSA_NAME
kono
parents:
diff changeset
258 || is_gimple_min_invariant (element.expr()->ops.single.rhs)))
kono
parents:
diff changeset
259 return NULL_TREE;
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 /* Finally try to find the expression in the main expression hash table. */
kono
parents:
diff changeset
262 slot = m_avail_exprs->find_slot (&element, (insert ? INSERT : NO_INSERT));
kono
parents:
diff changeset
263 if (slot == NULL)
kono
parents:
diff changeset
264 {
kono
parents:
diff changeset
265 return NULL_TREE;
kono
parents:
diff changeset
266 }
kono
parents:
diff changeset
267 else if (*slot == NULL)
kono
parents:
diff changeset
268 {
kono
parents:
diff changeset
269 /* If we did not find the expression in the hash table, we may still
kono
parents:
diff changeset
270 be able to produce a result for some expressions. */
kono
parents:
diff changeset
271 tree retval = avail_exprs_stack::simplify_binary_operation (stmt,
kono
parents:
diff changeset
272 element);
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 /* We have, in effect, allocated *SLOT for ELEMENT at this point.
kono
parents:
diff changeset
275 We must initialize *SLOT to a real entry, even if we found a
kono
parents:
diff changeset
276 way to prove ELEMENT was a constant after not finding ELEMENT
kono
parents:
diff changeset
277 in the hash table.
kono
parents:
diff changeset
278
kono
parents:
diff changeset
279 An uninitialized or empty slot is an indication no prior objects
kono
parents:
diff changeset
280 entered into the hash table had a hash collection with ELEMENT.
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 If we fail to do so and had such entries in the table, they
kono
parents:
diff changeset
283 would become unreachable. */
kono
parents:
diff changeset
284 class expr_hash_elt *element2 = new expr_hash_elt (element);
kono
parents:
diff changeset
285 *slot = element2;
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 record_expr (element2, NULL, '2');
kono
parents:
diff changeset
288 return retval;
kono
parents:
diff changeset
289 }
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291 /* If we found a redundant memory operation do an alias walk to
kono
parents:
diff changeset
292 check if we can re-use it. */
kono
parents:
diff changeset
293 if (gimple_vuse (stmt) != (*slot)->vop ())
kono
parents:
diff changeset
294 {
kono
parents:
diff changeset
295 tree vuse1 = (*slot)->vop ();
kono
parents:
diff changeset
296 tree vuse2 = gimple_vuse (stmt);
kono
parents:
diff changeset
297 /* If we have a load of a register and a candidate in the
kono
parents:
diff changeset
298 hash with vuse1 then try to reach its stmt by walking
kono
parents:
diff changeset
299 up the virtual use-def chain using walk_non_aliased_vuses.
kono
parents:
diff changeset
300 But don't do this when removing expressions from the hash. */
kono
parents:
diff changeset
301 ao_ref ref;
kono
parents:
diff changeset
302 if (!(vuse1 && vuse2
kono
parents:
diff changeset
303 && gimple_assign_single_p (stmt)
kono
parents:
diff changeset
304 && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
kono
parents:
diff changeset
305 && (ao_ref_init (&ref, gimple_assign_rhs1 (stmt)),
kono
parents:
diff changeset
306 ref.base_alias_set = ref.ref_alias_set = tbaa_p ? -1 : 0, true)
kono
parents:
diff changeset
307 && walk_non_aliased_vuses (&ref, vuse2,
kono
parents:
diff changeset
308 vuse_eq, NULL, NULL, vuse1) != NULL))
kono
parents:
diff changeset
309 {
kono
parents:
diff changeset
310 if (insert)
kono
parents:
diff changeset
311 {
kono
parents:
diff changeset
312 class expr_hash_elt *element2 = new expr_hash_elt (element);
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 /* Insert the expr into the hash by replacing the current
kono
parents:
diff changeset
315 entry and recording the value to restore in the
kono
parents:
diff changeset
316 avail_exprs_stack. */
kono
parents:
diff changeset
317 record_expr (element2, *slot, '2');
kono
parents:
diff changeset
318 *slot = element2;
kono
parents:
diff changeset
319 }
kono
parents:
diff changeset
320 return NULL_TREE;
kono
parents:
diff changeset
321 }
kono
parents:
diff changeset
322 }
kono
parents:
diff changeset
323
kono
parents:
diff changeset
324 /* Extract the LHS of the assignment so that it can be used as the current
kono
parents:
diff changeset
325 definition of another variable. */
kono
parents:
diff changeset
326 lhs = (*slot)->lhs ();
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 /* Valueize the result. */
kono
parents:
diff changeset
329 if (TREE_CODE (lhs) == SSA_NAME)
kono
parents:
diff changeset
330 {
kono
parents:
diff changeset
331 tree tem = SSA_NAME_VALUE (lhs);
kono
parents:
diff changeset
332 if (tem)
kono
parents:
diff changeset
333 lhs = tem;
kono
parents:
diff changeset
334 }
kono
parents:
diff changeset
335
kono
parents:
diff changeset
336 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
337 {
kono
parents:
diff changeset
338 fprintf (dump_file, "FIND: ");
kono
parents:
diff changeset
339 print_generic_expr (dump_file, lhs);
kono
parents:
diff changeset
340 fprintf (dump_file, "\n");
kono
parents:
diff changeset
341 }
kono
parents:
diff changeset
342
kono
parents:
diff changeset
343 return lhs;
kono
parents:
diff changeset
344 }
kono
parents:
diff changeset
345
kono
parents:
diff changeset
346 /* Enter condition equivalence P into the hash table.
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 This indicates that a conditional expression has a known
kono
parents:
diff changeset
349 boolean value. */
kono
parents:
diff changeset
350
kono
parents:
diff changeset
351 void
kono
parents:
diff changeset
352 avail_exprs_stack::record_cond (cond_equivalence *p)
kono
parents:
diff changeset
353 {
kono
parents:
diff changeset
354 class expr_hash_elt *element = new expr_hash_elt (&p->cond, p->value);
kono
parents:
diff changeset
355 expr_hash_elt **slot;
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 slot = m_avail_exprs->find_slot_with_hash (element, element->hash (), INSERT);
kono
parents:
diff changeset
358 if (*slot == NULL)
kono
parents:
diff changeset
359 {
kono
parents:
diff changeset
360 *slot = element;
kono
parents:
diff changeset
361 record_expr (element, NULL, '1');
kono
parents:
diff changeset
362 }
kono
parents:
diff changeset
363 else
kono
parents:
diff changeset
364 delete element;
kono
parents:
diff changeset
365 }
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 /* Generate a hash value for a pair of expressions. This can be used
kono
parents:
diff changeset
368 iteratively by passing a previous result in HSTATE.
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 The same hash value is always returned for a given pair of expressions,
kono
parents:
diff changeset
371 regardless of the order in which they are presented. This is useful in
kono
parents:
diff changeset
372 hashing the operands of commutative functions. */
kono
parents:
diff changeset
373
kono
parents:
diff changeset
374 namespace inchash
kono
parents:
diff changeset
375 {
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 static void
kono
parents:
diff changeset
378 add_expr_commutative (const_tree t1, const_tree t2, hash &hstate)
kono
parents:
diff changeset
379 {
kono
parents:
diff changeset
380 hash one, two;
kono
parents:
diff changeset
381
kono
parents:
diff changeset
382 inchash::add_expr (t1, one);
kono
parents:
diff changeset
383 inchash::add_expr (t2, two);
kono
parents:
diff changeset
384 hstate.add_commutative (one, two);
kono
parents:
diff changeset
385 }
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 /* Compute a hash value for a hashable_expr value EXPR and a
kono
parents:
diff changeset
388 previously accumulated hash value VAL. If two hashable_expr
kono
parents:
diff changeset
389 values compare equal with hashable_expr_equal_p, they must
kono
parents:
diff changeset
390 hash to the same value, given an identical value of VAL.
kono
parents:
diff changeset
391 The logic is intended to follow inchash::add_expr in tree.c. */
kono
parents:
diff changeset
392
kono
parents:
diff changeset
393 static void
kono
parents:
diff changeset
394 add_hashable_expr (const struct hashable_expr *expr, hash &hstate)
kono
parents:
diff changeset
395 {
kono
parents:
diff changeset
396 switch (expr->kind)
kono
parents:
diff changeset
397 {
kono
parents:
diff changeset
398 case EXPR_SINGLE:
kono
parents:
diff changeset
399 inchash::add_expr (expr->ops.single.rhs, hstate);
kono
parents:
diff changeset
400 break;
kono
parents:
diff changeset
401
kono
parents:
diff changeset
402 case EXPR_UNARY:
kono
parents:
diff changeset
403 hstate.add_object (expr->ops.unary.op);
kono
parents:
diff changeset
404
kono
parents:
diff changeset
405 /* Make sure to include signedness in the hash computation.
kono
parents:
diff changeset
406 Don't hash the type, that can lead to having nodes which
kono
parents:
diff changeset
407 compare equal according to operand_equal_p, but which
kono
parents:
diff changeset
408 have different hash codes. */
kono
parents:
diff changeset
409 if (CONVERT_EXPR_CODE_P (expr->ops.unary.op)
kono
parents:
diff changeset
410 || expr->ops.unary.op == NON_LVALUE_EXPR)
kono
parents:
diff changeset
411 hstate.add_int (TYPE_UNSIGNED (expr->type));
kono
parents:
diff changeset
412
kono
parents:
diff changeset
413 inchash::add_expr (expr->ops.unary.opnd, hstate);
kono
parents:
diff changeset
414 break;
kono
parents:
diff changeset
415
kono
parents:
diff changeset
416 case EXPR_BINARY:
kono
parents:
diff changeset
417 hstate.add_object (expr->ops.binary.op);
kono
parents:
diff changeset
418 if (commutative_tree_code (expr->ops.binary.op))
kono
parents:
diff changeset
419 inchash::add_expr_commutative (expr->ops.binary.opnd0,
kono
parents:
diff changeset
420 expr->ops.binary.opnd1, hstate);
kono
parents:
diff changeset
421 else
kono
parents:
diff changeset
422 {
kono
parents:
diff changeset
423 inchash::add_expr (expr->ops.binary.opnd0, hstate);
kono
parents:
diff changeset
424 inchash::add_expr (expr->ops.binary.opnd1, hstate);
kono
parents:
diff changeset
425 }
kono
parents:
diff changeset
426 break;
kono
parents:
diff changeset
427
kono
parents:
diff changeset
428 case EXPR_TERNARY:
kono
parents:
diff changeset
429 hstate.add_object (expr->ops.ternary.op);
kono
parents:
diff changeset
430 if (commutative_ternary_tree_code (expr->ops.ternary.op))
kono
parents:
diff changeset
431 inchash::add_expr_commutative (expr->ops.ternary.opnd0,
kono
parents:
diff changeset
432 expr->ops.ternary.opnd1, hstate);
kono
parents:
diff changeset
433 else
kono
parents:
diff changeset
434 {
kono
parents:
diff changeset
435 inchash::add_expr (expr->ops.ternary.opnd0, hstate);
kono
parents:
diff changeset
436 inchash::add_expr (expr->ops.ternary.opnd1, hstate);
kono
parents:
diff changeset
437 }
kono
parents:
diff changeset
438 inchash::add_expr (expr->ops.ternary.opnd2, hstate);
kono
parents:
diff changeset
439 break;
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 case EXPR_CALL:
kono
parents:
diff changeset
442 {
kono
parents:
diff changeset
443 size_t i;
kono
parents:
diff changeset
444 enum tree_code code = CALL_EXPR;
kono
parents:
diff changeset
445 gcall *fn_from;
kono
parents:
diff changeset
446
kono
parents:
diff changeset
447 hstate.add_object (code);
kono
parents:
diff changeset
448 fn_from = expr->ops.call.fn_from;
kono
parents:
diff changeset
449 if (gimple_call_internal_p (fn_from))
kono
parents:
diff changeset
450 hstate.merge_hash ((hashval_t) gimple_call_internal_fn (fn_from));
kono
parents:
diff changeset
451 else
kono
parents:
diff changeset
452 inchash::add_expr (gimple_call_fn (fn_from), hstate);
kono
parents:
diff changeset
453 for (i = 0; i < expr->ops.call.nargs; i++)
kono
parents:
diff changeset
454 inchash::add_expr (expr->ops.call.args[i], hstate);
kono
parents:
diff changeset
455 }
kono
parents:
diff changeset
456 break;
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 case EXPR_PHI:
kono
parents:
diff changeset
459 {
kono
parents:
diff changeset
460 size_t i;
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 for (i = 0; i < expr->ops.phi.nargs; i++)
kono
parents:
diff changeset
463 inchash::add_expr (expr->ops.phi.args[i], hstate);
kono
parents:
diff changeset
464 }
kono
parents:
diff changeset
465 break;
kono
parents:
diff changeset
466
kono
parents:
diff changeset
467 default:
kono
parents:
diff changeset
468 gcc_unreachable ();
kono
parents:
diff changeset
469 }
kono
parents:
diff changeset
470 }
kono
parents:
diff changeset
471
kono
parents:
diff changeset
472 }
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 /* Hashing and equality functions. We compute a value number for expressions
kono
parents:
diff changeset
475 using the code of the expression and the SSA numbers of its operands. */
kono
parents:
diff changeset
476
kono
parents:
diff changeset
477 static hashval_t
kono
parents:
diff changeset
478 avail_expr_hash (class expr_hash_elt *p)
kono
parents:
diff changeset
479 {
kono
parents:
diff changeset
480 const struct hashable_expr *expr = p->expr ();
kono
parents:
diff changeset
481 inchash::hash hstate;
kono
parents:
diff changeset
482
kono
parents:
diff changeset
483 if (expr->kind == EXPR_SINGLE)
kono
parents:
diff changeset
484 {
kono
parents:
diff changeset
485 /* T could potentially be a switch index or a goto dest. */
kono
parents:
diff changeset
486 tree t = expr->ops.single.rhs;
kono
parents:
diff changeset
487 if (TREE_CODE (t) == MEM_REF || handled_component_p (t))
kono
parents:
diff changeset
488 {
kono
parents:
diff changeset
489 /* Make equivalent statements of both these kinds hash together.
kono
parents:
diff changeset
490 Dealing with both MEM_REF and ARRAY_REF allows us not to care
kono
parents:
diff changeset
491 about equivalence with other statements not considered here. */
kono
parents:
diff changeset
492 bool reverse;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
493 poly_int64 offset, size, max_size;
111
kono
parents:
diff changeset
494 tree base = get_ref_base_and_extent (t, &offset, &size, &max_size,
kono
parents:
diff changeset
495 &reverse);
kono
parents:
diff changeset
496 /* Strictly, we could try to normalize variable-sized accesses too,
kono
parents:
diff changeset
497 but here we just deal with the common case. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
498 if (known_size_p (max_size)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
499 && known_eq (size, max_size))
111
kono
parents:
diff changeset
500 {
kono
parents:
diff changeset
501 enum tree_code code = MEM_REF;
kono
parents:
diff changeset
502 hstate.add_object (code);
kono
parents:
diff changeset
503 inchash::add_expr (base, hstate);
kono
parents:
diff changeset
504 hstate.add_object (offset);
kono
parents:
diff changeset
505 hstate.add_object (size);
kono
parents:
diff changeset
506 return hstate.end ();
kono
parents:
diff changeset
507 }
kono
parents:
diff changeset
508 }
kono
parents:
diff changeset
509 }
kono
parents:
diff changeset
510
kono
parents:
diff changeset
511 inchash::add_hashable_expr (expr, hstate);
kono
parents:
diff changeset
512
kono
parents:
diff changeset
513 return hstate.end ();
kono
parents:
diff changeset
514 }
kono
parents:
diff changeset
515
kono
parents:
diff changeset
516 /* Compares trees T0 and T1 to see if they are MEM_REF or ARRAY_REFs equivalent
kono
parents:
diff changeset
517 to each other. (That is, they return the value of the same bit of memory.)
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 Return TRUE if the two are so equivalent; FALSE if not (which could still
kono
parents:
diff changeset
520 mean the two are equivalent by other means). */
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 static bool
kono
parents:
diff changeset
523 equal_mem_array_ref_p (tree t0, tree t1)
kono
parents:
diff changeset
524 {
kono
parents:
diff changeset
525 if (TREE_CODE (t0) != MEM_REF && ! handled_component_p (t0))
kono
parents:
diff changeset
526 return false;
kono
parents:
diff changeset
527 if (TREE_CODE (t1) != MEM_REF && ! handled_component_p (t1))
kono
parents:
diff changeset
528 return false;
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 if (!types_compatible_p (TREE_TYPE (t0), TREE_TYPE (t1)))
kono
parents:
diff changeset
531 return false;
kono
parents:
diff changeset
532 bool rev0;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
533 poly_int64 off0, sz0, max0;
111
kono
parents:
diff changeset
534 tree base0 = get_ref_base_and_extent (t0, &off0, &sz0, &max0, &rev0);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
535 if (!known_size_p (max0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
536 || maybe_ne (sz0, max0))
111
kono
parents:
diff changeset
537 return false;
kono
parents:
diff changeset
538
kono
parents:
diff changeset
539 bool rev1;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
540 poly_int64 off1, sz1, max1;
111
kono
parents:
diff changeset
541 tree base1 = get_ref_base_and_extent (t1, &off1, &sz1, &max1, &rev1);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
542 if (!known_size_p (max1)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
543 || maybe_ne (sz1, max1))
111
kono
parents:
diff changeset
544 return false;
kono
parents:
diff changeset
545
kono
parents:
diff changeset
546 if (rev0 != rev1)
kono
parents:
diff changeset
547 return false;
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 /* Types were compatible, so this is a sanity check. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
550 gcc_assert (known_eq (sz0, sz1));
111
kono
parents:
diff changeset
551
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
552 return known_eq (off0, off1) && operand_equal_p (base0, base1, 0);
111
kono
parents:
diff changeset
553 }
kono
parents:
diff changeset
554
kono
parents:
diff changeset
555 /* Compare two hashable_expr structures for equivalence. They are
kono
parents:
diff changeset
556 considered equivalent when the expressions they denote must
kono
parents:
diff changeset
557 necessarily be equal. The logic is intended to follow that of
kono
parents:
diff changeset
558 operand_equal_p in fold-const.c */
kono
parents:
diff changeset
559
kono
parents:
diff changeset
560 static bool
kono
parents:
diff changeset
561 hashable_expr_equal_p (const struct hashable_expr *expr0,
kono
parents:
diff changeset
562 const struct hashable_expr *expr1)
kono
parents:
diff changeset
563 {
kono
parents:
diff changeset
564 tree type0 = expr0->type;
kono
parents:
diff changeset
565 tree type1 = expr1->type;
kono
parents:
diff changeset
566
kono
parents:
diff changeset
567 /* If either type is NULL, there is nothing to check. */
kono
parents:
diff changeset
568 if ((type0 == NULL_TREE) ^ (type1 == NULL_TREE))
kono
parents:
diff changeset
569 return false;
kono
parents:
diff changeset
570
kono
parents:
diff changeset
571 /* If both types don't have the same signedness, precision, and mode,
kono
parents:
diff changeset
572 then we can't consider them equal. */
kono
parents:
diff changeset
573 if (type0 != type1
kono
parents:
diff changeset
574 && (TREE_CODE (type0) == ERROR_MARK
kono
parents:
diff changeset
575 || TREE_CODE (type1) == ERROR_MARK
kono
parents:
diff changeset
576 || TYPE_UNSIGNED (type0) != TYPE_UNSIGNED (type1)
kono
parents:
diff changeset
577 || TYPE_PRECISION (type0) != TYPE_PRECISION (type1)
kono
parents:
diff changeset
578 || TYPE_MODE (type0) != TYPE_MODE (type1)))
kono
parents:
diff changeset
579 return false;
kono
parents:
diff changeset
580
kono
parents:
diff changeset
581 if (expr0->kind != expr1->kind)
kono
parents:
diff changeset
582 return false;
kono
parents:
diff changeset
583
kono
parents:
diff changeset
584 switch (expr0->kind)
kono
parents:
diff changeset
585 {
kono
parents:
diff changeset
586 case EXPR_SINGLE:
kono
parents:
diff changeset
587 return equal_mem_array_ref_p (expr0->ops.single.rhs,
kono
parents:
diff changeset
588 expr1->ops.single.rhs)
kono
parents:
diff changeset
589 || operand_equal_p (expr0->ops.single.rhs,
kono
parents:
diff changeset
590 expr1->ops.single.rhs, 0);
kono
parents:
diff changeset
591 case EXPR_UNARY:
kono
parents:
diff changeset
592 if (expr0->ops.unary.op != expr1->ops.unary.op)
kono
parents:
diff changeset
593 return false;
kono
parents:
diff changeset
594
kono
parents:
diff changeset
595 if ((CONVERT_EXPR_CODE_P (expr0->ops.unary.op)
kono
parents:
diff changeset
596 || expr0->ops.unary.op == NON_LVALUE_EXPR)
kono
parents:
diff changeset
597 && TYPE_UNSIGNED (expr0->type) != TYPE_UNSIGNED (expr1->type))
kono
parents:
diff changeset
598 return false;
kono
parents:
diff changeset
599
kono
parents:
diff changeset
600 return operand_equal_p (expr0->ops.unary.opnd,
kono
parents:
diff changeset
601 expr1->ops.unary.opnd, 0);
kono
parents:
diff changeset
602
kono
parents:
diff changeset
603 case EXPR_BINARY:
kono
parents:
diff changeset
604 if (expr0->ops.binary.op != expr1->ops.binary.op)
kono
parents:
diff changeset
605 return false;
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 if (operand_equal_p (expr0->ops.binary.opnd0,
kono
parents:
diff changeset
608 expr1->ops.binary.opnd0, 0)
kono
parents:
diff changeset
609 && operand_equal_p (expr0->ops.binary.opnd1,
kono
parents:
diff changeset
610 expr1->ops.binary.opnd1, 0))
kono
parents:
diff changeset
611 return true;
kono
parents:
diff changeset
612
kono
parents:
diff changeset
613 /* For commutative ops, allow the other order. */
kono
parents:
diff changeset
614 return (commutative_tree_code (expr0->ops.binary.op)
kono
parents:
diff changeset
615 && operand_equal_p (expr0->ops.binary.opnd0,
kono
parents:
diff changeset
616 expr1->ops.binary.opnd1, 0)
kono
parents:
diff changeset
617 && operand_equal_p (expr0->ops.binary.opnd1,
kono
parents:
diff changeset
618 expr1->ops.binary.opnd0, 0));
kono
parents:
diff changeset
619
kono
parents:
diff changeset
620 case EXPR_TERNARY:
kono
parents:
diff changeset
621 if (expr0->ops.ternary.op != expr1->ops.ternary.op
kono
parents:
diff changeset
622 || !operand_equal_p (expr0->ops.ternary.opnd2,
kono
parents:
diff changeset
623 expr1->ops.ternary.opnd2, 0))
kono
parents:
diff changeset
624 return false;
kono
parents:
diff changeset
625
kono
parents:
diff changeset
626 /* BIT_INSERT_EXPR has an implict operand as the type precision
kono
parents:
diff changeset
627 of op1. Need to check to make sure they are the same. */
kono
parents:
diff changeset
628 if (expr0->ops.ternary.op == BIT_INSERT_EXPR
kono
parents:
diff changeset
629 && TREE_CODE (expr0->ops.ternary.opnd1) == INTEGER_CST
kono
parents:
diff changeset
630 && TREE_CODE (expr1->ops.ternary.opnd1) == INTEGER_CST
kono
parents:
diff changeset
631 && TYPE_PRECISION (TREE_TYPE (expr0->ops.ternary.opnd1))
kono
parents:
diff changeset
632 != TYPE_PRECISION (TREE_TYPE (expr1->ops.ternary.opnd1)))
kono
parents:
diff changeset
633 return false;
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 if (operand_equal_p (expr0->ops.ternary.opnd0,
kono
parents:
diff changeset
636 expr1->ops.ternary.opnd0, 0)
kono
parents:
diff changeset
637 && operand_equal_p (expr0->ops.ternary.opnd1,
kono
parents:
diff changeset
638 expr1->ops.ternary.opnd1, 0))
kono
parents:
diff changeset
639 return true;
kono
parents:
diff changeset
640
kono
parents:
diff changeset
641 /* For commutative ops, allow the other order. */
kono
parents:
diff changeset
642 return (commutative_ternary_tree_code (expr0->ops.ternary.op)
kono
parents:
diff changeset
643 && operand_equal_p (expr0->ops.ternary.opnd0,
kono
parents:
diff changeset
644 expr1->ops.ternary.opnd1, 0)
kono
parents:
diff changeset
645 && operand_equal_p (expr0->ops.ternary.opnd1,
kono
parents:
diff changeset
646 expr1->ops.ternary.opnd0, 0));
kono
parents:
diff changeset
647
kono
parents:
diff changeset
648 case EXPR_CALL:
kono
parents:
diff changeset
649 {
kono
parents:
diff changeset
650 size_t i;
kono
parents:
diff changeset
651
kono
parents:
diff changeset
652 /* If the calls are to different functions, then they
kono
parents:
diff changeset
653 clearly cannot be equal. */
kono
parents:
diff changeset
654 if (!gimple_call_same_target_p (expr0->ops.call.fn_from,
kono
parents:
diff changeset
655 expr1->ops.call.fn_from))
kono
parents:
diff changeset
656 return false;
kono
parents:
diff changeset
657
kono
parents:
diff changeset
658 if (! expr0->ops.call.pure)
kono
parents:
diff changeset
659 return false;
kono
parents:
diff changeset
660
kono
parents:
diff changeset
661 if (expr0->ops.call.nargs != expr1->ops.call.nargs)
kono
parents:
diff changeset
662 return false;
kono
parents:
diff changeset
663
kono
parents:
diff changeset
664 for (i = 0; i < expr0->ops.call.nargs; i++)
kono
parents:
diff changeset
665 if (! operand_equal_p (expr0->ops.call.args[i],
kono
parents:
diff changeset
666 expr1->ops.call.args[i], 0))
kono
parents:
diff changeset
667 return false;
kono
parents:
diff changeset
668
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
669 if (stmt_could_throw_p (cfun, expr0->ops.call.fn_from))
111
kono
parents:
diff changeset
670 {
kono
parents:
diff changeset
671 int lp0 = lookup_stmt_eh_lp (expr0->ops.call.fn_from);
kono
parents:
diff changeset
672 int lp1 = lookup_stmt_eh_lp (expr1->ops.call.fn_from);
kono
parents:
diff changeset
673 if ((lp0 > 0 || lp1 > 0) && lp0 != lp1)
kono
parents:
diff changeset
674 return false;
kono
parents:
diff changeset
675 }
kono
parents:
diff changeset
676
kono
parents:
diff changeset
677 return true;
kono
parents:
diff changeset
678 }
kono
parents:
diff changeset
679
kono
parents:
diff changeset
680 case EXPR_PHI:
kono
parents:
diff changeset
681 {
kono
parents:
diff changeset
682 size_t i;
kono
parents:
diff changeset
683
kono
parents:
diff changeset
684 if (expr0->ops.phi.nargs != expr1->ops.phi.nargs)
kono
parents:
diff changeset
685 return false;
kono
parents:
diff changeset
686
kono
parents:
diff changeset
687 for (i = 0; i < expr0->ops.phi.nargs; i++)
kono
parents:
diff changeset
688 if (! operand_equal_p (expr0->ops.phi.args[i],
kono
parents:
diff changeset
689 expr1->ops.phi.args[i], 0))
kono
parents:
diff changeset
690 return false;
kono
parents:
diff changeset
691
kono
parents:
diff changeset
692 return true;
kono
parents:
diff changeset
693 }
kono
parents:
diff changeset
694
kono
parents:
diff changeset
695 default:
kono
parents:
diff changeset
696 gcc_unreachable ();
kono
parents:
diff changeset
697 }
kono
parents:
diff changeset
698 }
kono
parents:
diff changeset
699
kono
parents:
diff changeset
700 /* Given a statement STMT, construct a hash table element. */
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 expr_hash_elt::expr_hash_elt (gimple *stmt, tree orig_lhs)
kono
parents:
diff changeset
703 {
kono
parents:
diff changeset
704 enum gimple_code code = gimple_code (stmt);
kono
parents:
diff changeset
705 struct hashable_expr *expr = this->expr ();
kono
parents:
diff changeset
706
kono
parents:
diff changeset
707 if (code == GIMPLE_ASSIGN)
kono
parents:
diff changeset
708 {
kono
parents:
diff changeset
709 enum tree_code subcode = gimple_assign_rhs_code (stmt);
kono
parents:
diff changeset
710
kono
parents:
diff changeset
711 switch (get_gimple_rhs_class (subcode))
kono
parents:
diff changeset
712 {
kono
parents:
diff changeset
713 case GIMPLE_SINGLE_RHS:
kono
parents:
diff changeset
714 expr->kind = EXPR_SINGLE;
kono
parents:
diff changeset
715 expr->type = TREE_TYPE (gimple_assign_rhs1 (stmt));
kono
parents:
diff changeset
716 expr->ops.single.rhs = gimple_assign_rhs1 (stmt);
kono
parents:
diff changeset
717 break;
kono
parents:
diff changeset
718 case GIMPLE_UNARY_RHS:
kono
parents:
diff changeset
719 expr->kind = EXPR_UNARY;
kono
parents:
diff changeset
720 expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
kono
parents:
diff changeset
721 if (CONVERT_EXPR_CODE_P (subcode))
kono
parents:
diff changeset
722 subcode = NOP_EXPR;
kono
parents:
diff changeset
723 expr->ops.unary.op = subcode;
kono
parents:
diff changeset
724 expr->ops.unary.opnd = gimple_assign_rhs1 (stmt);
kono
parents:
diff changeset
725 break;
kono
parents:
diff changeset
726 case GIMPLE_BINARY_RHS:
kono
parents:
diff changeset
727 expr->kind = EXPR_BINARY;
kono
parents:
diff changeset
728 expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
kono
parents:
diff changeset
729 expr->ops.binary.op = subcode;
kono
parents:
diff changeset
730 expr->ops.binary.opnd0 = gimple_assign_rhs1 (stmt);
kono
parents:
diff changeset
731 expr->ops.binary.opnd1 = gimple_assign_rhs2 (stmt);
kono
parents:
diff changeset
732 break;
kono
parents:
diff changeset
733 case GIMPLE_TERNARY_RHS:
kono
parents:
diff changeset
734 expr->kind = EXPR_TERNARY;
kono
parents:
diff changeset
735 expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
kono
parents:
diff changeset
736 expr->ops.ternary.op = subcode;
kono
parents:
diff changeset
737 expr->ops.ternary.opnd0 = gimple_assign_rhs1 (stmt);
kono
parents:
diff changeset
738 expr->ops.ternary.opnd1 = gimple_assign_rhs2 (stmt);
kono
parents:
diff changeset
739 expr->ops.ternary.opnd2 = gimple_assign_rhs3 (stmt);
kono
parents:
diff changeset
740 break;
kono
parents:
diff changeset
741 default:
kono
parents:
diff changeset
742 gcc_unreachable ();
kono
parents:
diff changeset
743 }
kono
parents:
diff changeset
744 }
kono
parents:
diff changeset
745 else if (code == GIMPLE_COND)
kono
parents:
diff changeset
746 {
kono
parents:
diff changeset
747 expr->type = boolean_type_node;
kono
parents:
diff changeset
748 expr->kind = EXPR_BINARY;
kono
parents:
diff changeset
749 expr->ops.binary.op = gimple_cond_code (stmt);
kono
parents:
diff changeset
750 expr->ops.binary.opnd0 = gimple_cond_lhs (stmt);
kono
parents:
diff changeset
751 expr->ops.binary.opnd1 = gimple_cond_rhs (stmt);
kono
parents:
diff changeset
752 }
kono
parents:
diff changeset
753 else if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
kono
parents:
diff changeset
754 {
kono
parents:
diff changeset
755 size_t nargs = gimple_call_num_args (call_stmt);
kono
parents:
diff changeset
756 size_t i;
kono
parents:
diff changeset
757
kono
parents:
diff changeset
758 gcc_assert (gimple_call_lhs (call_stmt));
kono
parents:
diff changeset
759
kono
parents:
diff changeset
760 expr->type = TREE_TYPE (gimple_call_lhs (call_stmt));
kono
parents:
diff changeset
761 expr->kind = EXPR_CALL;
kono
parents:
diff changeset
762 expr->ops.call.fn_from = call_stmt;
kono
parents:
diff changeset
763
kono
parents:
diff changeset
764 if (gimple_call_flags (call_stmt) & (ECF_CONST | ECF_PURE))
kono
parents:
diff changeset
765 expr->ops.call.pure = true;
kono
parents:
diff changeset
766 else
kono
parents:
diff changeset
767 expr->ops.call.pure = false;
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 expr->ops.call.nargs = nargs;
kono
parents:
diff changeset
770 expr->ops.call.args = XCNEWVEC (tree, nargs);
kono
parents:
diff changeset
771 for (i = 0; i < nargs; i++)
kono
parents:
diff changeset
772 expr->ops.call.args[i] = gimple_call_arg (call_stmt, i);
kono
parents:
diff changeset
773 }
kono
parents:
diff changeset
774 else if (gswitch *swtch_stmt = dyn_cast <gswitch *> (stmt))
kono
parents:
diff changeset
775 {
kono
parents:
diff changeset
776 expr->type = TREE_TYPE (gimple_switch_index (swtch_stmt));
kono
parents:
diff changeset
777 expr->kind = EXPR_SINGLE;
kono
parents:
diff changeset
778 expr->ops.single.rhs = gimple_switch_index (swtch_stmt);
kono
parents:
diff changeset
779 }
kono
parents:
diff changeset
780 else if (code == GIMPLE_GOTO)
kono
parents:
diff changeset
781 {
kono
parents:
diff changeset
782 expr->type = TREE_TYPE (gimple_goto_dest (stmt));
kono
parents:
diff changeset
783 expr->kind = EXPR_SINGLE;
kono
parents:
diff changeset
784 expr->ops.single.rhs = gimple_goto_dest (stmt);
kono
parents:
diff changeset
785 }
kono
parents:
diff changeset
786 else if (code == GIMPLE_PHI)
kono
parents:
diff changeset
787 {
kono
parents:
diff changeset
788 size_t nargs = gimple_phi_num_args (stmt);
kono
parents:
diff changeset
789 size_t i;
kono
parents:
diff changeset
790
kono
parents:
diff changeset
791 expr->type = TREE_TYPE (gimple_phi_result (stmt));
kono
parents:
diff changeset
792 expr->kind = EXPR_PHI;
kono
parents:
diff changeset
793 expr->ops.phi.nargs = nargs;
kono
parents:
diff changeset
794 expr->ops.phi.args = XCNEWVEC (tree, nargs);
kono
parents:
diff changeset
795 for (i = 0; i < nargs; i++)
kono
parents:
diff changeset
796 expr->ops.phi.args[i] = gimple_phi_arg_def (stmt, i);
kono
parents:
diff changeset
797 }
kono
parents:
diff changeset
798 else
kono
parents:
diff changeset
799 gcc_unreachable ();
kono
parents:
diff changeset
800
kono
parents:
diff changeset
801 m_lhs = orig_lhs;
kono
parents:
diff changeset
802 m_vop = gimple_vuse (stmt);
kono
parents:
diff changeset
803 m_hash = avail_expr_hash (this);
kono
parents:
diff changeset
804 m_stamp = this;
kono
parents:
diff changeset
805 }
kono
parents:
diff changeset
806
kono
parents:
diff changeset
807 /* Given a hashable_expr expression ORIG and an ORIG_LHS,
kono
parents:
diff changeset
808 construct a hash table element. */
kono
parents:
diff changeset
809
kono
parents:
diff changeset
810 expr_hash_elt::expr_hash_elt (struct hashable_expr *orig, tree orig_lhs)
kono
parents:
diff changeset
811 {
kono
parents:
diff changeset
812 m_expr = *orig;
kono
parents:
diff changeset
813 m_lhs = orig_lhs;
kono
parents:
diff changeset
814 m_vop = NULL_TREE;
kono
parents:
diff changeset
815 m_hash = avail_expr_hash (this);
kono
parents:
diff changeset
816 m_stamp = this;
kono
parents:
diff changeset
817 }
kono
parents:
diff changeset
818
kono
parents:
diff changeset
819 /* Copy constructor for a hash table element. */
kono
parents:
diff changeset
820
kono
parents:
diff changeset
821 expr_hash_elt::expr_hash_elt (class expr_hash_elt &old_elt)
kono
parents:
diff changeset
822 {
kono
parents:
diff changeset
823 m_expr = old_elt.m_expr;
kono
parents:
diff changeset
824 m_lhs = old_elt.m_lhs;
kono
parents:
diff changeset
825 m_vop = old_elt.m_vop;
kono
parents:
diff changeset
826 m_hash = old_elt.m_hash;
kono
parents:
diff changeset
827 m_stamp = this;
kono
parents:
diff changeset
828
kono
parents:
diff changeset
829 /* Now deep copy the malloc'd space for CALL and PHI args. */
kono
parents:
diff changeset
830 if (old_elt.m_expr.kind == EXPR_CALL)
kono
parents:
diff changeset
831 {
kono
parents:
diff changeset
832 size_t nargs = old_elt.m_expr.ops.call.nargs;
kono
parents:
diff changeset
833 size_t i;
kono
parents:
diff changeset
834
kono
parents:
diff changeset
835 m_expr.ops.call.args = XCNEWVEC (tree, nargs);
kono
parents:
diff changeset
836 for (i = 0; i < nargs; i++)
kono
parents:
diff changeset
837 m_expr.ops.call.args[i] = old_elt.m_expr.ops.call.args[i];
kono
parents:
diff changeset
838 }
kono
parents:
diff changeset
839 else if (old_elt.m_expr.kind == EXPR_PHI)
kono
parents:
diff changeset
840 {
kono
parents:
diff changeset
841 size_t nargs = old_elt.m_expr.ops.phi.nargs;
kono
parents:
diff changeset
842 size_t i;
kono
parents:
diff changeset
843
kono
parents:
diff changeset
844 m_expr.ops.phi.args = XCNEWVEC (tree, nargs);
kono
parents:
diff changeset
845 for (i = 0; i < nargs; i++)
kono
parents:
diff changeset
846 m_expr.ops.phi.args[i] = old_elt.m_expr.ops.phi.args[i];
kono
parents:
diff changeset
847 }
kono
parents:
diff changeset
848 }
kono
parents:
diff changeset
849
kono
parents:
diff changeset
850 /* Calls and PHIs have a variable number of arguments that are allocated
kono
parents:
diff changeset
851 on the heap. Thus we have to have a special dtor to release them. */
kono
parents:
diff changeset
852
kono
parents:
diff changeset
853 expr_hash_elt::~expr_hash_elt ()
kono
parents:
diff changeset
854 {
kono
parents:
diff changeset
855 if (m_expr.kind == EXPR_CALL)
kono
parents:
diff changeset
856 free (m_expr.ops.call.args);
kono
parents:
diff changeset
857 else if (m_expr.kind == EXPR_PHI)
kono
parents:
diff changeset
858 free (m_expr.ops.phi.args);
kono
parents:
diff changeset
859 }
kono
parents:
diff changeset
860
kono
parents:
diff changeset
861 /* Print a diagnostic dump of an expression hash table entry. */
kono
parents:
diff changeset
862
kono
parents:
diff changeset
863 void
kono
parents:
diff changeset
864 expr_hash_elt::print (FILE *stream)
kono
parents:
diff changeset
865 {
kono
parents:
diff changeset
866 fprintf (stream, "STMT ");
kono
parents:
diff changeset
867
kono
parents:
diff changeset
868 if (m_lhs)
kono
parents:
diff changeset
869 {
kono
parents:
diff changeset
870 print_generic_expr (stream, m_lhs);
kono
parents:
diff changeset
871 fprintf (stream, " = ");
kono
parents:
diff changeset
872 }
kono
parents:
diff changeset
873
kono
parents:
diff changeset
874 switch (m_expr.kind)
kono
parents:
diff changeset
875 {
kono
parents:
diff changeset
876 case EXPR_SINGLE:
kono
parents:
diff changeset
877 print_generic_expr (stream, m_expr.ops.single.rhs);
kono
parents:
diff changeset
878 break;
kono
parents:
diff changeset
879
kono
parents:
diff changeset
880 case EXPR_UNARY:
kono
parents:
diff changeset
881 fprintf (stream, "%s ", get_tree_code_name (m_expr.ops.unary.op));
kono
parents:
diff changeset
882 print_generic_expr (stream, m_expr.ops.unary.opnd);
kono
parents:
diff changeset
883 break;
kono
parents:
diff changeset
884
kono
parents:
diff changeset
885 case EXPR_BINARY:
kono
parents:
diff changeset
886 print_generic_expr (stream, m_expr.ops.binary.opnd0);
kono
parents:
diff changeset
887 fprintf (stream, " %s ", get_tree_code_name (m_expr.ops.binary.op));
kono
parents:
diff changeset
888 print_generic_expr (stream, m_expr.ops.binary.opnd1);
kono
parents:
diff changeset
889 break;
kono
parents:
diff changeset
890
kono
parents:
diff changeset
891 case EXPR_TERNARY:
kono
parents:
diff changeset
892 fprintf (stream, " %s <", get_tree_code_name (m_expr.ops.ternary.op));
kono
parents:
diff changeset
893 print_generic_expr (stream, m_expr.ops.ternary.opnd0);
kono
parents:
diff changeset
894 fputs (", ", stream);
kono
parents:
diff changeset
895 print_generic_expr (stream, m_expr.ops.ternary.opnd1);
kono
parents:
diff changeset
896 fputs (", ", stream);
kono
parents:
diff changeset
897 print_generic_expr (stream, m_expr.ops.ternary.opnd2);
kono
parents:
diff changeset
898 fputs (">", stream);
kono
parents:
diff changeset
899 break;
kono
parents:
diff changeset
900
kono
parents:
diff changeset
901 case EXPR_CALL:
kono
parents:
diff changeset
902 {
kono
parents:
diff changeset
903 size_t i;
kono
parents:
diff changeset
904 size_t nargs = m_expr.ops.call.nargs;
kono
parents:
diff changeset
905 gcall *fn_from;
kono
parents:
diff changeset
906
kono
parents:
diff changeset
907 fn_from = m_expr.ops.call.fn_from;
kono
parents:
diff changeset
908 if (gimple_call_internal_p (fn_from))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
909 fprintf (stream, ".%s",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
910 internal_fn_name (gimple_call_internal_fn (fn_from)));
111
kono
parents:
diff changeset
911 else
kono
parents:
diff changeset
912 print_generic_expr (stream, gimple_call_fn (fn_from));
kono
parents:
diff changeset
913 fprintf (stream, " (");
kono
parents:
diff changeset
914 for (i = 0; i < nargs; i++)
kono
parents:
diff changeset
915 {
kono
parents:
diff changeset
916 print_generic_expr (stream, m_expr.ops.call.args[i]);
kono
parents:
diff changeset
917 if (i + 1 < nargs)
kono
parents:
diff changeset
918 fprintf (stream, ", ");
kono
parents:
diff changeset
919 }
kono
parents:
diff changeset
920 fprintf (stream, ")");
kono
parents:
diff changeset
921 }
kono
parents:
diff changeset
922 break;
kono
parents:
diff changeset
923
kono
parents:
diff changeset
924 case EXPR_PHI:
kono
parents:
diff changeset
925 {
kono
parents:
diff changeset
926 size_t i;
kono
parents:
diff changeset
927 size_t nargs = m_expr.ops.phi.nargs;
kono
parents:
diff changeset
928
kono
parents:
diff changeset
929 fprintf (stream, "PHI <");
kono
parents:
diff changeset
930 for (i = 0; i < nargs; i++)
kono
parents:
diff changeset
931 {
kono
parents:
diff changeset
932 print_generic_expr (stream, m_expr.ops.phi.args[i]);
kono
parents:
diff changeset
933 if (i + 1 < nargs)
kono
parents:
diff changeset
934 fprintf (stream, ", ");
kono
parents:
diff changeset
935 }
kono
parents:
diff changeset
936 fprintf (stream, ">");
kono
parents:
diff changeset
937 }
kono
parents:
diff changeset
938 break;
kono
parents:
diff changeset
939 }
kono
parents:
diff changeset
940
kono
parents:
diff changeset
941 if (m_vop)
kono
parents:
diff changeset
942 {
kono
parents:
diff changeset
943 fprintf (stream, " with ");
kono
parents:
diff changeset
944 print_generic_expr (stream, m_vop);
kono
parents:
diff changeset
945 }
kono
parents:
diff changeset
946
kono
parents:
diff changeset
947 fprintf (stream, "\n");
kono
parents:
diff changeset
948 }
kono
parents:
diff changeset
949
kono
parents:
diff changeset
950 /* Pop entries off the stack until we hit the NULL marker.
kono
parents:
diff changeset
951 For each entry popped, use the SRC/DEST pair to restore
kono
parents:
diff changeset
952 SRC to its prior value. */
kono
parents:
diff changeset
953
kono
parents:
diff changeset
954 void
kono
parents:
diff changeset
955 const_and_copies::pop_to_marker (void)
kono
parents:
diff changeset
956 {
kono
parents:
diff changeset
957 while (m_stack.length () > 0)
kono
parents:
diff changeset
958 {
kono
parents:
diff changeset
959 tree prev_value, dest;
kono
parents:
diff changeset
960
kono
parents:
diff changeset
961 dest = m_stack.pop ();
kono
parents:
diff changeset
962
kono
parents:
diff changeset
963 /* A NULL value indicates we should stop unwinding, otherwise
kono
parents:
diff changeset
964 pop off the next entry as they're recorded in pairs. */
kono
parents:
diff changeset
965 if (dest == NULL)
kono
parents:
diff changeset
966 break;
kono
parents:
diff changeset
967
kono
parents:
diff changeset
968 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
969 {
kono
parents:
diff changeset
970 fprintf (dump_file, "<<<< COPY ");
kono
parents:
diff changeset
971 print_generic_expr (dump_file, dest);
kono
parents:
diff changeset
972 fprintf (dump_file, " = ");
kono
parents:
diff changeset
973 print_generic_expr (dump_file, SSA_NAME_VALUE (dest));
kono
parents:
diff changeset
974 fprintf (dump_file, "\n");
kono
parents:
diff changeset
975 }
kono
parents:
diff changeset
976
kono
parents:
diff changeset
977 prev_value = m_stack.pop ();
kono
parents:
diff changeset
978 set_ssa_name_value (dest, prev_value);
kono
parents:
diff changeset
979 }
kono
parents:
diff changeset
980 }
kono
parents:
diff changeset
981
kono
parents:
diff changeset
982 /* Record that X has the value Y and that X's previous value is PREV_X.
kono
parents:
diff changeset
983
kono
parents:
diff changeset
984 This variant does not follow the value chain for Y. */
kono
parents:
diff changeset
985
kono
parents:
diff changeset
986 void
kono
parents:
diff changeset
987 const_and_copies::record_const_or_copy_raw (tree x, tree y, tree prev_x)
kono
parents:
diff changeset
988 {
kono
parents:
diff changeset
989 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
990 {
kono
parents:
diff changeset
991 fprintf (dump_file, "0>>> COPY ");
kono
parents:
diff changeset
992 print_generic_expr (dump_file, x);
kono
parents:
diff changeset
993 fprintf (dump_file, " = ");
kono
parents:
diff changeset
994 print_generic_expr (dump_file, y);
kono
parents:
diff changeset
995 fprintf (dump_file, "\n");
kono
parents:
diff changeset
996 }
kono
parents:
diff changeset
997
kono
parents:
diff changeset
998 set_ssa_name_value (x, y);
kono
parents:
diff changeset
999 m_stack.reserve (2);
kono
parents:
diff changeset
1000 m_stack.quick_push (prev_x);
kono
parents:
diff changeset
1001 m_stack.quick_push (x);
kono
parents:
diff changeset
1002 }
kono
parents:
diff changeset
1003
kono
parents:
diff changeset
1004 /* Record that X has the value Y. */
kono
parents:
diff changeset
1005
kono
parents:
diff changeset
1006 void
kono
parents:
diff changeset
1007 const_and_copies::record_const_or_copy (tree x, tree y)
kono
parents:
diff changeset
1008 {
kono
parents:
diff changeset
1009 record_const_or_copy (x, y, SSA_NAME_VALUE (x));
kono
parents:
diff changeset
1010 }
kono
parents:
diff changeset
1011
kono
parents:
diff changeset
1012 /* Record that X has the value Y and that X's previous value is PREV_X.
kono
parents:
diff changeset
1013
kono
parents:
diff changeset
1014 This variant follow's Y value chain. */
kono
parents:
diff changeset
1015
kono
parents:
diff changeset
1016 void
kono
parents:
diff changeset
1017 const_and_copies::record_const_or_copy (tree x, tree y, tree prev_x)
kono
parents:
diff changeset
1018 {
kono
parents:
diff changeset
1019 /* Y may be NULL if we are invalidating entries in the table. */
kono
parents:
diff changeset
1020 if (y && TREE_CODE (y) == SSA_NAME)
kono
parents:
diff changeset
1021 {
kono
parents:
diff changeset
1022 tree tmp = SSA_NAME_VALUE (y);
kono
parents:
diff changeset
1023 y = tmp ? tmp : y;
kono
parents:
diff changeset
1024 }
kono
parents:
diff changeset
1025
kono
parents:
diff changeset
1026 record_const_or_copy_raw (x, y, prev_x);
kono
parents:
diff changeset
1027 }
kono
parents:
diff changeset
1028
kono
parents:
diff changeset
1029 bool
kono
parents:
diff changeset
1030 expr_elt_hasher::equal (const value_type &p1, const compare_type &p2)
kono
parents:
diff changeset
1031 {
kono
parents:
diff changeset
1032 const struct hashable_expr *expr1 = p1->expr ();
kono
parents:
diff changeset
1033 const struct expr_hash_elt *stamp1 = p1->stamp ();
kono
parents:
diff changeset
1034 const struct hashable_expr *expr2 = p2->expr ();
kono
parents:
diff changeset
1035 const struct expr_hash_elt *stamp2 = p2->stamp ();
kono
parents:
diff changeset
1036
kono
parents:
diff changeset
1037 /* This case should apply only when removing entries from the table. */
kono
parents:
diff changeset
1038 if (stamp1 == stamp2)
kono
parents:
diff changeset
1039 return true;
kono
parents:
diff changeset
1040
kono
parents:
diff changeset
1041 if (p1->hash () != p2->hash ())
kono
parents:
diff changeset
1042 return false;
kono
parents:
diff changeset
1043
kono
parents:
diff changeset
1044 /* In case of a collision, both RHS have to be identical and have the
kono
parents:
diff changeset
1045 same VUSE operands. */
kono
parents:
diff changeset
1046 if (hashable_expr_equal_p (expr1, expr2)
kono
parents:
diff changeset
1047 && types_compatible_p (expr1->type, expr2->type))
kono
parents:
diff changeset
1048 return true;
kono
parents:
diff changeset
1049
kono
parents:
diff changeset
1050 return false;
kono
parents:
diff changeset
1051 }
kono
parents:
diff changeset
1052
kono
parents:
diff changeset
1053 /* Given a conditional expression COND as a tree, initialize
kono
parents:
diff changeset
1054 a hashable_expr expression EXPR. The conditional must be a
kono
parents:
diff changeset
1055 comparison or logical negation. A constant or a variable is
kono
parents:
diff changeset
1056 not permitted. */
kono
parents:
diff changeset
1057
kono
parents:
diff changeset
1058 void
kono
parents:
diff changeset
1059 initialize_expr_from_cond (tree cond, struct hashable_expr *expr)
kono
parents:
diff changeset
1060 {
kono
parents:
diff changeset
1061 expr->type = boolean_type_node;
kono
parents:
diff changeset
1062
kono
parents:
diff changeset
1063 if (COMPARISON_CLASS_P (cond))
kono
parents:
diff changeset
1064 {
kono
parents:
diff changeset
1065 expr->kind = EXPR_BINARY;
kono
parents:
diff changeset
1066 expr->ops.binary.op = TREE_CODE (cond);
kono
parents:
diff changeset
1067 expr->ops.binary.opnd0 = TREE_OPERAND (cond, 0);
kono
parents:
diff changeset
1068 expr->ops.binary.opnd1 = TREE_OPERAND (cond, 1);
kono
parents:
diff changeset
1069 }
kono
parents:
diff changeset
1070 else if (TREE_CODE (cond) == TRUTH_NOT_EXPR)
kono
parents:
diff changeset
1071 {
kono
parents:
diff changeset
1072 expr->kind = EXPR_UNARY;
kono
parents:
diff changeset
1073 expr->ops.unary.op = TRUTH_NOT_EXPR;
kono
parents:
diff changeset
1074 expr->ops.unary.opnd = TREE_OPERAND (cond, 0);
kono
parents:
diff changeset
1075 }
kono
parents:
diff changeset
1076 else
kono
parents:
diff changeset
1077 gcc_unreachable ();
kono
parents:
diff changeset
1078 }
kono
parents:
diff changeset
1079
kono
parents:
diff changeset
1080 /* Build a cond_equivalence record indicating that the comparison
kono
parents:
diff changeset
1081 CODE holds between operands OP0 and OP1 and push it to **P. */
kono
parents:
diff changeset
1082
kono
parents:
diff changeset
1083 static void
kono
parents:
diff changeset
1084 build_and_record_new_cond (enum tree_code code,
kono
parents:
diff changeset
1085 tree op0, tree op1,
kono
parents:
diff changeset
1086 vec<cond_equivalence> *p,
kono
parents:
diff changeset
1087 bool val = true)
kono
parents:
diff changeset
1088 {
kono
parents:
diff changeset
1089 cond_equivalence c;
kono
parents:
diff changeset
1090 struct hashable_expr *cond = &c.cond;
kono
parents:
diff changeset
1091
kono
parents:
diff changeset
1092 gcc_assert (TREE_CODE_CLASS (code) == tcc_comparison);
kono
parents:
diff changeset
1093
kono
parents:
diff changeset
1094 cond->type = boolean_type_node;
kono
parents:
diff changeset
1095 cond->kind = EXPR_BINARY;
kono
parents:
diff changeset
1096 cond->ops.binary.op = code;
kono
parents:
diff changeset
1097 cond->ops.binary.opnd0 = op0;
kono
parents:
diff changeset
1098 cond->ops.binary.opnd1 = op1;
kono
parents:
diff changeset
1099
kono
parents:
diff changeset
1100 c.value = val ? boolean_true_node : boolean_false_node;
kono
parents:
diff changeset
1101 p->safe_push (c);
kono
parents:
diff changeset
1102 }
kono
parents:
diff changeset
1103
kono
parents:
diff changeset
1104 /* Record that COND is true and INVERTED is false into the edge information
kono
parents:
diff changeset
1105 structure. Also record that any conditions dominated by COND are true
kono
parents:
diff changeset
1106 as well.
kono
parents:
diff changeset
1107
kono
parents:
diff changeset
1108 For example, if a < b is true, then a <= b must also be true. */
kono
parents:
diff changeset
1109
kono
parents:
diff changeset
1110 void
kono
parents:
diff changeset
1111 record_conditions (vec<cond_equivalence> *p, tree cond, tree inverted)
kono
parents:
diff changeset
1112 {
kono
parents:
diff changeset
1113 tree op0, op1;
kono
parents:
diff changeset
1114 cond_equivalence c;
kono
parents:
diff changeset
1115
kono
parents:
diff changeset
1116 if (!COMPARISON_CLASS_P (cond))
kono
parents:
diff changeset
1117 return;
kono
parents:
diff changeset
1118
kono
parents:
diff changeset
1119 op0 = TREE_OPERAND (cond, 0);
kono
parents:
diff changeset
1120 op1 = TREE_OPERAND (cond, 1);
kono
parents:
diff changeset
1121
kono
parents:
diff changeset
1122 switch (TREE_CODE (cond))
kono
parents:
diff changeset
1123 {
kono
parents:
diff changeset
1124 case LT_EXPR:
kono
parents:
diff changeset
1125 case GT_EXPR:
kono
parents:
diff changeset
1126 if (FLOAT_TYPE_P (TREE_TYPE (op0)))
kono
parents:
diff changeset
1127 {
kono
parents:
diff changeset
1128 build_and_record_new_cond (ORDERED_EXPR, op0, op1, p);
kono
parents:
diff changeset
1129 build_and_record_new_cond (LTGT_EXPR, op0, op1, p);
kono
parents:
diff changeset
1130 }
kono
parents:
diff changeset
1131
kono
parents:
diff changeset
1132 build_and_record_new_cond ((TREE_CODE (cond) == LT_EXPR
kono
parents:
diff changeset
1133 ? LE_EXPR : GE_EXPR),
kono
parents:
diff changeset
1134 op0, op1, p);
kono
parents:
diff changeset
1135 build_and_record_new_cond (NE_EXPR, op0, op1, p);
kono
parents:
diff changeset
1136 build_and_record_new_cond (EQ_EXPR, op0, op1, p, false);
kono
parents:
diff changeset
1137 break;
kono
parents:
diff changeset
1138
kono
parents:
diff changeset
1139 case GE_EXPR:
kono
parents:
diff changeset
1140 case LE_EXPR:
kono
parents:
diff changeset
1141 if (FLOAT_TYPE_P (TREE_TYPE (op0)))
kono
parents:
diff changeset
1142 {
kono
parents:
diff changeset
1143 build_and_record_new_cond (ORDERED_EXPR, op0, op1, p);
kono
parents:
diff changeset
1144 }
kono
parents:
diff changeset
1145 break;
kono
parents:
diff changeset
1146
kono
parents:
diff changeset
1147 case EQ_EXPR:
kono
parents:
diff changeset
1148 if (FLOAT_TYPE_P (TREE_TYPE (op0)))
kono
parents:
diff changeset
1149 {
kono
parents:
diff changeset
1150 build_and_record_new_cond (ORDERED_EXPR, op0, op1, p);
kono
parents:
diff changeset
1151 }
kono
parents:
diff changeset
1152 build_and_record_new_cond (LE_EXPR, op0, op1, p);
kono
parents:
diff changeset
1153 build_and_record_new_cond (GE_EXPR, op0, op1, p);
kono
parents:
diff changeset
1154 break;
kono
parents:
diff changeset
1155
kono
parents:
diff changeset
1156 case UNORDERED_EXPR:
kono
parents:
diff changeset
1157 build_and_record_new_cond (NE_EXPR, op0, op1, p);
kono
parents:
diff changeset
1158 build_and_record_new_cond (UNLE_EXPR, op0, op1, p);
kono
parents:
diff changeset
1159 build_and_record_new_cond (UNGE_EXPR, op0, op1, p);
kono
parents:
diff changeset
1160 build_and_record_new_cond (UNEQ_EXPR, op0, op1, p);
kono
parents:
diff changeset
1161 build_and_record_new_cond (UNLT_EXPR, op0, op1, p);
kono
parents:
diff changeset
1162 build_and_record_new_cond (UNGT_EXPR, op0, op1, p);
kono
parents:
diff changeset
1163 break;
kono
parents:
diff changeset
1164
kono
parents:
diff changeset
1165 case UNLT_EXPR:
kono
parents:
diff changeset
1166 case UNGT_EXPR:
kono
parents:
diff changeset
1167 build_and_record_new_cond ((TREE_CODE (cond) == UNLT_EXPR
kono
parents:
diff changeset
1168 ? UNLE_EXPR : UNGE_EXPR),
kono
parents:
diff changeset
1169 op0, op1, p);
kono
parents:
diff changeset
1170 build_and_record_new_cond (NE_EXPR, op0, op1, p);
kono
parents:
diff changeset
1171 break;
kono
parents:
diff changeset
1172
kono
parents:
diff changeset
1173 case UNEQ_EXPR:
kono
parents:
diff changeset
1174 build_and_record_new_cond (UNLE_EXPR, op0, op1, p);
kono
parents:
diff changeset
1175 build_and_record_new_cond (UNGE_EXPR, op0, op1, p);
kono
parents:
diff changeset
1176 break;
kono
parents:
diff changeset
1177
kono
parents:
diff changeset
1178 case LTGT_EXPR:
kono
parents:
diff changeset
1179 build_and_record_new_cond (NE_EXPR, op0, op1, p);
kono
parents:
diff changeset
1180 build_and_record_new_cond (ORDERED_EXPR, op0, op1, p);
kono
parents:
diff changeset
1181 break;
kono
parents:
diff changeset
1182
kono
parents:
diff changeset
1183 default:
kono
parents:
diff changeset
1184 break;
kono
parents:
diff changeset
1185 }
kono
parents:
diff changeset
1186
kono
parents:
diff changeset
1187 /* Now store the original true and false conditions into the first
kono
parents:
diff changeset
1188 two slots. */
kono
parents:
diff changeset
1189 initialize_expr_from_cond (cond, &c.cond);
kono
parents:
diff changeset
1190 c.value = boolean_true_node;
kono
parents:
diff changeset
1191 p->safe_push (c);
kono
parents:
diff changeset
1192
kono
parents:
diff changeset
1193 /* It is possible for INVERTED to be the negation of a comparison,
kono
parents:
diff changeset
1194 and not a valid RHS or GIMPLE_COND condition. This happens because
kono
parents:
diff changeset
1195 invert_truthvalue may return such an expression when asked to invert
kono
parents:
diff changeset
1196 a floating-point comparison. These comparisons are not assumed to
kono
parents:
diff changeset
1197 obey the trichotomy law. */
kono
parents:
diff changeset
1198 initialize_expr_from_cond (inverted, &c.cond);
kono
parents:
diff changeset
1199 c.value = boolean_false_node;
kono
parents:
diff changeset
1200 p->safe_push (c);
kono
parents:
diff changeset
1201 }