This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[graphite] first part of the polyhedral representation


Hi,

Here is the patch, that I will commit to the graphite branch.
The patch reworks most of the code that was in graphite.[ch].
The detection of the scops remains the same, and now we
detect parameters of the scop and build in function of these
parameters the iteration domains.  The access matrices are
not yet built, but shouldn't be difficult now.  I thought that I
have written some code for that, but I'm seeing that the
toplevel is disabled just now.  I'll rework on that part.

The notion of parameter for a scop is something
for which I didn't get a good definition.
Informally, a scop param is a declaration that
cannot be instantiated and that is defined before
the scop, ie. in a bb that precedes the entry of the
scop.  Now for avoiding to have too many
parameters I had to change the instantiate_parameters
function to walk further than stopping at the first variable
outside some loop.  I didn't liked the way I implemented
that part, and this will surely change, as I would like to
create a new instantiate function, for not disturbing the
other passes by this new behavior.

Sebastian
	* tree-scalar-evolution.c (instantiate_parameters_1): Don't stop
	at the first declaration outside the varying loop, instantiate as
	far as possible.
	* tree-chrec.c (for_each_scev_op): New.
	* tree-chrec.h (for_each_scev_op): Declared.
	* tree-ssa-loop.c (pass_graphite_trans): Don't dump the function.
	* tree-data-ref.c (get_references_in_stmt, 
	find_data_references_in_stmt): New, from trunk.
	(find_data_references_in_loop): Use get_references_in_stmt
	and find_data_references_in_loop, modified as in trunk.
	(build_access_matrix_with_af): New.
	* tree-data-ref.h (data_reference): Add a field access_matrix.
	(data_ref_loc): New, as in trunk.
	* graphite.c (print_graphite_bb, bb_in_scop_p, stmt_in_scop_p,
	invariant_in_scop_p, param_index, scan_tree_for_params, 
	scop_loop_index, build_scop_loop_nests, build_scop_domain, irp_data,
	idx_record_param, idx_record_params, build_access_matrix, 
	build_scop_data_accesses, build_scop_canonical_schedules, 
	build_graphite_bb, build_scop_bbs, find_params_in_bb, 
	build_scop_params): New.
	* graphite.h (graphite_bb): New.
	(scop): Add fields static_schedule, params, loop_nest,
	iteration_domain.
	* lambda.h: Declare vecs of lambda_matrix.
	* tree-flow.h (print_loop_ir_bb): Declared.
	* tree-cfg.c (print_loop_ir_bb): New.
	(print_loop): Use print_loop_ir_bb.

