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.h (struct _stmt_vec_info): Add new fields:
        initial_offset, step, misalignment and base_aligned_p and macros
        to access them.
        * tree-vectorizer.c (vect_analyze_offset_expr): New function.
        (new_stmt_vec_info): Initialize the new fields of stmt_vec_info.

        (vect_create_data_ref_ptr): Fix printings.

From-SVN: r92701
This commit is contained in:
Ira Rosen 2004-12-29 13:16:07 +00:00 committed by Dorit Nuzman
parent 6e611d9276
commit 1de6a87312
3 changed files with 242 additions and 22 deletions

View File

@ -1,6 +1,17 @@
2004-12-29 Ira Rosen <irar@il.ibm.com>
PR tree-optimization/18179
PR tree-optimization/18179
* tree-vectorizer.h (struct _stmt_vec_info): Add new fields:
initial_offset, step, misalignment and base_aligned_p and macros
to access them.
* tree-vectorizer.c (vect_analyze_offset_expr): New function.
(new_stmt_vec_info): Initialize the new fields of stmt_vec_info.
(vect_create_data_ref_ptr): Fix printings.
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.

View File

@ -232,6 +232,8 @@ static tree vect_compute_array_ref_alignment
static tree vect_get_ptr_offset (tree, tree, tree *);
static tree vect_get_symbl_and_dr
(tree, tree, bool, loop_vec_info, struct data_reference **);
static bool vect_analyze_offset_expr (tree, struct loop *, tree, tree *,
tree *, tree *);
/* Utility functions for the code transformation. */
static tree vect_create_destination_var (tree, tree);
@ -1139,6 +1141,10 @@ new_stmt_vec_info (tree stmt, struct loop *loop)
STMT_VINFO_DATA_REF (res) = NULL;
STMT_VINFO_MEMTAG (res) = NULL;
STMT_VINFO_VECT_DR_BASE (res) = NULL;
STMT_VINFO_VECT_INIT_OFFSET (res) = NULL_TREE;
STMT_VINFO_VECT_STEP (res) = NULL_TREE;
STMT_VINFO_VECT_BASE_ALIGNED_P (res) = false;
STMT_VINFO_VECT_MISALIGNMENT (res) = NULL_TREE;
return res;
}
@ -1338,6 +1344,189 @@ vect_get_ptr_offset (tree ref ATTRIBUTE_UNUSED,
}
/* Function vect_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
subsituted, 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) if possible. Misalignment can be calculated only if all the
variables can be substitued with constants, or if a variable is multiplied
by a multiple of VECTYPE_ALIGNMENT. In the above example, since 'i' cannot
be substituted, MISALIGN will be NULL_TREE in case that C_i is not a multiple
of VECTYPE_ALIGNMENT, and C` otherwise. (We perform MISALIGN modulo
VECTYPE_ALIGNMENT computation in the caller of this function).
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 and STEP)
are NULL_TREEs. Otherwise, return TRUE.
*/
static bool
vect_analyze_offset_expr (tree expr,
struct loop *loop,
tree vectype_alignment,
tree *initial_offset,
tree *misalign,
tree *step)
{
tree oprnd0;
tree oprnd1;
tree left_offset = size_zero_node;
tree right_offset = size_zero_node;
tree left_misalign = size_zero_node;
tree right_misalign = size_zero_node;
tree left_step = size_zero_node;
tree right_step = size_zero_node;
enum tree_code code;
tree init, evolution, def_stmt;
STRIP_NOPS (expr);
*step = NULL_TREE;
*misalign = NULL_TREE;
*initial_offset = NULL_TREE;
/* Stop conditions:
1. Constant. */
if (TREE_CONSTANT (expr))
{
*initial_offset = fold_convert (sizetype, expr);
*misalign = fold_convert (sizetype, expr);
*step = size_zero_node;
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;
init = initial_condition_in_loop_num (access_fn, loop->num);
if (init == expr)
{
def_stmt = SSA_NAME_DEF_STMT (init);
if (def_stmt
&& !IS_EMPTY_STMT (def_stmt)
&& flow_bb_inside_loop_p (loop, bb_for_stmt (def_stmt)))
/* 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_CONSTANT (init))
*misalign = fold_convert (sizetype, init);
else
/* Not constant, misalignment cannot be calculated. */
*misalign = NULL_TREE;
*initial_offset = fold_convert (sizetype, init);
*step = evolution ? fold_convert (sizetype, evolution) : size_zero_node;
return true;
}
/* Recursive computation. */
oprnd0 = TREE_OPERAND (expr, 0);
oprnd1 = TREE_OPERAND (expr, 1);
if (!vect_analyze_offset_expr (oprnd0, loop, vectype_alignment, &left_offset,
&left_misalign, &left_step)
|| !vect_analyze_offset_expr (oprnd1, loop, vectype_alignment,
&right_offset, &right_misalign, &right_step))
return false;
/* The type of the operation: plus, minus or mult. */
code = TREE_CODE (expr);
switch (code)
{
case MULT_EXPR:
if (!TREE_CONSTANT (right_offset))
/* RIGHT_OFFSET can be not constant. For example, for arrays of variable
sized types.
FORNOW: We don't support such cases. */
return false;
/* Misalignment computation. */
if (SSA_VAR_P (left_offset))
{
/* If the left side contains variable that cannot be substituted with
constant, we check if the right side is a multiple of ALIGNMENT. */
if (integer_zerop (size_binop (TRUNC_MOD_EXPR, right_offset,
vectype_alignment)))
*misalign = size_zero_node;
else
/* If the remainder is not zero or the right side isn't constant, we
can't compute misalignment. */
*misalign = NULL_TREE;
}
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);
else
*misalign = NULL_TREE;
}
/* 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);
if (left_misalign && right_misalign)
*misalign = size_binop (code, left_misalign, right_misalign);
else
*misalign = NULL_TREE;
break;
default:
gcc_unreachable ();
}
/* Compute offset. */
*initial_offset = fold_convert (sizetype,
fold (build2 (code, TREE_TYPE (left_offset),
left_offset,
right_offset)));
return true;
}
/* Function vect_get_base_and_bit_offset
Return the BASE of the data reference EXPR.
@ -1885,13 +2074,13 @@ vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset,
fprintf (dump_file, "create array_ref of type: ");
print_generic_expr (dump_file, vectype, TDF_SLIM);
if (TREE_CODE (data_ref_base) == VAR_DECL)
fprintf (dump_file, "vectorizing a one dimensional array ref: ");
fprintf (dump_file, "\nvectorizing a one dimensional array ref: ");
else if (TREE_CODE (data_ref_base) == ARRAY_REF)
fprintf (dump_file, "vectorizing a multidimensional array ref: ");
fprintf (dump_file, "\nvectorizing a multidimensional array ref: ");
else if (TREE_CODE (data_ref_base) == COMPONENT_REF)
fprintf (dump_file, "vectorizing a record based array ref: ");
fprintf (dump_file, "\nvectorizing a record based array ref: ");
else if (TREE_CODE (data_ref_base) == SSA_NAME)
fprintf (dump_file, "vectorizing a pointer ref: ");
fprintf (dump_file, "\nvectorizing a pointer ref: ");
print_generic_expr (dump_file, base_name, TDF_SLIM);
}

View File

@ -85,26 +85,46 @@ typedef struct _stmt_vec_info {
/* Aliasing information. */
tree memtag;
/* Data reference base. This field holds the entire invariant part of the
data-reference (with respect to the relevant loop), as opposed to the
field DR_BASE of the STMT_VINFO_DATA_REF struct, which holds only the
initial base; e.g:
REF BR_BASE VECT_DR_BASE
a[i] a a
a[i][j] a a[i] */
tree vect_dr_base;
/** The following fields are used to store the information about
data-reference. {base + initial_offset} is the first location accessed by
data-ref in the loop, and step is the stride of data-ref in the loop;
e.g.:
Example 1 Example 2
data-ref a[j].b[i][j] a + 4B (a is int*)
base a a
initial_offset j_0*D_j + i_0*D_i + C 4
step D_j 4
**/
/* The above base, offset and step. */
tree base;
tree initial_offset;
tree step;
/* Alignment information. Whether the base of the data-reference is aligned
to vectype. */
bool base_aligned_p;
/* Alignment information. The offset of the data-reference from its base
in bytes. */
tree misalignment;
} *stmt_vec_info;
/* Access Functions. */
#define STMT_VINFO_TYPE(S) (S)->type
#define STMT_VINFO_STMT(S) (S)->stmt
#define STMT_VINFO_LOOP(S) (S)->loop
#define STMT_VINFO_RELEVANT_P(S) (S)->relevant
#define STMT_VINFO_VECTYPE(S) (S)->vectype
#define STMT_VINFO_VEC_STMT(S) (S)->vectorized_stmt
#define STMT_VINFO_DATA_REF(S) (S)->data_ref_info
#define STMT_VINFO_MEMTAG(S) (S)->memtag
#define STMT_VINFO_VECT_DR_BASE(S) (S)->vect_dr_base
#define STMT_VINFO_TYPE(S) (S)->type
#define STMT_VINFO_STMT(S) (S)->stmt
#define STMT_VINFO_LOOP(S) (S)->loop
#define STMT_VINFO_RELEVANT_P(S) (S)->relevant
#define STMT_VINFO_VECTYPE(S) (S)->vectype
#define STMT_VINFO_VEC_STMT(S) (S)->vectorized_stmt
#define STMT_VINFO_DATA_REF(S) (S)->data_ref_info
#define STMT_VINFO_MEMTAG(S) (S)->memtag
#define STMT_VINFO_VECT_DR_BASE(S) (S)->base
#define STMT_VINFO_VECT_INIT_OFFSET(S) (S)->initial_offset
#define STMT_VINFO_VECT_STEP(S) (S)->step
#define STMT_VINFO_VECT_BASE_ALIGNED_P(S) (S)->base_aligned_p
#define STMT_VINFO_VECT_MISALIGNMENT(S) (S)->misalignment
static inline void set_stmt_info (stmt_ann_t ann, stmt_vec_info stmt_info);
static inline stmt_vec_info vinfo_for_stmt (tree stmt);