Example #1
0
static unsigned int
tree_ssa_loop_init (void)
{
  loop_optimizer_init (LOOPS_NORMAL
		       | LOOPS_HAVE_RECORDED_EXITS);
  rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);

  if (number_of_loops () <= 1)
    return 0;

  scev_initialize ();
  return 0;
}
Example #2
0
static struct loops *
tree_loop_optimizer_init (void)
{
  struct loops *loops;
 
  loops = loop_optimizer_init (LOOPS_NORMAL
			       | LOOPS_HAVE_MARKED_SINGLE_EXITS);

  if (!loops)
    return NULL;

  rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);

  return loops;
}
Example #3
0
static unsigned int
tree_ssa_loop_init (void)
{
  loop_optimizer_init (LOOPS_NORMAL
		       | LOOPS_HAVE_RECORDED_EXITS);
  rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);

  /* We might discover new loops, e.g. when turning irreducible
     regions into reducible.  */
  scev_initialize ();

  if (number_of_loops (cfun) <= 1)
    return 0;

  return 0;
}
Example #4
0
void
linear_transform_loops (struct loops *loops)
{
  unsigned int i;
  
  compute_immediate_uses (TDFA_USE_OPS | TDFA_USE_VOPS, NULL);
  for (i = 1; i < loops->num; i++)
    {
      unsigned int depth = 0;
      varray_type datarefs;
      varray_type dependence_relations;
      struct loop *loop_nest = loops->parray[i];
      struct loop *temp;
      VEC (tree) *oldivs = NULL;
      VEC (tree) *invariants = NULL;
      lambda_loopnest before, after;
      lambda_trans_matrix trans;
      bool problem = false;
      bool need_perfect_nest = false;
      /* If it's not a loop nest, we don't want it.
         We also don't handle sibling loops properly, 
         which are loops of the following form:
         for (i = 0; i < 50; i++)
           {
             for (j = 0; j < 50; j++)
               {
	        ...
               }
           for (j = 0; j < 50; j++)
               {
                ...
               }
           } */
      if (!loop_nest->inner)
	continue;
      depth = 1;
      for (temp = loop_nest->inner; temp; temp = temp->inner)
	{
	  flow_loop_scan (temp, LOOP_ALL);
	  /* If we have a sibling loop or multiple exit edges, jump ship.  */
	  if (temp->next || temp->num_exits != 1)
	    {
	      problem = true;
	      break;
	    }
	  depth ++;
	}
      if (problem)
	continue;

      /* Analyze data references and dependence relations using scev.  */      
 
      VARRAY_GENERIC_PTR_INIT (datarefs, 10, "datarefs");
      VARRAY_GENERIC_PTR_INIT (dependence_relations, 10,
			       "dependence_relations");
      
  
      compute_data_dependences_for_loop (depth, loop_nest,
					 &datarefs, &dependence_relations);
      if (dump_file && (dump_flags & TDF_DETAILS))
	{
	  unsigned int j;
	  for (j = 0; j < VARRAY_ACTIVE_SIZE (dependence_relations); j++)
	    {
	      struct data_dependence_relation *ddr = 
		(struct data_dependence_relation *) 
		VARRAY_GENERIC_PTR (dependence_relations, j);

	      if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
		{
		  fprintf (dump_file, "DISTANCE_V (");
		  print_lambda_vector (dump_file, DDR_DIST_VECT (ddr), 
				       DDR_SIZE_VECT (ddr));
		  fprintf (dump_file, ")\n");
		  fprintf (dump_file, "DIRECTION_V (");
		  print_lambda_vector (dump_file, DDR_DIR_VECT (ddr), 
				       DDR_SIZE_VECT (ddr));
		  fprintf (dump_file, ")\n");
		}
	    }
	  fprintf (dump_file, "\n\n");
	}
      /* Build the transformation matrix.  */
      trans = lambda_trans_matrix_new (depth, depth);
      lambda_matrix_id (LTM_MATRIX (trans), depth);

      trans = try_interchange_loops (trans, depth, dependence_relations,
				     datarefs, loop_nest);

      if (lambda_trans_matrix_id_p (trans))
	{
	  if (dump_file)
	   fprintf (dump_file, "Won't transform loop. Optimal transform is the identity transform\n");
	  continue;
	}

      /* Check whether the transformation is legal.  */
      if (!lambda_transform_legal_p (trans, depth, dependence_relations))
	{
	  if (dump_file)
	    fprintf (dump_file, "Can't transform loop, transform is illegal:\n");
	  continue;
	}
      if (!perfect_nest_p (loop_nest))
	need_perfect_nest = true;
      before = gcc_loopnest_to_lambda_loopnest (loops,
						loop_nest, &oldivs, 
						&invariants,
						need_perfect_nest);
      if (!before)
	continue;
            
      if (dump_file)
	{
	  fprintf (dump_file, "Before:\n");
	  print_lambda_loopnest (dump_file, before, 'i');
	}
  
      after = lambda_loopnest_transform (before, trans);
      if (dump_file)
	{
	  fprintf (dump_file, "After:\n");
	  print_lambda_loopnest (dump_file, after, 'u');
	}
      lambda_loopnest_to_gcc_loopnest (loop_nest, oldivs, invariants,
				       after, trans);
      if (dump_file)
	fprintf (dump_file, "Successfully transformed loop.\n");
      oldivs = NULL;
      invariants = NULL;
      free_dependence_relations (dependence_relations);
      free_data_refs (datarefs);
    }
  free_df ();
  scev_reset ();
  rewrite_into_loop_closed_ssa ();
#ifdef ENABLE_CHECKING
  verify_loop_closed_ssa ();
#endif
}
static void
copy_loop_headers (void)
{
  struct loops *loops;
  unsigned i;
  struct loop *loop;
  basic_block header;
  edge exit;
  basic_block *bbs;
  unsigned n_bbs;

  loops = loop_optimizer_init (dump_file);
  if (!loops)
    return;
  rewrite_into_loop_closed_ssa ();
  
  /* We do not try to keep the information about irreducible regions
     up-to-date.  */
  loops->state &= ~LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS;

#ifdef ENABLE_CHECKING
  verify_loop_structure (loops);
#endif

  bbs = xmalloc (sizeof (basic_block) * n_basic_blocks);

  for (i = 1; i < loops->num; i++)
    {
      /* Copy at most 20 insns.  */
      int limit = 20;

      loop = loops->parray[i];
      if (!loop)
	continue;
      header = loop->header;

      /* If the loop is already a do-while style one (either because it was
	 written as such, or because jump threading transformed it into one),
	 we might be in fact peeling the first iteration of the loop.  This
	 in general is not a good idea.  */
      if (do_while_loop_p (loop))
	continue;

      /* Iterate the header copying up to limit; this takes care of the cases
	 like while (a && b) {...}, where we want to have both of the conditions
	 copied.  TODO -- handle while (a || b) - like cases, by not requiring
	 the header to have just a single successor and copying up to
	 postdominator.  */

      exit = NULL;
      n_bbs = 0;
      while (should_duplicate_loop_header_p (header, loop, &limit))
	{
	  /* Find a successor of header that is inside a loop; i.e. the new
	     header after the condition is copied.  */
	  if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest))
	    exit = EDGE_SUCC (header, 0);
	  else
	    exit = EDGE_SUCC (header, 1);
	  bbs[n_bbs++] = header;
	  header = exit->dest;
	}

      if (!exit)
	continue;

      if (dump_file && (dump_flags & TDF_DETAILS))
	fprintf (dump_file,
		 "Duplicating header of the loop %d up to edge %d->%d.\n",
		 loop->num, exit->src->index, exit->dest->index);

      /* Ensure that the header will have just the latch as a predecessor
	 inside the loop.  */
      if (EDGE_COUNT (exit->dest->preds) > 1)
	exit = EDGE_SUCC (loop_split_edge_with (exit, NULL), 0);

      if (!tree_duplicate_sese_region (loop_preheader_edge (loop), exit,
				       bbs, n_bbs, NULL))
	{
	  fprintf (dump_file, "Duplication failed.\n");
	  continue;
	}

      /* Ensure that the latch and the preheader is simple (we know that they
	 are not now, since there was the loop exit condition.  */
      loop_split_edge_with (loop_preheader_edge (loop), NULL);
      loop_split_edge_with (loop_latch_edge (loop), NULL);
    }

  free (bbs);

