[tuples] Tuplify tree-parloops.c

Jakub Jelinek jakub@redhat.com
Tue Jul 1 16:47:00 GMT 2008


Hi!

This patch tuplifies tree-parloops.c (on top of
http://gcc.gnu.org/ml/gcc-patches/2008-07/msg00019.html
).
make -C gcc check-gcc RUNTESTFLAGS=autopar.exp
make -C gcc check-g++ RUNTESTFLAGS=dg.exp=pr34355.C
make -C */libgomp check RUNTESTFLAGS=c.exp=autopar*.c
all pass, but given that the test coverage is so weak, that doesn't
say almost anything.

Ok to commit to tuples as is and let Sebastian/Zdenek
resolve the issues below later on?

Even on fairly simple testcases both trunk and tuples
have issues:
1) -O2 -ftree-parallelize-loops=4
extern unsigned int ub[], uc[];
unsigned int foo (void)
{
  int i;
  unsigned int udiff = 2;
  for (i = 0; i < 1000000; i++)
    udiff += ub[i] - uc[i];
  return udiff;
}
  One issue is in create_parallel_loop, where trunk has:
  for (phi = phi_nodes (ex_bb); phi; phi = PHI_CHAIN (phi))
    {
      res = PHI_RESULT (phi);
      gcc_assert (!is_gimple_reg (phi));
  Testing whether a PHI is not a gimple reg doesn't make any sense,
  in the patch below I had to comment that out, as PHIs are
  gimple, while is_gimple_reg is called on trees.  Unfortunately
  gcc_assert (!is_gimple_reg (res)); which might make some sense
  triggers e.g. on the above testcase.
  Another, more important issue, is that on the above testcase
  gcc relies on unitialized stack variable.
  gen_parallel_loop doesn't initialize clsn_data in any way,
  then separate_decls_in_region doesn't initialize it either,
  supposedly because of htab_elements (name_copies) == 0,
  and then gen_parallel_loop calls
  if (htab_elements (reduction_list) > 0)
    create_call_for_reduction (loop, reduction_list, &clsn_data);
  where create_call_for_reduction_1 relies on it being
  initialized:
  tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
  among other things.  While on the trunk it usually compiles
  because the stack contains some tree and it only triggers
  if I say memset (&clsn_data, 0xaa, sizeof clsn_data);
  at the beginning of gen_parallel_loop, on tuples I'm not
  so lucky and it segfaults all the time.
2) for -O2 -ftree-parallelize-loops=4
unsigned int ub[16], uc[16];
unsigned int foo (void)
{
  int i;
  unsigned int udiff = 2;
  for (i = 0; i < 16; i++)
    udiff += ub[i] - uc[i];
  return udiff;
}
  a *loopfn* function is created and emitted, but the
  bb with GOMP_parallel_{start,end} is immediately
  optimized out, as the loop number of iterations
  is constant small.  Shouldn't tree-parloops.c
  just avoid the whole optimization if it obviously
  only makes the code larger?  I.e. in parallelize_loops
  skip loops where
  many_iterations_cond =
    fold_build2 (GE_EXPR, boolean_type_node,
                 nit, build_int_cst (type, MIN_PER_THREAD * n_threads));
  many_iterations_cond
    = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
                   invert_truthvalue (unshare_expr (niter->may_be_zero)),
                   many_iterations_cond);
  folds to boolean_false_node.

2008-07-01  Jakub Jelinek  <jakub@redhat.com>

	* tree-parloops.c (struct reduction_info): Change reduc_stmt,
	reduc_phi, keep_res and new_phi field types to gimple.
	(struct elv_data): Add info field.
	(reduction_phi, loop_parallel_p, take_address_of,
	initialize_reductions, eliminate_local_variables_stmt,
	eliminate_local_variables, expr_invariant_in_region_p,
	separate_decls_in_region_name, separate_decls_in_region_stmt,
	create_phi_for_local_result, create_call_for_reduction_1,
	create_call_for_reduction, create_loads_for_reductions,
	create_final_loads_for_reduction, create_stores_for_reduction,
	create_loads_and_stores_for_name, separate_decls_in_region,
	canonicalize_loop_ivs, transform_to_exit_first_loop,
	create_parallel_loop, gen_parallel_loop,
	loop_has_vector_phi_nodes, parallelize_loops): Tuplify.
	* tree-cfg.c (gimple_duplicate_sese_tail): Tuplify.
	(move_block_to_fn): Don't call gsi_next after calling
	remove_phi_node.

--- gcc/tree-parloops.c.jj	2008-06-13 14:30:50.000000000 +0200
+++ gcc/tree-parloops.c	2008-07-01 17:07:44.000000000 +0200
@@ -37,20 +37,18 @@ Software Foundation, 51 Franklin Street,
 #include "langhooks.h"
 #include "tree-vectorizer.h"
 
-/* FIXME tuples.  */
-#if 0
 /* This pass tries to distribute iterations of loops into several threads.
    The implementation is straightforward -- for each loop we test whether its
    iterations are independent, and if it is the case (and some additional
    conditions regarding profitability and correctness are satisfied), we
-   add OMP_PARALLEL and OMP_FOR codes and let omp expansion machinery do
-   its job.
+   add GIMPLE_OMP_PARALLEL and GIMPLE_OMP_FOR codes and let omp expansion
+   machinery do its job.
    
    The most of the complexity is in bringing the code into shape expected
    by the omp expanders:
-   -- for OMP_FOR, ensuring that the loop has only one induction variable
-      and that the exit test is at the start of the loop body
-   -- for OMP_PARALLEL, replacing the references to local addressable
+   -- for GIMPLE_OMP_FOR, ensuring that the loop has only one induction
+      variable and that the exit test is at the start of the loop body
+   -- for GIMPLE_OMP_PARALLEL, replacing the references to local addressable
       variables by accesses through pointers, and breaking up ssa chains
       by storing the values incoming to the parallelized loop to a structure
       passed to the new function as an argument (something similar is done
@@ -124,11 +122,11 @@ parloop
 
   sum.27_11 = D.1827_8 + sum.27_29;
 
-  OMP_CONTINUE
+  GIMPLE_OMP_CONTINUE
 
   # Adding this reduction phi is done at create_phi_for_local_result() #
   # sum.27_56 = PHI <sum.27_11, 0>
-  OMP_RETURN
+  GIMPLE_OMP_RETURN
   
   # Creating the atomic operation is done at 
   create_call_for_reduction_1()  #
@@ -138,7 +136,7 @@ parloop
   D.1840_60 = sum.27_56 + D.1839_59;
   #pragma omp atomic_store (D.1840_60);
   
-  OMP_RETURN
+  GIMPLE_OMP_RETURN
   
  # collecting the result after the join of the threads is done at
   create_loads_for_reductions().
@@ -168,15 +166,15 @@ parloop
    reduction in the current loop.  */
 struct reduction_info
 {
-  tree reduc_stmt;		/* reduction statement.  */
-  tree reduc_phi;		/* The phi node defining the reduction.  */
-  enum tree_code reduction_code;	/* code for the reduction operation.  */
-  tree keep_res;		/* The PHI_RESULT of this phi is the resulting value 
+  gimple reduc_stmt;		/* reduction statement.  */
+  gimple reduc_phi;		/* The phi node defining the reduction.  */
+  enum tree_code reduction_code;/* code for the reduction operation.  */
+  gimple keep_res;		/* The PHI_RESULT of this phi is the resulting value 
 				   of the reduction variable when existing the loop. */
   tree initial_value;		/* The initial value of the reduction var before entering the loop.  */
   tree field;			/*  the name of the field in the parloop data structure intended for reduction.  */
   tree init;			/* reduction initialization value.  */
-  tree new_phi;			/* (helper field) Newly created phi node whose result 
+  gimple new_phi;		/* (helper field) Newly created phi node whose result 
 				   will be passed to the atomic operation.  Represents
 				   the local result each thread computed for the reduction
 				   operation.  */
@@ -202,7 +200,7 @@ reduction_info_hash (const void *aa)
 }
 
 static struct reduction_info *
