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