]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-ssa-scopedtables.c
* ira.c (ira): Update regstat data if we deleted insns.
[thirdparty/gcc.git] / gcc / tree-ssa-scopedtables.c
CommitLineData
545372c5 1/* Header file for SSA dominator optimizations.
f1717362 2 Copyright (C) 2013-2016 Free Software Foundation, Inc.
545372c5 3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
7c29e30e 23#include "function.h"
24#include "basic-block.h"
545372c5 25#include "tree.h"
7c29e30e 26#include "gimple.h"
545372c5 27#include "tree-pass.h"
7c29e30e 28#include "tree-pretty-print.h"
545372c5 29#include "tree-ssa-scopedtables.h"
30#include "tree-ssa-threadedge.h"
3149d5c3 31#include "stor-layout.h"
32#include "fold-const.h"
3149d5c3 33#include "tree-eh.h"
34#include "internal-fn.h"
fa75ab55 35#include "tree-dfa.h"
3149d5c3 36
37static bool hashable_expr_equal_p (const struct hashable_expr *,
38 const struct hashable_expr *);
39
40/* Initialize local stacks for this optimizer and record equivalences
41 upon entry to BB. Equivalences can come from the edge traversed to
42 reach BB or they may come from PHI nodes at the start of BB. */
43
44/* Pop items off the unwinding stack, removing each from the hash table
45 until a marker is encountered. */
46
47void
48avail_exprs_stack::pop_to_marker ()
49{
50 /* Remove all the expressions made available in this block. */
51 while (m_stack.length () > 0)
52 {
53 std::pair<expr_hash_elt_t, expr_hash_elt_t> victim = m_stack.pop ();
54 expr_hash_elt **slot;
55
56 if (victim.first == NULL)
57 break;
58
59 /* This must precede the actual removal from the hash table,
60 as ELEMENT and the table entry may share a call argument
61 vector which will be freed during removal. */
62 if (dump_file && (dump_flags & TDF_DETAILS))
63 {
64 fprintf (dump_file, "<<<< ");
65 victim.first->print (dump_file);
66 }
67
68 slot = m_avail_exprs->find_slot (victim.first, NO_INSERT);
69 gcc_assert (slot && *slot == victim.first);
70 if (victim.second != NULL)
71 {
72 delete *slot;
73 *slot = victim.second;
74 }
75 else
76 m_avail_exprs->clear_slot (slot);
77 }
78}
79
80/* Add <ELT1,ELT2> to the unwinding stack so they can be later removed
81 from the hash table. */
82
83void
84avail_exprs_stack::record_expr (class expr_hash_elt *elt1,
85 class expr_hash_elt *elt2,
86 char type)
87{
88 if (elt1 && dump_file && (dump_flags & TDF_DETAILS))
89 {
90 fprintf (dump_file, "%c>>> ", type);
91 elt1->print (dump_file);
92 }
93
94 m_stack.safe_push (std::pair<expr_hash_elt_t, expr_hash_elt_t> (elt1, elt2));
95}
96
97/* Generate a hash value for a pair of expressions. This can be used
98 iteratively by passing a previous result in HSTATE.
99
100 The same hash value is always returned for a given pair of expressions,
101 regardless of the order in which they are presented. This is useful in
102 hashing the operands of commutative functions. */
103
104namespace inchash
105{
106
107static void
108add_expr_commutative (const_tree t1, const_tree t2, hash &hstate)
109{
110 hash one, two;
111
112 inchash::add_expr (t1, one);
113 inchash::add_expr (t2, two);
114 hstate.add_commutative (one, two);
115}
116
117/* Compute a hash value for a hashable_expr value EXPR and a
118 previously accumulated hash value VAL. If two hashable_expr
119 values compare equal with hashable_expr_equal_p, they must
120 hash to the same value, given an identical value of VAL.
121 The logic is intended to follow inchash::add_expr in tree.c. */
122
123static void
124add_hashable_expr (const struct hashable_expr *expr, hash &hstate)
125{
126 switch (expr->kind)
127 {
128 case EXPR_SINGLE:
129 inchash::add_expr (expr->ops.single.rhs, hstate);
130 break;
131
132 case EXPR_UNARY:
133 hstate.add_object (expr->ops.unary.op);
134
135 /* Make sure to include signedness in the hash computation.
136 Don't hash the type, that can lead to having nodes which
137 compare equal according to operand_equal_p, but which
138 have different hash codes. */
139 if (CONVERT_EXPR_CODE_P (expr->ops.unary.op)
140 || expr->ops.unary.op == NON_LVALUE_EXPR)
141 hstate.add_int (TYPE_UNSIGNED (expr->type));
142
143 inchash::add_expr (expr->ops.unary.opnd, hstate);
144 break;
145
146 case EXPR_BINARY:
147 hstate.add_object (expr->ops.binary.op);
148 if (commutative_tree_code (expr->ops.binary.op))
149 inchash::add_expr_commutative (expr->ops.binary.opnd0,
150 expr->ops.binary.opnd1, hstate);
151 else
152 {
153 inchash::add_expr (expr->ops.binary.opnd0, hstate);
154 inchash::add_expr (expr->ops.binary.opnd1, hstate);
155 }
156 break;
157
158 case EXPR_TERNARY:
159 hstate.add_object (expr->ops.ternary.op);
160 if (commutative_ternary_tree_code (expr->ops.ternary.op))
161 inchash::add_expr_commutative (expr->ops.ternary.opnd0,
162 expr->ops.ternary.opnd1, hstate);
163 else
164 {
165 inchash::add_expr (expr->ops.ternary.opnd0, hstate);
166 inchash::add_expr (expr->ops.ternary.opnd1, hstate);
167 }
168 inchash::add_expr (expr->ops.ternary.opnd2, hstate);
169 break;
170
171 case EXPR_CALL:
172 {
173 size_t i;
174 enum tree_code code = CALL_EXPR;
175 gcall *fn_from;
176
177 hstate.add_object (code);
178 fn_from = expr->ops.call.fn_from;
179 if (gimple_call_internal_p (fn_from))
180 hstate.merge_hash ((hashval_t) gimple_call_internal_fn (fn_from));
181 else
182 inchash::add_expr (gimple_call_fn (fn_from), hstate);
183 for (i = 0; i < expr->ops.call.nargs; i++)
184 inchash::add_expr (expr->ops.call.args[i], hstate);
185 }
186 break;
187
188 case EXPR_PHI:
189 {
190 size_t i;
191
192 for (i = 0; i < expr->ops.phi.nargs; i++)
193 inchash::add_expr (expr->ops.phi.args[i], hstate);
194 }
195 break;
196
197 default:
198 gcc_unreachable ();
199 }
200}
201
202}
203
204/* Hashing and equality functions. We compute a value number for expressions
205 using the code of the expression and the SSA numbers of its operands. */
206
207static hashval_t
208avail_expr_hash (class expr_hash_elt *p)
209{
210 const struct hashable_expr *expr = p->expr ();
211 inchash::hash hstate;
212
fa75ab55 213 if (expr->kind == EXPR_SINGLE)
214 {
215 /* T could potentially be a switch index or a goto dest. */
216 tree t = expr->ops.single.rhs;
217 if (TREE_CODE (t) == MEM_REF || TREE_CODE (t) == ARRAY_REF)
218 {
219 /* Make equivalent statements of both these kinds hash together.
220 Dealing with both MEM_REF and ARRAY_REF allows us not to care
221 about equivalence with other statements not considered here. */
222 bool reverse;
223 HOST_WIDE_INT offset, size, max_size;
224 tree base = get_ref_base_and_extent (t, &offset, &size, &max_size,
225 &reverse);
226 /* Strictly, we could try to normalize variable-sized accesses too,
227 but here we just deal with the common case. */
228 if (size == max_size)
229 {
230 enum tree_code code = MEM_REF;
231 hstate.add_object (code);
232 inchash::add_expr (base, hstate);
233 hstate.add_object (offset);
234 hstate.add_object (size);
235 return hstate.end ();
236 }
237 }
238 }
239
3149d5c3 240 inchash::add_hashable_expr (expr, hstate);
241
242 return hstate.end ();
243}
244
fa75ab55 245/* Compares trees T0 and T1 to see if they are MEM_REF or ARRAY_REFs equivalent
246 to each other. (That is, they return the value of the same bit of memory.)
247
248 Return TRUE if the two are so equivalent; FALSE if not (which could still
249 mean the two are equivalent by other means). */
250
251static bool
252equal_mem_array_ref_p (tree t0, tree t1)
253{
254 if (TREE_CODE (t0) != MEM_REF && TREE_CODE (t0) != ARRAY_REF)
255 return false;
256 if (TREE_CODE (t1) != MEM_REF && TREE_CODE (t1) != ARRAY_REF)
257 return false;
258
259 if (!types_compatible_p (TREE_TYPE (t0), TREE_TYPE (t1)))
260 return false;
261 bool rev0;
262 HOST_WIDE_INT off0, sz0, max0;
263 tree base0 = get_ref_base_and_extent (t0, &off0, &sz0, &max0, &rev0);
264
265 bool rev1;
266 HOST_WIDE_INT off1, sz1, max1;
267 tree base1 = get_ref_base_and_extent (t1, &off1, &sz1, &max1, &rev1);
268
269 /* Types were compatible, so these are sanity checks. */
270 gcc_assert (sz0 == sz1);
271 gcc_assert (max0 == max1);
272 gcc_assert (rev0 == rev1);
273
274 return (off0 == off1) && operand_equal_p (base0, base1, 0);
275}
276
3149d5c3 277/* Compare two hashable_expr structures for equivalence. They are
278 considered equivalent when the expressions they denote must
279 necessarily be equal. The logic is intended to follow that of
280 operand_equal_p in fold-const.c */
281
282static bool
283hashable_expr_equal_p (const struct hashable_expr *expr0,
284 const struct hashable_expr *expr1)
285{
286 tree type0 = expr0->type;
287 tree type1 = expr1->type;
288
289 /* If either type is NULL, there is nothing to check. */
290 if ((type0 == NULL_TREE) ^ (type1 == NULL_TREE))
291 return false;
292
293 /* If both types don't have the same signedness, precision, and mode,
294 then we can't consider them equal. */
295 if (type0 != type1
296 && (TREE_CODE (type0) == ERROR_MARK
297 || TREE_CODE (type1) == ERROR_MARK
298 || TYPE_UNSIGNED (type0) != TYPE_UNSIGNED (type1)
299 || TYPE_PRECISION (type0) != TYPE_PRECISION (type1)
300 || TYPE_MODE (type0) != TYPE_MODE (type1)))
301 return false;
302
303 if (expr0->kind != expr1->kind)
304 return false;
305
306 switch (expr0->kind)
307 {
308 case EXPR_SINGLE:
fa75ab55 309 return equal_mem_array_ref_p (expr0->ops.single.rhs,
310 expr1->ops.single.rhs)
311 || operand_equal_p (expr0->ops.single.rhs,
312 expr1->ops.single.rhs, 0);
3149d5c3 313 case EXPR_UNARY:
314 if (expr0->ops.unary.op != expr1->ops.unary.op)
315 return false;
316
317 if ((CONVERT_EXPR_CODE_P (expr0->ops.unary.op)
318 || expr0->ops.unary.op == NON_LVALUE_EXPR)
319 && TYPE_UNSIGNED (expr0->type) != TYPE_UNSIGNED (expr1->type))
320 return false;
321
322 return operand_equal_p (expr0->ops.unary.opnd,
323 expr1->ops.unary.opnd, 0);
324
325 case EXPR_BINARY:
326 if (expr0->ops.binary.op != expr1->ops.binary.op)
327 return false;
328
329 if (operand_equal_p (expr0->ops.binary.opnd0,
330 expr1->ops.binary.opnd0, 0)
331 && operand_equal_p (expr0->ops.binary.opnd1,
332 expr1->ops.binary.opnd1, 0))
333 return true;
334
335 /* For commutative ops, allow the other order. */
336 return (commutative_tree_code (expr0->ops.binary.op)
337 && operand_equal_p (expr0->ops.binary.opnd0,
338 expr1->ops.binary.opnd1, 0)
339 && operand_equal_p (expr0->ops.binary.opnd1,
340 expr1->ops.binary.opnd0, 0));
341
342 case EXPR_TERNARY:
343 if (expr0->ops.ternary.op != expr1->ops.ternary.op
344 || !operand_equal_p (expr0->ops.ternary.opnd2,
345 expr1->ops.ternary.opnd2, 0))
346 return false;
347
348 if (operand_equal_p (expr0->ops.ternary.opnd0,
349 expr1->ops.ternary.opnd0, 0)
350 && operand_equal_p (expr0->ops.ternary.opnd1,
351 expr1->ops.ternary.opnd1, 0))
352 return true;
353
354 /* For commutative ops, allow the other order. */
355 return (commutative_ternary_tree_code (expr0->ops.ternary.op)
356 && operand_equal_p (expr0->ops.ternary.opnd0,
357 expr1->ops.ternary.opnd1, 0)
358 && operand_equal_p (expr0->ops.ternary.opnd1,
359 expr1->ops.ternary.opnd0, 0));
360
361 case EXPR_CALL:
362 {
363 size_t i;
364
365 /* If the calls are to different functions, then they
366 clearly cannot be equal. */
367 if (!gimple_call_same_target_p (expr0->ops.call.fn_from,
368 expr1->ops.call.fn_from))
369 return false;
370
371 if (! expr0->ops.call.pure)
372 return false;
373
374 if (expr0->ops.call.nargs != expr1->ops.call.nargs)
375 return false;
376
377 for (i = 0; i < expr0->ops.call.nargs; i++)
378 if (! operand_equal_p (expr0->ops.call.args[i],
379 expr1->ops.call.args[i], 0))
380 return false;
381
382 if (stmt_could_throw_p (expr0->ops.call.fn_from))
383 {
384 int lp0 = lookup_stmt_eh_lp (expr0->ops.call.fn_from);
385 int lp1 = lookup_stmt_eh_lp (expr1->ops.call.fn_from);
386 if ((lp0 > 0 || lp1 > 0) && lp0 != lp1)
387 return false;
388 }
389
390 return true;
391 }
392
393 case EXPR_PHI:
394 {
395 size_t i;
396
397 if (expr0->ops.phi.nargs != expr1->ops.phi.nargs)
398 return false;
399
400 for (i = 0; i < expr0->ops.phi.nargs; i++)
401 if (! operand_equal_p (expr0->ops.phi.args[i],
402 expr1->ops.phi.args[i], 0))
403 return false;
404
405 return true;
406 }
407
408 default:
409 gcc_unreachable ();
410 }
411}
412
413/* Given a statement STMT, construct a hash table element. */
414
42acab1c 415expr_hash_elt::expr_hash_elt (gimple *stmt, tree orig_lhs)
3149d5c3 416{
417 enum gimple_code code = gimple_code (stmt);
418 struct hashable_expr *expr = this->expr ();
419
420 if (code == GIMPLE_ASSIGN)
421 {
422 enum tree_code subcode = gimple_assign_rhs_code (stmt);
423
424 switch (get_gimple_rhs_class (subcode))
425 {
426 case GIMPLE_SINGLE_RHS:
427 expr->kind = EXPR_SINGLE;
428 expr->type = TREE_TYPE (gimple_assign_rhs1 (stmt));
429 expr->ops.single.rhs = gimple_assign_rhs1 (stmt);
430 break;
431 case GIMPLE_UNARY_RHS:
432 expr->kind = EXPR_UNARY;
433 expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
434 if (CONVERT_EXPR_CODE_P (subcode))
435 subcode = NOP_EXPR;
436 expr->ops.unary.op = subcode;
437 expr->ops.unary.opnd = gimple_assign_rhs1 (stmt);
438 break;
439 case GIMPLE_BINARY_RHS:
440 expr->kind = EXPR_BINARY;
441 expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
442 expr->ops.binary.op = subcode;
443 expr->ops.binary.opnd0 = gimple_assign_rhs1 (stmt);
444 expr->ops.binary.opnd1 = gimple_assign_rhs2 (stmt);
445 break;
446 case GIMPLE_TERNARY_RHS:
447 expr->kind = EXPR_TERNARY;
448 expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
449 expr->ops.ternary.op = subcode;
450 expr->ops.ternary.opnd0 = gimple_assign_rhs1 (stmt);
451 expr->ops.ternary.opnd1 = gimple_assign_rhs2 (stmt);
452 expr->ops.ternary.opnd2 = gimple_assign_rhs3 (stmt);
453 break;
454 default:
455 gcc_unreachable ();
456 }
457 }
458 else if (code == GIMPLE_COND)
459 {
460 expr->type = boolean_type_node;
461 expr->kind = EXPR_BINARY;
462 expr->ops.binary.op = gimple_cond_code (stmt);
463 expr->ops.binary.opnd0 = gimple_cond_lhs (stmt);
464 expr->ops.binary.opnd1 = gimple_cond_rhs (stmt);
465 }
466 else if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
467 {
468 size_t nargs = gimple_call_num_args (call_stmt);
469 size_t i;
470
471 gcc_assert (gimple_call_lhs (call_stmt));
472
473 expr->type = TREE_TYPE (gimple_call_lhs (call_stmt));
474 expr->kind = EXPR_CALL;
475 expr->ops.call.fn_from = call_stmt;
476
477 if (gimple_call_flags (call_stmt) & (ECF_CONST | ECF_PURE))
478 expr->ops.call.pure = true;
479 else
480 expr->ops.call.pure = false;
481
482 expr->ops.call.nargs = nargs;
483 expr->ops.call.args = XCNEWVEC (tree, nargs);
484 for (i = 0; i < nargs; i++)
485 expr->ops.call.args[i] = gimple_call_arg (call_stmt, i);
486 }
487 else if (gswitch *swtch_stmt = dyn_cast <gswitch *> (stmt))
488 {
489 expr->type = TREE_TYPE (gimple_switch_index (swtch_stmt));
490 expr->kind = EXPR_SINGLE;
491 expr->ops.single.rhs = gimple_switch_index (swtch_stmt);
492 }
493 else if (code == GIMPLE_GOTO)
494 {
495 expr->type = TREE_TYPE (gimple_goto_dest (stmt));
496 expr->kind = EXPR_SINGLE;
497 expr->ops.single.rhs = gimple_goto_dest (stmt);
498 }
499 else if (code == GIMPLE_PHI)
500 {
501 size_t nargs = gimple_phi_num_args (stmt);
502 size_t i;
503
504 expr->type = TREE_TYPE (gimple_phi_result (stmt));
505 expr->kind = EXPR_PHI;
506 expr->ops.phi.nargs = nargs;
507 expr->ops.phi.args = XCNEWVEC (tree, nargs);
508 for (i = 0; i < nargs; i++)
509 expr->ops.phi.args[i] = gimple_phi_arg_def (stmt, i);
510 }
511 else
512 gcc_unreachable ();
513
514 m_lhs = orig_lhs;
515 m_vop = gimple_vuse (stmt);
516 m_hash = avail_expr_hash (this);
517 m_stamp = this;
518}
519
520/* Given a hashable_expr expression ORIG and an ORIG_LHS,
521 construct a hash table element. */
522
523expr_hash_elt::expr_hash_elt (struct hashable_expr *orig, tree orig_lhs)
524{
525 m_expr = *orig;
526 m_lhs = orig_lhs;
527 m_vop = NULL_TREE;
528 m_hash = avail_expr_hash (this);
529 m_stamp = this;
530}
531
532/* Copy constructor for a hash table element. */
533
534expr_hash_elt::expr_hash_elt (class expr_hash_elt &old_elt)
535{
536 m_expr = old_elt.m_expr;
537 m_lhs = old_elt.m_lhs;
538 m_vop = old_elt.m_vop;
539 m_hash = old_elt.m_hash;
540 m_stamp = this;
541
542 /* Now deep copy the malloc'd space for CALL and PHI args. */
543 if (old_elt.m_expr.kind == EXPR_CALL)
544 {
545 size_t nargs = old_elt.m_expr.ops.call.nargs;
546 size_t i;
547
548 m_expr.ops.call.args = XCNEWVEC (tree, nargs);
549 for (i = 0; i < nargs; i++)
550 m_expr.ops.call.args[i] = old_elt.m_expr.ops.call.args[i];
551 }
552 else if (old_elt.m_expr.kind == EXPR_PHI)
553 {
554 size_t nargs = old_elt.m_expr.ops.phi.nargs;
555 size_t i;
556
557 m_expr.ops.phi.args = XCNEWVEC (tree, nargs);
558 for (i = 0; i < nargs; i++)
559 m_expr.ops.phi.args[i] = old_elt.m_expr.ops.phi.args[i];
560 }
561}
562
563/* Calls and PHIs have a variable number of arguments that are allocated
564 on the heap. Thus we have to have a special dtor to release them. */
565
566expr_hash_elt::~expr_hash_elt ()
567{
568 if (m_expr.kind == EXPR_CALL)
569 free (m_expr.ops.call.args);
570 else if (m_expr.kind == EXPR_PHI)
571 free (m_expr.ops.phi.args);
572}
573
574/* Print a diagnostic dump of an expression hash table entry. */
575
576void
577expr_hash_elt::print (FILE *stream)
578{
579 fprintf (stream, "STMT ");
580
581 if (m_lhs)
582 {
583 print_generic_expr (stream, m_lhs, 0);
584 fprintf (stream, " = ");
585 }
586
587 switch (m_expr.kind)
588 {
589 case EXPR_SINGLE:
590 print_generic_expr (stream, m_expr.ops.single.rhs, 0);
591 break;
592
593 case EXPR_UNARY:
594 fprintf (stream, "%s ", get_tree_code_name (m_expr.ops.unary.op));
595 print_generic_expr (stream, m_expr.ops.unary.opnd, 0);
596 break;
597
598 case EXPR_BINARY:
599 print_generic_expr (stream, m_expr.ops.binary.opnd0, 0);
600 fprintf (stream, " %s ", get_tree_code_name (m_expr.ops.binary.op));
601 print_generic_expr (stream, m_expr.ops.binary.opnd1, 0);
602 break;
603
604 case EXPR_TERNARY:
605 fprintf (stream, " %s <", get_tree_code_name (m_expr.ops.ternary.op));
606 print_generic_expr (stream, m_expr.ops.ternary.opnd0, 0);
607 fputs (", ", stream);
608 print_generic_expr (stream, m_expr.ops.ternary.opnd1, 0);
609 fputs (", ", stream);
610 print_generic_expr (stream, m_expr.ops.ternary.opnd2, 0);
611 fputs (">", stream);
612 break;
613
614 case EXPR_CALL:
615 {
616 size_t i;
617 size_t nargs = m_expr.ops.call.nargs;
618 gcall *fn_from;
619
620 fn_from = m_expr.ops.call.fn_from;
621 if (gimple_call_internal_p (fn_from))
622 fputs (internal_fn_name (gimple_call_internal_fn (fn_from)),
623 stream);
624 else
625 print_generic_expr (stream, gimple_call_fn (fn_from), 0);
626 fprintf (stream, " (");
627 for (i = 0; i < nargs; i++)
628 {
629 print_generic_expr (stream, m_expr.ops.call.args[i], 0);
630 if (i + 1 < nargs)
631 fprintf (stream, ", ");
632 }
633 fprintf (stream, ")");
634 }
635 break;
636
637 case EXPR_PHI:
638 {
639 size_t i;
640 size_t nargs = m_expr.ops.phi.nargs;
641
642 fprintf (stream, "PHI <");
643 for (i = 0; i < nargs; i++)
644 {
645 print_generic_expr (stream, m_expr.ops.phi.args[i], 0);
646 if (i + 1 < nargs)
647 fprintf (stream, ", ");
648 }
649 fprintf (stream, ">");
650 }
651 break;
652 }
653
654 if (m_vop)
655 {
656 fprintf (stream, " with ");
657 print_generic_expr (stream, m_vop, 0);
658 }
659
660 fprintf (stream, "\n");
661}
545372c5 662
545372c5 663/* Pop entries off the stack until we hit the NULL marker.
664 For each entry popped, use the SRC/DEST pair to restore
665 SRC to its prior value. */
666
667void
668const_and_copies::pop_to_marker (void)
669{
01e56285 670 while (m_stack.length () > 0)
545372c5 671 {
672 tree prev_value, dest;
673
01e56285 674 dest = m_stack.pop ();
545372c5 675
676 /* A NULL value indicates we should stop unwinding, otherwise
677 pop off the next entry as they're recorded in pairs. */
678 if (dest == NULL)
679 break;
680
681 if (dump_file && (dump_flags & TDF_DETAILS))
682 {
683 fprintf (dump_file, "<<<< COPY ");
684 print_generic_expr (dump_file, dest, 0);
685 fprintf (dump_file, " = ");
686 print_generic_expr (dump_file, SSA_NAME_VALUE (dest), 0);
687 fprintf (dump_file, "\n");
688 }
689
01e56285 690 prev_value = m_stack.pop ();
545372c5 691 set_ssa_name_value (dest, prev_value);
692 }
693}
694
695/* Record that X has the value Y. */
696
697void
698const_and_copies::record_const_or_copy (tree x, tree y)
699{
700 record_const_or_copy (x, y, SSA_NAME_VALUE (x));
701}
702
703/* Record that X has the value Y and that X's previous value is PREV_X. */
704
705void
706const_and_copies::record_const_or_copy (tree x, tree y, tree prev_x)
707{
708 /* Y may be NULL if we are invalidating entries in the table. */
709 if (y && TREE_CODE (y) == SSA_NAME)
710 {
711 tree tmp = SSA_NAME_VALUE (y);
712 y = tmp ? tmp : y;
713 }
714
715 if (dump_file && (dump_flags & TDF_DETAILS))
716 {
717 fprintf (dump_file, "0>>> COPY ");
718 print_generic_expr (dump_file, x, 0);
719 fprintf (dump_file, " = ");
720 print_generic_expr (dump_file, y, 0);
721 fprintf (dump_file, "\n");
722 }
723
724 set_ssa_name_value (x, y);
01e56285 725 m_stack.reserve (2);
726 m_stack.quick_push (prev_x);
727 m_stack.quick_push (x);
545372c5 728}
729
3149d5c3 730bool
731expr_elt_hasher::equal (const value_type &p1, const compare_type &p2)
732{
733 const struct hashable_expr *expr1 = p1->expr ();
734 const struct expr_hash_elt *stamp1 = p1->stamp ();
735 const struct hashable_expr *expr2 = p2->expr ();
736 const struct expr_hash_elt *stamp2 = p2->stamp ();
737
738 /* This case should apply only when removing entries from the table. */
739 if (stamp1 == stamp2)
740 return true;
741
742 if (p1->hash () != p2->hash ())
743 return false;
744
745 /* In case of a collision, both RHS have to be identical and have the
746 same VUSE operands. */
747 if (hashable_expr_equal_p (expr1, expr2)
748 && types_compatible_p (expr1->type, expr2->type))
749 return true;
750
751 return false;
752}
753
754/* Given a conditional expression COND as a tree, initialize
755 a hashable_expr expression EXPR. The conditional must be a
756 comparison or logical negation. A constant or a variable is
757 not permitted. */
758
759void
760initialize_expr_from_cond (tree cond, struct hashable_expr *expr)
761{
762 expr->type = boolean_type_node;
763
764 if (COMPARISON_CLASS_P (cond))
765 {
766 expr->kind = EXPR_BINARY;
767 expr->ops.binary.op = TREE_CODE (cond);
768 expr->ops.binary.opnd0 = TREE_OPERAND (cond, 0);
769 expr->ops.binary.opnd1 = TREE_OPERAND (cond, 1);
770 }
771 else if (TREE_CODE (cond) == TRUTH_NOT_EXPR)
772 {
773 expr->kind = EXPR_UNARY;
774 expr->ops.unary.op = TRUTH_NOT_EXPR;
775 expr->ops.unary.opnd = TREE_OPERAND (cond, 0);
776 }
777 else
778 gcc_unreachable ();
779}
780