Home | History | Annotate | Line # | Download | only in gcc
      1 /* List management for the GCC expander.
      2    Copyright (C) 1987-2022 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 #include "config.h"
     21 #include "system.h"
     22 #include "coretypes.h"
     23 #include "tm.h"
     24 #include "rtl.h"
     25 
     26 static void free_list (rtx *, rtx *);
     27 
     28 /* Functions for maintaining cache-able lists of EXPR_LIST and INSN_LISTs.  */
     29 
     30 /* An INSN_LIST containing all INSN_LISTs allocated but currently unused.  */
     31 static GTY ((deletable)) rtx unused_insn_list;
     32 
     33 /* An EXPR_LIST containing all EXPR_LISTs allocated but currently unused.  */
     34 static GTY ((deletable)) rtx unused_expr_list;
     35 
     36 /* This function will free an entire list of either EXPR_LIST, INSN_LIST
     37    or DEPS_LIST nodes.  This is to be used only on lists that consist
     38    exclusively of nodes of one type only.  This is only called by
     39    free_EXPR_LIST_list, free_INSN_LIST_list and free_DEPS_LIST_list.  */
     40 static void
     41 free_list (rtx *listp, rtx *unused_listp)
     42 {
     43   rtx link, prev_link;
     44 
     45   prev_link = *listp;
     46   link = XEXP (prev_link, 1);
     47 
     48   gcc_assert (unused_listp != &unused_insn_list
     49 	      || GET_CODE (prev_link) == INSN_LIST);
     50 
     51   while (link)
     52     {
     53       gcc_assert (unused_listp != &unused_insn_list
     54 		  || GET_CODE (prev_link) == INSN_LIST);
     55 
     56       prev_link = link;
     57       link = XEXP (link, 1);
     58     }
     59 
     60   XEXP (prev_link, 1) = *unused_listp;
     61   *unused_listp = *listp;
     62   *listp = 0;
     63 }
     64 
     65 /* Find corresponding to ELEM node in the list pointed to by LISTP.
     66    This node must exist in the list.  Returns pointer to that node.  */
     67 static rtx *
     68 find_list_elem (rtx elem, rtx *listp)
     69 {
     70   while (XEXP (*listp, 0) != elem)
     71     listp = &XEXP (*listp, 1);
     72   return listp;
     73 }
     74 
     75 /* Remove the node pointed to by LISTP from the list.  */
     76 static void
     77 remove_list_node (rtx *listp)
     78 {
     79   rtx node;
     80 
     81   node = *listp;
     82   *listp = XEXP (node, 1);
     83   XEXP (node, 1) = 0;
     84 }
     85 
     86 /* Removes corresponding to ELEM node from the list pointed to by LISTP.
     87    Returns that node.  */
     88 rtx
     89 remove_list_elem (rtx elem, rtx *listp)
     90 {
     91   rtx node;
     92 
     93   listp = find_list_elem (elem, listp);
     94   node = *listp;
     95   remove_list_node (listp);
     96   return node;
     97 }
     98 
     99 /* This call is used in place of a gen_rtx_INSN_LIST. If there is a cached
    100    node available, we'll use it, otherwise a call to gen_rtx_INSN_LIST
    101    is made.  */
    102 rtx_insn_list *
    103 alloc_INSN_LIST (rtx val, rtx next)
    104 {
    105   rtx_insn_list *r;
    106 
    107   if (unused_insn_list)
    108     {
    109       r = as_a <rtx_insn_list *> (unused_insn_list);
    110       unused_insn_list = r->next ();
    111       XEXP (r, 0) = val;
    112       XEXP (r, 1) = next;
    113       PUT_REG_NOTE_KIND (r, VOIDmode);
    114 
    115       gcc_assert (GET_CODE (r) == INSN_LIST);
    116     }
    117   else
    118     r = gen_rtx_INSN_LIST (VOIDmode, val, next);
    119 
    120   return r;
    121 }
    122 
    123 /* This call is used in place of a gen_rtx_EXPR_LIST. If there is a cached
    124    node available, we'll use it, otherwise a call to gen_rtx_EXPR_LIST
    125    is made.  */
    126 rtx_expr_list *
    127 alloc_EXPR_LIST (int kind, rtx val, rtx next)
    128 {
    129   rtx_expr_list *r;
    130 
    131   if (unused_expr_list)
    132     {
    133       r = as_a <rtx_expr_list *> (unused_expr_list);
    134       unused_expr_list = XEXP (r, 1);
    135       XEXP (r, 0) = val;
    136       XEXP (r, 1) = next;
    137       PUT_REG_NOTE_KIND (r, kind);
    138     }
    139   else
    140     r = gen_rtx_EXPR_LIST ((machine_mode) kind, val, next);
    141 
    142   return r;
    143 }
    144 
    145 /* This function will free up an entire list of EXPR_LIST nodes.  */
    146 void
    147 free_EXPR_LIST_list (rtx_expr_list **listp)
    148 {
    149   if (*listp == 0)
    150     return;
    151   free_list ((rtx *)listp, &unused_expr_list);
    152 }
    153 
    154 /* This function will free up an entire list of INSN_LIST nodes.  */
    155 void
    156 free_INSN_LIST_list (rtx_insn_list **listp)
    157 {
    158   if (*listp == 0)
    159     return;
    160   free_list ((rtx *)listp, &unused_insn_list);
    161 }
    162 
    163 /* Make a copy of the INSN_LIST list LINK and return it.  */
    164 rtx_insn_list *
    165 copy_INSN_LIST (rtx_insn_list *link)
    166 {
    167   rtx_insn_list *new_queue;
    168   rtx_insn_list **pqueue = &new_queue;
    169 
    170   for (; link; link = link->next ())
    171     {
    172       rtx_insn *x = link->insn ();
    173       rtx_insn_list *newlink = alloc_INSN_LIST (x, NULL);
    174       *pqueue = newlink;
    175       pqueue = (rtx_insn_list **)&XEXP (newlink, 1);
    176     }
    177   *pqueue = NULL;
    178   return new_queue;
    179 }
    180 
    181 /* Duplicate the INSN_LIST elements of COPY and prepend them to OLD.  */
    182 rtx_insn_list *
    183 concat_INSN_LIST (rtx_insn_list *copy, rtx_insn_list *old)
    184 {
    185   rtx_insn_list *new_rtx = old;
    186   for (; copy ; copy = copy->next ())
    187     {
    188       new_rtx = alloc_INSN_LIST (copy->insn (), new_rtx);
    189       PUT_REG_NOTE_KIND (new_rtx, REG_NOTE_KIND (copy));
    190     }
    191   return new_rtx;
    192 }
    193 
    194 /* This function will free up an individual EXPR_LIST node.  */
    195 void
    196 free_EXPR_LIST_node (rtx ptr)
    197 {
    198   XEXP (ptr, 1) = unused_expr_list;
    199   unused_expr_list = ptr;
    200 }
    201 
    202 /* This function will free up an individual INSN_LIST node.  */
    203 void
    204 free_INSN_LIST_node (rtx ptr)
    205 {
    206   gcc_assert (GET_CODE (ptr) == INSN_LIST);
    207   XEXP (ptr, 1) = unused_insn_list;
    208   unused_insn_list = ptr;
    209 }
    210 
    211 /* Remove and free corresponding to ELEM node in the INSN_LIST pointed to
    212    by LISTP.  */
    213 void
    214 remove_free_INSN_LIST_elem (rtx_insn *elem, rtx_insn_list **listp)
    215 {
    216   free_INSN_LIST_node (remove_list_elem (elem, (rtx *)listp));
    217 }
    218 
    219 /* Remove and free the first node in the INSN_LIST pointed to by LISTP.  */
    220 rtx_insn *
    221 remove_free_INSN_LIST_node (rtx_insn_list **listp)
    222 {
    223   rtx_insn_list *node = *listp;
    224   rtx_insn *elem = node->insn ();
    225 
    226   remove_list_node ((rtx *)listp);
    227   free_INSN_LIST_node (node);
    228 
    229   return elem;
    230 }
    231 
    232 /* Remove and free the first node in the EXPR_LIST pointed to by LISTP.  */
    233 rtx
    234 remove_free_EXPR_LIST_node (rtx_expr_list **listp)
    235 {
    236   rtx_expr_list *node = *listp;
    237   rtx elem = XEXP (node, 0);
    238 
    239   remove_list_node ((rtx *)listp);
    240   free_EXPR_LIST_node (node);
    241 
    242   return elem;
    243 }
    244 
    245 #include "gt-lists.h"
    246