Example #1
0
void
insert_debug_temp_for_var_def (gimple stmt)
{
  gimple def_stmt = ((void *) 0);
  int usecount = 0;
  tree value = ((void *) 0);
  for (; arf ();)
    {
      if (!gimple_debug_bind_p (stmt))
        continue;
      if (usecount++)
        break;
      unsigned char no_value = 0;
      if (!gimple_bb (def_stmt))
        no_value = 1;
      if (!no_value)
        value = gimple_assign_rhs_to_tree ();
    }
  if (value)
    {
      if ((tree_code_type[(int) (((value)->code))] == 42)
          || (usecount == 1 && (is_gimple_min_invariant (value))))
        value = unshare_expr (value);
    }
}
Example #2
0
/* Check whether G is a potential conditional compare candidate.  */
static bool
ccmp_candidate_p (gimple *g)
{
  tree rhs = gimple_assign_rhs_to_tree (g);
  tree lhs, op0, op1;
  gimple *gs0, *gs1;
  enum tree_code tcode, tcode0, tcode1;
  tcode = TREE_CODE (rhs);

  if (tcode != BIT_AND_EXPR && tcode != BIT_IOR_EXPR)
    return false;

  lhs = gimple_assign_lhs (g);
  op0 = TREE_OPERAND (rhs, 0);
  op1 = TREE_OPERAND (rhs, 1);

  if ((TREE_CODE (op0) != SSA_NAME) || (TREE_CODE (op1) != SSA_NAME)
      || !has_single_use (lhs))
    return false;

  gs0 = get_gimple_for_ssa_name (op0);
  gs1 = get_gimple_for_ssa_name (op1);
  if (!gs0 || !gs1 || !is_gimple_assign (gs0) || !is_gimple_assign (gs1)
      /* g, gs0 and gs1 must be in the same basic block, since current stage
	 is out-of-ssa.  We can not guarantee the correctness when forwording
	 the gs0 and gs1 into g whithout DATAFLOW analysis.  */
      || gimple_bb (gs0) != gimple_bb (gs1)
      || gimple_bb (gs0) != gimple_bb (g))
    return false;

  if (!(INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (gs0)))
       || POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (gs0))))
      || !(INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (gs1)))
	   || POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (gs1)))))
    return false;

  tcode0 = gimple_assign_rhs_code (gs0);
  tcode1 = gimple_assign_rhs_code (gs1);
  if (TREE_CODE_CLASS (tcode0) == tcc_comparison
      && TREE_CODE_CLASS (tcode1) == tcc_comparison)
    return true;
  if (TREE_CODE_CLASS (tcode0) == tcc_comparison
      && ccmp_candidate_p (gs1))
    return true;
  else if (TREE_CODE_CLASS (tcode1) == tcc_comparison
	   && ccmp_candidate_p (gs0))
    return true;
  /* We skip ccmp_candidate_p (gs1) && ccmp_candidate_p (gs0) since
     there is no way to set the CC flag.  */
  return false;
}
Example #3
0
/* Expand conditional compare gimple G.  A typical CCMP sequence is like:

     CC0 = CMP (a, b);
     CC1 = CCMP (NE (CC0, 0), CMP (e, f));
     ...
     CCn = CCMP (NE (CCn-1, 0), CMP (...));

   hook gen_ccmp_first is used to expand the first compare.
   hook gen_ccmp_next is used to expand the following CCMP.
   PREP_SEQ returns all insns to prepare opearand.
   GEN_SEQ returns all compare insns.  */
static rtx
expand_ccmp_expr_1 (gimple *g, rtx *prep_seq, rtx *gen_seq)
{
  tree exp = gimple_assign_rhs_to_tree (g);
  enum tree_code code = TREE_CODE (exp);
  gimple *gs0 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 0));
  gimple *gs1 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 1));
  rtx tmp;
  enum tree_code code0 = gimple_assign_rhs_code (gs0);
  enum tree_code code1 = gimple_assign_rhs_code (gs1);

  gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
  gcc_assert (gs0 && gs1 && is_gimple_assign (gs0) && is_gimple_assign (gs1));

  if (TREE_CODE_CLASS (code0) == tcc_comparison)
    {
      if (TREE_CODE_CLASS (code1) == tcc_comparison)
	{
	  int unsignedp0;
	  enum rtx_code rcode0;

	  unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs0)));
	  rcode0 = get_rtx_code (code0, unsignedp0);

	  tmp = targetm.gen_ccmp_first (prep_seq, gen_seq, rcode0,
					gimple_assign_rhs1 (gs0),
					gimple_assign_rhs2 (gs0));
	  if (!tmp)
	    return NULL_RTX;

	  return expand_ccmp_next (gs1, code, tmp, prep_seq, gen_seq);
	}
      else
	{
	  tmp = expand_ccmp_expr_1 (gs1, prep_seq, gen_seq);
	  if (!tmp)
	    return NULL_RTX;

	  return expand_ccmp_next (gs0, code, tmp, prep_seq, gen_seq);
	}
    }
  else
    {
      gcc_assert (gimple_assign_rhs_code (gs0) == BIT_AND_EXPR
                  || gimple_assign_rhs_code (gs0) == BIT_IOR_EXPR);

      if (TREE_CODE_CLASS (gimple_assign_rhs_code (gs1)) == tcc_comparison)
	{
	  tmp = expand_ccmp_expr_1 (gs0, prep_seq, gen_seq);
	  if (!tmp)
	    return NULL_RTX;

	  return expand_ccmp_next (gs1, code, tmp, prep_seq, gen_seq);
	}
      else
	{
	  gcc_assert (gimple_assign_rhs_code (gs1) == BIT_AND_EXPR
		      || gimple_assign_rhs_code (gs1) == BIT_IOR_EXPR);
	}
    }

  return NULL_RTX;
}
Example #4
0
File: ccmp.c Project: kraj/gcc
/* Expand conditional compare gimple G.  A typical CCMP sequence is like:

     CC0 = CMP (a, b);
     CC1 = CCMP (NE (CC0, 0), CMP (e, f));
     ...
     CCn = CCMP (NE (CCn-1, 0), CMP (...));

   hook gen_ccmp_first is used to expand the first compare.
   hook gen_ccmp_next is used to expand the following CCMP.
   PREP_SEQ returns all insns to prepare opearand.
   GEN_SEQ returns all compare insns.  */
