+2017-01-26 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2016-09-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/77745
+ * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):
+ When removing redundant stores make sure to check compatibility
+ of the TBAA state for downstream accesses.
+ * tree-ssa-sccvn.c (visit_reference_op_store): Likewise for when
+ value-numbering virtual operands for store matches.
+
+ 2016-09-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/77768
+ * tree-ssa-sccvn.c (visit_reference_op_store): Properly deal
+ with stores to a place we know has a constant value.
+ * tree-vrp.c (set_defs_to_varying): New helper avoiding
+ writing to vr_const_varying.
+ (vrp_initialize): Call it.
+ (vrp_visit_stmt): Likewise.
+ (evrp_dom_walker::before_dom_children): Likewise.
+ * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):
+ Handle stores to readonly memory when removing redundant stores.
+
2017-01-24 Wilco Dijkstra <wdijkstr@arm.com>
Backport from mainline
+2017-01-26 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2016-09-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/77745
+ * g++.dg/torture/pr77745.C: New testcase.
+
+ 2016-09-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/77768
+ * gcc.dg/torture/pr77768.c: New testcase.
+
2017-01-24 Wilco Dijkstra <wdijkstr@arm.com>
Backport from mainline
--- /dev/null
+// { dg-do run }
+// { dg-additional-options "-std=gnu++14" }
+
+inline void* operator new(__SIZE_TYPE__, void* __p) noexcept { return __p; }
+
+long foo(char *c1, char *c2)
+{
+ long *p1 = new (c1) long;
+ *p1 = 100;
+ long long *p2 = new (c2) long long;
+ *p2 = 200;
+ long *p3 = new (c2) long;
+ *p3 = 200;
+ return *p1;
+}
+int main()
+{
+ union {
+ char c;
+ long l;
+ long long ll;
+ } c;
+ if (foo(&c.c, &c.c) != 200)
+ __builtin_abort();
+}
--- /dev/null
+/* { dg-do run } */
+
+static const int a;
+int b;
+int *c, *d;
+int main()
+{
+ c = (int *)&a;
+ c == d ?: __builtin_exit(0);
+ for (; b; b++ >= (*d = a))
+ ;
+ return 0;
+}
&& !is_gimple_reg (gimple_assign_lhs (stmt))
&& (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
|| is_gimple_min_invariant (gimple_assign_rhs1 (stmt))))
- {
- tree val;
+ {
+ tree val;
tree rhs = gimple_assign_rhs1 (stmt);
- val = vn_reference_lookup (gimple_assign_lhs (stmt),
- gimple_vuse (stmt), VN_WALK, NULL, false);
- if (TREE_CODE (rhs) == SSA_NAME)
- rhs = VN_INFO (rhs)->valnum;
- if (val
- && operand_equal_p (val, rhs, 0))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Deleted redundant store ");
- print_gimple_stmt (dump_file, stmt, 0, 0);
- }
-
- /* Queue stmt for removal. */
- el_to_remove.safe_push (stmt);
- continue;
- }
+ vn_reference_t vnresult;
+ val = vn_reference_lookup (lhs, gimple_vuse (stmt), VN_WALK,
+ &vnresult, false);
+ if (TREE_CODE (rhs) == SSA_NAME)
+ rhs = VN_INFO (rhs)->valnum;
+ if (val
+ && operand_equal_p (val, rhs, 0))
+ {
+ /* We can only remove the later store if the former aliases
+ at least all accesses the later one does or if the store
+ was to readonly memory storing the same value. */
+ alias_set_type set = get_alias_set (lhs);
+ if (! vnresult
+ || vnresult->set == set
+ || alias_set_subset_of (set, vnresult->set))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Deleted redundant store ");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ }
+
+ /* Queue stmt for removal. */
+ el_to_remove.safe_push (stmt);
+ continue;
+ }
+ }
}
bool can_make_abnormal_goto = stmt_can_make_abnormal_goto (stmt);
{
bool changed = false;
vn_reference_t vnresult = NULL;
- tree result, assign;
+ tree assign;
bool resultsame = false;
tree vuse = gimple_vuse (stmt);
tree vdef = gimple_vdef (stmt);
Otherwise, the vdefs for the store are used when inserting into
the table, since the store generates a new memory state. */
- result = vn_reference_lookup (lhs, vuse, VN_NOWALK, NULL, false);
-
- if (result)
+ vn_reference_lookup (lhs, vuse, VN_NOWALK, &vnresult, false);
+ if (vnresult
+ && vnresult->result)
{
+ tree result = vnresult->result;
if (TREE_CODE (result) == SSA_NAME)
result = SSA_VAL (result);
resultsame = expressions_equal_p (result, op);
+ if (resultsame)
+ {
+ /* If the TBAA state isn't compatible for downstream reads
+ we cannot value-number the VDEFs the same. */
+ alias_set_type set = get_alias_set (lhs);
+ if (vnresult->set != set
+ && ! alias_set_subset_of (set, vnresult->set))
+ resultsame = false;
+ }
}
- if ((!result || !resultsame)
+ if (!resultsame)
+ {
/* Only perform the following when being called from PRE
which embeds tail merging. */
- && default_vn_walk_kind == VN_WALK)
- {
- assign = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, op);
- vn_reference_lookup (assign, vuse, VN_NOWALK, &vnresult, false);
- if (vnresult)
+ if (default_vn_walk_kind == VN_WALK)
{
- VN_INFO (vdef)->use_processed = true;
- return set_ssa_val_to (vdef, vnresult->result_vdef);
+ assign = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, op);
+ vn_reference_lookup (assign, vuse, VN_NOWALK, &vnresult, false);
+ if (vnresult)
+ {
+ VN_INFO (vdef)->use_processed = true;
+ return set_ssa_val_to (vdef, vnresult->result_vdef);
+ }
}
- }
- if (!result || !resultsame)
- {
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "No store match\n");
/* Have to set value numbers before insert, since insert is
going to valueize the references in-place. */
if (vdef)
- {
- changed |= set_ssa_val_to (vdef, vdef);
- }
+ changed |= set_ssa_val_to (vdef, vdef);
/* Do not insert structure copies into the tables. */
if (is_gimple_min_invariant (op)
return vr;
}
+/* Set value-ranges of all SSA names defined by STMT to varying. */
+
+static void
+set_defs_to_varying (gimple stmt)
+{
+ ssa_op_iter i;
+ tree def;
+ FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF)
+ {
+ value_range_t *vr = get_value_range (def);
+ /* Avoid writing to vr_const_varying get_value_range may return. */
+ if (vr->type != VR_VARYING)
+ set_value_range_to_varying (vr);
+ }
+}
+
+
/* Return true, if VAL1 and VAL2 are equal values for VRP purposes. */
static inline bool
prop_set_simulate_again (stmt, true);
else if (!stmt_interesting_for_vrp (stmt))
{
- ssa_op_iter i;
- tree def;
- FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF)
- set_value_range_to_varying (get_value_range (def));
+ set_defs_to_varying (stmt);
prop_set_simulate_again (stmt, false);
}
else
static enum ssa_prop_result
vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
{
- tree def, lhs;
- ssa_op_iter iter;
+ tree lhs;
enum gimple_code code = gimple_code (stmt);
lhs = gimple_get_lhs (stmt);
}
/* Every other statement produces no useful ranges. */
- FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
- set_value_range_to_varying (get_value_range (def));
+ set_defs_to_varying (stmt);
return SSA_PROP_VARYING;
}
static enum ssa_prop_result
vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
{
- tree def;
- ssa_op_iter iter;
-
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "\nVisiting statement:\n");
/* All other statements produce nothing of interest for VRP, so mark
their outputs varying and prevent further simulation. */
- FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
- set_value_range_to_varying (get_value_range (def));
+ set_defs_to_varying (stmt);
return SSA_PROP_VARYING;
}