public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/ranger] Shuffle all the ranger code around into various files:
@ 2020-04-03 7:05 Aldy Hernandez
0 siblings, 0 replies; only message in thread
From: Aldy Hernandez @ 2020-04-03 7:05 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:fa8f67d081065db1b5692f5fc037139fb0d713a3
commit fa8f67d081065db1b5692f5fc037139fb0d713a3
Author: Aldy Hernandez <aldyh@redhat.com>
Date: Thu Apr 2 19:54:58 2020 +0200
Shuffle all the ranger code around into various files:
gimple-range-cache.*
gimple-range-stmt.*
gimple-range-gori.*
gimple-range-cfg.*
gimple-ranger.*
Diff:
---
gcc/Makefile.in | 7 +-
gcc/{ssa-range-cache.cc => gimple-range-cache.cc} | 25 +-
gcc/{ssa-range-cache.h => gimple-range-cache.h} | 4 +-
gcc/gimple-range-cfg.cc | 459 ++++++++++++++++++++++
gcc/gimple-range-cfg.h | 41 ++
gcc/gimple-range-gori.cc | 8 +-
gcc/gimple-range-gori.h | 4 +-
gcc/{gimple-range.cc => gimple-range-stmt.cc} | 18 +-
gcc/{gimple-range.h => gimple-range-stmt.h} | 11 +-
gcc/{ssa-range.cc => gimple-ranger.cc} | 451 +--------------------
gcc/{ssa-range.h => gimple-ranger.h} | 36 +-
gcc/gimple-ssa-evrp-analyze.c | 4 +-
gcc/vr-values.c | 2 +-
13 files changed, 543 insertions(+), 527 deletions(-)
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index d66e6da17bf..52ba2098a4a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1327,7 +1327,10 @@ OBJS = \
gimple-loop-versioning.o \
gimple-low.o \
gimple-pretty-print.o \
- gimple-range.o \
+ gimple-ranger.o \
+ gimple-range-cache.o \
+ gimple-range-cfg.o \
+ gimple-range-stmt.o \
gimple-range-gori.o \
gimple-ssa-backprop.o \
gimple-ssa-evrp.o \
@@ -1497,8 +1500,6 @@ OBJS = \
spellcheck.o \
spellcheck-tree.o \
sreal.o \
- ssa-range.o \
- ssa-range-cache.o \
stack-ptr-mod.o \
statistics.o \
stmt.o \
diff --git a/gcc/ssa-range-cache.cc b/gcc/gimple-range-cache.cc
similarity index 95%
rename from gcc/ssa-range-cache.cc
rename to gcc/gimple-range-cache.cc
index b8011a5945e..bfcc8901146 100644
--- a/gcc/ssa-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -1,5 +1,5 @@
-/* SSA range cache related functionalilty.
- Copyright (C) 2017-2018 Free Software Foundation, Inc.
+/* Gimple ranger SSA cache implementation.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>.
This file is part of GCC.
@@ -23,29 +23,12 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "backend.h"
#include "insn-codes.h"
-#include "rtl.h"
#include "tree.h"
#include "gimple.h"
-#include "cfghooks.h"
-#include "tree-pass.h"
#include "ssa.h"
-#include "optabs-tree.h"
#include "gimple-pretty-print.h"
-#include "diagnostic-core.h"
-#include "flags.h"
-#include "fold-const.h"
-#include "stor-layout.h"
-#include "calls.h"
-#include "cfganal.h"
-#include "gimple-fold.h"
-#include "tree-eh.h"
-#include "gimple-iterator.h"
-#include "gimple-walk.h"
-#include "tree-cfg.h"
-#include "wide-int.h"
-#include "ssa-range.h"
-#include "fold-const.h"
-#include "dbgcnt.h"
+#include "gimple-range-stmt.h"
+#include "gimple-range-cache.h"
// During contructor, Allocate the vector of ssa_names.
diff --git a/gcc/ssa-range-cache.h b/gcc/gimple-range-cache.h
similarity index 96%
rename from gcc/ssa-range-cache.h
rename to gcc/gimple-range-cache.h
index 79827df9014..b841ce29823 100644
--- a/gcc/ssa-range-cache.h
+++ b/gcc/gimple-range-cache.h
@@ -1,5 +1,5 @@
-/* Header file for SSA range cache classes.
- Copyright (C) 2017-2018 Free Software Foundation, Inc.
+/* Header file for gimple ranger SSA cache.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>.
This file is part of GCC.
diff --git a/gcc/gimple-range-cfg.cc b/gcc/gimple-range-cfg.cc
new file mode 100644
index 00000000000..a2ac0c40f9d
--- /dev/null
+++ b/gcc/gimple-range-cfg.cc
@@ -0,0 +1,459 @@
+/* Implementation of the gimple_ranger class.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@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 "insn-codes.h"
+#include "tree.h"
+#include "gimple.h"
+#include "ssa.h"
+#include "optabs-tree.h"
+#include "gimple-fold.h"
+#include "tree-cfg.h"
+#include "wide-int.h"
+#include "gimple-range-stmt.h"
+#include "gimple-range-gori.h"
+#include "gimple-range-cfg.h"
+#include "fold-const.h"
+#include "case-cfn-macros.h"
+#include "omp-general.h"
+
+// Calculate a range for statement S and return it in R. If NAME is provided it
+// represents the SSA_NAME on the LHS of the statement. It is only required
+// if there is more than one lhs/output. If a range cannot
+// be calculated, return false.
+
+bool
+gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
+{
+ bool res = false;
+ // If name is specified, make sure it is a LHS of S.
+ gcc_checking_assert (name ? SSA_NAME_DEF_STMT (name) == s : true);
+
+ if (gimple_range_handler (s))
+ res = range_of_range_op (r, s);
+ else if (is_a<gphi *>(s))
+ res = range_of_phi (r, as_a<gphi *> (s));
+ else if (is_a<gcall *>(s))
+ res = range_of_call (r, as_a<gcall *> (s));
+ else if (is_a<gassign *> (s) && gimple_assign_rhs_code (s) == COND_EXPR)
+ res = range_of_cond_expr (r, as_a<gassign *> (s));
+ else
+ {
+ // If no name is specified, try the expression kind.
+ if (!name)
+ {
+ tree t = gimple_expr_type (s);
+ if (!irange::supports_type_p (t))
+ return false;
+ r.set_varying (t);
+ return true;
+ }
+ // We don't understand the stmt, so return the global range.
+ r = gimple_range_global (name);
+ return true;
+ }
+ if (res)
+ {
+ if (r.undefined_p ())
+ return true;
+ if (name && TREE_TYPE (name) != r.type ())
+ range_cast (r, TREE_TYPE (name));
+ return true;
+ }
+ return false;
+}
+
+
+// Calculate a range for NAME on edge E and return it in R.
+// Return false if no range can be determined.
+
+void
+gimple_ranger::range_on_edge (irange &r, edge e, tree name)
+{
+ widest_irange edge_range;
+ gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
+
+ // PHI arguments can be constants, catch these here.
+ if (!gimple_range_ssa_p (name))
+ {
+ gcc_assert (range_of_expr (r, name));
+ return;
+ }
+
+ range_on_exit (r, e->src, name);
+ gcc_checking_assert (r.undefined_p ()
+ || types_compatible_p (r.type(), TREE_TYPE (name)));
+
+ // Check to see if NAME is defined on edge e.
+ if (outgoing_edge_range_p (edge_range, e, name, &r))
+ r = edge_range;
+}
+
+// Return the range for NAME on entry to block BB in R.
+// At the statement level, this amounts to whatever the global value is.
+
+void
+gimple_ranger::range_on_entry (irange &r, basic_block bb ATTRIBUTE_UNUSED,
+ tree name)
+{
+ range_of_ssa_name (r, name);
+}
+
+
+// Return the range for NAME on exit from block BB in R.
+// At the statement level, this amounts to whatever the global value is.
+
+void
+gimple_ranger::range_on_exit (irange &r, basic_block bb ATTRIBUTE_UNUSED,
+ tree name)
+{
+ range_of_ssa_name (r, name);
+}
+
+
+// Calculate a range for range_op statement S and return it in R. If any
+// If a range cannot be calculated, return false.
+
+bool
+gimple_ranger::range_of_range_op (irange &r, gimple *s)
+{
+ widest_irange range1, range2;
+ tree type = gimple_expr_type (s);
+ gcc_checking_assert (irange::supports_type_p (type));
+
+ tree op1 = gimple_range_operand1 (s);
+ tree op2 = gimple_range_operand2 (s);
+
+ if (range_of_expr (range1, op1, s))
+ {
+ if (!op2)
+ return gimple_range_fold (s, r, range1);
+
+ if (range_of_expr (range2, op2, s))
+ return gimple_range_fold (s, r, range1, range2);
+ }
+ r.set_varying (type);
+ return true;
+}
+
+
+// Calculate a range for phi statement S and return it in R.
+// If a range cannot be calculated, return false.
+
+bool
+gimple_ranger::range_of_phi (irange &r, gphi *phi)
+{
+ tree phi_def = gimple_phi_result (phi);
+ tree type = TREE_TYPE (phi_def);
+ widest_irange phi_range;
+ unsigned x;
+
+ if (!irange::supports_type_p (type))
+ return false;
+
+ // And start with an empty range, unioning in each argument's range.
+ r.set_undefined ();
+ for (x = 0; x < gimple_phi_num_args (phi); x++)
+ {
+ widest_irange arg_range;
+ tree arg = gimple_phi_arg_def (phi, x);
+ edge e = gimple_phi_arg_edge (phi, x);
+
+ range_on_edge (arg_range, e, arg);
+ r.union_ (arg_range);
+ // Once the value reaches varying, stop looking.
+ if (r.varying_p ())
+ break;
+ }
+
+ return true;
+}
+
+
+void
+gimple_ranger::range_of_ubsan_call (irange &r, gcall *call, tree_code code)
+{
+ tree type = gimple_call_return_type (call);
+ range_operator *op = range_op_handler (code, type);
+ gcc_checking_assert (op);
+ widest_irange ir0, ir1;
+ tree arg0 = gimple_call_arg (call, 0);
+ tree arg1 = gimple_call_arg (call, 1);
+ gcc_assert (range_of_expr (ir0, arg0, call));
+ gcc_assert (range_of_expr (ir1, arg1, call));
+
+ bool saved_flag_wrapv = flag_wrapv;
+ /* Pretend the arithmetics is wrapping. If there is
+ any overflow, we'll complain, but will actually do
+ wrapping operation. */
+ flag_wrapv = 1;
+ op->fold_range (r, type, ir0, ir1);
+ flag_wrapv = saved_flag_wrapv;
+
+ /* If for both arguments vrp_valueize returned non-NULL,
+ this should have been already folded and if not, it
+ wasn't folded because of overflow. Avoid removing the
+ UBSAN_CHECK_* calls in that case. */
+ if (r.singleton_p ())
+ r.set_varying (type);
+}
+
+
+// Calculate a range for call statement S and return it in R.
+// If a range cannot be calculated, return false.
+
+bool
+gimple_ranger::range_of_call (irange &r, gcall *call)
+{
+ tree type = gimple_call_return_type (call);
+ tree lhs = gimple_call_lhs (call);
+ tree arg;
+ int mini, maxi, zerov, prec;
+ scalar_int_mode mode;
+
+ if (!irange::supports_type_p (type))
+ return false;
+
+ combined_fn func = gimple_call_combined_fn (call);
+ switch (func)
+ {
+ case CFN_BUILT_IN_CONSTANT_P:
+ if (cfun->after_inlining)
+ {
+ r.set_zero (type);
+ // r.equiv_clean ();
+ }
+ break;
+ /* __builtin_ffs* and __builtin_popcount* return [0, prec]. */
+ CASE_CFN_FFS:
+ CASE_CFN_POPCOUNT:
+ arg = gimple_call_arg (call, 0);
+ prec = TYPE_PRECISION (TREE_TYPE (arg));
+ mini = 0;
+ maxi = prec;
+ if (TREE_CODE (arg) == SSA_NAME)
+ {
+ widest_irange vr0;
+ gcc_assert (range_of_expr (vr0, arg, call));
+ /* If arg is non-zero, then ffs or popcount are non-zero. */
+ if (range_includes_zero_p (&vr0) == 0)
+ mini = 1;
+ /* If some high bits are known to be zero, we can decrease
+ the maximum. */
+ if (vr0.kind () == VR_RANGE
+ && TREE_CODE (vr0.max ()) == INTEGER_CST
+ && !operand_less_p (vr0.min (),
+ build_zero_cst (TREE_TYPE (vr0.min ()))))
+ maxi = tree_floor_log2 (vr0.max ()) + 1;
+ }
+ r.set (build_int_cst (type, mini),
+ build_int_cst (type, maxi));
+ break;
+ /* __builtin_parity* returns [0, 1]. */
+ CASE_CFN_PARITY:
+ r.set (build_int_cst (type, 0),
+ build_int_cst (type, 1));
+ break;
+ /* __builtin_c[lt]z* return [0, prec-1], except for
+ when the argument is 0, but that is undefined behavior.
+ On many targets where the CLZ RTL or optab value is defined
+ for 0 the value is prec, so include that in the range
+ by default. */
+ CASE_CFN_CLZ:
+ arg = gimple_call_arg (call, 0);
+ prec = TYPE_PRECISION (TREE_TYPE (arg));
+ mini = 0;
+ maxi = prec;
+ mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
+ if (optab_handler (clz_optab, mode) != CODE_FOR_nothing
+ && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov)
+ /* Handle only the single common value. */
+ && zerov != prec)
+ /* Magic value to give up, unless vr0 proves
+ arg is non-zero. */
+ mini = -2;
+ if (TREE_CODE (arg) == SSA_NAME)
+ {
+ widest_irange vr0;
+ gcc_assert (range_of_expr (vr0, arg, call));
+ /* From clz of VR_RANGE minimum we can compute
+ result maximum. */
+ if (vr0.kind () == VR_RANGE
+ && TREE_CODE (vr0.min ()) == INTEGER_CST)
+ {
+ maxi = prec - 1 - tree_floor_log2 (vr0.min ());
+ if (maxi != prec)
+ mini = 0;
+ }
+ else if (!range_includes_zero_p (&vr0))
+ {
+ maxi = prec - 1;
+ mini = 0;
+ }
+ if (mini == -2)
+ break;
+ /* From clz of VR_RANGE maximum we can compute
+ result minimum. */
+ if (vr0.kind () == VR_RANGE
+ && TREE_CODE (vr0.max ()) == INTEGER_CST)
+ {
+ mini = prec - 1 - tree_floor_log2 (vr0.max ());
+ if (mini == prec)
+ break;
+ }
+ }
+ if (mini == -2)
+ break;
+ r.set (build_int_cst (type, mini),
+ build_int_cst (type, maxi));
+ break;
+ /* __builtin_ctz* return [0, prec-1], except for
+ when the argument is 0, but that is undefined behavior.
+ If there is a ctz optab for this mode and
+ CTZ_DEFINED_VALUE_AT_ZERO, include that in the range,
+ otherwise just assume 0 won't be seen. */
+ CASE_CFN_CTZ:
+ arg = gimple_call_arg (call, 0);
+ prec = TYPE_PRECISION (TREE_TYPE (arg));
+ mini = 0;
+ maxi = prec - 1;
+ mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
+ if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing
+ && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov))
+ {
+ /* Handle only the two common values. */
+ if (zerov == -1)
+ mini = -1;
+ else if (zerov == prec)
+ maxi = prec;
+ else
+ /* Magic value to give up, unless vr0 proves
+ arg is non-zero. */
+ mini = -2;
+ }
+ if (TREE_CODE (arg) == SSA_NAME)
+ {
+ widest_irange vr0;
+ gcc_assert (range_of_expr (vr0, arg, call));
+ /* If arg is non-zero, then use [0, prec - 1]. */
+ if (vr0.kind () == VR_RANGE
+ && integer_nonzerop (vr0.min ()))
+ {
+ mini = 0;
+ maxi = prec - 1;
+ }
+ /* If some high bits are known to be zero,
+ we can decrease the result maximum. */
+ if (vr0.kind () == VR_RANGE
+ && TREE_CODE (vr0.max ()) == INTEGER_CST)
+ {
+ maxi = tree_floor_log2 (vr0.max ());
+ /* For vr0 [0, 0] give up. */
+ if (maxi == -1)
+ break;
+ }
+ }
+ if (mini == -2)
+ break;
+ r.set (build_int_cst (type, mini),
+ build_int_cst (type, maxi));
+ break;
+ /* __builtin_clrsb* returns [0, prec-1]. */
+ CASE_CFN_CLRSB:
+ arg = gimple_call_arg (call, 0);
+ prec = TYPE_PRECISION (TREE_TYPE (arg));
+ r.set (build_int_cst (type, 0), build_int_cst (type, prec - 1));
+ break;
+ case CFN_UBSAN_CHECK_ADD:
+ range_of_ubsan_call (r, call, PLUS_EXPR);
+ break;
+ case CFN_UBSAN_CHECK_SUB:
+ range_of_ubsan_call (r, call, MINUS_EXPR);
+ break;
+ case CFN_UBSAN_CHECK_MUL:
+ range_of_ubsan_call (r, call, MULT_EXPR);
+ break;
+ case CFN_GOACC_DIM_SIZE:
+ case CFN_GOACC_DIM_POS:
+ /* Optimizing these two internal functions helps the loop
+ optimizer eliminate outer comparisons. Size is [1,N]
+ and pos is [0,N-1]. */
+ {
+ bool is_pos = func == CFN_GOACC_DIM_POS;
+ int axis = oacc_get_ifn_dim_arg (call);
+ int size = oacc_get_fn_dim_size (current_function_decl, axis);
+
+ if (!size)
+ /* If it's dynamic, the backend might know a hardware
+ limitation. */
+ size = targetm.goacc.dim_limit (axis);
+
+ tree type = TREE_TYPE (gimple_call_lhs (call));
+ r.set (build_int_cst (type, is_pos ? 0 : 1),
+ size
+ ? build_int_cst (type, size - is_pos) : vrp_val_max (type));
+ }
+ break;
+ case CFN_BUILT_IN_STRLEN:
+ if (tree lhs = gimple_call_lhs (call))
+ if (ptrdiff_type_node
+ && (TYPE_PRECISION (ptrdiff_type_node)
+ == TYPE_PRECISION (TREE_TYPE (lhs))))
+ {
+ tree type = TREE_TYPE (lhs);
+ tree max = vrp_val_max (ptrdiff_type_node);
+ wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
+ tree range_min = build_zero_cst (type);
+ /* To account for the terminating NULL, the maximum length
+ is one less than the maximum array size, which in turn
+ is one less than PTRDIFF_MAX (or SIZE_MAX where it's
+ smaller than the former type).
+ FIXME: Use max_object_size() - 1 here. */
+ tree range_max = wide_int_to_tree (type, wmax - 2);
+ r.set (range_min, range_max);
+ break;
+ }
+ break;
+ default:
+ {
+ bool ignore;
+ if (gimple_stmt_nonnegative_warnv_p (call, &ignore))
+ r.set (build_int_cst (type, 0), TYPE_MAX_VALUE (type));
+ else if (gimple_call_nonnull_result_p (call)
+ || gimple_call_nonnull_arg (call))
+ r = range_nonzero (type);
+ else
+ r.set_varying (type);
+ break;
+ }
+ }
+
+ // If there is a lHS, intersect that with what is known.
+ if (lhs)
+ {
+ value_range def;
+ def = gimple_range_global (lhs);
+ r.intersect (def);
+ }
+ return true;
+}
diff --git a/gcc/gimple-range-cfg.h b/gcc/gimple-range-cfg.h
new file mode 100644
index 00000000000..d7e78830310
--- /dev/null
+++ b/gcc/gimple-range-cfg.h
@@ -0,0 +1,41 @@
+/* Header file for the gimple_ranger class.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@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_GIMPLE_RANGE_CFG_H
+#define GCC_GIMPLE_RANGE_CFG_H
+
+class gimple_ranger : public gori_compute
+{
+public:
+ virtual bool range_of_stmt (irange &r, gimple *s, tree name = NULL_TREE);
+ virtual void range_on_edge (irange &r, edge e, tree name);
+
+ virtual void range_on_entry (irange &r, basic_block bb, tree name);
+ virtual void range_on_exit (irange &r, basic_block bb, tree name);
+protected:
+ bool range_of_range_op (irange &r, gimple *s);
+ bool range_of_phi (irange &r, gphi *phi);
+ bool range_of_call (irange &r, gcall *call);
+ bool range_of_cond_expr (irange &r, gassign* cond);
+private:
+ void range_of_ubsan_call (irange &r, gcall *call, tree_code code);
+};
+
+#endif // GCC_GIMPLE_RANGE_CFG_H
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index f44a6b20042..e3535c99868 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -1,5 +1,5 @@
-/* GIMPLE range GORI functions.
- Copyright (C) 2017-2019 Free Software Foundation, Inc.
+/* Gimple range GORI functions.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>.
This file is part of GCC.
@@ -26,9 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "ssa.h"
#include "gimple-pretty-print.h"
-#include "diagnostic-core.h"
-#include "wide-int.h"
-#include "gimple-range.h"
+#include "gimple-range-stmt.h"
#include "gimple-range-gori.h"
#include "fold-const.h"
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index 45aaa2404ad..a393f47883a 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -1,5 +1,5 @@
-/* Header file for GIMPLE range GORI structures.
- Copyright (C) 2017-2019 Free Software Foundation, Inc.
+/* Header file for gimple range GORI structures.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>.
This file is part of GCC.
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range-stmt.cc
similarity index 96%
rename from gcc/gimple-range.cc
rename to gcc/gimple-range-stmt.cc
index 2bed7dae7dd..4e4847763af 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range-stmt.cc
@@ -1,5 +1,5 @@
/* Code for GIMPLE range related routines.
- Copyright (C) 2019 Free Software Foundation, Inc.
+ Copyright (C) 2019-2020 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>
and Aldy Hernandez <aldyh@redhat.com>.
@@ -27,24 +27,10 @@ along with GCC; see the file COPYING3. If not see
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
-#include "cfghooks.h"
-#include "tree-pass.h"
#include "ssa.h"
-#include "optabs-tree.h"
-#include "gimple-pretty-print.h"
-#include "diagnostic-core.h"
-#include "flags.h"
-#include "fold-const.h"
-#include "stor-layout.h"
-#include "calls.h"
-#include "cfganal.h"
-#include "gimple-fold.h"
-#include "tree-eh.h"
#include "gimple-iterator.h"
-#include "gimple-walk.h"
#include "tree-cfg.h"
-#include "wide-int.h"
-#include "gimple-range.h"
+#include "gimple-range-stmt.h"
// This function looks for situations when walking the use/def chains
// may provide additonal contextual range information not exposed on
diff --git a/gcc/gimple-range.h b/gcc/gimple-range-stmt.h
similarity index 92%
rename from gcc/gimple-range.h
rename to gcc/gimple-range-stmt.h
index 641522bdfda..ddc6872ab8b 100644
--- a/gcc/gimple-range.h
+++ b/gcc/gimple-range-stmt.h
@@ -1,6 +1,7 @@
/* Header file for the GIMPLE range interface.
- Copyright (C) 2019 Free Software Foundation, Inc.
- Contributed by Andrew MacLeod <amacleod@redhat.com>.
+ Copyright (C) 2019-2020 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.com>
+ and Aldy Hernandez <aldyh@redhat.com>.
This file is part of GCC.
@@ -18,8 +19,8 @@ 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_GIMPLE_RANGE_H
-#define GCC_GIMPLE_RANGE_H
+#ifndef GCC_GIMPLE_RANGE_STMT_H
+#define GCC_GIMPLE_RANGE_STMT_H
#include "range.h"
@@ -94,4 +95,4 @@ gimple_range_global (tree name)
return value_range (type);
}
-#endif // GCC_GIMPLE_RANGE_H
+#endif // GCC_GIMPLE_RANGE_STMT_H
diff --git a/gcc/ssa-range.cc b/gcc/gimple-ranger.cc
similarity index 67%
rename from gcc/ssa-range.cc
rename to gcc/gimple-ranger.cc
index 1d3f6442a4c..1d3e872e7c7 100644
--- a/gcc/ssa-range.cc
+++ b/gcc/gimple-ranger.cc
@@ -1,6 +1,7 @@
-/* SSA range support functions.
- Copyright (C) 2017-2018 Free Software Foundation, Inc.
- Contributed by Andrew MacLeod <amacleod@redhat.com>.
+/* Main entry point for the gimple ranger.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.com>
+ and Aldy Hernandez <aldyh@redhat.com>.
This file is part of GCC.
@@ -26,455 +27,17 @@ along with GCC; see the file COPYING3. If not see
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
-#include "cfghooks.h"
-#include "tree-pass.h"
#include "ssa.h"
-#include "optabs-tree.h"
#include "gimple-pretty-print.h"
-#include "diagnostic-core.h"
-#include "flags.h"
-#include "fold-const.h"
-#include "stor-layout.h"
-#include "calls.h"
-#include "cfganal.h"
-#include "gimple-fold.h"
-#include "tree-eh.h"
#include "gimple-iterator.h"
-#include "gimple-walk.h"
#include "tree-cfg.h"
-#include "wide-int.h"
-#include "ssa-range.h"
-#include "fold-const.h"
+#include "gimple-ranger.h"
#include "cfgloop.h"
-#include "tree-scalar-evolution.h"
#include "tree-ssa-loop.h"
+#include "tree-scalar-evolution.h"
+#include "dbgcnt.h"
#include "alloc-pool.h"
#include "vr-values.h"
-#include "dbgcnt.h"
-#include "case-cfn-macros.h"
-#include "omp-general.h"
-
-// Calculate a range for statement S and return it in R. If NAME is provided it
-// represents the SSA_NAME on the LHS of the statement. It is only required
-// if there is more than one lhs/output. If a range cannot
-// be calculated, return false.
-
-bool
-gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
-{
- bool res = false;
- // If name is specified, make sure it is a LHS of S.
- gcc_checking_assert (name ? SSA_NAME_DEF_STMT (name) == s : true);
-
- if (gimple_range_handler (s))
- res = range_of_range_op (r, s);
- else if (is_a<gphi *>(s))
- res = range_of_phi (r, as_a<gphi *> (s));
- else if (is_a<gcall *>(s))
- res = range_of_call (r, as_a<gcall *> (s));
- else if (is_a<gassign *> (s) && gimple_assign_rhs_code (s) == COND_EXPR)
- res = range_of_cond_expr (r, as_a<gassign *> (s));
- else
- {
- // If no name is specified, try the expression kind.
- if (!name)
- {
- tree t = gimple_expr_type (s);
- if (!irange::supports_type_p (t))
- return false;
- r.set_varying (t);
- return true;
- }
- // We don't understand the stmt, so return the global range.
- r = gimple_range_global (name);
- return true;
- }
- if (res)
- {
- if (r.undefined_p ())
- return true;
- if (name && TREE_TYPE (name) != r.type ())
- range_cast (r, TREE_TYPE (name));
- return true;
- }
- return false;
-}
-
-
-// Calculate a range for NAME on edge E and return it in R.
-// Return false if no range can be determined.
-
-void
-gimple_ranger::range_on_edge (irange &r, edge e, tree name)
-{
- widest_irange edge_range;
- gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
-
- // PHI arguments can be constants, catch these here.
- if (!gimple_range_ssa_p (name))
- {
- gcc_assert (range_of_expr (r, name));
- return;
- }
-
- range_on_exit (r, e->src, name);
- gcc_checking_assert (r.undefined_p ()
- || types_compatible_p (r.type(), TREE_TYPE (name)));
-
- // Check to see if NAME is defined on edge e.
- if (outgoing_edge_range_p (edge_range, e, name, &r))
- r = edge_range;
-}
-
-// Return the range for NAME on entry to block BB in R.
-// At the statement level, this amounts to whatever the global value is.
-
-void
-gimple_ranger::range_on_entry (irange &r, basic_block bb ATTRIBUTE_UNUSED,
- tree name)
-{
- range_of_ssa_name (r, name);
-}
-
-
-// Return the range for NAME on exit from block BB in R.
-// At the statement level, this amounts to whatever the global value is.
-
-void
-gimple_ranger::range_on_exit (irange &r, basic_block bb ATTRIBUTE_UNUSED,
- tree name)
-{
- range_of_ssa_name (r, name);
-}
-
-
-// Calculate a range for range_op statement S and return it in R. If any
-// If a range cannot be calculated, return false.
-
-bool
-gimple_ranger::range_of_range_op (irange &r, gimple *s)
-{
- widest_irange range1, range2;
- tree type = gimple_expr_type (s);
- gcc_checking_assert (irange::supports_type_p (type));
-
- tree op1 = gimple_range_operand1 (s);
- tree op2 = gimple_range_operand2 (s);
-
- if (range_of_expr (range1, op1, s))
- {
- if (!op2)
- return gimple_range_fold (s, r, range1);
-
- if (range_of_expr (range2, op2, s))
- return gimple_range_fold (s, r, range1, range2);
- }
- r.set_varying (type);
- return true;
-}
-
-
-// Calculate a range for phi statement S and return it in R.
-// If a range cannot be calculated, return false.
-
-bool
-gimple_ranger::range_of_phi (irange &r, gphi *phi)
-{
- tree phi_def = gimple_phi_result (phi);
- tree type = TREE_TYPE (phi_def);
- widest_irange phi_range;
- unsigned x;
-
- if (!irange::supports_type_p (type))
- return false;
-
- // And start with an empty range, unioning in each argument's range.
- r.set_undefined ();
- for (x = 0; x < gimple_phi_num_args (phi); x++)
- {
- widest_irange arg_range;
- tree arg = gimple_phi_arg_def (phi, x);
- edge e = gimple_phi_arg_edge (phi, x);
-
- range_on_edge (arg_range, e, arg);
- r.union_ (arg_range);
- // Once the value reaches varying, stop looking.
- if (r.varying_p ())
- break;
- }
-
- return true;
-}
-
-
-void
-gimple_ranger::range_of_ubsan_call (irange &r, gcall *call, tree_code code)
-{
- tree type = gimple_call_return_type (call);
- range_operator *op = range_op_handler (code, type);
- gcc_checking_assert (op);
- widest_irange ir0, ir1;
- tree arg0 = gimple_call_arg (call, 0);
- tree arg1 = gimple_call_arg (call, 1);
- gcc_assert (range_of_expr (ir0, arg0, call));
- gcc_assert (range_of_expr (ir1, arg1, call));
-
- bool saved_flag_wrapv = flag_wrapv;
- /* Pretend the arithmetics is wrapping. If there is
- any overflow, we'll complain, but will actually do
- wrapping operation. */
- flag_wrapv = 1;
- op->fold_range (r, type, ir0, ir1);
- flag_wrapv = saved_flag_wrapv;
-
- /* If for both arguments vrp_valueize returned non-NULL,
- this should have been already folded and if not, it
- wasn't folded because of overflow. Avoid removing the
- UBSAN_CHECK_* calls in that case. */
- if (r.singleton_p ())
- r.set_varying (type);
-}
-
-
-// Calculate a range for call statement S and return it in R.
-// If a range cannot be calculated, return false.
-
-bool
-gimple_ranger::range_of_call (irange &r, gcall *call)
-{
- tree type = gimple_call_return_type (call);
- tree lhs = gimple_call_lhs (call);
- tree arg;
- int mini, maxi, zerov, prec;
- scalar_int_mode mode;
-
- if (!irange::supports_type_p (type))
- return false;
-
- combined_fn func = gimple_call_combined_fn (call);
- switch (func)
- {
- case CFN_BUILT_IN_CONSTANT_P:
- if (cfun->after_inlining)
- {
- r.set_zero (type);
- // r.equiv_clean ();
- }
- break;
- /* __builtin_ffs* and __builtin_popcount* return [0, prec]. */
- CASE_CFN_FFS:
- CASE_CFN_POPCOUNT:
- arg = gimple_call_arg (call, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- mini = 0;
- maxi = prec;
- if (TREE_CODE (arg) == SSA_NAME)
- {
- widest_irange vr0;
- gcc_assert (range_of_expr (vr0, arg, call));
- /* If arg is non-zero, then ffs or popcount are non-zero. */
- if (range_includes_zero_p (&vr0) == 0)
- mini = 1;
- /* If some high bits are known to be zero, we can decrease
- the maximum. */
- if (vr0.kind () == VR_RANGE
- && TREE_CODE (vr0.max ()) == INTEGER_CST
- && !operand_less_p (vr0.min (),
- build_zero_cst (TREE_TYPE (vr0.min ()))))
- maxi = tree_floor_log2 (vr0.max ()) + 1;
- }
- r.set (build_int_cst (type, mini),
- build_int_cst (type, maxi));
- break;
- /* __builtin_parity* returns [0, 1]. */
- CASE_CFN_PARITY:
- r.set (build_int_cst (type, 0),
- build_int_cst (type, 1));
- break;
- /* __builtin_c[lt]z* return [0, prec-1], except for
- when the argument is 0, but that is undefined behavior.
- On many targets where the CLZ RTL or optab value is defined
- for 0 the value is prec, so include that in the range
- by default. */
- CASE_CFN_CLZ:
- arg = gimple_call_arg (call, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- mini = 0;
- maxi = prec;
- mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
- if (optab_handler (clz_optab, mode) != CODE_FOR_nothing
- && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov)
- /* Handle only the single common value. */
- && zerov != prec)
- /* Magic value to give up, unless vr0 proves
- arg is non-zero. */
- mini = -2;
- if (TREE_CODE (arg) == SSA_NAME)
- {
- widest_irange vr0;
- gcc_assert (range_of_expr (vr0, arg, call));
- /* From clz of VR_RANGE minimum we can compute
- result maximum. */
- if (vr0.kind () == VR_RANGE
- && TREE_CODE (vr0.min ()) == INTEGER_CST)
- {
- maxi = prec - 1 - tree_floor_log2 (vr0.min ());
- if (maxi != prec)
- mini = 0;
- }
- else if (!range_includes_zero_p (&vr0))
- {
- maxi = prec - 1;
- mini = 0;
- }
- if (mini == -2)
- break;
- /* From clz of VR_RANGE maximum we can compute
- result minimum. */
- if (vr0.kind () == VR_RANGE
- && TREE_CODE (vr0.max ()) == INTEGER_CST)
- {
- mini = prec - 1 - tree_floor_log2 (vr0.max ());
- if (mini == prec)
- break;
- }
- }
- if (mini == -2)
- break;
- r.set (build_int_cst (type, mini),
- build_int_cst (type, maxi));
- break;
- /* __builtin_ctz* return [0, prec-1], except for
- when the argument is 0, but that is undefined behavior.
- If there is a ctz optab for this mode and
- CTZ_DEFINED_VALUE_AT_ZERO, include that in the range,
- otherwise just assume 0 won't be seen. */
- CASE_CFN_CTZ:
- arg = gimple_call_arg (call, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- mini = 0;
- maxi = prec - 1;
- mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
- if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing
- && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov))
- {
- /* Handle only the two common values. */
- if (zerov == -1)
- mini = -1;
- else if (zerov == prec)
- maxi = prec;
- else
- /* Magic value to give up, unless vr0 proves
- arg is non-zero. */
- mini = -2;
- }
- if (TREE_CODE (arg) == SSA_NAME)
- {
- widest_irange vr0;
- gcc_assert (range_of_expr (vr0, arg, call));
- /* If arg is non-zero, then use [0, prec - 1]. */
- if (vr0.kind () == VR_RANGE
- && integer_nonzerop (vr0.min ()))
- {
- mini = 0;
- maxi = prec - 1;
- }
- /* If some high bits are known to be zero,
- we can decrease the result maximum. */
- if (vr0.kind () == VR_RANGE
- && TREE_CODE (vr0.max ()) == INTEGER_CST)
- {
- maxi = tree_floor_log2 (vr0.max ());
- /* For vr0 [0, 0] give up. */
- if (maxi == -1)
- break;
- }
- }
- if (mini == -2)
- break;
- r.set (build_int_cst (type, mini),
- build_int_cst (type, maxi));
- break;
- /* __builtin_clrsb* returns [0, prec-1]. */
- CASE_CFN_CLRSB:
- arg = gimple_call_arg (call, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- r.set (build_int_cst (type, 0), build_int_cst (type, prec - 1));
- break;
- case CFN_UBSAN_CHECK_ADD:
- range_of_ubsan_call (r, call, PLUS_EXPR);
- break;
- case CFN_UBSAN_CHECK_SUB:
- range_of_ubsan_call (r, call, MINUS_EXPR);
- break;
- case CFN_UBSAN_CHECK_MUL:
- range_of_ubsan_call (r, call, MULT_EXPR);
- break;
- case CFN_GOACC_DIM_SIZE:
- case CFN_GOACC_DIM_POS:
- /* Optimizing these two internal functions helps the loop
- optimizer eliminate outer comparisons. Size is [1,N]
- and pos is [0,N-1]. */
- {
- bool is_pos = func == CFN_GOACC_DIM_POS;
- int axis = oacc_get_ifn_dim_arg (call);
- int size = oacc_get_fn_dim_size (current_function_decl, axis);
-
- if (!size)
- /* If it's dynamic, the backend might know a hardware
- limitation. */
- size = targetm.goacc.dim_limit (axis);
-
- tree type = TREE_TYPE (gimple_call_lhs (call));
- r.set (build_int_cst (type, is_pos ? 0 : 1),
- size
- ? build_int_cst (type, size - is_pos) : vrp_val_max (type));
- }
- break;
- case CFN_BUILT_IN_STRLEN:
- if (tree lhs = gimple_call_lhs (call))
- if (ptrdiff_type_node
- && (TYPE_PRECISION (ptrdiff_type_node)
- == TYPE_PRECISION (TREE_TYPE (lhs))))
- {
- tree type = TREE_TYPE (lhs);
- tree max = vrp_val_max (ptrdiff_type_node);
- wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
- tree range_min = build_zero_cst (type);
- /* To account for the terminating NULL, the maximum length
- is one less than the maximum array size, which in turn
- is one less than PTRDIFF_MAX (or SIZE_MAX where it's
- smaller than the former type).
- FIXME: Use max_object_size() - 1 here. */
- tree range_max = wide_int_to_tree (type, wmax - 2);
- r.set (range_min, range_max);
- break;
- }
- break;
- default:
- {
- bool ignore;
- if (gimple_stmt_nonnegative_warnv_p (call, &ignore))
- r.set (build_int_cst (type, 0), TYPE_MAX_VALUE (type));
- else if (gimple_call_nonnull_result_p (call)
- || gimple_call_nonnull_arg (call))
- r = range_nonzero (type);
- else
- r.set_varying (type);
- break;
- }
- }
-
- // If there is a lHS, intersect that with what is known.
- if (lhs)
- {
- value_range def;
- def = gimple_range_global (lhs);
- r.intersect (def);
- }
- return true;
-}
-
// Calculate a range for COND_EXPR statement S and return it in R.
// If a range cannot be calculated, return false.
diff --git a/gcc/ssa-range.h b/gcc/gimple-ranger.h
similarity index 82%
rename from gcc/ssa-range.h
rename to gcc/gimple-ranger.h
index 87acc95af6d..f2b31edc70f 100644
--- a/gcc/ssa-range.h
+++ b/gcc/gimple-ranger.h
@@ -1,6 +1,7 @@
-/* Header file for SSA range interface.
- Copyright (C) 2017-2018 Free Software Foundation, Inc.
- Contributed by Andrew MacLeod <amacleod@redhat.com>.
+/* Header file for the gimple ranger.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.com>
+ and Aldy Hernandez <aldyh@redhat.com>.
This file is part of GCC.
@@ -18,12 +19,13 @@ 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_SSA_RANGE_H
-#define GCC_SSA_RANGE_H
+#ifndef GCC_GIMPLE_RANGER_H
+#define GCC_GIMPLE_RANGER_H
-#include "gimple-range.h"
+#include "gimple-range-stmt.h"
#include "gimple-range-gori.h"
-#include "ssa-range-cache.h"
+#include "gimple-range-cfg.h"
+#include "gimple-range-cache.h"
// This is the basic range generator interface.
@@ -38,24 +40,6 @@ along with GCC; see the file COPYING3. If not see
// type is not supported, then false is returned. Non-statement
// related methods return whatever the current global value is.
-class gimple_ranger : public gori_compute
-{
-public:
- virtual bool range_of_stmt (irange &r, gimple *s, tree name = NULL_TREE);
- virtual void range_on_edge (irange &r, edge e, tree name);
-
- virtual void range_on_entry (irange &r, basic_block bb, tree name);
- virtual void range_on_exit (irange &r, basic_block bb, tree name);
-protected:
- bool range_of_range_op (irange &r, gimple *s);
- bool range_of_phi (irange &r, gphi *phi);
- bool range_of_call (irange &r, gcall *call);
- bool range_of_cond_expr (irange &r, gassign* cond);
-private:
- void range_of_ubsan_call (irange &r, gcall *call, tree_code code);
-};
-
-
class global_ranger : public gimple_ranger
{
public:
@@ -152,4 +136,4 @@ on_demand_get_range_on_stmt (irange &r, tree ssa, gimple *stmt)
return false;
return ret;
}
-#endif // GCC_SSA_RANGE_H
+#endif // GCC_GIMPLE_RANGER_H
diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c
index 43daa7285aa..7a3f22fcc9d 100644
--- a/gcc/gimple-ssa-evrp-analyze.c
+++ b/gcc/gimple-ssa-evrp-analyze.c
@@ -42,8 +42,8 @@ along with GCC; see the file COPYING3. If not see
#include "vr-values.h"
#include "gimple-ssa-evrp-analyze.h"
#include "dbgcnt.h"
-#include "gimple-range.h"
-#include "ssa-range.h"
+#include "gimple-range-stmt.h"
+#include "gimple-ranger.h"
class vr_gori_interface : public trace_gori_compute
{
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index f001aa49b51..eab4cb4555f 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -50,7 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "vr-values.h"
#include "cfghooks.h"
#include "range-op.h"
-#include "gimple-range.h"
+#include "gimple-range-stmt.h"
/* Set value range VR to a non-negative range of type TYPE. */
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-04-03 7:05 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-03 7:05 [gcc/devel/ranger] Shuffle all the ranger code around into various files: Aldy Hernandez
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).