Commit 6e611d92 by Ira Rosen Committed by Dorit Nuzman

re PR tree-optimization/18179 (vectorizer: wrong alignment/step/initial-address…

re PR tree-optimization/18179 (vectorizer: wrong alignment/step/initial-address computed for struct accesses)

2004-12-29  Ira Rosen  <irar@il.ibm.com>

        PR tree-optimization/18179
        * tree-vectorizer.c (vect_get_symbl_and_dr): Reorganize. Add memtag
        retrieval.
        (vect_analyze_data_refs): Remove memtag retrieval.

From-SVN: r92700
parent 5249b4b0
2004-12-29 Ira Rosen <irar@il.ibm.com>
PR tree-optimization/18179
* tree-vectorizer.c (vect_get_symbl_and_dr): Reorganize. Add memtag
retrieval.
(vect_analyze_data_refs): Remove memtag retrieval.
2004-12-28 Richard Henderson <rth@redhat.com> 2004-12-28 Richard Henderson <rth@redhat.com>
PR inline-asm/15740 PR inline-asm/15740
......
...@@ -4763,6 +4763,23 @@ vect_analyze_pointer_ref_access (tree memref, tree stmt, bool is_read) ...@@ -4763,6 +4763,23 @@ vect_analyze_pointer_ref_access (tree memref, tree stmt, bool is_read)
memory tag (for aliasing purposes). memory tag (for aliasing purposes).
Also data reference structure DR is created. Also data reference structure DR is created.
This function handles three kinds of MEMREF:
It is called from vect_analyze_data_refs with a MEMREF that is either an
ARRAY_REF or an INDIRECT_REF (this is category 1 - "recursion begins").
It builds a DR for them using vect_get_base_and_bit_offset, and calls itself
recursively to retrieve the relevant memtag for the MEMREF, "peeling" the
MEMREF along the way. During the recursive calls, the function may be called
with a MEMREF for which the recursion has to continue - PLUS_EXPR,
MINUS_EXPR, INDIRECT_REF (category 2 - "recursion continues"),
and/or with a MEMREF for which a memtag can be trivially obtained - VAR_DECL
and SSA_NAME (this is category 3 - "recursion stop condition").
When the MEMREF falls into category 1 there is still no data reference struct
(DR) available. It is created by this function, and then, along the recursion,
MEMREF will fall into category 2 or 3, in which case a DR will have already
been created, but the analysis continues to retrieve the MEMTAG.
Input: Input:
MEMREF - data reference in STMT MEMREF - data reference in STMT
IS_READ - TRUE if STMT reads from MEMREF, FALSE if writes to MEMREF IS_READ - TRUE if STMT reads from MEMREF, FALSE if writes to MEMREF
...@@ -4780,118 +4797,118 @@ vect_get_symbl_and_dr (tree memref, tree stmt, bool is_read, ...@@ -4780,118 +4797,118 @@ vect_get_symbl_and_dr (tree memref, tree stmt, bool is_read,
tree symbl, oprnd0, oprnd1; tree symbl, oprnd0, oprnd1;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt); stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree offset; tree offset;
tree array_base, base; tree tag;
struct data_reference *new_dr; struct data_reference *new_dr;
bool base_aligned_p; bool base_aligned_p;
*dr = NULL; if (*dr)
{
/* Category 3: recursion stop condition. */
/* (1) A DR already exists. We only need to get the relevant memtag for
MEMREF, the rest of the data was already initialized. */
switch (TREE_CODE (memref)) switch (TREE_CODE (memref))
{ {
case INDIRECT_REF: /* (1.1) Stop condition: find the relevant memtag and return. */
new_dr = vect_analyze_pointer_ref_access (memref, stmt, is_read); case SSA_NAME:
if (! new_dr) symbl = SSA_NAME_VAR (memref);
tag = get_var_ann (symbl)->type_mem_tag;
if (!tag)
{
tree ptr = TREE_OPERAND (DR_REF ((*dr)), 0);
if (TREE_CODE (ptr) == SSA_NAME)
tag = get_var_ann (SSA_NAME_VAR (ptr))->type_mem_tag;
}
if (!tag)
{
if (vect_debug_details (NULL))
fprintf (dump_file, "not vectorized: no memtag for ref.");
return NULL_TREE; return NULL_TREE;
*dr = new_dr; }
symbl = DR_BASE_NAME (new_dr); return tag;
STMT_VINFO_VECT_DR_BASE (stmt_info) = symbl;
case VAR_DECL:
case PARM_DECL:
return memref;
/* Category 2: recursion continues. */
/* (1.2) A recursive call to find the relevant memtag is required. */
case INDIRECT_REF:
symbl = TREE_OPERAND (memref, 0);
break; /* For recursive call. */
case COMPONENT_REF:
/* Could have recorded more accurate information -
i.e, the actual FIELD_DECL that is being referenced -
but later passes expect VAR_DECL as the nmt. */
/* Fall through. */
case ADDR_EXPR:
symbl = vect_get_base_and_bit_offset ((*dr), memref, NULL_TREE,
loop_vinfo, &offset, &base_aligned_p);
break; /* For recursive call. */
switch (TREE_CODE (symbl))
{
case PLUS_EXPR: case PLUS_EXPR:
case MINUS_EXPR: case MINUS_EXPR:
oprnd0 = TREE_OPERAND (symbl, 0); /* Although DR exists, we have to call the function recursively to
oprnd1 = TREE_OPERAND (symbl, 1); build MEMTAG for such expression. This is handled below. */
oprnd0 = TREE_OPERAND (memref, 0);
STRIP_NOPS(oprnd1); oprnd1 = TREE_OPERAND (memref, 1);
/* Only {address_base + offset} expressions are supported,
where address_base can be POINTER_TYPE or ARRAY_TYPE and STRIP_NOPS (oprnd1);
offset can be anything but POINTER_TYPE or ARRAY_TYPE. /* Supported plus/minus expressions are of the form
{address_base + offset}, such that address_base is of type
POINTER/ARRAY, and offset is either an INTEGER_CST of type POINTER,
or it's not of type POINTER/ARRAY.
TODO: swap operands if {offset + address_base}. */ TODO: swap operands if {offset + address_base}. */
if ((TREE_CODE (TREE_TYPE (oprnd1)) == POINTER_TYPE if ((TREE_CODE (TREE_TYPE (oprnd1)) == POINTER_TYPE
&& TREE_CODE (oprnd1) != INTEGER_CST) && TREE_CODE (oprnd1) != INTEGER_CST)
|| TREE_CODE (TREE_TYPE (oprnd1)) == ARRAY_TYPE) || TREE_CODE (TREE_TYPE (oprnd1)) == ARRAY_TYPE)
return NULL_TREE; return NULL_TREE;
if (TREE_CODE (TREE_TYPE (oprnd0)) == POINTER_TYPE)
symbl = oprnd0; symbl = oprnd0;
else break; /* For recursive call. */
symbl = vect_get_symbl_and_dr (oprnd0, stmt, is_read,
loop_vinfo, &new_dr);
case SSA_NAME:
case ADDR_EXPR:
/* symbl remains unchanged. */
break;
default: default:
if (vect_debug_details (NULL))
{
fprintf (dump_file, "unhandled data ref: ");
print_generic_expr (dump_file, memref, TDF_SLIM);
fprintf (dump_file, " (symbl ");
print_generic_expr (dump_file, symbl, TDF_SLIM);
fprintf (dump_file, ") in stmt ");
print_generic_expr (dump_file, stmt, TDF_SLIM);
}
return NULL_TREE; return NULL_TREE;
} }
}
else
{
/* Category 1: recursion begins. */
/* (2) A DR does not exist yet and must be built, followed by a
recursive call to get the relevant memtag for MEMREF. */
switch (TREE_CODE (memref))
{
case INDIRECT_REF:
new_dr = vect_analyze_pointer_ref_access (memref, stmt, is_read);
if (!new_dr)
return NULL_TREE;
*dr = new_dr;
symbl = DR_BASE_NAME (new_dr);
STMT_VINFO_VECT_DR_BASE (stmt_info) = symbl;
break; break;
case ARRAY_REF: case ARRAY_REF:
offset = size_zero_node;
/* Store the array base in the stmt info.
For one dimensional array ref a[i], the base is a,
for multidimensional a[i1][i2]..[iN], the base is
a[i1][i2]..[iN-1]. */
array_base = TREE_OPERAND (memref, 0);
STMT_VINFO_VECT_DR_BASE (stmt_info) = array_base;
new_dr = analyze_array (stmt, memref, is_read); new_dr = analyze_array (stmt, memref, is_read);
*dr = new_dr; *dr = new_dr;
symbl = DR_BASE_NAME (new_dr);
/* Find the relevant symbol for aliasing purposes. */ STMT_VINFO_VECT_DR_BASE (stmt_info) = TREE_OPERAND (memref, 0);
base = DR_BASE_NAME (new_dr);
switch (TREE_CODE (base))
{
case VAR_DECL:
symbl = base;
break;
case INDIRECT_REF:
symbl = TREE_OPERAND (base, 0);
break; break;
case COMPONENT_REF:
/* Could have recorded more accurate information -
i.e, the actual FIELD_DECL that is being referenced -
but later passes expect VAR_DECL as the nmt. */
symbl = vect_get_base_and_bit_offset (new_dr, base, NULL_TREE,
loop_vinfo, &offset, &base_aligned_p);
if (symbl)
break;
/* fall through */
default: default:
if (vect_debug_details (NULL)) /* TODO: Support data-refs of form a[i].p for unions and single
{ field structures. */
fprintf (dump_file, "unhandled struct/class field access ");
print_generic_expr (dump_file, stmt, TDF_SLIM);
}
return NULL_TREE; return NULL_TREE;
} }
break;
default:
if (vect_debug_details (NULL))
{
fprintf (dump_file, "unhandled data ref: ");
print_generic_expr (dump_file, memref, TDF_SLIM);
fprintf (dump_file, " in stmt ");
print_generic_expr (dump_file, stmt, TDF_SLIM);
} }
if (!symbl)
return NULL_TREE; return NULL_TREE;
} /* Recursive call to retrieve the relevant memtag. */
return symbl; tag = vect_get_symbl_and_dr (symbl, stmt, is_read, loop_vinfo, dr);
return tag;
} }
...@@ -4912,10 +4929,6 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) ...@@ -4912,10 +4929,6 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
block_stmt_iterator si; block_stmt_iterator si;
int j; int j;
struct data_reference *dr; struct data_reference *dr;
tree tag;
tree address_base;
bool base_aligned_p;
tree offset;
if (vect_debug_details (NULL)) if (vect_debug_details (NULL))
fprintf (dump_file, "\n<<vect_analyze_data_refs>>\n"); fprintf (dump_file, "\n<<vect_analyze_data_refs>>\n");
...@@ -4982,6 +4995,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) ...@@ -4982,6 +4995,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
/* Analyze MEMREF. If it is of a supported form, build data_reference /* Analyze MEMREF. If it is of a supported form, build data_reference
struct for it (DR) and find the relevant symbol for aliasing struct for it (DR) and find the relevant symbol for aliasing
purposes. */ purposes. */
dr = NULL;
symbl = vect_get_symbl_and_dr (memref, stmt, is_read, loop_vinfo, symbl = vect_get_symbl_and_dr (memref, stmt, is_read, loop_vinfo,
&dr); &dr);
if (!symbl) if (!symbl)
...@@ -4993,83 +5007,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) ...@@ -4993,83 +5007,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
} }
return false; return false;
} }
/* Find and record the memtag assigned to this data-ref. */
switch (TREE_CODE (symbl))
{
case VAR_DECL:
STMT_VINFO_MEMTAG (stmt_info) = symbl; STMT_VINFO_MEMTAG (stmt_info) = symbl;
break;
case SSA_NAME:
symbl = SSA_NAME_VAR (symbl);
tag = get_var_ann (symbl)->type_mem_tag;
if (!tag)
{
tree ptr = TREE_OPERAND (memref, 0);
if (TREE_CODE (ptr) == SSA_NAME)
tag = get_var_ann (SSA_NAME_VAR (ptr))->type_mem_tag;
}
if (!tag)
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file, "not vectorized: no memtag for ref.");
return false;
}
STMT_VINFO_MEMTAG (stmt_info) = tag;
break;
case ADDR_EXPR:
address_base = TREE_OPERAND (symbl, 0);
switch (TREE_CODE (address_base))
{
case ARRAY_REF:
{
struct data_reference *tmp_dr;
tmp_dr = analyze_array (stmt, TREE_OPERAND (symbl, 0),
DR_IS_READ (dr));
tag = vect_get_base_and_bit_offset
(tmp_dr, DR_BASE_NAME (tmp_dr),
NULL_TREE, loop_vinfo, &offset, &base_aligned_p);
if (!tag)
{
if (vect_debug_stats (loop)
|| vect_debug_details (loop))
fprintf (dump_file,
"not vectorized: no memtag for ref.");
return false;
}
STMT_VINFO_MEMTAG (stmt_info) = tag;
}
break;
case VAR_DECL:
STMT_VINFO_MEMTAG (stmt_info) = address_base;
break;
default:
if (vect_debug_stats (loop) || vect_debug_details (loop))
{
fprintf (dump_file,
"not vectorized: unhandled address expr: ");
print_generic_expr (dump_file, stmt, TDF_SLIM);
}
return false;
}
break;
default:
if (vect_debug_stats (loop) || vect_debug_details (loop))
{
fprintf (dump_file, "not vectorized: unsupported data-ref: ");
print_generic_expr (dump_file, memref, TDF_SLIM);
}
return false;
}
VARRAY_PUSH_GENERIC_PTR (*datarefs, dr); VARRAY_PUSH_GENERIC_PTR (*datarefs, dr);
STMT_VINFO_DATA_REF (stmt_info) = dr; STMT_VINFO_DATA_REF (stmt_info) = dr;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment