Commit 8006f46b by Richard Biener Committed by Richard Biener

fold-const.h (const_unop): Declare.

2014-11-26  Richard Biener  <rguenther@suse.de>

	* fold-const.h (const_unop): Declare.
	(const_binop): Likewise.
	* fold-const.c (const_binop): Export overload that expects
	a type parameter and dispatches to fold_relational_const as well.
	Check both operand kinds for guarding the transforms.
	(const_unop): New function, with constant folding from fold_unary_loc.
	(fold_unary_loc): Dispatch to const_unop for tcc_constant operand.
	Remove constant folding done there from the simplifications.
	(fold_binary_loc): Check for constants using CONSTANT_CLASS_P.
	(fold_negate_expr): Remove dead code from the REAL_CST case.
	Avoid building garbage in the COMPLEX_CST case.
	* gimple-match-head.c (gimple_resimplify1): Dispatch to
	const_unop.
	(gimple_resimplify2): Dispatch to const_binop.
	(gimple_simplify): Likewise.

From-SVN: r218086
parent 41866363
2014-11-26 Richard Biener <rguenther@suse.de>
* fold-const.h (const_unop): Declare.
(const_binop): Likewise.
* fold-const.c (const_binop): Export overload that expects
a type parameter and dispatches to fold_relational_const as well.
Check both operand kinds for guarding the transforms.
(const_unop): New function, with constant folding from fold_unary_loc.
(fold_unary_loc): Dispatch to const_unop for tcc_constant operand.
Remove constant folding done there from the simplifications.
(fold_binary_loc): Check for constants using CONSTANT_CLASS_P.
(fold_negate_expr): Remove dead code from the REAL_CST case.
Avoid building garbage in the COMPLEX_CST case.
* gimple-match-head.c (gimple_resimplify1): Dispatch to
const_unop.
(gimple_resimplify2): Dispatch to const_binop.
(gimple_simplify): Likewise.
2014-11-26 Ilya Enkovich <ilya.enkovich@intel.com> 2014-11-26 Ilya Enkovich <ilya.enkovich@intel.com>
PR bootstrap/63995 PR bootstrap/63995
...@@ -115,7 +115,6 @@ static bool negate_expr_p (tree); ...@@ -115,7 +115,6 @@ static bool negate_expr_p (tree);
static tree negate_expr (tree); static tree negate_expr (tree);
static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int); static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
static tree associate_trees (location_t, tree, tree, enum tree_code, tree); static tree associate_trees (location_t, tree, tree, enum tree_code, tree);
static tree const_binop (enum tree_code, tree, tree);
static enum comparison_code comparison_to_compcode (enum tree_code); static enum comparison_code comparison_to_compcode (enum tree_code);
static enum tree_code compcode_to_comparison (enum comparison_code); static enum tree_code compcode_to_comparison (enum comparison_code);
static int operand_equal_for_comparison_p (tree, tree, tree); static int operand_equal_for_comparison_p (tree, tree, tree);
...@@ -156,6 +155,9 @@ static tree fold_negate_const (tree, tree); ...@@ -156,6 +155,9 @@ static tree fold_negate_const (tree, tree);
static tree fold_not_const (const_tree, tree); static tree fold_not_const (const_tree, tree);
static tree fold_relational_const (enum tree_code, tree, tree, tree); static tree fold_relational_const (enum tree_code, tree, tree, tree);
static tree fold_convert_const (enum tree_code, tree, tree); static tree fold_convert_const (enum tree_code, tree, tree);
static tree fold_view_convert_expr (tree, tree);
static bool vec_cst_ctor_to_array (tree, tree *);
/* Return EXPR_LOCATION of T if it is not UNKNOWN_LOCATION. /* Return EXPR_LOCATION of T if it is not UNKNOWN_LOCATION.
Otherwise, return LOC. */ Otherwise, return LOC. */
...@@ -564,10 +566,7 @@ fold_negate_expr (location_t loc, tree t) ...@@ -564,10 +566,7 @@ fold_negate_expr (location_t loc, tree t)
case REAL_CST: case REAL_CST:
tem = fold_negate_const (t, type); tem = fold_negate_const (t, type);
/* Two's complement FP formats, such as c4x, may overflow. */ return tem;
if (!TREE_OVERFLOW (tem) || !flag_trapping_math)
return tem;
break;
case FIXED_CST: case FIXED_CST:
tem = fold_negate_const (t, type); tem = fold_negate_const (t, type);
...@@ -575,13 +574,9 @@ fold_negate_expr (location_t loc, tree t) ...@@ -575,13 +574,9 @@ fold_negate_expr (location_t loc, tree t)
case COMPLEX_CST: case COMPLEX_CST:
{ {
tree rpart = negate_expr (TREE_REALPART (t)); tree rpart = fold_negate_expr (loc, TREE_REALPART (t));
tree ipart = negate_expr (TREE_IMAGPART (t)); tree ipart = fold_negate_expr (loc, TREE_IMAGPART (t));
if (rpart && ipart)
if ((TREE_CODE (rpart) == REAL_CST
&& TREE_CODE (ipart) == REAL_CST)
|| (TREE_CODE (rpart) == INTEGER_CST
&& TREE_CODE (ipart) == INTEGER_CST))
return build_complex (type, rpart, ipart); return build_complex (type, rpart, ipart);
} }
break; break;
...@@ -1138,10 +1133,10 @@ const_binop (enum tree_code code, tree arg1, tree arg2) ...@@ -1138,10 +1133,10 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
STRIP_NOPS (arg1); STRIP_NOPS (arg1);
STRIP_NOPS (arg2); STRIP_NOPS (arg2);
if (TREE_CODE (arg1) == INTEGER_CST) if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg2) == INTEGER_CST)
return int_const_binop (code, arg1, arg2); return int_const_binop (code, arg1, arg2);
if (TREE_CODE (arg1) == REAL_CST) if (TREE_CODE (arg1) == REAL_CST && TREE_CODE (arg2) == REAL_CST)
{ {
machine_mode mode; machine_mode mode;
REAL_VALUE_TYPE d1; REAL_VALUE_TYPE d1;
...@@ -1219,7 +1214,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2) ...@@ -1219,7 +1214,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
return t; return t;
} }
if (TREE_CODE (arg1) == FIXED_CST) if (TREE_CODE (arg1) == FIXED_CST && TREE_CODE (arg2) == FIXED_CST)
{ {
FIXED_VALUE_TYPE f1; FIXED_VALUE_TYPE f1;
FIXED_VALUE_TYPE f2; FIXED_VALUE_TYPE f2;
...@@ -1263,7 +1258,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2) ...@@ -1263,7 +1258,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
return t; return t;
} }
if (TREE_CODE (arg1) == COMPLEX_CST) if (TREE_CODE (arg1) == COMPLEX_CST && TREE_CODE (arg2) == COMPLEX_CST)
{ {
tree type = TREE_TYPE (arg1); tree type = TREE_TYPE (arg1);
tree r1 = TREE_REALPART (arg1); tree r1 = TREE_REALPART (arg1);
...@@ -1440,6 +1435,179 @@ const_binop (enum tree_code code, tree arg1, tree arg2) ...@@ -1440,6 +1435,179 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
return NULL_TREE; return NULL_TREE;
} }
/* Overload that adds a TYPE parameter to be able to dispatch
to fold_relational_const. */
tree
const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
{
if (TREE_CODE_CLASS (code) == tcc_comparison)
return fold_relational_const (code, type, arg1, arg2);
else
return const_binop (code, arg1, arg2);
}
/* Compute CODE ARG1 with resulting type TYPE with ARG1 being constant.
Return zero if computing the constants is not possible. */
tree
const_unop (enum tree_code code, tree type, tree arg0)
{
switch (code)
{
CASE_CONVERT:
case FLOAT_EXPR:
case FIX_TRUNC_EXPR:
case FIXED_CONVERT_EXPR:
return fold_convert_const (code, type, arg0);
case ADDR_SPACE_CONVERT_EXPR:
if (integer_zerop (arg0))
return fold_convert_const (code, type, arg0);
break;
case VIEW_CONVERT_EXPR:
return fold_view_convert_expr (type, arg0);
case NEGATE_EXPR:
{
/* Can't call fold_negate_const directly here as that doesn't
handle all cases and we might not be able to negate some
constants. */
tree tem = fold_negate_expr (UNKNOWN_LOCATION, arg0);
if (tem && CONSTANT_CLASS_P (tem))
return tem;
break;
}
case ABS_EXPR:
return fold_abs_const (arg0, type);
case CONJ_EXPR:
if (TREE_CODE (arg0) == COMPLEX_CST)
{
tree ipart = fold_negate_const (TREE_IMAGPART (arg0),
TREE_TYPE (type));
return build_complex (type, TREE_REALPART (arg0), ipart);
}
break;
case BIT_NOT_EXPR:
if (TREE_CODE (arg0) == INTEGER_CST)
return fold_not_const (arg0, type);
/* Perform BIT_NOT_EXPR on each element individually. */
else if (TREE_CODE (arg0) == VECTOR_CST)
{
tree *elements;
tree elem;
unsigned count = VECTOR_CST_NELTS (arg0), i;
elements = XALLOCAVEC (tree, count);
for (i = 0; i < count; i++)
{
elem = VECTOR_CST_ELT (arg0, i);
elem = const_unop (BIT_NOT_EXPR, TREE_TYPE (type), elem);
if (elem == NULL_TREE)
break;
elements[i] = elem;
}
if (i == count)
return build_vector (type, elements);
}
break;
case TRUTH_NOT_EXPR:
if (TREE_CODE (arg0) == INTEGER_CST)
return constant_boolean_node (integer_zerop (arg0), type);
break;
case REALPART_EXPR:
if (TREE_CODE (arg0) == COMPLEX_CST)
return fold_convert (type, TREE_REALPART (arg0));
break;
case IMAGPART_EXPR:
if (TREE_CODE (arg0) == COMPLEX_CST)
return fold_convert (type, TREE_IMAGPART (arg0));
break;
case VEC_UNPACK_LO_EXPR:
case VEC_UNPACK_HI_EXPR:
case VEC_UNPACK_FLOAT_LO_EXPR:
case VEC_UNPACK_FLOAT_HI_EXPR:
{
unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
tree *elts;
enum tree_code subcode;
gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2);
if (TREE_CODE (arg0) != VECTOR_CST)
return NULL_TREE;
elts = XALLOCAVEC (tree, nelts * 2);
if (!vec_cst_ctor_to_array (arg0, elts))
return NULL_TREE;
if ((!BYTES_BIG_ENDIAN) ^ (code == VEC_UNPACK_LO_EXPR
|| code == VEC_UNPACK_FLOAT_LO_EXPR))
elts += nelts;
if (code == VEC_UNPACK_LO_EXPR || code == VEC_UNPACK_HI_EXPR)
subcode = NOP_EXPR;
else
subcode = FLOAT_EXPR;
for (i = 0; i < nelts; i++)
{
elts[i] = fold_convert_const (subcode, TREE_TYPE (type), elts[i]);
if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
return NULL_TREE;
}
return build_vector (type, elts);
}
case REDUC_MIN_EXPR:
case REDUC_MAX_EXPR:
case REDUC_PLUS_EXPR:
{
unsigned int nelts, i;
tree *elts;
enum tree_code subcode;
if (TREE_CODE (arg0) != VECTOR_CST)
return NULL_TREE;
nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
elts = XALLOCAVEC (tree, nelts);
if (!vec_cst_ctor_to_array (arg0, elts))
return NULL_TREE;
switch (code)
{
case REDUC_MIN_EXPR: subcode = MIN_EXPR; break;
case REDUC_MAX_EXPR: subcode = MAX_EXPR; break;
case REDUC_PLUS_EXPR: subcode = PLUS_EXPR; break;
default: gcc_unreachable ();
}
for (i = 1; i < nelts; i++)
{
elts[0] = const_binop (subcode, elts[0], elts[i]);
if (elts[0] == NULL_TREE || !CONSTANT_CLASS_P (elts[0]))
return NULL_TREE;
}
return elts[0];
}
default:
break;
}
return NULL_TREE;
}
/* Create a sizetype INT_CST node with NUMBER sign extended. KIND /* Create a sizetype INT_CST node with NUMBER sign extended. KIND
indicates which particular sizetype to create. */ indicates which particular sizetype to create. */
...@@ -7507,8 +7675,6 @@ build_fold_addr_expr_loc (location_t loc, tree t) ...@@ -7507,8 +7675,6 @@ build_fold_addr_expr_loc (location_t loc, tree t)
return build_fold_addr_expr_with_type_loc (loc, t, ptrtype); return build_fold_addr_expr_with_type_loc (loc, t, ptrtype);
} }
static bool vec_cst_ctor_to_array (tree, tree *);
/* Fold a unary expression of code CODE and type TYPE with operand /* Fold a unary expression of code CODE and type TYPE with operand
OP0. Return the folded expression if folding is successful. OP0. Return the folded expression if folding is successful.
Otherwise, return NULL_TREE. */ Otherwise, return NULL_TREE. */
...@@ -7523,10 +7689,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -7523,10 +7689,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
gcc_assert (IS_EXPR_CODE_CLASS (kind) gcc_assert (IS_EXPR_CODE_CLASS (kind)
&& TREE_CODE_LENGTH (code) == 1); && TREE_CODE_LENGTH (code) == 1);
tem = generic_simplify (loc, code, type, op0);
if (tem)
return tem;
arg0 = op0; arg0 = op0;
if (arg0) if (arg0)
{ {
...@@ -7552,8 +7714,23 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -7552,8 +7714,23 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
constant folder. */ constant folder. */
STRIP_NOPS (arg0); STRIP_NOPS (arg0);
} }
if (CONSTANT_CLASS_P (arg0))
{
tree tem = const_unop (code, type, arg0);
if (tem)
{
if (TREE_TYPE (tem) != type)
tem = fold_convert_loc (loc, type, tem);
return tem;
}
}
} }
tem = generic_simplify (loc, code, type, op0);
if (tem)
return tem;
if (TREE_CODE_CLASS (code) == tcc_unary) if (TREE_CODE_CLASS (code) == tcc_unary)
{ {
if (TREE_CODE (arg0) == COMPOUND_EXPR) if (TREE_CODE (arg0) == COMPOUND_EXPR)
...@@ -7790,24 +7967,14 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -7790,24 +7967,14 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
} }
} }
tem = fold_convert_const (code, type, arg0);
return tem ? tem : NULL_TREE;
case ADDR_SPACE_CONVERT_EXPR:
if (integer_zerop (arg0))
return fold_convert_const (code, type, arg0);
return NULL_TREE; return NULL_TREE;
case FIXED_CONVERT_EXPR:
tem = fold_convert_const (code, type, arg0);
return tem ? tem : NULL_TREE;
case VIEW_CONVERT_EXPR: case VIEW_CONVERT_EXPR:
if (TREE_CODE (op0) == MEM_REF) if (TREE_CODE (op0) == MEM_REF)
return fold_build2_loc (loc, MEM_REF, type, return fold_build2_loc (loc, MEM_REF, type,
TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1)); TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
return fold_view_convert_expr (type, op0); return NULL_TREE;
case NEGATE_EXPR: case NEGATE_EXPR:
tem = fold_negate_expr (loc, arg0); tem = fold_negate_expr (loc, arg0);
...@@ -7816,11 +7983,9 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -7816,11 +7983,9 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
return NULL_TREE; return NULL_TREE;
case ABS_EXPR: case ABS_EXPR:
if (TREE_CODE (arg0) == INTEGER_CST || TREE_CODE (arg0) == REAL_CST)
return fold_abs_const (arg0, type);
/* Convert fabs((double)float) into (double)fabsf(float). */ /* Convert fabs((double)float) into (double)fabsf(float). */
else if (TREE_CODE (arg0) == NOP_EXPR if (TREE_CODE (arg0) == NOP_EXPR
&& TREE_CODE (type) == REAL_TYPE) && TREE_CODE (type) == REAL_TYPE)
{ {
tree targ0 = strip_float_extensions (arg0); tree targ0 = strip_float_extensions (arg0);
if (targ0 != arg0) if (targ0 != arg0)
...@@ -7854,22 +8019,13 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -7854,22 +8019,13 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart, return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart,
negate_expr (ipart)); negate_expr (ipart));
} }
if (TREE_CODE (arg0) == COMPLEX_CST)
{
tree itype = TREE_TYPE (type);
tree rpart = fold_convert_loc (loc, itype, TREE_REALPART (arg0));
tree ipart = fold_convert_loc (loc, itype, TREE_IMAGPART (arg0));
return build_complex (type, rpart, negate_expr (ipart));
}
if (TREE_CODE (arg0) == CONJ_EXPR) if (TREE_CODE (arg0) == CONJ_EXPR)
return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)); return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
return NULL_TREE; return NULL_TREE;
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
if (TREE_CODE (arg0) == INTEGER_CST)
return fold_not_const (arg0, type);
/* Convert ~ (-A) to A - 1. */ /* Convert ~ (-A) to A - 1. */
else if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR) if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR)
return fold_build2_loc (loc, MINUS_EXPR, type, return fold_build2_loc (loc, MINUS_EXPR, type,
fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)), fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)),
build_int_cst (type, 1)); build_int_cst (type, 1));
...@@ -7897,25 +8053,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -7897,25 +8053,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
return fold_build2_loc (loc, BIT_XOR_EXPR, type, return fold_build2_loc (loc, BIT_XOR_EXPR, type,
fold_convert_loc (loc, type, fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)), tem); TREE_OPERAND (arg0, 0)), tem);
/* Perform BIT_NOT_EXPR on each element individually. */
else if (TREE_CODE (arg0) == VECTOR_CST)
{
tree *elements;
tree elem;
unsigned count = VECTOR_CST_NELTS (arg0), i;
elements = XALLOCAVEC (tree, count);
for (i = 0; i < count; i++)
{
elem = VECTOR_CST_ELT (arg0, i);
elem = fold_unary_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type), elem);
if (elem == NULL_TREE)
break;
elements[i] = elem;
}
if (i == count)
return build_vector (type, elements);
}
return NULL_TREE; return NULL_TREE;
...@@ -7932,8 +8069,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -7932,8 +8069,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
case REALPART_EXPR: case REALPART_EXPR:
if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE) if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
return fold_convert_loc (loc, type, arg0); return fold_convert_loc (loc, type, arg0);
if (TREE_CODE (arg0) == COMPLEX_CST)
return fold_convert_loc (loc, type, TREE_REALPART (arg0));
if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
{ {
tree itype = TREE_TYPE (TREE_TYPE (arg0)); tree itype = TREE_TYPE (TREE_TYPE (arg0));
...@@ -7972,8 +8107,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -7972,8 +8107,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
case IMAGPART_EXPR: case IMAGPART_EXPR:
if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE) if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
return build_zero_cst (type); return build_zero_cst (type);
if (TREE_CODE (arg0) == COMPLEX_CST)
return fold_convert_loc (loc, type, TREE_IMAGPART (arg0));
if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
{ {
tree itype = TREE_TYPE (TREE_TYPE (arg0)); tree itype = TREE_TYPE (TREE_TYPE (arg0));
...@@ -8021,76 +8154,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -8021,76 +8154,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
} }
return NULL_TREE; return NULL_TREE;
case VEC_UNPACK_LO_EXPR:
case VEC_UNPACK_HI_EXPR:
case VEC_UNPACK_FLOAT_LO_EXPR:
case VEC_UNPACK_FLOAT_HI_EXPR:
{
unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
tree *elts;
enum tree_code subcode;
gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2);
if (TREE_CODE (arg0) != VECTOR_CST)
return NULL_TREE;
elts = XALLOCAVEC (tree, nelts * 2);
if (!vec_cst_ctor_to_array (arg0, elts))
return NULL_TREE;
if ((!BYTES_BIG_ENDIAN) ^ (code == VEC_UNPACK_LO_EXPR
|| code == VEC_UNPACK_FLOAT_LO_EXPR))
elts += nelts;
if (code == VEC_UNPACK_LO_EXPR || code == VEC_UNPACK_HI_EXPR)
subcode = NOP_EXPR;
else
subcode = FLOAT_EXPR;
for (i = 0; i < nelts; i++)
{
elts[i] = fold_convert_const (subcode, TREE_TYPE (type), elts[i]);
if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
return NULL_TREE;
}
return build_vector (type, elts);
}
case REDUC_MIN_EXPR:
case REDUC_MAX_EXPR:
case REDUC_PLUS_EXPR:
{
unsigned int nelts, i;
tree *elts;
enum tree_code subcode;
if (TREE_CODE (op0) != VECTOR_CST)
return NULL_TREE;
nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (op0));
elts = XALLOCAVEC (tree, nelts);
if (!vec_cst_ctor_to_array (op0, elts))
return NULL_TREE;
switch (code)
{
case REDUC_MIN_EXPR: subcode = MIN_EXPR; break;
case REDUC_MAX_EXPR: subcode = MAX_EXPR; break;
case REDUC_PLUS_EXPR: subcode = PLUS_EXPR; break;
default: gcc_unreachable ();
}
for (i = 1; i < nelts; i++)
{
elts[0] = const_binop (subcode, elts[0], elts[i]);
if (elts[0] == NULL_TREE || !CONSTANT_CLASS_P (elts[0]))
return NULL_TREE;
}
return elts[0];
}
default: default:
return NULL_TREE; return NULL_TREE;
} /* switch (code) */ } /* switch (code) */
...@@ -9689,19 +9752,13 @@ fold_binary_loc (location_t loc, ...@@ -9689,19 +9752,13 @@ fold_binary_loc (location_t loc,
/* Note that TREE_CONSTANT isn't enough: static var addresses are /* Note that TREE_CONSTANT isn't enough: static var addresses are
constant but we can't do arithmetic on them. */ constant but we can't do arithmetic on them. */
if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) if (CONSTANT_CLASS_P (arg0) && CONSTANT_CLASS_P (arg1))
|| (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
|| (TREE_CODE (arg0) == FIXED_CST && TREE_CODE (arg1) == FIXED_CST)
|| (TREE_CODE (arg0) == FIXED_CST && TREE_CODE (arg1) == INTEGER_CST)
|| (TREE_CODE (arg0) == COMPLEX_CST && TREE_CODE (arg1) == COMPLEX_CST)
|| (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
|| (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == INTEGER_CST))
{ {
if (kind == tcc_binary) if (kind == tcc_binary)
{ {
/* Make sure type and arg0 have the same saturating flag. */ /* Make sure type and arg0 have the same saturating flag. */
gcc_assert (TYPE_SATURATING (type) gcc_checking_assert (TYPE_SATURATING (type)
== TYPE_SATURATING (TREE_TYPE (arg0))); == TYPE_SATURATING (TREE_TYPE (arg0)));
tem = const_binop (code, arg0, arg1); tem = const_binop (code, arg0, arg1);
} }
else if (kind == tcc_comparison) else if (kind == tcc_comparison)
......
...@@ -169,5 +169,7 @@ extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int, ...@@ -169,5 +169,7 @@ extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int,
tree, tree); tree, tree);
extern tree sign_bit_p (tree, const_tree); extern tree sign_bit_p (tree, const_tree);
extern tree exact_inverse (tree, tree); extern tree exact_inverse (tree, tree);
extern tree const_unop (enum tree_code, tree, tree);
extern tree const_binop (enum tree_code, tree, tree, tree);
#endif // GCC_FOLD_CONST_H #endif // GCC_FOLD_CONST_H
...@@ -94,7 +94,7 @@ gimple_resimplify1 (gimple_seq *seq, ...@@ -94,7 +94,7 @@ gimple_resimplify1 (gimple_seq *seq,
{ {
tree tem = NULL_TREE; tree tem = NULL_TREE;
if (res_code->is_tree_code ()) if (res_code->is_tree_code ())
tem = fold_unary_to_constant (*res_code, type, res_ops[0]); tem = const_unop (*res_code, type, res_ops[0]);
else else
{ {
tree decl = builtin_decl_implicit (*res_code); tree decl = builtin_decl_implicit (*res_code);
...@@ -150,8 +150,7 @@ gimple_resimplify2 (gimple_seq *seq, ...@@ -150,8 +150,7 @@ gimple_resimplify2 (gimple_seq *seq,
{ {
tree tem = NULL_TREE; tree tem = NULL_TREE;
if (res_code->is_tree_code ()) if (res_code->is_tree_code ())
tem = fold_binary_to_constant (*res_code, type, tem = const_binop (*res_code, type, res_ops[0], res_ops[1]);
res_ops[0], res_ops[1]);
else else
{ {
tree decl = builtin_decl_implicit (*res_code); tree decl = builtin_decl_implicit (*res_code);
...@@ -386,7 +385,7 @@ gimple_simplify (enum tree_code code, tree type, ...@@ -386,7 +385,7 @@ gimple_simplify (enum tree_code code, tree type,
{ {
if (constant_for_folding (op0)) if (constant_for_folding (op0))
{ {
tree res = fold_unary_to_constant (code, type, op0); tree res = const_unop (code, type, op0);
if (res != NULL_TREE if (res != NULL_TREE
&& CONSTANT_CLASS_P (res)) && CONSTANT_CLASS_P (res))
return res; return res;
...@@ -409,7 +408,7 @@ gimple_simplify (enum tree_code code, tree type, ...@@ -409,7 +408,7 @@ gimple_simplify (enum tree_code code, tree type,
{ {
if (constant_for_folding (op0) && constant_for_folding (op1)) if (constant_for_folding (op0) && constant_for_folding (op1))
{ {
tree res = fold_binary_to_constant (code, type, op0, op1); tree res = const_binop (code, type, op0, op1);
if (res != NULL_TREE if (res != NULL_TREE
&& CONSTANT_CLASS_P (res)) && CONSTANT_CLASS_P (res))
return res; return res;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment