Beispiel #1
0
void
Ltahoe_estimate_liveness (L_Func *fn, char *str)
{
  L_Cb *cb;
  L_Oper *op;
  L_Attr *attr;
  int liveness, oplive;

  L_do_flow_analysis (fn, LIVE_VARIABLE);

  for (cb = fn->first_cb; cb; cb = cb->next_cb)
    {
      liveness = Set_size (L_get_cb_IN_set (cb));
      for (op = cb->first_op; op; op = op->next_op)
	{
	  oplive = Set_size (L_get_oper_IN_set (op));

	  if (oplive > liveness)
	    liveness = oplive;
	}
      attr = L_new_attr (str, 1);
      L_set_int_attr_field (attr, 0, liveness);
      cb->attr = L_concat_attr (cb->attr, attr);
    }
 
  return;
}
int
L_loadstore_union_postdominates_amb (L_Func * fn, L_Cb * cb, L_Oper * oper,
                                     Set LDST, Set AMB)
{
  int i, size;
  int *buf;
  L_Cb *def_cb;
  Set pd_cbset;
  int val = 0;

  pd_cbset = NULL;


  /* Convert RDEF is a set of cbs */
  size = Set_size (LDST);
  if (!size)
    return 0;

  buf = (int *) Lcode_malloc (sizeof (int) * size);
  Set_2array (LDST, buf);
  for (i = 0; i < size; i++)
    {
      def_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]);

      pd_cbset = Set_add (pd_cbset, def_cb->id);
    }
  Lcode_free (buf);


  /* Foreach cb in AMB, Does pd_cbset post_dominate it */
  size = Set_size (AMB);
  if (!size)
    return 1;

  buf = (int *) Lcode_malloc (sizeof (int) * size);
  Set_2array (AMB, buf);
  for (i = 0; i < size; i++)
    {
      def_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]);

      val = L_cb_set_dominates (fn, def_cb, cb, pd_cbset);
      if (!val)
        break;
    }

  Lcode_free (buf);
  pd_cbset = Set_dispose (pd_cbset);

  return val;
}
int
L_load_postdominates_each_store (L_Func * fn, L_Cb * cb, L_Oper * oper,
                                 Set RDEF)
{
  int i, size;
  int *buf;
  L_Cb *use_cb;

  size = Set_size (RDEF);
  if (!size)
    return 0;

  buf = (int *) Lcode_malloc (sizeof (int) * size);
  Set_2array (RDEF, buf);

  for (i = 0; i < size; i++)
    {
      use_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]);

      if (!(L_in_cb_PDOM_set (use_cb, cb->id)))
        return 0;
    }
  Lcode_free (buf);

  return 1;
}
Beispiel #4
0
static int
LB_functionally_equivalent_cbs (Set cb_set)
{
  L_Cb *cb1, *cb2;
  int num_cb, *cb_array, i, equiv;

  num_cb = Set_size (cb_set);
  if (num_cb <= 1)
    return (1);

  cb_array = (int *) Lcode_malloc (sizeof (int) * num_cb);
  Set_2array (cb_set, cb_array);

  if (!(cb1 = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, cb_array[0])))
    L_punt ("LB_functionally_equivalent_cbs: corrupt cb_set");

  equiv = 1;
  for (i = 1; i < num_cb; i++)
    {
      if (!(cb2 = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, cb_array[i])))
	L_punt ("LB_functionally_equivalent_cbs: corrupt cb_set");
      if (!LB_are_equivalent_cbs (cb1, cb2))
	{
	  equiv = 0;
	  break;
	}
    }

  Lcode_free (cb_array);

  return (equiv);
}
int
L_store_union_dominates_load (L_Func * fn, L_Cb * cb, L_Oper * oper, Set RDEF)
{
  int i, size;
  int *buf;
  L_Cb *def_cb, *start;
  Set cbset;
  int val;

  cbset = NULL;
  /* start needs to dominate all nodes in function */
  start = fn->first_cb;

  /* Convert RDEF is a set of cbs */
  size = Set_size (RDEF);
  if (!size)
    return 0;

  buf = (int *) Lcode_malloc (sizeof (int) * size);
  Set_2array (RDEF, buf);
  for (i = 0; i < size; i++)
    {
      def_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]);

      cbset = Set_add (cbset, def_cb->id);
    }
  Lcode_free (buf);

  /* Does cbset dominate cb from start */
  val = L_cb_set_dominates (fn, start, cb, cbset);
  cbset = Set_dispose (cbset);

  return val;
}
int
L_load_compatible_each_load (L_Func * fn, L_Oper * oper, Set RDEF)
{
  int i, size;
  int *buf;
  L_Oper *use_op;

  size = Set_size (RDEF);
  if (!size)
    return 0;

  buf = (int *) Lcode_malloc (sizeof (int) * size);
  Set_2array (RDEF, buf);

  for (i = 0; i < size; i++)
    {
      use_op = L_oper_hash_tbl_find_oper (fn->oper_hash_tbl, buf[i]);

      if (!L_same_opcode (oper, use_op))
        return 0;
    }
  Lcode_free (buf);

  return 1;
}
Beispiel #7
0
static int
M_does_operand_contain_label_addr (L_Oper * oper,
				   L_Operand * operand, int *reaching_df_done)
{
  L_Oper *def_oper;
  Set def_set;
  int num_defs, *def_buf;
  int i, value = FALSE;

  if (!L_is_macro (operand))
    {
      def_set = L_get_reaching_defs (operand, oper, reaching_df_done);

      if (def_set)
	{
	  value = TRUE;
	  num_defs = Set_size (def_set);
	  def_buf = (int *) Lcode_malloc (sizeof (int) * (num_defs + 1));
	  (void) Set_2array (def_set, def_buf);

	  for (i = 0; i < num_defs; i++)
	    {
	      def_oper = L_oper_hash_tbl_find_oper (L_fn->oper_hash_tbl,
						    def_buf[i]);
	      if (def_oper->proc_opc != TAHOEop_MOVL)
		{
		  value = FALSE;
		  break;
		}		/* if */
	    }			/* for i */
	  Lcode_free (def_buf);
	}			/* if */
    }				/* if */
  return (value);
}				/* M_does_operand_contain_label_addr */
Beispiel #8
0
void
PSS_PrintLoops(PC_Loop pcloop)
{
    int *bbs;
    int bb_count, i;

    for (; pcloop; pcloop = pcloop->sibling)
    {
        fprintf(debug_file_id, "-");

        PSS_PrintLoops(pcloop->child);

        fprintf(debug_file_id, "Loop %d: ", pcloop->ID);

        bbs = (int *) calloc (Set_size (pcloop->body), sizeof (int));
        bb_count = Set_2array (pcloop->body, bbs);

        for (i = 0; i < bb_count; i++)
            fprintf(debug_file_id, "%d ", bbs[i]);

        fprintf(debug_file_id, "\n");

        free(bbs);
    }
}
Beispiel #9
0
void
LB_elim_all_loop_backedges (L_Func * fn)
{
  int loop_count;
  L_Loop *loop;
  Set loop_done;

  /* count how many loops there are */
  loop_count = 0;
  for (loop = fn->first_loop; loop; loop = loop->next_loop)
    loop_count++;

  /* inner most to outer */
  loop_done = NULL;
  while (Set_size (loop_done) < loop_count)
    {
      for (loop = fn->first_loop; loop; loop = loop->next_loop)
	{
	  if (Set_in (loop_done, loop->id))
	    continue;
	  if (!Set_subtract_empty (loop->nested_loops, loop_done))
	    continue;
	  loop_done = Set_add (loop_done, loop->id);

	  LB_elim_loop_backedges (fn, loop);
	}
    }

  Set_dispose (loop_done);
}
Beispiel #10
0
int
LB_hb_jsr_in_cb_set (Set cb_set)
{
  int i, num_jsr, num_cb, *cb_array;
  L_Cb *cb;
  L_Oper *oper;

  num_cb = Set_size (cb_set);
  if (num_cb <= 0)
    return (0);

  cb_array = (int *) alloca (sizeof (int) * num_cb);
  Set_2array (cb_set, cb_array);

  num_jsr = 0;
  for (i = 0; i < num_cb; i++)
    {
      if (!(cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, cb_array[i])))
	L_punt ("LB_hb_jsr_in_cb_set: corrupt cb_set");
      for (oper = cb->first_op; oper != NULL; oper = oper->next_op)
	if (L_subroutine_call_opcode (oper))
	  num_jsr++;
    }

  return (num_jsr > 0);
}
Beispiel #11
0
int main(int argc, char* argv[]) {
    Set s = Set_new();
    int   a = 42;
    char* b = "hello";
    assert(Set_size(s) == 0);
    Set_show(s, stdout, &show_func);
    Set_add(s, &a);
    assert(Set_size(s) == 1);
    Set_show(s, stdout, &show_func);
    Set_add(s, b);
    assert(Set_size(s) == 2);
    Set_show(s, stdout, &show_func);
    Set_remove(s, b);
    assert(Set_size(s) == 1);
    Set_show(s, stdout, &show_func);
    Set_remove(s, b);
    assert(Set_size(s) == 1);
    Set_show(s, stdout, &show_func);

    fprintf(stdout, "All tests passed!\n");
}
Beispiel #12
0
static void
LB_combine_equivalent_backedges (L_Loop * loop)
{
  int num_back_edge, *back_edge_array, i;
  L_Cb *cb, *keep_cb, *src_cb;
  L_Flow *src_flow, *next_flow;

  num_back_edge = Set_size (loop->back_edge_cb);
  if (num_back_edge <= 1)
    return;
  back_edge_array = (int *) alloca (sizeof (int) * num_back_edge);
  Set_2array (loop->back_edge_cb, back_edge_array);

  /* pick the one with the largest weight to keep */

  if (!(keep_cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, back_edge_array[0])))
    L_punt ("LB_combine_equivalent_backedges: corrupt backedge cbs");

  for (i = 1; i < num_back_edge; i++)
    {
      if (!(cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, back_edge_array[i])))
	L_punt ("LB_combine_equivalent_backedges: corrupt backedge cbs");

      if (cb->weight > keep_cb->weight)
	keep_cb = cb;
    }