Index: tree-scalar-evolution.c
===================================================================
--- tree-scalar-evolution.c	(revision 118003)
+++ tree-scalar-evolution.c	(working copy)
@@ -2180,7 +2180,30 @@ instantiate_parameters_1 (struct loop *l
 	 is defined outside of the loop, we may just leave it in symbolic
 	 form, otherwise we need to admit that we do not know its behavior
 	 inside the loop.  */
-      res = !flow_bb_inside_loop_p (loop, def_bb) ? chrec : chrec_dont_know;
+      if (!flow_bb_inside_loop_p (loop, def_bb))
+	res = chrec;
+      else
+	{
+	  /* res = chrec_dont_know; */
+	  tree def = SSA_NAME_DEF_STMT (chrec);
+
+	  /* Instantiate as much as possible until ending on a phi
+	     node of the same loop, in which case it means that the
+	     definition is varying in that loop.  */
+	  switch (TREE_CODE (def))
+	    {
+	    case MODIFY_EXPR:
+	      res = instantiate_parameters_1 (loop, TREE_OPERAND (def, 1),
+					      flags, cache, size_expr);
+	      break;
+
+	    case PHI_NODE:
+	    default:
+	      res = chrec_dont_know;
+	      break;
+	    }
+	}
+
       set_instantiated_value (cache, chrec, res);
 
       /* To make things even more complicated, instantiate_parameters_1
Index: tree-chrec.c
===================================================================
--- tree-chrec.c	(revision 118003)
+++ tree-chrec.c	(working copy)
@@ -1395,3 +1395,23 @@ scev_direction (tree chrec)
   else
     return EV_DIR_GROWS;
 }
+
+/* Iterates over all the components of SCEV, and calls CBCK.  */
+
+void
+for_each_scev_op (tree *scev, bool (*cbck) (tree *, void *), void *data)
+{
+  switch (TREE_CODE_LENGTH (TREE_CODE (*scev)))
+    {
+    case 2:
+      for_each_scev_op (&TREE_OPERAND (*scev, 1), cbck, data);
+
+    case 1:
+      for_each_scev_op (&TREE_OPERAND (*scev, 0), cbck, data);
+
+    default:
+      cbck (scev, data);
+      break;
+    }
+}
+
Index: tree-chrec.h
===================================================================
--- tree-chrec.h	(revision 118003)
+++ tree-chrec.h	(working copy)
@@ -79,6 +79,7 @@ extern tree evolution_part_in_loop_num (
 extern tree hide_evolution_in_other_loops_than_loop (tree, unsigned);
 extern tree reset_evolution_in_loop (unsigned, tree, tree);
 extern tree chrec_merge (tree, tree);
+extern void for_each_scev_op (tree *, bool (*) (tree *, void *), void *);
 
 /* Observers.  */
 extern bool eq_evolutions_p (tree, tree);
Index: tree-ssa-loop.c
===================================================================
--- tree-ssa-loop.c	(revision 118003)
+++ tree-ssa-loop.c	(working copy)
@@ -282,7 +282,7 @@ struct tree_opt_pass pass_graphite_trans
   0,					/* properties_provided */
   0,					/* properties_destroyed */
   0,					/* todo_flags_start */
-  TODO_dump_func | TODO_verify_loops,	/* todo_flags_finish */
+  TODO_verify_loops,			/* todo_flags_finish */
   0				        /* letter */	
 };
 
Index: tree-data-ref.c
===================================================================
--- tree-data-ref.c	(revision 118003)
+++ tree-data-ref.c	(working copy)
@@ -4060,12 +4060,109 @@ compute_all_dependences (VEC (data_refer
       }
 }
 
+
+/* Stores the locations of memory references in STMT to REFERENCES.  Returns
+   true if STMT clobbers memory, false otherwise.  */
+ 
+bool
+get_references_in_stmt (tree stmt, VEC (data_ref_loc, heap) **references)
+{
+  bool clobbers_memory = false;
+  data_ref_loc *ref;
+  tree *op0, *op1, args, call;
+ 
+  *references = NULL;
+ 
+  /* ASM_EXPR and CALL_EXPR may embed arbitrary side effects.
+     Calls have side-effects, except those to const or pure
+     functions.  */
+  call = get_call_expr_in (stmt);
+  if ((call
+       && !(call_expr_flags (call) & (ECF_CONST | ECF_PURE)))
+      || (TREE_CODE (stmt) == ASM_EXPR
+ 	  && ASM_VOLATILE_P (stmt)))
+    clobbers_memory = true;
+ 
+  if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+    return clobbers_memory;
+ 
+  if (TREE_CODE (stmt) ==  MODIFY_EXPR)
+    {
+      op0 = &TREE_OPERAND (stmt, 0);
+      op1 = &TREE_OPERAND (stmt, 1);
+ 		
+      if (DECL_P (*op1)
+ 	  || REFERENCE_CLASS_P (*op1))
+ 	{
+ 	  ref = VEC_safe_push (data_ref_loc, heap, *references, NULL);
+ 	  ref->pos = op1;
+ 	  ref->is_read = true;
+ 	}
+ 
+      if (DECL_P (*op0)
+ 	  || REFERENCE_CLASS_P (*op0))
+ 	{
+ 	  ref = VEC_safe_push (data_ref_loc, heap, *references, NULL);
+ 	  ref->pos = op0;
+ 	  ref->is_read = false;
+ 	}
+    }
+ 
+  if (call)
+    {
+      for (args = TREE_OPERAND (call, 1); args; args = TREE_CHAIN (args))
+ 	{
+ 	  op0 = &TREE_VALUE (args);
+ 	  if (DECL_P (*op0)
+ 	      || REFERENCE_CLASS_P (*op0))
+ 	    {
+ 	      ref = VEC_safe_push (data_ref_loc, heap, *references, NULL);
+ 	      ref->pos = op0;
+ 	      ref->is_read = true;
+ 	    }
+ 	}
+    }
+ 
+  return clobbers_memory;
+}
+ 
+/* Stores the data references in STMT to DATAREFS.  If there is an unanalyzable
+   reference, returns false, otherwise returns true.  */
+ 
+bool
+find_data_references_in_stmt (tree stmt,
+ 			      VEC (data_reference_p, heap) **datarefs)
+{
+  unsigned i;
+  VEC (data_ref_loc, heap) *references;
+  data_ref_loc *ref;
+  bool ret = true;
+  data_reference_p dr;
+ 
+  if (get_references_in_stmt (stmt, &references))
+    {
+      VEC_free (data_ref_loc, heap, references);
+      return false;
+    }
+ 
+  for (i = 0; VEC_iterate (data_ref_loc, references, i, ref); i++)
+    {
+      dr = create_data_ref (*ref->pos, stmt, ref->is_read);
+      if (dr)
+ 	VEC_safe_push (data_reference_p, heap, *datarefs, dr);
+      else
+ 	{
+ 	  ret = false;
+ 	  break;
+ 	}
+    }
+  VEC_free (data_ref_loc, heap, references);
+  return ret;
+}
+
 /* 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.  */
+   difficult case, returns NULL_TREE otherwise.  */
 
 tree 
 find_data_references_in_loop (struct loop *loop,
@@ -4074,129 +4171,129 @@ find_data_references_in_loop (struct loo
   basic_block bb, *bbs;
   unsigned int i;
   block_stmt_iterator bsi;
-  struct data_reference *dr;
 
   bbs = get_loop_body (loop);
+  loop->parallel_p = true;
 
   for (i = 0; i < loop->num_nodes; i++)
     {
       bb = bbs[i];
 
       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-        {
+	{
 	  tree stmt = bsi_stmt (bsi);
 
-	  /* ASM_EXPR and CALL_EXPR may embed arbitrary side effects.
-	     Calls have side-effects, except those to const or pure
-	     functions.  */
-	  if ((TREE_CODE (stmt) == CALL_EXPR
-	       && !(call_expr_flags (stmt) & (ECF_CONST | ECF_PURE)))
-	      || (TREE_CODE (stmt) == ASM_EXPR
-		  && ASM_VOLATILE_P (stmt)))
-	    goto insert_dont_know_node;
-
-	  if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
-	    continue;
-
-	  switch (TREE_CODE (stmt))
+	  if (!find_data_references_in_stmt (stmt, datarefs))
 	    {
-	    case MODIFY_EXPR:
-	      {
-		bool one_inserted = false;
-		tree opnd0 = TREE_OPERAND (stmt, 0);
-		tree opnd1 = TREE_OPERAND (stmt, 1);
-		
-		if (TREE_CODE (opnd0) == ARRAY_REF 
-		    || TREE_CODE (opnd0) == INDIRECT_REF
-                    || TREE_CODE (opnd0) == COMPONENT_REF)
-		  {
-		    dr = create_data_ref (opnd0, stmt, false);
-		    if (dr) 
-		      {
-			VEC_safe_push (data_reference_p, heap, *datarefs, dr);
-			one_inserted = true;
-		      }
-		  }
-
-		if (TREE_CODE (opnd1) == ARRAY_REF 
-		    || TREE_CODE (opnd1) == INDIRECT_REF
-		    || TREE_CODE (opnd1) == COMPONENT_REF)
-		  {
-		    dr = create_data_ref (opnd1, stmt, true);
-		    if (dr) 
-		      {
-			VEC_safe_push (data_reference_p, heap, *datarefs, dr);
-			one_inserted = true;
-		      }
-		  }
+	      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;
+	      loop->parallel_p = false;
+	      VEC_safe_push (data_reference_p, heap, *datarefs, res);
 
-		if (!one_inserted)
-		  goto insert_dont_know_node;
+	      free (bbs);
+	      return chrec_dont_know;
+	    }
 
-		break;
-	      }
+	  /* When there are no defs in the loop, the loop is parallel.  */
+	  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
+	    loop->parallel_p = false;
+	}
+    }
+  free (bbs);
 
-	    case CALL_EXPR:
-	      {
-		tree args;
-		bool one_inserted = false;
-
-		for (args = TREE_OPERAND (stmt, 1); args; 
-		     args = TREE_CHAIN (args))
-		  if (TREE_CODE (TREE_VALUE (args)) == ARRAY_REF
-		      || TREE_CODE (TREE_VALUE (args)) == INDIRECT_REF
-		      || TREE_CODE (TREE_VALUE (args)) == COMPONENT_REF)
-		    {
-		      dr = create_data_ref (TREE_VALUE (args), stmt, true);
-		      if (dr)
-			{
-			  VEC_safe_push (data_reference_p, heap, *datarefs, dr);
-			  one_inserted = true;
-			}
-		    }
+  return NULL_TREE;
+}
 
-		if (!one_inserted)
-		  goto insert_dont_know_node;
+/* Initializes an equation CY of the access matrix using the
+   information for a subscript from ACCESS_FUN.  Returns true when the
+   operation succeeded.  */
 
+static 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 i, 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;
+
+	if (loopi->num == var)
+	  cy[var_idx] = int_cst_value (right);
+	else
+	  {
+	    tree param;
+	    
+	    /* This is potentially a parameter.  */
+	    for (i = 0; VEC_iterate (tree, params, i, param);
+		 i++, var_idx++)
+	      if (loopi->num == var)
 		break;
-	      }
+	    
+	  }
 
-	    default:
-		{
-		  struct data_reference *res;
+	switch (TREE_CODE (left))
+	  {
+	  case POLYNOMIAL_CHREC:
+	    return build_access_matrix_with_af (left, cy, loop_nest, params);
 
-		insert_dont_know_node:;
-		  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;
-		  VEC_safe_push (data_reference_p, heap, *datarefs, res);
+	  case INTEGER_CST:
+	    {
+	      /* Constant part.  */
+	      unsigned nb_loops = VEC_length (loop_p, loop_nest);
+	      unsigned nb_params = VEC_length (tree, params);
 
-		  free (bbs);
-		  return chrec_dont_know;
-		}
+	      cy[nb_loops + nb_params] = int_cst_value (left);
+	      return true;
 	    }
 
-	  /* When there are no defs in the loop, the loop is parallel.  */
-	  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
-	    loop->parallel_p = false;
-	}
-    }
+	  default:
+	    return false;
+	  }
+      }
 
