1/* SSA operand allocation and finalizing. 2 Copyright (C) 2005 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free 8Software Foundation; either version 2, or (at your option) any later 9version. 10 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or 13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14for more details. 15 16You should have received a copy of the GNU General Public License 17along with GCC; see the file COPYING. If not, write to the Free 18Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 1902110-1301, USA. */ 20 21 22/* This file contains common code which is used by each of the 5 operand 23 types. Macros are defined to specify the varying components. 24 25 FINALIZE_FUNC - name of finalize function. 26 FINALIZE_ALLOC - name of allocation routine. 27 FINALIZE_FREE - name of free list. 28 FINALIZE_TYPE - type of node. 29 FINALIZE_OPS - Lead element in list. 30 FINALIZE_USE_PTR - How to get the use_operand_p, if this is a use operand. 31 FINALIZE_INITIALIZE - How to initialize an element. 32 FINALIZE_ELEM - How to retrieve an element. 33 FINALIZE_BASE - How to retrieve the base variable of an element. 34 FINALIZE_BASE_TYPE - Type of the base variable. 35 FINALIZE_OPBUILD - Opbuild array for these nodes. 36 FINALIZE_OPBUILD_ELEM - How to get an element from the opbuild list. 37 FINALIZE_OPBUILD_BASE - How to get an element base from the opbuild list. 38 FINALIZE_BASE_ZERO - How to zero an element. */ 39 40 41/* This routine will either pick up a node from the free list, or allocate a 42 new one if need be. */ 43 44static inline FINALIZE_TYPE * 45FINALIZE_ALLOC (void) 46{ 47 FINALIZE_TYPE *ret; 48 if (FINALIZE_FREE) 49 { 50 ret = FINALIZE_FREE; 51 FINALIZE_FREE = FINALIZE_FREE->next; 52 } 53 else 54 ret = (FINALIZE_TYPE *)ssa_operand_alloc (sizeof (FINALIZE_TYPE)); 55 return ret; 56} 57 58 59 60/* This routine will take the new operands from FINALIZE_OPBUILD and turn them 61 into the new operands for STMT. All required linking and deleting is u 62 performed here. */ 63static inline void 64FINALIZE_FUNC (tree stmt) 65{ 66 unsigned new_i; 67 FINALIZE_TYPE *old_ops, *ptr, *last; 68 FINALIZE_BASE_TYPE old_base; 69 FINALIZE_TYPE new_list; 70 71 new_list.next = NULL; 72 last = &new_list; 73 74 old_ops = FINALIZE_OPS (stmt); 75 if (old_ops) 76 old_base = FINALIZE_BASE (FINALIZE_ELEM (old_ops)); 77 else 78 old_base = FINALIZE_BASE_ZERO; 79 80 new_i = 0; 81 while (old_ops && new_i < VEC_length (tree, FINALIZE_OPBUILD)) 82 { 83 FINALIZE_BASE_TYPE new_base = FINALIZE_OPBUILD_BASE (new_i); 84 if (old_base == new_base) 85 { 86 /* if variables are the same, reuse this node. */ 87 last->next = old_ops; 88 last = old_ops; 89#ifdef FINALIZE_CORRECT_USE 90 FINALIZE_CORRECT_USE (FINALIZE_USE_PTR (last), stmt); 91#endif 92 old_ops = old_ops->next; 93 new_i++; 94 } 95 else 96 if (old_base < new_base) 97 { 98 /* if old is less than new, old goes to the free list. */ 99#ifdef FINALIZE_USE_PTR 100 use_operand_p use_p = FINALIZE_USE_PTR (old_ops); 101 delink_imm_use (use_p); 102#endif 103 ptr = old_ops; 104 old_ops = old_ops->next; 105 ptr->next = FINALIZE_FREE; 106 FINALIZE_FREE = ptr; 107 } 108 else 109 { 110 /* This is a new operand. */ 111 ptr = FINALIZE_ALLOC (); 112 FINALIZE_INITIALIZE (ptr, FINALIZE_OPBUILD_ELEM (new_i), stmt); 113 last->next = ptr; 114 last = ptr; 115 new_i++; 116 } 117 if (old_ops) 118 old_base = FINALIZE_BASE (FINALIZE_ELEM (old_ops)); 119 } 120 121 /* If there is anything remaining in the opbuild list, simply emit them. */ 122 for ( ; new_i < VEC_length (tree, FINALIZE_OPBUILD); new_i++) 123 { 124 ptr = FINALIZE_ALLOC (); 125 FINALIZE_INITIALIZE (ptr, FINALIZE_OPBUILD_ELEM (new_i), stmt); 126 last->next = ptr; 127 last = ptr; 128 } 129 130 last->next = NULL; 131 132 /* If there is anything in the old list, free them. */ 133 if (old_ops) 134 { 135#ifdef FINALIZE_USE_PTR 136 for (ptr = old_ops; ptr; ptr = ptr->next) 137 { 138 use_operand_p use_p = FINALIZE_USE_PTR (ptr); 139 delink_imm_use (use_p); 140 } 141#endif 142 old_ops->next = FINALIZE_FREE; 143 FINALIZE_FREE = old_ops; 144 } 145 146 /* NOw set the stmt's operands. */ 147 FINALIZE_OPS (stmt) = new_list.next; 148 149#ifdef ENABLE_CHECKING 150 { 151 unsigned x = 0; 152 for (ptr = FINALIZE_OPS (stmt); ptr; ptr = ptr->next) 153 x++; 154 155 gcc_assert (x == VEC_length (tree, FINALIZE_OPBUILD)); 156 } 157#endif 158} 159 160#undef FINALIZE_FUNC 161#undef FINALIZE_ALLOC 162#undef FINALIZE_FREE 163#undef FINALIZE_TYPE 164#undef FINALIZE_OPS 165#undef FINALIZE_USE_PTR 166#undef FINALIZE_INITIALIZE 167#undef FINALIZE_ELEM 168#undef FINALIZE_BASE 169#undef FINALIZE_BASE_TYPE 170#undef FINALIZE_OPBUILD 171#undef FINALIZE_OPBUILD_ELEM 172#undef FINALIZE_OPBUILD_BASE 173#undef FINALIZE_BASE_ZERO 174#undef FINALIZE_CORRECT_USE 175