#ifdef DEBUG
  fprintf (stderr, "keeping cb %d for equivalent Backedge combining\n",
	   keep_cb->id);
#endif

  for (i = 0; i < num_back_edge; i++)
    {
      cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, back_edge_array[i]);
      if (cb == keep_cb)
	continue;
      for (src_flow = cb->src_flow; src_flow; src_flow = next_flow)
	{
	  next_flow = src_flow->next_flow;
	  src_cb = src_flow->src_cb;
	  LB_reconnect_blocks (src_cb, cb, keep_cb);
	}
    }

  L_rebuild_src_flow (L_fn);
  return;
}
Beispiel #13
0
/*
 * LB_hb_region_contains_cycle
 * ----------------------------------------------------------------------
 * Given a set of CB ids and a header CB, return 1 iff the region
 * contains a cycle which does not include the header; 0 otherwise.
 */
int
LB_hb_region_contains_cycle (Set blocks, L_Cb * header)
{
  int i, num_cb, *buf, cycle = 0;
  L_Cb *cb;

  num_cb = Set_size (blocks);
  buf = (int *) alloca (sizeof (int) * num_cb);
  Set_2array (blocks, buf);

  for (i = 0; i < num_cb; i++)
    {
      cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, buf[i]);
      cb->flags = L_CLR_BIT_FLAG (cb->flags, L_CB_VISITED);
      cb->flags = L_CLR_BIT_FLAG (cb->flags, L_CB_VISITED2);
    }

  if (dfs_visit (header, blocks, header))
    {
      cycle = 1;
    }
  else
    {
      for (i = 0; i < num_cb; i++)
	{
	  cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, buf[i]);
	  if (L_EXTRACT_BIT_VAL (cb->flags, L_CB_VISITED))
	    continue;
	  if (dfs_visit (cb, blocks, header))
	    {
	      cycle = 1;
	      break;
	    }
	}
    }

#ifdef DEBUG_CYCLE
  if (cycle)
    fprintf (stderr, "cycle in region (header %d)\n", header->id);
#endif

  return cycle;
}
Beispiel #14
0
/* \brief determine if an expr is part of a loop
 *
 * This will search for a given expression in a loop.  This function
 * hsa two possible techniques of searching.  If the expression has
 * a expr->BB hash table entry for the cfg, then we will find the inner
 * loop associated with that BB, and simply search up the loop tree for
 * the pcloop that is passed to this function.  If the expression does
 * not have an expr->BB hash table entry, we will have to use the slower
 * algorithm that searches through all the expressions in all the BBs of
 * the loop.
 *
 * \param cfg
 *   current cfg
 * \param lp
 *   loop context to search in
 * \param find_expr
 *   expression we are searching for
 *
 * \return
 *   1 if found, 0 if not
 */
