diff options
Diffstat (limited to 'gcc/fold-const.cc')
| -rw-r--r-- | gcc/fold-const.cc | 233 |
1 files changed, 142 insertions, 91 deletions
diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 3e20538..5353777 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see @@ This would also make life easier when this technology is used @@ for cross-compilers. */ -/* The entry points in this file are fold, size_int_wide and size_binop. +/* The entry points in this file are fold, size_int and size_binop. fold takes a tree as argument and returns a simplified tree. @@ -151,74 +151,89 @@ static tree fold_view_convert_expr (tree, tree); static tree fold_negate_expr (location_t, tree); /* This is a helper function to detect min/max for some operands of COND_EXPR. + The form is "(exp0 CMP cst1) ? exp0 : cst2". */ +tree_code +minmax_from_comparison (tree_code cmp, tree exp0, + const widest_int cst1, + const widest_int cst2) +{ + if (cst1 == cst2) + { + if (cmp == LE_EXPR || cmp == LT_EXPR) + return MIN_EXPR; + if (cmp == GT_EXPR || cmp == GE_EXPR) + return MAX_EXPR; + } + if (cst1 == cst2 - 1) + { + /* X <= Y - 1 equals to X < Y. */ + if (cmp == LE_EXPR) + return MIN_EXPR; + /* X > Y - 1 equals to X >= Y. */ + if (cmp == GT_EXPR) + return MAX_EXPR; + /* a != MIN_RANGE<a> ? a : MIN_RANGE<a>+1 -> MAX_EXPR<MIN_RANGE<a>+1, a> */ + if (cmp == NE_EXPR && TREE_CODE (exp0) == SSA_NAME) + { + int_range_max r; + get_range_query (cfun)->range_of_expr (r, exp0); + if (r.undefined_p ()) + r.set_varying (TREE_TYPE (exp0)); + + widest_int min = widest_int::from (r.lower_bound (), + TYPE_SIGN (TREE_TYPE (exp0))); + if (min == cst1) + return MAX_EXPR; + } + } + if (cst1 == cst2 + 1) + { + /* X < Y + 1 equals to X <= Y. */ + if (cmp == LT_EXPR) + return MIN_EXPR; + /* X >= Y + 1 equals to X > Y. */ + if (cmp == GE_EXPR) + return MAX_EXPR; + /* a != MAX_RANGE<a> ? a : MAX_RANGE<a>-1 -> MIN_EXPR<MIN_RANGE<a>-1, a> */ + if (cmp == NE_EXPR && TREE_CODE (exp0) == SSA_NAME) + { + int_range_max r; + get_range_query (cfun)->range_of_expr (r, exp0); + if (r.undefined_p ()) + r.set_varying (TREE_TYPE (exp0)); + + widest_int max = widest_int::from (r.upper_bound (), + TYPE_SIGN (TREE_TYPE (exp0))); + if (max == cst1) + return MIN_EXPR; + } + } + return ERROR_MARK; +} + + +/* This is a helper function to detect min/max for some operands of COND_EXPR. The form is "(EXP0 CMP EXP1) ? EXP2 : EXP3". */ tree_code minmax_from_comparison (tree_code cmp, tree exp0, tree exp1, tree exp2, tree exp3) { - enum tree_code code = ERROR_MARK; - if (HONOR_NANS (exp0) || HONOR_SIGNED_ZEROS (exp0)) return ERROR_MARK; if (!operand_equal_p (exp0, exp2)) return ERROR_MARK; - if (TREE_CODE (exp3) == INTEGER_CST && TREE_CODE (exp1) == INTEGER_CST) - { - if (wi::to_widest (exp1) == (wi::to_widest (exp3) - 1)) - { - /* X <= Y - 1 equals to X < Y. */ - if (cmp == LE_EXPR) - code = LT_EXPR; - /* X > Y - 1 equals to X >= Y. */ - if (cmp == GT_EXPR) - code = GE_EXPR; - /* a != MIN_RANGE<a> ? a : MIN_RANGE<a>+1 -> MAX_EXPR<MIN_RANGE<a>+1, a> */ - if (cmp == NE_EXPR && TREE_CODE (exp0) == SSA_NAME) - { - int_range_max r; - get_range_query (cfun)->range_of_expr (r, exp0); - if (r.undefined_p ()) - r.set_varying (TREE_TYPE (exp0)); - - widest_int min = widest_int::from (r.lower_bound (), - TYPE_SIGN (TREE_TYPE (exp0))); - if (min == wi::to_widest (exp1)) - code = MAX_EXPR; - } - } - if (wi::to_widest (exp1) == (wi::to_widest (exp3) + 1)) - { - /* X < Y + 1 equals to X <= Y. */ - if (cmp == LT_EXPR) - code = LE_EXPR; - /* X >= Y + 1 equals to X > Y. */ - if (cmp == GE_EXPR) - code = GT_EXPR; - /* a != MAX_RANGE<a> ? a : MAX_RANGE<a>-1 -> MIN_EXPR<MIN_RANGE<a>-1, a> */ - if (cmp == NE_EXPR && TREE_CODE (exp0) == SSA_NAME) - { - int_range_max r; - get_range_query (cfun)->range_of_expr (r, exp0); - if (r.undefined_p ()) - r.set_varying (TREE_TYPE (exp0)); - - widest_int max = widest_int::from (r.upper_bound (), - TYPE_SIGN (TREE_TYPE (exp0))); - if (max == wi::to_widest (exp1)) - code = MIN_EXPR; - } - } - } - if (code != ERROR_MARK - || operand_equal_p (exp1, exp3)) + if (operand_equal_p (exp1, exp3)) { if (cmp == LT_EXPR || cmp == LE_EXPR) - code = MIN_EXPR; + return MIN_EXPR; if (cmp == GT_EXPR || cmp == GE_EXPR) - code = MAX_EXPR; + return MAX_EXPR; } - return code; + if (TREE_CODE (exp3) == INTEGER_CST + && TREE_CODE (exp1) == INTEGER_CST) + return minmax_from_comparison (cmp, exp0, wi::to_widest (exp1), wi::to_widest (exp3)); + return ERROR_MARK; } /* Return EXPR_LOCATION of T if it is not UNKNOWN_LOCATION. @@ -249,22 +264,6 @@ protected_set_expr_location_unshare (tree x, location_t loc) return x; } -/* If ARG2 divides ARG1 with zero remainder, carries out the exact - division and returns the quotient. Otherwise returns - NULL_TREE. */ - -tree -div_if_zero_remainder (const_tree arg1, const_tree arg2) -{ - widest_int quo; - - if (wi::multiple_of_p (wi::to_widest (arg1), wi::to_widest (arg2), - SIGNED, &quo)) - return wide_int_to_tree (TREE_TYPE (arg1), quo); - - return NULL_TREE; -} - /* This is nonzero if we should defer warnings about undefined overflow. This facility exists because these warnings are a special case. The code to estimate loop iterations does not want @@ -395,10 +394,14 @@ negate_mathfn_p (combined_fn fn) CASE_CFN_ASIN_FN: CASE_CFN_ASINH: CASE_CFN_ASINH_FN: + CASE_CFN_ASINPI: + CASE_CFN_ASINPI_FN: CASE_CFN_ATAN: CASE_CFN_ATAN_FN: CASE_CFN_ATANH: CASE_CFN_ATANH_FN: + CASE_CFN_ATANPI: + CASE_CFN_ATANPI_FN: CASE_CFN_CASIN: CASE_CFN_CASIN_FN: CASE_CFN_CASINH: @@ -432,10 +435,14 @@ negate_mathfn_p (combined_fn fn) CASE_CFN_SIN_FN: CASE_CFN_SINH: CASE_CFN_SINH_FN: + CASE_CFN_SINPI: + CASE_CFN_SINPI_FN: CASE_CFN_TAN: CASE_CFN_TAN_FN: CASE_CFN_TANH: CASE_CFN_TANH_FN: + CASE_CFN_TANPI: + CASE_CFN_TANPI_FN: CASE_CFN_TRUNC: CASE_CFN_TRUNC_FN: return true; @@ -1284,6 +1291,13 @@ poly_int_binop (poly_wide_int &res, enum tree_code code, return false; break; + case BIT_AND_EXPR: + if (TREE_CODE (arg2) != INTEGER_CST + || !can_and_p (wi::to_poly_wide (arg1), wi::to_wide (arg2), + &res)) + return false; + break; + case BIT_IOR_EXPR: if (TREE_CODE (arg2) != INTEGER_CST || !can_ior_p (wi::to_poly_wide (arg1), wi::to_wide (arg2), @@ -2169,12 +2183,12 @@ size_diffop_loc (location_t loc, tree arg0, tree arg1) MINUS_EXPR, arg1, arg0))); } - -/* A subroutine of fold_convert_const handling conversions of an - INTEGER_CST to another integer type. */ -static tree -fold_convert_const_int_from_int (tree type, const_tree arg1) +/* Convert integer constant ARG1 to TYPE, which is an integral or offset + or pointer type. */ + +tree +int_const_convert (tree type, const_tree arg1, int overflowable) { /* Given an integer constant, make new constant with new type, appropriately sign-extended or truncated. Use widest_int @@ -2183,7 +2197,7 @@ fold_convert_const_int_from_int (tree type, const_tree arg1) unsigned prec = MAX (TYPE_PRECISION (arg1_type), TYPE_PRECISION (type)); return force_fit_type (type, wide_int::from (wi::to_wide (arg1), prec, TYPE_SIGN (arg1_type)), - !POINTER_TYPE_P (TREE_TYPE (arg1)), + overflowable, TREE_OVERFLOW (arg1)); } @@ -2486,7 +2500,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1) || TREE_CODE (type) == OFFSET_TYPE) { if (TREE_CODE (arg1) == INTEGER_CST) - return fold_convert_const_int_from_int (type, arg1); + return int_const_convert (type, arg1, !POINTER_TYPE_P (arg_type)); else if (TREE_CODE (arg1) == REAL_CST) return fold_convert_const_int_from_real (code, type, arg1); else if (TREE_CODE (arg1) == FIXED_CST) @@ -5078,6 +5092,11 @@ simple_operand_p (const_tree exp) #pragma weak, etc). */ && ! TREE_PUBLIC (exp) && ! DECL_EXTERNAL (exp) + /* DECL_VALUE_EXPR will expand to something non-simple. */ + && ! ((VAR_P (exp) + || TREE_CODE (exp) == PARM_DECL + || TREE_CODE (exp) == RESULT_DECL) + && DECL_HAS_VALUE_EXPR_P (exp)) /* Weakrefs are not safe to be read, since they can be NULL. They are !TREE_PUBLIC && !DECL_EXTERNAL but still have DECL_WEAK flag set. */ @@ -7239,6 +7258,12 @@ tree_swap_operands_p (const_tree arg0, const_tree arg1) if (TREE_CONSTANT (arg0)) return true; + /* Put addresses in arg1. */ + if (TREE_CODE (arg1) == ADDR_EXPR) + return false; + if (TREE_CODE (arg0) == ADDR_EXPR) + return true; + /* It is preferable to swap two SSA_NAME to ensure a canonical form for commutative and comparison operators. Ensuring a canonical form allows the optimizers to find additional redundancies without @@ -9904,22 +9929,29 @@ pointer_may_wrap_p (tree base, tree offset, poly_int64 bitpos) static int maybe_nonzero_address (tree decl) { + if (!DECL_P (decl)) + return -1; + /* Normally, don't do anything for variables and functions before symtab is built; it is quite possible that DECL will be declared weak later. But if folding_initializer, we need a constant answer now, so create the symtab entry and prevent later weak declaration. */ - if (DECL_P (decl) && decl_in_symtab_p (decl)) - if (struct symtab_node *symbol - = (folding_initializer - ? symtab_node::get_create (decl) - : symtab_node::get (decl))) - return symbol->nonzero_address (); + if (decl_in_symtab_p (decl)) + { + if (struct symtab_node *symbol + = (folding_initializer + ? symtab_node::get_create (decl) + : symtab_node::get (decl))) + return symbol->nonzero_address (); + } + else if (folding_cxx_constexpr) + /* Anything that doesn't go in the symtab has non-zero address. */ + return 1; /* Function local objects are never NULL. */ - if (DECL_P (decl) - && (DECL_CONTEXT (decl) + if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL - && auto_var_in_fn_p (decl, DECL_CONTEXT (decl)))) + && auto_var_in_fn_p (decl, DECL_CONTEXT (decl))) return 1; return -1; @@ -10906,10 +10938,12 @@ tree_expr_nonzero_p (tree t) return ret; } -/* Return true if T is known not to be equal to an integer W. */ +/* Return true if T is known not to be equal to an integer W. + If STMT is specified, the check is if T on STMT is not equal + to W. */ bool -expr_not_equal_to (tree t, const wide_int &w) +expr_not_equal_to (tree t, const wide_int &w, gimple *stmt /* = NULL */) { int_range_max vr; switch (TREE_CODE (t)) @@ -10921,7 +10955,7 @@ expr_not_equal_to (tree t, const wide_int &w) if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) return false; - get_range_query (cfun)->range_of_expr (vr, t); + get_range_query (cfun)->range_of_expr (vr, t, stmt); if (!vr.undefined_p () && !vr.contains_p (w)) return true; /* If T has some known zero bits and W has any of those bits set, @@ -14937,6 +14971,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, CASE_CFN_ACOS_FN: CASE_CFN_ACOSH: CASE_CFN_ACOSH_FN: + CASE_CFN_ACOSPI: + CASE_CFN_ACOSPI_FN: CASE_CFN_CABS: CASE_CFN_CABS_FN: CASE_CFN_COSH: @@ -14981,10 +15017,14 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, CASE_CFN_ASINH: CASE_CFN_ASINH_FN: + CASE_CFN_ASINPI: + CASE_CFN_ASINPI_FN: CASE_CFN_ATAN: CASE_CFN_ATAN_FN: CASE_CFN_ATANH: CASE_CFN_ATANH_FN: + CASE_CFN_ATANPI: + CASE_CFN_ATANPI_FN: CASE_CFN_CBRT: CASE_CFN_CBRT_FN: CASE_CFN_CEIL: @@ -15185,7 +15225,7 @@ bool tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p, int depth) { enum tree_code code; - if (t == error_mark_node) + if (error_operand_p (t)) return false; code = TREE_CODE (t); @@ -16475,6 +16515,17 @@ split_address_to_core_and_offset (tree exp, core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos, poffset, &mode, &unsignedp, &reversep, &volatilep); + /* If we are left with MEM[a + CST] strip that and add it to the + pbitpos and return a. */ + if (TREE_CODE (core) == MEM_REF) + { + poly_offset_int tem; + tem = wi::to_poly_offset (TREE_OPERAND (core, 1)); + tem <<= LOG2_BITS_PER_UNIT; + tem += *pbitpos; + if (tem.to_shwi (pbitpos)) + return TREE_OPERAND (core, 0); + } core = build_fold_addr_expr_loc (loc, core); } else if (TREE_CODE (exp) == POINTER_PLUS_EXPR) |
