From cd04ce7fb911311dae2532765e6b7b89c14c2561 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 1 Dec 2014 15:43:58 +0000 Subject: [PATCH] fold-const.c (const_binop): Handle POINTER_PLUS_EXPR. 2014-12-01 Richard Biener * fold-const.c (const_binop): Handle POINTER_PLUS_EXPR. Properly handle FIXED_CST shifts by INTEGER_CST. (const_binop): Move COMPLEX_EXPR, VEC_PACK_TRUNC_EXPR, VEC_PACK_FIX_TRUNC_EXPR, VEC_WIDEN_MULT_LO_EXPR, VEC_WIDEN_MULT_HI_EXPR, VEC_WIDEN_MULT_EVEN_EXPR and VEC_WIDEN_MULT_ODD_EXPR handling here from ... (fold_binary_loc): ... here. Call const_binop overload with result type. From-SVN: r218223 --- gcc/ChangeLog | 11 +++ gcc/fold-const.c | 213 ++++++++++++++++++++++++----------------------- 2 files changed, 120 insertions(+), 104 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 08f40967ca8..f2c4587899a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2014-12-01 Richard Biener + + * fold-const.c (const_binop): Handle POINTER_PLUS_EXPR. + Properly handle FIXED_CST shifts by INTEGER_CST. + (const_binop): Move COMPLEX_EXPR, VEC_PACK_TRUNC_EXPR, + VEC_PACK_FIX_TRUNC_EXPR, VEC_WIDEN_MULT_LO_EXPR, + VEC_WIDEN_MULT_HI_EXPR, VEC_WIDEN_MULT_EVEN_EXPR and + VEC_WIDEN_MULT_ODD_EXPR handling here from ... + (fold_binary_loc): ... here. Call const_binop overload + with result type. + 2014-12-01 Marek Polacek Jakub Jelinek diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 51f3e2f3de3..29975e438c7 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -1134,7 +1134,13 @@ const_binop (enum tree_code code, tree arg1, tree arg2) STRIP_NOPS (arg2); if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg2) == INTEGER_CST) - return int_const_binop (code, arg1, arg2); + { + if (code == POINTER_PLUS_EXPR) + return int_const_binop (PLUS_EXPR, + arg1, fold_convert (TREE_TYPE (arg1), arg2)); + + return int_const_binop (code, arg1, arg2); + } if (TREE_CODE (arg1) == REAL_CST && TREE_CODE (arg2) == REAL_CST) { @@ -1214,7 +1220,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2) return t; } - if (TREE_CODE (arg1) == FIXED_CST && TREE_CODE (arg2) == FIXED_CST) + if (TREE_CODE (arg1) == FIXED_CST) { FIXED_VALUE_TYPE f1; FIXED_VALUE_TYPE f2; @@ -1230,12 +1236,16 @@ const_binop (enum tree_code code, tree arg1, tree arg2) case MINUS_EXPR: case MULT_EXPR: case TRUNC_DIV_EXPR: + if (TREE_CODE (arg2) != FIXED_CST) + return NULL_TREE; f2 = TREE_FIXED_CST (arg2); break; case LSHIFT_EXPR: case RSHIFT_EXPR: { + if (TREE_CODE (arg2) != INTEGER_CST) + return NULL_TREE; wide_int w2 = arg2; f2.data.high = w2.elt (1); f2.data.low = w2.elt (0); @@ -1443,8 +1453,102 @@ 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); + + /* ??? Until we make the const_binop worker take the type of the + result as argument put those cases that need it here. */ + switch (code) + { + case COMPLEX_EXPR: + if ((TREE_CODE (arg1) == REAL_CST + && TREE_CODE (arg2) == REAL_CST) + || (TREE_CODE (arg1) == INTEGER_CST + && TREE_CODE (arg2) == INTEGER_CST)) + return build_complex (type, arg1, arg2); + return NULL_TREE; + + case VEC_PACK_TRUNC_EXPR: + case VEC_PACK_FIX_TRUNC_EXPR: + { + unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i; + tree *elts; + + gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts / 2 + && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2)) == nelts / 2); + if (TREE_CODE (arg1) != VECTOR_CST + || TREE_CODE (arg2) != VECTOR_CST) + return NULL_TREE; + + elts = XALLOCAVEC (tree, nelts); + if (!vec_cst_ctor_to_array (arg1, elts) + || !vec_cst_ctor_to_array (arg2, elts + nelts / 2)) + return NULL_TREE; + + for (i = 0; i < nelts; i++) + { + elts[i] = fold_convert_const (code == VEC_PACK_TRUNC_EXPR + ? NOP_EXPR : FIX_TRUNC_EXPR, + TREE_TYPE (type), elts[i]); + if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i])) + return NULL_TREE; + } + + return build_vector (type, elts); + } + + case VEC_WIDEN_MULT_LO_EXPR: + case VEC_WIDEN_MULT_HI_EXPR: + case VEC_WIDEN_MULT_EVEN_EXPR: + case VEC_WIDEN_MULT_ODD_EXPR: + { + unsigned int nelts = TYPE_VECTOR_SUBPARTS (type); + unsigned int out, ofs, scale; + tree *elts; + + gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts * 2 + && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2)) == nelts * 2); + if (TREE_CODE (arg1) != VECTOR_CST || TREE_CODE (arg2) != VECTOR_CST) + return NULL_TREE; + + elts = XALLOCAVEC (tree, nelts * 4); + if (!vec_cst_ctor_to_array (arg1, elts) + || !vec_cst_ctor_to_array (arg2, elts + nelts * 2)) + return NULL_TREE; + + if (code == VEC_WIDEN_MULT_LO_EXPR) + scale = 0, ofs = BYTES_BIG_ENDIAN ? nelts : 0; + else if (code == VEC_WIDEN_MULT_HI_EXPR) + scale = 0, ofs = BYTES_BIG_ENDIAN ? 0 : nelts; + else if (code == VEC_WIDEN_MULT_EVEN_EXPR) + scale = 1, ofs = 0; + else /* if (code == VEC_WIDEN_MULT_ODD_EXPR) */ + scale = 1, ofs = 1; + + for (out = 0; out < nelts; out++) + { + unsigned int in1 = (out << scale) + ofs; + unsigned int in2 = in1 + nelts * 2; + tree t1, t2; + + t1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in1]); + t2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in2]); + + if (t1 == NULL_TREE || t2 == NULL_TREE) + return NULL_TREE; + elts[out] = const_binop (MULT_EXPR, t1, t2); + if (elts[out] == NULL_TREE || !CONSTANT_CLASS_P (elts[out])) + return NULL_TREE; + } + + return build_vector (type, elts); + } + + default:; + } + + /* Make sure type and arg0 have the same saturating flag. */ + gcc_checking_assert (TYPE_SATURATING (type) + == TYPE_SATURATING (TREE_TYPE (arg1))); + return const_binop (code, arg1, arg2); } /* Compute CODE ARG1 with resulting type TYPE with ARG1 being constant. @@ -9756,18 +9860,7 @@ fold_binary_loc (location_t loc, constant but we can't do arithmetic on them. */ if (CONSTANT_CLASS_P (arg0) && CONSTANT_CLASS_P (arg1)) { - if (kind == tcc_binary) - { - /* Make sure type and arg0 have the same saturating flag. */ - gcc_checking_assert (TYPE_SATURATING (type) - == TYPE_SATURATING (TREE_TYPE (arg0))); - tem = const_binop (code, arg0, arg1); - } - else if (kind == tcc_comparison) - tem = fold_relational_const (code, type, arg0, arg1); - else - tem = NULL_TREE; - + tem = const_binop (code, type, arg0, arg1); if (tem != NULL_TREE) { if (TREE_TYPE (tem) != type) @@ -9920,11 +10013,6 @@ fold_binary_loc (location_t loc, fold_convert_loc (loc, sizetype, arg0))); - /* PTR_CST +p CST -> CST1 */ - if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) - return fold_build2_loc (loc, PLUS_EXPR, type, arg0, - fold_convert_loc (loc, type, arg1)); - return NULL_TREE; case PLUS_EXPR: @@ -13126,93 +13214,10 @@ fold_binary_loc (location_t loc, : fold_convert_loc (loc, type, arg1); return pedantic_non_lvalue_loc (loc, tem); - case COMPLEX_EXPR: - if ((TREE_CODE (arg0) == REAL_CST - && TREE_CODE (arg1) == REAL_CST) - || (TREE_CODE (arg0) == INTEGER_CST - && TREE_CODE (arg1) == INTEGER_CST)) - return build_complex (type, arg0, arg1); - return NULL_TREE; - case ASSERT_EXPR: /* An ASSERT_EXPR should never be passed to fold_binary. */ gcc_unreachable (); - case VEC_PACK_TRUNC_EXPR: - case VEC_PACK_FIX_TRUNC_EXPR: - { - unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i; - tree *elts; - - gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts / 2 - && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts / 2); - if (TREE_CODE (arg0) != VECTOR_CST || TREE_CODE (arg1) != VECTOR_CST) - return NULL_TREE; - - elts = XALLOCAVEC (tree, nelts); - if (!vec_cst_ctor_to_array (arg0, elts) - || !vec_cst_ctor_to_array (arg1, elts + nelts / 2)) - return NULL_TREE; - - for (i = 0; i < nelts; i++) - { - elts[i] = fold_convert_const (code == VEC_PACK_TRUNC_EXPR - ? NOP_EXPR : FIX_TRUNC_EXPR, - TREE_TYPE (type), elts[i]); - if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i])) - return NULL_TREE; - } - - return build_vector (type, elts); - } - - case VEC_WIDEN_MULT_LO_EXPR: - case VEC_WIDEN_MULT_HI_EXPR: - case VEC_WIDEN_MULT_EVEN_EXPR: - case VEC_WIDEN_MULT_ODD_EXPR: - { - unsigned int nelts = TYPE_VECTOR_SUBPARTS (type); - unsigned int out, ofs, scale; - tree *elts; - - gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2 - && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts * 2); - if (TREE_CODE (arg0) != VECTOR_CST || TREE_CODE (arg1) != VECTOR_CST) - return NULL_TREE; - - elts = XALLOCAVEC (tree, nelts * 4); - if (!vec_cst_ctor_to_array (arg0, elts) - || !vec_cst_ctor_to_array (arg1, elts + nelts * 2)) - return NULL_TREE; - - if (code == VEC_WIDEN_MULT_LO_EXPR) - scale = 0, ofs = BYTES_BIG_ENDIAN ? nelts : 0; - else if (code == VEC_WIDEN_MULT_HI_EXPR) - scale = 0, ofs = BYTES_BIG_ENDIAN ? 0 : nelts; - else if (code == VEC_WIDEN_MULT_EVEN_EXPR) - scale = 1, ofs = 0; - else /* if (code == VEC_WIDEN_MULT_ODD_EXPR) */ - scale = 1, ofs = 1; - - for (out = 0; out < nelts; out++) - { - unsigned int in1 = (out << scale) + ofs; - unsigned int in2 = in1 + nelts * 2; - tree t1, t2; - - t1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in1]); - t2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in2]); - - if (t1 == NULL_TREE || t2 == NULL_TREE) - return NULL_TREE; - elts[out] = const_binop (MULT_EXPR, t1, t2); - if (elts[out] == NULL_TREE || !CONSTANT_CLASS_P (elts[out])) - return NULL_TREE; - } - - return build_vector (type, elts); - } - default: return NULL_TREE; } /* switch (code) */ -- 2.30.2