diff options
Diffstat (limited to 'gcc/tree-ssa-sccvn.c')
-rw-r--r-- | gcc/tree-ssa-sccvn.c | 92 |
1 files changed, 75 insertions, 17 deletions
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 6766fc58bf8..930508deb29 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-cfgcleanup.h" #include "tree-ssa-loop.h" #include "tree-scalar-evolution.h" +#include "builtins.h" #include "tree-ssa-sccvn.h" /* This algorithm is based on the SCC algorithm presented by Keith @@ -1857,23 +1858,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, /* If we reach a clobbering statement try to skip it and see if we find a VN result with exactly the same value as the possible clobber. In this case we can ignore the clobber - and return the found value. - Note that we don't need to worry about partial overlapping - accesses as we then can use TBAA to disambiguate against the - clobbering statement when looking up a load (thus the - VN_WALKREWRITE guard). */ + and return the found value. */ if (vn_walk_kind == VN_WALKREWRITE && is_gimple_reg_type (TREE_TYPE (lhs)) && types_compatible_p (TREE_TYPE (lhs), vr->type) - /* The overlap restriction breaks down when either access - alias-set is zero. Still for accesses of the size of - an addressable unit there can be no overlaps. Overlaps - between different union members are not an issue since - activation of a union member via a store makes the - values of untouched bytes unspecified. */ - && (known_eq (ref->size, BITS_PER_UNIT) - || (get_alias_set (lhs) != 0 - && ao_ref_alias_set (ref) != 0))) + && ref->ref) { tree *saved_last_vuse_ptr = last_vuse_ptr; /* Do not update last_vuse_ptr in vn_reference_lookup_2. */ @@ -1891,7 +1880,14 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, vn_reference_t vnresult = (vn_reference_t) res; if (vnresult->result && operand_equal_p (vnresult->result, - gimple_assign_rhs1 (def_stmt), 0)) + gimple_assign_rhs1 (def_stmt), 0) + /* We have to honor our promise about union type punning + and also support arbitrary overlaps with + -fno-strict-aliasing. So simply resort to alignment to + rule out overlaps. Do this check last because it is + quite expensive compared to the hash-lookup above. */ + && multiple_p (get_object_alignment (ref->ref), ref->size) + && multiple_p (get_object_alignment (lhs), ref->size)) return res; } } @@ -2031,9 +2027,20 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, tree rhs = gimple_assign_rhs1 (def_stmt); if (TREE_CODE (rhs) == SSA_NAME) rhs = SSA_VAL (rhs); - len = native_encode_expr (gimple_assign_rhs1 (def_stmt), + unsigned pad = 0; + if (BYTES_BIG_ENDIAN + && is_a <scalar_mode> (TYPE_MODE (TREE_TYPE (rhs)))) + { + /* On big-endian the padding is at the 'front' so + just skip the initial bytes. */ + fixed_size_mode mode + = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (rhs))); + pad = GET_MODE_SIZE (mode) - size2 / BITS_PER_UNIT; + } + len = native_encode_expr (rhs, buffer, sizeof (buffer), - (offseti - offset2) / BITS_PER_UNIT); + ((offseti - offset2) / BITS_PER_UNIT + + pad)); if (len > 0 && len * BITS_PER_UNIT >= maxsizei) { tree type = vr->type; @@ -5207,6 +5214,57 @@ public: auto_vec<tree> avail_stack; }; +/* Return true if the reference operation REF may trap. */ + +bool +vn_reference_may_trap (vn_reference_t ref) +{ + switch (ref->operands[0].opcode) + { + case MODIFY_EXPR: + case CALL_EXPR: + /* We do not handle calls. */ + case ADDR_EXPR: + /* And toplevel address computations never trap. */ + return false; + default:; + } + + vn_reference_op_t op; + unsigned i; + FOR_EACH_VEC_ELT (ref->operands, i, op) + { + switch (op->opcode) + { + case WITH_SIZE_EXPR: + case TARGET_MEM_REF: + /* Always variable. */ + return true; + case COMPONENT_REF: + if (op->op1 && TREE_CODE (op->op1) == SSA_NAME) + return true; + break; + case ARRAY_RANGE_REF: + case ARRAY_REF: + if (TREE_CODE (op->op0) == SSA_NAME) + return true; + break; + case MEM_REF: + /* Nothing interesting in itself, the base is separate. */ + break; + /* The following are the address bases. */ + case SSA_NAME: + return true; + case ADDR_EXPR: + if (op->op0) + return tree_could_trap_p (TREE_OPERAND (op->op0, 0)); + return false; + default:; + } + } + return false; +} + eliminate_dom_walker::eliminate_dom_walker (cdi_direction direction, bitmap inserted_exprs_) : dom_walker (direction), do_pre (inserted_exprs_ != NULL), |