diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2021-06-22 11:41:30 -0400 |
---|---|---|
committer | Andrew MacLeod <amacleod@redhat.com> | 2021-06-23 10:26:16 -0400 |
commit | 4c85ff754927c518ed97da5e0221eeea742c9aa7 (patch) | |
tree | 79cdc22d855c971de3847197e544f3914cee985e /gcc/gimple-range-fold.h | |
parent | a03e944e92ee51ae583382079d4739b64bd93b35 (diff) | |
download | gcc-4c85ff754927c518ed97da5e0221eeea742c9aa7.zip gcc-4c85ff754927c518ed97da5e0221eeea742c9aa7.tar.gz gcc-4c85ff754927c518ed97da5e0221eeea742c9aa7.tar.bz2 |
Split gimple-range into gimple-range-fold and gimple-range.
Split the fold_using_range functions from gimple-range into gimple-range-fold.
Also move the gimple_range_calc* routines into gimple-range-gori.
* Makefile.in (OBJS): Add gimple-range-fold.o
* gimple-range-fold.cc: New.
* gimple-range-fold.h: New.
* gimple-range-gori.cc (gimple_range_calc_op1): Move to here.
(gimple_range_calc_op2): Ditto.
* gimple-range-gori.h: Move prototypes to here.
* gimple-range.cc: Adjust include files.
(fur_source:fur_source): Relocate to gimple-range-fold.cc.
(fur_source::get_operand): Ditto.
(fur_source::get_phi_operand): Ditto.
(fur_source::query_relation): Ditto.
(fur_source::register_relation): Ditto.
(class fur_edge): Ditto.
(fur_edge::fur_edge): Ditto.
(fur_edge::get_operand): Ditto.
(fur_edge::get_phi_operand): Ditto.
(fur_stmt::fur_stmt): Ditto.
(fur_stmt::get_operand): Ditto.
(fur_stmt::get_phi_operand): Ditto.
(fur_stmt::query_relation): Ditto.
(class fur_depend): Relocate to gimple-range-fold.h.
(fur_depend::fur_depend): Relocate to gimple-range-fold.cc.
(fur_depend::register_relation): Ditto.
(fur_depend::register_relation): Ditto.
(class fur_list): Ditto.
(fur_list::fur_list): Ditto.
(fur_list::get_operand): Ditto.
(fur_list::get_phi_operand): Ditto.
(fold_range): Ditto.
(adjust_pointer_diff_expr): Ditto.
(gimple_range_adjustment): Ditto.
(gimple_range_base_of_assignment): Ditto.
(gimple_range_operand1): Ditto.
(gimple_range_operand2): Ditto.
(gimple_range_calc_op1): Relocate to gimple-range-gori.cc.
(gimple_range_calc_op2): Ditto.
(fold_using_range::fold_stmt): Relocate to gimple-range-fold.cc.
(fold_using_range::range_of_range_op): Ditto.
(fold_using_range::range_of_address): Ditto.
(fold_using_range::range_of_phi): Ditto.
(fold_using_range::range_of_call): Ditto.
(fold_using_range::range_of_builtin_ubsan_call): Ditto.
(fold_using_range::range_of_builtin_call): Ditto.
(fold_using_range::range_of_cond_expr): Ditto.
(fold_using_range::range_of_ssa_name_with_loop_info): Ditto.
(fold_using_range::relation_fold_and_or): Ditto.
(fold_using_range::postfold_gcond_edges): Ditto.
* gimple-range.h: Add gimple-range-fold.h to include files. Change
GIMPLE_RANGE_STMT_H to GIMPLE_RANGE_H.
(gimple_range_handler): Relocate to gimple-range-fold.h.
(gimple_range_ssa_p): Ditto.
(range_compatible_p): Ditto.
(class fur_source): Ditto.
(class fur_stmt): Ditto.
(class fold_using_range): Ditto.
(gimple_range_calc_op1): Relocate to gimple-range-gori.h
(gimple_range_calc_op2): Ditto.
Diffstat (limited to 'gcc/gimple-range-fold.h')
-rw-r--r-- | gcc/gimple-range-fold.h | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h new file mode 100644 index 0000000..aeb9231 --- /dev/null +++ b/gcc/gimple-range-fold.h @@ -0,0 +1,163 @@ +/* Header file for the GIMPLE fold_using_range interface. + Copyright (C) 2019-2021 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_GIMPLE_RANGE_FOLD_H +#define GCC_GIMPLE_RANGE_FOLD_H + +// This file is the main include point for gimple range folding. +// These routines will fold stmt S into the result irange R. +// Any ssa_names on the stmt will be calculated using the range_query +// parameter via a call to range_of_expr. +// If no range_query is provided, current global range info will be used. +// The second variation specifies an edge, and stmt S is recalculated as if +// it appeared on that edge. + +// Fold stmt S into range R using range query Q. +bool fold_range (irange &r, gimple *s, range_query *q = NULL); +// Recalculate stmt S into R using range query Q as if it were on edge ON_EDGE. +bool fold_range (irange &r, gimple *s, edge on_edge, range_query *q = NULL); + +// These routines the operands to be specified when manually folding. +// Any excess queries will be drawn from the current range_query. +bool fold_range (irange &r, gimple *s, irange &r1); +bool fold_range (irange &r, gimple *s, irange &r1, irange &r2); +bool fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector); + +// Return the range_operator pointer for this statement. This routine +// can also be used to gate whether a routine is range-ops enabled. + +static inline range_operator * +gimple_range_handler (const gimple *s) +{ + if (const gassign *ass = dyn_cast<const gassign *> (s)) + return range_op_handler (gimple_assign_rhs_code (ass), + TREE_TYPE (gimple_assign_lhs (ass))); + if (const gcond *cond = dyn_cast<const gcond *> (s)) + return range_op_handler (gimple_cond_code (cond), + TREE_TYPE (gimple_cond_lhs (cond))); + return NULL; +} + +// Return EXP if it is an SSA_NAME with a type supported by gimple ranges. + +static inline tree +gimple_range_ssa_p (tree exp) +{ + if (exp && TREE_CODE (exp) == SSA_NAME && + !SSA_NAME_IS_VIRTUAL_OPERAND (exp) && + irange::supports_type_p (TREE_TYPE (exp))) + return exp; + return NULL_TREE; +} + +// Return true if TYPE1 and TYPE2 are compatible range types. + +static inline bool +range_compatible_p (tree type1, tree type2) +{ + // types_compatible_p requires conversion in both directions to be useless. + // GIMPLE only requires a cast one way in order to be compatible. + // Ranges really only need the sign and precision to be the same. + return (TYPE_PRECISION (type1) == TYPE_PRECISION (type2) + && TYPE_SIGN (type1) == TYPE_SIGN (type2)); +} + + +// Source of all operands for fold_using_range and gori_compute. +// It abstracts out the source of an operand so it can come from a stmt or +// and edge or anywhere a derived class of fur_source wants. +// The default simply picks up ranges from the current range_query. + +class fur_source +{ +public: + fur_source (range_query *q = NULL); + inline range_query *query () { return m_query; } + inline class gori_compute *gori () { return m_gori; }; + virtual bool get_operand (irange &r, tree expr); + virtual bool get_phi_operand (irange &r, tree expr, edge e); + virtual relation_kind query_relation (tree op1, tree op2); + virtual void register_relation (gimple *stmt, relation_kind k, tree op1, + tree op2); + virtual void register_relation (edge e, relation_kind k, tree op1, + tree op2); +protected: + range_query *m_query; + gori_compute *m_gori; +}; + +// fur_stmt is the specification for drawing an operand from range_query Q +// via a range_of_Expr call on stmt S. + +class fur_stmt : public fur_source +{ +public: + fur_stmt (gimple *s, range_query *q = NULL); + virtual bool get_operand (irange &r, tree expr) OVERRIDE; + virtual bool get_phi_operand (irange &r, tree expr, edge e) OVERRIDE; + virtual relation_kind query_relation (tree op1, tree op2) OVERRIDE; +private: + gimple *m_stmt; +}; + +// This version of fur_source will pick a range from a stmt, and also register +// dependencies via a gori_compute object. This is mostly an internal API. + +class fur_depend : public fur_stmt +{ +public: + fur_depend (gimple *s, gori_compute *gori, range_query *q = NULL); + virtual void register_relation (gimple *stmt, relation_kind k, tree op1, + tree op2) OVERRIDE; + virtual void register_relation (edge e, relation_kind k, tree op1, + tree op2) OVERRIDE; +private: + relation_oracle *m_oracle; +}; + +extern tree gimple_range_operand1 (const gimple *s); +extern tree gimple_range_operand2 (const gimple *s); + +// This class uses ranges to fold a gimple statement producinf a range for +// the LHS. The source of all operands is supplied via the fur_source class +// which provides a range_query as well as a source location and any other +// required information. + +class fold_using_range +{ +public: + bool fold_stmt (irange &r, gimple *s, class fur_source &src, + tree name = NULL_TREE); +protected: + bool range_of_range_op (irange &r, gimple *s, fur_source &src); + bool range_of_call (irange &r, gcall *call, fur_source &src); + bool range_of_cond_expr (irange &r, gassign* cond, fur_source &src); + bool range_of_address (irange &r, gimple *s, fur_source &src); + bool range_of_builtin_call (irange &r, gcall *call, fur_source &src); + void range_of_builtin_ubsan_call (irange &r, gcall *call, tree_code code, + fur_source &src); + bool range_of_phi (irange &r, gphi *phi, fur_source &src); + void range_of_ssa_name_with_loop_info (irange &, tree, class loop *, gphi *, + fur_source &src); + void relation_fold_and_or (irange& lhs_range, gimple *s, fur_source &src); + void postfold_gcond_edges (gcond *s, fur_source &src); +}; +#endif // GCC_GIMPLE_RANGE_FOLD_H |