-  free (bbs);
+    case INTEGER_CST:
+      {
+	/* Constant part.  */
+	unsigned nb_loops = VEC_length (loop_p, loop_nest);
+	unsigned nb_params = VEC_length (tree, params);
 
-  return NULL_TREE;
+	cy[nb_loops + nb_params] = int_cst_value (access_fun);
+	return true;
+      }
+
+    default:
+      return false;
+    }
 }
 
 /* Recursive helper function.  */
Index: tree-data-ref.h
===================================================================
--- tree-data-ref.h	(revision 118003)
+++ tree-data-ref.h	(working copy)
@@ -105,6 +105,34 @@ struct data_reference
 
   /* The type of the data-ref.  */
   enum data_ref_type type;
+
+  /* Each vector of the access matrix represents a linear access
+     function for a subscript.  First elements correspond to the
+     leftmost indices, ie. for a[i][j] the first vector corresponds to
+     the subscript in "i".  The elements of a vector are relative to
+     the loop nest in which the data reference is considered.  
+
+     For example, in
+
+     | loop_1
+     |    loop_2
+     |      a[i+3][2*j+n-1]
+
+     if "i" varies in loop_1 and "j" varies in loop_2, the access
+     matrix with respect to the loop nest {loop_1, loop_2} is:
+
+     | loop_1  loop_2  param_n  cst
+     |   1       0        0      3
+     |   0       2        1     -1
+
+     whereas the access matrix with respect to loop_2 considers "i" as
+     a parameter:
+
+     | loop_2  param_i  param_n  cst
+     |   0       1         0      3
+     |   2       0         1     -1
+  */
+  VEC (lambda_vector, heap) *access_matrix;
 };
 
 typedef struct data_reference *data_reference_p;
