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