1132718Skan/* List management for the GCC expander.
290075Sobrien   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3169689Skan   1999, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
490075Sobrien
590075SobrienThis file is part of GCC.
690075Sobrien
790075SobrienGCC is free software; you can redistribute it and/or modify it under
890075Sobrienthe terms of the GNU General Public License as published by the Free
990075SobrienSoftware Foundation; either version 2, or (at your option) any later
1090075Sobrienversion.
1190075Sobrien
1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1490075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590075Sobrienfor more details.
1690075Sobrien
1790075SobrienYou should have received a copy of the GNU General Public License
1890075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
2190075Sobrien
2290075Sobrien#include "config.h"
2390075Sobrien#include "system.h"
24132718Skan#include "coretypes.h"
25132718Skan#include "tm.h"
2690075Sobrien#include "toplev.h"
2790075Sobrien#include "rtl.h"
2890075Sobrien#include "ggc.h"
2990075Sobrien
30132718Skanstatic void free_list (rtx *, rtx *);
31169689Skanstatic void free_DEPS_LIST_node (rtx);
3290075Sobrien
3390075Sobrien/* Functions for maintaining cache-able lists of EXPR_LIST and INSN_LISTs.  */
3490075Sobrien
3590075Sobrien/* An INSN_LIST containing all INSN_LISTs allocated but currently unused.  */
36169689Skanstatic GTY ((deletable)) rtx unused_insn_list;
3790075Sobrien
3890075Sobrien/* An EXPR_LIST containing all EXPR_LISTs allocated but currently unused.  */
39169689Skanstatic GTY ((deletable)) rtx unused_expr_list;
4090075Sobrien
41169689Skan/* An DEPS_LIST containing all DEPS_LISTs allocated but currently unused.  */
42169689Skanstatic GTY ((deletable)) rtx unused_deps_list;
4390075Sobrien
44169689Skan
45169689Skan/* This function will free an entire list of either EXPR_LIST, INSN_LIST
46169689Skan   or DEPS_LIST nodes.  This is to be used only on lists that consist
47169689Skan   exclusively of nodes of one type only.  This is only called by
48169689Skan   free_EXPR_LIST_list, free_INSN_LIST_list and free_DEPS_LIST_list.  */
4990075Sobrienstatic void
50132718Skanfree_list (rtx *listp, rtx *unused_listp)
5190075Sobrien{
5290075Sobrien  rtx link, prev_link;
5390075Sobrien
5490075Sobrien  prev_link = *listp;
5590075Sobrien  link = XEXP (prev_link, 1);
5690075Sobrien
57169689Skan  gcc_assert ((unused_listp != &unused_insn_list
58169689Skan	       || GET_CODE (prev_link) == INSN_LIST)
59169689Skan	      && (unused_listp != &unused_deps_list
60169689Skan		  || GET_CODE (prev_link) == DEPS_LIST));
61169689Skan
6290075Sobrien  while (link)
6390075Sobrien    {
64169689Skan      gcc_assert ((unused_listp != &unused_insn_list
65169689Skan		   || GET_CODE (prev_link) == INSN_LIST)
66169689Skan		  && (unused_listp != &unused_deps_list
67169689Skan		      || GET_CODE (prev_link) == DEPS_LIST));
68169689Skan
6990075Sobrien      prev_link = link;
7090075Sobrien      link = XEXP (link, 1);
7190075Sobrien    }
7290075Sobrien
7390075Sobrien  XEXP (prev_link, 1) = *unused_listp;
7490075Sobrien  *unused_listp = *listp;
7590075Sobrien  *listp = 0;
7690075Sobrien}
7790075Sobrien
78169689Skan/* Find corresponding to ELEM node in the list pointed to by LISTP.
79169689Skan   This node must exist in the list.  Returns pointer to that node.  */
80169689Skanstatic rtx *
81169689Skanfind_list_elem (rtx elem, rtx *listp)
82169689Skan{
83169689Skan  while (XEXP (*listp, 0) != elem)
84169689Skan    listp = &XEXP (*listp, 1);
85169689Skan  return listp;
86169689Skan}
87169689Skan
88169689Skan/* Remove the node pointed to by LISTP from the list.  */
89169689Skanstatic void
90169689Skanremove_list_node (rtx *listp)
91169689Skan{
92169689Skan  rtx node;
93169689Skan
94169689Skan  node = *listp;
95169689Skan  *listp = XEXP (node, 1);
96169689Skan  XEXP (node, 1) = 0;
97169689Skan}
98169689Skan
99169689Skan/* Removes corresponding to ELEM node from the list pointed to by LISTP.
100169689Skan   Returns that node.  */
101169689Skanrtx
102169689Skanremove_list_elem (rtx elem, rtx *listp)
103169689Skan{
104169689Skan  rtx node;
105169689Skan
106169689Skan  listp = find_list_elem (elem, listp);
107169689Skan  node = *listp;
108169689Skan  remove_list_node (listp);
109169689Skan  return node;
110169689Skan}
111169689Skan
11290075Sobrien/* This call is used in place of a gen_rtx_INSN_LIST. If there is a cached
113117395Skan   node available, we'll use it, otherwise a call to gen_rtx_INSN_LIST
11490075Sobrien   is made.  */
11590075Sobrienrtx
116132718Skanalloc_INSN_LIST (rtx val, rtx next)
11790075Sobrien{
11890075Sobrien  rtx r;
11990075Sobrien
12090075Sobrien  if (unused_insn_list)
12190075Sobrien    {
12290075Sobrien      r = unused_insn_list;
12390075Sobrien      unused_insn_list = XEXP (r, 1);
12490075Sobrien      XEXP (r, 0) = val;
12590075Sobrien      XEXP (r, 1) = next;
12690075Sobrien      PUT_REG_NOTE_KIND (r, VOIDmode);
127169689Skan
128169689Skan      gcc_assert (GET_CODE (r) == INSN_LIST);
12990075Sobrien    }
13090075Sobrien  else
13190075Sobrien    r = gen_rtx_INSN_LIST (VOIDmode, val, next);
13290075Sobrien
13390075Sobrien  return r;
13490075Sobrien}
13590075Sobrien
13690075Sobrien/* This call is used in place of a gen_rtx_EXPR_LIST. If there is a cached
137117395Skan   node available, we'll use it, otherwise a call to gen_rtx_EXPR_LIST
13890075Sobrien   is made.  */
13990075Sobrienrtx
140132718Skanalloc_EXPR_LIST (int kind, rtx val, rtx next)
14190075Sobrien{
14290075Sobrien  rtx r;
14390075Sobrien
14490075Sobrien  if (unused_expr_list)
14590075Sobrien    {
14690075Sobrien      r = unused_expr_list;
14790075Sobrien      unused_expr_list = XEXP (r, 1);
14890075Sobrien      XEXP (r, 0) = val;
14990075Sobrien      XEXP (r, 1) = next;
15090075Sobrien      PUT_REG_NOTE_KIND (r, kind);
15190075Sobrien    }
15290075Sobrien  else
15390075Sobrien    r = gen_rtx_EXPR_LIST (kind, val, next);
15490075Sobrien
15590075Sobrien  return r;
15690075Sobrien}
15790075Sobrien
158169689Skan/* This call is used in place of a gen_rtx_DEPS_LIST.  If there is a cached
159169689Skan   node available, we'll use it, otherwise a call to gen_rtx_DEPS_LIST
160169689Skan   is made.  */
161169689Skanrtx
162169689Skanalloc_DEPS_LIST (rtx val, rtx next, int ds)
163169689Skan{
164169689Skan  rtx r;
165169689Skan
166169689Skan  if (unused_deps_list)
167169689Skan    {
168169689Skan      r = unused_deps_list;
169169689Skan      unused_deps_list = XEXP (r, 1);
170169689Skan      XEXP (r, 0) = val;
171169689Skan      XEXP (r, 1) = next;
172169689Skan      XINT (r, 2) = ds;
173169689Skan      PUT_REG_NOTE_KIND (r, VOIDmode);
174169689Skan
175169689Skan      gcc_assert (GET_CODE (r) == DEPS_LIST);
176169689Skan    }
177169689Skan  else
178169689Skan    r = gen_rtx_DEPS_LIST (VOIDmode, val, next, ds);
179169689Skan
180169689Skan  return r;
181169689Skan}
182169689Skan
18390075Sobrien/* This function will free up an entire list of EXPR_LIST nodes.  */
184117395Skanvoid
185132718Skanfree_EXPR_LIST_list (rtx *listp)
18690075Sobrien{
18790075Sobrien  if (*listp == 0)
18890075Sobrien    return;
18990075Sobrien  free_list (listp, &unused_expr_list);
19090075Sobrien}
19190075Sobrien
19290075Sobrien/* This function will free up an entire list of INSN_LIST nodes.  */
193117395Skanvoid
194132718Skanfree_INSN_LIST_list (rtx *listp)
19590075Sobrien{
19690075Sobrien  if (*listp == 0)
19790075Sobrien    return;
19890075Sobrien  free_list (listp, &unused_insn_list);
19990075Sobrien}
20090075Sobrien
201169689Skan/* This function will free up an entire list of DEPS_LIST nodes.  */
202169689Skanvoid
203169689Skanfree_DEPS_LIST_list (rtx *listp)
204169689Skan{
205169689Skan  if (*listp == 0)
206169689Skan    return;
207169689Skan  free_list (listp, &unused_deps_list);
208169689Skan}
209169689Skan
21090075Sobrien/* This function will free up an individual EXPR_LIST node.  */
211117395Skanvoid
212132718Skanfree_EXPR_LIST_node (rtx ptr)
21390075Sobrien{
21490075Sobrien  XEXP (ptr, 1) = unused_expr_list;
21590075Sobrien  unused_expr_list = ptr;
21690075Sobrien}
21790075Sobrien
21890075Sobrien/* This function will free up an individual INSN_LIST node.  */
219117395Skanvoid
220132718Skanfree_INSN_LIST_node (rtx ptr)
22190075Sobrien{
222169689Skan  gcc_assert (GET_CODE (ptr) == INSN_LIST);
22390075Sobrien  XEXP (ptr, 1) = unused_insn_list;
22490075Sobrien  unused_insn_list = ptr;
22590075Sobrien}
226117395Skan
227169689Skan/* This function will free up an individual DEPS_LIST node.  */
228169689Skanstatic void
229169689Skanfree_DEPS_LIST_node (rtx ptr)
230169689Skan{
231169689Skan  gcc_assert (GET_CODE (ptr) == DEPS_LIST);
232169689Skan  XEXP (ptr, 1) = unused_deps_list;
233169689Skan  unused_deps_list = ptr;
234169689Skan}
235169689Skan
236169689Skan/* Remove and free corresponding to ELEM node in the DEPS_LIST pointed to
237169689Skan   by LISTP.  */
238169689Skanvoid
239169689Skanremove_free_DEPS_LIST_elem (rtx elem, rtx *listp)
240169689Skan{
241169689Skan  free_DEPS_LIST_node (remove_list_elem (elem, listp));
242169689Skan}
243169689Skan
244169689Skan/* Remove and free corresponding to ELEM node in the INSN_LIST pointed to
245169689Skan   by LISTP.  */
246169689Skanvoid
247169689Skanremove_free_INSN_LIST_elem (rtx elem, rtx *listp)
248169689Skan{
249169689Skan  free_INSN_LIST_node (remove_list_elem (elem, listp));
250169689Skan}
251169689Skan
252169689Skan/* Create and return a copy of the DEPS_LIST LIST.  */
253169689Skanrtx
254169689Skancopy_DEPS_LIST_list (rtx list)
255169689Skan{
256169689Skan  rtx res = NULL_RTX, *resp = &res;
257169689Skan
258169689Skan  while (list)
259169689Skan    {
260169689Skan      *resp = alloc_DEPS_LIST (XEXP (list, 0), 0, XINT (list, 2));
261169689Skan      PUT_REG_NOTE_KIND (*resp, REG_NOTE_KIND (list));
262169689Skan      resp = &XEXP (*resp, 1);
263169689Skan      list = XEXP (list, 1);
264169689Skan    }
265169689Skan  return res;
266169689Skan}
267169689Skan
268117395Skan#include "gt-lists.h"
269