@@ -237,6 +265,7 @@ struct data_dependence_relation
 
   /* The classic distance vector.  */
   VEC (lambda_vector, heap) *dist_vects;
+
 };
 
 typedef struct data_dependence_relation *ddr_p;
@@ -269,6 +298,20 @@ DEF_VEC_ALLOC_P(ddr_p,heap);
 
 
 
+/* Describes a location of a memory reference.  */
+
+typedef struct data_ref_loc_d
+{
+  /* Position of the memory reference.  */
+  tree *pos;
+
+  /* True if the memory reference is read.  */
+  bool is_read;
+} data_ref_loc;
+
+DEF_VEC_O (data_ref_loc);
+DEF_VEC_ALLOC_O (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,
@@ -295,7 +338,7 @@ extern void free_data_refs (VEC (data_re
 extern struct data_reference *analyze_array (tree, tree, bool);
 extern void estimate_iters_using_array (tree, tree);
 extern struct data_reference *create_data_ref (tree, tree, bool);
-
+extern bool find_data_references_in_stmt (tree, VEC (data_reference_p, heap) **);
 
 /* Return the index of the variable VAR in the LOOP_NEST array.  */
 
Index: graphite.c
===================================================================
--- graphite.c	(revision 118003)
+++ graphite.c	(working copy)
@@ -1,7 +1,6 @@
 /* Gimple Represented as Polyhedra.
    Copyright (C) 2006 Free Software Foundation, Inc.
-   Contributed by Alexandru Plesco <shurikx@gmail.com>
-   and Sebastian Pop <pop@cri.ensmp.fr>.
+   Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
 
 This file is part of GCC.
 
@@ -47,45 +46,77 @@ Software Foundation, 51 Franklin Street,
 
 VEC (scop_p, heap) *current_scops;
 
+
+/* Print the schedules from SCHED.  */
+
+void
+print_graphite_bb (FILE *file, graphite_bb_p gb, int indent, int verbosity)
+{
+  print_loop_ir_bb (file, GBB_BB (gb), indent, verbosity);
+}
+
 /* Print SCOP to FILE.  */
 
 static void
-print_scop (FILE *file, scop_p scop)
+print_scop (FILE *file, scop_p scop, int verbosity)
 {
-  fprintf (file, "\nSCoP (\n");
-  fprintf (file, "  entry = bb_%d\n", scop->entry->index);
-  fprintf (file, "  exit = bb_%d\n", scop->exit->index);
+  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)
+    {
+      graphite_bb_p gb;
+      unsigned i;
+
+      for (i = 0; VEC_iterate (graphite_bb_p, scop->bbs, i, gb); i++)
+	print_graphite_bb (file, gb, 0, verbosity);
+    }
+
   fprintf (file, ")\n");
 }
 
 /* Print all the SCOPs to FILE.  */
 
 static void
-print_scops (FILE *file)
+print_scops (FILE *file, int verbosity)
 {
   unsigned i;
   scop_p scop;
 
   for (i = 0; VEC_iterate (scop_p, current_scops, i, scop); i++)
-    print_scop (file, scop);
+    print_scop (file, scop, verbosity);
 }
 
 /* Debug SCOP.  */
 
 void
-debug_scop (scop_p scop)
+debug_scop (scop_p scop, int verbosity)
 {
-  print_scop (stderr, scop);
+  print_scop (stderr, scop, verbosity);
 }
 
 /* Debug all SCOPs from CURRENT_SCOPS.  */
 
 void 
-debug_scops (void)
+debug_scops (int verbosity)
 {
-  print_scops (stderr);
+  print_scops (stderr, verbosity);
 }
 
+
+
 /* Return true when EXPR is an affine function in LOOP.  */
 
 static bool
@@ -174,8 +205,7 @@ stmt_simple_for_scop_p (tree stmt)
 	    return true;
 	  }
 
-	/*
-	  We cannot return (affine_expr (loop, opnd0) &&
+	/* We cannot return (affine_expr (loop, opnd0) &&
 	   affine_expr (loop, opnd1)) because D.1882_16 is not affine
 	   in the following:
 
@@ -189,8 +219,7 @@ stmt_simple_for_scop_p (tree stmt)
 	   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.
-	*/
+	   it is very well possible that we can handle this.  */
 	return true;
       }
 