int 
PC_LoopContainsExpr (PC_Graph cfg, PC_Loop lp, Expr find_expr)
{
  PC_Block bb;
  if ((bb = PC_FindExprBB(cfg, find_expr->id)))
    {
      /* EXPR -> BB Hash worked!  O(loopnest) algo... */
      PC_Loop check_loop = bb->loop;
      if (check_loop == NULL)
	return 0;
      do
	{
	  if (check_loop == lp)
	    return 1;
	} while ((check_loop = check_loop->parent));
      return 0;
    }
  else /* doh...we have to do it the slow way */
    {
      int *bb_ids;
      int bb_ids_size, i;

      /* loop through the bb's in the loop */
      bb_ids = (int *) calloc (Set_size (lp->body), sizeof (int));
      bb_ids_size = Set_2array (lp->body, bb_ids);
      for (i = 0; i < bb_ids_size; i++)
	{
	  Expr expr;
	  _PC_ExprIter ei;
	  bb = PC_FindBlock (cfg, bb_ids[i]);

	  for (expr = PC_ExprIterFirst(bb, &ei, 1); expr;
	       expr = PC_ExprIterNext(&ei, 1))
	    {
	      if (find_expr == expr)
		return 1;
	    }
	} /* for all bb's in lp */
      /* not found... */
      return 0;
    }
}
Beispiel #15
0
static void
PC_SetBlockSetLoop (PC_Graph cfg, PC_Loop lp, Set inner)
{
  int cnt, i, *buf;
  PC_Block blk;

  if (!(cnt = Set_size (inner)))
    return;

  buf = alloca (cnt * sizeof (int));

  Set_2array (inner, buf);

  for (i = 0; i < cnt; i++)
    {
      blk = PC_FindBlock (cfg, buf[i]);
      blk->loop = lp;
    }
  return;
}
Beispiel #16
0
/* TARGAN ALGO FUNCTIONS */
static PSS_TarLoop
Initialize_Tarjan (PC_Loop pcloop)
{
    PSS_TarLoop tloop;
    int *bb_ids;
    int bb_ids_size, i;

    /* create the control structure */
    tloop = New_TarLoop(pcloop);

    /* loop through the ops in the loop and generate
     * tarnodes for each of them */
    bb_ids = (int *) calloc (Set_size (pcloop->body), sizeof (int));
    bb_ids_size = Set_2array (pcloop->body, bb_ids);
    for (i = 0; i < bb_ids_size; i++)
    {
        PC_Block bb;
        Expr expr;
        _PC_ExprIter ei;
        bb = PC_FindBlock (cfg, bb_ids[i]);

        for (expr = PC_ExprIterFirst(bb, &ei, 1); expr;
                expr = PC_ExprIterNext(&ei, 1))
        {
            /* we only care about assign ops, cause that is where
             * the action is */
#if 1
            if (expr->opcode == OP_assign && expr->operands->opcode == OP_var)
#else
            /* need to filter out meaningless phi nodes */
            if (expr->opcode == OP_assign && expr->operands->opcode == OP_var &&
                    (expr->operands->sibling->opcode != OP_phi ||
                     expr->operands->value.var.ssa->uses))
#endif
            {
                New_TarNode(tloop, expr);
            } /* if assign op */
        } /* for expr in bb */
    } /* for bb's in loop */
    return tloop;
}
Beispiel #17
0
void
LB_hb_mark_all_cbs_with_attr (Set cb_set, L_Attr * attr)
{
  int i, num_cb, *cb_array;
  L_Attr *new_attr;
  L_Cb *cb;

  if (!(num_cb = Set_size (cb_set)))
    return;
  cb_array = (int *) alloca (sizeof (int) * num_cb);
  Set_2array (cb_set, cb_array);

  for (i = 0; i < num_cb; i++)
    {
      if (!(cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, cb_array[i])))
	L_punt ("LB_hb_mark_all_cbs_with_attr: corrupt cb_set");
      if (!L_find_attr (cb->attr, attr->name))
	{
	  new_attr = L_copy_attr (attr);
	  cb->attr = L_concat_attr (cb->attr, new_attr);
	}
    }
  return;
}
Beispiel #18
0
void
L_loop_carried_dep_reduction (L_Loop *loop)
{
  /* 10/25/04 REK Commenting out unused variables to quiet compiler warnings.
   */
#if 0
  int change, j, same_cb;
  L_Sync_Info *sync_info;
#endif
  int i, num_cb, *loop_cb = NULL, num_backedge_cb, *backedge_cb =
    NULL, num_out_cb, *out_cb = NULL, increment = 0;
  L_Cb *cb, *last_cb;
  L_Oper *ind_op, *oper, *oper2, *last_use;
  L_Operand *temp, *inductor_reg, *ind_offset;

  /* setup cb array */
  num_cb = Set_size (loop->loop_cb);
  if (num_cb > 0)
    {
      loop_cb = (int *) Lcode_malloc (sizeof (int) * num_cb);
      Set_2array (loop->loop_cb, loop_cb);
    }

  /* setup backedge_cb array */
  num_backedge_cb = Set_size (loop->back_edge_cb);
  if (num_backedge_cb > 0)
    {
      backedge_cb = (int *) Lcode_malloc (sizeof (int) * num_backedge_cb);
      Set_2array (loop->back_edge_cb, backedge_cb);
    }

  /* setup out_cb array */
  num_out_cb = Set_size (loop->out_cb);
  if (num_out_cb > 0)
    {
      out_cb = (int *) Lcode_malloc (sizeof (int) * num_out_cb);
      Set_2array (loop->out_cb, out_cb);
    }

  L_find_all_ind_info (loop, loop_cb, num_cb);

  for (i = 0; i < num_cb; i++)
    {
      cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, loop_cb[i]);

      for (ind_op = cb->first_op; ind_op != NULL; ind_op = ind_op->next_op)
        {
          /*
           *  match pattern
           */
          if (!(Set_in (loop->basic_ind_var_op, ind_op->id)))
            continue;
          if (!(L_int_add_opcode (ind_op) || L_int_sub_opcode (ind_op)))
            continue;

          last_use = L_find_last_use_of_ind_var (loop, loop_cb, num_cb,
						 backedge_cb, num_backedge_cb,
						 cb, ind_op);
          if (!(L_load_opcode (last_use) || L_store_opcode (last_use)))
	    continue;
          if (L_marked_as_post_increment (last_use) ||
              L_marked_as_pre_increment (last_use))
            continue;

          /* if increment is sub, convert it to an add */
          if (L_int_sub_opcode (ind_op) && L_is_int_constant (ind_op->src[1]))
            {
              temp = ind_op->src[1];
              ind_op->src[1] = L_new_gen_int_operand (-(temp->value.i));
              L_delete_operand (temp);
              L_change_opcode (ind_op, L_corresponding_add (ind_op));
            }

	  inductor_reg = ind_op->dest[0];

	  /* Determine the increment of the inductor */
	  if (L_same_operand (inductor_reg, ind_op->src[0]))
	    increment = ind_op->src[1]->value.i;
	  else if (L_same_operand (inductor_reg, ind_op->src[1]))
	    increment = ind_op->src[0]->value.i;
	  else
	    L_punt ("assumption violated");

	  last_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, 
					     last_use->id);

	  for (oper = last_cb->first_op; oper && (oper != last_use); 
	       oper = oper->next_op)
	    {
	      if (!(L_load_opcode (oper) || L_store_opcode (oper)))
		continue;

	      if (L_same_operand (inductor_reg, oper->src[0]))
		ind_offset = oper->src[1];
	      else if (L_same_operand (inductor_reg, oper->src[1]))
		ind_offset = oper->src[0];
	      else
		continue;

	      if (L_is_int_constant (ind_offset))
		{
		  if (ind_offset != oper->src[1])
		    L_punt ("constant in src[0]");

		  /* Look for any corresponding load/store from same
		     inductor within increment */
		  for (oper2 = oper->next_op; oper2 && (oper2 != ind_op); 
		       oper2 = oper2->next_op)
		    {
		      if (!(L_load_opcode (oper2) || L_store_opcode (oper2)))
			continue;

		      if (!(L_same_operand (oper2->src[0], inductor_reg) &&
			    L_is_int_constant (oper2->src[1])))
			continue;

		      if ((increment > 0) && 
			  (oper2->src[1]->value.i >= 
			   (ind_offset->value.i + increment)))
			continue;

		      if ((increment < 0) && 
			  (oper2->src[1]->value.i <= 
			   (ind_offset->value.i + increment)))
			continue;

		      L_clear_inner_carried_flag (oper, oper2);
		    }
		}
	      else
		{
		  /* Look for any corresponding load/store with exact
		     same operands */
		  for (oper2 = oper->next_op; oper2 && (oper2 != ind_op);
		       oper2 = oper2->next_op)
		    {
		      if (!(L_load_opcode (oper2) || L_store_opcode (oper2)))
			continue;

		      if (!(L_same_operand (oper->src[0], oper2->src[0]) &&
			    L_same_operand (oper->src[1], oper2->src[1])))
			continue;

		      L_clear_inner_carried_flag (oper, oper2);
		    }
		}
	    }
        }
    }

  if (loop_cb != NULL)
    Lcode_free (loop_cb);
  if (backedge_cb != NULL)
    Lcode_free (backedge_cb);
  if (out_cb != NULL)
    Lcode_free (out_cb);
}
Beispiel #19
0
static int
O_spill_fill_around_sync (L_Func * fn, L_Cb * cb, L_Oper * op,
			  int *int_spill_start, int *int_spill_end)
{
  L_Oper *op_list;
  L_Operand *spill_reg;
  Set live_variables;
  Set live_regs;
  int *live_reg_ids;
  int num_live_regs;
  Set live_macros;
  int *live_macro_ids;
  int num_live_macros;
  int variable;
  int int_offset, fp_offset;

  int_offset = *int_spill_start;

  fp_offset = fn->s_local;

  live_variables = L_get_oper_IN_set (op);

  /* registers */
  live_regs = L_unmap_reg_set (live_variables);
  num_live_regs = Set_size (live_regs);
  live_reg_ids = calloc (num_live_regs, sizeof (int));
  Set_2array (live_regs, live_reg_ids);

  /* macros */
  live_macros = L_unmap_macro_set (live_variables);
  num_live_macros = Set_size (live_macros);
  live_macro_ids = calloc (num_live_macros, sizeof (int));
  Set_2array (live_macros, live_macro_ids);

#ifdef DEBUG
#  ifdef DEBUG1
  L_print_cb (stderr, fn, cb);
  Set_print (stderr, "Live OUT set", live_variables);
  Set_print (stderr, "Registers", live_regs);
  Set_print (stderr, "Macros", live_macros);
#  endif
  fprintf (stderr, "fp setjmp spill/fill ops: ");
#endif

  /*
   * Spill the floating point registers and macros into
   * newly-allocated local variable space
   */

  /* first spill the floating point registers */
  /* create an operand, the id of it will be altered later. */
  spill_reg = L_new_register_operand (0, L_CTYPE_DOUBLE, L_PTYPE_NULL);

  for (variable = 0; variable < num_live_regs; variable++)
    {
      if (IS_FP_REGISTER (live_reg_ids[variable]))
	{
	  spill_reg->value.r = live_reg_ids[variable];
	  op_list = O_spill_reg (live_reg_ids[variable], L_OPERAND_REGISTER,
				 spill_reg, fp_offset, NULL, R_JSR_SAVE_CODE);
	  O_insert_spill_sequence (cb, op, op_list);
	  op_list = O_fill_reg (live_reg_ids[variable], L_OPERAND_REGISTER,
				spill_reg, fp_offset, NULL, R_JSR_SAVE_CODE);
	  O_insert_fill_sequence (cb, op, op_list);
	  fp_offset += 16;
	}
    }
#ifdef DEBUG
  fprintf (stderr, "\n");
  fprintf (stderr, "fp macro setjmp spill/fill ops: ");
#endif

  /* spill the floating point macros */
  /* change the operand to a macro operand. */
  L_assign_type_float_macro (spill_reg);
  for (variable = 0; variable < num_live_macros; variable++)
    {
      if (IS_FP_MACRO_TO_SPILL (live_macro_ids[variable]))
	{
	  spill_reg->value.r = live_macro_ids[variable];
	  op_list = O_spill_reg (live_macro_ids[variable], L_OPERAND_MACRO,
				 spill_reg, fp_offset, NULL, R_JSR_SAVE_CODE);
	  O_insert_spill_sequence (cb, op, op_list);
	  op_list = O_fill_reg (live_macro_ids[variable], L_OPERAND_MACRO,
				spill_reg, fp_offset, NULL, R_JSR_SAVE_CODE);
	  O_insert_fill_sequence (cb, op, op_list);
	  fp_offset += 16;
	}
    }

#ifdef DEBUG
  fprintf (stderr, "\n");
  fprintf (stderr, "int setjmp spill/fill ops: ");
#endif

  /*
   * Spill the integer registers and macros into sync space
   */

  L_assign_type_int_register (spill_reg);
  for (variable = 0; variable < num_live_regs; variable++)
    {
      if (IS_INT_REGISTER (live_reg_ids[variable]))
	{
	  int_offset += 8;
	  spill_reg->value.r = live_reg_ids[variable];
	  op_list = O_spill_reg (live_reg_ids[variable], L_OPERAND_REGISTER,
				 spill_reg, -int_offset,
				 NULL, R_JSR_SAVE_CODE);
	  O_insert_spill_sequence (cb, op, op_list);
	  op_list = O_fill_reg (live_reg_ids[variable], L_OPERAND_REGISTER,
				spill_reg, -int_offset,
				NULL, R_JSR_SAVE_CODE);
	  O_insert_fill_sequence (cb, op, op_list);
	}
    }

#ifdef DEBUG
  fprintf (stderr, "\n");
  fprintf (stderr, "int macro setjmp spill/fill ops: ");
#endif

  L_assign_type_int_macro (spill_reg);
  for (variable = 0; variable < num_live_macros; variable++)
    {
      if (IS_INT_MACRO_TO_SPILL (live_macro_ids[variable]))
	{
	  int_offset += 8;
	  spill_reg->value.r = live_macro_ids[variable];
	  op_list = O_spill_reg (live_macro_ids[variable], L_OPERAND_MACRO,
				 spill_reg, -int_offset, NULL,
				 R_JSR_SAVE_CODE);
	  O_insert_spill_sequence (cb, op, op_list);
	  op_list = O_fill_reg (live_macro_ids[variable], L_OPERAND_MACRO,
				spill_reg, -int_offset, NULL,
				R_JSR_SAVE_CODE);
	  O_insert_fill_sequence (cb, op, op_list);
	}
    }
#ifdef DEBUG
  fprintf (stderr, "\n");
#endif

  L_delete_operand (spill_reg);

  /*
   * Put fp regs into local variable space.
   */

  L_update_local_space_size (fn, fp_offset);

  /*
   * Put int regs into sync space -- must be managed by the UNAT
   */

  if (*int_spill_start == int_offset)
    {
      /* No integers spilled */
      *int_spill_end = *int_spill_start;
      return (0);
    }
  else
    {
      *int_spill_end = int_offset;
      return (1);
    }
}
Beispiel #20
0
/*! \brief Finds loops in the CFG. Builds lp hdr, body and exit bb sets, and 
 *   puts this lp info in a PC_Loop struct, which is appended to the CFG lp list.
 *
 * \param cfg
 *  control flow graph for the func being processed
 *
 *  Multiple back edges coming into the same loop header are considered as one
 *  loop. The loop body is a union of the bodies of the loops corresponding to 
 *  each one of these back edges. 
 *
 * \return void
 */
