Exemple #1
0
tree
gimple_simplify (enum tree_code code, tree type,
		 tree op0, tree op1,
		 gimple_seq *seq, tree (*valueize)(tree))
{
  if (constant_for_folding (op0) && constant_for_folding (op1))
    {
      tree res = const_binop (code, type, op0, op1);
      if (res != NULL_TREE
	  && CONSTANT_CLASS_P (res))
	return res;
    }

  /* Canonicalize operand order both for matching and fallback stmt
     generation.  */
  if ((commutative_tree_code (code)
       || TREE_CODE_CLASS (code) == tcc_comparison)
      && tree_swap_operands_p (op0, op1, false))
    {
      tree tem = op0;
      op0 = op1;
      op1 = tem;
      if (TREE_CODE_CLASS (code) == tcc_comparison)
	code = swap_tree_comparison (code);
    }

  code_helper rcode;
  tree ops[3] = {};
  if (!gimple_simplify (&rcode, ops, seq, valueize,
			code, type, op0, op1))
    return NULL_TREE;
  return maybe_push_res_to_seq (rcode, type, ops, seq);
}
bool
gimple_resimplify2 (gimple_seq *seq,
		    code_helper *res_code, tree type, tree *res_ops,
		    tree (*valueize)(tree))
{
  if (constant_for_folding (res_ops[0]) && constant_for_folding (res_ops[1]))
    {
      tree tem = NULL_TREE;
      if (res_code->is_tree_code ())
	tem = const_binop (*res_code, type, res_ops[0], res_ops[1]);
      else
	tem = fold_const_call (combined_fn (*res_code), type,
			       res_ops[0], res_ops[1]);
      if (tem != NULL_TREE
	  && CONSTANT_CLASS_P (tem))
	{
	  if (TREE_OVERFLOW_P (tem))
	    tem = drop_tree_overflow (tem);
	  res_ops[0] = tem;
	  res_ops[1] = NULL_TREE;
	  res_ops[2] = NULL_TREE;
	  *res_code = TREE_CODE (res_ops[0]);
	  return true;
	}
    }

  /* Canonicalize operand order.  */
  bool canonicalized = false;
  if (res_code->is_tree_code ()
      && (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison
	  || commutative_tree_code (*res_code))
      && tree_swap_operands_p (res_ops[0], res_ops[1]))
    {
      std::swap (res_ops[0], res_ops[1]);
      if (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison)
	*res_code = swap_tree_comparison (*res_code);
      canonicalized = true;
    }

  code_helper res_code2;
  tree res_ops2[3] = {};
  if (gimple_simplify (&res_code2, res_ops2, seq, valueize,
		       *res_code, type, res_ops[0], res_ops[1]))
    {
      *res_code = res_code2;
      res_ops[0] = res_ops2[0];
      res_ops[1] = res_ops2[1];
      res_ops[2] = res_ops2[2];
      return true;
    }

  return canonicalized;
}
Exemple #3
0
static tree
fold_const_reduction (tree type, tree arg, tree_code code)
{
  unsigned HOST_WIDE_INT nelts;
  if (TREE_CODE (arg) != VECTOR_CST
      || !VECTOR_CST_NELTS (arg).is_constant (&nelts))
    return NULL_TREE;

  tree res = VECTOR_CST_ELT (arg, 0);
  for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++)
    {
      res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i));
      if (res == NULL_TREE || !CONSTANT_CLASS_P (res))
	return NULL_TREE;
    }
  return res;
}
Exemple #4
0
static tree
fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code)
{
  if (TREE_CODE (arg1) != VECTOR_CST)
    return NULL_TREE;

  unsigned HOST_WIDE_INT nelts;
  if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts))
    return NULL_TREE;

  for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++)
    {
      arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i));
      if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0))
	return NULL_TREE;
    }
  return arg0;
}
Exemple #5
0
static bool
gimple_resimplify2 (gimple_seq *seq,
		    code_helper *res_code, tree type, tree *res_ops,
		    tree (*valueize)(tree))
{
  if (constant_for_folding (res_ops[0]) && constant_for_folding (res_ops[1]))
    {
      tree tem = NULL_TREE;
      if (res_code->is_tree_code ())
	tem = const_binop (*res_code, type, res_ops[0], res_ops[1]);
      else
	{
	  tree decl = builtin_decl_implicit (*res_code);
	  if (decl)
	    {
	      tem = fold_builtin_n (UNKNOWN_LOCATION, decl, res_ops, 2, false);
	      if (tem)
		{
		  /* fold_builtin_n wraps the result inside a NOP_EXPR.  */
		  STRIP_NOPS (tem);
		  tem = fold_convert (type, tem);
		}
	    }
	}
      if (tem != NULL_TREE
	  && CONSTANT_CLASS_P (tem))
	{
	  res_ops[0] = tem;
	  res_ops[1] = NULL_TREE;
	  res_ops[2] = NULL_TREE;
	  *res_code = TREE_CODE (res_ops[0]);
	  return true;
	}
    }

  /* Canonicalize operand order.  */
  bool canonicalized = false;
  if (res_code->is_tree_code ()
      && (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison
	  || commutative_tree_code (*res_code))
      && tree_swap_operands_p (res_ops[0], res_ops[1], false))
    {
      tree tem = res_ops[0];
      res_ops[0] = res_ops[1];
      res_ops[1] = tem;
      if (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison)
	*res_code = swap_tree_comparison (*res_code);
      canonicalized = true;
    }

  code_helper res_code2;
  tree res_ops2[3] = {};
  if (gimple_simplify (&res_code2, res_ops2, seq, valueize,
		       *res_code, type, res_ops[0], res_ops[1]))
    {
      *res_code = res_code2;
      res_ops[0] = res_ops2[0];
      res_ops[1] = res_ops2[1];
      res_ops[2] = res_ops2[2];
      return true;
    }

  return canonicalized;
}