/* Header file for gimple range phi analysis. Copyright (C) 2023-2024 Free Software Foundation, Inc. Contributed by 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_SSA_RANGE_PHI_H #define GCC_SSA_RANGE_PHI_H // ------------------------------------------------------------------------- // A PHI_GROUP consists of a set of SSA_NAMES which are all PHI_DEFS, and // their arguemnts contain nothing but other PHI defintions, with at most // 2 exceptions: // 1 - An initial value. This is either a constant, or another non-phi name // with a single incoming edge to the cycle group // 2 - A modifier statement which adjusts the value. ie, name2 = phi_name + 1 // The initial range is used to create one bound and the modifier is examined // to determine the other bound. // All members of the PHI cycle will be given the same range. // // For example, given the follwoing sequences: // qa_20 = qa_10 + 1; // qa_9 = PHI // qa_10 = PHI <0(2), qa_9(5)> // // We can determine the following group: // // PHI cycle members qa_9, qa_10 // Initial value : 0 // modifier stmt: qa_20 = qa_10 + 1; // // Based on just this analysis, We can project that qa_9 and qa_10 will have // a range of [0, +INF]. class phi_group { public: phi_group (bitmap bm, irange &init_range, gimple *mod, range_query *q); phi_group (const phi_group &g); const_bitmap group () const { return m_group; } const vrange &range () const { return m_vr; } gimple *modifier_stmt () const { return m_modifier; } void dump (FILE *); protected: bool calculate_using_modifier (range_query *q); bool refine_using_relation (relation_kind k); static unsigned is_modifier_p (gimple *s, const bitmap bm); bitmap m_group; gimple *m_modifier; // Single stmt which modifies phi group. unsigned m_modifier_op; // Operand of group member in modifier stmt. int_range_max m_vr; friend class phi_analyzer; }; // The phi anlyzer will return the group that name belongs to. // If inforamtion is not known about a name yet, analysis is conducted by // looking at the arguments to PHIS and following them to their defs to // determine whether the conditions are met to form a new group. class phi_analyzer { public: phi_analyzer (range_query &); ~phi_analyzer (); phi_group *operator[] (tree name); void dump (FILE *f); protected: phi_group *group (tree name) const; void process_phi (gphi *phi); range_query &m_global; vec m_work; bitmap m_simple; // Processed, not part of a group. bitmap m_current; // Potential group currently being analyzed. vec m_phi_groups; vec m_tab; bitmap_obstack m_bitmaps; }; // These are the APIs to start and stop a phi analyzerin a SCEV like manner. // There can only be one operating at any given time. // When initialized, a range-query if provided to do lookups of values for // PHIs and to evaluate modifier and initial value statements. // To avoid problems, this should be some form of constant query, like // global_range_query or better yet a const_query from a functioning ranger. bool phi_analysis_available_p (); phi_analyzer &phi_analysis (); void phi_analysis_initialize (range_query &); void phi_analysis_finalize (); #endif // GCC_SSA_RANGE_PHI_H