@@ -232,7 +261,32 @@ basic_block_simple_for_scop_p (basic_blo
   return true;
 }
 
-static scop_p down_open_scop;
+/* Return true when BB is contained in SCOP.  */
+
+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.  */
+
+static inline bool
+stmt_in_scop_p (tree stmt, scop_p scop)
+{
+  return bb_in_scop_p (bb_for_stmt (stmt), scop);
+}
+
+/* Return true when VAR is invariant in SCOP.  In that case, VAR is a
+   parameter of SCOP.  */
+
+static inline bool
+invariant_in_scop_p (tree var, scop_p scop)
+{
+  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
    current loop.  */
@@ -246,11 +300,12 @@ get_loop_start (basic_block bb)
   do {
     res = get_immediate_dominator (CDI_DOMINATORS, res);
     depth = res->loop_father->depth;
-    } while (depth != 0 && depth >= bb->loop_father->depth);
+  } while (depth != 0 && depth >= bb->loop_father->depth);
 
   return res;
 }
 
+static scop_p down_open_scop;
 
 /* Build the SCoP ending with BB.  */
 
@@ -268,8 +323,8 @@ end_scop (basic_block bb)
     }
 
   new_scop = XNEW (struct scop);
-  new_scop->entry = loop_start;
-  new_scop->exit = bb;
+  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);
 }
