Home | History | Annotate | Line # | Download | only in gcc
      1  1.1  mrg /* Analyze RTL for GNU compiler.
      2  1.1  mrg    Copyright (C) 2020-2022 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg This file is part of GCC.
      5  1.1  mrg 
      6  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      7  1.1  mrg the terms of the GNU General Public License as published by the Free
      8  1.1  mrg Software Foundation; either version 3, or (at your option) any later
      9  1.1  mrg version.
     10  1.1  mrg 
     11  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     12  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  1.1  mrg for more details.
     15  1.1  mrg 
     16  1.1  mrg You should have received a copy of the GNU General Public License
     17  1.1  mrg along with GCC; see the file COPYING3.  If not see
     18  1.1  mrg <http://www.gnu.org/licenses/>.  */
     19  1.1  mrg 
     20  1.1  mrg /* Note that for historical reasons, many rtlanal.cc functions are
     21  1.1  mrg    declared in rtl.h rather than here.  */
     22  1.1  mrg 
     23  1.1  mrg #ifndef GCC_RTLANAL_H
     24  1.1  mrg #define GCC_RTLANAL_H
     25  1.1  mrg 
     26  1.1  mrg /* A dummy register value that represents the whole of variable memory.
     27  1.1  mrg    Using ~0U means that arrays that track both registers and memory can
     28  1.1  mrg    be indexed by regno + 1.  */
     29  1.1  mrg const unsigned int MEM_REGNO = ~0U;
     30  1.1  mrg 
     31  1.1  mrg /* Bitmasks of flags describing an rtx_obj_reference.  See the accessors
     32  1.1  mrg    in the class for details.  */
     33  1.1  mrg namespace rtx_obj_flags
     34  1.1  mrg {
     35  1.1  mrg   const uint16_t IS_READ = 1U << 0;
     36  1.1  mrg   const uint16_t IS_WRITE = 1U << 1;
     37  1.1  mrg   const uint16_t IS_CLOBBER = 1U << 2;
     38  1.1  mrg   const uint16_t IS_PRE_POST_MODIFY = 1U << 3;
     39  1.1  mrg   const uint16_t IS_MULTIREG = 1U << 4;
     40  1.1  mrg   const uint16_t IN_MEM_LOAD = 1U << 5;
     41  1.1  mrg   const uint16_t IN_MEM_STORE = 1U << 6;
     42  1.1  mrg   const uint16_t IN_SUBREG = 1U << 7;
     43  1.1  mrg   const uint16_t IN_NOTE = 1U << 8;
     44  1.1  mrg 
     45  1.1  mrg   /* Flags that apply to all subrtxes of the rtx they were originally
     46  1.1  mrg      added for.  */
     47  1.1  mrg   static const uint16_t STICKY_FLAGS = IN_NOTE;
     48  1.1  mrg }
     49  1.1  mrg 
     50  1.1  mrg /* Contains information about a reference to a register or variable memory.  */
     51  1.1  mrg class rtx_obj_reference
     52  1.1  mrg {
     53  1.1  mrg public:
     54  1.1  mrg   rtx_obj_reference () = default;
     55  1.1  mrg   rtx_obj_reference (unsigned int regno, uint16_t flags,
     56  1.1  mrg 		     machine_mode mode, unsigned int multireg_offset = 0);
     57  1.1  mrg 
     58  1.1  mrg   bool is_reg () const { return regno != MEM_REGNO; }
     59  1.1  mrg   bool is_mem () const { return regno == MEM_REGNO; }
     60  1.1  mrg 
     61  1.1  mrg   /* True if the reference is a read or a write respectively.
     62  1.1  mrg      Both flags are set in a read-modify-write context, such as
     63  1.1  mrg      for read_modify_subreg_p.  */
     64  1.1  mrg   bool is_read () const { return flags & rtx_obj_flags::IS_READ; }
     65  1.1  mrg   bool is_write () const { return flags & rtx_obj_flags::IS_WRITE; }
     66  1.1  mrg 
     67  1.1  mrg   /* True if IS_WRITE and if the write is a clobber rather than a set.  */
     68  1.1  mrg   bool is_clobber () const { return flags & rtx_obj_flags::IS_CLOBBER; }
     69  1.1  mrg 
     70  1.1  mrg   /* True if the reference is updated by an RTX_AUTOINC.  Both IS_READ
     71  1.1  mrg      and IS_WRITE are also true if so.  */
     72  1.1  mrg   bool is_pre_post_modify () const
     73  1.1  mrg   {
     74  1.1  mrg     return flags & rtx_obj_flags::IS_PRE_POST_MODIFY;
     75  1.1  mrg   }
     76  1.1  mrg 
     77  1.1  mrg   /* True if the register is part of a multi-register hard REG.  */
     78  1.1  mrg   bool is_multireg () const { return flags & rtx_obj_flags::IS_MULTIREG; }
     79  1.1  mrg 
     80  1.1  mrg   /* True if the reference occurs in the address of a load MEM.  */
     81  1.1  mrg   bool in_mem_load () const { return flags & rtx_obj_flags::IN_MEM_LOAD; }
     82  1.1  mrg 
     83  1.1  mrg   /* True if the reference occurs in the address of a store MEM.  */
     84  1.1  mrg   bool in_mem_store () const { return flags & rtx_obj_flags::IN_MEM_STORE; }
     85  1.1  mrg 
     86  1.1  mrg   /* True if the reference occurs in any kind of MEM address.  */
     87  1.1  mrg   bool in_address () const { return in_mem_load () || in_mem_store (); }
     88  1.1  mrg 
     89  1.1  mrg   /* True if the reference occurs in a SUBREG.  */
     90  1.1  mrg   bool in_subreg () const { return flags & rtx_obj_flags::IN_SUBREG; }
     91  1.1  mrg 
     92  1.1  mrg   /* True if the reference occurs in a REG_EQUAL or REG_EQUIV note.  */
     93  1.1  mrg   bool in_note () const { return flags & rtx_obj_flags::IN_NOTE; }
     94  1.1  mrg 
     95  1.1  mrg   /* The referenced register, or MEM_REGNO for variable memory.  */
     96  1.1  mrg   unsigned int regno;
     97  1.1  mrg 
     98  1.1  mrg   /* A bitmask of rtx_obj_flags.  */
     99  1.1  mrg   unsigned int flags : 16;
    100  1.1  mrg 
    101  1.1  mrg   /* The mode of the reference.  If IS_MULTIREG, this is the mode of
    102  1.1  mrg      REGNO - MULTIREG_OFFSET.  */
    103  1.1  mrg   machine_mode mode : 8;
    104  1.1  mrg 
    105  1.1  mrg   /* If IS_MULTIREG, the offset of REGNO from the start of the register.  */
    106  1.1  mrg   unsigned int multireg_offset : 8;
    107  1.1  mrg };
    108  1.1  mrg 
    109  1.1  mrg /* Construct a reference with the given fields.  */
    110  1.1  mrg 
    111  1.1  mrg inline rtx_obj_reference::rtx_obj_reference (unsigned int regno, uint16_t flags,
    112  1.1  mrg 					     machine_mode mode,
    113  1.1  mrg 					     unsigned int multireg_offset)
    114  1.1  mrg   : regno (regno),
    115  1.1  mrg     flags (flags),
    116  1.1  mrg     mode (mode),
    117  1.1  mrg     multireg_offset (multireg_offset)
    118  1.1  mrg {
    119  1.1  mrg }
    120  1.1  mrg 
    121  1.1  mrg /* Contains information about an rtx or an instruction, including a
    122  1.1  mrg    list of rtx_obj_references.  The storage backing the list needs
    123  1.1  mrg    to be filled in by assigning to REF_BEGIN and REF_END.  */
    124  1.1  mrg 
    125  1.1  mrg class rtx_properties
    126  1.1  mrg {
    127  1.1  mrg public:
    128  1.1  mrg   rtx_properties ();
    129  1.1  mrg 
    130  1.1  mrg   void try_to_add_reg (const_rtx x, unsigned int flags = 0);
    131  1.1  mrg   void try_to_add_dest (const_rtx x, unsigned int flags = 0);
    132  1.1  mrg   void try_to_add_src (const_rtx x, unsigned int flags = 0);
    133  1.1  mrg   void try_to_add_pattern (const_rtx pat);
    134  1.1  mrg   void try_to_add_note (const_rtx x);
    135  1.1  mrg   void try_to_add_insn (const rtx_insn *insn, bool include_notes);
    136  1.1  mrg 
    137  1.1  mrg   iterator_range<rtx_obj_reference *> refs () const;
    138  1.1  mrg 
    139  1.1  mrg   /* Return the number of rtx_obj_references that have been recorded.  */
    140  1.1  mrg   size_t num_refs () const { return ref_iter - ref_begin; }
    141  1.1  mrg 
    142  1.1  mrg   bool has_side_effects () const;
    143  1.1  mrg 
    144  1.1  mrg   /* [REF_BEGIN, REF_END) is the maximum extent of the memory available
    145  1.1  mrg      for recording references.  REG_ITER is the first unused entry.  */
    146  1.1  mrg   rtx_obj_reference *ref_begin;
    147  1.1  mrg   rtx_obj_reference *ref_iter;
    148  1.1  mrg   rtx_obj_reference *ref_end;
    149  1.1  mrg 
    150  1.1  mrg   /* True if the rtx includes an asm.  */
    151  1.1  mrg   unsigned int has_asm : 1;
    152  1.1  mrg 
    153  1.1  mrg   /* True if the rtx includes a call.  */
    154  1.1  mrg   unsigned int has_call : 1;
    155  1.1  mrg 
    156  1.1  mrg   /* True if the rtx includes an RTX_AUTOINC expression.  */
    157  1.1  mrg   unsigned int has_pre_post_modify : 1;
    158  1.1  mrg 
    159  1.1  mrg   /* True if the rtx contains volatile references, in the sense of
    160  1.1  mrg      volatile_refs_p.  */
    161  1.1  mrg   unsigned int has_volatile_refs : 1;
    162  1.1  mrg 
    163  1.1  mrg   /* For future expansion.  */
    164  1.1  mrg   unsigned int spare : 28;
    165  1.1  mrg };
    166  1.1  mrg 
    167  1.1  mrg inline rtx_properties::rtx_properties ()
    168  1.1  mrg   : ref_begin (nullptr),
    169  1.1  mrg     ref_iter (nullptr),
    170  1.1  mrg     ref_end (nullptr),
    171  1.1  mrg     has_asm (false),
    172  1.1  mrg     has_call (false),
    173  1.1  mrg     has_pre_post_modify (false),
    174  1.1  mrg     has_volatile_refs (false),
    175  1.1  mrg     spare (0)
    176  1.1  mrg {
    177  1.1  mrg }
    178  1.1  mrg 
    179  1.1  mrg /* Like add_src, but treat X has being part of a REG_EQUAL or
    180  1.1  mrg    REG_EQUIV note.  */
    181  1.1  mrg 
    182  1.1  mrg inline void
    183  1.1  mrg rtx_properties::try_to_add_note (const_rtx x)
    184  1.1  mrg {
    185  1.1  mrg   try_to_add_src (x, rtx_obj_flags::IN_NOTE);
    186  1.1  mrg }
    187  1.1  mrg 
    188  1.1  mrg /* Return true if the rtx has side effects, in the sense of
    189  1.1  mrg    side_effects_p (except for side_effects_p's special handling
    190  1.1  mrg    of combine.cc clobbers).  */
    191  1.1  mrg 
    192  1.1  mrg inline bool
    193  1.1  mrg rtx_properties::has_side_effects () const
    194  1.1  mrg {
    195  1.1  mrg   return has_volatile_refs || has_pre_post_modify || has_call;
    196  1.1  mrg }
    197  1.1  mrg 
    198  1.1  mrg /* Return an iterator range for all the references, suitable for
    199  1.1  mrg    range-based for loops.  */
    200  1.1  mrg 
    201  1.1  mrg inline iterator_range<rtx_obj_reference *>
    202  1.1  mrg rtx_properties::refs () const
    203  1.1  mrg {
    204  1.1  mrg   return { ref_begin, ref_iter };
    205  1.1  mrg }
    206  1.1  mrg 
    207  1.1  mrg /* BASE is derived from rtx_properties and provides backing storage
    208  1.1  mrg    for REF_BEGIN.  It has a grow () method that increases the amount
    209  1.1  mrg    of memory available if the initial allocation was too small.  */
    210  1.1  mrg 
    211  1.1  mrg template<typename Base>
    212  1.1  mrg class growing_rtx_properties : public Base
    213  1.1  mrg {
    214  1.1  mrg public:
    215  1.1  mrg   template<typename... Args>
    216  1.1  mrg   growing_rtx_properties (Args...);
    217  1.1  mrg 
    218  1.1  mrg   template<typename AddFn>
    219  1.1  mrg   void repeat (AddFn add);
    220  1.1  mrg 
    221  1.1  mrg   /* Wrappers around the try_to_* functions that always succeed.  */
    222  1.1  mrg   void add_dest (const_rtx x, unsigned int flags = 0);
    223  1.1  mrg   void add_src (const_rtx x, unsigned int flags = 0);
    224  1.1  mrg   void add_pattern (const_rtx pat);
    225  1.1  mrg   void add_note (const_rtx x);
    226  1.1  mrg   void add_insn (const rtx_insn *insn, bool include_notes);
    227  1.1  mrg };
    228  1.1  mrg 
    229  1.1  mrg template<typename Base>
    230  1.1  mrg template<typename... Args>
    231  1.1  mrg growing_rtx_properties<Base>::growing_rtx_properties (Args... args)
    232  1.1  mrg   : Base (std::forward<Args> (args)...)
    233  1.1  mrg {
    234  1.1  mrg }
    235  1.1  mrg 
    236  1.1  mrg /* Perform ADD until there is enough room to hold the result.  */
    237  1.1  mrg 
    238  1.1  mrg template<typename Base>
    239  1.1  mrg template<typename AddFn>
    240  1.1  mrg inline void
    241  1.1  mrg growing_rtx_properties<Base>::repeat (AddFn add)
    242  1.1  mrg {
    243  1.1  mrg   ptrdiff_t count = this->num_refs ();
    244  1.1  mrg   for (;;)
    245  1.1  mrg     {
    246  1.1  mrg       add ();
    247  1.1  mrg       /* This retries if the storage happened to be exactly the right size,
    248  1.1  mrg 	 but that's expected to be a rare case and so isn't worth
    249  1.1  mrg 	 optimizing for.  */
    250  1.1  mrg       if (__builtin_expect (this->ref_iter != this->ref_end, 1))
    251  1.1  mrg 	break;
    252  1.1  mrg       this->grow (count);
    253  1.1  mrg     }
    254  1.1  mrg }
    255  1.1  mrg 
    256  1.1  mrg template<typename Base>
    257  1.1  mrg inline void
    258  1.1  mrg growing_rtx_properties<Base>::add_dest (const_rtx x, unsigned int flags)
    259  1.1  mrg {
    260  1.1  mrg   repeat ([&]() { this->try_to_add_dest (x, flags); });
    261  1.1  mrg }
    262  1.1  mrg 
    263  1.1  mrg template<typename Base>
    264  1.1  mrg inline void
    265  1.1  mrg growing_rtx_properties<Base>::add_src (const_rtx x, unsigned int flags)
    266  1.1  mrg {
    267  1.1  mrg   repeat ([&]() { this->try_to_add_src (x, flags); });
    268  1.1  mrg }
    269  1.1  mrg 
    270  1.1  mrg template<typename Base>
    271  1.1  mrg inline void
    272  1.1  mrg growing_rtx_properties<Base>::add_pattern (const_rtx pat)
    273  1.1  mrg {
    274  1.1  mrg   repeat ([&]() { this->try_to_add_pattern (pat); });
    275  1.1  mrg }
    276  1.1  mrg 
    277  1.1  mrg template<typename Base>
    278  1.1  mrg inline void
    279  1.1  mrg growing_rtx_properties<Base>::add_note (const_rtx x)
    280  1.1  mrg {
    281  1.1  mrg   repeat ([&]() { this->try_to_add_note (x); });
    282  1.1  mrg }
    283  1.1  mrg 
    284  1.1  mrg template<typename Base>
    285  1.1  mrg inline void
    286  1.1  mrg growing_rtx_properties<Base>::add_insn (const rtx_insn *insn, bool include_notes)
    287  1.1  mrg {
    288  1.1  mrg   repeat ([&]() { this->try_to_add_insn (insn, include_notes); });
    289  1.1  mrg }
    290  1.1  mrg 
    291  1.1  mrg /* A base class for vec_rtx_properties; see there for details.  */
    292  1.1  mrg 
    293  1.1  mrg class vec_rtx_properties_base : public rtx_properties
    294  1.1  mrg {
    295  1.1  mrg   static const size_t SIZE = 32;
    296  1.1  mrg 
    297  1.1  mrg public:
    298  1.1  mrg   vec_rtx_properties_base ();
    299  1.1  mrg   ~vec_rtx_properties_base ();
    300  1.1  mrg 
    301  1.1  mrg protected:
    302  1.1  mrg   void grow (ptrdiff_t);
    303  1.1  mrg 
    304  1.1  mrg private:
    305  1.1  mrg   rtx_obj_reference m_storage[SIZE];
    306  1.1  mrg };
    307  1.1  mrg 
    308  1.1  mrg inline vec_rtx_properties_base::vec_rtx_properties_base ()
    309  1.1  mrg {
    310  1.1  mrg   ref_begin = ref_iter = m_storage;
    311  1.1  mrg   ref_end = m_storage + SIZE;
    312  1.1  mrg }
    313  1.1  mrg 
    314  1.1  mrg inline vec_rtx_properties_base::~vec_rtx_properties_base ()
    315  1.1  mrg {
    316  1.1  mrg   if (__builtin_expect (ref_begin != m_storage, 0))
    317  1.1  mrg     free (ref_begin);
    318  1.1  mrg }
    319  1.1  mrg 
    320  1.1  mrg /* A rtx_properties that stores its references in a temporary array.
    321  1.1  mrg    Like auto_vec, the array is initially on the stack, but can switch
    322  1.1  mrg    to the heap if necessary.
    323  1.1  mrg 
    324  1.1  mrg    The reason for implementing this as a derived class is that the
    325  1.1  mrg    default on-stack size should be enough for the vast majority of
    326  1.1  mrg    expressions and instructions.  It's therefore not worth paying
    327  1.1  mrg    the cost of conditionally calling grow code at every site that
    328  1.1  mrg    records a new reference.  Instead, the rtx_properties code can use
    329  1.1  mrg    trivial iterator updates for the common case, and in the rare case
    330  1.1  mrg    that the vector needs to be resized, we can pay the cost of
    331  1.1  mrg    collecting the references a second time.  */
    332  1.1  mrg using vec_rtx_properties = growing_rtx_properties<vec_rtx_properties_base>;
    333  1.1  mrg 
    334  1.1  mrg bool
    335  1.1  mrg vec_series_highpart_p (machine_mode result_mode, machine_mode op_mode,
    336  1.1  mrg 		       rtx sel);
    337  1.1  mrg 
    338  1.1  mrg bool
    339  1.1  mrg vec_series_lowpart_p (machine_mode result_mode, machine_mode op_mode, rtx sel);
    340  1.1  mrg 
    341  1.1  mrg bool
    342  1.1  mrg contains_paradoxical_subreg_p (rtx x);
    343  1.1  mrg #endif
    344