void
PC_FindLoops (PC_Graph cfg)
{
  PC_Block h_bb;

  /* build dominator sets for each bb in the cfg */
  PC_BuildDomSets (cfg);

  /* check each cfg bb in turn to see if it's a lp header bb */
  for (h_bb = cfg->first_bb; h_bb; h_bb = h_bb->next)
    {
      PC_Flow be;
      PC_Loop *loop;
      int num_back_edge;
      int num_exit;
      int s_lp_head = -1;
      Set s_lp_body = Set_new (), s_lp_exits = Set_new ();

      /* check all edges coming into h_bb to see if they are back edges */
      num_back_edge = 0;
      for (be = h_bb->p_flow; be; be = be->p_next_flow)
	{
	  /* check to see if be is indeed a back edge */
	  if (PC_BB1DominatesBB2 (be->dest_bb, be->src_bb))
	    {
	      PC_Block bb;
	      Stack *st = New_Stack ();
	      Set lp_body = Set_new ();

              num_back_edge++;
	      s_lp_head = be->dest_bb->ID;

	      if (be->src_bb->ID == be->dest_bb->ID)
		P_warn
		  ("PC_FindNaturalLoop: back edge head & tail are same.");


	      /* Build the set of all bbs in the lp body. */
	      lp_body = Set_add (lp_body, s_lp_head);

	      if (!Set_in (lp_body, be->src_bb->ID))
		{
		  lp_body = Set_add (lp_body, be->src_bb->ID);
		  Push_Top (st, be->src_bb);
		}

	      while ((bb = Pop (st)) != ((void*)-1))
		{
		  PC_Flow fl;
		  for (fl = bb->p_flow; fl; fl = fl->p_next_flow)
		    {
		      if (!Set_in (lp_body, fl->src_bb->ID))
			{
			  lp_body = Set_add (lp_body, fl->src_bb->ID);
			  Push_Top (st, fl->src_bb);
			}
		    }
		}


	      /* the s_lp body is a union of all of these 'inner' lp bodies */
	      s_lp_body = Set_union (s_lp_body, lp_body);

	      Clear_Stack (st);
	      Set_dispose (lp_body);
	    }
	}

      /* If a loop was found, build its set of exits bbs, and append it to the 
         list of loops in the cfg. */
      if (s_lp_head != -1)
	{
	  int *s_lp_bod;
	  int lp_size = 0, i;

	  /* Build the set of all bbs that are exits out of the lp. */
	  s_lp_bod = (int *) calloc (Set_size (s_lp_body), sizeof (int));
	  lp_size = Set_2array (s_lp_body, s_lp_bod);
          num_exit = 0;
	  for (i = 0; i < lp_size; i++)
	    {
	      PC_Block bb;
	      PC_Flow fl;
	      bb = PC_FindBlock (cfg, s_lp_bod[i]);
	      for (fl = bb->s_flow; fl; fl = fl->s_next_flow)
		if (!Set_in (s_lp_body, fl->dest_bb->ID)) 
                  {
                    num_exit++;
                    s_lp_exits = Set_add (s_lp_exits, fl->dest_bb->ID);
                  }
	    }
	  free (s_lp_bod);

	  /* check for redundant loops */
	    {
	      PC_Loop lp = NULL;
	      int same = 0;
	      
	      for (lp = cfg->lp; lp; lp = lp->next)
		if (Set_same (s_lp_body, lp->body))
		  {
		    same = 1;
		    break;
		  }
	      
	      if (same)
		{
		  Set_dispose (s_lp_body);
		  Set_dispose (s_lp_exits);
		  continue;
		}
	    }

	  /* Create a new PC_Loop and append it to the current CFG
             loop list. */
	  loop = &cfg->lp;
	  while (*loop)
	    loop = &(*loop)->next;
	  *loop = PC_NewLoop (s_lp_head, s_lp_body, s_lp_exits, 
			      num_back_edge, num_exit);

	  cfg->lp_tree = PC_LoopTreeInsert (cfg->lp_tree, *loop, 1);
	}

      Set_dispose (s_lp_body);
      Set_dispose (s_lp_exits);
    }

  PC_SetBlockLoops (cfg);

  return;
}
int
L_global_memflow_multiloadstore_load (L_Func * fn, L_Cb * cb, L_Oper * oper)
{
  return 0;

#if 0
  int change = 0;
  Set RAMB_ST, RAMB_JSR;
  Set RDEF_ST, RDEF_LD;

  if (!L_general_load_opcode (oper))
    return 0;

  /* 02/07/03 REK Adding a check to make sure we don't touch a volatile
   *              oper. */
  if (L_EXTRACT_BIT_VAL (oper->flags, L_OPER_VOLATILE))
    return 0;

  RDEF_ST = NULL;
  RDEF_LD = NULL;
  RAMB_ST = NULL;
  RAMB_JSR = NULL;

  /* Get all reaching stores */
  RDEF_ST =
    L_get_mem_oper_RIN_defining_opers (oper, (MDF_RET_DEP | MDF_RET_STORES));

  /* Get all reaching loads */
  RDEF_LD =
    L_get_mem_oper_RIN_defining_opers (oper, (MDF_RET_DEP | MDF_RET_LOADS));

  if (!Set_size (RDEF_LD) || !Set_size (RDEF_ST))
    return change;


  fprintf (stderr, "\n\nMFMLSL: Examining load %d\n", oper->id);

  /* Are there any reaching, ambiguous stores */
  RAMB_ST =
    L_get_mem_oper_RIN_defining_opers (oper, (MDF_RET_AMB | MDF_RET_STORES));

  /* Are there any reaching, unsafe jsrs */
  RAMB_JSR =
    L_get_mem_oper_RIN_defining_opers (oper, (MDF_RET_AMB | MDF_RET_JSRS));

  fprintf (stderr, "MFMLSL: Dep Stores reach load %d ", oper->id);
  Set_print (stderr, "MSMLSL: ", RDEF_ST);
  fprintf (stderr, "MFMLSL: Dep Loads reach load %d ", oper->id);
  Set_print (stderr, "MSMLSL: ", RDEF_LD);
  fprintf (stderr, "MFMLSL: Amb Stores reach load %d ", oper->id);
  Set_print (stderr, "MSMLSL: ", RAMB_ST);
  fprintf (stderr, "MFMLSL: Unsafe jsrs reach load %d ", oper->id);
  Set_print (stderr, "MSMLSL: ", RAMB_JSR);

  if (!L_load_compatible_each_store (fn, oper, RDEF_ST))
    {
      fprintf (stderr, "MFMLSL: Load is incompatible with a store\n");
      Set_dispose (RDEF);
      Set_dispose (RDEF_LD);
      Set_dispose (RAMB_ST);
      Set_dispose (RAMB_JSR);
      return change;
    }

  if (!L_load_compatible_each_load (fn, oper, RDEF_LD))
    {
      fprintf (stderr, "MFMLSL: Load is incompatible with a store\n");
      Set_dispose (RDEF);
      Set_dispose (RDEF_LD);
      Set_dispose (RAMB_ST);
      Set_dispose (RAMB_JSR);
      return change;
    }

  if (!L_store_union_dominates_load
      (fn, cb, oper, Set_union (RDEF_LD, RDEF_ST)))
    {
      fprintf (stderr,
               "MFMLSL: Path to load exists not through a store/load\n");
      Set_dispose (RDEF);
      Set_dispose (RDEF_LD);
      Set_dispose (RAMB_ST);
      Set_dispose (RAMB_JSR);
      return change;
    }

  if (!L_loadstore_union_postdominates_amb (fn, cb, oper,
                                            Set_union (RDEF_LD, RDEF_ST),
                                            Set_union (RAMB_ST, RAMB_JSR)))
    {
      fprintf (stderr, "MFMLSL: A amb st/jsr lies between ld/st and load \n");
      Set_dispose (RDEF);
      Set_dispose (RDEF_LD);
      Set_dispose (RAMB_ST);
      Set_dispose (RAMB_JSR);
      return change;
    }


  /* Load can be removed, moves added */
  fprintf (stderr, "MFMLSL: red Load %d can be converted\n", oper->id);

  Set_dispose (RDEF);
  Set_dispose (RDEF_LD);
  Set_dispose (RAMB_ST);
  Set_dispose (RAMB_JSR);
  return change;
#endif
}
int
L_global_memflow_multistore_load (L_Func * fn, L_Cb * cb, L_Oper * oper)
{
  int change = 0;
  Set RAMB, RDEF;
  L_Oper *use_op, *new_op;
  L_Cb *use_cb;
  L_Operand *src, *dest;
  int i, size;
  int *buf;


  if (!L_general_load_opcode (oper))
    return 0;

  /* 02/07/03 REK Adding a check to make sure we don't touch a volatile
   *              oper. */
  if (L_EXTRACT_BIT_VAL (oper->flags, L_OPER_VOLATILE))
    return 0;

  RAMB = NULL;
  RDEF = NULL;

  /*fprintf(stderr,"MFMSL: Examining load %d\n",oper->id); */

  RDEF = L_get_mem_oper_RIN_set_rid (oper);

  /* Are there any reaching, ambiguous stores */
  RAMB =
    L_get_mem_oper_RIN_defining_opers (oper, (MDF_RET_AMB | MDF_RET_STORES));
  if (Set_size (RAMB))
    {
      Set_dispose (RAMB);
      return change;
    }

  /* Are there any reaching, unsafe jsrs */
  RAMB =
    L_get_mem_oper_RIN_defining_opers (oper, (MDF_RET_AMB | MDF_RET_JSRS));
  if (Set_size (RAMB))
    {
      Set_dispose (RAMB);
      return change;
    }

  /* Get all reaching stores */
  RDEF =
    L_get_mem_oper_RIN_defining_opers (oper, (MDF_RET_DEP | MDF_RET_STORES));
  if (!Set_size (RDEF))
    {
      return change;
    }

  /* fprintf(stderr,"MFMSL: Dep Stores reach load %d\n",oper->id);
     Set_print( stderr, "MSMSL: ", RDEF); */

  if (!L_load_compatible_each_store (fn, oper, RDEF))
    {
      /* fprintf(stderr,"MFMSL: Load is incompatible with store\n"); */
      return change;
    }

  if (!L_store_union_dominates_load (fn, cb, oper, RDEF))
    {
      /* fprintf(stderr,"MFMSL: Path to load exists not through a store\n"); */
      return change;
    }


  /* Load can be removed, moves added */
  if (Lopti_debug_memflow)
    fprintf (stderr, "MFMSL: red Load %d can be converted\n", oper->id);

  dest = L_new_register_operand (++L_fn->max_reg_id,
                                 L_return_old_ctype (oper->dest[0]),
                                 L_PTYPE_NULL);
  /* convert load to a move */
  change = 1;
  L_convert_to_extended_move (oper, L_copy_operand (oper->dest[0]), dest);

  /* add move to all stores */
  size = Set_size (RDEF);
  buf = (int *) Lcode_malloc (sizeof (int) * size);
  Set_2array (RDEF, buf);
  for (i = 0; i < size; i++)
    {
      use_op = L_oper_hash_tbl_find_oper (fn->oper_hash_tbl, buf[i]);
      use_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]);

      if (Lopti_debug_memflow)
        fprintf (stderr, "MFMSL: Converting store %d cb %d\n", use_op->id,
                 use_cb->id);

      /* change store to read from a new register */
      src = use_op->src[2];
      use_op->src[2] = L_copy_operand (dest);

      /* add new move before store */
      new_op = L_create_move_using (L_copy_operand (dest), src, use_op);
      L_insert_oper_before (use_cb, use_op, new_op);
    }
  Lcode_free (buf);

  return change;
}
Beispiel #23
0
/*! \brief Finds the natural loop corresponding to a back edge
 *
 * \param cfg
 *  control flow graph for the func being processed
 * \param be
 *  back edge going to the head of this particular natural loop
 *
 *  *** CURRENTLY NOT IN USE ***
 *
 * \return void
 */
