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 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 2, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING. If not, write to the Free 19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20 02110-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 30 static void free_list (rtx *, rtx *); 31 static 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. */ 36 static GTY ((deletable)) rtx unused_insn_list; 37 38 /* An EXPR_LIST containing all EXPR_LISTs allocated but currently unused. */ 39 static GTY ((deletable)) rtx unused_expr_list; 40 41 /* An DEPS_LIST containing all DEPS_LISTs allocated but currently unused. */ 42 static 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. */ 49 static void 50 free_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. */ 80 static rtx * 81 find_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. */ 89 static void 90 remove_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. */ 101 rtx 102 remove_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. */ 115 rtx 116 alloc_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. */ 139 rtx 140 alloc_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. */ 161 rtx 162 alloc_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. */ 184 void 185 free_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. */ 193 void 194 free_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. */ 202 void 203 free_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. */ 211 void 212 free_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. */ 219 void 220 free_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. */ 228 static void 229 free_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. */ 238 void 239 remove_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. */ 246 void 247 remove_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. */ 253 rtx 254 copy_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