#ifdef ENABLE_CHECKING
  verify_loop_closed_ssa ();
#endif

  loop_optimizer_finalize (loops, NULL);
}
Example #6
0
unsigned
vectorize_loops (void)
{
    unsigned int i;
    unsigned int num_vectorized_loops = 0;
    unsigned int vect_loops_num;
    loop_iterator li;
    struct loop *loop;

    vect_loops_num = number_of_loops (cfun);

    /* Bail out if there are no loops.  */
    if (vect_loops_num <= 1)
        return 0;

    init_stmt_vec_info_vec ();

    /*  ----------- Analyze loops. -----------  */

    /* If some loop was duplicated, it gets bigger number
       than all previously defined loops.  This fact allows us to run
       only over initial loops skipping newly generated ones.  */
    FOR_EACH_LOOP (li, loop, 0)
    if (optimize_loop_nest_for_speed_p (loop))
    {
        loop_vec_info loop_vinfo;
        vect_location = find_loop_location (loop);
        if (LOCATION_LOCUS (vect_location) != UNKNOWN_LOC
                && dump_enabled_p ())
            dump_printf (MSG_NOTE, "\nAnalyzing loop at %s:%d\n",
                         LOC_FILE (vect_location), LOC_LINE (vect_location));

        loop_vinfo = vect_analyze_loop (loop);
        loop->aux = loop_vinfo;

        if (!loop_vinfo || !LOOP_VINFO_VECTORIZABLE_P (loop_vinfo))
            continue;

        if (LOCATION_LOCUS (vect_location) != UNKNOWN_LOC
                && dump_enabled_p ())
            dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
                             "Vectorized loop\n");
        vect_transform_loop (loop_vinfo);
        num_vectorized_loops++;
    }

    vect_location = UNKNOWN_LOC;

    statistics_counter_event (cfun, "Vectorized loops", num_vectorized_loops);
    if (dump_enabled_p ()
            || (num_vectorized_loops > 0 && dump_enabled_p ()))
        dump_printf_loc (MSG_NOTE, vect_location,
                         "vectorized %u loops in function.\n",
                         num_vectorized_loops);

    /*  ----------- Finalize. -----------  */

    for (i = 1; i < vect_loops_num; i++)
    {
        loop_vec_info loop_vinfo;

        loop = get_loop (cfun, i);
        if (!loop)
            continue;
        loop_vinfo = (loop_vec_info) loop->aux;
        destroy_loop_vec_info (loop_vinfo, true);
        loop->aux = NULL;
    }

    free_stmt_vec_info_vec ();

    if (num_vectorized_loops > 0)
    {
        /* If we vectorized any loop only virtual SSA form needs to be updated.
        ???  Also while we try hard to update loop-closed SSA form we fail
         to properly do this in some corner-cases (see PR56286).  */
        rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa_only_virtuals);
        return TODO_cleanup_cfg;
    }

    return 0;
}