-/* Anlaysis Utilities for Loop Vectorization.
+/* Analysis Utilities for Loop Vectorization.
Copyright (C) 2003,2004,2005 Free Software Foundation, Inc.
Contributed by Dorit Naishlos <dorit@il.ibm.com>
struct data_reference *drb, bool *);
static tree vect_object_analysis (tree, tree, bool, tree,
struct data_reference **, tree *, tree *,
- tree *, bool *);
+ tree *, bool *, tree *);
static tree vect_address_analysis (tree, tree, bool, tree,
struct data_reference *, tree *, tree *,
tree *, bool *);
-static tree vect_get_memtag (tree, struct data_reference *);
/* Function vect_get_ptr_offset
"not vectorized: can't create epilog loop 1.");
return false;
}
- if (!slpeel_can_duplicate_loop_p (loop, loop->exit_edges[0]))
+ if (!slpeel_can_duplicate_loop_p (loop, loop->single_exit))
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
LOOP_LOC (loop_vinfo)))
}
reftype = TREE_TYPE (TREE_OPERAND (memref, 0));
- if (TREE_CODE (reftype) != POINTER_TYPE)
+ if (!POINTER_TYPE_P (reftype))
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
LOOP_LOC (loop_vinfo)))
}
reftype = TREE_TYPE (init);
- if (TREE_CODE (reftype) != POINTER_TYPE)
+ if (!POINTER_TYPE_P (reftype))
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
LOOP_LOC (loop_vinfo)))
}
-/* Function vect_get_memtag.
-
- The function returns the relevant variable for memory tag (for aliasing
- purposes). */
-
-static tree
-vect_get_memtag (tree memref, struct data_reference *dr)
-{
- tree symbl, tag;
-
- switch (TREE_CODE (memref))
- {
- case SSA_NAME:
- 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;
- }
- return tag;
-
- case ADDR_EXPR:
- return TREE_OPERAND (memref, 0);
-
- default:
- return NULL_TREE;
- }
-}
-
-
/* Function vect_address_analysis
Return the BASE of the address expression EXPR.
{
tree oprnd0, oprnd1, base_address, offset_expr, base_addr0, base_addr1;
tree address_offset = ssize_int (0), address_misalign = ssize_int (0);
+ tree dummy;
switch (TREE_CODE (expr))
{
case ADDR_EXPR:
base_address = vect_object_analysis (TREE_OPERAND (expr, 0), stmt, is_read,
vectype, &dr, offset, misalign, step,
- base_aligned);
+ base_aligned, &dummy);
return base_address;
case SSA_NAME:
- if (TREE_CODE (TREE_TYPE (expr)) != POINTER_TYPE)
+ if (!POINTER_TYPE_P (TREE_TYPE (expr)))
return NULL_TREE;
-
+
if (TYPE_ALIGN (TREE_TYPE (TREE_TYPE (expr))) < TYPE_ALIGN (vectype))
{
if (vect_get_ptr_offset (expr, vectype, misalign))
the computation is impossible
STEP - evolution of the DR_REF in the loop
BASE_ALIGNED - indicates if BASE is aligned
+ MEMTAG - memory tag for aliasing purposes
If something unexpected is encountered (an unsupported form of data-ref),
then NULL_TREE is returned. */
vect_object_analysis (tree memref, tree stmt, bool is_read,
tree vectype, struct data_reference **dr,
tree *offset, tree *misalign, tree *step,
- bool *base_aligned)
+ bool *base_aligned, tree *memtag)
{
tree base = NULL_TREE, base_address = NULL_TREE;
tree object_offset = ssize_int (0), object_misalign = ssize_int (0);
DR_BASE_NAME ((*dr)) = memref;
base_address = build_fold_addr_expr (memref);
+ *memtag = memref;
}
/* Part 1: Case 3. INDIRECT_REFs. */
base_address = vect_address_analysis (address_to_analyze, stmt, is_read,
vectype, *dr, &address_offset, &address_misalign,
&address_step, &address_base_aligned);
+ if (!base_address)
+ return NULL_TREE;
+
+ switch (TREE_CODE (base_address))
+ {
+ case SSA_NAME:
+ *memtag = get_var_ann (SSA_NAME_VAR (base_address))->type_mem_tag;
+ if (!(*memtag) && TREE_CODE (TREE_OPERAND (memref, 0)) == SSA_NAME)
+ *memtag = get_var_ann (
+ SSA_NAME_VAR (TREE_OPERAND (memref, 0)))->type_mem_tag;
+ break;
+ case ADDR_EXPR:
+ *memtag = TREE_OPERAND (base_address, 0);
+ break;
+ default:
+ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
+ LOOP_LOC (loop_vinfo)))
+ {
+ fprintf (vect_dump, "not vectorized: no memtag ref: ");
+ print_generic_expr (vect_dump, memref, TDF_SLIM);
+ }
+ return NULL_TREE;
+ }
}
if (!base_address)
{
fprintf (vect_dump, "Results of object analysis for: ");
print_generic_expr (vect_dump, memref, TDF_SLIM);
- fprintf (vect_dump, "\n\tbase: ");
- print_generic_expr (vect_dump, base, TDF_SLIM);
+ fprintf (vect_dump, "\n\tbase_address: ");
+ print_generic_expr (vect_dump, base_address, TDF_SLIM);
fprintf (vect_dump, "\n\toffset: ");
print_generic_expr (vect_dump, *offset, TDF_SLIM);
fprintf (vect_dump, "\n\tstep: ");
Find and analyze all data-refs in the loop:
foreach ref
base_address = vect_object_analysis(ref)
- ref_stmt.memtag = vect_get_memtag(base)
1.1- vect_object_analysis(ref):
Analyze ref, and build a DR (data_referece struct) for it;
compute base, initial_offset, step and alignment.
Call get_inner_reference for refs handled in this function.
Call vect_addr_analysis(addr) to analyze pointer type expressions.
- Set ref_stmt.base, ref_stmt.initial_offset, ref_stmt.alignment, and
- ref_stmt.step accordingly.
+ Set ref_stmt.base, ref_stmt.initial_offset, ref_stmt.alignment,
+ ref_stmt.memtag and ref_stmt.step accordingly.
2- vect_analyze_dependences(): apply dependence testing using ref_stmt.DR
3- vect_analyze_drs_alignment(): check that ref_stmt.alignment is ok.
4- vect_analyze_drs_access(): check that ref_stmt.step is ok.
dr = NULL;
base = vect_object_analysis (memref, stmt, is_read, vectype, &dr,
&offset, &misalign, &step,
- &base_aligned);
+ &base_aligned, &tag);
if (!base)
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
}
return false;
}
- /* Find memtag for aliasing purposes. */
- tag = vect_get_memtag (base, dr);
- if (!tag)
- {
- if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
- LOOP_LOC (loop_vinfo)))
- {
- fprintf (vect_dump, "not vectorized: no memtag ref: ");
- print_generic_expr (vect_dump, memref, TDF_SLIM);
- }
- return false;
- }
STMT_VINFO_VECT_DR_BASE_ADDRESS (stmt_info) = base;
STMT_VINFO_VECT_INIT_OFFSET (stmt_info) = offset;
STMT_VINFO_VECT_STEP (stmt_info) = step;
loop_vec_info loop_vinfo;
tree loop_cond;
tree number_of_iterations = NULL;
- bool rescan = false;
LOC loop_loc;
loop_loc = find_loop_location (loop);
if (!loop->single_exit
|| loop->num_nodes != 2
- || EDGE_COUNT (loop->header->preds) != 2
- || loop->num_entries != 1)
+ || EDGE_COUNT (loop->header->preds) != 2)
{
if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
{
fprintf (vect_dump, "not vectorized: too many BBs in loop.");
else if (EDGE_COUNT (loop->header->preds) != 2)
fprintf (vect_dump, "not vectorized: too many incoming edges.");
- else if (loop->num_entries != 1)
- fprintf (vect_dump, "not vectorized: too many entries.");
}
return NULL;
return NULL;
}
- /* Make sure we have a preheader basic block. */
- if (!loop->pre_header)
- {
- rescan = true;
- loop_split_edge_with (loop_preheader_edge (loop), NULL);
- }
-
/* Make sure there exists a single-predecessor exit bb: */
- if (EDGE_COUNT (loop->exit_edges[0]->dest->preds) != 1)
- {
- rescan = true;
- loop_split_edge_with (loop->exit_edges[0], NULL);
- }
-
- if (rescan)
+ if (EDGE_COUNT (loop->single_exit->dest->preds) != 1)
{
- flow_loop_scan (loop, LOOP_ALL);
- /* Flow loop scan does not update loop->single_exit field. */
- loop->single_exit = loop->exit_edges[0];
+ edge e = loop->single_exit;
+ if (!(e->flags & EDGE_ABNORMAL))
+ {
+ loop_split_edge_with (e, NULL);
+ if (vect_print_dump_info (REPORT_DETAILS, loop_loc))
+ fprintf (vect_dump, "split exit edge.");
+ }
+ else
+ {
+ if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
+ fprintf (vect_dump, "not vectorized: abnormal loop exit edge.");
+ return NULL;
+ }
}
if (empty_block_p (loop->header))