aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gcc-4.9/gcc/function.h3
-rw-r--r--gcc-4.9/gcc/testsuite/gcc.dg/tree-ssa/restrict-5.c24
-rw-r--r--gcc-4.9/gcc/tree-core.h10
-rw-r--r--gcc-4.9/gcc/tree-data-ref.c9
-rw-r--r--gcc-4.9/gcc/tree-inline.c40
-rw-r--r--gcc-4.9/gcc/tree-inline.h4
-rw-r--r--gcc-4.9/gcc/tree-pretty-print.c15
-rw-r--r--gcc-4.9/gcc/tree-ssa-alias.c31
-rw-r--r--gcc-4.9/gcc/tree-ssa-structalias.c203
-rw-r--r--gcc-4.9/gcc/tree-streamer-in.c13
-rw-r--r--gcc-4.9/gcc/tree-streamer-out.c11
-rw-r--r--gcc-4.9/gcc/tree.h5
12 files changed, 362 insertions, 6 deletions
diff --git a/gcc-4.9/gcc/function.h b/gcc-4.9/gcc/function.h
index 23ac15027..f2c348f28 100644
--- a/gcc-4.9/gcc/function.h
+++ b/gcc-4.9/gcc/function.h
@@ -595,6 +595,9 @@ struct GTY(()) function {
a string describing the reason for failure. */
const char * GTY((skip)) cannot_be_copied_reason;
+ /* Last assigned dependence info clique. */
+ unsigned short last_clique;
+
/* Collected bit flags. */
/* Number of units of general registers that need saving in stdarg
diff --git a/gcc-4.9/gcc/testsuite/gcc.dg/tree-ssa/restrict-5.c b/gcc-4.9/gcc/testsuite/gcc.dg/tree-ssa/restrict-5.c
new file mode 100644
index 000000000..d6c240aae
--- /dev/null
+++ b/gcc-4.9/gcc/testsuite/gcc.dg/tree-ssa/restrict-5.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-strict-aliasing -fdump-tree-lim1-details" } */
+
+static inline __attribute__((always_inline))
+void f(int * __restrict__ r,
+ int a[__restrict__ 16][16],
+ int b[__restrict__ 16][16],
+ int i, int j)
+{
+ int x;
+ *r = 0;
+ for (x = 1; x < 16; ++x)
+ *r = *r + a[i][x] * b[x][j];
+}
+
+void g(int *r, int a[16][16], int b[16][16], int i, int j)
+{
+ f (r, a, b, i ,j);
+}
+
+/* We should apply store motion to the store to *r. */
+
+/* { dg-final { scan-tree-dump "Executing store motion of \\\*r" "lim1" } } */
+/* { dg-final { cleanup-tree-dump "lim1" } } */
diff --git a/gcc-4.9/gcc/tree-core.h b/gcc-4.9/gcc/tree-core.h
index bb89feee1..77dca9683 100644
--- a/gcc-4.9/gcc/tree-core.h
+++ b/gcc-4.9/gcc/tree-core.h
@@ -766,6 +766,16 @@ struct GTY(()) tree_base {
int length;
/* SSA version number. This field is only used with SSA_NAME. */
unsigned int version;
+
+ /* The following two fields are used for MEM_REF and TARGET_MEM_REF
+ expression trees and specify known data non-dependences. For
+ two memory references in a function they are known to not
+ alias if dependence_info.clique are equal and dependence_info.base
+ are distinct. */
+ struct {
+ unsigned short clique;
+ unsigned short base;
+ } dependence_info;
} GTY((skip(""))) u;
};
diff --git a/gcc-4.9/gcc/tree-data-ref.c b/gcc-4.9/gcc/tree-data-ref.c
index 01d0a7a79..f279bf391 100644
--- a/gcc-4.9/gcc/tree-data-ref.c
+++ b/gcc-4.9/gcc/tree-data-ref.c
@@ -979,10 +979,13 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop)
guaranteed.
As a band-aid, mark the access so we can special-case
it in dr_may_alias_p. */
+ tree old = ref;
ref = fold_build2_loc (EXPR_LOCATION (ref),
MEM_REF, TREE_TYPE (ref),
base, memoff);
DR_UNCONSTRAINED_BASE (dr) = true;
+ MR_DEPENDENCE_CLIQUE (ref) = MR_DEPENDENCE_CLIQUE (old);
+ MR_DEPENDENCE_BASE (ref) = MR_DEPENDENCE_BASE (old);
access_fns.safe_push (access_fn);
}
}
@@ -1389,6 +1392,12 @@ dr_may_alias_p (const struct data_reference *a, const struct data_reference *b,
return false;
}
+ if ((TREE_CODE (addr_a) == MEM_REF || TREE_CODE (addr_a) == TARGET_MEM_REF)
+ && (TREE_CODE (addr_b) == MEM_REF || TREE_CODE (addr_b) == TARGET_MEM_REF)
+ && MR_DEPENDENCE_CLIQUE (addr_a) == MR_DEPENDENCE_CLIQUE (addr_b)
+ && MR_DEPENDENCE_BASE (addr_a) != MR_DEPENDENCE_BASE (addr_b))
+ return false;
+
/* If we had an evolution in a MEM_REF BASE_OBJECT we do not know
the size of the base-object. So we cannot do any offset/overlap
based analysis but have to rely on points-to information only. */
diff --git a/gcc-4.9/gcc/tree-inline.c b/gcc-4.9/gcc/tree-inline.c
index beb65f0b1..624eca1c4 100644
--- a/gcc-4.9/gcc/tree-inline.c
+++ b/gcc-4.9/gcc/tree-inline.c
@@ -787,6 +787,24 @@ is_parm (tree decl)
return (TREE_CODE (decl) == PARM_DECL);
}
+/* Remap the dependence CLIQUE from the source to the destination function
+ as specified in ID. */
+
+static unsigned short
+remap_dependence_clique (copy_body_data *id, unsigned short clique)
+{
+ if (clique == 0)
+ return 0;
+ if (!id->dependence_map)
+ id->dependence_map = pointer_map_create ();
+ void **newc = pointer_map_contains (id->dependence_map,
+ (void *)(uintptr_t)clique);
+ if (!newc)
+ newc = pointer_map_insert (id->dependence_map,
+ (void *)(uintptr_t)++cfun->last_clique);
+ return (uintptr_t)*newc;
+}
+
/* Remap the GIMPLE operand pointed to by *TP. DATA is really a
'struct walk_stmt_info *'. DATA->INFO is a 'copy_body_data *'.
WALK_SUBTREES is used to indicate walk_gimple_op whether to keep
@@ -886,6 +904,12 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
+ if (MR_DEPENDENCE_CLIQUE (old) != 0)
+ {
+ MR_DEPENDENCE_CLIQUE (*tp)
+ = remap_dependence_clique (id, MR_DEPENDENCE_CLIQUE (old));
+ MR_DEPENDENCE_BASE (*tp) = MR_DEPENDENCE_BASE (old);
+ }
/* We cannot propagate the TREE_THIS_NOTRAP flag if we have
remapped a parameter as the property might be valid only
for the parameter itself. */
@@ -1139,6 +1163,12 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
+ if (MR_DEPENDENCE_CLIQUE (old) != 0)
+ {
+ MR_DEPENDENCE_CLIQUE (*tp)
+ = remap_dependence_clique (id, MR_DEPENDENCE_CLIQUE (old));
+ MR_DEPENDENCE_BASE (*tp) = MR_DEPENDENCE_BASE (old);
+ }
/* We cannot propagate the TREE_THIS_NOTRAP flag if we have
remapped a parameter as the property might be valid only
for the parameter itself. */
@@ -2599,6 +2629,11 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
pointer_map_destroy (id->eh_map);
id->eh_map = NULL;
}
+ if (id->dependence_map)
+ {
+ pointer_map_destroy (id->dependence_map);
+ id->dependence_map = NULL;
+ }
return new_fndecl;
}
@@ -4954,6 +4989,11 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
pointer_map_destroy (id.decl_map);
if (id.debug_map)
pointer_map_destroy (id.debug_map);
+ if (id.dependence_map)
+ {
+ pointer_map_destroy (id.dependence_map);
+ id.dependence_map = NULL;
+ }
return copy;
}
diff --git a/gcc-4.9/gcc/tree-inline.h b/gcc-4.9/gcc/tree-inline.h
index 13c551666..8ad47f101 100644
--- a/gcc-4.9/gcc/tree-inline.h
+++ b/gcc-4.9/gcc/tree-inline.h
@@ -135,6 +135,10 @@ struct copy_body_data
/* Cilk keywords currently need to replace some variables that
ordinary nested functions do not. */
bool remap_var_for_cilk;
+
+ /* A map from the inlined functions dependence info cliques to
+ equivalents in the function into which it is being inlined. */
+ struct pointer_map_t *dependence_map;
};
/* Weights of constructions for estimate_num_insns. */
diff --git a/gcc-4.9/gcc/tree-pretty-print.c b/gcc-4.9/gcc/tree-pretty-print.c
index c3ec6c02d..68530c9eb 100644
--- a/gcc-4.9/gcc/tree-pretty-print.c
+++ b/gcc-4.9/gcc/tree-pretty-print.c
@@ -1078,7 +1078,9 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
/* Same value types ignoring qualifiers. */
&& (TYPE_MAIN_VARIANT (TREE_TYPE (node))
== TYPE_MAIN_VARIANT
- (TREE_TYPE (TREE_TYPE (TREE_OPERAND (node, 1))))))
+ (TREE_TYPE (TREE_TYPE (TREE_OPERAND (node, 1)))))
+ && (!(flags & TDF_ALIAS)
+ || MR_DEPENDENCE_CLIQUE (node) == 0))
{
if (TREE_CODE (TREE_OPERAND (node, 0)) != ADDR_EXPR)
{
@@ -1109,6 +1111,14 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
dump_generic_node (buffer, TREE_OPERAND (node, 1),
spc, flags, false);
}
+ if ((flags & TDF_ALIAS)
+ && MR_DEPENDENCE_CLIQUE (node) != 0)
+ {
+ pp_string (buffer, " clique ");
+ pp_unsigned_wide_integer (buffer, MR_DEPENDENCE_CLIQUE (node));
+ pp_string (buffer, " base ");
+ pp_unsigned_wide_integer (buffer, MR_DEPENDENCE_BASE (node));
+ }
pp_right_bracket (buffer);
}
break;
@@ -1434,7 +1444,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
/* Same value types ignoring qualifiers. */
&& (TYPE_MAIN_VARIANT (TREE_TYPE (op0))
== TYPE_MAIN_VARIANT
- (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 1))))))))
+ (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 1)))))
+ && MR_DEPENDENCE_CLIQUE (op0) == 0)))
{
op0 = TREE_OPERAND (op0, 0);
str = "->";
diff --git a/gcc-4.9/gcc/tree-ssa-alias.c b/gcc-4.9/gcc/tree-ssa-alias.c
index de3fd0598..9a02de399 100644
--- a/gcc-4.9/gcc/tree-ssa-alias.c
+++ b/gcc-4.9/gcc/tree-ssa-alias.c
@@ -1405,7 +1405,36 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
ao_ref_alias_set (ref1),
ao_ref_base_alias_set (ref1),
tbaa_p);
- else if (ind1_p && ind2_p)
+
+ /* Handle restrict based accesses.
+ ??? ao_ref_base strips inner MEM_REF [&decl], recover from that
+ here. */
+ tree rbase1 = base1;
+ tree rbase2 = base2;
+ if (var1_p)
+ {
+ rbase1 = ref1->ref;
+ if (rbase1)
+ while (handled_component_p (rbase1))
+ rbase1 = TREE_OPERAND (rbase1, 0);
+ }
+ if (var2_p)
+ {
+ rbase2 = ref2->ref;
+ if (rbase2)
+ while (handled_component_p (rbase2))
+ rbase2 = TREE_OPERAND (rbase2, 0);
+ }
+ if (rbase1 && rbase2
+ && (TREE_CODE (base1) == MEM_REF || TREE_CODE (base1) == TARGET_MEM_REF)
+ && (TREE_CODE (base2) == MEM_REF || TREE_CODE (base2) == TARGET_MEM_REF)
+ /* If the accesses are in the same restrict clique... */
+ && MR_DEPENDENCE_CLIQUE (base1) == MR_DEPENDENCE_CLIQUE (base2)
+ /* But based on different pointers they do not alias. */
+ && MR_DEPENDENCE_BASE (base1) != MR_DEPENDENCE_BASE (base2))
+ return false;
+
+ if (ind1_p && ind2_p)
return indirect_refs_may_alias_p (ref1->ref, base1,
offset1, max_size1,
ao_ref_alias_set (ref1), -1,
diff --git a/gcc-4.9/gcc/tree-ssa-structalias.c b/gcc-4.9/gcc/tree-ssa-structalias.c
index abc99ba37..f44667b57 100644
--- a/gcc-4.9/gcc/tree-ssa-structalias.c
+++ b/gcc-4.9/gcc/tree-ssa-structalias.c
@@ -53,6 +53,10 @@
#include "splay-tree.h"
#include "params.h"
#include "alias.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-pretty-print.h"
+#include "gimple-walk.h"
/* The idea behind this analyzer is to generate set constraints from the
program, then solve the resulting constraints in order to generate the
@@ -273,12 +277,19 @@ struct variable_info
/* True if this field has only restrict qualified pointers. */
unsigned int only_restrict_pointers : 1;
+ /* True if this represents a heap var created for a restrict qualified
+ pointer. */
+ unsigned int is_restrict_var : 1;
+
/* True if this represents a global variable. */
unsigned int is_global_var : 1;
/* True if this represents a IPA function info. */
unsigned int is_fn_info : 1;
+ /* ??? Store somewhere better. */
+ unsigned short ruid;
+
/* The ID of the variable for the next field in this structure
or zero for the last field in this structure. */
unsigned next;
@@ -370,6 +381,7 @@ new_var_info (tree t, const char *name)
ret->is_heap_var = false;
ret->may_have_pointers = true;
ret->only_restrict_pointers = false;
+ ret->is_restrict_var = false;
ret->is_global_var = (t == NULL_TREE);
ret->is_fn_info = false;
if (t && DECL_P (t))
@@ -3782,6 +3794,7 @@ static varinfo_t
make_constraint_from_restrict (varinfo_t lhs, const char *name)
{
varinfo_t vi = make_heapvar (name);
+ vi->is_restrict_var = 1;
vi->is_global_var = 1;
vi->may_have_pointers = 1;
make_constraint_from (lhs, vi->id);
@@ -5760,7 +5773,11 @@ create_variable_info_for (tree decl, const char *name)
&& TYPE_RESTRICT (TREE_TYPE (decl)))
|| vi->only_restrict_pointers)
{
- make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
+ varinfo_t rvi
+ = make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
+ /* ??? For now exclude reads from globals as restrict sources
+ if those are not (indirectly) from incoming parameters. */
+ rvi->is_restrict_var = false;
continue;
}
@@ -5870,6 +5887,7 @@ intra_create_variable_infos (void)
tree heapvar = build_fake_var_decl (TREE_TYPE (TREE_TYPE (t)));
DECL_EXTERNAL (heapvar) = 1;
vi = create_variable_info_for_1 (heapvar, "PARM_NOALIAS");
+ vi->is_restrict_var = 1;
insert_vi_for_tree (heapvar, vi);
lhsc.var = p->id;
lhsc.type = SCALAR;
@@ -6953,6 +6971,186 @@ delete_points_to_sets (void)
obstack_free (&final_solutions_obstack, NULL);
}
+/* Mark "other" loads and stores as belonging to CLIQUE and with
+ base zero. */
+
+static bool
+visit_loadstore (gimple, tree base, tree ref, void *clique_)
+{
+ unsigned short clique = (uintptr_t)clique_;
+ if (TREE_CODE (base) == MEM_REF
+ || TREE_CODE (base) == TARGET_MEM_REF)
+ {
+ tree ptr = TREE_OPERAND (base, 0);
+ if (TREE_CODE (ptr) == SSA_NAME)
+ {
+ /* ??? We need to make sure 'ptr' doesn't include any of
+ the restrict tags in its points-to set. */
+ return false;
+ }
+
+ /* For now let decls through. */
+
+ /* Do not overwrite existing cliques (that includes clique, base
+ pairs we just set). */
+ if (MR_DEPENDENCE_CLIQUE (base) == 0)
+ {
+ MR_DEPENDENCE_CLIQUE (base) = clique;
+ MR_DEPENDENCE_BASE (base) = 0;
+ }
+ }
+
+ /* For plain decl accesses see whether they are accesses to globals
+ and rewrite them to MEM_REFs with { clique, 0 }. */
+ if (TREE_CODE (base) == VAR_DECL
+ && is_global_var (base)
+ /* ??? We can't rewrite a plain decl with the walk_stmt_load_store
+ ops callback. */
+ && base != ref)
+ {
+ tree *basep = &ref;
+ while (handled_component_p (*basep))
+ basep = &TREE_OPERAND (*basep, 0);
+ gcc_assert (TREE_CODE (*basep) == VAR_DECL);
+ tree ptr = build_fold_addr_expr (*basep);
+ tree zero = build_int_cst (TREE_TYPE (ptr), 0);
+ *basep = build2 (MEM_REF, TREE_TYPE (*basep), ptr, zero);
+ MR_DEPENDENCE_CLIQUE (*basep) = clique;
+ MR_DEPENDENCE_BASE (*basep) = 0;
+ }
+
+ return false;
+}
+
+/* If REF is a MEM_REF then assign a clique, base pair to it, updating
+ CLIQUE, *RESTRICT_VAR and LAST_RUID. Return whether dependence info
+ was assigned to REF. */
+
+static bool
+maybe_set_dependence_info (tree ref, tree ptr,
+ unsigned short &clique, varinfo_t restrict_var,
+ unsigned short &last_ruid)
+{
+ while (handled_component_p (ref))
+ ref = TREE_OPERAND (ref, 0);
+ if ((TREE_CODE (ref) == MEM_REF
+ || TREE_CODE (ref) == TARGET_MEM_REF)
+ && TREE_OPERAND (ref, 0) == ptr)
+ {
+ /* Do not overwrite existing cliques. This avoids overwriting dependence
+ info inlined from a function with restrict parameters inlined
+ into a function with restrict parameters. This usually means we
+ prefer to be precise in innermost loops. */
+ if (MR_DEPENDENCE_CLIQUE (ref) == 0)
+ {
+ if (clique == 0)
+ clique = ++cfun->last_clique;
+ if (restrict_var->ruid == 0)
+ restrict_var->ruid = ++last_ruid;
+ MR_DEPENDENCE_CLIQUE (ref) = clique;
+ MR_DEPENDENCE_BASE (ref) = restrict_var->ruid;
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Compute the set of independend memory references based on restrict
+ tags and their conservative propagation to the points-to sets. */
+
+static void
+compute_dependence_clique (void)
+{
+ unsigned short clique = 0;
+ unsigned short last_ruid = 0;
+ for (unsigned i = 0; i < num_ssa_names; ++i)
+ {
+ tree ptr = ssa_name (i);
+ if (!ptr || !POINTER_TYPE_P (TREE_TYPE (ptr)))
+ continue;
+
+ /* Avoid all this when ptr is not dereferenced? */
+ tree p = ptr;
+ if (SSA_NAME_IS_DEFAULT_DEF (ptr)
+ && (TREE_CODE (SSA_NAME_VAR (ptr)) == PARM_DECL
+ || TREE_CODE (SSA_NAME_VAR (ptr)) == RESULT_DECL))
+ p = SSA_NAME_VAR (ptr);
+ varinfo_t vi = lookup_vi_for_tree (p);
+ if (!vi)
+ continue;
+ vi = get_varinfo (find (vi->id));
+ bitmap_iterator bi;
+ unsigned j;
+ varinfo_t restrict_var = NULL;
+ EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, j, bi)
+ {
+ varinfo_t oi = get_varinfo (j);
+ if (oi->is_restrict_var)
+ {
+ if (restrict_var)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "found restrict pointed-to "
+ "for ");
+ print_generic_expr (dump_file, ptr, 0);
+ fprintf (dump_file, " but not exclusively\n");
+ }
+ restrict_var = NULL;
+ break;
+ }
+ restrict_var = oi;
+ }
+ /* NULL is the only other valid points-to entry. */
+ else if (oi->id != nothing_id)
+ {
+ restrict_var = NULL;
+ break;
+ }
+ }
+ /* Ok, found that ptr must(!) point to a single(!) restrict
+ variable. */
+ /* ??? PTA isn't really a proper propagation engine to compute
+ this property.
+ ??? We could handle merging of two restricts by unifying them. */
+ if (restrict_var)
+ {
+ /* Now look at possible dereferences of ptr. */
+ imm_use_iterator ui;
+ gimple use_stmt;
+ FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr)
+ {
+ /* ??? Calls and asms. */
+ if (!gimple_assign_single_p (use_stmt))
+ continue;
+ maybe_set_dependence_info (gimple_assign_lhs (use_stmt), ptr,
+ clique, restrict_var, last_ruid);
+ maybe_set_dependence_info (gimple_assign_rhs1 (use_stmt), ptr,
+ clique, restrict_var, last_ruid);
+ }
+ }
+ }
+
+ if (clique == 0)
+ return;
+
+ /* Assign the BASE id zero to all accesses not based on a restrict
+ pointer. That way they get disabiguated against restrict
+ accesses but not against each other. */
+ /* ??? For restricts derived from globals (thus not incoming
+ parameters) we can't restrict scoping properly thus the following
+ is too aggressive there. For now we have excluded those globals from
+ getting into the MR_DEPENDENCE machinery. */
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, cfun)
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ walk_stmt_load_store_ops (stmt, (void *)(uintptr_t)clique,
+ visit_loadstore, visit_loadstore);
+ }
+}
/* Compute points-to information for every SSA_NAME pointer in the
current function and compute the transitive closure of escaped
@@ -6984,6 +7182,9 @@ compute_may_aliases (void)
if (dump_file)
dump_alias_info (dump_file);
+ /* Compute restrict-based memory disambiguations. */
+ compute_dependence_clique ();
+
/* Deallocate memory used by aliasing data structures and the internal
points-to solution. */
delete_points_to_sets ();
diff --git a/gcc-4.9/gcc/tree-streamer-in.c b/gcc-4.9/gcc/tree-streamer-in.c
index 1839f579e..4dad86cad 100644
--- a/gcc-4.9/gcc/tree-streamer-in.c
+++ b/gcc-4.9/gcc/tree-streamer-in.c
@@ -496,7 +496,18 @@ unpack_value_fields (struct data_in *data_in, struct bitpack_d *bp, tree expr)
unpack_ts_type_common_value_fields (bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_EXP))
- SET_EXPR_LOCATION (expr, stream_input_location (bp, data_in));
+ {
+ SET_EXPR_LOCATION (expr, stream_input_location (bp, data_in));
+ if (code == MEM_REF
+ || code == TARGET_MEM_REF)
+ {
+ MR_DEPENDENCE_CLIQUE (expr)
+ = (unsigned)bp_unpack_value (bp, sizeof (short) * 8);
+ if (MR_DEPENDENCE_CLIQUE (expr) != 0)
+ MR_DEPENDENCE_BASE (expr)
+ = (unsigned)bp_unpack_value (bp, sizeof (short) * 8);
+ }
+ }
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
unpack_ts_block_value_fields (data_in, bp, expr);
diff --git a/gcc-4.9/gcc/tree-streamer-out.c b/gcc-4.9/gcc/tree-streamer-out.c
index 90dec0a1c..ff8f70135 100644
--- a/gcc-4.9/gcc/tree-streamer-out.c
+++ b/gcc-4.9/gcc/tree-streamer-out.c
@@ -454,7 +454,16 @@ streamer_pack_tree_bitfields (struct output_block *ob,
pack_ts_type_common_value_fields (bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_EXP))
- stream_output_location (ob, bp, EXPR_LOCATION (expr));
+ {
+ stream_output_location (ob, bp, EXPR_LOCATION (expr));
+ if (code == MEM_REF
+ || code == TARGET_MEM_REF)
+ {
+ bp_pack_value (bp, MR_DEPENDENCE_CLIQUE (expr), sizeof (short) * 8);
+ if (MR_DEPENDENCE_CLIQUE (expr) != 0)
+ bp_pack_value (bp, MR_DEPENDENCE_BASE (expr), sizeof (short) * 8);
+ }
+ }
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
pack_ts_block_value_fields (ob, bp, expr);
diff --git a/gcc-4.9/gcc/tree.h b/gcc-4.9/gcc/tree.h
index f13366f9e..4c465f437 100644
--- a/gcc-4.9/gcc/tree.h
+++ b/gcc-4.9/gcc/tree.h
@@ -1080,6 +1080,11 @@ extern void protected_set_expr_location (tree, location_t);
#define TMR_STEP(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 3))
#define TMR_INDEX2(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 4))
+#define MR_DEPENDENCE_CLIQUE(NODE) \
+ (TREE_CHECK2 (NODE, MEM_REF, TARGET_MEM_REF)->base.u.dependence_info.clique)
+#define MR_DEPENDENCE_BASE(NODE) \
+ (TREE_CHECK2 (NODE, MEM_REF, TARGET_MEM_REF)->base.u.dependence_info.base)
+
/* The operands of a BIND_EXPR. */
#define BIND_EXPR_VARS(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 0))
#define BIND_EXPR_BODY(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 1))