summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-26 14:39:43 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-26 14:39:43 +0000
commit6d31c916e0682010ba9a3d2c1c7647201c28883c (patch)
tree8513d233a582b2c8a38f6db93929f5a48aaf43a8 /gcc/fold-const.c
parent13a78ad1136316949733262f5370a346394be242 (diff)
downloadgcc-6d31c916e0682010ba9a3d2c1c7647201c28883c.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@218086 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c355
1 files changed, 206 insertions, 149 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 04a195c2bf8..195d1e5408d 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -115,7 +115,6 @@ static bool negate_expr_p (tree);
static tree negate_expr (tree);
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 const_binop (enum tree_code, tree, tree);
static enum comparison_code comparison_to_compcode (enum tree_code);
static enum tree_code compcode_to_comparison (enum comparison_code);
static int operand_equal_for_comparison_p (tree, tree, tree);
@@ -156,6 +155,9 @@ static tree fold_negate_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_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.
Otherwise, return LOC. */
@@ -564,10 +566,7 @@ fold_negate_expr (location_t loc, tree t)
case REAL_CST:
tem = fold_negate_const (t, type);
- /* Two's complement FP formats, such as c4x, may overflow. */
- if (!TREE_OVERFLOW (tem) || !flag_trapping_math)
- return tem;
- break;
+ return tem;
case FIXED_CST:
tem = fold_negate_const (t, type);
@@ -575,13 +574,9 @@ fold_negate_expr (location_t loc, tree t)
case COMPLEX_CST:
{
- tree rpart = negate_expr (TREE_REALPART (t));
- tree ipart = negate_expr (TREE_IMAGPART (t));
-
- if ((TREE_CODE (rpart) == REAL_CST
- && TREE_CODE (ipart) == REAL_CST)
- || (TREE_CODE (rpart) == INTEGER_CST
- && TREE_CODE (ipart) == INTEGER_CST))
+ tree rpart = fold_negate_expr (loc, TREE_REALPART (t));
+ tree ipart = fold_negate_expr (loc, TREE_IMAGPART (t));
+ if (rpart && ipart)
return build_complex (type, rpart, ipart);
}
break;
@@ -1138,10 +1133,10 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
STRIP_NOPS (arg1);
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);
- if (TREE_CODE (arg1) == REAL_CST)
+ if (TREE_CODE (arg1) == REAL_CST && TREE_CODE (arg2) == REAL_CST)
{
machine_mode mode;
REAL_VALUE_TYPE d1;
@@ -1219,7 +1214,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
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 f2;
@@ -1263,7 +1258,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
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 r1 = TREE_REALPART (arg1);
@@ -1440,6 +1435,179 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
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
indicates which particular sizetype to create. */
@@ -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);
}
-static bool vec_cst_ctor_to_array (tree, tree *);
-
/* Fold a unary expression of code CODE and type TYPE with operand
OP0. Return the folded expression if folding is successful.
Otherwise, return NULL_TREE. */
@@ -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)
&& TREE_CODE_LENGTH (code) == 1);
- tem = generic_simplify (loc, code, type, op0);
- if (tem)
- return tem;
-
arg0 = op0;
if (arg0)
{
@@ -7552,8 +7714,23 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
constant folder. */
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 (arg0) == COMPOUND_EXPR)
@@ -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;
- case FIXED_CONVERT_EXPR:
- tem = fold_convert_const (code, type, arg0);
- return tem ? tem : NULL_TREE;
-
case VIEW_CONVERT_EXPR:
if (TREE_CODE (op0) == MEM_REF)
return fold_build2_loc (loc, MEM_REF, type,
TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
- return fold_view_convert_expr (type, op0);
+ return NULL_TREE;
case NEGATE_EXPR:
tem = fold_negate_expr (loc, arg0);
@@ -7816,11 +7983,9 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
return NULL_TREE;
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). */
- else if (TREE_CODE (arg0) == NOP_EXPR
- && TREE_CODE (type) == REAL_TYPE)
+ if (TREE_CODE (arg0) == NOP_EXPR
+ && TREE_CODE (type) == REAL_TYPE)
{
tree targ0 = strip_float_extensions (arg0);
if (targ0 != arg0)
@@ -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,
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)
return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
return NULL_TREE;
case BIT_NOT_EXPR:
- if (TREE_CODE (arg0) == INTEGER_CST)
- return fold_not_const (arg0, type);
/* 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,
fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)),
build_int_cst (type, 1));
@@ -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,
fold_convert_loc (loc, type,
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;
@@ -7932,8 +8069,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
case REALPART_EXPR:
if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
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)
{
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)
case IMAGPART_EXPR:
if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_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)
{
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)
}
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:
return NULL_TREE;
} /* switch (code) */
@@ -9689,19 +9752,13 @@ fold_binary_loc (location_t loc,
/* Note that TREE_CONSTANT isn't enough: static var addresses are
constant but we can't do arithmetic on them. */
- if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
- || (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 (CONSTANT_CLASS_P (arg0) && CONSTANT_CLASS_P (arg1))
{
if (kind == tcc_binary)
{
/* Make sure type and arg0 have the same saturating flag. */
- gcc_assert (TYPE_SATURATING (type)
- == TYPE_SATURATING (TREE_TYPE (arg0)));
+ gcc_checking_assert (TYPE_SATURATING (type)
+ == TYPE_SATURATING (TREE_TYPE (arg0)));
tem = const_binop (code, arg0, arg1);
}
else if (kind == tcc_comparison)