From 6eda9fa5f61e784638f0b1522840338e97fc5f7f Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Thu, 17 Sep 2020 09:23:12 +0200 Subject: [PATCH] Initial implementation of value query class. gcc/ChangeLog: * Makefile.in: Add value-query.o. * value-query.cc: New file. * value-query.h: New file. --- gcc/Makefile.in | 1 + gcc/value-query.cc | 162 +++++++++++++++++++++++++++++++++++++++++++++ gcc/value-query.h | 107 ++++++++++++++++++++++++++++++ 3 files changed, 270 insertions(+) create mode 100644 gcc/value-query.cc create mode 100644 gcc/value-query.h diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 9c6c1c93b97..50d6c83eb76 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1646,6 +1646,7 @@ OBJS = \ typed-splay-tree.o \ unique-ptr-tests.o \ valtrack.o \ + value-query.o \ value-range.o \ value-range-equiv.o \ value-prof.o \ diff --git a/gcc/value-query.cc b/gcc/value-query.cc new file mode 100644 index 00000000000..5370a23fe18 --- /dev/null +++ b/gcc/value-query.cc @@ -0,0 +1,162 @@ +/* Support routines for value queries. + Copyright (C) 2020 Free Software Foundation, Inc. + Contributed by Aldy Hernandez and + Andrew MacLeod . + +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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "tree.h" +#include "gimple.h" +#include "ssa.h" +#include "tree-pretty-print.h" +#include "fold-const.h" +#include "value-range-equiv.h" +#include "value-query.h" +#include "alloc-pool.h" + +// value_query default methods. + +tree +value_query::value_on_edge (edge, tree name) +{ + return value_of_expr (name); +} + +tree +value_query::value_of_stmt (gimple *stmt, tree name) +{ + if (!name) + name = gimple_get_lhs (stmt); + + gcc_checking_assert (!name || name == gimple_get_lhs (stmt)); + + if (name) + return value_of_expr (name); + return NULL_TREE; +} + +// range_query default methods. + +bool +range_query::range_on_edge (irange &r, edge, tree name) +{ + return range_of_expr (r, name); +} + +bool +range_query::range_of_stmt (irange &r, gimple *stmt, tree name) +{ + if (!name) + name = gimple_get_lhs (stmt); + + gcc_checking_assert (!name || name == gimple_get_lhs (stmt)); + + if (name) + return range_of_expr (r, name); + return false; +} + +tree +range_query::value_of_expr (tree name, gimple *stmt) +{ + tree t; + value_range r; + + if (!irange::supports_type_p (TREE_TYPE (name))) + return NULL_TREE; + if (range_of_expr (r, name, stmt) && r.singleton_p (&t)) + return t; + return NULL_TREE; +} + +tree +range_query::value_on_edge (edge e, tree name) +{ + tree t; + value_range r; + + if (!irange::supports_type_p (TREE_TYPE (name))) + return NULL_TREE; + if (range_on_edge (r, e, name) && r.singleton_p (&t)) + return t; + return NULL_TREE; + +} + +tree +range_query::value_of_stmt (gimple *stmt, tree name) +{ + tree t; + value_range r; + + if (!name) + name = gimple_get_lhs (stmt); + + gcc_checking_assert (!name || name == gimple_get_lhs (stmt)); + + if (!name || !irange::supports_type_p (TREE_TYPE (name))) + return NULL_TREE; + if (range_of_stmt (r, stmt, name) && r.singleton_p (&t)) + return t; + return NULL_TREE; + +} + +// valuation_query support routines for value_range_equiv's. + +class equiv_allocator : public object_allocator +{ +public: + equiv_allocator () + : object_allocator ("equiv_allocator pool") { } +}; + +value_range_equiv * +range_query::allocate_value_range_equiv () +{ + return new (equiv_alloc->allocate ()) value_range_equiv; +} + +void +range_query::free_value_range_equiv (value_range_equiv *v) +{ + equiv_alloc->remove (v); +} + +const class value_range_equiv * +range_query::get_value_range (const_tree expr, gimple *stmt) +{ + int_range_max r; + if (range_of_expr (r, const_cast (expr), stmt)) + return new (equiv_alloc->allocate ()) value_range_equiv (r); + return new (equiv_alloc->allocate ()) value_range_equiv (TREE_TYPE (expr)); +} + +range_query::range_query () +{ + equiv_alloc = new equiv_allocator; +} + +range_query::~range_query () +{ + equiv_alloc->release (); + delete equiv_alloc; +} diff --git a/gcc/value-query.h b/gcc/value-query.h new file mode 100644 index 00000000000..cf0b6ed5dc1 --- /dev/null +++ b/gcc/value-query.h @@ -0,0 +1,107 @@ +/* Support routines for value queries. + Copyright (C) 2020 Free Software Foundation, Inc. + Contributed by Aldy Hernandez and + Andrew Macleod . + +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 +. */ + +#ifndef GCC_QUERY_H +#define GCC_QUERY_H + +// The value_query class is used by optimization passes that require +// valueizing SSA names in terms of a tree value, but have no neeed +// for ranges. +// +// value_of_expr must be provided. The default for value_on_edge and +// value_of_stmt is to call value_of_expr. +// +// This implies the valuation is global in nature. If a pass can make +// use of more specific information, it can override the other queries. +// +// Proper usage of the correct query in passes will enable other +// valuation mechanisms to produce more precise results. + +class value_query +{ +public: + value_query () { } + // Return the singleton expression for NAME at a gimple statement, + // or NULL if none found. + virtual tree value_of_expr (tree name, gimple * = NULL) = 0; + // Return the singleton expression for NAME at an edge, or NULL if + // none found. + virtual tree value_on_edge (edge, tree name); + // Return the singleton expression for the LHS of a gimple + // statement, assuming an (optional) initial value of NAME. Returns + // NULL if none found. + // + // Note that this method calculates the range the LHS would have + // *after* the statement has executed. + virtual tree value_of_stmt (gimple *, tree name = NULL); + +private: + DISABLE_COPY_AND_ASSIGN (value_query); +}; + +// The range_query class is used by optimization passes which are +// range aware. +// +// range_of_expr must be provided. The default for range_on_edge and +// range_of_stmt is to call range_of_expr. If a pass can make use of +// more specific information, then it can override the other queries. +// +// The default for the value_* routines is to call the equivalent +// range_* routines, check if the range is a singleton, and return it +// if so. +// +// The get_value_range method is currently provided for compatibility +// with vr-values. It will be deprecated when possible. + +class range_query : public value_query +{ +public: + range_query (); + virtual ~range_query (); + + virtual tree value_of_expr (tree name, gimple * = NULL) OVERRIDE; + virtual tree value_on_edge (edge, tree name) OVERRIDE; + virtual tree value_of_stmt (gimple *, tree name = NULL) OVERRIDE; + + // These are the range equivalents of the value_* methods. Instead + // of returning a singleton, they calculate a range and return it in + // R. TRUE is returned on success or FALSE if no range was found. + // + // Note that range_of_expr must always return TRUE unless ranges are + // unsupported for NAME's type (supports_type_p is false). + virtual bool range_of_expr (irange &r, tree name, gimple * = NULL) = 0; + virtual bool range_on_edge (irange &r, edge, tree name); + virtual bool range_of_stmt (irange &r, gimple *, tree name = NULL); + + // DEPRECATED: This method is used from vr-values. The plan is to + // rewrite all uses of it to the above API. + virtual const class value_range_equiv *get_value_range (const_tree, + gimple * = NULL); + +protected: + class value_range_equiv *allocate_value_range_equiv (); + void free_value_range_equiv (class value_range_equiv *); + +private: + class equiv_allocator *equiv_alloc; +}; + +#endif // GCC_QUERY_H -- 2.30.2