Commit 38a73435 by Aldy Hernandez Committed by Aldy Hernandez

Makefile.in (OBJS): Add range.o and range-op.o.

	* Makefile.in (OBJS): Add range.o and range-op.o.
	Remove wide-int-range.o.
	* function-tests.c (test_ranges): New.
	(function_tests_c_tests): Call test_ranges.
	* ipa-cp.c (ipa_vr_operation_and_type_effects): Call
	range_fold_unary_expr instead of extract_range_from_unary_expr.
	* ipa-prop.c (ipa_compute_jump_functions_for_edge): Same.
	* range-op.cc: New file.
	* range-op.h: New file.
	* range.cc: New file.
	* range.h: New file.
	* selftest.h (range_tests): New prototype.
	* ssa.h: Include range.h.
	* tree-vrp.c (value_range_base::value_range_base): New
	constructors.
	(value_range_base::singleton_p): Do not call
	ranges_from_anti_range until sure we will need to.
	(value_range_base::type): Rename gcc_assert to
	gcc_checking_assert.
	(vrp_val_is_max): New argument.
	(vrp_val_is_min): Same.
	(wide_int_range_set_zero_nonzero_bits): Move from
	wide-int-range.cc.
	(extract_range_into_wide_ints): Remove.
	(extract_range_from_multiplicative_op): Remove.
	(extract_range_from_pointer_plus_expr): Abstract POINTER_PLUS code
	from extract_range_from_binary_expr.
	(extract_range_from_plus_minus_expr): Abstract PLUS/MINUS code
	from extract_range_from_binary_expr.
	(extract_range_from_binary_expr): Remove.
	(normalize_for_range_ops): New.
	(range_fold_binary_expr): New.
	(range_fold_unary_expr): New.
	(value_range_base::num_pairs): New.
	(value_range_base::lower_bound): New.
	(value_range_base::upper_bound): New.
	(value_range_base::upper_bound): New.
	(value_range_base::contains_p): New.
	(value_range_base::invert): New.
	(value_range_base::union_): New.
	(value_range_base::intersect): New.
	(range_compatible_p): New.
	(value_range_base::operator==): New.
	(determine_value_range_1): Call range_fold_*expr instead of
	extract_range_from_*expr.
	* tree-vrp.h (class value_range_base): Add new constructors.
	Add methods for union_, intersect, operator==, contains_p,
	num_pairs, lower_bound, upper_bound, invert.
	(vrp_val_is_min): Add handle_pointers argument.
	(vrp_val_is_max): Same.
	(extract_range_from_unary_expr): Remove.
	(extract_range_from_binary_expr): Remove.
	(range_fold_unary_expr): New.
	(range_fold_binary_expr): New.
	* vr-values.c (vr_values::extract_range_from_binary_expr): Call
	range_fold_binary_expr instead of extract_range_from_binary_expr.
	(vr_values::extract_range_basic): Same.
	(vr_values::extract_range_from_unary_expr): Call
	range_fold_unary_expr instead of extract_range_from_unary_expr.
	* wide-int-range.cc: Remove.
	* wide-int-range.h: Remove.

