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