This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[graphite] push some of my local changes in the branch
- From: "Sebastian Pop" <sebastian dot pop at inria dot fr>
- To: "GCC Patches" <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 9 May 2007 18:38:12 +0200
- Subject: [graphite] push some of my local changes in the branch
Hi,
here is a patch that updates the branch with some more fixes
for building the graphite representation. The patch was in one
of my local branches for some time now, but I'm still not happy
yet with the representation, so this will probably change again
in the near future. The next part will be the code generation
back to gimple representation.
Sebastian
2007-05-09 Sebastian Pop <sebastian.pop@inria.fr>
* tree-data-ref.c: Don't include graphite.h.
Comment out the code for printing data reference's scop.
(build_access_matrix_with_af): Moved...
* tree-data-ref.h (build_access_matrix_with_af): Removed declaration.
* graphite.c (build_access_matrix_with_af): ... here. Now static.
(print_graphite_bb): Print basic block's schedule.
(print_scop): Don't print the schedule, call cloog's pretty printer.
(bb_in_scop_p): A basic block is in a scop only if it is both
dominated and postdominated by the scop's entry and exit basic blocks.
(function_parameter_p): New.
(invariant_in_scop_p): Use function_parameter_p.
(new_scop, save_scop): New.
(end_scop, test_for_scop_bound, build_scops): Use new_scop, and
save_scop.
(scan_tree_for_params): Directly build the constraint as CloogMatrix.
(loop_in_scop_p): New.
(scop_record_loop): Use loop_in_scop_p.
(build_scop_domain): Renamed build_scop_iteration_domain.
(setup_cloog_loop, initialize_cloog_names, find_scop_parameters,
nb_params_in_scop, build_scop_context, first_loop_in_scop,
setup_cloog_loop, dot_scop_1, dot_scop): New.
* graphite.h (GBB_LOOP, SCOP_PROG, dot_scop): New.
(struct scop): Add a pointer to cloog's representation of a program.
Index: tree-data-ref.c
===================================================================
*** tree-data-ref.c (revision 123814)
--- tree-data-ref.c (working copy)
*************** Software Foundation, 51 Franklin Street,
*** 92,98 ****
#include "tree-chrec.h"
#include "tree-data-ref.h"
#include "tree-scalar-evolution.h"
! #include "graphite.h"
#include "tree-pass.h"
#include "langhooks.h"
--- 92,98 ----
#include "tree-chrec.h"
#include "tree-data-ref.h"
#include "tree-scalar-evolution.h"
! /* #include "graphite.h" */
#include "tree-pass.h"
#include "langhooks.h"
*************** dump_data_reference (FILE *outf,
*** 646,651 ****
--- 646,652 ----
print_generic_stmt (outf, DR_ACCESS_FN (dr, i), 0);
}
+ /*
if (DR_SCOP (dr))
{
lambda_vector v;
*************** dump_data_reference (FILE *outf,
*** 655,660 ****
--- 656,662 ----
for (i = 0; VEC_iterate (lambda_vector, DR_ACCESS_MATRIX (dr), i, v); i++)
print_lambda_vector (outf, v, scop_dim_domain (DR_SCOP (dr)));
}
+ */
fprintf (outf, ")\n");
}
*************** find_data_references_in_loop (struct loo
*** 5031,5103 ****
return NULL_TREE;
}
- /* Initializes an equation CY of the access matrix using the
- information for a subscript from ACCESS_FUN, relatively to the loop
- indexes from LOOP_NEST and parameter indexes from PARAMS. Returns
- true when the operation succeeded. */
-
- bool
- build_access_matrix_with_af (tree access_fun, lambda_vector cy,
- VEC (loop_p, heap) *loop_nest,
- VEC (tree, heap) *params)
- {
- switch (TREE_CODE (access_fun))
- {
- case POLYNOMIAL_CHREC:
- {
- tree left = CHREC_LEFT (access_fun);
- tree right = CHREC_RIGHT (access_fun);
- int var = CHREC_VARIABLE (access_fun);
- unsigned var_idx;
- struct loop *loopi;
-
- if (TREE_CODE (right) != INTEGER_CST)
- return false;
-
- /* Find the index of the current variable VAR_IDX in the
- LOOP_NEST array. */
- for (var_idx = 0; VEC_iterate (loop_p, loop_nest, var_idx, loopi);
- var_idx++)
- if (loopi->num == var)
- break;
-
- gcc_assert (loopi && loopi->num == var);
-
- cy[var_idx] = int_cst_value (right);
-
- switch (TREE_CODE (left))
- {
- case POLYNOMIAL_CHREC:
- return build_access_matrix_with_af (left, cy, loop_nest, params);
-
- case INTEGER_CST:
- {
- /* Constant part. */
- unsigned nb_loops = VEC_length (loop_p, loop_nest);
- unsigned nb_params = VEC_length (tree, params);
-
- cy[nb_loops + nb_params] = int_cst_value (left);
- return true;
- }
-
- default:
- return false;
- }
- }
- case INTEGER_CST:
- {
- /* Constant part. */
- unsigned nb_loops = VEC_length (loop_p, loop_nest);
- unsigned nb_params = VEC_length (tree, params);
- cy[nb_loops + nb_params] = int_cst_value (access_fun);
- return true;
- }
-
- default:
- return false;
- }
- }
-
/* Recursive helper function. */
static bool
--- 5033,5038 ----
Index: tree-data-ref.h
===================================================================
*** tree-data-ref.h (revision 123814)
--- tree-data-ref.h (working copy)
*************** extern void free_data_ref (data_referenc
*** 396,405 ****
extern void free_data_refs (VEC (data_reference_p, heap) *);
extern struct data_reference *create_data_ref (tree, tree, bool);
extern bool find_data_references_in_stmt (tree, VEC (data_reference_p, heap) **);
- extern bool build_access_matrix_with_af (tree, lambda_vector,
- VEC (loop_p, heap) *,
- VEC (tree, heap) *);
- extern unsigned dr_num_subscripts (data_reference_p);
/* Return the index of the variable VAR in the LOOP_NEST array. */
--- 396,401 ----
Index: graphite.c
===================================================================
*** graphite.c (revision 123814)
--- graphite.c (working copy)
*************** void
*** 55,60 ****
--- 55,65 ----
print_graphite_bb (FILE *file, graphite_bb_p gb, int indent, int verbosity)
{
fprintf (file, "\nGBB (\n");
+
+ fprintf (file, " (static schedule: ");
+ print_lambda_vector (file, GBB_STATIC_SCHEDULE (gb), scop_nb_loops (GBB_SCOP (gb)) + 1);
+ fprintf (file, " )\n");
+
print_loop_ir_bb (file, GBB_BB (gb), indent+2, verbosity);
dump_data_references (file, GBB_DATA_REFS (gb));
fprintf (file, ")\n");
*************** print_graphite_bb (FILE *file, graphite_
*** 65,83 ****
static void
print_scop (FILE *file, scop_p scop, int verbosity)
{
- unsigned i;
- lambda_vector v;
-
fprintf (file, "\nSCoP_%d_%d (\n",
! scop->entry->index, scop->exit->index);
!
! fprintf (file, " (static schedule: ");
! print_lambda_vector (file, SCOP_STATIC_SCHEDULE (scop), scop_nb_loops (scop));
! fprintf (file, " )\n");
! fprintf (file, " (domain: \n");
! for (i = 0; VEC_iterate (lambda_vector, SCOP_DOMAIN (scop), i, v); i++)
! print_lambda_vector (file, v, scop_dim_domain (scop));
fprintf (file, " )\n");
if (scop->bbs)
--- 70,80 ----
static void
print_scop (FILE *file, scop_p scop, int verbosity)
{
fprintf (file, "\nSCoP_%d_%d (\n",
! SCOP_ENTRY (scop)->index, SCOP_EXIT (scop)->index);
! fprintf (file, " (cloog: \n");
! cloog_program_print (file, SCOP_PROG (scop));
fprintf (file, " )\n");
if (scop->bbs)
*************** stmt_simple_for_scop_p (tree stmt)
*** 224,230 ****
there might be exponential scevs. On the other hand, if
these exponential scevs do not reference arrays, then
access functions, domains and schedules remain affine. So
! it is very well possible that we can handle this. */
return true;
}
--- 221,228 ----
there might be exponential scevs. On the other hand, if
these exponential scevs do not reference arrays, then
access functions, domains and schedules remain affine. So
! it is very well possible that we can handle exponential
! scalar computations. */
return true;
}
*************** basic_block_simple_for_scop_p (basic_blo
*** 271,277 ****
static inline bool
bb_in_scop_p (basic_block bb, scop_p scop)
{
! return dominated_by_p (CDI_DOMINATORS, bb, scop->entry);
}
/* Return true when STMT is contained in SCOP. */
--- 269,276 ----
static inline bool
bb_in_scop_p (basic_block bb, scop_p scop)
{
! return (dominated_by_p (CDI_DOMINATORS, bb, SCOP_ENTRY (scop))
! && dominated_by_p (CDI_POST_DOMINATORS, bb, SCOP_EXIT (scop)));
}
/* Return true when STMT is contained in SCOP. */
*************** stmt_in_scop_p (tree stmt, scop_p scop)
*** 282,287 ****
--- 281,292 ----
return bb_in_scop_p (bb_for_stmt (stmt), scop);
}
+ static inline bool
+ function_parameter_p (tree var)
+ {
+ return (TREE_CODE (SSA_NAME_VAR (var)) == PARM_DECL);
+ }
+
/* Return true when VAR is invariant in SCOP. In that case, VAR is a
parameter of SCOP. */
*************** invariant_in_scop_p (tree var, scop_p sc
*** 290,296 ****
{
gcc_assert (TREE_CODE (var) == SSA_NAME);
! return !stmt_in_scop_p (SSA_NAME_DEF_STMT (var), scop);
}
/* Find the first basic block that dominates BB and that exits the
--- 295,302 ----
{
gcc_assert (TREE_CODE (var) == SSA_NAME);
! return (function_parameter_p (var)
! || !stmt_in_scop_p (SSA_NAME_DEF_STMT (var), scop));
}
/* Find the first basic block that dominates BB and that exits the
*************** get_loop_start (basic_block bb)
*** 312,337 ****
static scop_p down_open_scop;
/* Build the SCoP ending with BB. */
static void
end_scop (basic_block bb)
{
! scop_p new_scop;
basic_block loop_start = get_loop_start (bb);
! if (dominated_by_p (CDI_DOMINATORS, down_open_scop->entry, loop_start))
{
! down_open_scop->exit = bb;
! VEC_safe_push (scop_p, heap, current_scops, down_open_scop);
! return;
}
! new_scop = XNEW (struct scop);
! SCOP_ENTRY (new_scop) = loop_start;
! SCOP_EXIT (new_scop) = bb;
! end_scop (loop_start);
! VEC_safe_push (scop_p, heap, current_scops, new_scop);
}
/* Mark difficult constructs as boundaries of SCoPs. Callback for
--- 318,369 ----
static scop_p down_open_scop;
+ /* Creates a new scop starting with BB. */
+
+ static scop_p
+ new_scop (basic_block bb)
+ {
+ scop_p scop = XNEW (struct scop);
+
+ SCOP_ENTRY (scop) = bb;
+ SCOP_BBS (scop) = VEC_alloc (graphite_bb_p, heap, 3);
+ SCOP_LOOP_NEST (scop) = VEC_alloc (loop_p, heap, 3);
+ SCOP_PARAMS (scop) = VEC_alloc (tree, heap, 3);
+ SCOP_PROG (scop) = cloog_program_malloc ();
+ SCOP_PROG (scop)->names = cloog_names_malloc ();
+
+ return scop;
+ }
+
+ /* Save the SCOP. */
+
+ static inline void
+ save_scop (scop_p scop)
+ {
+ VEC_safe_push (scop_p, heap, current_scops, scop);
+ }
+
/* Build the SCoP ending with BB. */
static void
end_scop (basic_block bb)
{
! scop_p scop;
basic_block loop_start = get_loop_start (bb);
! if (dominated_by_p (CDI_DOMINATORS, SCOP_ENTRY (down_open_scop), loop_start))
{
! scop = down_open_scop;
! SCOP_EXIT (scop) = bb;
! }
! else
! {
! scop = new_scop (loop_start);
! SCOP_EXIT (scop) = bb;
! end_scop (loop_start);
}
! save_scop (scop);
}
/* Mark difficult constructs as boundaries of SCoPs. Callback for
*************** test_for_scop_bound (struct dom_walk_dat
*** 348,361 ****
fprintf (dump_file, "down bb_%d\n", bb->index);
/* Exiting the loop containing the open scop ends the scop. */
! if (down_open_scop->entry->loop_father->depth > bb->loop_father->depth)
{
! down_open_scop->exit = bb;
! VEC_safe_push (scop_p, heap, current_scops, down_open_scop);
!
! /* Then we begin a new scop at this block. */
! down_open_scop = XNEW (struct scop);
! down_open_scop->entry = bb;
if (debug_p ())
fprintf (dump_file, "dom bound bb_%d\n\n", bb->index);
--- 380,390 ----
fprintf (dump_file, "down bb_%d\n", bb->index);
/* Exiting the loop containing the open scop ends the scop. */
! if (SCOP_ENTRY (down_open_scop)->loop_father->depth > bb->loop_father->depth)
{
! SCOP_EXIT (down_open_scop) = bb;
! save_scop (down_open_scop);
! down_open_scop = new_scop (bb);
if (debug_p ())
fprintf (dump_file, "dom bound bb_%d\n\n", bb->index);
*************** test_for_scop_bound (struct dom_walk_dat
*** 365,376 ****
if (!basic_block_simple_for_scop_p (bb))
{
- /* A difficult construct ends the scop. */
end_scop (bb);
!
! /* Then we begin a new scop at this block. */
! down_open_scop = XNEW (struct scop);
! down_open_scop->entry = bb;
if (debug_p ())
fprintf (dump_file, "difficult bound bb_%d\n\n", bb->index);
--- 394,401 ----
if (!basic_block_simple_for_scop_p (bb))
{
end_scop (bb);
! down_open_scop = new_scop (bb);
if (debug_p ())
fprintf (dump_file, "difficult bound bb_%d\n\n", bb->index);
*************** test_for_scop_bound (struct dom_walk_dat
*** 379,395 ****
}
}
! /* Find static control parts in LOOPS, and save these in the
! CURRENT_SCOPS vector. */
static void
build_scops (void)
{
struct dom_walk_data walk_data;
! down_open_scop = XNEW (struct scop);
! down_open_scop->entry = ENTRY_BLOCK_PTR;
!
memset (&walk_data, 0, sizeof (struct dom_walk_data));
walk_data.before_dom_children_before_stmts = test_for_scop_bound;
--- 404,417 ----
}
}
! /* Find static control parts. */
static void
build_scops (void)
{
struct dom_walk_data walk_data;
! down_open_scop = new_scop (ENTRY_BLOCK_PTR);
memset (&walk_data, 0, sizeof (struct dom_walk_data));
walk_data.before_dom_children_before_stmts = test_for_scop_bound;
*************** build_scops (void)
*** 398,405 ****
fini_walk_dominator_tree (&walk_data);
/* End the last open scop. */
! down_open_scop->exit = EXIT_BLOCK_PTR;
! VEC_safe_push (scop_p, heap, current_scops, down_open_scop);
}
--- 420,427 ----
fini_walk_dominator_tree (&walk_data);
/* End the last open scop. */
! SCOP_EXIT (down_open_scop) = EXIT_BLOCK_PTR;
! save_scop (down_open_scop);
}
*************** param_index (tree var, scop_p scop)
*** 414,419 ****
--- 436,443 ----
int i;
tree p;
+ gcc_assert (TREE_CODE (var) == SSA_NAME);
+
for (i = 0; VEC_iterate (tree, SCOP_PARAMS (scop), i, p); i++)
if (p == var)
return i;
*************** param_index (tree var, scop_p scop)
*** 422,495 ****
return VEC_length (tree, SCOP_PARAMS (scop)) - 1;
}
! /* Scan EXPR and translate it to an inequality vector INEQ that will
! be inserted in the domain matrix. */
static void
! scan_tree_for_params (scop_p scop, tree expr, lambda_vector ineq, int k)
{
! switch (TREE_CODE (expr))
! {
! case MULT_EXPR:
! if (chrec_contains_symbols (TREE_OPERAND (expr, 0)))
! {
! gcc_assert (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST);
! k *= int_cst_value (TREE_OPERAND (expr, 1));
! scan_tree_for_params (scop, TREE_OPERAND (expr, 0), ineq, k);
! }
! else
! {
! gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == INTEGER_CST);
! k *= int_cst_value (TREE_OPERAND (expr, 0));
! scan_tree_for_params (scop, TREE_OPERAND (expr, 1), ineq, k);
! }
! break;
! case PLUS_EXPR:
! scan_tree_for_params (scop, TREE_OPERAND (expr, 0), ineq, k);
! scan_tree_for_params (scop, TREE_OPERAND (expr, 1), ineq, k);
! break;
! case MINUS_EXPR:
! scan_tree_for_params (scop, TREE_OPERAND (expr, 0), ineq, k);
! scan_tree_for_params (scop, TREE_OPERAND (expr, 1), ineq, -1 * k);
! break;
! case SSA_NAME:
! ineq[scop_nb_loops (scop) + param_index (expr, scop)] = k;
! break;
! case INTEGER_CST:
! ineq[scop_nb_loops (scop) + scop_nb_params (scop)] = int_cst_value (expr);
! break;
! case NOP_EXPR:
! case CONVERT_EXPR:
! case NON_LVALUE_EXPR:
! scan_tree_for_params (scop, TREE_OPERAND (expr, 0), ineq, k);
! break;
! default:
! break;
! }
}
! /* Record LOOP as occuring in SCOP. */
! static inline void
! scop_record_loop (scop_p scop, struct loop *loop)
{
unsigned i;
struct loop *l;
for (i = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), i, l); i++)
if (l == loop)
! return;
VEC_safe_push (loop_p, heap, SCOP_LOOP_NEST (scop), loop);
}
! /* Build the loop nest around basic block BB. */
static void
build_scop_loop_nests (scop_p scop)
--- 446,522 ----
return VEC_length (tree, SCOP_PARAMS (scop)) - 1;
}
! /* Build for BB the static schedule. */
static void
! build_graphite_bb (struct dom_walk_data *dw_data, basic_block bb)
{
! struct graphite_bb *gb;
! scop_p scop = (scop_p) dw_data->global_data;
! /* Scop's exit is not in the scop. */
! if (bb == SCOP_EXIT (scop)
! /* Every block in the scop dominates scop's exit. */
! || !dominated_by_p (CDI_DOMINATORS, SCOP_EXIT (scop), bb))
! return;
! /* Build the new representation for the basic block. */
! gb = XNEW (struct graphite_bb);
! GBB_BB (gb) = bb;
! GBB_SCOP (gb) = scop;
! /* Store the GRAPHITE representation of the current BB. */
! VEC_safe_push (graphite_bb_p, heap, scop->bbs, gb);
! }
! /* Gather the basic blocks belonging to the SCOP. */
! static void
! build_scop_bbs (scop_p scop)
! {
! struct dom_walk_data walk_data;
! memset (&walk_data, 0, sizeof (struct dom_walk_data));
!
! /* Iterate over all the basic blocks of the scop in their pseudo
! execution order, and associate to each bb a static schedule.
! (pseudo exec order = the branches of a condition are scheduled
! sequentially: the then clause comes before the else clause.) */
! walk_data.before_dom_children_before_stmts = build_graphite_bb;
!
! walk_data.global_data = scop;
! init_walk_dominator_tree (&walk_data);
! walk_dominator_tree (&walk_data, SCOP_ENTRY (scop));
! fini_walk_dominator_tree (&walk_data);
}
! /* Returns true when LOOP is in SCOP. */
! static bool
! loop_in_scop_p (struct loop *loop, scop_p scop)
{
unsigned i;
struct loop *l;
for (i = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), i, l); i++)
if (l == loop)
! return true;
!
! return false;
! }
!
! /* Record LOOP as occuring in SCOP. */
!
! static void
! scop_record_loop (scop_p scop, struct loop *loop)
! {
! if (loop_in_scop_p (loop, scop))
! return;
VEC_safe_push (loop_p, heap, SCOP_LOOP_NEST (scop), loop);
}
! /* Build the loop nests contained in SCOP. */
static void
build_scop_loop_nests (scop_p scop)
*************** build_scop_loop_nests (scop_p scop)
*** 497,563 ****
unsigned i;
graphite_bb_p gb;
- SCOP_LOOP_NEST (scop) = VEC_alloc (loop_p, heap, 3);
-
for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
! scop_record_loop (scop, GBB_BB (gb)->loop_father);
}
! /* Build the current domain matrix: the loops belonging to the current
! SCOP, and that vary for the execution of the current basic block. */
static void
! build_scop_domain (scop_p scop)
{
unsigned i;
! struct loop *loop;
! SCOP_DOMAIN (scop) = VEC_alloc (lambda_vector, heap, scop_dim_domain (scop));
! for (i = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), i, loop); i++)
{
! tree nb_iters = number_of_latch_executions (loop);
! lambda_vector ineq_low = lambda_vector_new (scop_dim_domain (scop));
! lambda_vector ineq_up = lambda_vector_new (scop_dim_domain (scop));
!
! if (chrec_contains_undetermined (nb_iters))
! continue;
!
! /* 0 <= loop_i */
! ineq_low[i] = 1;
! VEC_safe_push (lambda_vector, heap, SCOP_DOMAIN (scop), ineq_low);
!
! if (TREE_CODE (nb_iters) == INTEGER_CST)
! {
! int nbi = int_cst_value (nb_iters);
!
! /* loop_i <= nb_iters */
! ineq_up[i] = -1;
! ineq_up[scop_dim_domain (scop) - 1] = nbi;
! VEC_safe_push (lambda_vector, heap, SCOP_DOMAIN (scop), ineq_up);
! }
!
! /* Otherwise nb_iters contains parameters: scan the nb_iters
! expression and build its matrix representation. */
! else
! {
! nb_iters = instantiate_parameters (scop->entry->loop_father,
! nb_iters);
! scan_tree_for_params (scop, nb_iters, ineq_up, 1);
! VEC_safe_push (lambda_vector, heap, SCOP_DOMAIN (scop), ineq_up);
! }
}
}
- /* Record parameters occurring in the index IDX of a data access.
- Callback for for_each_index. */
-
struct irp_data
{
struct loop *loop;
scop_p scop;
};
static bool
idx_record_param (tree *var, void *dta)
{
--- 524,561 ----
unsigned i;
graphite_bb_p gb;
for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
! scop_record_loop (scop, GBB_LOOP (gb));
}
! /* Build for BB the static schedule. */
static void
! build_scop_canonical_schedules (scop_p scop)
{
unsigned i;
! graphite_bb_p gb;
! unsigned nb = scop_nb_loops (scop) + 1;
! SCOP_STATIC_SCHEDULE (scop) = lambda_vector_new (nb);
! for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
{
! SCOP_STATIC_SCHEDULE (scop)[scop_loop_index (scop, GBB_LOOP (gb))] += 1;
! GBB_STATIC_SCHEDULE (gb) = lambda_vector_new (nb);
! lambda_vector_copy (SCOP_STATIC_SCHEDULE (scop),
! GBB_STATIC_SCHEDULE (gb), nb);
}
}
struct irp_data
{
struct loop *loop;
scop_p scop;
};
+ /* Record VAR as a parameter of DTA->scop. */
+
static bool
idx_record_param (tree *var, void *dta)
{
*************** idx_record_param (tree *var, void *dta)
*** 575,580 ****
--- 573,581 ----
}
}
+ /* Record parameters occurring in an evolution function of a data
+ access, niter expression, etc. Callback for for_each_index. */
+
static bool
idx_record_params (tree base, tree *idx, void *dta)
{
*************** idx_record_params (tree base, tree *idx,
*** 585,600 ****
if (TREE_CODE (*idx) == SSA_NAME)
{
! tree scev = instantiate_parameters
! (data->scop->entry->loop_father,
! analyze_scalar_evolution (data->loop, *idx));
for_each_scev_op (&scev, idx_record_param, dta);
}
return true;
}
/* Initialize the access matrix in the data reference REF with respect
to the loop nesting LOOP_NEST. Return true when the operation
succeeded. */
--- 586,986 ----
if (TREE_CODE (*idx) == SSA_NAME)
{
! tree scev;
! scop_p scop = data->scop;
! struct loop *loop = data->loop;
! struct loop *floop = SCOP_ENTRY (scop)->loop_father;
+ scev = analyze_scalar_evolution (loop, *idx);
+ scev = instantiate_parameters (floop, scev);
for_each_scev_op (&scev, idx_record_param, dta);
}
return true;
}
+ /* Helper function for walking in dominance order basic blocks. Find
+ parameters with respect to SCOP in memory access functions used in
+ BB. DW_DATA contains the context and the results for extract
+ parameters information. */
+
+ static void
+ find_params_in_bb (struct dom_walk_data *dw_data, basic_block bb)
+ {
+ unsigned i;
+ data_reference_p dr;
+ VEC (data_reference_p, heap) *drs;
+ block_stmt_iterator bsi;
+ scop_p scop = (scop_p) dw_data->global_data;
+
+ /* Find the parameters used in the memory access functions. */
+ drs = VEC_alloc (data_reference_p, heap, 5);
+ for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ find_data_references_in_stmt (bsi_stmt (bsi), &drs);
+
+ for (i = 0; VEC_iterate (data_reference_p, drs, i, dr); i++)
+ {
+ struct irp_data irp;
+
+ irp.loop = bb->loop_father;
+ irp.scop = scop;
+ for_each_index (&dr->ref, idx_record_params, &irp);
+ }
+
+ VEC_free (data_reference_p, heap, drs);
+ }
+
+ /* Initialize Cloog's parameter names from the names used in GIMPLE. */
+
+ static void
+ initialize_cloog_names (scop_p scop)
+ {
+ unsigned i, nb_params = VEC_length (tree, SCOP_PARAMS (scop));
+ char **params = XNEWVEC (char *, nb_params);
+ tree p;
+
+ for (i = 0; VEC_iterate (tree, SCOP_PARAMS (scop), i, p); i++)
+ {
+ const char *name = get_name (SSA_NAME_VAR (p));
+
+ if (name)
+ {
+ params[i] = XNEWVEC (char, strlen (name) + 12);
+ sprintf (params[i], "%s_%d", name, SSA_NAME_VERSION (p));
+ }
+ else
+ {
+ params[i] = XNEWVEC (char, 12);
+ sprintf (params[i], "T_%d", SSA_NAME_VERSION (p));
+ }
+ }
+
+ SCOP_PROG (scop)->names->nb_parameters = nb_params;
+ SCOP_PROG (scop)->names->parameters = params;
+ }
+
+ /* Record the parameters used in the SCOP. A variable is a parameter
+ in a scop if it does not vary during the execution of that scop. */
+
+ static void
+ find_scop_parameters (scop_p scop)
+ {
+ unsigned i;
+ struct dom_walk_data walk_data;
+ struct loop *loop;
+
+ /* Find the parameters used in the loop bounds. */
+ for (i = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), i, loop); i++)
+ {
+ tree nb_iters = number_of_latch_executions (loop);
+
+ if (chrec_contains_symbols (nb_iters))
+ {
+ struct irp_data irp;
+
+ irp.loop = loop;
+ irp.scop = scop;
+ for_each_scev_op (&nb_iters, idx_record_param, &irp);
+ }
+ }
+
+ /* Find the parameters used in data accesses. */
+ memset (&walk_data, 0, sizeof (struct dom_walk_data));
+ walk_data.before_dom_children_before_stmts = find_params_in_bb;
+ walk_data.global_data = scop;
+ init_walk_dominator_tree (&walk_data);
+ walk_dominator_tree (&walk_data, SCOP_ENTRY (scop));
+ fini_walk_dominator_tree (&walk_data);
+
+ initialize_cloog_names (scop);
+ }
+
+ /* Returns the number of parameters for SCOP. */
+
+ static inline unsigned
+ nb_params_in_scop (scop_p scop)
+ {
+ return VEC_length (tree, SCOP_PARAMS (scop));
+ }
+
+ /* Build the context constraints for SCOP: constraints and relations
+ on parameters. */
+
+ static void
+ build_scop_context (scop_p scop)
+ {
+ unsigned nb_params = nb_params_in_scop (scop);
+ CloogMatrix *matrix = cloog_matrix_alloc (1, nb_params + 2);
+
+ cloog_matrix_print (stderr, matrix);
+
+ value_init (matrix->p[0][0]);
+ value_set_si (matrix->p[0][0], 1);
+
+ value_init (matrix->p[0][nb_params + 1]);
+ value_set_si (matrix->p[0][nb_params + 1], -1);
+
+ cloog_matrix_print (stderr, matrix);
+
+ SCOP_PROG (scop)->context = cloog_domain_matrix2domain (matrix);
+ }
+
+ /* Scan EXPR and translate it to an inequality vector INEQ that will
+ be inserted in the domain matrix. */
+
+ static void
+ scan_tree_for_params (scop_p scop, tree expr, CloogMatrix *cstr, int row,
+ Value k)
+ {
+ int col;
+
+ switch (TREE_CODE (expr))
+ {
+ case MULT_EXPR:
+ if (chrec_contains_symbols (TREE_OPERAND (expr, 0)))
+ {
+ Value val;
+
+ gcc_assert (host_integerp (TREE_OPERAND (expr, 1), 1));
+
+ value_init (val);
+ value_set_si (val, int_cst_value (TREE_OPERAND (expr, 1)));
+ value_multiply (k, k, val);
+ value_clear (val);
+ scan_tree_for_params (scop, TREE_OPERAND (expr, 0), cstr, row, k);
+ }
+ else
+ {
+ Value val;
+
+ gcc_assert (host_integerp (TREE_OPERAND (expr, 0), 1));
+
+ value_init (val);
+ value_set_si (val, int_cst_value (TREE_OPERAND (expr, 0)));
+ value_multiply (k, k, val);
+ value_clear (val);
+ scan_tree_for_params (scop, TREE_OPERAND (expr, 1), cstr, row, k);
+ }
+ break;
+
+ case PLUS_EXPR:
+ scan_tree_for_params (scop, TREE_OPERAND (expr, 0), cstr, row, k);
+ scan_tree_for_params (scop, TREE_OPERAND (expr, 1), cstr, row, k);
+ break;
+
+ case MINUS_EXPR:
+ scan_tree_for_params (scop, TREE_OPERAND (expr, 0), cstr, row, k);
+ value_oppose (k, k);
+ scan_tree_for_params (scop, TREE_OPERAND (expr, 1), cstr, row, k);
+ break;
+
+ case SSA_NAME:
+ col = scop_nb_loops (scop) + param_index (expr, scop);
+ value_init (cstr->p[row][col]);
+ value_assign (cstr->p[row][col], k);
+ break;
+
+ case INTEGER_CST:
+ col = scop_nb_loops (scop) + scop_nb_params (scop);
+ value_init (cstr->p[row][col]);
+ value_set_si (cstr->p[row][col], int_cst_value (expr));
+ break;
+
+ case NOP_EXPR:
+ case CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
+ scan_tree_for_params (scop, TREE_OPERAND (expr, 0), cstr, row, k);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Returns the first loop in SCOP, returns NULL if there is no loop in
+ SCOP. */
+
+ static struct loop *
+ first_loop_in_scop (scop_p scop)
+ {
+ struct loop *loop = SCOP_ENTRY (scop)->loop_father->inner;
+
+ if (loop == NULL)
+ return NULL;
+
+ while (loop->next && !loop_in_scop_p (loop, scop))
+ loop = loop->next;
+
+ if (loop_in_scop_p (loop, scop))
+ return loop;
+
+ return NULL;
+ }
+
+ /* Converts LOOP in SCOP to cloog's format. NB_ITERATORS is the
+ number of loops surrounding LOOP in SCOP. OUTER_CSTR gives the
+ constraints matrix for the surrounding loops. */
+
+ static CloogLoop *
+ setup_cloog_loop (scop_p scop, struct loop *loop, CloogMatrix *outer_cstr,
+ int nb_iterators)
+ {
+ unsigned i, j, row;
+ unsigned nb_rows = outer_cstr->NbRows + 1;
+ unsigned nb_cols = outer_cstr->NbColumns;
+ CloogMatrix *cstr;
+ CloogStatement *statement;
+ CloogLoop *res = cloog_loop_malloc ();
+ tree nb_iters = number_of_latch_executions (loop);
+
+ if (TREE_CODE (nb_iters) == INTEGER_CST
+ || !chrec_contains_undetermined (nb_iters))
+ nb_rows++;
+
+ cstr = cloog_matrix_alloc (nb_rows, nb_cols);
+
+ for (i = 0; i < outer_cstr->NbRows; i++)
+ for (j = 0; j < outer_cstr->NbColumns; j++)
+ {
+ value_init (cstr->p[i][j]);
+ value_assign (cstr->p[i][j], outer_cstr->p[i][j]);
+ }
+
+ /* 0 <= loop_i */
+ row = outer_cstr->NbRows;
+ value_init (cstr->p[row][row]);
+ value_set_si (cstr->p[row][row], 1);
+
+ /* loop_i <= nb_iters */
+ row++;
+
+ if (TREE_CODE (nb_iters) == INTEGER_CST)
+ {
+ value_init (cstr->p[row][row]);
+ value_set_si (cstr->p[row][row], -1);
+
+ value_init (cstr->p[row][scop_dim_domain (scop) - 1]);
+ value_set_si (cstr->p[row][scop_dim_domain (scop) - 1],
+ int_cst_value (nb_iters));
+ }
+ else if (!chrec_contains_undetermined (nb_iters))
+ {
+ /* Otherwise nb_iters contains parameters: scan the nb_iters
+ expression and build its matrix representation. */
+ Value one;
+
+ nb_iters = instantiate_parameters (SCOP_ENTRY (scop)->loop_father,
+ nb_iters);
+ value_init (one);
+ value_set_si (one, 1);
+ scan_tree_for_params (scop, nb_iters, cstr, row, one);
+ value_clear (one);
+ }
+
+ res->domain = cloog_domain_matrix2domain (cstr);
+
+ if (loop->inner && loop_in_scop_p (loop->inner, scop))
+ res->inner = setup_cloog_loop (scop, loop->inner, cstr, nb_iterators + 1);
+
+ if (loop->next && loop_in_scop_p (loop->next, scop))
+ res->next = setup_cloog_loop (scop, loop->next, outer_cstr, nb_iterators);
+
+ {
+ static int number = 0;
+ statement = cloog_statement_alloc (number++);
+ }
+ res->block = cloog_block_alloc (statement, NULL, 0, NULL, nb_iterators + 1);
+
+ return res;
+ }
+
+ /* Build the current domain matrix: the loops belonging to the current
+ SCOP, and that vary for the execution of the current basic block.
+ Returns false if there is no loop in SCOP. */
+
+ static bool
+ build_scop_iteration_domain (scop_p scop)
+ {
+ struct loop *loop = first_loop_in_scop (scop);
+ CloogMatrix *outer_cstr;
+
+ if (loop == NULL)
+ return false;
+
+ outer_cstr = cloog_matrix_alloc (0, scop_dim_domain (scop));
+ SCOP_PROG (scop)->loop = setup_cloog_loop (scop, loop, outer_cstr, 0);
+ return true;
+ }
+
+ /* Initializes an equation CY of the access matrix using the
+ information for a subscript from ACCESS_FUN, relatively to the loop
+ indexes from LOOP_NEST and parameter indexes from PARAMS. Returns
+ true when the operation succeeded. */
+
+ static bool
+ build_access_matrix_with_af (tree access_fun, lambda_vector cy,
+ scop_p scop)
+ {
+ VEC (loop_p, heap) *loop_nest = SCOP_LOOP_NEST (scop);
+ VEC (tree, heap) *params = SCOP_PARAMS (scop);
+
+ switch (TREE_CODE (access_fun))
+ {
+ case POLYNOMIAL_CHREC:
+ {
+ tree left = CHREC_LEFT (access_fun);
+ tree right = CHREC_RIGHT (access_fun);
+ int var = CHREC_VARIABLE (access_fun);
+ unsigned var_idx;
+ struct loop *loopi;
+
+ if (TREE_CODE (right) != INTEGER_CST)
+ return false;
+
+ /* Find the index of the current variable VAR_IDX in the
+ LOOP_NEST array. */
+ for (var_idx = 0; VEC_iterate (loop_p, loop_nest, var_idx, loopi);
+ var_idx++)
+ if (loopi->num == var)
+ break;
+
+ gcc_assert (loopi && loopi->num == var);
+
+ cy[var_idx] = int_cst_value (right);
+
+ switch (TREE_CODE (left))
+ {
+ case POLYNOMIAL_CHREC:
+ return build_access_matrix_with_af (left, cy, scop);
+
+ case INTEGER_CST:
+ {
+ /* Constant part. */
+ unsigned nb_loops = VEC_length (loop_p, loop_nest);
+ unsigned nb_params = VEC_length (tree, params);
+
+ cy[nb_loops + nb_params] = int_cst_value (left);
+ return true;
+ }
+
+ default:
+ return false;
+ }
+ }
+ case INTEGER_CST:
+ {
+ /* Constant part. */
+ unsigned nb_loops = VEC_length (loop_p, loop_nest);
+ unsigned nb_params = VEC_length (tree, params);
+ cy[nb_loops + nb_params] = int_cst_value (access_fun);
+ return true;
+ }
+
+ default:
+ return false;
+ }
+ }
+
/* Initialize the access matrix in the data reference REF with respect
to the loop nesting LOOP_NEST. Return true when the operation
succeeded. */
*************** idx_record_params (tree base, tree *idx,
*** 602,620 ****
static bool
build_access_matrix (data_reference_p ref, graphite_bb_p gb)
{
! unsigned i;
DR_SCOP (ref) = GBB_SCOP (gb);
! DR_ACCESS_MATRIX (ref) = VEC_alloc (lambda_vector, heap,
! DR_NUM_DIMENSIONS (ref));
! for (i = 0; i < DR_NUM_DIMENSIONS (ref); i++)
{
lambda_vector v = lambda_vector_new (gbb_dim_domain (gb));
! bool res = build_access_matrix_with_af (DR_ACCESS_FN (ref, i), v,
! SCOP_LOOP_NEST (GBB_SCOP (gb)),
! SCOP_PARAMS (GBB_SCOP (gb)));
! if (!res)
return false;
VEC_safe_push (lambda_vector, heap, DR_ACCESS_MATRIX (ref), v);
--- 988,1005 ----
static bool
build_access_matrix (data_reference_p ref, graphite_bb_p gb)
{
! unsigned i, ndim = DR_NUM_DIMENSIONS (ref);
DR_SCOP (ref) = GBB_SCOP (gb);
! DR_ACCESS_MATRIX (ref) = VEC_alloc (lambda_vector, heap, ndim);
! for (i = 0; i < ndim; i++)
{
lambda_vector v = lambda_vector_new (gbb_dim_domain (gb));
! scop_p scop = GBB_SCOP (gb);
! tree af = DR_ACCESS_FN (ref, i);
!
! if (!build_access_matrix_with_af (af, v, scop))
return false;
VEC_safe_push (lambda_vector, heap, DR_ACCESS_MATRIX (ref), v);
*************** build_scop_data_accesses (scop_p scop)
*** 650,795 ****
}
}
! /* Build for BB the static schedule. */
! static void
! build_scop_canonical_schedules (scop_p scop)
{
! unsigned i;
! graphite_bb_p gb;
! SCOP_STATIC_SCHEDULE (scop) = lambda_vector_new (scop_nb_loops (scop) + 1);
! for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
! {
! basic_block bb = GBB_BB (gb);
! SCOP_STATIC_SCHEDULE (scop)[scop_loop_index (scop, bb->loop_father)] += 1;
! GBB_STATIC_SCHEDULE (gb) = lambda_vector_new (scop_nb_loops (scop));
! lambda_vector_copy (SCOP_STATIC_SCHEDULE (scop), GBB_STATIC_SCHEDULE (gb),
! scop_nb_loops (scop) + 1);
}
}
! /* Build for BB the static schedule. */
static void
! build_graphite_bb (struct dom_walk_data *dw_data, basic_block bb)
{
! struct graphite_bb *gb;
! scop_p scop = (scop_p) dw_data->global_data;
!
! /* Scop's exit is not in the scop. */
! if (bb == scop->exit
! /* Every block in the scop dominates scop's exit. */
! || !dominated_by_p (CDI_DOMINATORS, scop->exit, bb))
! return;
!
! /* Build the new representation for the basic block. */
! gb = XNEW (struct graphite_bb);
! GBB_BB (gb) = bb;
! GBB_SCOP (gb) = scop;
!
! /* Store the GRAPHITE representation of the current BB. */
! VEC_safe_push (graphite_bb_p, heap, scop->bbs, gb);
}
- static void
- build_scop_bbs (scop_p scop)
- {
- struct dom_walk_data walk_data;
! memset (&walk_data, 0, sizeof (struct dom_walk_data));
! /* Iterate over all the basic blocks of the scop in their pseudo
! execution order, and associate to each bb a static schedule.
! (pseudo exec order = the branches of a condition are scheduled
! sequentially: the then clause comes before the else clause.) */
! walk_data.before_dom_children_before_stmts = build_graphite_bb;
!
! SCOP_BBS (scop) = VEC_alloc (graphite_bb_p, heap, 5);
! walk_data.global_data = scop;
! init_walk_dominator_tree (&walk_data);
! walk_dominator_tree (&walk_data, scop->entry);
! fini_walk_dominator_tree (&walk_data);
! }
!
! static void
! find_params_in_bb (struct dom_walk_data *dw_data, basic_block bb)
{
! unsigned i;
! data_reference_p dr;
! VEC (data_reference_p, heap) *drs;
! block_stmt_iterator bsi;
! scop_p scop = (scop_p) dw_data->global_data;
! /* Find the parameters used in the memory access functions. */
! drs = VEC_alloc (data_reference_p, heap, 5);
! for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
! find_data_references_in_stmt (bsi_stmt (bsi), &drs);
!
! for (i = 0; VEC_iterate (data_reference_p, drs, i, dr); i++)
{
! struct irp_data irp;
!
! irp.loop = bb->loop_father;
! irp.scop = scop;
! for_each_index (&dr->ref, idx_record_params, &irp);
! }
!
! VEC_free (data_reference_p, heap, drs);
! }
!
! /* Record the parameters used in the SCOP. A variable is a parameter
! in a scop if it does not vary during the execution of that scop. */
! static void
! build_scop_params (scop_p scop)
! {
! unsigned i;
! struct dom_walk_data walk_data;
! struct loop *loop;
! SCOP_PARAMS (scop) = VEC_alloc (tree, heap, 3);
! /* Find the parameters used in the loop bounds. */
! for (i = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), i, loop); i++)
! {
! tree nb_iters = number_of_latch_executions (loop);
!
! if (chrec_contains_symbols (nb_iters))
! {
! struct irp_data irp;
!
! irp.loop = loop;
! irp.scop = scop;
! for_each_scev_op (&nb_iters, idx_record_param, &irp);
! }
}
! /* Find the parameters used in data accesses. */
! memset (&walk_data, 0, sizeof (struct dom_walk_data));
! walk_data.before_dom_children_before_stmts = find_params_in_bb;
! walk_data.global_data = scop;
! init_walk_dominator_tree (&walk_data);
! walk_dominator_tree (&walk_data, scop->entry);
! fini_walk_dominator_tree (&walk_data);
}
! /* Find the right transform for the SCOP. */
! static void
! find_transform (scop_p scop ATTRIBUTE_UNUSED)
{
!
! }
!
! /* GIMPLE Loop Generator: generates loops in GIMPLE form for SCOP. */
! static void
! gloog (scop_p scop ATTRIBUTE_UNUSED)
! {
}
--- 1035,1119 ----
}
}
! /* Find the right transform for the SCOP, and return a Cloog AST
! representing the new form of the program. */
! static struct clast_stmt *
! find_transform (scop_p scop)
{
! struct clast_stmt *stmt;
! CloogOptions *options = cloog_options_malloc ();
! CloogProgram *prog = SCOP_PROG (scop);
! prog = cloog_program_generate (prog, options);
! stmt = cloog_clast_create (prog, options);
! pprint (stderr, stmt, 0, options);
! cloog_program_dump_cloog (stderr, prog);
! if (dump_file && (dump_flags & TDF_DETAILS))
! {
! pprint (dump_file, stmt, 0, options);
! cloog_program_dump_cloog (dump_file, prog);
}
+
+ return stmt;
}
! /* GIMPLE Loop Generator: generates loops from STMT in GIMPLE form for
! the given SCOP. */
static void
! gloog (scop_p scop ATTRIBUTE_UNUSED, struct clast_stmt *stmt)
{
! cloog_clast_free (stmt);
}
! /* Pretty print a scop in DOT format. */
! static void
! dot_scop_1 (FILE *file, scop_p scop)
{
! edge e;
! edge_iterator ei;
! basic_block bb;
! basic_block entry = SCOP_ENTRY (scop);
! basic_block exit = SCOP_EXIT (scop);
!
! fprintf (file, "digraph SCoP_%d_%d {\n", entry->index,
! exit->index);
! FOR_ALL_BB (bb)
{
! if (bb == entry)
! fprintf (file, "%d [shape=triangle];\n", bb->index);
! if (bb == exit)
! fprintf (file, "%d [shape=box];\n", bb->index);
! if (bb_in_scop_p (bb, scop))
! fprintf (file, "%d [color=red];\n", bb->index);
! FOR_EACH_EDGE (e, ei, bb->succs)
! fprintf (file, "%d -> %d;\n", bb->index, e->dest->index);
}
! fputs ("}\n\n", file);
}
! /* Display SCOP using dotty. */
! void
! dot_scop (scop_p scop)
{
! FILE *stream = fopen ("/tmp/foo.dot", "w");
! gcc_assert (stream != NULL);
! dot_scop_1 (stream, scop);
! fclose (stream);
! system ("dotty /tmp/foo.dot");
}
*************** graphite_transform_loops (void)
*** 802,807 ****
--- 1126,1134 ----
scop_p scop;
current_scops = VEC_alloc (scop_p, heap, 3);
+ calculate_dominance_info (CDI_POST_DOMINATORS);
+ calculate_dominance_info (CDI_DOMINATORS);
+
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Graphite loop transformations \n");
*************** graphite_transform_loops (void)
*** 812,823 ****
build_scop_bbs (scop);
build_scop_loop_nests (scop);
build_scop_canonical_schedules (scop);
! build_scop_params (scop);
! build_scop_domain (scop);
! build_scop_data_accesses (scop);
! find_transform (scop);
! gloog (scop);
}
if (dump_file && (dump_flags & TDF_DETAILS))
--- 1139,1152 ----
build_scop_bbs (scop);
build_scop_loop_nests (scop);
build_scop_canonical_schedules (scop);
! find_scop_parameters (scop);
! build_scop_context (scop);
! if (!build_scop_iteration_domain (scop))
! continue;
!
! build_scop_data_accesses (scop);
! gloog (scop, find_transform (scop));
}
if (dump_file && (dump_flags & TDF_DETAILS))
Index: graphite.h
===================================================================
*** graphite.h (revision 123814)
--- graphite.h (working copy)
***************
*** 1,5 ****
/* Gimple Represented as Polyhedra.
! Copyright (C) 2006 Free Software Foundation, Inc.
Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
This file is part of GCC.
--- 1,5 ----
/* Gimple Represented as Polyhedra.
! Copyright (C) 2006, 2007 Free Software Foundation, Inc.
Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
This file is part of GCC.
*************** struct graphite_bb
*** 38,43 ****
--- 38,44 ----
};
#define GBB_BB(GBB) GBB->bb
+ #define GBB_LOOP(GBB) GBB->bb->loop_father
#define GBB_SCOP(GBB) GBB->scop
#define GBB_STATIC_SCHEDULE(GBB) GBB->static_schedule
#define GBB_DATA_REFS(GBB) GBB->data_refs
*************** struct scop
*** 63,69 ****
--- 64,74 ----
/* Loops contained in the scop. */
VEC (loop_p, heap) *loop_nest;
+ /* Constraints on loop iterations. */
VEC (lambda_vector, heap) *iteration_domain;
+
+ /* Cloog representation of this scop. */
+ CloogProgram *program;
};
#define SCOP_BBS(S) S->bbs
*************** struct scop
*** 72,83 ****
#define SCOP_STATIC_SCHEDULE(S) S->static_schedule
#define SCOP_LOOP_NEST(S) S->loop_nest
#define SCOP_PARAMS(S) S->params
-
#define SCOP_DOMAIN(S) S->iteration_domain
extern void debug_scop (scop_p, int);
extern void debug_scops (int);
extern void print_graphite_bb (FILE *, graphite_bb_p, int, int);
/* Return the number of parameters used in SCOP. */
--- 77,89 ----
#define SCOP_STATIC_SCHEDULE(S) S->static_schedule
#define SCOP_LOOP_NEST(S) S->loop_nest
#define SCOP_PARAMS(S) S->params
#define SCOP_DOMAIN(S) S->iteration_domain
+ #define SCOP_PROG(S) S->program
extern void debug_scop (scop_p, int);
extern void debug_scops (int);
extern void print_graphite_bb (FILE *, graphite_bb_p, int, int);
+ extern void dot_scop (scop_p);
/* Return the number of parameters used in SCOP. */