@@ -342,28 +397,383 @@ build_scops (void)
   VEC_safe_push (scop_p, heap, current_scops, down_open_scop);
 }
 
-/* Build the domains for each loop in the SCOP.  */
+
+
+/* Get the index corresponding to VAR in the current LOOP.  If
+   it's the first time we ask for this VAR, then we return
+   chrec_not_analyzed_yet for this VAR and return its index.  */
+
+static int
+param_index (tree var, scop_p scop)
+{
+  int i;
+  tree p;
+
+  for (i = 0; VEC_iterate (tree, SCOP_PARAMS (scop), i, p); i++)
+    if (p == var)
+      return i;
+
+  VEC_safe_push (tree, heap, SCOP_PARAMS (scop), var);
+  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
-build_domains (scop_p scop ATTRIBUTE_UNUSED)
+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;
+    }
 }
 
+/* Returns the index of LOOP in the domain matrix for the SCOP.  */
+
+static int
+scop_loop_index (scop_p scop, struct loop *loop)
+{
+  unsigned i;
+  struct loop *l;
 
-/* Build a schedule for each statement in the SCOP.  */
+  for (i = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), i, l); i++)
+    if (l == loop)
+      return i;
+
+  VEC_safe_push (loop_p, heap, SCOP_LOOP_NEST (scop), loop);
+  return VEC_length (loop_p, SCOP_LOOP_NEST (scop)) - 1;
+}
+
+/* Build the loop nest around basic block BB.  */
 
 static void
-build_scattering_functions (scop_p scop ATTRIBUTE_UNUSED)
+build_scop_loop_nests (scop_p scop)
 {
-  
+  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_loop_index (scop, GBB_BB (gb)->loop_father);
+
+  SCOP_NB_LOOPS (scop) = VEC_length (loop_p, SCOP_LOOP_NEST (scop));
+}
+
+/* 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_DIM_DOMAIN (scop) = SCOP_NB_LOOPS (scop) + SCOP_NB_PARAMS (scop) + 1;
+  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_iterations_in_loop (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)
+{
+  struct irp_data *data = dta;
+
+  switch (TREE_CODE (*var))
+    {
+    case SSA_NAME:
+      if (invariant_in_scop_p (*var, data->scop))
+	param_index (*var, data->scop);
+      return true;
+
+    default:
+      return true;
+    }
+}
+
+static bool
+idx_record_params (tree base, tree *idx, void *dta)
+{
+  struct irp_data *data = dta;
+
+  if (TREE_CODE (base) != ARRAY_REF)
+    return true;
+
+  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.  */
+
+static void
+build_access_matrix (data_reference_p ref ATTRIBUTE_UNUSED, graphite_bb_p bb ATTRIBUTE_UNUSED)
+{
+
+#if 0
+  for (i = 0; i < DDR_NUM_SUBSCRIPTS (ref); i++)
+    {
+      lambda_vector v = lambda_vector_new (VEC_length (loop_p, loop_nest));
+      bool res = build_access_matrix_with_af (DR_ACCESS_FN (ref, i), v, 
+					      loop_nest, params);
+      if (res == false)
+	{
+	  ref->affine = false;
+	  break;
+	}
+    }
+#endif
+}
+
+/* Build a schedule for each basic-block in the SCOP.  */
+
+static void
+build_scop_data_accesses (scop_p scop)
+{
+  unsigned i;
+  graphite_bb_p gb;
+
+  for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
+    {
+      unsigned j;
+      block_stmt_iterator bsi;
+      data_reference_p dr;
+
+      /* On each statement of the basic block, gather all the occurences
+	 to read/write memory.  */
+      GBB_DATA_REFS (gb) = VEC_alloc (data_reference_p, heap, 5);
+      for (bsi = bsi_start (GBB_BB (gb)); !bsi_end_p (bsi); bsi_next (&bsi))
+	find_data_references_in_stmt (bsi_stmt (bsi), &GBB_DATA_REFS (gb));
+
+      /* Construct the access matrix for each data ref, with respect to
+	 the loop nest of the current BB in the considered SCOP.  */
+      for (j = 0; VEC_iterate (data_reference_p, GBB_DATA_REFS (gb), j, dr); j++)
+	build_access_matrix (dr, gb);
+    }
+}
+
+/* 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;
+
+  /* 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_iterations_in_loop (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);
+
+  SCOP_NB_PARAMS (scop) = VEC_length (tree, SCOP_PARAMS (scop));
+}
 
 /* Find the right transform for the SCOP.  */
 
 static void