From-SVN: r276504
parent 0a8c8f4d
2019-10-03 Aldy Hernandez <aldyh@redhat.com>
* Makefile.in (OBJS): Add range.o and range-op.o.
Remove wide-int-range.o.
* function-tests.c (test_ranges): New.
(function_tests_c_tests): Call test_ranges.
* ipa-cp.c (ipa_vr_operation_and_type_effects): Call
range_fold_unary_expr instead of extract_range_from_unary_expr.
* ipa-prop.c (ipa_compute_jump_functions_for_edge): Same.
* range-op.cc: New file.
* range-op.h: New file.
* range.cc: New file.
* range.h: New file.
* selftest.h (range_tests): New prototype.
* ssa.h: Include range.h.
* tree-vrp.c (value_range_base::value_range_base): New
constructors.
(value_range_base::singleton_p): Do not call
ranges_from_anti_range until sure we will need to.
(value_range_base::type): Rename gcc_assert to
gcc_checking_assert.
(vrp_val_is_max): New argument.
(vrp_val_is_min): Same.
(wide_int_range_set_zero_nonzero_bits): Move from
wide-int-range.cc.
(extract_range_into_wide_ints): Remove.
(extract_range_from_multiplicative_op): Remove.
(extract_range_from_pointer_plus_expr): Abstract POINTER_PLUS code
from extract_range_from_binary_expr.
(extract_range_from_plus_minus_expr): Abstract PLUS/MINUS code
from extract_range_from_binary_expr.
(extract_range_from_binary_expr): Remove.
(normalize_for_range_ops): New.
(range_fold_binary_expr): New.
(range_fold_unary_expr): New.
(value_range_base::num_pairs): New.
(value_range_base::lower_bound): New.
(value_range_base::upper_bound): New.
(value_range_base::upper_bound): New.
(value_range_base::contains_p): New.
(value_range_base::invert): New.
(value_range_base::union_): New.
(value_range_base::intersect): New.
(range_compatible_p): New.
(value_range_base::operator==): New.
(determine_value_range_1): Call range_fold_*expr instead of
extract_range_from_*expr.
* tree-vrp.h (class value_range_base): Add new constructors.
Add methods for union_, intersect, operator==, contains_p,
num_pairs, lower_bound, upper_bound, invert.
(vrp_val_is_min): Add handle_pointers argument.
(vrp_val_is_max): Same.
(extract_range_from_unary_expr): Remove.
(extract_range_from_binary_expr): Remove.
(range_fold_unary_expr): New.
(range_fold_binary_expr): New.
* vr-values.c (vr_values::extract_range_from_binary_expr): Call
range_fold_binary_expr instead of extract_range_from_binary_expr.
(vr_values::extract_range_basic): Same.
(vr_values::extract_range_from_unary_expr): Call
range_fold_unary_expr instead of extract_range_from_unary_expr.
* wide-int-range.cc: Remove.
* wide-int-range.h: Remove.
2019-10-02 Michael Meissner <meissner@linux.ibm.com>
* config/rs6000/rs6000.c (mem_operand_gpr): Use
......
......@@ -1453,6 +1453,8 @@ OBJS = \
print-tree.o \
profile.o \
profile-count.o \
range.o \
range-op.o \
read-md.o \
read-rtl.o \
read-rtl-function.o \
......@@ -1611,7 +1613,6 @@ OBJS = \
web.o \
wide-int.o \
wide-int-print.o \
wide-int-range.o \
xcoffout.o \
$(out_object_file) \
$(EXTRA_OBJS) \
......
......@@ -570,6 +570,19 @@ test_conversion_to_ssa ()
ASSERT_EQ (SSA_NAME, TREE_CODE (gimple_return_retval (return_stmt)));
}
/* Test range folding. We must start this here because we need cfun
set. */
static void
test_ranges ()
{
tree fndecl = build_trivial_high_gimple_function ();
function *fun = DECL_STRUCT_FUNCTION (fndecl);
push_cfun (fun);
range_tests ();
pop_cfun ();
}
/* Test of expansion from gimple-ssa to RTL. */
static void
......@@ -674,6 +687,7 @@ function_tests_c_tests ()
test_gimplification ();
test_building_cfg ();
test_conversion_to_ssa ();
test_ranges ();
test_expansion_to_rtl ();
}
......
......@@ -1944,8 +1944,7 @@ ipa_vr_operation_and_type_effects (value_range_base *dst_vr,
enum tree_code operation,
tree dst_type, tree src_type)
{
extract_range_from_unary_expr (dst_vr, operation, dst_type,
src_vr, src_type);
range_fold_unary_expr (dst_vr, operation, dst_type, src_vr, src_type);
if (dst_vr->varying_p () || dst_vr->undefined_p ())
return false;
return true;
......
......@@ -1921,8 +1921,8 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
value_range_base tmpvr (type,
wide_int_to_tree (TREE_TYPE (arg), min),
wide_int_to_tree (TREE_TYPE (arg), max));
extract_range_from_unary_expr (&resvr, NOP_EXPR, param_type,
&tmpvr, TREE_TYPE (arg));
range_fold_unary_expr (&resvr, NOP_EXPR, param_type,
&tmpvr, TREE_TYPE (arg));
if (!resvr.undefined_p () && !resvr.varying_p ())
ipa_set_jfunc_vr (jfunc, &resvr);
else
......
This diff is collapsed. Click to expand it.
/* Header file for range operator class.
Copyright (C) 2017-2019 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>
and Aldy Hernandez <aldyh@redhat.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_RANGE_OP_H
#define GCC_RANGE_OP_H
// This class is implemented for each kind of operator supported by
// the range generator. It serves various purposes.
//
// 1 - Generates range information for the specific operation between
// two ranges. This provides the ability to fold ranges for an
// expression.
//
// 2 - Performs range algebra on the expression such that a range can be
// adjusted in terms of one of the operands:
//
// def = op1 + op2
//
// Given a range for def, we can adjust the range so that it is in
// terms of either operand.
//
// op1_range (def_range, op2) will adjust the range in place so it
// is in terms of op1. Since op1 = def - op2, it will subtract
// op2 from each element of the range.
//
// 3 - Creates a range for an operand based on whether the result is 0 or
// non-zero. This is mostly for logical true false, but can serve other
// purposes.
// ie 0 = op1 - op2 implies op2 has the same range as op1.
class range_operator
{
public:
// Perform an operation between 2 ranges and return it.
virtual value_range_base fold_range (tree type,
const value_range_base &lh,
const value_range_base &rh) const;
// Return the range for op[12] in the general case. LHS is the range for
// the LHS of the expression, OP[12]is the range for the other
//
// The operand and the result is returned in R.
//
// TYPE is the expected type of the range.
//
// Return TRUE if the operation is performed and a valid range is available.
//
// i.e. [LHS] = ??? + OP2
// is re-formed as R = [LHS] - OP2.
virtual bool op1_range (value_range_base &r, tree type,
const value_range_base &lhs,
const value_range_base &op2) const;
virtual bool op2_range (value_range_base &r, tree type,
const value_range_base &lhs,
const value_range_base &op1) const;
protected:
// Perform an operation between 2 sub-ranges and return it.
virtual value_range_base wi_fold (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const;
};
extern range_operator *range_op_handler (enum tree_code code, tree type);
extern void range_cast (value_range_base &, tree type);
#endif // GCC_RANGE_OP_H
/* Misc range functions.
Copyright (C) 2017-2019 Free Software Foundation, Inc.
Contributed by Aldy Hernandez <aldyh@redhat.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "gimple-pretty-print.h"
#include "fold-const.h"
#include "ssa.h"
#include "range.h"
value_range_base
range_intersect (const value_range_base &r1, const value_range_base &r2)
{
value_range_base tmp (r1);
tmp.intersect (r2);
return tmp;
}
value_range_base
range_invert (const value_range_base &r1)
{
value_range_base tmp (r1);
tmp.invert ();
return tmp;
}
value_range_base
range_union (const value_range_base &r1, const value_range_base &r2)
{
value_range_base tmp (r1);
tmp.union_ (r2);
return tmp;
}
value_range_base
range_zero (tree type)
{
return value_range_base (build_zero_cst (type), build_zero_cst (type));
}
value_range_base
range_nonzero (tree type)
{
return value_range_base (VR_ANTI_RANGE,
build_zero_cst (type), build_zero_cst (type));
}
value_range_base
range_positives (tree type)
{
unsigned prec = TYPE_PRECISION (type);
signop sign = TYPE_SIGN (type);
return value_range_base (type, wi::zero (prec), wi::max_value (prec, sign));
}
value_range_base
range_negatives (tree type)
{
unsigned prec = TYPE_PRECISION (type);
signop sign = TYPE_SIGN (type);
value_range_base r;
if (sign == UNSIGNED)
r.set_undefined ();
else
r = value_range_base (type, wi::min_value (prec, sign),
wi::minus_one (prec));
return r;
}
/* Header file for misc range functions. -*- C++ -*-
Copyright (C) 2017-2019 Free Software Foundation, Inc.
Contributed by Aldy Hernandez <aldyh@redhat.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_RANGE_H
#define GCC_RANGE_H
value_range_base range_zero (tree type);
value_range_base range_nonzero (tree type);
value_range_base range_intersect (const value_range_base &,
const value_range_base &);
value_range_base range_union (const value_range_base &,
const value_range_base &);
value_range_base range_invert (const value_range_base &);
value_range_base range_positives (tree type);
value_range_base range_negatives (tree type);
#endif // GCC_RANGE_H
......@@ -259,6 +259,10 @@ extern int num_passes;
} /* end of namespace selftest. */
/* This is outside of the selftest namespace because it's a friend of
value_range_base. */
extern void range_tests ();
/* Macros for writing tests. */
/* Evaluate EXPR and coerce to bool, calling
......
......@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "gimple-ssa.h"
#include "tree-vrp.h"
#include "range.h"
#include "tree-ssanames.h"
#include "tree-phinodes.h"
#include "ssa-iterators.h"
......
......@@ -35,14 +35,19 @@ enum value_range_kind
VR_LAST
};
/* Range of values that can be associated with an SSA_NAME after VRP
has executed. */
class GTY((for_user)) value_range_base
{
friend void range_tests ();
public:
value_range_base ();
value_range_base (value_range_kind, tree, tree);
value_range_base (tree, tree);
value_range_base (value_range_kind,
tree type, const wide_int &, const wide_int &);
value_range_base (tree type, const wide_int &, const wide_int &);
value_range_base (tree type);
void set (value_range_kind, tree, tree);
void set (tree);
......@@ -63,8 +68,10 @@ public:
void union_ (const value_range_base *);
void intersect (const value_range_base *);
void union_ (const value_range_base &);
void intersect (const value_range_base &);
bool operator== (const value_range_base &) const /* = delete */;
bool operator== (const value_range_base &) const;
bool operator!= (const value_range_base &) const /* = delete */;
bool equal_p (const value_range_base &) const;
......@@ -80,6 +87,14 @@ public:
static bool supports_type_p (tree);
value_range_base normalize_symbolics () const;
static const unsigned int m_max_pairs = 2;
bool contains_p (tree) const;
unsigned num_pairs () const;
wide_int lower_bound (unsigned = 0) const;
wide_int upper_bound (unsigned) const;
wide_int upper_bound () const;
void invert ();
protected:
void check ();
static value_range_base union_helper (const value_range_base *,
......@@ -281,21 +296,17 @@ extern bool range_int_cst_singleton_p (const value_range_base *);
extern int compare_values (tree, tree);
extern int compare_values_warnv (tree, tree, bool *);
extern int operand_less_p (tree, tree);
extern bool vrp_val_is_min (const_tree);
extern bool vrp_val_is_max (const_tree);
extern bool vrp_val_is_min (const_tree, bool handle_pointers = false);
extern bool vrp_val_is_max (const_tree, bool handle_pointers = false);
extern tree vrp_val_min (const_tree, bool handle_pointers = false);
extern tree vrp_val_max (const_tree, bool handle_pointers = false);
extern void extract_range_from_unary_expr (value_range_base *vr,
enum tree_code code,
tree type,
const value_range_base *vr0_,
tree op0_type);
extern void extract_range_from_binary_expr (value_range_base *,
enum tree_code,
tree, const value_range_base *,
const value_range_base *);
void range_fold_unary_expr (value_range_base *, enum tree_code, tree type,
const value_range_base *, tree op0_type);
void range_fold_binary_expr (value_range_base *, enum tree_code, tree type,
const value_range_base *,
const value_range_base *);
extern bool vrp_operand_equal_p (const_tree, const_tree);
extern enum value_range_kind intersect_range_with_nonzero_bits
......
......@@ -46,8 +46,10 @@ along with GCC; see the file COPYING3. If not see
#include "case-cfn-macros.h"
#include "alloc-pool.h"
#include "attribs.h"
#include "range.h"
#include "vr-values.h"
#include "cfghooks.h"
#include "range-op.h"
/* Set value range VR to a non-negative range of type TYPE. */
......@@ -803,7 +805,7 @@ vr_values::extract_range_from_binary_expr (value_range *vr,
vrp_val_max (expr_type));
}
::extract_range_from_binary_expr (vr, code, expr_type, &vr0, &vr1);
range_fold_binary_expr (vr, code, expr_type, &vr0, &vr1);
/* Set value_range for n in following sequence:
def = __builtin_memchr (arg, 0, sz)
......@@ -864,7 +866,7 @@ vr_values::extract_range_from_binary_expr (value_range *vr,
else
n_vr1.set (VR_RANGE, op1, op1);
::extract_range_from_binary_expr (vr, code, expr_type, &vr0, &n_vr1);
range_fold_binary_expr (vr, code, expr_type, &vr0, &n_vr1);
}
if (vr->varying_p ()
......@@ -888,7 +890,7 @@ vr_values::extract_range_from_binary_expr (value_range *vr,
else
n_vr0.set (op0);
::extract_range_from_binary_expr (vr, code, expr_type, &n_vr0, &vr1);
range_fold_binary_expr (vr, code, expr_type, &n_vr0, &vr1);
}
/* If we didn't derive a range for MINUS_EXPR, and
......@@ -929,7 +931,7 @@ vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code code,
else
vr0.set_varying (type);
::extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
range_fold_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
}
......@@ -1427,8 +1429,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
type, op0);
extract_range_from_unary_expr (&vr1, NOP_EXPR,
type, op1);
::extract_range_from_binary_expr (vr, subcode, type,
&vr0, &vr1);
range_fold_binary_expr (vr, subcode, type, &vr0, &vr1);
flag_wrapv = saved_flag_wrapv;
}
return;
......
/* Support routines for range operations on wide ints.
Copyright (C) 2018-2019 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_WIDE_INT_RANGE_H
#define GCC_WIDE_INT_RANGE_H
extern bool wide_int_range_cross_product (wide_int &res_lb, wide_int &res_ub,
enum tree_code code, signop sign,
const wide_int &, const wide_int &,
const wide_int &, const wide_int &,
bool overflow_undefined);
extern bool wide_int_range_mult_wrapping (wide_int &res_lb,
wide_int &res_ub,
signop sign,
unsigned prec,
const wide_int &min0_,
const wide_int &max0_,
const wide_int &min1_,
const wide_int &max1_);
extern bool wide_int_range_multiplicative_op (wide_int &res_lb,
wide_int &res_ub,
enum tree_code code,
signop sign,
unsigned prec,
const wide_int &vr0_lb,
const wide_int &vr0_ub,
const wide_int &vr1_lb,
const wide_int &vr1_ub,
bool overflow_undefined);
extern bool wide_int_range_lshift (wide_int &res_lb, wide_int &res_ub,
signop sign, unsigned prec,
const wide_int &, const wide_int &,
const wide_int &, const wide_int &,
bool overflow_undefined);
extern void wide_int_range_set_zero_nonzero_bits (signop,
const wide_int &lb,
const wide_int &ub,
wide_int &may_be_nonzero,
wide_int &must_be_nonzero);
extern bool wide_int_range_optimize_bit_op (wide_int &res_lb, wide_int &res_ub,
enum tree_code code,
signop sign,
const wide_int &vr0_lb,
const wide_int &vr0_ub,
const wide_int &vr1_lb,
const wide_int &vr1_ub);
extern bool wide_int_range_get_mask_and_bounds (wide_int &mask,
wide_int &lower_bound,
wide_int &upper_bound,
const wide_int &vr0_min,
const wide_int &vr0_max,
const wide_int &vr1_min,
const wide_int &vr1_max);
extern bool wide_int_range_bit_xor (wide_int &wmin, wide_int &wmax,
signop sign,
unsigned prec,
const wide_int &must_be_nonzero0,
const wide_int &may_be_nonzero0,
const wide_int &must_be_nonzero1,
const wide_int &may_be_nonzero1);
extern bool wide_int_range_bit_ior (wide_int &wmin, wide_int &wmax,
signop sign,
const wide_int &vr0_min,
const wide_int &vr0_max,
const wide_int &vr1_min,
const wide_int &vr1_max,
const wide_int &must_be_nonzero0,
const wide_int &may_be_nonzero0,
const wide_int &must_be_nonzero1,
const wide_int &may_be_nonzero1);
extern bool wide_int_range_bit_and (wide_int &wmin, wide_int &wmax,
signop sign,
unsigned prec,
const wide_int &vr0_min,
const wide_int &vr0_max,
const wide_int &vr1_min,
const wide_int &vr1_max,
const wide_int &must_be_nonzero0,
const wide_int &may_be_nonzero0,
const wide_int &must_be_nonzero1,
const wide_int &may_be_nonzero1);
extern void wide_int_range_trunc_mod (wide_int &wmin, wide_int &wmax,
signop sign,
unsigned prec,
const wide_int &vr0_min,
const wide_int &vr0_max,
const wide_int &vr1_min,
const wide_int &vr1_max);
extern bool wide_int_range_abs (wide_int &min, wide_int &max,
signop sign, unsigned prec,
const wide_int &vr0_min,
const wide_int &vr0_max,
bool overflow_undefined);
extern void wide_int_range_absu (wide_int &min, wide_int &max,
unsigned prec,
const wide_int &vr0_min,
const wide_int &vr0_max);
extern bool wide_int_range_convert (wide_int &min, wide_int &max,
signop inner_sign,
unsigned inner_prec,
signop outer_sign,
unsigned outer_prec,
const wide_int &vr0_min,
const wide_int &vr0_max);
extern bool wide_int_range_div (wide_int &wmin, wide_int &wmax,
enum tree_code code,
signop sign, unsigned prec,
const wide_int &dividend_min,
const wide_int &dividend_max,
const wide_int &divisor_min,
const wide_int &divisor_max,
bool overflow_undefined,
bool &extra_range_p,
wide_int &extra_min, wide_int &extra_max);
/* Return TRUE if shifting by range [MIN, MAX] is undefined behavior,
interpreting MIN and MAX according to SIGN. */
inline bool
wide_int_range_shift_undefined_p (signop sign, unsigned prec,
const wide_int &min, const wide_int &max)
{
/* ?? Note: The original comment said this only applied to
RSHIFT_EXPR, but it was being applied to both left and right
shifts. */
/* Shifting by any values outside [0..prec-1], gets undefined
behavior from the shift operation. We cannot even trust
SHIFT_COUNT_TRUNCATED at this stage, because that applies to rtl
shifts, and the operation at the tree level may be widened. */
return wi::lt_p (min, 0, sign) || wi::ge_p (max, prec, sign);
}
/* Calculate MIN/MAX_EXPR of two ranges and store the result in [MIN, MAX]. */
inline bool
wide_int_range_min_max (wide_int &min, wide_int &max,
tree_code code,
signop sign, unsigned prec,
const wide_int &vr0_min, const wide_int &vr0_max,
const wide_int &vr1_min, const wide_int &vr1_max)
{
wi::overflow_type overflow;
wide_int_binop (min, code, vr0_min, vr1_min, sign, &overflow);
wide_int_binop (max, code, vr0_max, vr1_max, sign, &overflow);
/* If the new range covers the entire domain, that's really no range
at all. */
if (min == wi::min_value (prec, sign)
&& max == wi::max_value (prec, sign))
return false;
return true;
}
/* Return TRUE if 0 is within [WMIN, WMAX]. */
inline bool
wide_int_range_includes_zero_p (const wide_int &wmin, const wide_int &wmax,
signop sign)
{
return wi::le_p (wmin, 0, sign) && wi::ge_p (wmax, 0, sign);
}
/* Return TRUE if [WMIN, WMAX] is the singleton 0. */
inline bool
wide_int_range_zero_p (const wide_int &wmin, const wide_int &wmax,
unsigned prec)
{
return wmin == wmax && wi::eq_p (wmin, wi::zero (prec));
}
#endif /* GCC_WIDE_INT_RANGE_H */
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