1 /* Header file for SSA dominator optimizations.
2 Copyright (C) 2013-2016 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
24 #include "basic-block.h"
27 #include "tree-pass.h"
28 #include "tree-pretty-print.h"
29 #include "tree-ssa-scopedtables.h"
30 #include "tree-ssa-threadedge.h"
31 #include "stor-layout.h"
32 #include "fold-const.h"
34 #include "internal-fn.h"
37 static bool hashable_expr_equal_p (const struct hashable_expr
*,
38 const struct hashable_expr
*);
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. */
44 /* Pop items off the unwinding stack, removing each from the hash table
45 until a marker is encountered. */
48 avail_exprs_stack::pop_to_marker ()
50 /* Remove all the expressions made available in this block. */
51 while (m_stack
.length () > 0)
53 std::pair
<expr_hash_elt_t
, expr_hash_elt_t
> victim
= m_stack
.pop ();
56 if (victim
.first
== NULL
)
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
))
64 fprintf (dump_file
, "<<<< ");
65 victim
.first
->print (dump_file
);
68 slot
= m_avail_exprs
->find_slot (victim
.first
, NO_INSERT
);
69 gcc_assert (slot
&& *slot
== victim
.first
);
70 if (victim
.second
!= NULL
)
73 *slot
= victim
.second
;
76 m_avail_exprs
->clear_slot (slot
);
80 /* Add <ELT1,ELT2> to the unwinding stack so they can be later removed
81 from the hash table. */
84 avail_exprs_stack::record_expr (class expr_hash_elt
*elt1
,
85 class expr_hash_elt
*elt2
,
88 if (elt1
&& dump_file
&& (dump_flags
& TDF_DETAILS
))
90 fprintf (dump_file
, "%c>>> ", type
);
91 elt1
->print (dump_file
);
94 m_stack
.safe_push (std::pair
<expr_hash_elt_t
, expr_hash_elt_t
> (elt1
, elt2
));
97 /* Generate a hash value for a pair of expressions. This can be used
98 iteratively by passing a previous result in HSTATE.
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. */
108 add_expr_commutative (const_tree t1
, const_tree t2
, hash
&hstate
)
112 inchash::add_expr (t1
, one
);
113 inchash::add_expr (t2
, two
);
114 hstate
.add_commutative (one
, two
);
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. */
124 add_hashable_expr (const struct hashable_expr
*expr
, hash
&hstate
)
129 inchash::add_expr (expr
->ops
.single
.rhs
, hstate
);
133 hstate
.add_object (expr
->ops
.unary
.op
);
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
));
143 inchash::add_expr (expr
->ops
.unary
.opnd
, hstate
);
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
);
153 inchash::add_expr (expr
->ops
.binary
.opnd0
, hstate
);
154 inchash::add_expr (expr
->ops
.binary
.opnd1
, hstate
);
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
);
165 inchash::add_expr (expr
->ops
.ternary
.opnd0
, hstate
);
166 inchash::add_expr (expr
->ops
.ternary
.opnd1
, hstate
);
168 inchash::add_expr (expr
->ops
.ternary
.opnd2
, hstate
);
174 enum tree_code code
= CALL_EXPR
;
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
));
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
);
192 for (i
= 0; i
< expr
->ops
.phi
.nargs
; i
++)
193 inchash::add_expr (expr
->ops
.phi
.args
[i
], hstate
);
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. */
208 avail_expr_hash (class expr_hash_elt
*p
)
210 const struct hashable_expr
*expr
= p
->expr ();
211 inchash::hash hstate
;
213 if (expr
->kind
== EXPR_SINGLE
)
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
|| handled_component_p (t
))
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. */
223 HOST_WIDE_INT offset
, size
, max_size
;
224 tree base
= get_ref_base_and_extent (t
, &offset
, &size
, &max_size
,
226 /* Strictly, we could try to normalize variable-sized accesses too,
227 but here we just deal with the common case. */
231 enum tree_code code
= MEM_REF
;
232 hstate
.add_object (code
);
233 inchash::add_expr (base
, hstate
);
234 hstate
.add_object (offset
);
235 hstate
.add_object (size
);
236 return hstate
.end ();
241 inchash::add_hashable_expr (expr
, hstate
);
243 return hstate
.end ();
246 /* Compares trees T0 and T1 to see if they are MEM_REF or ARRAY_REFs equivalent
247 to each other. (That is, they return the value of the same bit of memory.)
249 Return TRUE if the two are so equivalent; FALSE if not (which could still
250 mean the two are equivalent by other means). */
253 equal_mem_array_ref_p (tree t0
, tree t1
)
255 if (TREE_CODE (t0
) != MEM_REF
&& ! handled_component_p (t0
))
257 if (TREE_CODE (t1
) != MEM_REF
&& ! handled_component_p (t1
))
260 if (!types_compatible_p (TREE_TYPE (t0
), TREE_TYPE (t1
)))
263 HOST_WIDE_INT off0
, sz0
, max0
;
264 tree base0
= get_ref_base_and_extent (t0
, &off0
, &sz0
, &max0
, &rev0
);
270 HOST_WIDE_INT off1
, sz1
, max1
;
271 tree base1
= get_ref_base_and_extent (t1
, &off1
, &sz1
, &max1
, &rev1
);
279 /* Types were compatible, so this is a sanity check. */
280 gcc_assert (sz0
== sz1
);
282 return (off0
== off1
) && operand_equal_p (base0
, base1
, 0);
285 /* Compare two hashable_expr structures for equivalence. They are
286 considered equivalent when the expressions they denote must
287 necessarily be equal. The logic is intended to follow that of
288 operand_equal_p in fold-const.c */
291 hashable_expr_equal_p (const struct hashable_expr
*expr0
,
292 const struct hashable_expr
*expr1
)
294 tree type0
= expr0
->type
;
295 tree type1
= expr1
->type
;
297 /* If either type is NULL, there is nothing to check. */
298 if ((type0
== NULL_TREE
) ^ (type1
== NULL_TREE
))
301 /* If both types don't have the same signedness, precision, and mode,
302 then we can't consider them equal. */
304 && (TREE_CODE (type0
) == ERROR_MARK
305 || TREE_CODE (type1
) == ERROR_MARK
306 || TYPE_UNSIGNED (type0
) != TYPE_UNSIGNED (type1
)
307 || TYPE_PRECISION (type0
) != TYPE_PRECISION (type1
)
308 || TYPE_MODE (type0
) != TYPE_MODE (type1
)))
311 if (expr0
->kind
!= expr1
->kind
)
317 return equal_mem_array_ref_p (expr0
->ops
.single
.rhs
,
318 expr1
->ops
.single
.rhs
)
319 || operand_equal_p (expr0
->ops
.single
.rhs
,
320 expr1
->ops
.single
.rhs
, 0);
322 if (expr0
->ops
.unary
.op
!= expr1
->ops
.unary
.op
)
325 if ((CONVERT_EXPR_CODE_P (expr0
->ops
.unary
.op
)
326 || expr0
->ops
.unary
.op
== NON_LVALUE_EXPR
)
327 && TYPE_UNSIGNED (expr0
->type
) != TYPE_UNSIGNED (expr1
->type
))
330 return operand_equal_p (expr0
->ops
.unary
.opnd
,
331 expr1
->ops
.unary
.opnd
, 0);
334 if (expr0
->ops
.binary
.op
!= expr1
->ops
.binary
.op
)
337 if (operand_equal_p (expr0
->ops
.binary
.opnd0
,
338 expr1
->ops
.binary
.opnd0
, 0)
339 && operand_equal_p (expr0
->ops
.binary
.opnd1
,
340 expr1
->ops
.binary
.opnd1
, 0))
343 /* For commutative ops, allow the other order. */
344 return (commutative_tree_code (expr0
->ops
.binary
.op
)
345 && operand_equal_p (expr0
->ops
.binary
.opnd0
,
346 expr1
->ops
.binary
.opnd1
, 0)
347 && operand_equal_p (expr0
->ops
.binary
.opnd1
,
348 expr1
->ops
.binary
.opnd0
, 0));
351 if (expr0
->ops
.ternary
.op
!= expr1
->ops
.ternary
.op
352 || !operand_equal_p (expr0
->ops
.ternary
.opnd2
,
353 expr1
->ops
.ternary
.opnd2
, 0))
356 if (operand_equal_p (expr0
->ops
.ternary
.opnd0
,
357 expr1
->ops
.ternary
.opnd0
, 0)
358 && operand_equal_p (expr0
->ops
.ternary
.opnd1
,
359 expr1
->ops
.ternary
.opnd1
, 0))
362 /* For commutative ops, allow the other order. */
363 return (commutative_ternary_tree_code (expr0
->ops
.ternary
.op
)
364 && operand_equal_p (expr0
->ops
.ternary
.opnd0
,
365 expr1
->ops
.ternary
.opnd1
, 0)
366 && operand_equal_p (expr0
->ops
.ternary
.opnd1
,
367 expr1
->ops
.ternary
.opnd0
, 0));
373 /* If the calls are to different functions, then they
374 clearly cannot be equal. */
375 if (!gimple_call_same_target_p (expr0
->ops
.call
.fn_from
,
376 expr1
->ops
.call
.fn_from
))
379 if (! expr0
->ops
.call
.pure
)
382 if (expr0
->ops
.call
.nargs
!= expr1
->ops
.call
.nargs
)
385 for (i
= 0; i
< expr0
->ops
.call
.nargs
; i
++)
386 if (! operand_equal_p (expr0
->ops
.call
.args
[i
],
387 expr1
->ops
.call
.args
[i
], 0))
390 if (stmt_could_throw_p (expr0
->ops
.call
.fn_from
))
392 int lp0
= lookup_stmt_eh_lp (expr0
->ops
.call
.fn_from
);
393 int lp1
= lookup_stmt_eh_lp (expr1
->ops
.call
.fn_from
);
394 if ((lp0
> 0 || lp1
> 0) && lp0
!= lp1
)
405 if (expr0
->ops
.phi
.nargs
!= expr1
->ops
.phi
.nargs
)
408 for (i
= 0; i
< expr0
->ops
.phi
.nargs
; i
++)
409 if (! operand_equal_p (expr0
->ops
.phi
.args
[i
],
410 expr1
->ops
.phi
.args
[i
], 0))
421 /* Given a statement STMT, construct a hash table element. */
423 expr_hash_elt::expr_hash_elt (gimple
*stmt
, tree orig_lhs
)
425 enum gimple_code code
= gimple_code (stmt
);
426 struct hashable_expr
*expr
= this->expr ();
428 if (code
== GIMPLE_ASSIGN
)
430 enum tree_code subcode
= gimple_assign_rhs_code (stmt
);
432 switch (get_gimple_rhs_class (subcode
))
434 case GIMPLE_SINGLE_RHS
:
435 expr
->kind
= EXPR_SINGLE
;
436 expr
->type
= TREE_TYPE (gimple_assign_rhs1 (stmt
));
437 expr
->ops
.single
.rhs
= gimple_assign_rhs1 (stmt
);
439 case GIMPLE_UNARY_RHS
:
440 expr
->kind
= EXPR_UNARY
;
441 expr
->type
= TREE_TYPE (gimple_assign_lhs (stmt
));
442 if (CONVERT_EXPR_CODE_P (subcode
))
444 expr
->ops
.unary
.op
= subcode
;
445 expr
->ops
.unary
.opnd
= gimple_assign_rhs1 (stmt
);
447 case GIMPLE_BINARY_RHS
:
448 expr
->kind
= EXPR_BINARY
;
449 expr
->type
= TREE_TYPE (gimple_assign_lhs (stmt
));
450 expr
->ops
.binary
.op
= subcode
;
451 expr
->ops
.binary
.opnd0
= gimple_assign_rhs1 (stmt
);
452 expr
->ops
.binary
.opnd1
= gimple_assign_rhs2 (stmt
);
454 case GIMPLE_TERNARY_RHS
:
455 expr
->kind
= EXPR_TERNARY
;
456 expr
->type
= TREE_TYPE (gimple_assign_lhs (stmt
));
457 expr
->ops
.ternary
.op
= subcode
;
458 expr
->ops
.ternary
.opnd0
= gimple_assign_rhs1 (stmt
);
459 expr
->ops
.ternary
.opnd1
= gimple_assign_rhs2 (stmt
);
460 expr
->ops
.ternary
.opnd2
= gimple_assign_rhs3 (stmt
);
466 else if (code
== GIMPLE_COND
)
468 expr
->type
= boolean_type_node
;
469 expr
->kind
= EXPR_BINARY
;
470 expr
->ops
.binary
.op
= gimple_cond_code (stmt
);
471 expr
->ops
.binary
.opnd0
= gimple_cond_lhs (stmt
);
472 expr
->ops
.binary
.opnd1
= gimple_cond_rhs (stmt
);
474 else if (gcall
*call_stmt
= dyn_cast
<gcall
*> (stmt
))
476 size_t nargs
= gimple_call_num_args (call_stmt
);
479 gcc_assert (gimple_call_lhs (call_stmt
));
481 expr
->type
= TREE_TYPE (gimple_call_lhs (call_stmt
));
482 expr
->kind
= EXPR_CALL
;
483 expr
->ops
.call
.fn_from
= call_stmt
;
485 if (gimple_call_flags (call_stmt
) & (ECF_CONST
| ECF_PURE
))
486 expr
->ops
.call
.pure
= true;
488 expr
->ops
.call
.pure
= false;
490 expr
->ops
.call
.nargs
= nargs
;
491 expr
->ops
.call
.args
= XCNEWVEC (tree
, nargs
);
492 for (i
= 0; i
< nargs
; i
++)
493 expr
->ops
.call
.args
[i
] = gimple_call_arg (call_stmt
, i
);
495 else if (gswitch
*swtch_stmt
= dyn_cast
<gswitch
*> (stmt
))
497 expr
->type
= TREE_TYPE (gimple_switch_index (swtch_stmt
));
498 expr
->kind
= EXPR_SINGLE
;
499 expr
->ops
.single
.rhs
= gimple_switch_index (swtch_stmt
);
501 else if (code
== GIMPLE_GOTO
)
503 expr
->type
= TREE_TYPE (gimple_goto_dest (stmt
));
504 expr
->kind
= EXPR_SINGLE
;
505 expr
->ops
.single
.rhs
= gimple_goto_dest (stmt
);
507 else if (code
== GIMPLE_PHI
)
509 size_t nargs
= gimple_phi_num_args (stmt
);
512 expr
->type
= TREE_TYPE (gimple_phi_result (stmt
));
513 expr
->kind
= EXPR_PHI
;
514 expr
->ops
.phi
.nargs
= nargs
;
515 expr
->ops
.phi
.args
= XCNEWVEC (tree
, nargs
);
516 for (i
= 0; i
< nargs
; i
++)
517 expr
->ops
.phi
.args
[i
] = gimple_phi_arg_def (stmt
, i
);
523 m_vop
= gimple_vuse (stmt
);
524 m_hash
= avail_expr_hash (this);
528 /* Given a hashable_expr expression ORIG and an ORIG_LHS,
529 construct a hash table element. */
531 expr_hash_elt::expr_hash_elt (struct hashable_expr
*orig
, tree orig_lhs
)
536 m_hash
= avail_expr_hash (this);
540 /* Copy constructor for a hash table element. */
542 expr_hash_elt::expr_hash_elt (class expr_hash_elt
&old_elt
)
544 m_expr
= old_elt
.m_expr
;
545 m_lhs
= old_elt
.m_lhs
;
546 m_vop
= old_elt
.m_vop
;
547 m_hash
= old_elt
.m_hash
;
550 /* Now deep copy the malloc'd space for CALL and PHI args. */
551 if (old_elt
.m_expr
.kind
== EXPR_CALL
)
553 size_t nargs
= old_elt
.m_expr
.ops
.call
.nargs
;
556 m_expr
.ops
.call
.args
= XCNEWVEC (tree
, nargs
);
557 for (i
= 0; i
< nargs
; i
++)
558 m_expr
.ops
.call
.args
[i
] = old_elt
.m_expr
.ops
.call
.args
[i
];
560 else if (old_elt
.m_expr
.kind
== EXPR_PHI
)
562 size_t nargs
= old_elt
.m_expr
.ops
.phi
.nargs
;
565 m_expr
.ops
.phi
.args
= XCNEWVEC (tree
, nargs
);
566 for (i
= 0; i
< nargs
; i
++)
567 m_expr
.ops
.phi
.args
[i
] = old_elt
.m_expr
.ops
.phi
.args
[i
];
571 /* Calls and PHIs have a variable number of arguments that are allocated
572 on the heap. Thus we have to have a special dtor to release them. */
574 expr_hash_elt::~expr_hash_elt ()
576 if (m_expr
.kind
== EXPR_CALL
)
577 free (m_expr
.ops
.call
.args
);
578 else if (m_expr
.kind
== EXPR_PHI
)
579 free (m_expr
.ops
.phi
.args
);
582 /* Print a diagnostic dump of an expression hash table entry. */
585 expr_hash_elt::print (FILE *stream
)
587 fprintf (stream
, "STMT ");
591 print_generic_expr (stream
, m_lhs
, 0);
592 fprintf (stream
, " = ");
598 print_generic_expr (stream
, m_expr
.ops
.single
.rhs
, 0);
602 fprintf (stream
, "%s ", get_tree_code_name (m_expr
.ops
.unary
.op
));
603 print_generic_expr (stream
, m_expr
.ops
.unary
.opnd
, 0);
607 print_generic_expr (stream
, m_expr
.ops
.binary
.opnd0
, 0);
608 fprintf (stream
, " %s ", get_tree_code_name (m_expr
.ops
.binary
.op
));
609 print_generic_expr (stream
, m_expr
.ops
.binary
.opnd1
, 0);
613 fprintf (stream
, " %s <", get_tree_code_name (m_expr
.ops
.ternary
.op
));
614 print_generic_expr (stream
, m_expr
.ops
.ternary
.opnd0
, 0);
615 fputs (", ", stream
);
616 print_generic_expr (stream
, m_expr
.ops
.ternary
.opnd1
, 0);
617 fputs (", ", stream
);
618 print_generic_expr (stream
, m_expr
.ops
.ternary
.opnd2
, 0);
625 size_t nargs
= m_expr
.ops
.call
.nargs
;
628 fn_from
= m_expr
.ops
.call
.fn_from
;
629 if (gimple_call_internal_p (fn_from
))
630 fputs (internal_fn_name (gimple_call_internal_fn (fn_from
)),
633 print_generic_expr (stream
, gimple_call_fn (fn_from
), 0);
634 fprintf (stream
, " (");
635 for (i
= 0; i
< nargs
; i
++)
637 print_generic_expr (stream
, m_expr
.ops
.call
.args
[i
], 0);
639 fprintf (stream
, ", ");
641 fprintf (stream
, ")");
648 size_t nargs
= m_expr
.ops
.phi
.nargs
;
650 fprintf (stream
, "PHI <");
651 for (i
= 0; i
< nargs
; i
++)
653 print_generic_expr (stream
, m_expr
.ops
.phi
.args
[i
], 0);
655 fprintf (stream
, ", ");
657 fprintf (stream
, ">");
664 fprintf (stream
, " with ");
665 print_generic_expr (stream
, m_vop
, 0);
668 fprintf (stream
, "\n");
671 /* Pop entries off the stack until we hit the NULL marker.
672 For each entry popped, use the SRC/DEST pair to restore
673 SRC to its prior value. */
676 const_and_copies::pop_to_marker (void)
678 while (m_stack
.length () > 0)
680 tree prev_value
, dest
;
682 dest
= m_stack
.pop ();
684 /* A NULL value indicates we should stop unwinding, otherwise
685 pop off the next entry as they're recorded in pairs. */
689 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
691 fprintf (dump_file
, "<<<< COPY ");
692 print_generic_expr (dump_file
, dest
, 0);
693 fprintf (dump_file
, " = ");
694 print_generic_expr (dump_file
, SSA_NAME_VALUE (dest
), 0);
695 fprintf (dump_file
, "\n");
698 prev_value
= m_stack
.pop ();
699 set_ssa_name_value (dest
, prev_value
);
703 /* Record that X has the value Y and that X's previous value is PREV_X.
705 This variant does not follow the value chain for Y. */
708 const_and_copies::record_const_or_copy_raw (tree x
, tree y
, tree prev_x
)
710 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
712 fprintf (dump_file
, "0>>> COPY ");
713 print_generic_expr (dump_file
, x
, 0);
714 fprintf (dump_file
, " = ");
715 print_generic_expr (dump_file
, y
, 0);
716 fprintf (dump_file
, "\n");
719 set_ssa_name_value (x
, y
);
721 m_stack
.quick_push (prev_x
);
722 m_stack
.quick_push (x
);
725 /* Record that X has the value Y. */
728 const_and_copies::record_const_or_copy (tree x
, tree y
)
730 record_const_or_copy (x
, y
, SSA_NAME_VALUE (x
));
733 /* Record that X has the value Y and that X's previous value is PREV_X.
735 This variant follow's Y value chain. */
738 const_and_copies::record_const_or_copy (tree x
, tree y
, tree prev_x
)
740 /* Y may be NULL if we are invalidating entries in the table. */
741 if (y
&& TREE_CODE (y
) == SSA_NAME
)
743 tree tmp
= SSA_NAME_VALUE (y
);
747 record_const_or_copy_raw (x
, y
, prev_x
);
751 expr_elt_hasher::equal (const value_type
&p1
, const compare_type
&p2
)
753 const struct hashable_expr
*expr1
= p1
->expr ();
754 const struct expr_hash_elt
*stamp1
= p1
->stamp ();
755 const struct hashable_expr
*expr2
= p2
->expr ();
756 const struct expr_hash_elt
*stamp2
= p2
->stamp ();
758 /* This case should apply only when removing entries from the table. */
759 if (stamp1
== stamp2
)
762 if (p1
->hash () != p2
->hash ())
765 /* In case of a collision, both RHS have to be identical and have the
766 same VUSE operands. */
767 if (hashable_expr_equal_p (expr1
, expr2
)
768 && types_compatible_p (expr1
->type
, expr2
->type
))
774 /* Given a conditional expression COND as a tree, initialize
775 a hashable_expr expression EXPR. The conditional must be a
776 comparison or logical negation. A constant or a variable is
780 initialize_expr_from_cond (tree cond
, struct hashable_expr
*expr
)
782 expr
->type
= boolean_type_node
;
784 if (COMPARISON_CLASS_P (cond
))
786 expr
->kind
= EXPR_BINARY
;
787 expr
->ops
.binary
.op
= TREE_CODE (cond
);
788 expr
->ops
.binary
.opnd0
= TREE_OPERAND (cond
, 0);
789 expr
->ops
.binary
.opnd1
= TREE_OPERAND (cond
, 1);
791 else if (TREE_CODE (cond
) == TRUTH_NOT_EXPR
)
793 expr
->kind
= EXPR_UNARY
;
794 expr
->ops
.unary
.op
= TRUTH_NOT_EXPR
;
795 expr
->ops
.unary
.opnd
= TREE_OPERAND (cond
, 0);