static rtx
expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
{
    tree exp = gimple_assign_rhs_to_tree (g);
    tree_code code = TREE_CODE (exp);
    gimple *gs0 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 0));
    gimple *gs1 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 1));
    rtx tmp;
    tree_code code0 = gimple_assign_rhs_code (gs0);
    tree_code code1 = gimple_assign_rhs_code (gs1);

    gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
    gcc_assert (gs0 && gs1 && is_gimple_assign (gs0) && is_gimple_assign (gs1));

    if (TREE_CODE_CLASS (code0) == tcc_comparison)
    {
        if (TREE_CODE_CLASS (code1) == tcc_comparison)
        {
            int unsignedp0, unsignedp1;
            rtx_code rcode0, rcode1;
            int speed_p = optimize_insn_for_speed_p ();
            rtx tmp2 = NULL_RTX, ret = NULL_RTX, ret2 = NULL_RTX;
            unsigned cost1 = MAX_COST;
            unsigned cost2 = MAX_COST;

            unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs0)));
            unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs1)));
            rcode0 = get_rtx_code (code0, unsignedp0);
            rcode1 = get_rtx_code (code1, unsignedp1);

            rtx_insn *prep_seq_1, *gen_seq_1;
            tmp = targetm.gen_ccmp_first (&prep_seq_1, &gen_seq_1, rcode0,
                                          gimple_assign_rhs1 (gs0),
                                          gimple_assign_rhs2 (gs0));

            if (tmp != NULL)
            {
                ret = expand_ccmp_next (gs1, code, tmp, &prep_seq_1, &gen_seq_1);
                cost1 = seq_cost (prep_seq_1, speed_p);
                cost1 += seq_cost (gen_seq_1, speed_p);
            }

            /* FIXME: Temporary workaround for PR69619.
               Avoid exponential compile time due to expanding gs0 and gs1 twice.
               If gs0 and gs1 are complex, the cost will be high, so avoid
               reevaluation if above an arbitrary threshold.  */
            rtx_insn *prep_seq_2, *gen_seq_2;
            if (tmp == NULL || cost1 < COSTS_N_INSNS (25))
                tmp2 = targetm.gen_ccmp_first (&prep_seq_2, &gen_seq_2, rcode1,
                                               gimple_assign_rhs1 (gs1),
                                               gimple_assign_rhs2 (gs1));

            if (!tmp && !tmp2)
                return NULL_RTX;

            if (tmp2 != NULL)
            {
                ret2 = expand_ccmp_next (gs0, code, tmp2, &prep_seq_2,
                                         &gen_seq_2);
                cost2 = seq_cost (prep_seq_2, speed_p);
                cost2 += seq_cost (gen_seq_2, speed_p);
            }

            if (cost2 < cost1)
            {
                *prep_seq = prep_seq_2;
                *gen_seq = gen_seq_2;
                return ret2;
            }

            *prep_seq = prep_seq_1;
            *gen_seq = gen_seq_1;
            return ret;
        }
        else
        {
            tmp = expand_ccmp_expr_1 (gs1, prep_seq, gen_seq);
            if (!tmp)
                return NULL_RTX;

            return expand_ccmp_next (gs0, code, tmp, prep_seq, gen_seq);
        }
    }
    else
    {
        gcc_assert (gimple_assign_rhs_code (gs0) == BIT_AND_EXPR
                    || gimple_assign_rhs_code (gs0) == BIT_IOR_EXPR);

        if (TREE_CODE_CLASS (gimple_assign_rhs_code (gs1)) == tcc_comparison)
        {
            tmp = expand_ccmp_expr_1 (gs0, prep_seq, gen_seq);
            if (!tmp)
                return NULL_RTX;

            return expand_ccmp_next (gs1, code, tmp, prep_seq, gen_seq);
        }
        else
        {
            gcc_assert (gimple_assign_rhs_code (gs1) == BIT_AND_EXPR
                        || gimple_assign_rhs_code (gs1) == BIT_IOR_EXPR);
        }
    }

    return NULL_RTX;
}