-reduction_phi (htab_t reduction_list, tree phi)
+reduction_phi (htab_t reduction_list, gimple phi)
 {
   struct reduction_info tmpred, *red;
 
@@ -251,14 +249,15 @@ name_to_copy_elt_hash (const void *aa)
    reductions are found, they are inserted to the REDUCTION_LIST.  */  
 
 static bool
-loop_parallel_p (struct loop *loop, htab_t reduction_list, struct tree_niter_desc *niter)
+loop_parallel_p (struct loop *loop, htab_t reduction_list,
+		 struct tree_niter_desc *niter)
 {
   edge exit = single_dom_exit (loop);
   VEC (ddr_p, heap) * dependence_relations;
-  VEC (data_reference_p, heap) * datarefs;
+  VEC (data_reference_p, heap) *datarefs;
   lambda_trans_matrix trans;
   bool ret = false;
-  tree phi;
+  gimple_stmt_iterator gsi;
   loop_vec_info simple_loop_info;
 
   /* Only consider innermost loops with just one exit.  The innermost-loop
@@ -281,9 +280,10 @@ loop_parallel_p (struct loop *loop, htab
 
   simple_loop_info = vect_analyze_loop_form (loop);
 
-  for (phi = phi_nodes (loop->header); phi; phi = PHI_CHAIN (phi))
+  for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
     {
-      tree reduc_stmt = NULL, operation;
+      gimple phi = gsi_stmt (gsi);
+      gimple reduc_stmt = NULL;
 
       /* ??? TODO: Change this into a generic function that 
          recognizes reductions.  */
@@ -304,7 +304,7 @@ loop_parallel_p (struct loop *loop, htab
 	    {
 	      fprintf (dump_file,
 		       "Detected reduction. reduction stmt is: \n");
-	      print_generic_stmt (dump_file, reduc_stmt, 0);
+	      print_gimple_stmt (dump_file, reduc_stmt, 0, 0);
 	      fprintf (dump_file, "\n");
 	    }
 
@@ -312,8 +312,7 @@ loop_parallel_p (struct loop *loop, htab
 
 	  new_reduction->reduc_stmt = reduc_stmt;
 	  new_reduction->reduc_phi = phi;
-	  operation = GIMPLE_STMT_OPERAND (reduc_stmt, 1);
-	  new_reduction->reduction_code = TREE_CODE (operation);
+	  new_reduction->reduction_code = gimple_assign_rhs_code (reduc_stmt);
 	  slot = htab_find_slot (reduction_list, new_reduction, INSERT);
 	  *slot = new_reduction;
 	}
@@ -322,13 +321,13 @@ loop_parallel_p (struct loop *loop, htab
   /* Get rid of the information created by the vectorizer functions.  */
   destroy_loop_vec_info (simple_loop_info, true);
 
-  for (phi = phi_nodes (exit->dest); phi; phi = PHI_CHAIN (phi))
+  for (gsi = gsi_start_phis (exit->dest); !gsi_end_p (gsi); gsi_next (&gsi))
     {
+      gimple phi = gsi_stmt (gsi);
       struct reduction_info *red;
       imm_use_iterator imm_iter;
       use_operand_p use_p;
-      tree reduc_phi;
-
+      gimple reduc_phi;
       tree val = PHI_ARG_DEF_FROM_EDGE (phi, exit);
 
       if (is_gimple_reg (val))
@@ -336,7 +335,7 @@ loop_parallel_p (struct loop *loop, htab
 	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
 	      fprintf (dump_file, "phi is ");
-	      print_generic_expr (dump_file, phi, 0);
+	      print_gimple_stmt (dump_file, phi, 0, 0);
 	      fprintf (dump_file, "arg of phi to exit:   value ");
 	      print_generic_expr (dump_file, val, 0);
 	      fprintf (dump_file, " used outside loop\n");
@@ -353,7 +352,7 @@ loop_parallel_p (struct loop *loop, htab
 	  reduc_phi = NULL;
 	  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, val)
 	  {
-	    if (flow_bb_inside_loop_p (loop, bb_for_stmt (USE_STMT (use_p))))
+	    if (flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p))))
 	      {
 		reduc_phi = USE_STMT (use_p);
 		break;
@@ -370,9 +369,9 @@ loop_parallel_p (struct loop *loop, htab
 	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
 	      fprintf (dump_file, "reduction phi is  ");
-	      print_generic_expr (dump_file, red->reduc_phi, 0);
+	      print_gimple_stmt (dump_file, red->reduc_phi, 0, 0);
 	      fprintf (dump_file, "reduction stmt is  ");
-	      print_generic_expr (dump_file, red->reduc_stmt, 0);
+	      print_gimple_stmt (dump_file, red->reduc_stmt, 0, 0);
 	    }
 
 	}
@@ -380,8 +379,9 @@ loop_parallel_p (struct loop *loop, htab
 
   /* The iterations of the loop may communicate only through bivs whose
      iteration space can be distributed efficiently.  */
-  for (phi = phi_nodes (loop->header); phi; phi = PHI_CHAIN (phi))
+  for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
     {
+      gimple phi = gsi_stmt (gsi);
       tree def = PHI_RESULT (phi);
       affine_iv iv;
 
@@ -467,7 +467,9 @@ take_address_of (tree obj, tree type, ed
   int uid;
   void **dslot;
   struct int_tree_map ielt, *nielt;
-  tree *var_p, name, bvar, stmt, addr;
+  tree *var_p, name, bvar, addr;
+  gimple stmt;
+  gimple_seq stmts;
 
   /* Since the address of OBJ is invariant, the trees may be shared.
      Avoid rewriting unrelated parts of the code.  */
@@ -485,10 +487,10 @@ take_address_of (tree obj, tree type, ed
       addr = build_addr (*var_p, current_function_decl);
       bvar = create_tmp_var (TREE_TYPE (addr), get_name (*var_p));
       add_referenced_var (bvar);
-      stmt = build_gimple_modify_stmt (bvar, addr);
+      stmt = gimple_build_assign (bvar, addr);
       name = make_ssa_name (bvar, stmt);
-      GIMPLE_STMT_OPERAND (stmt, 0) = name;
-      bsi_insert_on_edge_immediate (entry, stmt);
+      gimple_assign_set_lhs (stmt, name);
+      gsi_insert_on_edge_immediate (entry, stmt);
 
       nielt = XNEW (struct int_tree_map);
       nielt->uid = uid;
@@ -502,17 +504,17 @@ take_address_of (tree obj, tree type, ed
     {
       *var_p = build1 (INDIRECT_REF, TREE_TYPE (*var_p), name);
       name = force_gimple_operand (build_addr (obj, current_function_decl),
-				   &stmt, true, NULL_TREE);
-      if (stmt)
-	bsi_insert_on_edge_immediate (entry, stmt);
+				   &stmts, true, NULL_TREE);
+      if (!gimple_seq_empty_p (stmts))
+	gsi_insert_seq_on_edge_immediate (entry, stmts);
     }
 
   if (TREE_TYPE (name) != type)
     {
-      name = force_gimple_operand (fold_convert (type, name), &stmt, true,
+      name = force_gimple_operand (fold_convert (type, name), &stmts, true,
 				   NULL_TREE);
-      if (stmt)
-	bsi_insert_on_edge_immediate (entry, stmt);
+      if (!gimple_seq_empty_p (stmts))
+	gsi_insert_seq_on_edge_immediate (entry, stmts);
     }
 
   return name;
@@ -545,8 +547,7 @@ initialize_reductions (void **slot, void
 
   c = build_omp_clause (OMP_CLAUSE_REDUCTION);
   OMP_CLAUSE_REDUCTION_CODE (c) = reduc->reduction_code;
-  OMP_CLAUSE_DECL (c) =
-    SSA_NAME_VAR (GIMPLE_STMT_OPERAND (reduc->reduc_stmt, 0));
+  OMP_CLAUSE_DECL (c) = SSA_NAME_VAR (gimple_assign_lhs (reduc->reduc_stmt));
 
   init = omp_reduction_init (c, TREE_TYPE (bvar));
   reduc->init = init;
@@ -571,6 +572,7 @@ initialize_reductions (void **slot, void
 
 struct elv_data
 {
+  struct walk_stmt_info info;
   edge entry;
   htab_t decl_address;
   bool changed;
@@ -646,16 +648,17 @@ eliminate_local_variables_1 (tree *tp, i
    already.  */
 
 static void
-eliminate_local_variables_stmt (edge entry, tree stmt,
+eliminate_local_variables_stmt (edge entry, gimple stmt,
 				htab_t decl_address)
 {
   struct elv_data dta;
 
+  memset (&dta.info, '\0', sizeof (dta.info));
   dta.entry = entry;
   dta.decl_address = decl_address;
   dta.changed = false;
 
-  walk_tree (&stmt, eliminate_local_variables_1, &dta, NULL);
+  walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info);
 
   if (dta.changed)
     update_stmt (stmt);
@@ -678,7 +681,7 @@ eliminate_local_variables (edge entry, e
   basic_block bb;
   VEC (basic_block, heap) *body = VEC_alloc (basic_block, heap, 3);
   unsigned i;
-  block_stmt_iterator bsi;
+  gimple_stmt_iterator gsi;
   htab_t decl_address = htab_create (10, int_tree_map_hash, int_tree_map_eq,
 				     free);
   basic_block entry_bb = entry->src;
@@ -688,8 +691,8 @@ eliminate_local_variables (edge entry, e
 
   for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
     if (bb != entry_bb && bb != exit_bb)
-      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-	eliminate_local_variables_stmt (entry, bsi_stmt (bsi),
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	eliminate_local_variables_stmt (entry, gsi_stmt (gsi),
 					decl_address);
 
   htab_delete (decl_address);
@@ -705,14 +708,13 @@ expr_invariant_in_region_p (edge entry, 
   basic_block entry_bb = entry->src;
   basic_block exit_bb = exit->dest;
   basic_block def_bb;
-  unsigned i, len;
 
   if (is_gimple_min_invariant (expr))
     return true;
 
   if (TREE_CODE (expr) == SSA_NAME)
     {
-      def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (expr));
+      def_bb = gimple_bb (SSA_NAME_DEF_STMT (expr));
       if (def_bb
 	  && dominated_by_p (CDI_DOMINATORS, def_bb, entry_bb)
 	  && !dominated_by_p (CDI_DOMINATORS, def_bb, exit_bb))
@@ -721,15 +723,7 @@ expr_invariant_in_region_p (edge entry, 
       return true;
     }
 
-  if (!EXPR_P (expr) && !GIMPLE_STMT_P (expr))
-    return false;
-
-  len = TREE_OPERAND_LENGTH (expr);
-  for (i = 0; i < len; i++)
-    if (!expr_invariant_in_region_p (entry, exit, TREE_OPERAND (expr, i)))
-      return false;
-
-  return true;
+  return false;
 }
 
 /* If COPY_NAME_P is true, creates and returns a duplicate of NAME.
@@ -790,7 +784,7 @@ separate_decls_in_region_name (tree name
 
   if (copy_name_p)
     {
-      copy = duplicate_ssa_name (name, NULL_TREE);
+      copy = duplicate_ssa_name (name, NULL);
       nelt = XNEW (struct name_to_copy_elt);
       nelt->version = idx;
       nelt->new_name = copy;
@@ -815,7 +809,7 @@ separate_decls_in_region_name (tree name
    replacement decls are stored in DECL_COPIES.  */
 
 static void
-separate_decls_in_region_stmt (edge entry, edge exit, tree stmt,
+separate_decls_in_region_stmt (edge entry, edge exit, gimple stmt,
 			       htab_t name_copies, htab_t decl_copies)
 {
   use_operand_p use;
@@ -857,7 +851,7 @@ add_field_for_reduction (void **slot, vo
   
   struct reduction_info *red = *slot;
   tree type = data;
-  tree var = SSA_NAME_VAR (GIMPLE_STMT_OPERAND (red->reduc_stmt, 0));
+  tree var = SSA_NAME_VAR (gimple_assign_lhs (red->reduc_stmt));
   tree field = build_decl (FIELD_DECL, DECL_NAME (var), TREE_TYPE (var));
 
   insert_field_into_struct (type, field);
@@ -898,13 +892,13 @@ create_phi_for_local_result (void **slot
   struct reduction_info *reduc = *slot;
   struct loop *loop = data;
   edge e;
-  tree new_phi;
+  gimple new_phi;
   basic_block store_bb;
   tree local_res;
 
   /* STORE_BB is the block where the phi 
      should be stored.  It is the destination of the loop exit.  
-     (Find the fallthru edge from OMP_CONTINUE).  */
+     (Find the fallthru edge from GIMPLE_OMP_CONTINUE).  */
   store_bb = FALLTHRU_EDGE (loop->latch)->dest;
 
   /* STORE_BB has two predecessors.  One coming from  the loop
@@ -916,11 +910,13 @@ create_phi_for_local_result (void **slot
     e = EDGE_PRED (store_bb, 1);
   else
     e = EDGE_PRED (store_bb, 0);
-  local_res = make_ssa_name (SSA_NAME_VAR (GIMPLE_STMT_OPERAND (reduc->reduc_stmt, 0)), NULL_TREE);
+  local_res
+    = make_ssa_name (SSA_NAME_VAR (gimple_assign_lhs (reduc->reduc_stmt)),
+		     NULL);
   new_phi = create_phi_node (local_res, store_bb);
   SSA_NAME_DEF_STMT (local_res) = new_phi;
   add_phi_arg (new_phi, reduc->init, e);
-  add_phi_arg (new_phi, GIMPLE_STMT_OPERAND (reduc->reduc_stmt, 0),
+  add_phi_arg (new_phi, gimple_assign_lhs (reduc->reduc_stmt),
 	       FALLTHRU_EDGE (loop->latch));
   reduc->new_phi = new_phi;
 
@@ -946,7 +942,7 @@ create_call_for_reduction_1 (void **slot
 {
   struct reduction_info *reduc = *slot;
   struct clsn_data *clsn_data = data;
-  block_stmt_iterator bsi;
+  gimple_stmt_iterator gsi;
   tree type = TREE_TYPE (PHI_RESULT (reduc->reduc_phi));
   tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
   tree load_struct;
@@ -954,7 +950,8 @@ create_call_for_reduction_1 (void **slot
   basic_block new_bb;
   edge e;
   tree t, addr, addr_type, ref, x;
-  tree tmp_load, load, name;
+  tree tmp_load, name;
+  gimple load;
 
   load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
   t = build3 (COMPONENT_REF, type, load_struct, reduc->field, NULL_TREE);
@@ -971,27 +968,23 @@ create_call_for_reduction_1 (void **slot
   tmp_load = create_tmp_var (TREE_TYPE (TREE_TYPE (addr)), NULL);
   add_referenced_var (tmp_load);
   tmp_load = make_ssa_name (tmp_load, NULL);
-  load = build2 (OMP_ATOMIC_LOAD, void_type_node, tmp_load, addr);
+  load = gimple_build_omp_atomic_load (tmp_load, addr);
   SSA_NAME_DEF_STMT (tmp_load) = load;
-  bsi = bsi_start (new_bb);
-  bsi_insert_after (&bsi, load, BSI_NEW_STMT);
+  gsi = gsi_start_bb (new_bb);
+  gsi_insert_after (&gsi, load, GSI_NEW_STMT);
 
   e = split_block (new_bb, load);
   new_bb = e->dest;
-  bsi = bsi_start (new_bb);
+  gsi = gsi_start_bb (new_bb);
   ref = tmp_load;
-  x =
-    fold_build2 (reduc->reduction_code,
-		 TREE_TYPE (PHI_RESULT (reduc->new_phi)), ref,
-		 PHI_RESULT (reduc->new_phi));
-
-  name =
-    force_gimple_operand_bsi (&bsi, x, true, NULL_TREE, true,
-			      BSI_CONTINUE_LINKING);
+  x = fold_build2 (reduc->reduction_code,
+		   TREE_TYPE (PHI_RESULT (reduc->new_phi)), ref,
+		   PHI_RESULT (reduc->new_phi));
 
-  x = build1 (OMP_ATOMIC_STORE, void_type_node, name);
+  name = force_gimple_operand_gsi (&gsi, x, true, NULL_TREE, true,
+				   GSI_CONTINUE_LINKING);
 
-  bsi_insert_after (&bsi, x, BSI_NEW_STMT);
+  gsi_insert_after (&gsi, gimple_build_omp_atomic_store (name), GSI_NEW_STMT);
   return 1;
 }
 
@@ -1004,7 +997,7 @@ create_call_for_reduction (struct loop *
 			   struct clsn_data *ld_st_data)
 {
   htab_traverse (reduction_list, create_phi_for_local_result, loop);
-  /* Find the fallthru edge from OMP_CONTINUE.  */
+  /* Find the fallthru edge from GIMPLE_OMP_CONTINUE.  */
   ld_st_data->load_bb = FALLTHRU_EDGE (loop->latch)->dest;
   htab_traverse (reduction_list, create_call_for_reduction_1, ld_st_data);
 }
@@ -1017,30 +1010,34 @@ create_loads_for_reductions (void **slot
 {
   struct reduction_info *red = *slot;
   struct clsn_data *clsn_data = data;
-  tree stmt;
-  block_stmt_iterator bsi;
-  tree type = TREE_TYPE (GIMPLE_STMT_OPERAND (red->reduc_stmt, 0));
+  gimple stmt;
+  gimple_stmt_iterator gsi;
+  tree type = TREE_TYPE (gimple_assign_lhs (red->reduc_stmt));
   tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
   tree load_struct;
   tree name;
   tree x;
 
-  bsi = bsi_after_labels (clsn_data->load_bb);
+  gsi = gsi_after_labels (clsn_data->load_bb);
   load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
   load_struct = build3 (COMPONENT_REF, type, load_struct, red->field,
 			NULL_TREE);
 
   x = load_struct;
   name = PHI_RESULT (red->keep_res);
-  stmt = build_gimple_modify_stmt (name, x);
-  GIMPLE_STMT_OPERAND (stmt, 0) = name;
+  stmt = gimple_build_assign (name, x);
   SSA_NAME_DEF_STMT (name) = stmt;
 
-  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
+  gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
 
-  remove_phi_node (red->keep_res, NULL_TREE, false);
-
-  return 1;
+  for (gsi = gsi_start_phis (gimple_bb (red->keep_res));
+       !gsi_end_p (gsi); gsi_next (&gsi))
+    if (gsi_stmt (gsi) == red->keep_res)
+      {
+	remove_phi_node (&gsi, false);
+	return 1;
+      }
+  gcc_unreachable ();
 }
 
 /* Load the reduction result that was stored in LD_ST_DATA.  
@@ -1050,18 +1047,16 @@ static void
 create_final_loads_for_reduction (htab_t reduction_list, 
 				  struct clsn_data *ld_st_data)
 {
-  block_stmt_iterator bsi;
+  gimple_stmt_iterator gsi;
   tree t;
+  gimple stmt;
 
-  bsi = bsi_after_labels (ld_st_data->load_bb);
+  gsi = gsi_after_labels (ld_st_data->load_bb);
   t = build_fold_addr_expr (ld_st_data->store);
-  t =
-    build_gimple_modify_stmt (ld_st_data->load,
-			      build_fold_addr_expr (ld_st_data->store));
-
-  bsi_insert_before (&bsi, t, BSI_NEW_STMT);
-  SSA_NAME_DEF_STMT (ld_st_data->load) = t;
-  GIMPLE_STMT_OPERAND (t, 0) = ld_st_data->load;
+  stmt = gimple_build_assign (ld_st_data->load, t);
+
+  gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
+  SSA_NAME_DEF_STMT (ld_st_data->load) = stmt;
 
   htab_traverse (reduction_list, create_loads_for_reductions, ld_st_data);
 
@@ -1078,18 +1073,16 @@ create_stores_for_reduction (void **slot
 {
   struct reduction_info *red = *slot;
   struct clsn_data *clsn_data = data;
-  tree stmt;
-  block_stmt_iterator bsi;
-  tree type = TREE_TYPE (GIMPLE_STMT_OPERAND (red->reduc_stmt, 0));
+  tree t;
+  gimple stmt;
+  gimple_stmt_iterator gsi;
+  tree type = TREE_TYPE (gimple_assign_lhs (red->reduc_stmt));
   
-  bsi = bsi_last (clsn_data->store_bb);
-  stmt =
-    build_gimple_modify_stmt (build3
-                              (COMPONENT_REF, type, clsn_data->store,
-                               red->field, NULL_TREE),
-                               red->initial_value);
+  gsi = gsi_last_bb (clsn_data->store_bb);
+  t = build3 (COMPONENT_REF, type, clsn_data->store, red->field, NULL_TREE);
+  stmt = gimple_build_assign (t, red->initial_value);
   mark_virtual_ops_for_renaming (stmt);
-  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
+  gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
 
   return 1;
 }
@@ -1103,28 +1096,25 @@ create_loads_and_stores_for_name (void *
 {
   struct name_to_copy_elt *elt = *slot;
   struct clsn_data *clsn_data = data;
-  tree stmt;
-  block_stmt_iterator bsi;
+  tree t;
+  gimple stmt;
+  gimple_stmt_iterator gsi;
   tree type = TREE_TYPE (elt->new_name);
   tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
   tree load_struct;
 
-  bsi = bsi_last (clsn_data->store_bb);
-  stmt =
-    build_gimple_modify_stmt (build3
-			      (COMPONENT_REF, type, clsn_data->store,
-			       elt->field, NULL_TREE),
-			      ssa_name (elt->version));
+  gsi = gsi_last_bb (clsn_data->store_bb);
+  t = build3 (COMPONENT_REF, type, clsn_data->store, elt->field, NULL_TREE);
+  stmt = gimple_build_assign (t, ssa_name (elt->version));
   mark_virtual_ops_for_renaming (stmt);
-  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
+  gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
 
-  bsi = bsi_last (clsn_data->load_bb);
+  gsi = gsi_last_bb (clsn_data->load_bb);
   load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
-  stmt = build_gimple_modify_stmt (elt->new_name,
-				   build3 (COMPONENT_REF, type, load_struct,
-					   elt->field, NULL_TREE));
+  t = build3 (COMPONENT_REF, type, load_struct, elt->field, NULL_TREE);
+  stmt = gimple_build_assign (elt->new_name, t);
   SSA_NAME_DEF_STMT (elt->new_name) = stmt;
-  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
+  gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
 
   return 1;
 }
@@ -1176,27 +1166,27 @@ separate_decls_in_region (edge entry, ed
   htab_t decl_copies = htab_create (10, int_tree_map_hash, int_tree_map_eq,
 				    free);
   unsigned i;
-  tree phi, type, type_name, nvar;
-  block_stmt_iterator bsi;
+  tree type, type_name, nvar;
+  gimple_stmt_iterator gsi;
   struct clsn_data clsn_data;
   VEC (basic_block, heap) *body = VEC_alloc (basic_block, heap, 3);
   basic_block bb;
   basic_block entry_bb = bb1;
   basic_block exit_bb = exit->dest;
 
-  entry = single_succ_edge(entry_bb);
+  entry = single_succ_edge (entry_bb);
   gather_blocks_in_sese_region (entry_bb, exit_bb, &body);
 
   for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
     {
       if (bb != entry_bb && bb != exit_bb) 
 	{
-	  for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-	    separate_decls_in_region_stmt (entry, exit, phi, name_copies,
-					   decl_copies);
-	  
-	  for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-	    separate_decls_in_region_stmt (entry, exit, bsi_stmt (bsi),
+	  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	    separate_decls_in_region_stmt (entry, exit, gsi_stmt (gsi),
+					   name_copies, decl_copies);
+
+	  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	    separate_decls_in_region_stmt (entry, exit, gsi_stmt (gsi),
 					   name_copies, decl_copies);
 	}
     }
@@ -1232,7 +1222,7 @@ separate_decls_in_region (edge entry, ed
       add_referenced_var (*arg_struct);
       nvar = create_tmp_var (build_pointer_type (type), ".paral_data_load");
       add_referenced_var (nvar);
-      *new_arg_struct = make_ssa_name (nvar, NULL_TREE);
+      *new_arg_struct = make_ssa_name (nvar, NULL);
 
       ld_st_data->store = *arg_struct;
       ld_st_data->load = *new_arg_struct;
@@ -1248,7 +1238,7 @@ separate_decls_in_region (edge entry, ed
 	{
 	  htab_traverse (reduction_list, create_stores_for_reduction,
                         ld_st_data); 
-	  clsn_data.load = make_ssa_name (nvar, NULL_TREE);
+	  clsn_data.load = make_ssa_name (nvar, NULL);
 	  clsn_data.load_bb = exit->dest;
 	  clsn_data.store = ld_st_data->store;
 	  create_final_loads_for_reduction (reduction_list, &clsn_data);
@@ -1258,7 +1248,6 @@ separate_decls_in_region (edge entry, ed
   htab_delete (decl_copies);
   htab_delete (name_copies);
 }
-#endif
 
 /* Bitmap containing uids of functions created by parallelization.  We cannot
    allocate it from the default obstack, as it must live across compilation
@@ -1266,8 +1255,6 @@ separate_decls_in_region (edge entry, ed
 
 static GTY(()) bitmap parallelized_functions;
 
-/* FIXME tuples.  */
-#if 0
 /* Returns true if FN was created by create_loop_fn.  */
 
 static bool
@@ -1343,15 +1330,18 @@ static void
 canonicalize_loop_ivs (struct loop *loop, htab_t reduction_list, tree nit)
 {
   unsigned precision = TYPE_PRECISION (TREE_TYPE (nit));
-  tree phi, prev, res, type, var_before, val, atype, mtype, t, next;
-  block_stmt_iterator bsi;
+  tree res, type, var_before, val, atype, mtype;
+  gimple_stmt_iterator gsi, psi;
+  gimple phi, stmt;
   bool ok;
   affine_iv iv;
   edge exit = single_dom_exit (loop);
   struct reduction_info *red;
 
-  for (phi = phi_nodes (loop->header); phi; phi = PHI_CHAIN (phi))
+  for (psi = gsi_start_phis (loop->header);
+       !gsi_end_p (psi); gsi_next (&psi))
     {
+      phi = gsi_stmt (psi);
       res = PHI_RESULT (phi);
 
       if (is_gimple_reg (res) && TYPE_PRECISION (TREE_TYPE (res)) > precision)
@@ -1360,20 +1350,19 @@ canonicalize_loop_ivs (struct loop *loop
 
   type = lang_hooks.types.type_for_size (precision, 1);
 
-  bsi = bsi_last (loop->latch);
+  gsi = gsi_last_bb (loop->latch);
   create_iv (build_int_cst_type (type, 0), build_int_cst (type, 1), NULL_TREE,
-	     loop, &bsi, true, &var_before, NULL);
+	     loop, &gsi, true, &var_before, NULL);
 
-  bsi = bsi_after_labels (loop->header);
-  prev = NULL;
-  for (phi = phi_nodes (loop->header); phi; phi = next)
+  gsi = gsi_after_labels (loop->header);
+  for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); )
     {
-      next = PHI_CHAIN (phi);
+      phi = gsi_stmt (psi);
       res = PHI_RESULT (phi);
 
       if (!is_gimple_reg (res) || res == var_before)
 	{
-	  prev = phi;
+	  gsi_next (&psi);
 	  continue;
 	}
 
@@ -1382,12 +1371,12 @@ canonicalize_loop_ivs (struct loop *loop
       /* We preserve the reduction phi nodes.  */
       if (!ok && red)
 	{
-	  prev = phi;
+	  gsi_next (&psi);
 	  continue;
 	}
       else
 	gcc_assert (ok);
-      remove_phi_node (phi, prev, false);
+      remove_phi_node (&psi, false);
 
       atype = TREE_TYPE (res);
       mtype = POINTER_TYPE_P (atype) ? sizetype : atype;
@@ -1396,14 +1385,14 @@ canonicalize_loop_ivs (struct loop *loop
       val = fold_build2 (POINTER_TYPE_P (atype)
 			 ? POINTER_PLUS_EXPR : PLUS_EXPR,
 			 atype, unshare_expr (iv.base), val);
-      val = force_gimple_operand_bsi (&bsi, val, false, NULL_TREE, true,
-				      BSI_SAME_STMT);
-      t = build_gimple_modify_stmt (res, val);
-      bsi_insert_before (&bsi, t, BSI_SAME_STMT);
-      SSA_NAME_DEF_STMT (res) = t;
+      val = force_gimple_operand_gsi (&gsi, val, false, NULL_TREE, true,
+				      GSI_SAME_STMT);
+      stmt = gimple_build_assign (res, val);
+      gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+      SSA_NAME_DEF_STMT (res) = stmt;
     }
 
-  t = last_stmt (exit->src);
+  stmt = last_stmt (exit->src);
   /* Make the loop exit if the control condition is not satisfied.  */
   if (exit->flags & EDGE_TRUE_VALUE)
     {
@@ -1413,7 +1402,9 @@ canonicalize_loop_ivs (struct loop *loop
       te->flags = EDGE_FALSE_VALUE;
       fe->flags = EDGE_TRUE_VALUE;
     }
-  COND_EXPR_COND (t) = build2 (LT_EXPR, boolean_type_node, var_before, nit);
+  gimple_cond_set_code (stmt, LT_EXPR);
+  gimple_cond_set_lhs (stmt, var_before);
+  gimple_cond_set_rhs (stmt, nit);
 }
 
 /* Moves the exit condition of LOOP to the beginning of its header, and
@@ -1435,22 +1426,23 @@ transform_to_exit_first_loop (struct loo
   unsigned n;
   bool ok;
   edge exit = single_dom_exit (loop), hpred;
-  tree phi, nphi, cond, control, control_name, res, t, cond_stmt;
-  block_stmt_iterator bsi;
+  tree control, control_name, res, t;
+  gimple phi, nphi, cond_stmt, stmt;
+  gimple_stmt_iterator gsi;
 
   split_block_after_labels (loop->header);
   orig_header = single_succ (loop->header);
   hpred = single_succ_edge (loop->header);
 
   cond_stmt = last_stmt (exit->src);
-  cond = COND_EXPR_COND (cond_stmt);
-  control = TREE_OPERAND (cond, 0);
-  gcc_assert (TREE_OPERAND (cond, 1) == nit);
+  control = gimple_cond_lhs (cond_stmt);
+  gcc_assert (gimple_cond_rhs (cond_stmt) == nit);
 
   /* Make sure that we have phi nodes on exit for all loop header phis
      (create_parallel_loop requires that).  */
-  for (phi = phi_nodes (loop->header); phi; phi = PHI_CHAIN (phi))
+  for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
     {
+      phi = gsi_stmt (gsi);
       res = PHI_RESULT (phi);
       t = make_ssa_name (SSA_NAME_VAR (res), phi);
       SET_PHI_RESULT (phi, t);
@@ -1461,7 +1453,7 @@ transform_to_exit_first_loop (struct loo
 
       if (res == control)
 	{
-	  TREE_OPERAND (cond, 0) = t;
+	  gimple_cond_set_lhs (cond_stmt, t);
 	  update_stmt (cond_stmt);
 	  control = t;
 	}
@@ -1471,22 +1463,26 @@ transform_to_exit_first_loop (struct loo
   for (n = 0; bbs[n] != exit->src; n++)
     continue;
   nbbs = XNEWVEC (basic_block, n);
-  ok = tree_duplicate_sese_tail (single_succ_edge (loop->header), exit,
-				 bbs + 1, n, nbbs);
+  ok = gimple_duplicate_sese_tail (single_succ_edge (loop->header), exit,
+				   bbs + 1, n, nbbs);
   gcc_assert (ok);
   free (bbs);
   ex_bb = nbbs[0];
   free (nbbs);
 
   /* Other than reductions, the only gimple reg that should be copied 
-   out of the loop is the control variable.  */
+     out of the loop is the control variable.  */
 
   control_name = NULL_TREE;
-  for (phi = phi_nodes (ex_bb); phi; phi = PHI_CHAIN (phi))
+  for (gsi = gsi_start_phis (ex_bb); !gsi_end_p (gsi); )
     {
+      phi = gsi_stmt (gsi);
       res = PHI_RESULT (phi);
       if (!is_gimple_reg (res))
-	continue;
+	{
+	  gsi_next (&gsi);
+	  continue;
+	}
 
       /* Check if it is a part of reduction.  If it is,
          keep the phi at the reduction's keep_res field.  The  
@@ -1503,93 +1499,95 @@ transform_to_exit_first_loop (struct loo
 
 	  red = reduction_phi (reduction_list, SSA_NAME_DEF_STMT (val));
 	  if (red)
-	    red->keep_res = phi;
+	    {
+	      red->keep_res = phi;
+	      gsi_next (&gsi);
+	      continue;
+	    }
 	}
-      else
-	gcc_assert (control_name == NULL_TREE
-		    && SSA_NAME_VAR (res) == SSA_NAME_VAR (control));
+      gcc_assert (control_name == NULL_TREE
+		  && SSA_NAME_VAR (res) == SSA_NAME_VAR (control));
       control_name = res;
+      remove_phi_node (&gsi, false);
     }
   gcc_assert (control_name != NULL_TREE);
-  phi = SSA_NAME_DEF_STMT (control_name);
-  remove_phi_node (phi, NULL_TREE, false);
 
   /* Initialize the control variable to NIT.  */
-  bsi = bsi_after_labels (ex_bb);
-  nit = force_gimple_operand_bsi (&bsi,
+  gsi = gsi_after_labels (ex_bb);
+  nit = force_gimple_operand_gsi (&gsi,
 				  fold_convert (TREE_TYPE (control_name), nit),
-				  false, NULL_TREE, false, BSI_SAME_STMT);
-  t = build_gimple_modify_stmt (control_name, nit);
-  bsi_insert_before (&bsi, t, BSI_NEW_STMT);
-  SSA_NAME_DEF_STMT (control_name) = t;
+				  false, NULL_TREE, false, GSI_SAME_STMT);
+  stmt = gimple_build_assign (control_name, nit);
+  gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
+  SSA_NAME_DEF_STMT (control_name) = stmt;
 }
 
 /* Create the parallel constructs for LOOP as described in gen_parallel_loop.
-   LOOP_FN and DATA are the arguments of OMP_PARALLEL.
+   LOOP_FN and DATA are the arguments of GIMPLE_OMP_PARALLEL.
    NEW_DATA is the variable that should be initialized from the argument
    of LOOP_FN.  N_THREADS is the requested number of threads.  Returns the
-   basic block containing OMP_PARALLEL tree.  */
+   basic block containing GIMPLE_OMP_PARALLEL tree.  */
 
 static basic_block
 create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
 		      tree new_data, unsigned n_threads)
 {
-  block_stmt_iterator bsi;
+  gimple_stmt_iterator gsi;
   basic_block bb, paral_bb, for_bb, ex_bb;
-  tree t, param, res, for_stmt;
-  tree cvar, cvar_init, initvar, cvar_next, cvar_base, cond, phi, type;
+  tree t, param, res;
+  gimple stmt, for_stmt, phi, cond_stmt;
+  tree cvar, cvar_init, initvar, cvar_next, cvar_base, type;
   edge exit, nexit, guard, end, e;
 
-  /* Prepare the OMP_PARALLEL statement.  */
+  /* Prepare the GIMPLE_OMP_PARALLEL statement.  */
   bb = loop_preheader_edge (loop)->src;
   paral_bb = single_pred (bb);
-  bsi = bsi_last (paral_bb);
+  gsi = gsi_last_bb (paral_bb);
 
   t = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
   OMP_CLAUSE_NUM_THREADS_EXPR (t)
     = build_int_cst (integer_type_node, n_threads);
-  t = build4 (OMP_PARALLEL, void_type_node, NULL_TREE, t, loop_fn, data);
+  stmt = gimple_build_omp_parallel (NULL, t, loop_fn, data);
 
-  bsi_insert_after (&bsi, t, BSI_NEW_STMT);
+  gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
 
   /* Initialize NEW_DATA.  */
   if (data)
     {
-      bsi = bsi_after_labels (bb);
+      gsi = gsi_after_labels (bb);
 
-      param = make_ssa_name (DECL_ARGUMENTS (loop_fn), NULL_TREE);
-      t = build_gimple_modify_stmt (param, build_fold_addr_expr (data));
-      bsi_insert_before (&bsi, t, BSI_SAME_STMT);
-      SSA_NAME_DEF_STMT (param) = t;
+      param = make_ssa_name (DECL_ARGUMENTS (loop_fn), NULL);
+      stmt = gimple_build_assign (param, build_fold_addr_expr (data));
+      gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+      SSA_NAME_DEF_STMT (param) = stmt;
 
-      t = build_gimple_modify_stmt (new_data,
-				    fold_convert (TREE_TYPE (new_data),
-						  param));
-      bsi_insert_before (&bsi, t, BSI_SAME_STMT);
-      SSA_NAME_DEF_STMT (new_data) = t;
+      stmt = gimple_build_assign (new_data,
+				  fold_convert (TREE_TYPE (new_data), param));
+      gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+      SSA_NAME_DEF_STMT (new_data) = stmt;
     }
 
-  /* Emit OMP_RETURN for OMP_PARALLEL.  */
+  /* Emit GIMPLE_OMP_RETURN for GIMPLE_OMP_PARALLEL.  */
   bb = split_loop_exit_edge (single_dom_exit (loop));
-  bsi = bsi_last (bb);
-  bsi_insert_after (&bsi, make_node (OMP_RETURN), BSI_NEW_STMT);
+  gsi = gsi_last_bb (bb);
+  gsi_insert_after (&gsi, gimple_build_omp_return (false), GSI_NEW_STMT);
 
-  /* Extract data for OMP_FOR.  */
+  /* Extract data for GIMPLE_OMP_FOR.  */
   gcc_assert (loop->header == single_dom_exit (loop)->src);
-  cond = COND_EXPR_COND (last_stmt (loop->header));
+  cond_stmt = last_stmt (loop->header);
 
-  cvar = TREE_OPERAND (cond, 0);
+  cvar = gimple_cond_lhs (cond_stmt);
   cvar_base = SSA_NAME_VAR (cvar);
   phi = SSA_NAME_DEF_STMT (cvar);
   cvar_init = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
-  initvar = make_ssa_name (cvar_base, NULL_TREE);
+  initvar = make_ssa_name (cvar_base, NULL);
   SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, loop_preheader_edge (loop)),
 	   initvar);
   cvar_next = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop));
 
-  bsi = bsi_last (loop->latch);
-  gcc_assert (bsi_stmt (bsi) == SSA_NAME_DEF_STMT (cvar_next));
-  bsi_remove (&bsi, true);
+  gsi = gsi_last_bb (loop->latch);
+  gcc_assert (gsi_stmt (gsi) == SSA_NAME_DEF_STMT (cvar_next));
+  gsi_remove (&gsi, true);
 
   /* Prepare cfg.  */
   for_bb = split_edge (loop_preheader_edge (loop));
@@ -1600,56 +1598,52 @@ create_parallel_loop (struct loop *loop,
   guard = make_edge (for_bb, ex_bb, 0);
   single_succ_edge (loop->latch)->flags = 0;
   end = make_edge (loop->latch, ex_bb, EDGE_FALLTHRU);
-  for (phi = phi_nodes (ex_bb); phi; phi = PHI_CHAIN (phi))
+  for (gsi = gsi_start_phis (ex_bb); !gsi_end_p (gsi); gsi_next (&gsi))
     {
+      phi = gsi_stmt (gsi);
       res = PHI_RESULT (phi);
-      gcc_assert (!is_gimple_reg (phi));
-      t = SSA_NAME_DEF_STMT (PHI_ARG_DEF_FROM_EDGE (phi, exit));
-      add_phi_arg (phi, PHI_ARG_DEF_FROM_EDGE (t, loop_preheader_edge (loop)),
+      /* FIXME tuples
+	 The original code was doing gcc_assert (!is_gimple_reg (phi));
+	 which doesn't make sense at all.
+	 gcc_assert (!is_gimple_reg (res));  */
+      stmt = SSA_NAME_DEF_STMT (PHI_ARG_DEF_FROM_EDGE (phi, exit));
+      add_phi_arg (phi,
+		   PHI_ARG_DEF_FROM_EDGE (stmt, loop_preheader_edge (loop)),
 		   guard);
-      add_phi_arg (phi, PHI_ARG_DEF_FROM_EDGE (t, loop_latch_edge (loop)),
+      add_phi_arg (phi, PHI_ARG_DEF_FROM_EDGE (stmt, loop_latch_edge (loop)),
 		   end);
     }
   e = redirect_edge_and_branch (exit, nexit->dest);
   PENDING_STMT (e) = NULL;
 
-  /* Emit OMP_FOR.  */
-  TREE_OPERAND (cond, 0) = cvar_base;
+  /* Emit GIMPLE_OMP_FOR.  */
+  gimple_cond_set_lhs (cond_stmt, cvar_base);
   type = TREE_TYPE (cvar);
   t = build_omp_clause (OMP_CLAUSE_SCHEDULE);
   OMP_CLAUSE_SCHEDULE_KIND (t) = OMP_CLAUSE_SCHEDULE_STATIC;
 
-  for_stmt = make_node (OMP_FOR);
-  TREE_TYPE (for_stmt) = void_type_node;
-  OMP_FOR_CLAUSES (for_stmt) = t;
-  OMP_FOR_INIT (for_stmt) = make_tree_vec (1);
-  TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), 0)
-    = build_gimple_modify_stmt (initvar, cvar_init);
-  OMP_FOR_COND (for_stmt) = make_tree_vec (1);
-  TREE_VEC_ELT (OMP_FOR_COND (for_stmt), 0) = cond;
-  OMP_FOR_INCR (for_stmt) = make_tree_vec (2);
-  TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), 0)
-    = build_gimple_modify_stmt (cvar_base,
-				build2 (PLUS_EXPR, type, cvar_base,
-					build_int_cst (type, 1)));
-  OMP_FOR_BODY (for_stmt) = NULL_TREE;
-  OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
+  for_stmt = gimple_build_omp_for (NULL, t, 1, NULL);
+  gimple_omp_for_set_index (for_stmt, 0, initvar);
+  gimple_omp_for_set_initial (for_stmt, 0, cvar_init);
+  gimple_omp_for_set_final (for_stmt, 0, gimple_cond_rhs (cond_stmt));
+  gimple_omp_for_set_cond (for_stmt, 0, gimple_cond_code (cond_stmt));
+  gimple_omp_for_set_incr (for_stmt, 0, build2 (PLUS_EXPR, type,
+						cvar_base,
+						build_int_cst (type, 1)));
 
-  bsi = bsi_last (for_bb);
-  bsi_insert_after (&bsi, for_stmt, BSI_NEW_STMT);
+  gsi = gsi_last_bb (for_bb);
+  gsi_insert_after (&gsi, for_stmt, GSI_NEW_STMT);
   SSA_NAME_DEF_STMT (initvar) = for_stmt;
 
-  /* Emit OMP_CONTINUE.  */
-  bsi = bsi_last (loop->latch);
-  t = build2 (OMP_CONTINUE, void_type_node, cvar_next, cvar);
-  bsi_insert_after (&bsi, t, BSI_NEW_STMT);
-  SSA_NAME_DEF_STMT (cvar_next) = t;
-
-  /* Emit OMP_RETURN for OMP_FOR.  */
-  bsi = bsi_last (ex_bb);
-  t = make_node (OMP_RETURN);
-  OMP_RETURN_NOWAIT (t) = 1;
-  bsi_insert_after (&bsi, t, BSI_NEW_STMT);
+  /* Emit GIMPLE_OMP_CONTINUE.  */
+  gsi = gsi_last_bb (loop->latch);
+  stmt = gimple_build_omp_continue (cvar_next, cvar);
+  gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+  SSA_NAME_DEF_STMT (cvar_next) = stmt;
+
+  /* Emit GIMPLE_OMP_RETURN for GIMPLE_OMP_FOR.  */
+  gsi = gsi_last_bb (ex_bb);
+  gsi_insert_after (&gsi, gimple_build_omp_return (true), GSI_NEW_STMT);
 
   return paral_bb;
 }
@@ -1665,7 +1659,8 @@ gen_parallel_loop (struct loop *loop, ht
   struct loop *nloop;
   loop_iterator li;
   tree many_iterations_cond, type, nit;
-  tree stmts, arg_struct, new_arg_struct;
+  tree arg_struct, new_arg_struct;
+  gimple_seq stmts;
   basic_block parallel_head;
   edge entry, exit;
   struct clsn_data clsn_data;
@@ -1695,14 +1690,14 @@ gen_parallel_loop (struct loop *loop, ht
 
      BODY1;
      store all local loop-invariant variables used in body of the loop to DATA.
-     OMP_PARALLEL (OMP_CLAUSE_NUM_THREADS (N_THREADS), LOOPFN, DATA);
+     GIMPLE_OMP_PARALLEL (OMP_CLAUSE_NUM_THREADS (N_THREADS), LOOPFN, DATA);
      load the variables from DATA.
-     OMP_FOR (IV = INIT; COND; IV += STEP) (OMP_CLAUSE_SCHEDULE (static))
+     GIMPLE_OMP_FOR (IV = INIT; COND; IV += STEP) (OMP_CLAUSE_SCHEDULE (static))
      BODY2;
      BODY1;
-     OMP_CONTINUE;
-     OMP_RETURN         -- OMP_FOR
-     OMP_RETURN         -- OMP_PARALLEL
+     GIMPLE_OMP_CONTINUE;
+     GIMPLE_OMP_RETURN         -- GIMPLE_OMP_FOR
+     GIMPLE_OMP_RETURN         -- GIMPLE_OMP_PARALLEL
      goto end;
 
      original:
@@ -1728,7 +1723,7 @@ gen_parallel_loop (struct loop *loop, ht
   nit = force_gimple_operand (unshare_expr (niter->niter), &stmts, true,
 			      NULL_TREE);
   if (stmts)
-    bsi_insert_on_edge_immediate (loop_preheader_edge (loop), stmts);
+    gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);
 
   many_iterations_cond =
     fold_build2 (GE_EXPR, boolean_type_node,
@@ -1740,14 +1735,14 @@ gen_parallel_loop (struct loop *loop, ht
   many_iterations_cond
     = force_gimple_operand (many_iterations_cond, &stmts, false, NULL_TREE);
   if (stmts)
-    bsi_insert_on_edge_immediate (loop_preheader_edge (loop), stmts);
+    gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);
   if (!is_gimple_condexpr (many_iterations_cond))
     {
       many_iterations_cond
 	= force_gimple_operand (many_iterations_cond, &stmts,
 				true, NULL_TREE);
       if (stmts)
-	bsi_insert_on_edge_immediate (loop_preheader_edge (loop), stmts);
+	gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);
     }
 
   initialize_original_copy_tables ();
@@ -1812,12 +1807,12 @@ loop_has_vector_phi_nodes (struct loop *
 {
   unsigned i;
   basic_block *bbs = get_loop_body_in_dom_order (loop);
+  gimple_stmt_iterator gsi;
   bool res = true;
-  tree phi;
 
   for (i = 0; i < loop->num_nodes; i++)
-    for (phi = phi_nodes (bbs[i]); phi; phi = PHI_CHAIN (phi))
-      if (TREE_CODE (TREE_TYPE (PHI_RESULT (phi))) == VECTOR_TYPE)
+    for (gsi = gsi_start_phis (bbs[i]); !gsi_end_p (gsi); gsi_next (&gsi))
+      if (TREE_CODE (TREE_TYPE (PHI_RESULT (gsi_stmt (gsi)))) == VECTOR_TYPE)
 	goto end;
 
   res = false;
@@ -1825,7 +1820,6 @@ loop_has_vector_phi_nodes (struct loop *
   free (bbs);
   return res;
 }
-#endif
 
 /* Detect parallel loops and generate parallel code using libgomp
    primitives.  Returns true if some loop was parallelized, false
@@ -1834,8 +1828,6 @@ loop_has_vector_phi_nodes (struct loop *
 bool
 parallelize_loops (void)
 {
-  /* FIXME tuples.  */
-#if 0
   unsigned n_threads = flag_tree_parallelize_loops;
   bool changed = false;
   struct loop *loop;
@@ -1849,6 +1841,7 @@ parallelize_loops (void)
 
   reduction_list = htab_create (10, reduction_info_hash,
                                 reduction_info_eq, free);
+  init_stmt_vec_info_htab ();
 
   FOR_EACH_LOOP (li, loop, 0)
     {
@@ -1873,12 +1866,9 @@ parallelize_loops (void)
       verify_loop_closed_ssa ();
     }
 
+  free_stmt_vec_info_htab ();
   htab_delete (reduction_list);
   return changed;
-#else
-  gimple_unreachable ();
-  return false;
-#endif
 }
 
 #include "gt-tree-parloops.h"
--- gcc/tree-cfg.c.jj	2008-06-13 14:30:50.000000000 +0200
+++ gcc/tree-cfg.c	2008-07-01 14:30:51.000000000 +0200
@@ -5041,8 +5041,6 @@ gimple_duplicate_sese_tail (edge entry A
 			  basic_block *region ATTRIBUTE_UNUSED, unsigned n_region ATTRIBUTE_UNUSED,
 			  basic_block *region_copy ATTRIBUTE_UNUSED)
 {
-  /* FIXME tuples.  */
-#if 0
   unsigned i;
   bool free_region_copy = false;
   struct loop *loop = exit->dest->loop_father;
@@ -5052,8 +5050,8 @@ gimple_duplicate_sese_tail (edge entry A
   int total_freq = 0, exit_freq = 0;
   gcov_type total_count = 0, exit_count = 0;
   edge exits[2], nexits[2], e;
-  block_stmt_iterator bsi;
-  tree cond;
+  gimple_stmt_iterator gsi;
+  gimple cond_stmt;
   edge sorig, snew;
 
   gcc_assert (EDGE_COUNT (exit->src->succs) == 2);
@@ -5142,10 +5140,13 @@ gimple_duplicate_sese_tail (edge entry A
     switch_bb = split_edge (entry);
   set_immediate_dominator (CDI_DOMINATORS, nentry_bb, switch_bb);
 
-  bsi = bsi_last (switch_bb);
-  cond = last_stmt (exit->src);
-  gcc_assert (TREE_CODE (cond) == COND_EXPR);
-  bsi_insert_after (&bsi, unshare_expr (cond), BSI_NEW_STMT);
+  gsi = gsi_last_bb (switch_bb);
+  cond_stmt = last_stmt (exit->src);
+  gcc_assert (gimple_code (cond_stmt) == GIMPLE_COND);
+  cond_stmt = gimple_copy (cond_stmt);
+  gimple_cond_set_lhs (cond_stmt, unshare_expr (gimple_cond_lhs (cond_stmt)));
+  gimple_cond_set_rhs (cond_stmt, unshare_expr (gimple_cond_rhs (cond_stmt)));
+  gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
 
   sorig = single_succ_edge (switch_bb);
   sorig->flags = exits[1]->flags;
@@ -5160,9 +5161,9 @@ gimple_duplicate_sese_tail (edge entry A
   /* Get rid of now superfluous conditions and associated edges (and phi node
      arguments).  */
   e = redirect_edge_and_branch (exits[0], exits[1]->dest);
-  PENDING_STMT (e) = NULL_TREE;
+  PENDING_STMT (e) = NULL;
   e = redirect_edge_and_branch (nexits[1], nexits[0]->dest);
-  PENDING_STMT (e) = NULL_TREE;
+  PENDING_STMT (e) = NULL;
 
   /* Anything that is outside of the region, but was dominated by something
      inside needs to update dominance info.  */
@@ -5177,10 +5178,6 @@ gimple_duplicate_sese_tail (edge entry A
 
   free_original_copy_tables ();
   return true;
-#else
-  gimple_unreachable ();
-  return false;
-#endif
 }
 
 /* Add all the blocks dominated by ENTRY to the array BBS_P.  Stop
@@ -5477,7 +5474,7 @@ move_block_to_fn (struct function *dest_
                bb->index, bb);
 
   /* Remap the variables in phi nodes.  */
-  for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+  for (si = gsi_start_phis (bb); !gsi_end_p (si); )
     {
       gimple phi = gsi_stmt (si);
       use_operand_p use;
@@ -5499,6 +5496,8 @@ move_block_to_fn (struct function *dest_
 	  if (TREE_CODE (op) == SSA_NAME)
 	    SET_USE (use, replace_ssa_name (op, vars_map, dest_cfun->decl));
 	}
+
+      gsi_next (&si);
     }
 
   /* The statements in BB need to be associated with a new TREE_BLOCK.

	Jakub



More information about the Gcc-patches mailing list