diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9f76c923ad8..240bda5789c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,36 @@ +2019-11-14 Andrew MacLeod + + * range-op.h (range_operator::fold_range): Return a bool. + * range-op.cc (range_operator::wi_fold): Assert supported type. + (range_operator::fold_range): Assert supported type and return true. + (operator_equal::fold_range): Return true. + (operator_not_equal::fold_range): Same. + (operator_lt::fold_range): Same. + (operator_le::fold_range): Same. + (operator_gt::fold_range): Same. + (operator_ge::fold_range): Same. + (operator_plus::op1_range): Adjust call to fold_range. + (operator_plus::op2_range): Same. + (operator_minus::op1_range): Same. + (operator_minus::op2_range): Same. + (operator_exact_divide::op1_range): Same. + (operator_lshift::fold_range): Return true and adjust fold_range call. + (operator_rshift::fold_range): Same. + (operator_cast::fold_range): Return true. + (operator_logical_and::fold_range): Same. + (operator_logical_or::fold_range): Same. + (operator_logical_not::fold_range): Same. + (operator_bitwise_not::fold_range): Adjust call to fold_range. + (operator_bitwise_not::op1_range): Same. + (operator_cst::fold_range): Return true. + (operator_identity::fold_range): Return true. + (operator_negate::fold_range): Return true and adjust fold_range call. + (operator_addr_expr::fold_range): Return true. + (operator_addr_expr::op1_range): Adjust call to fold_range. + (range_cast): Same. + * tree-vrp.c (range_fold_binary_symbolics_p): Adjust call to fold_range. + (range_fold_unary_symbolics_p): Same. + 2019-11-14 Andrew MacLeod PR tree-optimization/92506 diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 39c35919dec..59d5d006d2e 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -131,19 +131,21 @@ range_operator::wi_fold (value_range &r, tree type, const wide_int &rh_lb ATTRIBUTE_UNUSED, const wide_int &rh_ub ATTRIBUTE_UNUSED) const { + gcc_checking_assert (value_range::supports_type_p (type)); r = value_range (type); } // The default for fold is to break all ranges into sub-ranges and // invoke the wi_fold method on each sub-range pair. -void +bool range_operator::fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh) const { + gcc_checking_assert (value_range::supports_type_p (type)); if (empty_range_check (r, lh, rh)) - return; + return true; value_range tmp; r.set_undefined (); @@ -157,8 +159,9 @@ range_operator::fold_range (value_range &r, tree type, wi_fold (tmp, type, lh_lb, lh_ub, rh_lb, rh_ub); r.union_ (tmp); if (r.varying_p ()) - return; + return true; } + return true; } // The default for op1_range is to return false. @@ -364,7 +367,7 @@ get_bool_state (value_range &r, const value_range &lhs, tree val_type) class operator_equal : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual bool op1_range (value_range &r, tree type, @@ -375,13 +378,13 @@ public: const value_range &val) const; } op_equal; -void +bool operator_equal::fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const { if (empty_range_check (r, op1, op2)) - return; + return true; // We can be sure the values are always equal or not if both ranges // consist of a single value, and then compare them. @@ -404,6 +407,7 @@ operator_equal::fold_range (value_range &r, tree type, else r = range_true_and_false (type); } + return true; } bool @@ -448,7 +452,7 @@ operator_equal::op2_range (value_range &r, tree type, class operator_not_equal : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual bool op1_range (value_range &r, tree type, @@ -459,13 +463,13 @@ public: const value_range &op1) const; } op_not_equal; -void +bool operator_not_equal::fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const { if (empty_range_check (r, op1, op2)) - return; + return true; // We can be sure the values are always equal or not if both ranges // consist of a single value, and then compare them. @@ -488,6 +492,7 @@ operator_not_equal::fold_range (value_range &r, tree type, else r = range_true_and_false (type); } + return true; } bool @@ -578,7 +583,7 @@ build_ge (value_range &r, tree type, const wide_int &val) class operator_lt : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual bool op1_range (value_range &r, tree type, @@ -589,13 +594,13 @@ public: const value_range &op1) const; } op_lt; -void +bool operator_lt::fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const { if (empty_range_check (r, op1, op2)) - return; + return true; signop sign = TYPE_SIGN (op1.type ()); gcc_checking_assert (sign == TYPE_SIGN (op2.type ())); @@ -606,6 +611,7 @@ operator_lt::fold_range (value_range &r, tree type, r = range_false (type); else r = range_true_and_false (type); + return true; } bool @@ -654,7 +660,7 @@ operator_lt::op2_range (value_range &r, tree type, class operator_le : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual bool op1_range (value_range &r, tree type, @@ -665,13 +671,13 @@ public: const value_range &op1) const; } op_le; -void +bool operator_le::fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const { if (empty_range_check (r, op1, op2)) - return; + return true; signop sign = TYPE_SIGN (op1.type ()); gcc_checking_assert (sign == TYPE_SIGN (op2.type ())); @@ -682,6 +688,7 @@ operator_le::fold_range (value_range &r, tree type, r = range_false (type); else r = range_true_and_false (type); + return true; } bool @@ -730,7 +737,7 @@ operator_le::op2_range (value_range &r, tree type, class operator_gt : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual bool op1_range (value_range &r, tree type, @@ -741,12 +748,12 @@ public: const value_range &op1) const; } op_gt; -void +bool operator_gt::fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const { if (empty_range_check (r, op1, op2)) - return; + return true; signop sign = TYPE_SIGN (op1.type ()); gcc_checking_assert (sign == TYPE_SIGN (op2.type ())); @@ -757,6 +764,7 @@ operator_gt::fold_range (value_range &r, tree type, r = range_false (type); else r = range_true_and_false (type); + return true; } bool @@ -804,7 +812,7 @@ operator_gt::op2_range (value_range &r, tree type, class operator_ge : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual bool op1_range (value_range &r, tree type, @@ -815,13 +823,13 @@ public: const value_range &op1) const; } op_ge; -void +bool operator_ge::fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const { if (empty_range_check (r, op1, op2)) - return; + return true; signop sign = TYPE_SIGN (op1.type ()); gcc_checking_assert (sign == TYPE_SIGN (op2.type ())); @@ -832,6 +840,7 @@ operator_ge::fold_range (value_range &r, tree type, r = range_false (type); else r = range_true_and_false (type); + return true; } bool @@ -910,8 +919,7 @@ operator_plus::op1_range (value_range &r, tree type, const value_range &lhs, const value_range &op2) const { - range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2); - return true; + return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2); } bool @@ -919,8 +927,7 @@ operator_plus::op2_range (value_range &r, tree type, const value_range &lhs, const value_range &op1) const { - range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1); - return true; + return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1); } @@ -957,8 +964,7 @@ operator_minus::op1_range (value_range &r, tree type, const value_range &lhs, const value_range &op2) const { - range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2); - return true; + return range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2); } bool @@ -966,8 +972,7 @@ operator_minus::op2_range (value_range &r, tree type, const value_range &lhs, const value_range &op1) const { - fold_range (r, type, op1, lhs); - return true; + return fold_range (r, type, op1, lhs); } @@ -1351,10 +1356,7 @@ operator_exact_divide::op1_range (value_range &r, tree type, // If op2 is a multiple of 2, we would be able to set some non-zero bits. if (op2.singleton_p (&offset) && !integer_zerop (offset)) - { - range_op_handler (MULT_EXPR, type)->fold_range (r, type, lhs, op2); - return true; - } + return range_op_handler (MULT_EXPR, type)->fold_range (r, type, lhs, op2); return false; } @@ -1362,7 +1364,7 @@ operator_exact_divide::op1_range (value_range &r, tree type, class operator_lshift : public cross_product_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; @@ -1375,13 +1377,13 @@ public: const wide_int &) const; } op_lshift; -void +bool operator_lshift::fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const { if (undefined_shift_range_check (r, type, op2)) - return; + return true; // Transform left shifts by constants into multiplies. if (op2.singleton_p ()) @@ -1395,14 +1397,15 @@ operator_lshift::fold_range (value_range &r, tree type, bool saved_flag_wrapv_pointer = flag_wrapv_pointer; flag_wrapv = 1; flag_wrapv_pointer = 1; - range_op_handler (MULT_EXPR, type)->fold_range (r, type, op1, mult); + bool b = range_op_handler (MULT_EXPR, type)->fold_range (r, type, op1, + mult); flag_wrapv = saved_flag_wrapv; flag_wrapv_pointer = saved_flag_wrapv_pointer; - return; + return b; } - - // Otherwise, invoke the generic fold routine. - range_operator::fold_range (r, type, op1, op2); + else + // Otherwise, invoke the generic fold routine. + return range_operator::fold_range (r, type, op1, op2); } void @@ -1486,7 +1489,7 @@ operator_lshift::wi_op_overflows (wide_int &res, tree type, class operator_rshift : public cross_product_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual void wi_fold (value_range &r, tree type, @@ -1519,16 +1522,16 @@ operator_rshift::wi_op_overflows (wide_int &res, return false; } -void +bool operator_rshift::fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const { + // Invoke the generic fold routine if not undefined.. if (undefined_shift_range_check (r, type, op2)) - return; + return true; - // Otherwise, invoke the generic fold routine. - range_operator::fold_range (r, type, op1, op2); + return range_operator::fold_range (r, type, op1, op2); } void @@ -1543,7 +1546,7 @@ operator_rshift::wi_fold (value_range &r, tree type, class operator_cast: public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual bool op1_range (value_range &r, tree type, @@ -1552,13 +1555,13 @@ public: } op_convert; -void +bool operator_cast::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED, const value_range &lh, const value_range &rh) const { if (empty_range_check (r, lh, rh)) - return; + return true; tree inner = lh.type (); tree outer = rh.type (); @@ -1598,8 +1601,9 @@ operator_cast::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED, } } r = value_range (type); - return; + break; } + return true; } bool @@ -1682,7 +1686,7 @@ operator_cast::op1_range (value_range &r, tree type, class operator_logical_and : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh) const; virtual bool op1_range (value_range &r, tree type, @@ -1694,13 +1698,13 @@ public: } op_logical_and; -void +bool operator_logical_and::fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh) const { if (empty_range_check (r, lh, rh)) - return; + return true; // 0 && anything is 0. if ((wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (lh.upper_bound (), 0)) @@ -1713,6 +1717,7 @@ operator_logical_and::fold_range (value_range &r, tree type, r = range_true_and_false (type); else r = range_true (type); + return true; } bool @@ -1964,7 +1969,7 @@ operator_bitwise_and::op2_range (value_range &r, tree type, class operator_logical_or : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh) const; virtual bool op1_range (value_range &r, tree type, @@ -1975,16 +1980,17 @@ public: const value_range &op1) const; } op_logical_or; -void +bool operator_logical_or::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED, const value_range &lh, const value_range &rh) const { if (empty_range_check (r, lh, rh)) - return; + return true; r = lh; r.union_ (rh); + return true; } bool @@ -2198,7 +2204,7 @@ operator_trunc_mod::wi_fold (value_range &r, tree type, class operator_logical_not : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh) const; virtual bool op1_range (value_range &r, tree type, @@ -2220,13 +2226,13 @@ public: // b_2 = x_1 < 20 [0,0] = x_1 < 20, false, so x_1 == [20, 255] // which is the result we are looking for.. so.. pass it through. -void +bool operator_logical_not::fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh ATTRIBUTE_UNUSED) const { if (empty_range_check (r, lh, rh)) - return; + return true; if (lh.varying_p () || lh.undefined_p ()) r = lh; @@ -2236,7 +2242,7 @@ operator_logical_not::fold_range (value_range &r, tree type, r.invert (); } gcc_checking_assert (lh.type() == type); - return; + return true; } bool @@ -2255,7 +2261,7 @@ operator_logical_not::op1_range (value_range &r, class operator_bitwise_not : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh) const; virtual bool op1_range (value_range &r, tree type, @@ -2263,19 +2269,19 @@ public: const value_range &op2) const; } op_bitwise_not; -void +bool operator_bitwise_not::fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh) const { if (empty_range_check (r, lh, rh)) - return; + return true; // ~X is simply -1 - X. value_range minusone (type, wi::minus_one (TYPE_PRECISION (type)), wi::minus_one (TYPE_PRECISION (type))); - range_op_handler (MINUS_EXPR, type)->fold_range (r, type, minusone, lh); - return; + return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, minusone, + lh); } bool @@ -2284,32 +2290,32 @@ operator_bitwise_not::op1_range (value_range &r, tree type, const value_range &op2) const { // ~X is -1 - X and since bitwise NOT is involutary...do it again. - fold_range (r, type, lhs, op2); - return true; + return fold_range (r, type, lhs, op2); } class operator_cst : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; } op_integer_cst; -void +bool operator_cst::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED, const value_range &lh, const value_range &rh ATTRIBUTE_UNUSED) const { r = lh; + return true; } class operator_identity : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual bool op1_range (value_range &r, tree type, @@ -2317,12 +2323,13 @@ public: const value_range &op2) const; } op_identity; -void +bool operator_identity::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED, const value_range &lh, const value_range &rh ATTRIBUTE_UNUSED) const { r = lh; + return true; } bool @@ -2485,7 +2492,7 @@ operator_absu::wi_fold (value_range &r, tree type, class operator_negate : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual bool op1_range (value_range &r, tree type, @@ -2493,16 +2500,17 @@ class operator_negate : public range_operator const value_range &op2) const; } op_negate; -void +bool operator_negate::fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh) const { if (empty_range_check (r, lh, rh)) - return; + return true; // -X is simply 0 - X. - range_op_handler (MINUS_EXPR, type)->fold_range (r, type, - range_zero (type), lh); + return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, + range_zero (type), + lh); } bool @@ -2511,15 +2519,14 @@ operator_negate::op1_range (value_range &r, tree type, const value_range &op2) const { // NEGATE is involutory. - fold_range (r, type, lhs, op2); - return true; + return fold_range (r, type, lhs, op2); } class operator_addr_expr : public range_operator { public: - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &op1, const value_range &op2) const; virtual bool op1_range (value_range &r, tree type, @@ -2527,13 +2534,13 @@ public: const value_range &op2) const; } op_addr; -void +bool operator_addr_expr::fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh) const { if (empty_range_check (r, lh, rh)) - return; + return true; // Return a non-null pointer of the LHS type (passed in op2). if (lh.zero_p ()) @@ -2542,6 +2549,7 @@ operator_addr_expr::fold_range (value_range &r, tree type, r = range_nonzero (type); else r = value_range (type); + return true; } bool @@ -2549,8 +2557,7 @@ operator_addr_expr::op1_range (value_range &r, tree type, const value_range &lhs, const value_range &op2) const { - operator_addr_expr::fold_range (r, type, lhs, op2); - return true; + return operator_addr_expr::fold_range (r, type, lhs, op2); } @@ -2808,7 +2815,9 @@ range_cast (value_range &r, tree type) { value_range tmp = r; range_operator *op = range_op_handler (CONVERT_EXPR, type); - op->fold_range (r, type, tmp, value_range (type)); + // Call op_convert, if it fails, the result is varying. + if (!op->fold_range (r, type, tmp, value_range (type))) + r = value_range (type); } #if CHECKING_P diff --git a/gcc/range-op.h b/gcc/range-op.h index 4b0b57225a3..458b42ffe7f 100644 --- a/gcc/range-op.h +++ b/gcc/range-op.h @@ -50,7 +50,7 @@ class range_operator { public: // Perform an operation between 2 ranges and return it. - virtual void fold_range (value_range &r, tree type, + virtual bool fold_range (value_range &r, tree type, const value_range &lh, const value_range &rh) const; @@ -73,7 +73,7 @@ public: const value_range &op1) const; protected: - // Perform an operation between 2 sub-ranges and return it. + // Perform an integral operation between 2 sub-ranges and return it. virtual void wi_fold (value_range &r, tree type, const wide_int &lh_lb, const wide_int &lh_ub, diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index ff66bed4b03..bbcf237a925 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1185,8 +1185,7 @@ range_fold_binary_symbolics_p (value_range *vr, value_range vr0_cst (*vr0), vr1_cst (*vr1); vr0_cst.normalize_symbolics (); vr1_cst.normalize_symbolics (); - op->fold_range (*vr, expr_type, vr0_cst, vr1_cst); - return true; + return op->fold_range (*vr, expr_type, vr0_cst, vr1_cst); } return false; } @@ -1221,8 +1220,7 @@ range_fold_unary_symbolics_p (value_range *vr, const range_operator *op = get_range_op_handler (vr, code, expr_type); value_range vr0_cst (*vr0); vr0_cst.normalize_symbolics (); - op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); - return true; + return op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); } return false; }