diff options
Diffstat (limited to 'gcc/tree-ssa-opfinalize.h')
-rw-r--r-- | gcc/tree-ssa-opfinalize.h | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/gcc/tree-ssa-opfinalize.h b/gcc/tree-ssa-opfinalize.h new file mode 100644 index 00000000000..16850c06d49 --- /dev/null +++ b/gcc/tree-ssa-opfinalize.h @@ -0,0 +1,175 @@ +/* SSA operand allocation and finalizing. + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + + +/* This file contains common code which is used by each of the 5 operand + types. Macros are defined to specify the varying componenets. + + FINALIZE_FUNC - name of finalize function. + FINALIZE_ALLOC - name of allocation routine. + FINALIZE_FREE - name of free list. + FINALIZE_TYPE - type of node. + FINALIZE_OPS - Lead element in list. + FINALIZE_USE_PTR - How to get the use_operand_p, if this is a use operand. + FINALIZE_INITIALIZE - How to initialize an element. + FINALIZE_ELEM - How to retreive an element. + FINALIZE_BASE - How to retreive the base variable of an element. + FINALIZE_BASE_TYPE - Type of the base variable. + FINALIZE_OPBUILD - Opbuild array for these nodes. + FINALIZE_OPBUILD_ELEM - How to get an element from the opbuild list. + FINALIZE_OPBUILD_BASE - How to get an element base from the opbuild list. + FINALIZE_BASE_ZERO - How to zero an element. */ + + +/* This routine will either pick up a node from the free list, or allocate a + new one if need be. */ + +static inline FINALIZE_TYPE * +FINALIZE_ALLOC (void) +{ + FINALIZE_TYPE *ret; + if (FINALIZE_FREE) + { + ret = FINALIZE_FREE; + FINALIZE_FREE = FINALIZE_FREE->next; + } + else + ret = (FINALIZE_TYPE *)ssa_operand_alloc (sizeof (FINALIZE_TYPE)); + return ret; +} + + + +/* This routine will take the new operands from FINALIZE_OPBUILD and turn them + into the new operands for STMT. All required linking and deleting is u + performed here. */ +static inline void +FINALIZE_FUNC (tree stmt) +{ + int new_i; + FINALIZE_TYPE *old_ops, *ptr, *last; + FINALIZE_BASE_TYPE old_base; + FINALIZE_TYPE new_list; + + new_list.next = NULL; + last = &new_list; + + old_ops = FINALIZE_OPS (stmt); + if (old_ops) + old_base = FINALIZE_BASE (FINALIZE_ELEM (old_ops)); + else + old_base = FINALIZE_BASE_ZERO; + + new_i = opbuild_first (&FINALIZE_OPBUILD); + while (old_ops && new_i != OPBUILD_LAST) + { + FINALIZE_BASE_TYPE new_base = FINALIZE_OPBUILD_BASE (new_i); + if (old_base == new_base) + { + /* if variables are the same, reuse this node. */ + last->next = old_ops; + last = old_ops; +#ifdef FINALIZE_USE_PTR + correct_use_link (FINALIZE_USE_PTR (last), stmt); +#endif + old_ops = old_ops->next; + new_i = opbuild_next (&FINALIZE_OPBUILD, new_i); + } + else + if (old_base < new_base) + { + /* if old is less than new, old goes to the free list. */ +#ifdef FINALIZE_USE_PTR + use_operand_p use_p = FINALIZE_USE_PTR (old_ops); + delink_imm_use (use_p); +#endif + ptr = old_ops; + old_ops = old_ops->next; + ptr->next = FINALIZE_FREE; + FINALIZE_FREE = ptr; + } + else + { + /* This is a new operand. */ + ptr = FINALIZE_ALLOC (); + FINALIZE_INITIALIZE (ptr, FINALIZE_OPBUILD_ELEM (new_i), stmt); + last->next = ptr; + last = ptr; + new_i = opbuild_next (&FINALIZE_OPBUILD, new_i); + } + if (old_ops) + old_base = FINALIZE_BASE (FINALIZE_ELEM (old_ops)); + } + + /* If there is anything remaining in the opbuild list, simply emit them. */ + for ( ; + new_i != OPBUILD_LAST; + new_i = opbuild_next (&FINALIZE_OPBUILD, new_i)) + { + ptr = FINALIZE_ALLOC (); + FINALIZE_INITIALIZE (ptr, FINALIZE_OPBUILD_ELEM (new_i), stmt); + last->next = ptr; + last = ptr; + } + + last->next = NULL; + + /* If there is anything in the old list, free them. */ + if (old_ops) + { +#ifdef FINALIZE_USE_PTR + for (ptr = old_ops; ptr; ptr = ptr->next) + { + use_operand_p use_p = FINALIZE_USE_PTR (ptr); + delink_imm_use (use_p); + } +#endif + old_ops->next = FINALIZE_FREE; + FINALIZE_FREE = old_ops; + } + + /* NOw set the stmt's operands. */ + FINALIZE_OPS (stmt) = new_list.next; + +#ifdef ENABLE_CHECKING + { + unsigned x = 0; + for (ptr = FINALIZE_OPS (stmt); ptr; ptr = ptr->next) + x++; + + gcc_assert (x == opbuild_num_elems (&FINALIZE_OPBUILD)); + } +#endif +} + +#undef FINALIZE_FUNC +#undef FINALIZE_ALLOC +#undef FINALIZE_FREE +#undef FINALIZE_TYPE +#undef FINALIZE_OPS +#undef FINALIZE_USE_PTR +#undef FINALIZE_INITIALIZE +#undef FINALIZE_ELEM +#undef FINALIZE_BASE +#undef FINALIZE_BASE_TYPE +#undef FINALIZE_OPBUILD +#undef FINALIZE_OPBUILD_ELEM +#undef FINALIZE_OPBUILD_BASE +#undef FINALIZE_BASE_ZERO |