bd52d17906
too large to list, but see: http://gcc.gnu.org/gcc-3.4/changes.html http://gcc.gnu.org/gcc-4.0/changes.html http://gcc.gnu.org/gcc-4.1/changes.html for the details.
175 lines
4.8 KiB
C
175 lines
4.8 KiB
C
/* 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, 51 Franklin Street, Fifth Floor, Boston, MA
|
|
02110-1301, USA. */
|
|
|
|
|
|
/* This file contains common code which is used by each of the 5 operand
|
|
types. Macros are defined to specify the varying components.
|
|
|
|
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 retrieve an element.
|
|
FINALIZE_BASE - How to retrieve 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)
|
|
{
|
|
unsigned 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 = 0;
|
|
while (old_ops && new_i < VEC_length (tree, FINALIZE_OPBUILD))
|
|
{
|
|
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_CORRECT_USE
|
|
FINALIZE_CORRECT_USE (FINALIZE_USE_PTR (last), stmt);
|
|
#endif
|
|
old_ops = old_ops->next;
|
|
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++;
|
|
}
|
|
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 < VEC_length (tree, 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 == VEC_length (tree, 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
|
|
#undef FINALIZE_CORRECT_USE
|