void
PC_FindNaturalLoop (PC_Graph cfg, PC_Flow be)
{
  PC_Loop *loop = NULL;
  PC_Block bb = NULL;
  PC_Flow fl = NULL;
  Stack *st = New_Stack ();
  int lp_head = be->dest_bb->ID, lp_size = 0, i;
  int *lp_bod;
  Set lp = Set_new (), lp_exits = Set_new ();
  int num_back_edge = 0;
  int num_exit = 0;

  if (be->src_bb->ID == be->dest_bb->ID)
    P_warn ("PC_FindNaturalLoop: head and tail of back edge are same.");


  /* Build the set of all bbs in the lp body. */
  lp = Set_add (lp, lp_head);

  if (!Set_in (lp, be->src_bb->ID))
    {
      lp = Set_add (lp, be->src_bb->ID);
      Push_Top (st, be->src_bb);
    }

  while ((bb = Pop (st)) != ((void*)-1))
    {
      for (fl = bb->p_flow; fl; fl = fl->p_next_flow)
	{
	  if (!Set_in (lp, fl->src_bb->ID))
	    {
	      lp = Set_add (lp, fl->src_bb->ID);
	      Push_Top (st, fl->src_bb);
	    }
	}
    }


  /* Build the set of all bbs that are exits out of the lp. */
  lp_bod = (int *) calloc (Set_size (lp), sizeof (int));
  lp_size = Set_2array (lp, lp_bod);
  for (i = 0; i < lp_size; i++)
    {
      bb = PC_FindBlock (cfg, lp_bod[i]);
      for (fl = bb->s_flow; fl; fl = fl->s_next_flow)
	if (!Set_in (lp, fl->dest_bb->ID)) {
	  lp_exits = Set_add (lp_exits, fl->dest_bb->ID);
          num_exit++;
        }
    }
  free (lp_bod);

  /* Append this loop to the list of loops in the PC_Graph. */
  loop = &cfg->lp;
  while (*loop)
    {
      loop = &(*loop)->next;
    }
  *loop = PC_NewLoop (lp_head, lp, lp_exits, num_back_edge, num_exit);

  Set_dispose (lp);
  Set_dispose (lp_exits);
}
Beispiel #24
0
int
L_loop_check_load_for_linked_list_base (L_Loop * loop, int *pred, int *early,
                                        int *dp)
{
  int change, i, num_cb, *loop_cb = NULL, num_out_cb, *out_cb = NULL, temp;
  int base_reg_id = -2, largest_value = 1;
  Lint loaded_reg_id = 0;
  L_Cb *cb, *header;
  L_Oper *op;
  L_Attr *attr;
  INT_Symbol_Table *int_table;
  INT_Symbol *int_symbol;

  /* setup cb array */
  num_cb = Set_size (loop->loop_cb);
  if (num_cb > 0)
    {
      loop_cb = (int *) Lcode_malloc (sizeof (int) * num_cb);
      Set_2array (loop->loop_cb, loop_cb);
    }

  /* setup out_cb array */
  num_out_cb = Set_size (loop->out_cb);
  if (num_out_cb > 0)
    {
      out_cb = (int *) Lcode_malloc (sizeof (int) * num_out_cb);
      Set_2array (loop->out_cb, out_cb);
    }

  L_find_all_ind_info (loop, loop_cb, num_cb);

  header = loop->header;
  for (i = 0; i < num_cb; i++)
    {
      cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, loop_cb[i]);
      for (op = cb->first_op; op != NULL; op = op->next_op)
        {
          if (!L_load_opcode (op))
            continue;
          if (L_is_reg (op->dest[0]))
            {
              if (!InLint (loaded_reg_id, op->dest[0]->value.r))
                loaded_reg_id = AppendLint (NewLint (op->dest[0]->value.r),
                                            loaded_reg_id);
            }

          if (L_find_attr (op->attr, L_SETUP_IMPLIED_REG) ||
              L_find_attr (op->attr, L_DONT_PREDICT) ||
              L_find_attr (op->attr, L_PREDICT))
            continue;

          if ((base_reg_id == -2) && L_is_reg (op->dest[0]) &&
              L_same_operand (op->dest[0], op->src[0]))
            {
              base_reg_id = op->src[0]->value.r;
            }
        }
    }

  change = 1;

  /* BCC - 9/7/98
   * Initially, loaded_reg_id should only contain the register ids that are
   * destinations of load instructions. Here more register ids are added to
   * loaded_reg_id set if one of the instruction's source operands are loaded
   * from memory.
   */
  while (change)
    {
      change = 0;
      for (i = 0; i < num_cb; i++)
        {
          cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, loop_cb[i]);
          for (op = cb->first_op; op != NULL; op = op->next_op)
            {
              if (L_store_opcode (op))
                continue;
              if (!L_is_reg (op->dest[0]))
                continue;
              if (L_is_reg (op->src[0]))
                {
                  if (InLint (loaded_reg_id, op->src[0]->value.r) &&
                      !InLint (loaded_reg_id, op->dest[0]->value.r))
                    {
                      loaded_reg_id =
                        AppendLint (NewLint (op->dest[0]->value.r),
                                    loaded_reg_id);
                      change = 1;
                    }
                }
              if (L_is_reg (op->src[1]))
                {
                  if (InLint (loaded_reg_id, op->src[1]->value.r) &&
                      !InLint (loaded_reg_id, op->dest[0]->value.r))
                    {
                      loaded_reg_id =
                        AppendLint (NewLint (op->dest[0]->value.r),
                                    loaded_reg_id);
                      change = 1;
                    }
                }
            }
        }
    }

  /* Now, loaded_reg_id should contain all register ids whose contents are
   * loaded from memory in each iteration. If base_red_id is not set, search
   * for the largest group of load-dependent loads that use the same base
   * register. Then mark these loads as L_SETUP_IMPLIED_REG.
   */
  if (base_reg_id == -2)
    {
      int_table = INT_new_symbol_table ("src_reg_table", 32);
      for (i = 0; i < num_cb; i++)
        {
          cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, loop_cb[i]);
          for (op = cb->first_op; op != NULL; op = op->next_op)
            {
              if (!L_load_opcode (op))
                continue;
              if (L_find_attr (op->attr, L_SETUP_IMPLIED_REG) ||
                  L_find_attr (op->attr, L_DONT_PREDICT) ||
                  L_find_attr (op->attr, L_PREDICT))
                continue;
              if (L_is_reg (op->src[0]) && L_is_int_constant (op->src[1]) &&
                  InLint (loaded_reg_id, op->src[0]->value.r))
                {
                  int_symbol =
                    INT_find_symbol (int_table, op->src[0]->value.r);
                  if (int_symbol)
                    {
#ifdef LP64_ARCHITECTURE
		      temp = (int)((long)(int_symbol->data));
#else
                      temp = (int) int_symbol->data;
#endif
                      temp++;
#ifdef LP64_ARCHITECTURE
		      int_symbol->data = (void *)((long)temp);
#else
                      int_symbol->data = (void *) temp;
#endif
                    }
                  else
                    INT_add_symbol (int_table, op->src[0]->value.r,
                                    (void *) 1);
                }
            }
        }

      for (int_symbol = int_table->head_symbol;
           int_symbol; int_symbol = int_symbol->next_symbol)
        {
#ifdef LP64_ARCHITECTURE
	  if ((int)((long)(int_symbol->data)) > largest_value)
#else
          if ((int) int_symbol->data > largest_value)
#endif
            {
#ifdef LP64_ARCHITECTURE
	      largest_value = (int)((long)(int_symbol->data));
#else
              largest_value = (int) int_symbol->data;
#endif
              base_reg_id = int_symbol->value;
            }
        }
      INT_delete_symbol_table (int_table, 0);
    }

  for (i = 0; i < num_cb; i++)
    {
      cb = L_cb_hash_tbl_find (L_fn->cb_hash_tbl, loop_cb[i]);
      for (op = cb->first_op; op != NULL; op = op->next_op)
        {
          if (!L_load_opcode (op))
            continue;
          if (L_find_attr (op->attr, L_SETUP_IMPLIED_REG) ||
              L_find_attr (op->attr, L_DONT_PREDICT) ||
              L_find_attr (op->attr, L_PREDICT))
            continue;
          if (L_is_reg (op->src[0]) && L_is_int_constant (op->src[1]))
            {
              if (op->src[0]->value.r == base_reg_id)
                {
                  attr = L_new_attr (L_SETUP_IMPLIED_REG, 0);
                  op->attr = L_concat_attr (op->attr, attr);
                  (*early)++;
                }
              else if (InLint (loaded_reg_id, op->src[0]->value.r))
                {
                  attr = L_new_attr (L_DONT_PREDICT, 0);
                  op->attr = L_concat_attr (op->attr, attr);
                  (*dp)++;
                }
              else
                {
                  attr = L_new_attr (L_PREDICT, 0);
                  op->attr = L_concat_attr (op->attr, attr);
                  (*pred)++;
                }
            }
          else if ((L_is_reg (op->src[0]) &&
                    InLint (loaded_reg_id, op->src[0]->value.r)) ||
                   (L_is_reg (op->src[1]) &&
                    InLint (loaded_reg_id, op->src[1]->value.r)))
            {
              attr = L_new_attr (L_DONT_PREDICT, 0);
              op->attr = L_concat_attr (op->attr, attr);
              (*dp)++;
            }
          else
            {
              attr = L_new_attr (L_PREDICT, 0);
              op->attr = L_concat_attr (op->attr, attr);
              (*pred)++;
            }
        }
    }

  if (loop_cb != NULL)
    Lcode_free (loop_cb);
  if (out_cb != NULL)
    Lcode_free (out_cb);
  if (loaded_reg_id)
    FreeLint (loaded_reg_id);

  return change;
}
Beispiel #25
0
void
LB_elim_loop_backedges (L_Func * fn, L_Loop * loop)
{
  L_Cb *loop_header_cb = loop->header, *loop_end_cb, *cb;
  L_Flow *src_flow, *dst_flow, *back_edge_flow, *header_src_flow;
  L_Oper *oper, *branch;
  int num_back_edges, *back_edge_cb, i;

  /* We will only modify loops with more than one back edge */
  if ((num_back_edges = Set_size (loop->back_edge_cb)) <= 1)
    return;

#ifdef DEBUG
  fprintf (stderr, "Loop %d has %d backedges\n", loop->id, num_back_edges);
  Set_print (stderr, "backedges", loop->back_edge_cb);
#endif

  if (LB_functionally_equivalent_cbs (loop->back_edge_cb) &&
      !Set_in (loop->back_edge_cb, loop->header->id))
    {
#ifdef DEBUG
      fprintf (stderr, "Loop backedge cbs are equivalent!!\n");
#endif
      LB_combine_equivalent_backedges (loop);
      return;
    }

#ifdef DEBUG
  fprintf (stderr, "Loop backedge cbs are NOT equivalent!!\n");
#endif

  /* Create a cb with a back-edge to the loop header cb. */
  loop_end_cb = L_create_cb (0.0);
  header_src_flow = L_new_flow (1, loop_end_cb, loop_header_cb, 0.0);
  loop_header_cb->src_flow =
    L_concat_flow (loop_header_cb->src_flow, header_src_flow);
  back_edge_flow = L_new_flow (1, loop_end_cb, loop_header_cb, 0.0);
  loop_end_cb->dest_flow =
    L_concat_flow (loop_end_cb->dest_flow, back_edge_flow);
  L_insert_cb_after (fn, fn->last_cb, loop_end_cb);

  /* Create the jump instruction that leads to the header cb */
  oper = L_create_new_op (Lop_JUMP);
  oper->src[0] = L_new_cb_operand (loop_header_cb);
  L_insert_oper_after (loop_end_cb, loop_end_cb->first_op, oper);
#ifdef DEBUG
  fprintf (stderr, "created cb %d, placed it after cb %d\n",
	   loop_end_cb->id, loop_end_cb->prev_cb->id);
#endif

  /* 
   * Loop through all loop back-edge cbs and make them branch to the
   * to the new end loop cb.
   */

  back_edge_cb = (int *) Lcode_malloc (sizeof (int) * num_back_edges);
  Set_2array (loop->back_edge_cb, back_edge_cb);

  for (i = 0; i < num_back_edges; i++)
    {
      cb = L_cb_hash_tbl_find (fn->cb_hash_tbl, back_edge_cb[i]);

      /* 
       * Find the destination flow arc in the current cb corresponding to the 
       * loop back edge.
       */
      for (dst_flow = cb->dest_flow; dst_flow; dst_flow = dst_flow->next_flow)
	{
	  if (dst_flow->dst_cb != loop_header_cb)
	    continue;

	  /*
	   * Find the src flow arc in the loop header cb corresponding to the
	   * current back edge and delete it.
	   */
	  src_flow = L_find_flow (loop_header_cb->src_flow, dst_flow->cc,
				  dst_flow->src_cb, dst_flow->dst_cb);
	  loop_header_cb->src_flow = L_delete_flow (loop_header_cb->src_flow,
						    src_flow);

	  /* Modify the flow arc and branch target for the branch */
	  branch = L_find_branch_for_flow (cb, dst_flow);

#ifdef DEBUG
	  fprintf (stderr, "\t (cb %d) branch oper %d\n", cb->id, branch->id);
	  fprintf (stderr, "\t");
	  L_print_oper (stderr, branch);
#endif
	  if (branch)
	    {
	      L_change_branch_dest (branch, dst_flow->dst_cb, loop_end_cb);
	    }
	  else
	    {
	      L_Oper *new_op;
	      new_op = L_create_new_op (Lop_JUMP);
	      new_op->src[0] = L_new_cb_operand (loop_end_cb);
	      L_insert_oper_after (cb, cb->last_op, new_op);
	    }

	  dst_flow->dst_cb = loop_end_cb;

	  src_flow =
	    L_new_flow (dst_flow->cc, dst_flow->src_cb, dst_flow->dst_cb,
			dst_flow->weight);
	  loop_end_cb->src_flow =
	    L_concat_flow (loop_end_cb->src_flow, src_flow);
	  loop_end_cb->weight += src_flow->weight;

	  back_edge_flow->weight += src_flow->weight;
	  header_src_flow->weight += src_flow->weight;
	}
    }

  /* Add the new back-edge cb to the back edge cb list for the loop */
  loop->back_edge_cb = Set_dispose (loop->back_edge_cb);
  loop->back_edge_cb = Set_add (loop->back_edge_cb, loop_end_cb->id);
  loop->loop_cb = Set_add (loop->loop_cb, loop_end_cb->id);

  /* free up space */
  Lcode_free (back_edge_cb);

}