-graphite_find_transform (scop_p scop ATTRIBUTE_UNUSED)
+find_transform (scop_p scop ATTRIBUTE_UNUSED)
 {
   
 }
@@ -392,19 +802,23 @@ graphite_transform_loops (struct loops *
 
   build_scops ();
 
-  if (dump_file && (dump_flags & TDF_DETAILS))
+  for (i = 0; VEC_iterate (scop_p, current_scops, i, scop); i++)
     {
-      print_loop_ir (dump_file, 2);
-      print_scops (dump_file);
-      fprintf (dump_file, "\nnumber of SCoPs: %d\n",
-	       VEC_length (scop_p, current_scops));
+      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);
     }
 
-  for (i = 0; VEC_iterate (scop_p, current_scops, i, scop); i++)
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      build_domains (scop);
-      build_scattering_functions (scop);
-      graphite_find_transform (scop);
-      gloog (scop);
+      print_scops (dump_file, 2);
+      fprintf (dump_file, "\nnumber of SCoPs: %d\n",
+	       VEC_length (scop_p, current_scops));
     }
 }
Index: graphite.h
===================================================================
--- graphite.h	(revision 118003)
+++ graphite.h	(working copy)
@@ -1,7 +1,6 @@
 /* Gimple Represented as Polyhedra.
    Copyright (C) 2006 Free Software Foundation, Inc.
-   Contributed by Alexandru Plesco <shurikx@gmail.com>
-   and Sebastian Pop <pop@cri.ensmp.fr>.
+   Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
 
 This file is part of GCC.
 
@@ -20,25 +19,71 @@ along with GCC; see the file COPYING.  I
 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301, USA.  */
 
+#include "tree-data-ref.h"
 
-/* FIXME: get code from polyhedron.c from autovect branch.  */
-struct polyhedron
+typedef struct graphite_bb *graphite_bb_p;
+DEF_VEC_P(graphite_bb_p);
+DEF_VEC_ALLOC_P (graphite_bb_p, heap);
+
+typedef struct scop *scop_p;
+DEF_VEC_P(scop_p);
+DEF_VEC_ALLOC_P (scop_p, heap);
+
+struct graphite_bb
 {
-  int foo;
+  basic_block bb;
+
+  lambda_vector static_schedule;
+  VEC (lambda_vector, heap) *iteration_domain;
+  VEC (data_reference_p, heap) *data_refs;
 };
 
+#define GBB_BB(GBB) GBB->bb
+#define GBB_SCOP(GBB) GBB->scop
+#define GBB_STATIC_SCHEDULE(GBB) GBB->static_schedule
+#define GBB_DOMAIN(GBB) GBB->iteration_domain
+#define GBB_DATA_REFS(GBB) GBB->data_refs
+
+
 /* A SCoP is a Static Control Part of the program, simple enough to be
    represented in polyhedral form.  */
 struct scop
 {
+  /* The entry bb dominates all the bbs of the scop.  The exit bb
+     post-dominates all the bbs of the scop.  These entry and exit bbs
+     potentially contain non affine data accesses, side effect
+     statements or difficult constructs, and thus they are not
+     considered part of the scop, but just boundaries.  */
   basic_block entry, exit;
-};
+  VEC (graphite_bb_p, heap) *bbs;
 
-typedef struct scop *scop_p;
-DEF_VEC_P(scop_p);
-DEF_VEC_ALLOC_P (scop_p, heap);
+  lambda_vector static_schedule;
+
+  /* Parameters used within the SCOP.  */
+  int nb_params;
+  VEC (tree, heap) *params;
+
+  /* Loops contained in the scop.  */
+  int nb_loops;
+  VEC (loop_p, heap) *loop_nest;
+
+  int dim_domain;
+  VEC (lambda_vector, heap) *iteration_domain;
+};
 
-extern void debug_scop (scop_p);
-extern void debug_scops (void);
+#define SCOP_BBS(S) S->bbs
+#define SCOP_ENTRY(S) S->entry
+#define SCOP_EXIT(S) S->exit
+#define SCOP_STATIC_SCHEDULE(S) S->static_schedule
+#define SCOP_LOOP_NEST(S) S->loop_nest
+#define SCOP_NB_LOOPS(S) S->nb_loops
+#define SCOP_PARAMS(S) S->params
+#define SCOP_NB_PARAMS(S) S->nb_params
+#define SCOP_DIM_DOMAIN(S) S->dim_domain
+#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);
 
 #define SCOP_STMTS(S) (S)->stmts
