diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2022-10-13 18:03:58 -0400 |
---|---|---|
committer | Andrew MacLeod <amacleod@redhat.com> | 2022-10-17 09:20:39 -0400 |
commit | b565ac19264a5827162d28537bccc8531c25e817 (patch) | |
tree | 52a1122cf961dd409f02c3eb5c34811ed5e1f3e7 /gcc/value-relation.h | |
parent | 04874fedae8074b252abbd70fea68bf3dd0a605b (diff) | |
download | gcc-b565ac19264a5827162d28537bccc8531c25e817.zip gcc-b565ac19264a5827162d28537bccc8531c25e817.tar.gz gcc-b565ac19264a5827162d28537bccc8531c25e817.tar.bz2 |
Add relation_trio class for range-ops.
There are 3 possible relations range-ops might care about, but only the one
most likely to be needed is supplied. This patch provides a new class
relation_trio which allows 3 relations to be passed in a single word.
fold_range (), op1_range (), and op2_range () are adjusted to take a
relation_trio class instead of a relation_kind, then the routine can
extract which relation it wants to work with.
* gimple-range-fold.cc (fold_using_range::range_of_range_op):
Provide relation_trio class.
* gimple-range-gori.cc (gori_compute::refine_using_relation):
Provide relation_trio class.
(gori_compute::refine_using_relation): Ditto.
(gori_compute::compute_operand1_range): Provide lhs_op2 and
op1_op2 relations via relation_trio class.
(gori_compute::compute_operand2_range): Ditto.
* gimple-range-op.cc (gimple_range_op_handler::calc_op1): Use
relation_trio instead of relation_kind.
(gimple_range_op_handler::calc_op2): Ditto.
(*::fold_range): Ditto.
* gimple-range-op.h (gimple_range_op::calc_op1): Adjust prototypes.
(gimple_range_op::calc_op2): Adjust prototypes.
* range-op-float.cc (*::fold_range): Use relation_trio instead of
relation_kind.
(*::op1_range): Ditto.
(*::op2_range): Ditto.
* range-op.cc (*::fold_range): Use relation_trio instead of
relation_kind.
(*::op1_range): Ditto.
(*::op2_range): Ditto.
* range-op.h (class range_operator): Adjust prototypes.
(class range_operator_float): Ditto.
(class range_op_handler): Adjust prototypes.
(relop_early_resolve): Pickup op1_op2 relation from relation_trio.
* value-relation.cc (VREL_LAST): Adjust use to be one past the end of
the enum.
(relation_oracle::validate_relation): Use relation_trio in call
to fold_range.
* value-relation.h (enum relation_kind_t): Add VREL_LAST as
final element.
(class relation_trio): New.
(TRIO_VARYING, TRIO_SHIFT, TRIO_MASK): New.
Diffstat (limited to 'gcc/value-relation.h')
-rw-r--r-- | gcc/value-relation.h | 119 |
1 files changed, 107 insertions, 12 deletions
diff --git a/gcc/value-relation.h b/gcc/value-relation.h index fa9097a..027d741 100644 --- a/gcc/value-relation.h +++ b/gcc/value-relation.h @@ -35,20 +35,21 @@ along with GCC; see the file COPYING3. If not see // utilizes the relation information to enhance it's range calculations, this // is totally transparent to the client, and they are free to make queries. // -// -// relation_kind is a typedef of enum tree_code, but has restricted range -// and a couple of extra values. +// relation_kind is a new enum which represents the different relations, +// often with a direct mapping to treee codes. ie VREL_EQ is equivalent to +// EQ_EXPR. // // A query is made requesting the relation between SSA1 and SSA@ in a basic // block, or on an edge, the possible return values are: // -// EQ_EXPR, NE_EXPR, LT_EXPR, LE_EXPR, GT_EXPR, and GE_EXPR mean the same. +// VREL_EQ, VREL_NE, VREL_LT, VREL_LE, VREL_GT, and VREL_GE mean the same. // VREL_VARYING : No relation between the 2 names. // VREL_UNDEFINED : Impossible relation (ie, A < B && A > B) // -// The oracle maintains EQ_EXPR relations with equivalency sets, so if a -// relation comes back EQ_EXPR, it is also possible to query the set of -// equivlaencies. These are basically bitmaps over ssa_names. +// The oracle maintains VREL_EQ relations with equivalency sets, so if a +// relation comes back VREL_EQ, it is also possible to query the set of +// equivlaencies. These are basically bitmaps over ssa_names. An iterator is +// provided later for this activity. // // Relations are maintained via the dominace trees and are optimized assuming // they are registered in dominance order. When a new relation is added, it @@ -56,10 +57,8 @@ along with GCC; see the file COPYING3. If not see // and registered at the specified block. -// Rather than introduce a new enumerated type for relations, we can use the -// existing tree_codes for relations, plus add a couple of #defines for -// the other cases. These codes are arranged such that VREL_VARYING is the -// first code, and all the rest are contiguous. +// These codes are arranged such that VREL_VARYING is the first code, and all +// the rest are contiguous. typedef enum relation_kind_t { @@ -74,7 +73,8 @@ typedef enum relation_kind_t VREL_PE8, // 8 bit partial equivalency VREL_PE16, // 16 bit partial equivalency VREL_PE32, // 32 bit partial equivalency - VREL_PE64 // 64 bit partial equivalency + VREL_PE64, // 64 bit partial equivalency + VREL_LAST // terminate, not a real relation. } relation_kind; // General relation kind transformations. @@ -315,6 +315,101 @@ protected: ((equiv_name) = iter.get_name (&equiv_rel)); \ iter.next ()) +// ----------------------------------------------------------------------- + +// Range-ops deals with a LHS and 2 operands. A relation trio is a set of +// 3 potential relations packed into a single unsigned value. +// 1 - LHS relation OP1 +// 2 - LHS relation OP2 +// 3 - OP1 relation OP2 +// VREL_VARYING is a value of 0, and is the default for each position. +class relation_trio +{ +public: + relation_trio (); + relation_trio (relation_kind lhs_op1, relation_kind lhs_op2, + relation_kind op1_op2); + relation_kind lhs_op1 (); + relation_kind lhs_op2 (); + relation_kind op1_op2 (); + relation_trio swap_op1_op2 (); + + static relation_trio lhs_op1 (relation_kind k); + static relation_trio lhs_op2 (relation_kind k); + static relation_trio op1_op2 (relation_kind k); + +protected: + unsigned m_val; +}; + +// Default VREL_VARYING for all 3 relations. +#define TRIO_VARYING relation_trio () + +#define TRIO_SHIFT 4 +#define TRIO_MASK 0x000F + +// These 3 classes are shortcuts for when a caller has a single relation to +// pass as a trio, it can simply construct the appropriate one. The other +// unspecified realtions will be VREL_VARYING. + +inline relation_trio::relation_trio () +{ + STATIC_ASSERT (VREL_LAST <= (1 << TRIO_SHIFT)); + m_val = 0; +} + +inline relation_trio::relation_trio (relation_kind lhs_op1, + relation_kind lhs_op2, + relation_kind op1_op2) +{ + STATIC_ASSERT (VREL_LAST <= (1 << TRIO_SHIFT)); + unsigned i1 = (unsigned) lhs_op1; + unsigned i2 = ((unsigned) lhs_op2) << TRIO_SHIFT; + unsigned i3 = ((unsigned) op1_op2) << (TRIO_SHIFT * 2); + m_val = i1 | i2 | i3; +} + +inline relation_trio +relation_trio::lhs_op1 (relation_kind k) +{ + return relation_trio (k, VREL_VARYING, VREL_VARYING); +} +inline relation_trio +relation_trio::lhs_op2 (relation_kind k) +{ + return relation_trio (VREL_VARYING, k, VREL_VARYING); +} +inline relation_trio +relation_trio::op1_op2 (relation_kind k) +{ + return relation_trio (VREL_VARYING, VREL_VARYING, k); +} + +inline relation_kind +relation_trio::lhs_op1 () +{ + return (relation_kind) (m_val & TRIO_MASK); +} + +inline relation_kind +relation_trio::lhs_op2 () +{ + return (relation_kind) ((m_val >> TRIO_SHIFT) & TRIO_MASK); +} + +inline relation_kind +relation_trio::op1_op2 () +{ + return (relation_kind) ((m_val >> (TRIO_SHIFT * 2)) & TRIO_MASK); +} + +inline relation_trio +relation_trio::swap_op1_op2 () +{ + return relation_trio (lhs_op2 (), lhs_op1 (), relation_swap (op1_op2 ())); +} + +// ----------------------------------------------------------------------- // The value-relation class is used to encapsulate the represention of an // individual relation between 2 ssa-names, and to facilitate operating on |