From 3cb960c703ec1fbbd2c0b9f821dc957a56aa5d00 Mon Sep 17 00:00:00 2001 From: Zdenek Dvorak Date: Sun, 13 May 2007 19:32:06 +0200 Subject: [PATCH] tree-scalar-evolution.c (resolve_mixers): Exported. * tree-scalar-evolution.c (resolve_mixers): Exported. * tree-scalar-evolution.h (resolve_mixers): Declare. * tree-data-ref.c (object_analysis, ptr_decl_may_alias_p, ptr_ptr_may_alias_p, may_alias_p, record_ptr_differ_p, record_record_differ_p, record_array_differ_p, array_ptr_differ_p, base_object_differ_p, base_addr_differ_p, analyze_array_indexes, init_array_ref, init_pointer_ref, analyze_indirect_ref, strip_conversion, analyze_offset_expr, address_analysis, object_analysis, analyze_offset): Removed. (dr_analyze_innermost, dr_analyze_indices, dr_analyze_alias, split_constant_offset, canonicalize_base_object_address, object_address_invariant_in_loop_p, disjoint_objects_p, dr_may_alias_p, dr_address_invariant_p): New functions. (create_data_ref): Use dr_analyze_innermost, dr_analyze_indices and dr_analyze_alias. (initialize_data_dependence_relation): Use dr_may_alias_p and object_address_invariant_in_loop_p. (compute_self_dependence): Handle the case when DDR_ARE_DEPENDENT (ddr) is chrec_dont_know. (find_data_references_in_stmt): Restrict the analysis of data references to the given loop nest. (find_data_references_in_loop): Made static. Pass loop nest to find_data_references_in_stmt. (compute_data_dependences_for_loop): Use DR_VOPS. (free_data_ref): Free DR_VOPS. * tree-data-ref.h (struct first_location_in_loop): Replaced by ... (struct innermost_loop_behavior): ... new. (struct base_object_info): Replaced by ... (struct indices): ... new. (struct dr_alias): New. (enum data_ref_type): Removed. (struct data_reference): Consist of struct innermost_loop_behavior, struct indices and struct dr_alias. (DR_SET_ACCESS_FNS, DR_FREE_ACCESS_FNS): Removed. (DR_MEMTAG): Renamed to ... (DR_SYMBOL_TAG): ... this. (find_data_references_in_loop): Declaration removed. * tree-vect-analyze.c (vect_compute_data_ref_alignment): Use DR_INIT instead of DR_OFFSET_MISALIGNMENT. DR_ALIGNED_TO is never NULL. (vect_analyze_data_refs): Use DR_SYMBOL_TAG instead of DR_MEMTAG. * tree-vect-transform.c (vect_create_data_ref_ptr): Ditto. * gcc.dg/vect/no-section-anchors-vect-69.c: Fix outcome. * gcc.dg/tree-ssa/loop-30.c: New test. From-SVN: r124655 --- gcc/ChangeLog | 44 + gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.dg/tree-ssa/loop-30.c | 14 + .../gcc.dg/vect/no-section-anchors-vect-69.c | 9 +- gcc/tree-data-ref.c | 1964 +++++--------------- gcc/tree-data-ref.h | 168 +- gcc/tree-scalar-evolution.c | 3 +- gcc/tree-scalar-evolution.h | 1 + gcc/tree-vect-analyze.c | 7 +- gcc/tree-vect-transform.c | 2 +- 10 files changed, 575 insertions(+), 1642 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/loop-30.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f454c19..e3380b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,47 @@ +2007-05-13 Zdenek Dvorak + + * tree-scalar-evolution.c (resolve_mixers): Exported. + * tree-scalar-evolution.h (resolve_mixers): Declare. + * tree-data-ref.c (object_analysis, ptr_decl_may_alias_p, + ptr_ptr_may_alias_p, may_alias_p, record_ptr_differ_p, + record_record_differ_p, record_array_differ_p, array_ptr_differ_p, + base_object_differ_p, base_addr_differ_p, analyze_array_indexes, + init_array_ref, init_pointer_ref, analyze_indirect_ref, + strip_conversion, analyze_offset_expr, address_analysis, + object_analysis, analyze_offset): Removed. + (dr_analyze_innermost, dr_analyze_indices, dr_analyze_alias, + split_constant_offset, canonicalize_base_object_address, + object_address_invariant_in_loop_p, disjoint_objects_p, + dr_may_alias_p, dr_address_invariant_p): New functions. + (create_data_ref): Use dr_analyze_innermost, dr_analyze_indices + and dr_analyze_alias. + (initialize_data_dependence_relation): Use dr_may_alias_p + and object_address_invariant_in_loop_p. + (compute_self_dependence): Handle the case when DDR_ARE_DEPENDENT (ddr) + is chrec_dont_know. + (find_data_references_in_stmt): Restrict the analysis of data references + to the given loop nest. + (find_data_references_in_loop): Made static. Pass loop nest to + find_data_references_in_stmt. + (compute_data_dependences_for_loop): Use DR_VOPS. + (free_data_ref): Free DR_VOPS. + * tree-data-ref.h (struct first_location_in_loop): Replaced by ... + (struct innermost_loop_behavior): ... new. + (struct base_object_info): Replaced by ... + (struct indices): ... new. + (struct dr_alias): New. + (enum data_ref_type): Removed. + (struct data_reference): Consist of struct innermost_loop_behavior, + struct indices and struct dr_alias. + (DR_SET_ACCESS_FNS, DR_FREE_ACCESS_FNS): Removed. + (DR_MEMTAG): Renamed to ... + (DR_SYMBOL_TAG): ... this. + (find_data_references_in_loop): Declaration removed. + * tree-vect-analyze.c (vect_compute_data_ref_alignment): Use DR_INIT + instead of DR_OFFSET_MISALIGNMENT. DR_ALIGNED_TO is never NULL. + (vect_analyze_data_refs): Use DR_SYMBOL_TAG instead of DR_MEMTAG. + * tree-vect-transform.c (vect_create_data_ref_ptr): Ditto. + 2007-05-13 Revital Eres * tree-ssa-dse.c (get_use_of_stmt_lhs): New function diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 73ae05a..7cb625a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-05-13 Zdenek Dvorak + + * gcc.dg/vect/no-section-anchors-vect-69.c: Fix outcome. + * gcc.dg/tree-ssa/loop-30.c: New test. + 2007-05-13 Richard Guenther * gcc.dg/tree-ssa/pr17141-1.c: Scan in forwprop2, xfail diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-30.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-30.c new file mode 100644 index 0000000..14d58e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-30.c @@ -0,0 +1,14 @@ +/* PR 25371 */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +void +slow_close(int n) +{ + int i; + double *mm; + for (i=0;i<2*n;i++) + for (i=0;i<2*n;i++) + *(mm+i*2*n+i) = 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/no-section-anchors-vect-69.c b/gcc/testsuite/gcc.dg/vect/no-section-anchors-vect-69.c index a590458..08ea7de 100644 --- a/gcc/testsuite/gcc.dg/vect/no-section-anchors-vect-69.c +++ b/gcc/testsuite/gcc.dg/vect/no-section-anchors-vect-69.c @@ -50,7 +50,7 @@ int main1 () abort (); } - /* 2. aligned on 8-bytes */ + /* 2. aligned */ for (i = 3; i < N-1; i++) { tmp1[2].a.n[1][2][i] = 6; @@ -63,7 +63,7 @@ int main1 () abort (); } - /* 3. aligned on 16-bytes */ + /* 3. aligned */ for (i = 0; i < N; i++) { for (j = 0; j < N; j++) @@ -113,8 +113,5 @@ int main (void) /* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" } } */ /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" } } */ -/* Loops 1,2,4 are unaligned on targets that require 16-byte alignment. - Loops 1,4 are unaligned on targets that require 8-byte alignment (ia64). */ -/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 3 "vect" { xfail ia64-*-* } } } */ -/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 2 "vect" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 2 "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index ac5aa50..1a81431 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -122,463 +122,9 @@ static struct datadep_stats int num_miv_unimplemented; } dependence_stats; -static tree object_analysis (tree, tree, bool, struct data_reference **, - tree *, tree *, tree *, tree *, tree *, - struct ptr_info_def **, subvar_t *); static bool subscript_dependence_tester_1 (struct data_dependence_relation *, struct data_reference *, struct data_reference *); - -/* Determine if PTR and DECL may alias, the result is put in ALIASED. - Return FALSE if there is no symbol memory tag for PTR. */ - -static bool -ptr_decl_may_alias_p (tree ptr, tree decl, - struct data_reference *ptr_dr, - bool *aliased) -{ - tree tag = NULL_TREE; - struct ptr_info_def *pi = DR_PTR_INFO (ptr_dr); - - gcc_assert (TREE_CODE (ptr) == SSA_NAME && DECL_P (decl)); - - if (pi) - tag = pi->name_mem_tag; - if (!tag) - tag = symbol_mem_tag (SSA_NAME_VAR (ptr)); - if (!tag) - tag = DR_MEMTAG (ptr_dr); - if (!tag) - return false; - - *aliased = is_aliased_with (tag, decl); - return true; -} - - -/* Determine if two pointers may alias, the result is put in ALIASED. - Return FALSE if there is no symbol memory tag for one of the pointers. */ - -static bool -ptr_ptr_may_alias_p (tree ptr_a, tree ptr_b, - struct data_reference *dra, - struct data_reference *drb, - bool *aliased) -{ - tree tag_a = NULL_TREE, tag_b = NULL_TREE; - struct ptr_info_def *pi_a = DR_PTR_INFO (dra); - struct ptr_info_def *pi_b = DR_PTR_INFO (drb); - bitmap bal1, bal2; - - if (pi_a && pi_a->name_mem_tag && pi_b && pi_b->name_mem_tag) - { - tag_a = pi_a->name_mem_tag; - tag_b = pi_b->name_mem_tag; - } - else - { - tag_a = symbol_mem_tag (SSA_NAME_VAR (ptr_a)); - if (!tag_a) - tag_a = DR_MEMTAG (dra); - if (!tag_a) - return false; - - tag_b = symbol_mem_tag (SSA_NAME_VAR (ptr_b)); - if (!tag_b) - tag_b = DR_MEMTAG (drb); - if (!tag_b) - return false; - } - bal1 = BITMAP_ALLOC (NULL); - bitmap_set_bit (bal1, DECL_UID (tag_a)); - if (MTAG_P (tag_a) && MTAG_ALIASES (tag_a)) - bitmap_ior_into (bal1, MTAG_ALIASES (tag_a)); - - bal2 = BITMAP_ALLOC (NULL); - bitmap_set_bit (bal2, DECL_UID (tag_b)); - if (MTAG_P (tag_b) && MTAG_ALIASES (tag_b)) - bitmap_ior_into (bal2, MTAG_ALIASES (tag_b)); - *aliased = bitmap_intersect_p (bal1, bal2); - - BITMAP_FREE (bal1); - BITMAP_FREE (bal2); - return true; -} - - -/* Determine if BASE_A and BASE_B may alias, the result is put in ALIASED. - Return FALSE if there is no symbol memory tag for one of the symbols. */ - -static bool -may_alias_p (tree base_a, tree base_b, - struct data_reference *dra, - struct data_reference *drb, - bool *aliased) -{ - if (TREE_CODE (base_a) == ADDR_EXPR || TREE_CODE (base_b) == ADDR_EXPR) - { - if (TREE_CODE (base_a) == ADDR_EXPR && TREE_CODE (base_b) == ADDR_EXPR) - { - *aliased = (TREE_OPERAND (base_a, 0) == TREE_OPERAND (base_b, 0)); - return true; - } - if (TREE_CODE (base_a) == ADDR_EXPR) - return ptr_decl_may_alias_p (base_b, TREE_OPERAND (base_a, 0), drb, - aliased); - else - return ptr_decl_may_alias_p (base_a, TREE_OPERAND (base_b, 0), dra, - aliased); - } - - return ptr_ptr_may_alias_p (base_a, base_b, dra, drb, aliased); -} - - -/* Determine if a pointer (BASE_A) and a record/union access (BASE_B) - are not aliased. Return TRUE if they differ. */ -static bool -record_ptr_differ_p (struct data_reference *dra, - struct data_reference *drb) -{ - bool aliased; - tree base_a = DR_BASE_OBJECT (dra); - tree base_b = DR_BASE_OBJECT (drb); - - if (TREE_CODE (base_b) != COMPONENT_REF) - return false; - - /* Peel COMPONENT_REFs to get to the base. Do not peel INDIRECT_REFs. - For a.b.c.d[i] we will get a, and for a.b->c.d[i] we will get a.b. - Probably will be unnecessary with struct alias analysis. */ - while (TREE_CODE (base_b) == COMPONENT_REF) - base_b = TREE_OPERAND (base_b, 0); - /* Compare a record/union access (b.c[i] or p->c[i]) and a pointer - ((*q)[i]). */ - if (TREE_CODE (base_a) == INDIRECT_REF - && ((TREE_CODE (base_b) == VAR_DECL - && (ptr_decl_may_alias_p (TREE_OPERAND (base_a, 0), base_b, dra, - &aliased) - && !aliased)) - || (TREE_CODE (base_b) == INDIRECT_REF - && (ptr_ptr_may_alias_p (TREE_OPERAND (base_a, 0), - TREE_OPERAND (base_b, 0), dra, drb, - &aliased) - && !aliased)))) - return true; - else - return false; -} - -/* Determine if two record/union accesses are aliased. Return TRUE if they - differ. */ -static bool -record_record_differ_p (struct data_reference *dra, - struct data_reference *drb) -{ - bool aliased; - tree base_a = DR_BASE_OBJECT (dra); - tree base_b = DR_BASE_OBJECT (drb); - - if (TREE_CODE (base_b) != COMPONENT_REF - || TREE_CODE (base_a) != COMPONENT_REF) - return false; - - /* Peel COMPONENT_REFs to get to the base. Do not peel INDIRECT_REFs. - For a.b.c.d[i] we will get a, and for a.b->c.d[i] we will get a.b. - Probably will be unnecessary with struct alias analysis. */ - while (TREE_CODE (base_b) == COMPONENT_REF) - base_b = TREE_OPERAND (base_b, 0); - while (TREE_CODE (base_a) == COMPONENT_REF) - base_a = TREE_OPERAND (base_a, 0); - - if (TREE_CODE (base_a) == INDIRECT_REF - && TREE_CODE (base_b) == INDIRECT_REF - && ptr_ptr_may_alias_p (TREE_OPERAND (base_a, 0), - TREE_OPERAND (base_b, 0), - dra, drb, &aliased) - && !aliased) - return true; - else - return false; -} - -/* Determine if an array access (BASE_A) and a record/union access (BASE_B) - are not aliased. Return TRUE if they differ. */ -static bool -record_array_differ_p (struct data_reference *dra, - struct data_reference *drb) -{ - bool aliased; - tree base_a = DR_BASE_OBJECT (dra); - tree base_b = DR_BASE_OBJECT (drb); - - if (TREE_CODE (base_b) != COMPONENT_REF) - return false; - - /* Peel COMPONENT_REFs to get to the base. Do not peel INDIRECT_REFs. - For a.b.c.d[i] we will get a, and for a.b->c.d[i] we will get a.b. - Probably will be unnecessary with struct alias analysis. */ - while (TREE_CODE (base_b) == COMPONENT_REF) - base_b = TREE_OPERAND (base_b, 0); - - /* Compare a record/union access (b.c[i] or p->c[i]) and an array access - (a[i]). In case of p->c[i] use alias analysis to verify that p is not - pointing to a. */ - if (TREE_CODE (base_a) == VAR_DECL - && (TREE_CODE (base_b) == VAR_DECL - || (TREE_CODE (base_b) == INDIRECT_REF - && (ptr_decl_may_alias_p (TREE_OPERAND (base_b, 0), base_a, drb, - &aliased) - && !aliased)))) - return true; - else - return false; -} - - -/* Determine if an array access (BASE_A) and a pointer (BASE_B) - are not aliased. Return TRUE if they differ. */ -static bool -array_ptr_differ_p (tree base_a, tree base_b, - struct data_reference *drb) -{ - bool aliased; - - /* In case one of the bases is a pointer (a[i] and (*p)[i]), we check with the - help of alias analysis that p is not pointing to a. */ - if (TREE_CODE (base_a) == VAR_DECL && TREE_CODE (base_b) == INDIRECT_REF - && (ptr_decl_may_alias_p (TREE_OPERAND (base_b, 0), base_a, drb, &aliased) - && !aliased)) - return true; - else - return false; -} - - -/* This is the simplest data dependence test: determines whether the - data references A and B access the same array/region. Returns - false when the property is not computable at compile time. - Otherwise return true, and DIFFER_P will record the result. This - utility will not be necessary when alias_sets_conflict_p will be - less conservative. */ - -static bool -base_object_differ_p (struct data_reference *a, - struct data_reference *b, - bool *differ_p) -{ - tree base_a = DR_BASE_OBJECT (a); - tree base_b = DR_BASE_OBJECT (b); - bool aliased; - - if (!base_a || !base_b) - return false; - - /* Determine if same base. Example: for the array accesses - a[i], b[i] or pointer accesses *a, *b, bases are a, b. */ - if (base_a == base_b) - { - *differ_p = false; - return true; - } - - /* For pointer based accesses, (*p)[i], (*q)[j], the bases are (*p) - and (*q) */ - if (TREE_CODE (base_a) == INDIRECT_REF && TREE_CODE (base_b) == INDIRECT_REF - && TREE_OPERAND (base_a, 0) == TREE_OPERAND (base_b, 0)) - { - *differ_p = false; - return true; - } - - /* Record/union based accesses - s.a[i], t.b[j]. bases are s.a,t.b. */ - if (TREE_CODE (base_a) == COMPONENT_REF && TREE_CODE (base_b) == COMPONENT_REF - && TREE_OPERAND (base_a, 0) == TREE_OPERAND (base_b, 0) - && TREE_OPERAND (base_a, 1) == TREE_OPERAND (base_b, 1)) - { - *differ_p = false; - return true; - } - - - /* Determine if different bases. */ - - /* At this point we know that base_a != base_b. However, pointer - accesses of the form x=(*p) and y=(*q), whose bases are p and q, - may still be pointing to the same base. In SSAed GIMPLE p and q will - be SSA_NAMES in this case. Therefore, here we check if they are - really two different declarations. */ - if (TREE_CODE (base_a) == VAR_DECL && TREE_CODE (base_b) == VAR_DECL) - { - *differ_p = true; - return true; - } - - /* In case one of the bases is a pointer (a[i] and (*p)[i]), we check with the - help of alias analysis that p is not pointing to a. */ - if (array_ptr_differ_p (base_a, base_b, b) - || array_ptr_differ_p (base_b, base_a, a)) - { - *differ_p = true; - return true; - } - - /* If the bases are pointers ((*q)[i] and (*p)[i]), we check with the - help of alias analysis they don't point to the same bases. */ - if (TREE_CODE (base_a) == INDIRECT_REF && TREE_CODE (base_b) == INDIRECT_REF - && (may_alias_p (TREE_OPERAND (base_a, 0), TREE_OPERAND (base_b, 0), a, b, - &aliased) - && !aliased)) - { - *differ_p = true; - return true; - } - - /* Compare two record/union bases s.a and t.b: s != t or (a != b and - s and t are not unions). */ - if (TREE_CODE (base_a) == COMPONENT_REF && TREE_CODE (base_b) == COMPONENT_REF - && ((TREE_CODE (TREE_OPERAND (base_a, 0)) == VAR_DECL - && TREE_CODE (TREE_OPERAND (base_b, 0)) == VAR_DECL - && TREE_OPERAND (base_a, 0) != TREE_OPERAND (base_b, 0)) - || (TREE_CODE (TREE_TYPE (TREE_OPERAND (base_a, 0))) == RECORD_TYPE - && TREE_CODE (TREE_TYPE (TREE_OPERAND (base_b, 0))) == RECORD_TYPE - && TREE_OPERAND (base_a, 1) != TREE_OPERAND (base_b, 1)))) - { - *differ_p = true; - return true; - } - - /* Compare a record/union access (b.c[i] or p->c[i]) and a pointer - ((*q)[i]). */ - if (record_ptr_differ_p (a, b) || record_ptr_differ_p (b, a)) - { - *differ_p = true; - return true; - } - - /* Compare a record/union access (b.c[i] or p->c[i]) and an array access - (a[i]). In case of p->c[i] use alias analysis to verify that p is not - pointing to a. */ - if (record_array_differ_p (a, b) || record_array_differ_p (b, a)) - { - *differ_p = true; - return true; - } - - /* Compare two record/union accesses (b.c[i] or p->c[i]). */ - if (record_record_differ_p (a, b)) - { - *differ_p = true; - return true; - } - - return false; -} - -/* Function base_addr_differ_p. - - This is the simplest data dependence test: determines whether the - data references DRA and DRB access the same array/region. Returns - false when the property is not computable at compile time. - Otherwise return true, and DIFFER_P will record the result. - - The algorithm: - 1. if (both DRA and DRB are represented as arrays) - compare DRA.BASE_OBJECT and DRB.BASE_OBJECT - 2. else if (both DRA and DRB are represented as pointers) - try to prove that DRA.FIRST_LOCATION == DRB.FIRST_LOCATION - 3. else if (DRA and DRB are represented differently or 2. fails) - only try to prove that the bases are surely different -*/ - -static bool -base_addr_differ_p (struct data_reference *dra, - struct data_reference *drb, - bool *differ_p) -{ - tree addr_a = DR_BASE_ADDRESS (dra); - tree addr_b = DR_BASE_ADDRESS (drb); - tree type_a, type_b; - tree decl_a, decl_b; - bool aliased; - - if (!addr_a || !addr_b) - return false; - - type_a = TREE_TYPE (addr_a); - type_b = TREE_TYPE (addr_b); - - gcc_assert (POINTER_TYPE_P (type_a) && POINTER_TYPE_P (type_b)); - - /* 1. if (both DRA and DRB are represented as arrays) - compare DRA.BASE_OBJECT and DRB.BASE_OBJECT. */ - if (DR_TYPE (dra) == ARRAY_REF_TYPE && DR_TYPE (drb) == ARRAY_REF_TYPE) - return base_object_differ_p (dra, drb, differ_p); - - /* 2. else if (both DRA and DRB are represented as pointers) - try to prove that DRA.FIRST_LOCATION == DRB.FIRST_LOCATION. */ - /* If base addresses are the same, we check the offsets, since the access of - the data-ref is described by {base addr + offset} and its access function, - i.e., in order to decide whether the bases of data-refs are the same we - compare both base addresses and offsets. */ - if (DR_TYPE (dra) == POINTER_REF_TYPE && DR_TYPE (drb) == POINTER_REF_TYPE - && (addr_a == addr_b - || (TREE_CODE (addr_a) == ADDR_EXPR && TREE_CODE (addr_b) == ADDR_EXPR - && TREE_OPERAND (addr_a, 0) == TREE_OPERAND (addr_b, 0)))) - { - /* Compare offsets. */ - tree offset_a = DR_OFFSET (dra); - tree offset_b = DR_OFFSET (drb); - - STRIP_NOPS (offset_a); - STRIP_NOPS (offset_b); - - /* FORNOW: we only compare offsets that are MULT_EXPR, i.e., we don't handle - PLUS_EXPR. */ - if (offset_a == offset_b - || (TREE_CODE (offset_a) == MULT_EXPR - && TREE_CODE (offset_b) == MULT_EXPR - && TREE_OPERAND (offset_a, 0) == TREE_OPERAND (offset_b, 0) - && TREE_OPERAND (offset_a, 1) == TREE_OPERAND (offset_b, 1))) - { - *differ_p = false; - return true; - } - } - - /* 3. else if (DRA and DRB are represented differently or 2. fails) - only try to prove that the bases are surely different. */ - - /* Apply alias analysis. */ - if (may_alias_p (addr_a, addr_b, dra, drb, &aliased) && !aliased) - { - *differ_p = true; - return true; - } - - /* An instruction writing through a restricted pointer is "independent" of any - instruction reading or writing through a different restricted pointer, - in the same block/scope. */ - else if (TYPE_RESTRICT (type_a) - && TYPE_RESTRICT (type_b) - && (!DR_IS_READ (drb) || !DR_IS_READ (dra)) - && TREE_CODE (DR_BASE_ADDRESS (dra)) == SSA_NAME - && (decl_a = SSA_NAME_VAR (DR_BASE_ADDRESS (dra))) - && TREE_CODE (decl_a) == PARM_DECL - && TREE_CODE (DECL_CONTEXT (decl_a)) == FUNCTION_DECL - && TREE_CODE (DR_BASE_ADDRESS (drb)) == SSA_NAME - && (decl_b = SSA_NAME_VAR (DR_BASE_ADDRESS (drb))) - && TREE_CODE (decl_b) == PARM_DECL - && TREE_CODE (DECL_CONTEXT (decl_b)) == FUNCTION_DECL - && DECL_CONTEXT (decl_a) == DECL_CONTEXT (decl_b)) - { - *differ_p = true; - return true; - } - - return false; -} - /* Returns true iff A divides B. */ static inline bool @@ -940,1125 +486,334 @@ dump_ddrs (FILE *file, VEC (ddr_p, heap) *ddrs) fprintf (file, "\n\n"); } - - -/* Given an ARRAY_REF node REF, records its access functions. - Example: given A[i][3], record in ACCESS_FNS the opnd1 function, - i.e. the constant "3", then recursively call the function on opnd0, - i.e. the ARRAY_REF "A[i]". - The function returns the base name: "A". */ - -static tree -analyze_array_indexes (struct loop *loop, - VEC(tree,heap) **access_fns, - tree ref, tree stmt) -{ - tree opnd0, opnd1; - tree access_fn; - - opnd0 = TREE_OPERAND (ref, 0); - opnd1 = TREE_OPERAND (ref, 1); +/* Expresses EXP as VAR + OFF, where off is a constant. The type of OFF + will be ssizetype. */ - /* The detection of the evolution function for this data access is - postponed until the dependence test. This lazy strategy avoids - the computation of access functions that are of no interest for - the optimizers. */ - access_fn = instantiate_parameters - (loop, analyze_scalar_evolution (loop, opnd1)); - - VEC_safe_push (tree, heap, *access_fns, access_fn); - - /* Recursively record other array access functions. */ - if (TREE_CODE (opnd0) == ARRAY_REF) - return analyze_array_indexes (loop, access_fns, opnd0, stmt); - - /* Return the base name of the data access. */ - else - return opnd0; -} - -/* For a data reference REF contained in the statement STMT, initialize - a DATA_REFERENCE structure, and return it. IS_READ flag has to be - set to true when REF is in the right hand side of an - assignment. */ - -static struct data_reference * -init_array_ref (tree stmt, tree ref, bool is_read) -{ - struct loop *loop = loop_containing_stmt (stmt); - VEC(tree,heap) *acc_fns = VEC_alloc (tree, heap, 3); - struct data_reference *res = XNEW (struct data_reference);; - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "(init_array_ref \n"); - fprintf (dump_file, " (ref = "); - print_generic_stmt (dump_file, ref, 0); - fprintf (dump_file, ")\n"); - } - - DR_STMT (res) = stmt; - DR_REF (res) = ref; - DR_BASE_OBJECT (res) = analyze_array_indexes (loop, &acc_fns, ref, stmt); - DR_TYPE (res) = ARRAY_REF_TYPE; - DR_SET_ACCESS_FNS (res, acc_fns); - DR_IS_READ (res) = is_read; - DR_BASE_ADDRESS (res) = NULL_TREE; - DR_OFFSET (res) = NULL_TREE; - DR_INIT (res) = NULL_TREE; - DR_STEP (res) = NULL_TREE; - DR_OFFSET_MISALIGNMENT (res) = NULL_TREE; - DR_MEMTAG (res) = NULL_TREE; - DR_PTR_INFO (res) = NULL; - - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, ")\n"); - - return res; -} - -/* For a data reference REF contained in the statement STMT, initialize - a DATA_REFERENCE structure, and return it. */ - -static struct data_reference * -init_pointer_ref (tree stmt, tree ref, tree access_fn, bool is_read, - tree base_address, tree step, struct ptr_info_def *ptr_info) -{ - struct data_reference *res = XNEW (struct data_reference); - VEC(tree,heap) *acc_fns = VEC_alloc (tree, heap, 3); - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "(init_pointer_ref \n"); - fprintf (dump_file, " (ref = "); - print_generic_stmt (dump_file, ref, 0); - fprintf (dump_file, ")\n"); - } - - DR_STMT (res) = stmt; - DR_REF (res) = ref; - DR_BASE_OBJECT (res) = NULL_TREE; - DR_TYPE (res) = POINTER_REF_TYPE; - DR_SET_ACCESS_FNS (res, acc_fns); - VEC_quick_push (tree, DR_ACCESS_FNS (res), access_fn); - DR_IS_READ (res) = is_read; - DR_BASE_ADDRESS (res) = base_address; - DR_OFFSET (res) = NULL_TREE; - DR_INIT (res) = NULL_TREE; - DR_STEP (res) = step; - DR_OFFSET_MISALIGNMENT (res) = NULL_TREE; - DR_MEMTAG (res) = NULL_TREE; - DR_PTR_INFO (res) = ptr_info; - - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, ")\n"); - - return res; -} - -/* Analyze an indirect memory reference, REF, that comes from STMT. - IS_READ is true if this is an indirect load, and false if it is - an indirect store. - Return a new data reference structure representing the indirect_ref, or - NULL if we cannot describe the access function. */ - -static struct data_reference * -analyze_indirect_ref (tree stmt, tree ref, bool is_read) -{ - struct loop *loop = loop_containing_stmt (stmt); - tree ptr_ref = TREE_OPERAND (ref, 0); - tree access_fn = analyze_scalar_evolution (loop, ptr_ref); - tree init = initial_condition_in_loop_num (access_fn, loop->num); - tree base_address = NULL_TREE, evolution, step = NULL_TREE; - struct ptr_info_def *ptr_info = NULL; - - if (TREE_CODE (ptr_ref) == SSA_NAME) - ptr_info = SSA_NAME_PTR_INFO (ptr_ref); - - STRIP_NOPS (init); - if (access_fn == chrec_dont_know || !init || init == chrec_dont_know) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nBad access function of ptr: "); - print_generic_expr (dump_file, ref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL; - } - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nAccess function of ptr: "); - print_generic_expr (dump_file, access_fn, TDF_SLIM); - fprintf (dump_file, "\n"); - } - - if (!expr_invariant_in_loop_p (loop, init)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "\ninitial condition is not loop invariant.\n"); - } - else - { - base_address = init; - evolution = evolution_part_in_loop_num (access_fn, loop->num); - if (evolution != chrec_dont_know) - { - if (!evolution) - step = ssize_int (0); - else - { - if (TREE_CODE (evolution) == INTEGER_CST) - step = fold_convert (ssizetype, evolution); - else - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "\nnon constant step for ptr access.\n"); - } - } - else - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "\nunknown evolution of ptr.\n"); - } - return init_pointer_ref (stmt, ref, access_fn, is_read, base_address, - step, ptr_info); -} - -/* Function strip_conversions - - Strip conversions that don't narrow the mode. */ - -static tree -strip_conversion (tree expr) -{ - tree to, ti, oprnd0; - - while (TREE_CODE (expr) == NOP_EXPR || TREE_CODE (expr) == CONVERT_EXPR) - { - to = TREE_TYPE (expr); - oprnd0 = TREE_OPERAND (expr, 0); - ti = TREE_TYPE (oprnd0); - - if (!INTEGRAL_TYPE_P (to) || !INTEGRAL_TYPE_P (ti)) - return NULL_TREE; - if (GET_MODE_SIZE (TYPE_MODE (to)) < GET_MODE_SIZE (TYPE_MODE (ti))) - return NULL_TREE; - - expr = oprnd0; - } - return expr; -} - - -/* Function analyze_offset_expr - - Given an offset expression EXPR received from get_inner_reference, analyze - it and create an expression for INITIAL_OFFSET by substituting the variables - of EXPR with initial_condition of the corresponding access_fn in the loop. - E.g., - for i - for (j = 3; j < N; j++) - a[j].b[i][j] = 0; - - For a[j].b[i][j], EXPR will be 'i * C_i + j * C_j + C'. 'i' cannot be - substituted, since its access_fn in the inner loop is i. 'j' will be - substituted with 3. An INITIAL_OFFSET will be 'i * C_i + C`', where - C` = 3 * C_j + C. - - Compute MISALIGN (the misalignment of the data reference initial access from - its base). Misalignment can be calculated only if all the variables can be - substituted with constants, otherwise, we record maximum possible alignment - in ALIGNED_TO. In the above example, since 'i' cannot be substituted, MISALIGN - will be NULL_TREE, and the biggest divider of C_i (a power of 2) will be - recorded in ALIGNED_TO. - - STEP is an evolution of the data reference in this loop in bytes. - In the above example, STEP is C_j. - - Return FALSE, if the analysis fails, e.g., there is no access_fn for a - variable. In this case, all the outputs (INITIAL_OFFSET, MISALIGN, ALIGNED_TO - and STEP) are NULL_TREEs. Otherwise, return TRUE. - -*/ - -static bool -analyze_offset_expr (tree expr, - struct loop *loop, - tree *initial_offset, - tree *misalign, - tree *aligned_to, - tree *step) +static void +split_constant_offset (tree exp, tree *var, tree *off) { - tree oprnd0; - tree oprnd1; - tree left_offset = ssize_int (0); - tree right_offset = ssize_int (0); - tree left_misalign = ssize_int (0); - tree right_misalign = ssize_int (0); - tree left_step = ssize_int (0); - tree right_step = ssize_int (0); - enum tree_code code; - tree init, evolution; - tree left_aligned_to = NULL_TREE, right_aligned_to = NULL_TREE; - - *step = NULL_TREE; - *misalign = NULL_TREE; - *aligned_to = NULL_TREE; - *initial_offset = NULL_TREE; - - /* Strip conversions that don't narrow the mode. */ - expr = strip_conversion (expr); - if (!expr) - return false; - - /* Stop conditions: - 1. Constant. */ - if (TREE_CODE (expr) == INTEGER_CST) - { - *initial_offset = fold_convert (ssizetype, expr); - *misalign = fold_convert (ssizetype, expr); - *step = ssize_int (0); - return true; - } - - /* 2. Variable. Try to substitute with initial_condition of the corresponding - access_fn in the current loop. */ - if (SSA_VAR_P (expr)) - { - tree access_fn = analyze_scalar_evolution (loop, expr); - - if (access_fn == chrec_dont_know) - /* No access_fn. */ - return false; + tree type = TREE_TYPE (exp), otype; + tree var0, var1; + tree off0, off1; - init = initial_condition_in_loop_num (access_fn, loop->num); - if (!expr_invariant_in_loop_p (loop, init)) - /* Not enough information: may be not loop invariant. - E.g., for a[b[i]], we get a[D], where D=b[i]. EXPR is D, its - initial_condition is D, but it depends on i - loop's induction - variable. */ - return false; - - evolution = evolution_part_in_loop_num (access_fn, loop->num); - if (evolution && TREE_CODE (evolution) != INTEGER_CST) - /* Evolution is not constant. */ - return false; - - if (TREE_CODE (init) == INTEGER_CST) - *misalign = fold_convert (ssizetype, init); - else - /* Not constant, misalignment cannot be calculated. */ - *misalign = NULL_TREE; - - *initial_offset = fold_convert (ssizetype, init); - - *step = evolution ? fold_convert (ssizetype, evolution) : ssize_int (0); - return true; - } + *var = exp; + STRIP_NOPS (exp); + otype = TREE_TYPE (exp); - /* Recursive computation. */ - if (!BINARY_CLASS_P (expr)) + switch (TREE_CODE (exp)) { - /* We expect to get binary expressions (PLUS/MINUS and MULT). */ - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nNot binary expression "); - print_generic_expr (dump_file, expr, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return false; - } - oprnd0 = TREE_OPERAND (expr, 0); - oprnd1 = TREE_OPERAND (expr, 1); + case INTEGER_CST: + *var = build_int_cst (type, 0); + *off = fold_convert (ssizetype, exp); + return; - if (!analyze_offset_expr (oprnd0, loop, &left_offset, &left_misalign, - &left_aligned_to, &left_step) - || !analyze_offset_expr (oprnd1, loop, &right_offset, &right_misalign, - &right_aligned_to, &right_step)) - return false; + case PLUS_EXPR: + case MINUS_EXPR: + split_constant_offset (TREE_OPERAND (exp, 0), &var0, &off0); + split_constant_offset (TREE_OPERAND (exp, 1), &var1, &off1); + *var = fold_convert (type, fold_build2 (TREE_CODE (exp), otype, + var0, var1)); + *off = size_binop (TREE_CODE (exp), off0, off1); + return; - /* The type of the operation: plus, minus or mult. */ - code = TREE_CODE (expr); - switch (code) - { case MULT_EXPR: - if (TREE_CODE (right_offset) != INTEGER_CST) - /* RIGHT_OFFSET can be not constant. For example, for arrays of variable - sized types. - FORNOW: We don't support such cases. */ - return false; - - /* Strip conversions that don't narrow the mode. */ - left_offset = strip_conversion (left_offset); - if (!left_offset) - return false; - /* Misalignment computation. */ - if (SSA_VAR_P (left_offset)) - { - /* If the left side contains variables that can't be substituted with - constants, the misalignment is unknown. However, if the right side - is a multiple of some alignment, we know that the expression is - aligned to it. Therefore, we record such maximum possible value. - */ - *misalign = NULL_TREE; - *aligned_to = ssize_int (highest_pow2_factor (right_offset)); - } - else - { - /* The left operand was successfully substituted with constant. */ - if (left_misalign) - { - /* In case of EXPR '(i * C1 + j) * C2', LEFT_MISALIGN is - NULL_TREE. */ - *misalign = size_binop (code, left_misalign, right_misalign); - if (left_aligned_to && right_aligned_to) - *aligned_to = size_binop (MIN_EXPR, left_aligned_to, - right_aligned_to); - else - *aligned_to = left_aligned_to ? - left_aligned_to : right_aligned_to; - } - else - *misalign = NULL_TREE; - } + off1 = TREE_OPERAND (exp, 1); + if (TREE_CODE (off1) != INTEGER_CST) + break; + + split_constant_offset (TREE_OPERAND (exp, 0), &var0, &off0); + *var = fold_convert (type, fold_build2 (MULT_EXPR, otype, + var0, off1)); + *off = size_binop (MULT_EXPR, off0, fold_convert (ssizetype, off1)); + return; - /* Step calculation. */ - /* Multiply the step by the right operand. */ - *step = size_binop (MULT_EXPR, left_step, right_offset); - break; - - case PLUS_EXPR: - case MINUS_EXPR: - /* Combine the recursive calculations for step and misalignment. */ - *step = size_binop (code, left_step, right_step); + case ADDR_EXPR: + { + tree op, base, poffset; + HOST_WIDE_INT pbitsize, pbitpos; + enum machine_mode pmode; + int punsignedp, pvolatilep; - /* Unknown alignment. */ - if ((!left_misalign && !left_aligned_to) - || (!right_misalign && !right_aligned_to)) - { - *misalign = NULL_TREE; - *aligned_to = NULL_TREE; + op = TREE_OPERAND (exp, 0); + if (!handled_component_p (op)) break; - } - if (left_misalign && right_misalign) - *misalign = size_binop (code, left_misalign, right_misalign); - else - *misalign = left_misalign ? left_misalign : right_misalign; + base = get_inner_reference (op, &pbitsize, &pbitpos, &poffset, + &pmode, &punsignedp, &pvolatilep, false); - if (left_aligned_to && right_aligned_to) - *aligned_to = size_binop (MIN_EXPR, left_aligned_to, right_aligned_to); - else - *aligned_to = left_aligned_to ? left_aligned_to : right_aligned_to; + if (pbitpos % BITS_PER_UNIT != 0) + break; + base = build_fold_addr_expr (base); + off0 = ssize_int (pbitpos / BITS_PER_UNIT); - break; + if (poffset) + { + split_constant_offset (poffset, &poffset, &off1); + off0 = size_binop (PLUS_EXPR, off0, off1); + base = fold_build2 (PLUS_EXPR, TREE_TYPE (base), + base, + fold_convert (TREE_TYPE (base), poffset)); + } + + *var = fold_convert (type, base); + *off = off0; + return; + } default: - gcc_unreachable (); + break; } - /* Compute offset. */ - *initial_offset = fold_convert (ssizetype, - fold_build2 (code, TREE_TYPE (left_offset), - left_offset, - right_offset)); - return true; + *off = ssize_int (0); } -/* Function address_analysis - - Return the BASE of the address expression EXPR. - Also compute the OFFSET from BASE, MISALIGN and STEP. - - Input: - EXPR - the address expression that is being analyzed - STMT - the statement that contains EXPR or its original memory reference - IS_READ - TRUE if STMT reads from EXPR, FALSE if writes to EXPR - DR - data_reference struct for the original memory reference - - Output: - BASE (returned value) - the base of the data reference EXPR. - INITIAL_OFFSET - initial offset of EXPR from BASE (an expression) - MISALIGN - offset of EXPR from BASE in bytes (a constant) or NULL_TREE if the - computation is impossible - ALIGNED_TO - maximum alignment of EXPR or NULL_TREE if MISALIGN can be - calculated (doesn't depend on variables) - STEP - evolution of EXPR in the loop - - If something unexpected is encountered (an unsupported form of data-ref), - then NULL_TREE is returned. - */ +/* Returns the address ADDR of an object in a canonical shape (without nop + casts, and with type of pointer to the object). */ static tree -address_analysis (tree expr, tree stmt, bool is_read, struct data_reference *dr, - tree *offset, tree *misalign, tree *aligned_to, tree *step) +canonicalize_base_object_address (tree addr) { - tree oprnd0, oprnd1, base_address, offset_expr, base_addr0, base_addr1; - tree address_offset = ssize_int (0), address_misalign = ssize_int (0); - tree dummy, address_aligned_to = NULL_TREE; - struct ptr_info_def *dummy1; - subvar_t dummy2; - - switch (TREE_CODE (expr)) - { - case PLUS_EXPR: - case MINUS_EXPR: - /* EXPR is of form {base +/- offset} (or {offset +/- base}). */ - oprnd0 = TREE_OPERAND (expr, 0); - oprnd1 = TREE_OPERAND (expr, 1); + STRIP_NOPS (addr); - STRIP_NOPS (oprnd0); - STRIP_NOPS (oprnd1); - - /* Recursively try to find the base of the address contained in EXPR. - For offset, the returned base will be NULL. */ - base_addr0 = address_analysis (oprnd0, stmt, is_read, dr, &address_offset, - &address_misalign, &address_aligned_to, - step); - - base_addr1 = address_analysis (oprnd1, stmt, is_read, dr, &address_offset, - &address_misalign, &address_aligned_to, - step); - - /* We support cases where only one of the operands contains an - address. */ - if ((base_addr0 && base_addr1) || (!base_addr0 && !base_addr1)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, - "\neither more than one address or no addresses in expr "); - print_generic_expr (dump_file, expr, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL_TREE; - } + if (TREE_CODE (addr) != ADDR_EXPR) + return addr; - /* To revert STRIP_NOPS. */ - oprnd0 = TREE_OPERAND (expr, 0); - oprnd1 = TREE_OPERAND (expr, 1); - - offset_expr = base_addr0 ? - fold_convert (ssizetype, oprnd1) : fold_convert (ssizetype, oprnd0); - - /* EXPR is of form {base +/- offset} (or {offset +/- base}). If offset is - a number, we can add it to the misalignment value calculated for base, - otherwise, misalignment is NULL. */ - if (TREE_CODE (offset_expr) == INTEGER_CST && address_misalign) - { - *misalign = size_binop (TREE_CODE (expr), address_misalign, - offset_expr); - *aligned_to = address_aligned_to; - } - else - { - *misalign = NULL_TREE; - *aligned_to = NULL_TREE; - } - - /* Combine offset (from EXPR {base + offset}) with the offset calculated - for base. */ - *offset = size_binop (TREE_CODE (expr), address_offset, offset_expr); - return base_addr0 ? base_addr0 : base_addr1; - - case ADDR_EXPR: - base_address = object_analysis (TREE_OPERAND (expr, 0), stmt, is_read, - &dr, offset, misalign, aligned_to, step, - &dummy, &dummy1, &dummy2); - return base_address; - - case SSA_NAME: - if (!POINTER_TYPE_P (TREE_TYPE (expr))) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nnot pointer SSA_NAME "); - print_generic_expr (dump_file, expr, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL_TREE; - } - *aligned_to = ssize_int (TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (expr)))); - *misalign = ssize_int (0); - *offset = ssize_int (0); - *step = ssize_int (0); - return expr; - - default: - return NULL_TREE; - } + return build_fold_addr_expr (TREE_OPERAND (addr, 0)); } +/* Analyzes the behavior of the memory reference DR in the innermost loop that + contains it. */ -/* Function object_analysis - - Create a data-reference structure DR for MEMREF. - Return the BASE of the data reference MEMREF if the analysis is possible. - Also compute the INITIAL_OFFSET from BASE, MISALIGN and STEP. - E.g., for EXPR a.b[i] + 4B, BASE is a, and OFFSET is the overall offset - 'a.b[i] + 4B' from a (can be an expression), MISALIGN is an OFFSET - instantiated with initial_conditions of access_functions of variables, - and STEP is the evolution of the DR_REF in this loop. - - Function get_inner_reference is used for the above in case of ARRAY_REF and - COMPONENT_REF. - - The structure of the function is as follows: - Part 1: - Case 1. For handled_component_p refs - 1.1 build data-reference structure for MEMREF - 1.2 call get_inner_reference - 1.2.1 analyze offset expr received from get_inner_reference - (fall through with BASE) - Case 2. For declarations - 2.1 set MEMTAG - Case 3. For INDIRECT_REFs - 3.1 build data-reference structure for MEMREF - 3.2 analyze evolution and initial condition of MEMREF - 3.3 set data-reference structure for MEMREF - 3.4 call address_analysis to analyze INIT of the access function - 3.5 extract memory tag - - Part 2: - Combine the results of object and address analysis to calculate - INITIAL_OFFSET, STEP and misalignment info. - - Input: - MEMREF - the memory reference that is being analyzed - STMT - the statement that contains MEMREF - IS_READ - TRUE if STMT reads from MEMREF, FALSE if writes to MEMREF - - Output: - BASE_ADDRESS (returned value) - the base address of the data reference MEMREF - E.g, if MEMREF is a.b[k].c[i][j] the returned - base is &a. - DR - data_reference struct for MEMREF - INITIAL_OFFSET - initial offset of MEMREF from BASE (an expression) - MISALIGN - offset of MEMREF from BASE in bytes (a constant) modulo alignment of - ALIGNMENT or NULL_TREE if the computation is impossible - ALIGNED_TO - maximum alignment of EXPR or NULL_TREE if MISALIGN can be - calculated (doesn't depend on variables) - STEP - evolution of the DR_REF in the loop - MEMTAG - memory tag for aliasing purposes - PTR_INFO - NULL or points-to aliasing info from a pointer SSA_NAME - SUBVARS - Sub-variables of the variable - - If the analysis of MEMREF evolution in the loop fails, NULL_TREE is returned, - but DR can be created anyway. - -*/ - -static tree -object_analysis (tree memref, tree stmt, bool is_read, - struct data_reference **dr, tree *offset, tree *misalign, - tree *aligned_to, tree *step, tree *memtag, - struct ptr_info_def **ptr_info, subvar_t *subvars) +static void +dr_analyze_innermost (struct data_reference *dr) { - tree base = NULL_TREE, base_address = NULL_TREE; - tree object_offset = ssize_int (0), object_misalign = ssize_int (0); - tree object_step = ssize_int (0), address_step = ssize_int (0); - tree address_offset = ssize_int (0), address_misalign = ssize_int (0); + tree stmt = DR_STMT (dr); + struct loop *loop = loop_containing_stmt (stmt); + tree ref = DR_REF (dr); HOST_WIDE_INT pbitsize, pbitpos; - tree poffset, bit_pos_in_bytes; + tree base, poffset; enum machine_mode pmode; int punsignedp, pvolatilep; - tree ptr_step = ssize_int (0), ptr_init = NULL_TREE; - struct loop *loop = loop_containing_stmt (stmt); - struct data_reference *ptr_dr = NULL; - tree object_aligned_to = NULL_TREE, address_aligned_to = NULL_TREE; - tree comp_ref = NULL_TREE; + affine_iv base_iv, offset_iv; + tree init, dinit, step; + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "analyze_innermost: "); - *ptr_info = NULL; + base = get_inner_reference (ref, &pbitsize, &pbitpos, &poffset, + &pmode, &punsignedp, &pvolatilep, false); + gcc_assert (base != NULL_TREE); - /* Part 1: */ - /* Case 1. handled_component_p refs. */ - if (handled_component_p (memref)) + if (pbitpos % BITS_PER_UNIT != 0) { - /* 1.1 build data-reference structure for MEMREF. */ - if (!(*dr)) - { - if (TREE_CODE (memref) == ARRAY_REF) - *dr = init_array_ref (stmt, memref, is_read); - else if (TREE_CODE (memref) == COMPONENT_REF) - comp_ref = memref; - else - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\ndata-ref of unsupported type "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL_TREE; - } - } + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "failed: bit offset alignment.\n"); + return; + } - /* 1.2 call get_inner_reference. */ - /* Find the base and the offset from it. */ - base = get_inner_reference (memref, &pbitsize, &pbitpos, &poffset, - &pmode, &punsignedp, &pvolatilep, false); - if (!base) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nfailed to get inner ref for "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL_TREE; - } + base = build_fold_addr_expr (base); + if (!simple_iv (loop, stmt, base, &base_iv, false)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "failed: evolution of base is not affine.\n"); + return; + } + if (!poffset) + { + offset_iv.base = ssize_int (0); + offset_iv.step = ssize_int (0); + } + else if (!simple_iv (loop, stmt, poffset, &offset_iv, false)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "failed: evolution of offset is not affine.\n"); + return; + } - /* 1.2.1 analyze offset expr received from get_inner_reference. */ - if (poffset - && !analyze_offset_expr (poffset, loop, &object_offset, - &object_misalign, &object_aligned_to, - &object_step)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nfailed to compute offset or step for "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL_TREE; - } + init = ssize_int (pbitpos / BITS_PER_UNIT); + split_constant_offset (base_iv.base, &base_iv.base, &dinit); + init = size_binop (PLUS_EXPR, init, dinit); + split_constant_offset (offset_iv.base, &offset_iv.base, &dinit); + init = size_binop (PLUS_EXPR, init, dinit); - /* Add bit position to OFFSET and MISALIGN. */ + step = size_binop (PLUS_EXPR, + fold_convert (ssizetype, base_iv.step), + fold_convert (ssizetype, offset_iv.step)); - bit_pos_in_bytes = ssize_int (pbitpos/BITS_PER_UNIT); - /* Check that there is no remainder in bits. */ - if (pbitpos%BITS_PER_UNIT) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "\nbit offset alignment.\n"); - return NULL_TREE; - } - object_offset = size_binop (PLUS_EXPR, bit_pos_in_bytes, object_offset); - if (object_misalign) - object_misalign = size_binop (PLUS_EXPR, object_misalign, - bit_pos_in_bytes); - - memref = base; /* To continue analysis of BASE. */ - /* fall through */ - } - - /* Part 1: Case 2. Declarations. */ - if (DECL_P (memref)) - { - /* We expect to get a decl only if we already have a DR, or with - COMPONENT_REFs of type 'a[i].b'. */ - if (!(*dr)) - { - if (comp_ref && TREE_CODE (TREE_OPERAND (comp_ref, 0)) == ARRAY_REF) - { - *dr = init_array_ref (stmt, TREE_OPERAND (comp_ref, 0), is_read); - if (DR_NUM_DIMENSIONS (*dr) != 1) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\n multidimensional component ref "); - print_generic_expr (dump_file, comp_ref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL_TREE; - } - } - else - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nunhandled decl "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL_TREE; - } - } + DR_BASE_ADDRESS (dr) = canonicalize_base_object_address (base_iv.base); - /* TODO: if during the analysis of INDIRECT_REF we get to an object, put - the object in BASE_OBJECT field if we can prove that this is O.K., - i.e., the data-ref access is bounded by the bounds of the BASE_OBJECT. - (e.g., if the object is an array base 'a', where 'a[N]', we must prove - that every access with 'p' (the original INDIRECT_REF based on '&a') - in the loop is within the array boundaries - from a[0] to a[N-1]). - Otherwise, our alias analysis can be incorrect. - Even if an access function based on BASE_OBJECT can't be build, update - BASE_OBJECT field to enable us to prove that two data-refs are - different (without access function, distance analysis is impossible). - */ - if (SSA_VAR_P (memref) && var_can_have_subvars (memref)) - *subvars = get_subvars_for_var (memref); - base_address = build_fold_addr_expr (memref); - /* 2.1 set MEMTAG. */ - *memtag = memref; - } + DR_OFFSET (dr) = fold_convert (ssizetype, offset_iv.base); + DR_INIT (dr) = init; + DR_STEP (dr) = step; - /* Part 1: Case 3. INDIRECT_REFs. */ - else if (TREE_CODE (memref) == INDIRECT_REF) - { - tree ptr_ref = TREE_OPERAND (memref, 0); - if (TREE_CODE (ptr_ref) == SSA_NAME) - *ptr_info = SSA_NAME_PTR_INFO (ptr_ref); + DR_ALIGNED_TO (dr) = size_int (highest_pow2_factor (offset_iv.base)); - /* 3.1 build data-reference structure for MEMREF. */ - ptr_dr = analyze_indirect_ref (stmt, memref, is_read); - if (!ptr_dr) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nfailed to create dr for "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL_TREE; - } + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "success.\n"); +} - /* 3.2 analyze evolution and initial condition of MEMREF. */ - ptr_step = DR_STEP (ptr_dr); - ptr_init = DR_BASE_ADDRESS (ptr_dr); - if (!ptr_init || !ptr_step || !POINTER_TYPE_P (TREE_TYPE (ptr_init))) - { - *dr = (*dr) ? *dr : ptr_dr; - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nbad pointer access "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL_TREE; - } +/* Determines the base object and the list of indices of memory reference + DR, analysed in loop nest NEST. */ - if (integer_zerop (ptr_step) && !(*dr)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "\nptr is loop invariant.\n"); - *dr = ptr_dr; - return NULL_TREE; - - /* If there exists DR for MEMREF, we are analyzing the base of - handled component (PTR_INIT), which not necessary has evolution in - the loop. */ - } - object_step = size_binop (PLUS_EXPR, object_step, ptr_step); - - /* 3.3 set data-reference structure for MEMREF. */ - if (!*dr) - *dr = ptr_dr; - - /* 3.4 call address_analysis to analyze INIT of the access - function. */ - base_address = address_analysis (ptr_init, stmt, is_read, *dr, - &address_offset, &address_misalign, - &address_aligned_to, &address_step); - if (!base_address) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nfailed to analyze address "); - print_generic_expr (dump_file, ptr_init, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL_TREE; - } +static void +dr_analyze_indices (struct data_reference *dr, struct loop *nest) +{ + tree stmt = DR_STMT (dr); + struct loop *loop = loop_containing_stmt (stmt); + VEC (tree, heap) *access_fns = NULL; + tree ref = unshare_expr (DR_REF (dr)), aref = ref, op; + tree base, off, access_fn; - /* 3.5 extract memory tag. */ - switch (TREE_CODE (base_address)) - { - case SSA_NAME: - *memtag = symbol_mem_tag (SSA_NAME_VAR (base_address)); - if (!(*memtag) && TREE_CODE (TREE_OPERAND (memref, 0)) == SSA_NAME) - *memtag = symbol_mem_tag (SSA_NAME_VAR (TREE_OPERAND (memref, 0))); - break; - case ADDR_EXPR: - *memtag = TREE_OPERAND (base_address, 0); - break; - default: - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nno memtag for "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - *memtag = NULL_TREE; - break; - } - } - - if (!base_address) + while (handled_component_p (aref)) { - /* MEMREF cannot be analyzed. */ - if (dump_file && (dump_flags & TDF_DETAILS)) + if (TREE_CODE (aref) == ARRAY_REF) { - fprintf (dump_file, "\ndata-ref of unsupported type "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n"); + op = TREE_OPERAND (aref, 1); + access_fn = analyze_scalar_evolution (loop, op); + access_fn = resolve_mixers (nest, access_fn); + VEC_safe_push (tree, heap, access_fns, access_fn); + + TREE_OPERAND (aref, 1) = build_int_cst (TREE_TYPE (op), 0); } - return NULL_TREE; + + aref = TREE_OPERAND (aref, 0); } - if (comp_ref) - DR_REF (*dr) = comp_ref; - - if (SSA_VAR_P (*memtag) && var_can_have_subvars (*memtag)) - *subvars = get_subvars_for_var (*memtag); - - /* Part 2: Combine the results of object and address analysis to calculate - INITIAL_OFFSET, STEP and misalignment info. */ - *offset = size_binop (PLUS_EXPR, object_offset, address_offset); - - if ((!object_misalign && !object_aligned_to) - || (!address_misalign && !address_aligned_to)) - { - *misalign = NULL_TREE; - *aligned_to = NULL_TREE; - } - else + if (INDIRECT_REF_P (aref)) { - if (object_misalign && address_misalign) - *misalign = size_binop (PLUS_EXPR, object_misalign, address_misalign); - else - *misalign = object_misalign ? object_misalign : address_misalign; - if (object_aligned_to && address_aligned_to) - *aligned_to = size_binop (MIN_EXPR, object_aligned_to, - address_aligned_to); - else - *aligned_to = object_aligned_to ? - object_aligned_to : address_aligned_to; + op = TREE_OPERAND (aref, 0); + access_fn = analyze_scalar_evolution (loop, op); + access_fn = resolve_mixers (nest, access_fn); + base = initial_condition (access_fn); + split_constant_offset (base, &base, &off); + access_fn = chrec_replace_initial_condition (access_fn, + fold_convert (TREE_TYPE (base), off)); + + TREE_OPERAND (aref, 0) = base; + VEC_safe_push (tree, heap, access_fns, access_fn); } - *step = size_binop (PLUS_EXPR, object_step, address_step); - return base_address; + DR_BASE_OBJECT (dr) = ref; + DR_ACCESS_FNS (dr) = access_fns; } -/* Function analyze_offset. - - Extract INVARIANT and CONSTANT parts from OFFSET. +/* Extracts the alias analysis information from the memory reference DR. */ -*/ -static bool -analyze_offset (tree offset, tree *invariant, tree *constant) +static void +dr_analyze_alias (struct data_reference *dr) { - tree op0, op1, constant_0, constant_1, invariant_0, invariant_1; - enum tree_code code = TREE_CODE (offset); + tree stmt = DR_STMT (dr); + tree ref = DR_REF (dr); + tree base = get_base_address (ref), addr, smt = NULL_TREE; + ssa_op_iter it; + tree op; + bitmap vops; + + if (DECL_P (base)) + smt = base; + else if (INDIRECT_REF_P (base)) + { + addr = TREE_OPERAND (base, 0); + if (TREE_CODE (addr) == SSA_NAME) + { + smt = symbol_mem_tag (SSA_NAME_VAR (addr)); + DR_PTR_INFO (dr) = SSA_NAME_PTR_INFO (addr); + } + } - *invariant = NULL_TREE; - *constant = NULL_TREE; + DR_SYMBOL_TAG (dr) = smt; + if (var_can_have_subvars (smt)) + DR_SUBVARS (dr) = get_subvars_for_var (smt); - /* Not PLUS/MINUS expression - recursion stop condition. */ - if (code != PLUS_EXPR && code != MINUS_EXPR) + vops = BITMAP_ALLOC (NULL); + FOR_EACH_SSA_TREE_OPERAND (op, stmt, it, SSA_OP_VIRTUAL_USES) { - if (TREE_CODE (offset) == INTEGER_CST) - *constant = offset; - else - *invariant = offset; - return true; + bitmap_set_bit (vops, DECL_UID (SSA_NAME_VAR (op))); } - op0 = TREE_OPERAND (offset, 0); - op1 = TREE_OPERAND (offset, 1); + DR_VOPS (dr) = vops; +} - /* Recursive call with the operands. */ - if (!analyze_offset (op0, &invariant_0, &constant_0) - || !analyze_offset (op1, &invariant_1, &constant_1)) - return false; +/* Returns true if the address of DR is invariant. */ - /* Combine the results. Add negation to the subtrahend in case of - subtraction. */ - if (constant_0 && constant_1) - return false; - *constant = constant_0 ? constant_0 : constant_1; - if (code == MINUS_EXPR && constant_1) - *constant = fold_build1 (NEGATE_EXPR, TREE_TYPE (*constant), *constant); +static bool +dr_address_invariant_p (struct data_reference *dr) +{ + unsigned i; + tree idx; + + for (i = 0; VEC_iterate (tree, DR_ACCESS_FNS (dr), i, idx); i++) + if (tree_contains_chrecs (idx, NULL)) + return false; - if (invariant_0 && invariant_1) - *invariant = - fold_build2 (code, TREE_TYPE (invariant_0), invariant_0, invariant_1); - else - { - *invariant = invariant_0 ? invariant_0 : invariant_1; - if (code == MINUS_EXPR && invariant_1) - *invariant = - fold_build1 (NEGATE_EXPR, TREE_TYPE (*invariant), *invariant); - } return true; } -/* Free the memory used by the data reference DR. */ +/* Frees data reference DR. */ static void free_data_ref (data_reference_p dr) { - DR_FREE_ACCESS_FNS (dr); + BITMAP_FREE (DR_VOPS (dr)); + VEC_free (tree, heap, DR_ACCESS_FNS (dr)); free (dr); } -/* Function create_data_ref. - - Create a data-reference structure for MEMREF. Set its DR_BASE_ADDRESS, - DR_OFFSET, DR_INIT, DR_STEP, DR_OFFSET_MISALIGNMENT, DR_ALIGNED_TO, - DR_MEMTAG, and DR_POINTSTO_INFO fields. - - Input: - MEMREF - the memory reference that is being analyzed - STMT - the statement that contains MEMREF - IS_READ - TRUE if STMT reads from MEMREF, FALSE if writes to MEMREF - - Output: - DR (returned value) - data_reference struct for MEMREF -*/ +/* Analyzes memory reference MEMREF accessed in STMT. The reference + is read if IS_READ is true, write otherwise. Returns the + data_reference description of MEMREF. NEST is the outermost loop of the + loop nest in that the reference should be analysed. */ static struct data_reference * -create_data_ref (tree memref, tree stmt, bool is_read) +create_data_ref (struct loop *nest, tree memref, tree stmt, bool is_read) { - struct data_reference *dr = NULL; - tree base_address, offset, step, misalign, memtag; - struct loop *loop = loop_containing_stmt (stmt); - tree invariant = NULL_TREE, constant = NULL_TREE; - tree type_size, init_cond; - struct ptr_info_def *ptr_info; - subvar_t subvars = NULL; - tree aligned_to, type = NULL_TREE, orig_offset; - - if (!memref) - return NULL; - - base_address = object_analysis (memref, stmt, is_read, &dr, &offset, - &misalign, &aligned_to, &step, &memtag, - &ptr_info, &subvars); - if (!dr || !base_address) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\ncreate_data_ref: failed to create a dr for "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL; - } - - DR_BASE_ADDRESS (dr) = base_address; - DR_OFFSET (dr) = offset; - DR_INIT (dr) = ssize_int (0); - DR_STEP (dr) = step; - DR_OFFSET_MISALIGNMENT (dr) = misalign; - DR_ALIGNED_TO (dr) = aligned_to; - DR_MEMTAG (dr) = memtag; - DR_PTR_INFO (dr) = ptr_info; - DR_SUBVARS (dr) = subvars; - - type_size = fold_convert (ssizetype, TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)))); - - /* Extract CONSTANT and INVARIANT from OFFSET. */ - /* Remove cast from OFFSET and restore it for INVARIANT part. */ - orig_offset = offset; - STRIP_NOPS (offset); - if (offset != orig_offset) - type = TREE_TYPE (orig_offset); - if (!analyze_offset (offset, &invariant, &constant)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\ncreate_data_ref: failed to analyze dr's"); - fprintf (dump_file, " offset for "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n"); - } - return NULL; - } - if (type && invariant) - invariant = fold_convert (type, invariant); + struct data_reference *dr; - /* Put CONSTANT part of OFFSET in DR_INIT and INVARIANT in DR_OFFSET field - of DR. */ - if (constant) + if (dump_file && (dump_flags & TDF_DETAILS)) { - DR_INIT (dr) = fold_convert (ssizetype, constant); - init_cond = fold_build2 (TRUNC_DIV_EXPR, TREE_TYPE (constant), - constant, type_size); + fprintf (dump_file, "Creating dr for "); + print_generic_expr (dump_file, memref, TDF_SLIM); + fprintf (dump_file, "\n"); } - else - DR_INIT (dr) = init_cond = ssize_int (0); - - if (invariant) - DR_OFFSET (dr) = invariant; - else - DR_OFFSET (dr) = ssize_int (0); - - /* Change the access function for INIDIRECT_REFs, according to - DR_BASE_ADDRESS. Analyze OFFSET calculated in object_analysis. OFFSET is - an expression that can contain loop invariant expressions and constants. - We put the constant part in the initial condition of the access function - (for data dependence tests), and in DR_INIT of the data-ref. The loop - invariant part is put in DR_OFFSET. - The evolution part of the access function is STEP calculated in - object_analysis divided by the size of data type. - */ - if (!DR_BASE_OBJECT (dr) - || (TREE_CODE (memref) == COMPONENT_REF && DR_NUM_DIMENSIONS (dr) == 1)) - { - tree access_fn; - tree new_step; - - /* Update access function. */ - access_fn = DR_ACCESS_FN (dr, 0); - if (automatically_generated_chrec_p (access_fn)) - { - free_data_ref (dr); - return NULL; - } - new_step = size_binop (TRUNC_DIV_EXPR, - fold_convert (ssizetype, step), type_size); - - init_cond = chrec_convert (chrec_type (access_fn), init_cond, stmt); - new_step = chrec_convert (chrec_type (access_fn), new_step, stmt); - if (automatically_generated_chrec_p (init_cond) - || automatically_generated_chrec_p (new_step)) - { - free_data_ref (dr); - return NULL; - } - access_fn = chrec_replace_initial_condition (access_fn, init_cond); - access_fn = reset_evolution_in_loop (loop->num, access_fn, new_step); + dr = XCNEW (struct data_reference); + DR_STMT (dr) = stmt; + DR_REF (dr) = memref; + DR_IS_READ (dr) = is_read; - VEC_replace (tree, DR_ACCESS_FNS (dr), 0, access_fn); - } + dr_analyze_innermost (dr); + dr_analyze_indices (dr, nest); + dr_analyze_alias (dr); if (dump_file && (dump_flags & TDF_DETAILS)) { - struct ptr_info_def *pi = DR_PTR_INFO (dr); - - fprintf (dump_file, "\nCreated dr for "); - print_generic_expr (dump_file, memref, TDF_SLIM); - fprintf (dump_file, "\n\tbase_address: "); + fprintf (dump_file, "\tbase_address: "); print_generic_expr (dump_file, DR_BASE_ADDRESS (dr), TDF_SLIM); fprintf (dump_file, "\n\toffset from base address: "); print_generic_expr (dump_file, DR_OFFSET (dr), TDF_SLIM); fprintf (dump_file, "\n\tconstant offset from base address: "); print_generic_expr (dump_file, DR_INIT (dr), TDF_SLIM); - fprintf (dump_file, "\n\tbase_object: "); - print_generic_expr (dump_file, DR_BASE_OBJECT (dr), TDF_SLIM); fprintf (dump_file, "\n\tstep: "); print_generic_expr (dump_file, DR_STEP (dr), TDF_SLIM); - fprintf (dump_file, "B\n\tmisalignment from base: "); - print_generic_expr (dump_file, DR_OFFSET_MISALIGNMENT (dr), TDF_SLIM); - if (DR_OFFSET_MISALIGNMENT (dr)) - fprintf (dump_file, "B"); - if (DR_ALIGNED_TO (dr)) - { - fprintf (dump_file, "\n\taligned to: "); - print_generic_expr (dump_file, DR_ALIGNED_TO (dr), TDF_SLIM); - } - fprintf (dump_file, "\n\tmemtag: "); - print_generic_expr (dump_file, DR_MEMTAG (dr), TDF_SLIM); + fprintf (dump_file, "\n\taligned to: "); + print_generic_expr (dump_file, DR_ALIGNED_TO (dr), TDF_SLIM); + fprintf (dump_file, "\n\tbase_object: "); + print_generic_expr (dump_file, DR_BASE_OBJECT (dr), TDF_SLIM); + fprintf (dump_file, "\n\tsymbol tag: "); + print_generic_expr (dump_file, DR_SYMBOL_TAG (dr), TDF_SLIM); fprintf (dump_file, "\n"); - if (pi && pi->name_mem_tag) - { - fprintf (dump_file, "\n\tnametag: "); - print_generic_expr (dump_file, pi->name_mem_tag, TDF_SLIM); - fprintf (dump_file, "\n"); - } - } + } + + /* FIXME -- data dependence analysis does not work correctly for objects with + invariant addresses. Let us fail here until the problem is fixed. */ + if (dr_address_invariant_p (dr)) + { + free_data_ref (dr); + dr = NULL; + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "\tFAILED as dr address is invariant\n"); + } + return dr; } @@ -2259,6 +1014,180 @@ conflict_fn_no_dependence (void) return fn; } +/* Returns true if the address of OBJ is invariant in LOOP. */ + +static bool +object_address_invariant_in_loop_p (struct loop *loop, tree obj) +{ + while (handled_component_p (obj)) + { + if (TREE_CODE (obj) == ARRAY_REF) + { + /* Index of the ARRAY_REF was zeroed in analyze_indices, thus we only + need to check the stride and the lower bound of the reference. */ + if (chrec_contains_symbols_defined_in_loop (TREE_OPERAND (obj, 2), + loop->num) + || chrec_contains_symbols_defined_in_loop (TREE_OPERAND (obj, 3), + loop->num)) + return false; + } + else if (TREE_CODE (obj) == COMPONENT_REF) + { + if (chrec_contains_symbols_defined_in_loop (TREE_OPERAND (obj, 2), + loop->num)) + return false; + } + obj = TREE_OPERAND (obj, 0); + } + + if (!INDIRECT_REF_P (obj)) + return true; + + return !chrec_contains_symbols_defined_in_loop (TREE_OPERAND (obj, 0), + loop->num); +} + +/* Returns true if A and B are accesses to different objects, or to different + fields of the same object. */ + +static bool +disjoint_objects_p (tree a, tree b) +{ + tree base_a, base_b; + VEC (tree, heap) *comp_a = NULL, *comp_b = NULL; + bool ret; + + base_a = get_base_address (a); + base_b = get_base_address (b); + + if (DECL_P (base_a) + && DECL_P (base_b) + && base_a != base_b) + return true; + + if (!operand_equal_p (base_a, base_b, 0)) + return false; + + /* Compare the component references of A and B. We must start from the inner + ones, so record them to the vector first. */ + while (handled_component_p (a)) + { + VEC_safe_push (tree, heap, comp_a, a); + a = TREE_OPERAND (a, 0); + } + while (handled_component_p (b)) + { + VEC_safe_push (tree, heap, comp_b, b); + b = TREE_OPERAND (b, 0); + } + + ret = false; + while (1) + { + if (VEC_length (tree, comp_a) == 0 + || VEC_length (tree, comp_b) == 0) + break; + + a = VEC_pop (tree, comp_a); + b = VEC_pop (tree, comp_b); + + /* Real and imaginary part of a variable do not alias. */ + if ((TREE_CODE (a) == REALPART_EXPR + && TREE_CODE (b) == IMAGPART_EXPR) + || (TREE_CODE (a) == IMAGPART_EXPR + && TREE_CODE (b) == REALPART_EXPR)) + { + ret = true; + break; + } + + if (TREE_CODE (a) != TREE_CODE (b)) + break; + + /* Nothing to do for ARRAY_REFs, as the indices of array_refs in + DR_BASE_OBJECT are always zero. */ + if (TREE_CODE (a) == ARRAY_REF) + continue; + else if (TREE_CODE (a) == COMPONENT_REF) + { + if (operand_equal_p (TREE_OPERAND (a, 1), TREE_OPERAND (b, 1), 0)) + continue; + + /* Different fields of unions may overlap. */ + base_a = TREE_OPERAND (a, 0); + if (TREE_CODE (TREE_TYPE (base_a)) == UNION_TYPE) + break; + + /* Different fields of structures cannot. */ + ret = true; + break; + } + else + break; + } + + VEC_free (tree, heap, comp_a); + VEC_free (tree, heap, comp_b); + + return ret; +} + +/* Returns false if we can prove that data references A and B do not alias, + true otherwise. */ + +static bool +dr_may_alias_p (struct data_reference *a, struct data_reference *b) +{ + tree addr_a = DR_BASE_ADDRESS (a); + tree addr_b = DR_BASE_ADDRESS (b); + tree type_a, type_b; + tree decl_a = NULL_TREE, decl_b = NULL_TREE; + + /* If the sets of virtual operands are disjoint, the memory references do not + alias. */ + if (!bitmap_intersect_p (DR_VOPS (a), DR_VOPS (b))) + return false; + + /* If the accessed objects are disjoint, the memory references do not + alias. */ + if (disjoint_objects_p (DR_BASE_OBJECT (a), DR_BASE_OBJECT (b))) + return false; + + if (!addr_a || !addr_b) + return true; + + /* If the references are based on different static objects, they cannot alias + (PTA should be able to disambiguate such accesses, but often it fails to, + since currently we cannot distinguish between pointer and offset in pointer + arithmetics). */ + if (TREE_CODE (addr_a) == ADDR_EXPR + && TREE_CODE (addr_b) == ADDR_EXPR) + return TREE_OPERAND (addr_a, 0) == TREE_OPERAND (addr_b, 0); + + /* An instruction writing through a restricted pointer is "independent" of any + instruction reading or writing through a different restricted pointer, + in the same block/scope. */ + + type_a = TREE_TYPE (addr_a); + type_b = TREE_TYPE (addr_b); + gcc_assert (POINTER_TYPE_P (type_a) && POINTER_TYPE_P (type_b)); + + if (TREE_CODE (addr_a) == SSA_NAME) + decl_a = SSA_NAME_VAR (addr_a); + if (TREE_CODE (addr_b) == SSA_NAME) + decl_b = SSA_NAME_VAR (addr_b); + + if (TYPE_RESTRICT (type_a) && TYPE_RESTRICT (type_b) + && (!DR_IS_READ (a) || !DR_IS_READ (b)) + && decl_a && TREE_CODE (decl_a) == PARM_DECL + && decl_b && TREE_CODE (decl_b) == PARM_DECL + && TREE_CODE (DECL_CONTEXT (decl_a)) == FUNCTION_DECL + && DECL_CONTEXT (decl_a) == DECL_CONTEXT (decl_b)) + return false; + + return true; +} + /* Initialize a data dependence relation between data accesses A and B. NB_LOOPS is the number of loops surrounding the references: the size of the classic distance/direction vectors. */ @@ -2269,7 +1198,6 @@ initialize_data_dependence_relation (struct data_reference *a, VEC (loop_p, heap) *loop_nest) { struct data_dependence_relation *res; - bool differ_p, known_dependence; unsigned int i; res = XNEW (struct data_dependence_relation); @@ -2283,34 +1211,33 @@ initialize_data_dependence_relation (struct data_reference *a, return res; } - /* When A and B are arrays and their dimensions differ, we directly - initialize the relation to "there is no dependence": chrec_known. */ - if (DR_BASE_OBJECT (a) && DR_BASE_OBJECT (b) - && DR_NUM_DIMENSIONS (a) != DR_NUM_DIMENSIONS (b)) + /* If the data references do not alias, then they are independent. */ + if (!dr_may_alias_p (a, b)) { - DDR_ARE_DEPENDENT (res) = chrec_known; + DDR_ARE_DEPENDENT (res) = chrec_known; return res; } - if (DR_BASE_ADDRESS (a) && DR_BASE_ADDRESS (b)) - known_dependence = base_addr_differ_p (a, b, &differ_p); - else - known_dependence = base_object_differ_p (a, b, &differ_p); - - if (!known_dependence) + /* If the references do not access the same object, we do not know + whether they alias or not. */ + if (!operand_equal_p (DR_BASE_OBJECT (a), DR_BASE_OBJECT (b), 0)) { - /* Can't determine whether the data-refs access the same memory - region. */ DDR_ARE_DEPENDENT (res) = chrec_dont_know; return res; } - if (differ_p) + /* If the base of the object is not invariant in the loop nest, we cannot + analyse it. TODO -- in fact, it would suffice to record that there may + be arbitrary depencences in the loops where the base object varies. */ + if (!object_address_invariant_in_loop_p (VEC_index (loop_p, loop_nest, 0), + DR_BASE_OBJECT (a))) { - DDR_ARE_DEPENDENT (res) = chrec_known; + DDR_ARE_DEPENDENT (res) = chrec_dont_know; return res; } - + + gcc_assert (DR_NUM_DIMENSIONS (a) == DR_NUM_DIMENSIONS (b)); + DDR_AFFINE_P (res) = true; DDR_ARE_DEPENDENT (res) = NULL_TREE; DDR_SUBSCRIPTS (res) = VEC_alloc (subscript_p, heap, DR_NUM_DIMENSIONS (a)); @@ -4895,6 +3822,9 @@ compute_self_dependence (struct data_dependence_relation *ddr) unsigned int i; struct subscript *subscript; + if (DDR_ARE_DEPENDENT (ddr) != NULL_TREE) + return; + for (i = 0; VEC_iterate (subscript_p, DDR_SUBSCRIPTS (ddr), i, subscript); i++) { @@ -5013,10 +3943,11 @@ get_references_in_stmt (tree stmt, VEC (data_ref_loc, heap) **references) } /* Stores the data references in STMT to DATAREFS. If there is an unanalyzable - reference, returns false, otherwise returns true. */ + reference, returns false, otherwise returns true. NEST is the outermost + loop of the loop nest in that the references should be analysed. */ static bool -find_data_references_in_stmt (tree stmt, +find_data_references_in_stmt (struct loop *nest, tree stmt, VEC (data_reference_p, heap) **datarefs) { unsigned i; @@ -5033,7 +3964,7 @@ find_data_references_in_stmt (tree stmt, for (i = 0; VEC_iterate (data_ref_loc, references, i, ref); i++) { - dr = create_data_ref (*ref->pos, stmt, ref->is_read); + dr = create_data_ref (nest, *ref->pos, stmt, ref->is_read); if (dr) VEC_safe_push (data_reference_p, heap, *datarefs, dr); else @@ -5049,11 +3980,11 @@ find_data_references_in_stmt (tree stmt, /* Search the data references in LOOP, and record the information into DATAREFS. Returns chrec_dont_know when failing to analyze a difficult case, returns NULL_TREE otherwise. - + TODO: This function should be made smarter so that it can handle address arithmetic as if they were array accesses, etc. */ -tree +static tree find_data_references_in_loop (struct loop *loop, VEC (data_reference_p, heap) **datarefs) { @@ -5071,24 +4002,10 @@ find_data_references_in_loop (struct loop *loop, { tree stmt = bsi_stmt (bsi); - if (!find_data_references_in_stmt (stmt, datarefs)) + if (!find_data_references_in_stmt (loop, stmt, datarefs)) { struct data_reference *res; - res = XNEW (struct data_reference); - DR_STMT (res) = NULL_TREE; - DR_REF (res) = NULL_TREE; - DR_BASE_OBJECT (res) = NULL; - DR_TYPE (res) = ARRAY_REF_TYPE; - DR_SET_ACCESS_FNS (res, NULL); - DR_BASE_OBJECT (res) = NULL; - DR_IS_READ (res) = false; - DR_BASE_ADDRESS (res) = NULL_TREE; - DR_OFFSET (res) = NULL_TREE; - DR_INIT (res) = NULL_TREE; - DR_STEP (res) = NULL_TREE; - DR_OFFSET_MISALIGNMENT (res) = NULL_TREE; - DR_MEMTAG (res) = NULL_TREE; - DR_PTR_INFO (res) = NULL; + res = XCNEW (struct data_reference); VEC_safe_push (data_reference_p, heap, *datarefs, res); free (bbs); @@ -5155,7 +4072,6 @@ compute_data_dependences_for_loop (struct loop *loop, VEC (data_reference_p, heap) **datarefs, VEC (ddr_p, heap) **dependence_relations) { - struct loop *loop_nest = loop; VEC (loop_p, heap) *vloops = VEC_alloc (loop_p, heap, 3); memset (&dependence_stats, 0, sizeof (dependence_stats)); @@ -5163,8 +4079,8 @@ compute_data_dependences_for_loop (struct loop *loop, /* If the loop nest is not well formed, or one of the data references is not computable, give up without spending time to compute other dependences. */ - if (!loop_nest - || !find_loop_nest (loop_nest, &vloops) + if (!loop + || !find_loop_nest (loop, &vloops) || find_data_references_in_loop (loop, datarefs) == chrec_dont_know) { struct data_dependence_relation *ddr; @@ -5287,12 +4203,8 @@ analyze_all_data_dependences (struct loop *loop) { struct data_reference *a = DDR_A (ddr); struct data_reference *b = DDR_B (ddr); - bool differ_p; - - if ((DR_BASE_OBJECT (a) && DR_BASE_OBJECT (b) - && DR_NUM_DIMENSIONS (a) != DR_NUM_DIMENSIONS (b)) - || (base_object_differ_p (a, b, &differ_p) - && differ_p)) + + if (!bitmap_intersect_p (DR_VOPS (a), DR_VOPS (b))) nb_basename_differ++; else nb_bot_relations++; diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h index e339d98..2edee2c 100644 --- a/gcc/tree-data-ref.h +++ b/gcc/tree-data-ref.h @@ -26,48 +26,73 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "omega.h" /* - The first location accessed by data-ref in the loop is the address of data-ref's - base (BASE_ADDRESS) plus the initial offset from the base. We divide the initial offset - into two parts: loop invariant offset (OFFSET) and constant offset (INIT). - STEP is the stride of data-ref in the loop in bytes. + innermost_loop_behavior describes the evolution of the address of the memory + reference in the innermost enclosing loop. The address is expressed as + BASE + STEP * # of iteration, and base is further decomposed as the base + pointer (BASE_ADDRESS), loop invariant offset (OFFSET) and + constant offset (INIT). Examples, in loop nest + + for (i = 0; i < 100; i++) + for (j = 3; j < 100; j++) Example 1 Example 2 - data-ref a[j].b[i][j] a + x + 16B (a is int*) + data-ref a[j].b[i][j] *(p + x + 16B + 4B * j) - First location info: - base_address &a a - offset j_0*D_j + i_0*D_i x - init C_b + C_a 16 + innermost_loop_behavior + base_address &a p + offset i * D_i x + init 3 * D_j + offsetof (b) 28 step D_j 4 - access_fn NULL {16, +, 1} - - Base object info: - base_object a NULL - access_fn NULL */ -struct first_location_in_loop +struct innermost_loop_behavior { tree base_address; tree offset; tree init; tree step; - /* Access function related to first location in the loop. */ - VEC(tree,heap) *access_fns; + + /* Alignment information. ALIGNED_TO is set to the largest power of two + that divides OFFSET. */ + tree aligned_to; }; -struct base_object_info +/* Describes the evolutions of indices of the memory reference. The indices + are indices of the ARRAY_REFs and the operands of INDIRECT_REFs. + For ARRAY_REFs, BASE_OBJECT is the reference with zeroed indices + (note that this reference does not have to be valid, if zero does not + belong to the range of the array; hence it is not recommended to use + BASE_OBJECT in any code generation). For INDIRECT_REFs, the address is + set to the loop-invariant part of the address of the object, except for + the constant offset. For the examples above, + + base_object: a[0].b[0][0] *(p + x + 4B * j_0) + indices: {j_0, +, 1}_2 {16, +, 4}_2 + {i_0, +, 1}_1 + {j_0, +, 1}_2 +*/ + +struct indices { /* The object. */ tree base_object; - /* A list of chrecs. Access functions related to BASE_OBJECT. */ + /* A list of chrecs. Access functions of the indices. */ VEC(tree,heap) *access_fns; }; -enum data_ref_type { - ARRAY_REF_TYPE, - POINTER_REF_TYPE +struct dr_alias +{ + /* The alias information that should be used for new pointers to this + location. SYMBOL_TAG is either a DECL or a SYMBOL_MEMORY_TAG. */ + tree symbol_tag; + subvar_t subvars; + struct ptr_info_def *ptr_info; + + /* The set of virtual operands corresponding to this memory reference, + serving as a description of the alias information for the memory + reference. This could be eliminated if we had alias oracle. */ + bitmap vops; }; struct data_reference @@ -75,7 +100,7 @@ struct data_reference /* A pointer to the statement that contains this DR. */ tree stmt; - /* A pointer to the ARRAY_REF node. */ + /* A pointer to the memory reference. */ tree ref; /* Auxiliary info specific to a pass. */ @@ -84,58 +109,14 @@ struct data_reference /* True when the data reference is in RHS of a stmt. */ bool is_read; - /* First location accessed by the data-ref in the loop. */ - struct first_location_in_loop first_location; + /* Behavior of the memory reference in the innermost loop. */ + struct innermost_loop_behavior innermost; - /* Base object related info. */ - struct base_object_info object_info; + /* Decomposition to indices for alias analysis. */ + struct indices indices; - /* Aliasing information. This field represents the symbol that - should be aliased by a pointer holding the address of this data - reference. If the original data reference was a pointer - dereference, then this field contains the memory tag that should - be used by the new vector-pointer. */ - tree memtag; - struct ptr_info_def *ptr_info; - subvar_t subvars; - - /* Alignment information. - MISALIGNMENT is the offset of the data-reference from its base in bytes. - ALIGNED_TO is the maximum data-ref's alignment. - - Example 1, - for i - for (j = 3; j < N; j++) - a[j].b[i][j] = 0; - - For a[j].b[i][j], the offset from base (calculated in get_inner_reference() - will be 'i * C_i + j * C_j + C'. - We try to substitute the variables of the offset expression - with initial_condition of the corresponding access_fn in the loop. - 'i' cannot be substituted, since its access_fn in the inner loop is i. 'j' - will be substituted with 3. - - Example 2 - for (j = 3; j < N; j++) - a[j].b[5][j] = 0; - - Here the offset expression (j * C_j + C) will not contain variables after - substitution of j=3 (3*C_j + C). - - Misalignment can be calculated only if all the variables can be - substituted with constants, otherwise, we record maximum possible alignment - in ALIGNED_TO. In Example 1, since 'i' cannot be substituted, - MISALIGNMENT will be NULL_TREE, and the biggest divider of C_i (a power of - 2) will be recorded in ALIGNED_TO. - - In Example 2, MISALIGNMENT will be the value of 3*C_j + C in bytes, and - ALIGNED_TO will be NULL_TREE. - */ - tree misalignment; - tree aligned_to; - - /* The type of the data-ref. */ - enum data_ref_type type; + /* Alias information for the data reference. */ + struct dr_alias alias; }; typedef struct data_reference *data_reference_p; @@ -144,37 +125,20 @@ DEF_VEC_ALLOC_P (data_reference_p, heap); #define DR_STMT(DR) (DR)->stmt #define DR_REF(DR) (DR)->ref -#define DR_BASE_OBJECT(DR) (DR)->object_info.base_object -#define DR_TYPE(DR) (DR)->type -#define DR_ACCESS_FNS(DR)\ - (DR_TYPE(DR) == ARRAY_REF_TYPE ? \ - (DR)->object_info.access_fns : (DR)->first_location.access_fns) +#define DR_BASE_OBJECT(DR) (DR)->indices.base_object +#define DR_ACCESS_FNS(DR) (DR)->indices.access_fns #define DR_ACCESS_FN(DR, I) VEC_index (tree, DR_ACCESS_FNS (DR), I) #define DR_NUM_DIMENSIONS(DR) VEC_length (tree, DR_ACCESS_FNS (DR)) #define DR_IS_READ(DR) (DR)->is_read -#define DR_BASE_ADDRESS(DR) (DR)->first_location.base_address -#define DR_OFFSET(DR) (DR)->first_location.offset -#define DR_INIT(DR) (DR)->first_location.init -#define DR_STEP(DR) (DR)->first_location.step -#define DR_MEMTAG(DR) (DR)->memtag -#define DR_ALIGNED_TO(DR) (DR)->aligned_to -#define DR_OFFSET_MISALIGNMENT(DR) (DR)->misalignment -#define DR_PTR_INFO(DR) (DR)->ptr_info -#define DR_SUBVARS(DR) (DR)->subvars -#define DR_SET_ACCESS_FNS(DR, ACC_FNS) \ -{ \ - if (DR_TYPE(DR) == ARRAY_REF_TYPE) \ - (DR)->object_info.access_fns = ACC_FNS; \ - else \ - (DR)->first_location.access_fns = ACC_FNS; \ -} -#define DR_FREE_ACCESS_FNS(DR) \ -{ \ - if (DR_TYPE(DR) == ARRAY_REF_TYPE) \ - VEC_free (tree, heap, (DR)->object_info.access_fns); \ - else \ - VEC_free (tree, heap, (DR)->first_location.access_fns); \ -} +#define DR_BASE_ADDRESS(DR) (DR)->innermost.base_address +#define DR_OFFSET(DR) (DR)->innermost.offset +#define DR_INIT(DR) (DR)->innermost.init +#define DR_STEP(DR) (DR)->innermost.step +#define DR_SYMBOL_TAG(DR) (DR)->alias.symbol_tag +#define DR_PTR_INFO(DR) (DR)->alias.ptr_info +#define DR_SUBVARS(DR) (DR)->alias.subvars +#define DR_VOPS(DR) (DR)->alias.vops +#define DR_ALIGNED_TO(DR) (DR)->innermost.aligned_to enum data_dependence_direction { dir_positive, @@ -335,8 +299,6 @@ DEF_VEC_O (data_ref_loc); DEF_VEC_ALLOC_O (data_ref_loc, heap); bool get_references_in_stmt (tree, VEC (data_ref_loc, heap) **); -extern tree find_data_references_in_loop (struct loop *, - VEC (data_reference_p, heap) **); extern void compute_data_dependences_for_loop (struct loop *, bool, VEC (data_reference_p, heap) **, VEC (ddr_p, heap) **); diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index b2a266b..9fd5c78 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -254,7 +254,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "params.h" static tree analyze_scalar_evolution_1 (struct loop *, tree, tree); -static tree resolve_mixers (struct loop *, tree); /* The cached information about a ssa name VAR, claiming that inside LOOP, the value of VAR can be expressed as CHREC. */ @@ -2408,7 +2407,7 @@ instantiate_parameters (struct loop *loop, care about causing overflows, as long as they do not affect value of an expression. */ -static tree +tree resolve_mixers (struct loop *loop, tree chrec) { htab_t cache = htab_create (10, hash_scev_info, eq_scev_info, del_scev_info); diff --git a/gcc/tree-scalar-evolution.h b/gcc/tree-scalar-evolution.h index 464fe8f..e0218cc 100644 --- a/gcc/tree-scalar-evolution.h +++ b/gcc/tree-scalar-evolution.h @@ -31,6 +31,7 @@ extern void scev_reset (void); extern void scev_finalize (void); extern tree analyze_scalar_evolution (struct loop *, tree); extern tree instantiate_parameters (struct loop *, tree); +extern tree resolve_mixers (struct loop *, tree); extern void gather_stats_on_scev_database (void); extern void scev_analysis (void); unsigned int scev_const_prop (void); diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c index 3a4841d..f928973 100644 --- a/gcc/tree-vect-analyze.c +++ b/gcc/tree-vect-analyze.c @@ -1130,15 +1130,14 @@ vect_compute_data_ref_alignment (struct data_reference *dr) /* Initialize misalignment to unknown. */ DR_MISALIGNMENT (dr) = -1; - misalign = DR_OFFSET_MISALIGNMENT (dr); + misalign = DR_INIT (dr); aligned_to = DR_ALIGNED_TO (dr); base_addr = DR_BASE_ADDRESS (dr); base = build_fold_indirect_ref (base_addr); vectype = STMT_VINFO_VECTYPE (stmt_info); alignment = ssize_int (TYPE_ALIGN (vectype)/BITS_PER_UNIT); - if ((aligned_to && tree_int_cst_compare (aligned_to, alignment) < 0) - || !misalign) + if (tree_int_cst_compare (aligned_to, alignment) < 0) { if (vect_print_dump_info (REPORT_DETAILS)) { @@ -2044,7 +2043,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) } return false; } - if (!DR_MEMTAG (dr)) + if (!DR_SYMBOL_TAG (dr)) { if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) { diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index 0ecbba5..875731d 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -298,7 +298,7 @@ vect_create_data_ref_ptr (tree stmt, /** (2) Add aliasing information to the new vector-pointer: (The points-to info (DR_PTR_INFO) may be defined later.) **/ - tag = DR_MEMTAG (dr); + tag = DR_SYMBOL_TAG (dr); gcc_assert (tag); /* If tag is a variable (and NOT_A_TAG) than a new symbol memory -- 2.7.4