Index: lambda.h
===================================================================
--- lambda.h	(revision 118003)
+++ lambda.h	(working copy)
@@ -37,6 +37,9 @@ DEF_VEC_ALLOC_P(lambda_vector,heap);
    all vectors are the same length).  */
 typedef lambda_vector *lambda_matrix;
 
+DEF_VEC_P (lambda_matrix);
+DEF_VEC_ALLOC_P (lambda_matrix, heap);
+
 /* A transformation matrix, which is a self-contained ROWSIZE x COLSIZE
    matrix.  Rather than use floats, we simply keep a single DENOMINATOR that
    represents the denominator for every element in the matrix.  */
Index: tree-flow.h
===================================================================
--- tree-flow.h	(revision 118003)
+++ tree-flow.h	(working copy)
@@ -575,6 +575,7 @@ extern void dump_cfg_stats (FILE *);
 extern void debug_cfg_stats (void);
 extern void debug_loop_ir (int);
 extern void print_loop_ir (FILE *, int);
+extern void print_loop_ir_bb (FILE *, basic_block, int, int);
 extern void cleanup_dead_labels (void);
 extern void group_case_labels (void);
 extern tree first_stmt (basic_block);
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 118003)
+++ tree-cfg.c	(working copy)
@@ -5133,6 +5133,34 @@ print_succ_bbs (FILE *file, basic_block 
     fprintf (file, "bb_%d ", e->dest->index);
 }
 
+/* Print to FILE the basic block BB following the VERBOSITY level.  */
+
+void 
+print_loop_ir_bb (FILE *file, basic_block bb, int indent, int verbosity)
+{
+  char *s_indent = (char *) alloca ((size_t) indent + 1);
+  memset ((void *) s_indent, ' ', (size_t) indent);
+  s_indent[indent] = '\0';
+
+  /* Print basic_block's header.  */
+  if (verbosity >= 2)
+    {
+      fprintf (file, "%s  bb_%d (preds = {", s_indent, bb->index);
+      print_pred_bbs (file, bb);
+      fprintf (file, "}, succs = {");
+      print_succ_bbs (file, bb);
+      fprintf (file, "})\n");
+    }
+
+  /* Print basic_block's body.  */
+  if (verbosity >= 3)
+    {
+      fprintf (file, "%s  {\n", s_indent);
+      tree_dump_bb (bb, file, indent + 4);
+      fprintf (file, "%s  }\n", s_indent);
+    }
+}
+
 
 /* Pretty print LOOP on FILE, indented INDENT spaces.  Following
    VERBOSITY level this outputs the contents of the loop, or just its
@@ -5152,7 +5180,13 @@ print_loop (FILE *file, struct loop *loo
   s_indent[indent] = '\0';
 
   /* Print loop's header.  */
-  fprintf (file, "%sloop_%d\n", s_indent, loop->num);
+  fprintf (file, "%sloop_%d (header = %d, latch = %d", s_indent, 
+	   loop->num, loop->header->index, loop->latch->index);
+  fprintf (file, ", niter = ");
+  print_generic_expr (file, loop->nb_iterations, 0);
+  fprintf (file, ", estim_niter = ");
+  print_generic_expr (file, loop->estimated_nb_iterations, 0);
+  fprintf (file, ")\n");
 
   /* Print loop's body.  */
   if (verbosity >= 1)
@@ -5160,25 +5194,7 @@ print_loop (FILE *file, struct loop *loo
       fprintf (file, "%s{\n", s_indent);
       FOR_EACH_BB (bb)
 	if (bb->loop_father == loop)
-	  {
-	    /* Print basic_block's header.  */
-	    if (verbosity >= 2)
-	      {
-		fprintf (file, "%s  bb_%d (preds = {", s_indent, bb->index);
-		print_pred_bbs (file, bb);
-		fprintf (file, "}, succs = {");
-		print_succ_bbs (file, bb);
-		fprintf (file, "})\n");
-	      }
-	    
-	    /* Print basic_block's body.  */
-	    if (verbosity >= 3)
-	      {
-		fprintf (file, "%s  {\n", s_indent);
-		tree_dump_bb (bb, file, indent + 4);
-		fprintf (file, "%s  }\n", s_indent);
-	      }
-	  }
+	  print_loop_ir_bb (file, bb, indent, verbosity);
 
       print_loop (file, loop->inner, indent + 2, verbosity);
       fprintf (file, "%s}\n", s_indent);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]