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