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