LCOV - code coverage report
Current view: top level - gcc - rtlanal.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 48 48
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 4 4
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.