Example #1
0
/* Transform (subreg (plus reg const)) to (plus (subreg reg) const)
   when it is possible.  Return X or the transformation result if the
   transformation is done.  */
static rtx
move_plus_up (rtx x)
{
  rtx subreg_reg;
  enum machine_mode x_mode, subreg_reg_mode;
  
  if (GET_CODE (x) != SUBREG || !subreg_lowpart_p (x))
    return x;
  subreg_reg = SUBREG_REG (x);
  x_mode = GET_MODE (x);
  subreg_reg_mode = GET_MODE (subreg_reg);
  if (GET_CODE (x) == SUBREG && GET_CODE (subreg_reg) == PLUS
      && GET_MODE_SIZE (x_mode) <= GET_MODE_SIZE (subreg_reg_mode)
      && CONSTANT_P (XEXP (subreg_reg, 1))
      && GET_MODE_CLASS (x_mode) == MODE_INT
      && GET_MODE_CLASS (subreg_reg_mode) == MODE_INT)
    {
      rtx cst = simplify_subreg (x_mode, XEXP (subreg_reg, 1), subreg_reg_mode,
				 subreg_lowpart_offset (x_mode,
							subreg_reg_mode));
      if (cst && CONSTANT_P (cst))
	return gen_rtx_PLUS (x_mode, lowpart_subreg (x_mode,
						     XEXP (subreg_reg, 0),
						     subreg_reg_mode), cst);
    }
  return x;
}
Example #2
0
static int
try_apply_stack_adjustment (rtx insn, struct csa_reflist *reflist,
			    HOST_WIDE_INT new_adjust, HOST_WIDE_INT delta)
{
  struct csa_reflist *ml;
  rtx set;

  set = single_set_for_csa (insn);
  if (MEM_P (SET_DEST (set)))
    validate_change (insn, &SET_DEST (set),
		     replace_equiv_address (SET_DEST (set), stack_pointer_rtx),
		     1);
  else
    validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1);

  for (ml = reflist; ml ; ml = ml->next)
    {
      rtx new_addr = plus_constant (Pmode, stack_pointer_rtx,
				    ml->sp_offset - delta);
      rtx new_val;

      if (MEM_P (*ml->ref))
	new_val = replace_equiv_address_nv (*ml->ref, new_addr);
      else if (GET_MODE (*ml->ref) == GET_MODE (stack_pointer_rtx))
	new_val = new_addr;
      else
	new_val = lowpart_subreg (GET_MODE (*ml->ref), new_addr,
				  GET_MODE (new_addr));
      validate_change (ml->insn, ml->ref, new_val, 1);
    }

  if (apply_change_group ())
    {
      /* Succeeded.  Update our knowledge of the stack references.  */
      for (ml = reflist; ml ; ml = ml->next)
	ml->sp_offset -= delta;

      return 1;
    }
  else
    return 0;
}
Example #3
0
static bool
doloop_optimize (struct loop *loop)
{
    enum machine_mode mode;
    rtx doloop_seq, doloop_pat, doloop_reg;
    rtx iterations, count;
    rtx iterations_max;
    rtx start_label;
    rtx condition;
    unsigned level, est_niter;
    struct niter_desc *desc;
    unsigned word_mode_size;
    unsigned HOST_WIDE_INT word_mode_max;

    if (dump_file)
        fprintf (dump_file, "Doloop: Processing loop %d.\n", loop->num);

    /* APPLE LOCAL begin lno */
    /* Ignore large loops.  */
    if (loop->ninsns > (unsigned) PARAM_VALUE (PARAM_MAX_DOLOOP_INSNS))
    {
        if (dump_file)
            fprintf (dump_file,
                     "Doloop: The loop is too large.\n");
        return false;
    }
    /* APPLE LOCAL end lno */

    iv_analysis_loop_init (loop);

    /* Find the simple exit of a LOOP.  */
    desc = get_simple_loop_desc (loop);

    /* Check that loop is a candidate for a low-overhead looping insn.  */
    if (!doloop_valid_p (loop, desc))
    {
        if (dump_file)
            fprintf (dump_file,
                     "Doloop: The loop is not suitable.\n");
        return false;
    }
    mode = desc->mode;

    est_niter = 3;
    if (desc->const_iter)
        est_niter = desc->niter;
    /* If the estimate on number of iterations is reliable (comes from profile
       feedback), use it.  Do not use it normally, since the expected number
       of iterations of an unrolled loop is 2.  */
    if (loop->header->count)
        est_niter = expected_loop_iterations (loop);

    if (est_niter < 3)
    {
        if (dump_file)
            fprintf (dump_file,
                     "Doloop: Too few iterations (%u) to be profitable.\n",
                     est_niter);
        return false;
    }

    count = copy_rtx (desc->niter_expr);
    iterations = desc->const_iter ? desc->niter_expr : const0_rtx;
    iterations_max = GEN_INT (desc->niter_max);
    level = get_loop_level (loop) + 1;

    /* Generate looping insn.  If the pattern FAILs then give up trying
       to modify the loop since there is some aspect the back-end does
       not like.  */
    start_label = block_label (desc->in_edge->dest);
    doloop_reg = gen_reg_rtx (mode);
    doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
                                 GEN_INT (level), start_label);

    word_mode_size = GET_MODE_BITSIZE (word_mode);
    word_mode_max
        = ((unsigned HOST_WIDE_INT) 1 << (word_mode_size - 1) << 1) - 1;
    if (! doloop_seq
            && mode != word_mode
            /* Before trying mode different from the one in that # of iterations is
            computed, we must be sure that the number of iterations fits into
             the new mode.  */
            && (word_mode_size >= GET_MODE_BITSIZE (mode)
                || desc->niter_max <= word_mode_max))
    {
        if (word_mode_size > GET_MODE_BITSIZE (mode))
        {
            count = simplify_gen_unary (ZERO_EXTEND, word_mode,
                                        count, mode);
            iterations = simplify_gen_unary (ZERO_EXTEND, word_mode,
                                             iterations, mode);
            iterations_max = simplify_gen_unary (ZERO_EXTEND, word_mode,
                                                 iterations_max, mode);
        }
        else
        {
            count = lowpart_subreg (word_mode, count, mode);
            iterations = lowpart_subreg (word_mode, iterations, mode);
            iterations_max = lowpart_subreg (word_mode, iterations_max, mode);
        }
        PUT_MODE (doloop_reg, word_mode);
        doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
                                     GEN_INT (level), start_label);
    }
    if (! doloop_seq)
    {
        if (dump_file)
            fprintf (dump_file,
                     "Doloop: Target unwilling to use doloop pattern!\n");
        return false;
    }

    /* If multiple instructions were created, the last must be the
       jump instruction.  Also, a raw define_insn may yield a plain
       pattern.  */
    doloop_pat = doloop_seq;
    if (INSN_P (doloop_pat))
    {
        while (NEXT_INSN (doloop_pat) != NULL_RTX)
            doloop_pat = NEXT_INSN (doloop_pat);
        if (JUMP_P (doloop_pat))
            doloop_pat = PATTERN (doloop_pat);
        else
            doloop_pat = NULL_RTX;
    }

    if (! doloop_pat
            || ! (condition = doloop_condition_get (doloop_pat)))
    {
        if (dump_file)
            fprintf (dump_file, "Doloop: Unrecognizable doloop pattern!\n");
        return false;
    }

    doloop_modify (loop, desc, doloop_seq, condition, count);
    return true;
}
static rtx
may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
{
  rtx test, at, op[2], stest;
  struct rtx_iv iv;
  unsigned i;
  enum machine_mode mode;

  /* BB must end in a simple conditional jump.  */
  if (EDGE_COUNT (bb->succs) != 2)
    return NULL_RTX;
  if (!any_condjump_p (BB_END (bb)))
    return NULL_RTX;

  /* With branches inside loop.  */
  if (!flow_bb_inside_loop_p (loop, EDGE_SUCC (bb, 0)->dest)
      || !flow_bb_inside_loop_p (loop, EDGE_SUCC (bb, 1)->dest))
    return NULL_RTX;

  /* It must be executed just once each iteration (because otherwise we
     are unable to update dominator/irreducible loop information correctly).  */
  if (!just_once_each_iteration_p (loop, bb))
    return NULL_RTX;

  /* Condition must be invariant.  */
  test = get_condition (BB_END (bb), &at, true, false);
  if (!test)
    return NULL_RTX;

  mode = VOIDmode;
  for (i = 0; i < 2; i++)
    {
      op[i] = XEXP (test, i);

      if (CONSTANT_P (op[i]))
	continue;

      if (!iv_analyze (at, op[i], &iv))
	return NULL_RTX;
      if (iv.step != const0_rtx
	  || iv.first_special)
	return NULL_RTX;

      op[i] = get_iv_value (&iv, const0_rtx);
      if (iv.extend != IV_UNKNOWN_EXTEND
	  && iv.mode != iv.extend_mode)
	op[i] = lowpart_subreg (iv.mode, op[i], iv.extend_mode);
      if (mode == VOIDmode)
	mode = iv.mode;
      else
	gcc_assert (mode == iv.mode);
    }

  if (GET_MODE_CLASS (mode) == MODE_CC)
    {
      if (at != BB_END (bb))
	return NULL_RTX;

      if (!rtx_equal_p (op[0], XEXP (test, 0))
	  || !rtx_equal_p (op[1], XEXP (test, 1)))
	return NULL_RTX;

      *cinsn = BB_END (bb);
      return test;
    }

  stest = simplify_gen_relational (GET_CODE (test), SImode,
				   mode, op[0], op[1]);
  if (stest == const0_rtx
      || stest == const_true_rtx)
    return stest;

  return canon_condition (gen_rtx_fmt_ee (GET_CODE (test), SImode,
					  op[0], op[1]));
}