1*e4b17023SJohn Marino /* IRA conflict builder.
2*e4b17023SJohn Marino    Copyright (C) 2006, 2007, 2008, 2009, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tm.h"
26*e4b17023SJohn Marino #include "regs.h"
27*e4b17023SJohn Marino #include "rtl.h"
28*e4b17023SJohn Marino #include "tm_p.h"
29*e4b17023SJohn Marino #include "target.h"
30*e4b17023SJohn Marino #include "flags.h"
31*e4b17023SJohn Marino #include "hard-reg-set.h"
32*e4b17023SJohn Marino #include "basic-block.h"
33*e4b17023SJohn Marino #include "insn-config.h"
34*e4b17023SJohn Marino #include "recog.h"
35*e4b17023SJohn Marino #include "diagnostic-core.h"
36*e4b17023SJohn Marino #include "params.h"
37*e4b17023SJohn Marino #include "df.h"
38*e4b17023SJohn Marino #include "sparseset.h"
39*e4b17023SJohn Marino #include "ira-int.h"
40*e4b17023SJohn Marino #include "addresses.h"
41*e4b17023SJohn Marino 
42*e4b17023SJohn Marino /* This file contains code responsible for allocno conflict creation,
43*e4b17023SJohn Marino    allocno copy creation and allocno info accumulation on upper level
44*e4b17023SJohn Marino    regions.  */
45*e4b17023SJohn Marino 
46*e4b17023SJohn Marino /* ira_allocnos_num array of arrays of bits, recording whether two
47*e4b17023SJohn Marino    allocno's conflict (can't go in the same hardware register).
48*e4b17023SJohn Marino 
49*e4b17023SJohn Marino    Some arrays will be used as conflict bit vector of the
50*e4b17023SJohn Marino    corresponding allocnos see function build_object_conflicts.  */
51*e4b17023SJohn Marino static IRA_INT_TYPE **conflicts;
52*e4b17023SJohn Marino 
53*e4b17023SJohn Marino /* Macro to test a conflict of C1 and C2 in `conflicts'.  */
54*e4b17023SJohn Marino #define OBJECTS_CONFLICT_P(C1, C2)					\
55*e4b17023SJohn Marino   (OBJECT_MIN (C1) <= OBJECT_CONFLICT_ID (C2)				\
56*e4b17023SJohn Marino    && OBJECT_CONFLICT_ID (C2) <= OBJECT_MAX (C1)			\
57*e4b17023SJohn Marino    && TEST_MINMAX_SET_BIT (conflicts[OBJECT_CONFLICT_ID (C1)],		\
58*e4b17023SJohn Marino 			   OBJECT_CONFLICT_ID (C2),			\
59*e4b17023SJohn Marino 			   OBJECT_MIN (C1), OBJECT_MAX (C1)))
60*e4b17023SJohn Marino 
61*e4b17023SJohn Marino 
62*e4b17023SJohn Marino /* Record a conflict between objects OBJ1 and OBJ2.  If necessary,
63*e4b17023SJohn Marino    canonicalize the conflict by recording it for lower-order subobjects
64*e4b17023SJohn Marino    of the corresponding allocnos. */
65*e4b17023SJohn Marino static void
record_object_conflict(ira_object_t obj1,ira_object_t obj2)66*e4b17023SJohn Marino record_object_conflict (ira_object_t obj1, ira_object_t obj2)
67*e4b17023SJohn Marino {
68*e4b17023SJohn Marino   ira_allocno_t a1 = OBJECT_ALLOCNO (obj1);
69*e4b17023SJohn Marino   ira_allocno_t a2 = OBJECT_ALLOCNO (obj2);
70*e4b17023SJohn Marino   int w1 = OBJECT_SUBWORD (obj1);
71*e4b17023SJohn Marino   int w2 = OBJECT_SUBWORD (obj2);
72*e4b17023SJohn Marino   int id1, id2;
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino   /* Canonicalize the conflict.  If two identically-numbered words
75*e4b17023SJohn Marino      conflict, always record this as a conflict between words 0.  That
76*e4b17023SJohn Marino      is the only information we need, and it is easier to test for if
77*e4b17023SJohn Marino      it is collected in each allocno's lowest-order object.  */
78*e4b17023SJohn Marino   if (w1 == w2 && w1 > 0)
79*e4b17023SJohn Marino     {
80*e4b17023SJohn Marino       obj1 = ALLOCNO_OBJECT (a1, 0);
81*e4b17023SJohn Marino       obj2 = ALLOCNO_OBJECT (a2, 0);
82*e4b17023SJohn Marino     }
83*e4b17023SJohn Marino   id1 = OBJECT_CONFLICT_ID (obj1);
84*e4b17023SJohn Marino   id2 = OBJECT_CONFLICT_ID (obj2);
85*e4b17023SJohn Marino 
86*e4b17023SJohn Marino   SET_MINMAX_SET_BIT (conflicts[id1], id2, OBJECT_MIN (obj1),
87*e4b17023SJohn Marino 		      OBJECT_MAX (obj1));
88*e4b17023SJohn Marino   SET_MINMAX_SET_BIT (conflicts[id2], id1, OBJECT_MIN (obj2),
89*e4b17023SJohn Marino 		      OBJECT_MAX (obj2));
90*e4b17023SJohn Marino }
91*e4b17023SJohn Marino 
92*e4b17023SJohn Marino /* Build allocno conflict table by processing allocno live ranges.
93*e4b17023SJohn Marino    Return true if the table was built.  The table is not built if it
94*e4b17023SJohn Marino    is too big.  */
95*e4b17023SJohn Marino static bool
build_conflict_bit_table(void)96*e4b17023SJohn Marino build_conflict_bit_table (void)
97*e4b17023SJohn Marino {
98*e4b17023SJohn Marino   int i;
99*e4b17023SJohn Marino   unsigned int j;
100*e4b17023SJohn Marino   enum reg_class aclass;
101*e4b17023SJohn Marino   int object_set_words, allocated_words_num, conflict_bit_vec_words_num;
102*e4b17023SJohn Marino   live_range_t r;
103*e4b17023SJohn Marino   ira_allocno_t allocno;
104*e4b17023SJohn Marino   ira_allocno_iterator ai;
105*e4b17023SJohn Marino   sparseset objects_live;
106*e4b17023SJohn Marino   ira_object_t obj;
107*e4b17023SJohn Marino   ira_allocno_object_iterator aoi;
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino   allocated_words_num = 0;
110*e4b17023SJohn Marino   FOR_EACH_ALLOCNO (allocno, ai)
111*e4b17023SJohn Marino     FOR_EACH_ALLOCNO_OBJECT (allocno, obj, aoi)
112*e4b17023SJohn Marino       {
113*e4b17023SJohn Marino 	if (OBJECT_MAX (obj) < OBJECT_MIN (obj))
114*e4b17023SJohn Marino 	  continue;
115*e4b17023SJohn Marino 	conflict_bit_vec_words_num
116*e4b17023SJohn Marino 	  = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS)
117*e4b17023SJohn Marino 	     / IRA_INT_BITS);
118*e4b17023SJohn Marino 	allocated_words_num += conflict_bit_vec_words_num;
119*e4b17023SJohn Marino 	if ((unsigned HOST_WIDEST_INT) allocated_words_num * sizeof (IRA_INT_TYPE)
120*e4b17023SJohn Marino 	    > (unsigned HOST_WIDEST_INT) IRA_MAX_CONFLICT_TABLE_SIZE * 1024 * 1024)
121*e4b17023SJohn Marino 	  {
122*e4b17023SJohn Marino 	    if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
123*e4b17023SJohn Marino 	      fprintf
124*e4b17023SJohn Marino 		(ira_dump_file,
125*e4b17023SJohn Marino 		 "+++Conflict table will be too big(>%dMB) -- don't use it\n",
126*e4b17023SJohn Marino 		 IRA_MAX_CONFLICT_TABLE_SIZE);
127*e4b17023SJohn Marino 	    return false;
128*e4b17023SJohn Marino 	  }
129*e4b17023SJohn Marino       }
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino   conflicts = (IRA_INT_TYPE **) ira_allocate (sizeof (IRA_INT_TYPE *)
132*e4b17023SJohn Marino 					      * ira_objects_num);
133*e4b17023SJohn Marino   allocated_words_num = 0;
134*e4b17023SJohn Marino   FOR_EACH_ALLOCNO (allocno, ai)
135*e4b17023SJohn Marino     FOR_EACH_ALLOCNO_OBJECT (allocno, obj, aoi)
136*e4b17023SJohn Marino       {
137*e4b17023SJohn Marino 	int id = OBJECT_CONFLICT_ID (obj);
138*e4b17023SJohn Marino 	if (OBJECT_MAX (obj) < OBJECT_MIN (obj))
139*e4b17023SJohn Marino 	  {
140*e4b17023SJohn Marino 	    conflicts[id] = NULL;
141*e4b17023SJohn Marino 	    continue;
142*e4b17023SJohn Marino 	  }
143*e4b17023SJohn Marino 	conflict_bit_vec_words_num
144*e4b17023SJohn Marino 	  = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS)
145*e4b17023SJohn Marino 	     / IRA_INT_BITS);
146*e4b17023SJohn Marino 	allocated_words_num += conflict_bit_vec_words_num;
147*e4b17023SJohn Marino 	conflicts[id]
148*e4b17023SJohn Marino 	  = (IRA_INT_TYPE *) ira_allocate (sizeof (IRA_INT_TYPE)
149*e4b17023SJohn Marino 					   * conflict_bit_vec_words_num);
150*e4b17023SJohn Marino 	memset (conflicts[id], 0,
151*e4b17023SJohn Marino 		sizeof (IRA_INT_TYPE) * conflict_bit_vec_words_num);
152*e4b17023SJohn Marino       }
153*e4b17023SJohn Marino 
154*e4b17023SJohn Marino   object_set_words = (ira_objects_num + IRA_INT_BITS - 1) / IRA_INT_BITS;
155*e4b17023SJohn Marino   if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
156*e4b17023SJohn Marino     fprintf
157*e4b17023SJohn Marino       (ira_dump_file,
158*e4b17023SJohn Marino        "+++Allocating %ld bytes for conflict table (uncompressed size %ld)\n",
159*e4b17023SJohn Marino        (long) allocated_words_num * sizeof (IRA_INT_TYPE),
160*e4b17023SJohn Marino        (long) object_set_words * ira_objects_num * sizeof (IRA_INT_TYPE));
161*e4b17023SJohn Marino 
162*e4b17023SJohn Marino   objects_live = sparseset_alloc (ira_objects_num);
163*e4b17023SJohn Marino   for (i = 0; i < ira_max_point; i++)
164*e4b17023SJohn Marino     {
165*e4b17023SJohn Marino       for (r = ira_start_point_ranges[i]; r != NULL; r = r->start_next)
166*e4b17023SJohn Marino 	{
167*e4b17023SJohn Marino 	  ira_object_t obj = r->object;
168*e4b17023SJohn Marino 	  ira_allocno_t allocno = OBJECT_ALLOCNO (obj);
169*e4b17023SJohn Marino 	  int id = OBJECT_CONFLICT_ID (obj);
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino 	  gcc_assert (id < ira_objects_num);
172*e4b17023SJohn Marino 
173*e4b17023SJohn Marino 	  aclass = ALLOCNO_CLASS (allocno);
174*e4b17023SJohn Marino 	  sparseset_set_bit (objects_live, id);
175*e4b17023SJohn Marino 	  EXECUTE_IF_SET_IN_SPARSESET (objects_live, j)
176*e4b17023SJohn Marino 	    {
177*e4b17023SJohn Marino 	      ira_object_t live_obj = ira_object_id_map[j];
178*e4b17023SJohn Marino 	      ira_allocno_t live_a = OBJECT_ALLOCNO (live_obj);
179*e4b17023SJohn Marino 	      enum reg_class live_aclass = ALLOCNO_CLASS (live_a);
180*e4b17023SJohn Marino 
181*e4b17023SJohn Marino 	      if (ira_reg_classes_intersect_p[aclass][live_aclass]
182*e4b17023SJohn Marino 		  /* Don't set up conflict for the allocno with itself.  */
183*e4b17023SJohn Marino 		  && live_a != allocno)
184*e4b17023SJohn Marino 		{
185*e4b17023SJohn Marino 		  record_object_conflict (obj, live_obj);
186*e4b17023SJohn Marino 		}
187*e4b17023SJohn Marino 	    }
188*e4b17023SJohn Marino 	}
189*e4b17023SJohn Marino 
190*e4b17023SJohn Marino       for (r = ira_finish_point_ranges[i]; r != NULL; r = r->finish_next)
191*e4b17023SJohn Marino 	sparseset_clear_bit (objects_live, OBJECT_CONFLICT_ID (r->object));
192*e4b17023SJohn Marino     }
193*e4b17023SJohn Marino   sparseset_free (objects_live);
194*e4b17023SJohn Marino   return true;
195*e4b17023SJohn Marino }
196*e4b17023SJohn Marino 
197*e4b17023SJohn Marino /* Return true iff allocnos A1 and A2 cannot be allocated to the same
198*e4b17023SJohn Marino    register due to conflicts.  */
199*e4b17023SJohn Marino 
200*e4b17023SJohn Marino static bool
allocnos_conflict_for_copy_p(ira_allocno_t a1,ira_allocno_t a2)201*e4b17023SJohn Marino allocnos_conflict_for_copy_p (ira_allocno_t a1, ira_allocno_t a2)
202*e4b17023SJohn Marino {
203*e4b17023SJohn Marino   /* Due to the fact that we canonicalize conflicts (see
204*e4b17023SJohn Marino      record_object_conflict), we only need to test for conflicts of
205*e4b17023SJohn Marino      the lowest order words.  */
206*e4b17023SJohn Marino   ira_object_t obj1 = ALLOCNO_OBJECT (a1, 0);
207*e4b17023SJohn Marino   ira_object_t obj2 = ALLOCNO_OBJECT (a2, 0);
208*e4b17023SJohn Marino 
209*e4b17023SJohn Marino   return OBJECTS_CONFLICT_P (obj1, obj2);
210*e4b17023SJohn Marino }
211*e4b17023SJohn Marino 
212*e4b17023SJohn Marino /* Return TRUE if the operand constraint STR is commutative.  */
213*e4b17023SJohn Marino static bool
commutative_constraint_p(const char * str)214*e4b17023SJohn Marino commutative_constraint_p (const char *str)
215*e4b17023SJohn Marino {
216*e4b17023SJohn Marino   int curr_alt, c;
217*e4b17023SJohn Marino   bool ignore_p;
218*e4b17023SJohn Marino 
219*e4b17023SJohn Marino   for (ignore_p = false, curr_alt = 0;;)
220*e4b17023SJohn Marino     {
221*e4b17023SJohn Marino       c = *str;
222*e4b17023SJohn Marino       if (c == '\0')
223*e4b17023SJohn Marino 	break;
224*e4b17023SJohn Marino       str += CONSTRAINT_LEN (c, str);
225*e4b17023SJohn Marino       if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
226*e4b17023SJohn Marino 	ignore_p = true;
227*e4b17023SJohn Marino       else if (c == ',')
228*e4b17023SJohn Marino 	{
229*e4b17023SJohn Marino 	  curr_alt++;
230*e4b17023SJohn Marino 	  ignore_p = false;
231*e4b17023SJohn Marino 	}
232*e4b17023SJohn Marino       else if (! ignore_p)
233*e4b17023SJohn Marino 	{
234*e4b17023SJohn Marino 	  /* Usually `%' is the first constraint character but the
235*e4b17023SJohn Marino 	     documentation does not require this.  */
236*e4b17023SJohn Marino 	  if (c == '%')
237*e4b17023SJohn Marino 	    return true;
238*e4b17023SJohn Marino 	}
239*e4b17023SJohn Marino     }
240*e4b17023SJohn Marino   return false;
241*e4b17023SJohn Marino }
242*e4b17023SJohn Marino 
243*e4b17023SJohn Marino /* Return the number of the operand which should be the same in any
244*e4b17023SJohn Marino    case as operand with number OP_NUM (or negative value if there is
245*e4b17023SJohn Marino    no such operand).  If USE_COMMUT_OP_P is TRUE, the function makes
246*e4b17023SJohn Marino    temporarily commutative operand exchange before this.  The function
247*e4b17023SJohn Marino    takes only really possible alternatives into consideration.  */
248*e4b17023SJohn Marino static int
get_dup_num(int op_num,bool use_commut_op_p)249*e4b17023SJohn Marino get_dup_num (int op_num, bool use_commut_op_p)
250*e4b17023SJohn Marino {
251*e4b17023SJohn Marino   int curr_alt, c, original, dup;
252*e4b17023SJohn Marino   bool ignore_p, commut_op_used_p;
253*e4b17023SJohn Marino   const char *str;
254*e4b17023SJohn Marino   rtx op;
255*e4b17023SJohn Marino 
256*e4b17023SJohn Marino   if (op_num < 0 || recog_data.n_alternatives == 0)
257*e4b17023SJohn Marino     return -1;
258*e4b17023SJohn Marino   op = recog_data.operand[op_num];
259*e4b17023SJohn Marino   commut_op_used_p = true;
260*e4b17023SJohn Marino   if (use_commut_op_p)
261*e4b17023SJohn Marino     {
262*e4b17023SJohn Marino       if (commutative_constraint_p (recog_data.constraints[op_num]))
263*e4b17023SJohn Marino 	op_num++;
264*e4b17023SJohn Marino       else if (op_num > 0 && commutative_constraint_p (recog_data.constraints
265*e4b17023SJohn Marino 						       [op_num - 1]))
266*e4b17023SJohn Marino 	op_num--;
267*e4b17023SJohn Marino       else
268*e4b17023SJohn Marino 	commut_op_used_p = false;
269*e4b17023SJohn Marino     }
270*e4b17023SJohn Marino   str = recog_data.constraints[op_num];
271*e4b17023SJohn Marino   for (ignore_p = false, original = -1, curr_alt = 0;;)
272*e4b17023SJohn Marino     {
273*e4b17023SJohn Marino       c = *str;
274*e4b17023SJohn Marino       if (c == '\0')
275*e4b17023SJohn Marino 	break;
276*e4b17023SJohn Marino       if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
277*e4b17023SJohn Marino 	ignore_p = true;
278*e4b17023SJohn Marino       else if (c == ',')
279*e4b17023SJohn Marino 	{
280*e4b17023SJohn Marino 	  curr_alt++;
281*e4b17023SJohn Marino 	  ignore_p = false;
282*e4b17023SJohn Marino 	}
283*e4b17023SJohn Marino       else if (! ignore_p)
284*e4b17023SJohn Marino 	switch (c)
285*e4b17023SJohn Marino 	  {
286*e4b17023SJohn Marino 	  case 'X':
287*e4b17023SJohn Marino 	    return -1;
288*e4b17023SJohn Marino 
289*e4b17023SJohn Marino 	  case 'm':
290*e4b17023SJohn Marino 	  case 'o':
291*e4b17023SJohn Marino 	    /* Accept a register which might be placed in memory.  */
292*e4b17023SJohn Marino 	    return -1;
293*e4b17023SJohn Marino 	    break;
294*e4b17023SJohn Marino 
295*e4b17023SJohn Marino 	  case 'V':
296*e4b17023SJohn Marino 	  case '<':
297*e4b17023SJohn Marino 	  case '>':
298*e4b17023SJohn Marino 	    break;
299*e4b17023SJohn Marino 
300*e4b17023SJohn Marino 	  case 'p':
301*e4b17023SJohn Marino 	    if (address_operand (op, VOIDmode))
302*e4b17023SJohn Marino 	      return -1;
303*e4b17023SJohn Marino 	    break;
304*e4b17023SJohn Marino 
305*e4b17023SJohn Marino 	  case 'g':
306*e4b17023SJohn Marino 	    return -1;
307*e4b17023SJohn Marino 
308*e4b17023SJohn Marino 	  case 'r':
309*e4b17023SJohn Marino 	  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
310*e4b17023SJohn Marino 	  case 'h': case 'j': case 'k': case 'l':
311*e4b17023SJohn Marino 	  case 'q': case 't': case 'u':
312*e4b17023SJohn Marino 	  case 'v': case 'w': case 'x': case 'y': case 'z':
313*e4b17023SJohn Marino 	  case 'A': case 'B': case 'C': case 'D':
314*e4b17023SJohn Marino 	  case 'Q': case 'R': case 'S': case 'T': case 'U':
315*e4b17023SJohn Marino 	  case 'W': case 'Y': case 'Z':
316*e4b17023SJohn Marino 	    {
317*e4b17023SJohn Marino 	      enum reg_class cl;
318*e4b17023SJohn Marino 
319*e4b17023SJohn Marino 	      cl = (c == 'r'
320*e4b17023SJohn Marino 		    ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, str));
321*e4b17023SJohn Marino 	      if (cl != NO_REGS)
322*e4b17023SJohn Marino 		return -1;
323*e4b17023SJohn Marino #ifdef EXTRA_CONSTRAINT_STR
324*e4b17023SJohn Marino 	      else if (EXTRA_CONSTRAINT_STR (op, c, str))
325*e4b17023SJohn Marino 		return -1;
326*e4b17023SJohn Marino #endif
327*e4b17023SJohn Marino 	      break;
328*e4b17023SJohn Marino 	    }
329*e4b17023SJohn Marino 
330*e4b17023SJohn Marino 	  case '0': case '1': case '2': case '3': case '4':
331*e4b17023SJohn Marino 	  case '5': case '6': case '7': case '8': case '9':
332*e4b17023SJohn Marino 	    if (original != -1 && original != c)
333*e4b17023SJohn Marino 	      return -1;
334*e4b17023SJohn Marino 	    original = c;
335*e4b17023SJohn Marino 	    break;
336*e4b17023SJohn Marino 	  }
337*e4b17023SJohn Marino       str += CONSTRAINT_LEN (c, str);
338*e4b17023SJohn Marino     }
339*e4b17023SJohn Marino   if (original == -1)
340*e4b17023SJohn Marino     return -1;
341*e4b17023SJohn Marino   dup = original - '0';
342*e4b17023SJohn Marino   if (use_commut_op_p)
343*e4b17023SJohn Marino     {
344*e4b17023SJohn Marino       if (commutative_constraint_p (recog_data.constraints[dup]))
345*e4b17023SJohn Marino 	dup++;
346*e4b17023SJohn Marino       else if (dup > 0
347*e4b17023SJohn Marino 	       && commutative_constraint_p (recog_data.constraints[dup -1]))
348*e4b17023SJohn Marino 	dup--;
349*e4b17023SJohn Marino       else if (! commut_op_used_p)
350*e4b17023SJohn Marino 	return -1;
351*e4b17023SJohn Marino     }
352*e4b17023SJohn Marino   return dup;
353*e4b17023SJohn Marino }
354*e4b17023SJohn Marino 
355*e4b17023SJohn Marino /* Check that X is REG or SUBREG of REG.  */
356*e4b17023SJohn Marino #define REG_SUBREG_P(x)							\
357*e4b17023SJohn Marino    (REG_P (x) || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))))
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino /* Return X if X is a REG, otherwise it should be SUBREG of REG and
360*e4b17023SJohn Marino    the function returns the reg in this case.  *OFFSET will be set to
361*e4b17023SJohn Marino    0 in the first case or the regno offset in the first case.  */
362*e4b17023SJohn Marino static rtx
go_through_subreg(rtx x,int * offset)363*e4b17023SJohn Marino go_through_subreg (rtx x, int *offset)
364*e4b17023SJohn Marino {
365*e4b17023SJohn Marino   rtx reg;
366*e4b17023SJohn Marino 
367*e4b17023SJohn Marino   *offset = 0;
368*e4b17023SJohn Marino   if (REG_P (x))
369*e4b17023SJohn Marino     return x;
370*e4b17023SJohn Marino   ira_assert (GET_CODE (x) == SUBREG);
371*e4b17023SJohn Marino   reg = SUBREG_REG (x);
372*e4b17023SJohn Marino   ira_assert (REG_P (reg));
373*e4b17023SJohn Marino   if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
374*e4b17023SJohn Marino     *offset = subreg_regno_offset (REGNO (reg), GET_MODE (reg),
375*e4b17023SJohn Marino 				   SUBREG_BYTE (x), GET_MODE (x));
376*e4b17023SJohn Marino   else
377*e4b17023SJohn Marino     *offset = (SUBREG_BYTE (x) / REGMODE_NATURAL_SIZE (GET_MODE (x)));
378*e4b17023SJohn Marino   return reg;
379*e4b17023SJohn Marino }
380*e4b17023SJohn Marino 
381*e4b17023SJohn Marino /* Process registers REG1 and REG2 in move INSN with execution
382*e4b17023SJohn Marino    frequency FREQ.  The function also processes the registers in a
383*e4b17023SJohn Marino    potential move insn (INSN == NULL in this case) with frequency
384*e4b17023SJohn Marino    FREQ.  The function can modify hard register costs of the
385*e4b17023SJohn Marino    corresponding allocnos or create a copy involving the corresponding
386*e4b17023SJohn Marino    allocnos.  The function does nothing if the both registers are hard
387*e4b17023SJohn Marino    registers.  When nothing is changed, the function returns
388*e4b17023SJohn Marino    FALSE.  */
389*e4b17023SJohn Marino static bool
process_regs_for_copy(rtx reg1,rtx reg2,bool constraint_p,rtx insn,int freq)390*e4b17023SJohn Marino process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p,
391*e4b17023SJohn Marino 		       rtx insn, int freq)
392*e4b17023SJohn Marino {
393*e4b17023SJohn Marino   int allocno_preferenced_hard_regno, cost, index, offset1, offset2;
394*e4b17023SJohn Marino   bool only_regs_p;
395*e4b17023SJohn Marino   ira_allocno_t a;
396*e4b17023SJohn Marino   reg_class_t rclass, aclass;
397*e4b17023SJohn Marino   enum machine_mode mode;
398*e4b17023SJohn Marino   ira_copy_t cp;
399*e4b17023SJohn Marino 
400*e4b17023SJohn Marino   gcc_assert (REG_SUBREG_P (reg1) && REG_SUBREG_P (reg2));
401*e4b17023SJohn Marino   only_regs_p = REG_P (reg1) && REG_P (reg2);
402*e4b17023SJohn Marino   reg1 = go_through_subreg (reg1, &offset1);
403*e4b17023SJohn Marino   reg2 = go_through_subreg (reg2, &offset2);
404*e4b17023SJohn Marino   /* Set up hard regno preferenced by allocno.  If allocno gets the
405*e4b17023SJohn Marino      hard regno the copy (or potential move) insn will be removed.  */
406*e4b17023SJohn Marino   if (HARD_REGISTER_P (reg1))
407*e4b17023SJohn Marino     {
408*e4b17023SJohn Marino       if (HARD_REGISTER_P (reg2))
409*e4b17023SJohn Marino 	return false;
410*e4b17023SJohn Marino       allocno_preferenced_hard_regno = REGNO (reg1) + offset1 - offset2;
411*e4b17023SJohn Marino       a = ira_curr_regno_allocno_map[REGNO (reg2)];
412*e4b17023SJohn Marino     }
413*e4b17023SJohn Marino   else if (HARD_REGISTER_P (reg2))
414*e4b17023SJohn Marino     {
415*e4b17023SJohn Marino       allocno_preferenced_hard_regno = REGNO (reg2) + offset2 - offset1;
416*e4b17023SJohn Marino       a = ira_curr_regno_allocno_map[REGNO (reg1)];
417*e4b17023SJohn Marino     }
418*e4b17023SJohn Marino   else
419*e4b17023SJohn Marino     {
420*e4b17023SJohn Marino       ira_allocno_t a1 = ira_curr_regno_allocno_map[REGNO (reg1)];
421*e4b17023SJohn Marino       ira_allocno_t a2 = ira_curr_regno_allocno_map[REGNO (reg2)];
422*e4b17023SJohn Marino 
423*e4b17023SJohn Marino       if (!allocnos_conflict_for_copy_p (a1, a2) && offset1 == offset2)
424*e4b17023SJohn Marino 	{
425*e4b17023SJohn Marino 	  cp = ira_add_allocno_copy (a1, a2, freq, constraint_p, insn,
426*e4b17023SJohn Marino 				     ira_curr_loop_tree_node);
427*e4b17023SJohn Marino 	  bitmap_set_bit (ira_curr_loop_tree_node->local_copies, cp->num);
428*e4b17023SJohn Marino 	  return true;
429*e4b17023SJohn Marino 	}
430*e4b17023SJohn Marino       else
431*e4b17023SJohn Marino 	return false;
432*e4b17023SJohn Marino     }
433*e4b17023SJohn Marino 
434*e4b17023SJohn Marino   if (! IN_RANGE (allocno_preferenced_hard_regno,
435*e4b17023SJohn Marino 		  0, FIRST_PSEUDO_REGISTER - 1))
436*e4b17023SJohn Marino     /* Can not be tied.  */
437*e4b17023SJohn Marino     return false;
438*e4b17023SJohn Marino   rclass = REGNO_REG_CLASS (allocno_preferenced_hard_regno);
439*e4b17023SJohn Marino   mode = ALLOCNO_MODE (a);
440*e4b17023SJohn Marino   aclass = ALLOCNO_CLASS (a);
441*e4b17023SJohn Marino   if (only_regs_p && insn != NULL_RTX
442*e4b17023SJohn Marino       && reg_class_size[rclass] <= ira_reg_class_max_nregs [rclass][mode])
443*e4b17023SJohn Marino     /* It is already taken into account in ira-costs.c.  */
444*e4b17023SJohn Marino     return false;
445*e4b17023SJohn Marino   index = ira_class_hard_reg_index[aclass][allocno_preferenced_hard_regno];
446*e4b17023SJohn Marino   if (index < 0)
447*e4b17023SJohn Marino     /* Can not be tied.  It is not in the allocno class.  */
448*e4b17023SJohn Marino     return false;
449*e4b17023SJohn Marino   ira_init_register_move_cost_if_necessary (mode);
450*e4b17023SJohn Marino   if (HARD_REGISTER_P (reg1))
451*e4b17023SJohn Marino     cost = ira_register_move_cost[mode][aclass][rclass] * freq;
452*e4b17023SJohn Marino   else
453*e4b17023SJohn Marino     cost = ira_register_move_cost[mode][rclass][aclass] * freq;
454*e4b17023SJohn Marino   do
455*e4b17023SJohn Marino     {
456*e4b17023SJohn Marino       ira_allocate_and_set_costs
457*e4b17023SJohn Marino 	(&ALLOCNO_HARD_REG_COSTS (a), aclass,
458*e4b17023SJohn Marino 	 ALLOCNO_CLASS_COST (a));
459*e4b17023SJohn Marino       ira_allocate_and_set_costs
460*e4b17023SJohn Marino 	(&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), aclass, 0);
461*e4b17023SJohn Marino       ALLOCNO_HARD_REG_COSTS (a)[index] -= cost;
462*e4b17023SJohn Marino       ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost;
463*e4b17023SJohn Marino       if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a))
464*e4b17023SJohn Marino 	ALLOCNO_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index];
465*e4b17023SJohn Marino       a = ira_parent_or_cap_allocno (a);
466*e4b17023SJohn Marino     }
467*e4b17023SJohn Marino   while (a != NULL);
468*e4b17023SJohn Marino   return true;
469*e4b17023SJohn Marino }
470*e4b17023SJohn Marino 
471*e4b17023SJohn Marino /* Process all of the output registers of the current insn which are
472*e4b17023SJohn Marino    not bound (BOUND_P) and the input register REG (its operand number
473*e4b17023SJohn Marino    OP_NUM) which dies in the insn as if there were a move insn between
474*e4b17023SJohn Marino    them with frequency FREQ.  */
475*e4b17023SJohn Marino static void
process_reg_shuffles(rtx reg,int op_num,int freq,bool * bound_p)476*e4b17023SJohn Marino process_reg_shuffles (rtx reg, int op_num, int freq, bool *bound_p)
477*e4b17023SJohn Marino {
478*e4b17023SJohn Marino   int i;
479*e4b17023SJohn Marino   rtx another_reg;
480*e4b17023SJohn Marino 
481*e4b17023SJohn Marino   gcc_assert (REG_SUBREG_P (reg));
482*e4b17023SJohn Marino   for (i = 0; i < recog_data.n_operands; i++)
483*e4b17023SJohn Marino     {
484*e4b17023SJohn Marino       another_reg = recog_data.operand[i];
485*e4b17023SJohn Marino 
486*e4b17023SJohn Marino       if (!REG_SUBREG_P (another_reg) || op_num == i
487*e4b17023SJohn Marino 	  || recog_data.operand_type[i] != OP_OUT
488*e4b17023SJohn Marino 	  || bound_p[i])
489*e4b17023SJohn Marino 	continue;
490*e4b17023SJohn Marino 
491*e4b17023SJohn Marino       process_regs_for_copy (reg, another_reg, false, NULL_RTX, freq);
492*e4b17023SJohn Marino     }
493*e4b17023SJohn Marino }
494*e4b17023SJohn Marino 
495*e4b17023SJohn Marino /* Process INSN and create allocno copies if necessary.  For example,
496*e4b17023SJohn Marino    it might be because INSN is a pseudo-register move or INSN is two
497*e4b17023SJohn Marino    operand insn.  */
498*e4b17023SJohn Marino static void
add_insn_allocno_copies(rtx insn)499*e4b17023SJohn Marino add_insn_allocno_copies (rtx insn)
500*e4b17023SJohn Marino {
501*e4b17023SJohn Marino   rtx set, operand, dup;
502*e4b17023SJohn Marino   const char *str;
503*e4b17023SJohn Marino   bool commut_p, bound_p[MAX_RECOG_OPERANDS];
504*e4b17023SJohn Marino   int i, j, n, freq;
505*e4b17023SJohn Marino 
506*e4b17023SJohn Marino   freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
507*e4b17023SJohn Marino   if (freq == 0)
508*e4b17023SJohn Marino     freq = 1;
509*e4b17023SJohn Marino   if ((set = single_set (insn)) != NULL_RTX
510*e4b17023SJohn Marino       && REG_SUBREG_P (SET_DEST (set)) && REG_SUBREG_P (SET_SRC (set))
511*e4b17023SJohn Marino       && ! side_effects_p (set)
512*e4b17023SJohn Marino       && find_reg_note (insn, REG_DEAD,
513*e4b17023SJohn Marino 			REG_P (SET_SRC (set))
514*e4b17023SJohn Marino 			? SET_SRC (set)
515*e4b17023SJohn Marino 			: SUBREG_REG (SET_SRC (set))) != NULL_RTX)
516*e4b17023SJohn Marino     {
517*e4b17023SJohn Marino       process_regs_for_copy (SET_DEST (set), SET_SRC (set),
518*e4b17023SJohn Marino 			     false, insn, freq);
519*e4b17023SJohn Marino       return;
520*e4b17023SJohn Marino     }
521*e4b17023SJohn Marino   /* Fast check of possibility of constraint or shuffle copies.  If
522*e4b17023SJohn Marino      there are no dead registers, there will be no such copies.  */
523*e4b17023SJohn Marino   if (! find_reg_note (insn, REG_DEAD, NULL_RTX))
524*e4b17023SJohn Marino     return;
525*e4b17023SJohn Marino   extract_insn (insn);
526*e4b17023SJohn Marino   for (i = 0; i < recog_data.n_operands; i++)
527*e4b17023SJohn Marino     bound_p[i] = false;
528*e4b17023SJohn Marino   for (i = 0; i < recog_data.n_operands; i++)
529*e4b17023SJohn Marino     {
530*e4b17023SJohn Marino       operand = recog_data.operand[i];
531*e4b17023SJohn Marino       if (! REG_SUBREG_P (operand))
532*e4b17023SJohn Marino 	continue;
533*e4b17023SJohn Marino       str = recog_data.constraints[i];
534*e4b17023SJohn Marino       while (*str == ' ' || *str == '\t')
535*e4b17023SJohn Marino 	str++;
536*e4b17023SJohn Marino       for (j = 0, commut_p = false; j < 2; j++, commut_p = true)
537*e4b17023SJohn Marino 	if ((n = get_dup_num (i, commut_p)) >= 0)
538*e4b17023SJohn Marino 	  {
539*e4b17023SJohn Marino 	    bound_p[n] = true;
540*e4b17023SJohn Marino 	    dup = recog_data.operand[n];
541*e4b17023SJohn Marino 	    if (REG_SUBREG_P (dup)
542*e4b17023SJohn Marino 		&& find_reg_note (insn, REG_DEAD,
543*e4b17023SJohn Marino 				  REG_P (operand)
544*e4b17023SJohn Marino 				  ? operand
545*e4b17023SJohn Marino 				  : SUBREG_REG (operand)) != NULL_RTX)
546*e4b17023SJohn Marino 	      process_regs_for_copy (operand, dup, true, NULL_RTX, freq);
547*e4b17023SJohn Marino 	  }
548*e4b17023SJohn Marino     }
549*e4b17023SJohn Marino   for (i = 0; i < recog_data.n_operands; i++)
550*e4b17023SJohn Marino     {
551*e4b17023SJohn Marino       operand = recog_data.operand[i];
552*e4b17023SJohn Marino       if (REG_SUBREG_P (operand)
553*e4b17023SJohn Marino 	  && find_reg_note (insn, REG_DEAD,
554*e4b17023SJohn Marino 			    REG_P (operand)
555*e4b17023SJohn Marino 			    ? operand : SUBREG_REG (operand)) != NULL_RTX)
556*e4b17023SJohn Marino 	/* If an operand dies, prefer its hard register for the output
557*e4b17023SJohn Marino 	   operands by decreasing the hard register cost or creating
558*e4b17023SJohn Marino 	   the corresponding allocno copies.  The cost will not
559*e4b17023SJohn Marino 	   correspond to a real move insn cost, so make the frequency
560*e4b17023SJohn Marino 	   smaller.  */
561*e4b17023SJohn Marino 	process_reg_shuffles (operand, i, freq < 8 ? 1 : freq / 8, bound_p);
562*e4b17023SJohn Marino     }
563*e4b17023SJohn Marino }
564*e4b17023SJohn Marino 
565*e4b17023SJohn Marino /* Add copies originated from BB given by LOOP_TREE_NODE.  */
566*e4b17023SJohn Marino static void
add_copies(ira_loop_tree_node_t loop_tree_node)567*e4b17023SJohn Marino add_copies (ira_loop_tree_node_t loop_tree_node)
568*e4b17023SJohn Marino {
569*e4b17023SJohn Marino   basic_block bb;
570*e4b17023SJohn Marino   rtx insn;
571*e4b17023SJohn Marino 
572*e4b17023SJohn Marino   bb = loop_tree_node->bb;
573*e4b17023SJohn Marino   if (bb == NULL)
574*e4b17023SJohn Marino     return;
575*e4b17023SJohn Marino   FOR_BB_INSNS (bb, insn)
576*e4b17023SJohn Marino     if (NONDEBUG_INSN_P (insn))
577*e4b17023SJohn Marino       add_insn_allocno_copies (insn);
578*e4b17023SJohn Marino }
579*e4b17023SJohn Marino 
580*e4b17023SJohn Marino /* Propagate copies the corresponding allocnos on upper loop tree
581*e4b17023SJohn Marino    level.  */
582*e4b17023SJohn Marino static void
propagate_copies(void)583*e4b17023SJohn Marino propagate_copies (void)
584*e4b17023SJohn Marino {
585*e4b17023SJohn Marino   ira_copy_t cp;
586*e4b17023SJohn Marino   ira_copy_iterator ci;
587*e4b17023SJohn Marino   ira_allocno_t a1, a2, parent_a1, parent_a2;
588*e4b17023SJohn Marino 
589*e4b17023SJohn Marino   FOR_EACH_COPY (cp, ci)
590*e4b17023SJohn Marino     {
591*e4b17023SJohn Marino       a1 = cp->first;
592*e4b17023SJohn Marino       a2 = cp->second;
593*e4b17023SJohn Marino       if (ALLOCNO_LOOP_TREE_NODE (a1) == ira_loop_tree_root)
594*e4b17023SJohn Marino 	continue;
595*e4b17023SJohn Marino       ira_assert ((ALLOCNO_LOOP_TREE_NODE (a2) != ira_loop_tree_root));
596*e4b17023SJohn Marino       parent_a1 = ira_parent_or_cap_allocno (a1);
597*e4b17023SJohn Marino       parent_a2 = ira_parent_or_cap_allocno (a2);
598*e4b17023SJohn Marino       ira_assert (parent_a1 != NULL && parent_a2 != NULL);
599*e4b17023SJohn Marino       if (! allocnos_conflict_for_copy_p (parent_a1, parent_a2))
600*e4b17023SJohn Marino 	ira_add_allocno_copy (parent_a1, parent_a2, cp->freq,
601*e4b17023SJohn Marino 			      cp->constraint_p, cp->insn, cp->loop_tree_node);
602*e4b17023SJohn Marino     }
603*e4b17023SJohn Marino }
604*e4b17023SJohn Marino 
605*e4b17023SJohn Marino /* Array used to collect all conflict allocnos for given allocno.  */
606*e4b17023SJohn Marino static ira_object_t *collected_conflict_objects;
607*e4b17023SJohn Marino 
608*e4b17023SJohn Marino /* Build conflict vectors or bit conflict vectors (whatever is more
609*e4b17023SJohn Marino    profitable) for object OBJ from the conflict table.  */
610*e4b17023SJohn Marino static void
build_object_conflicts(ira_object_t obj)611*e4b17023SJohn Marino build_object_conflicts (ira_object_t obj)
612*e4b17023SJohn Marino {
613*e4b17023SJohn Marino   int i, px, parent_num;
614*e4b17023SJohn Marino   ira_allocno_t parent_a, another_parent_a;
615*e4b17023SJohn Marino   ira_object_t parent_obj;
616*e4b17023SJohn Marino   ira_allocno_t a = OBJECT_ALLOCNO (obj);
617*e4b17023SJohn Marino   IRA_INT_TYPE *object_conflicts;
618*e4b17023SJohn Marino   minmax_set_iterator asi;
619*e4b17023SJohn Marino   int parent_min, parent_max ATTRIBUTE_UNUSED;
620*e4b17023SJohn Marino 
621*e4b17023SJohn Marino   object_conflicts = conflicts[OBJECT_CONFLICT_ID (obj)];
622*e4b17023SJohn Marino   px = 0;
623*e4b17023SJohn Marino   FOR_EACH_BIT_IN_MINMAX_SET (object_conflicts,
624*e4b17023SJohn Marino 			      OBJECT_MIN (obj), OBJECT_MAX (obj), i, asi)
625*e4b17023SJohn Marino     {
626*e4b17023SJohn Marino       ira_object_t another_obj = ira_object_id_map[i];
627*e4b17023SJohn Marino       ira_allocno_t another_a = OBJECT_ALLOCNO (obj);
628*e4b17023SJohn Marino 
629*e4b17023SJohn Marino       ira_assert (ira_reg_classes_intersect_p
630*e4b17023SJohn Marino 		  [ALLOCNO_CLASS (a)][ALLOCNO_CLASS (another_a)]);
631*e4b17023SJohn Marino       collected_conflict_objects[px++] = another_obj;
632*e4b17023SJohn Marino     }
633*e4b17023SJohn Marino   if (ira_conflict_vector_profitable_p (obj, px))
634*e4b17023SJohn Marino     {
635*e4b17023SJohn Marino       ira_object_t *vec;
636*e4b17023SJohn Marino       ira_allocate_conflict_vec (obj, px);
637*e4b17023SJohn Marino       vec = OBJECT_CONFLICT_VEC (obj);
638*e4b17023SJohn Marino       memcpy (vec, collected_conflict_objects, sizeof (ira_object_t) * px);
639*e4b17023SJohn Marino       vec[px] = NULL;
640*e4b17023SJohn Marino       OBJECT_NUM_CONFLICTS (obj) = px;
641*e4b17023SJohn Marino     }
642*e4b17023SJohn Marino   else
643*e4b17023SJohn Marino     {
644*e4b17023SJohn Marino       int conflict_bit_vec_words_num;
645*e4b17023SJohn Marino 
646*e4b17023SJohn Marino       OBJECT_CONFLICT_ARRAY (obj) = object_conflicts;
647*e4b17023SJohn Marino       if (OBJECT_MAX (obj) < OBJECT_MIN (obj))
648*e4b17023SJohn Marino 	conflict_bit_vec_words_num = 0;
649*e4b17023SJohn Marino       else
650*e4b17023SJohn Marino 	conflict_bit_vec_words_num
651*e4b17023SJohn Marino 	  = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS)
652*e4b17023SJohn Marino 	     / IRA_INT_BITS);
653*e4b17023SJohn Marino       OBJECT_CONFLICT_ARRAY_SIZE (obj)
654*e4b17023SJohn Marino 	= conflict_bit_vec_words_num * sizeof (IRA_INT_TYPE);
655*e4b17023SJohn Marino     }
656*e4b17023SJohn Marino 
657*e4b17023SJohn Marino   parent_a = ira_parent_or_cap_allocno (a);
658*e4b17023SJohn Marino   if (parent_a == NULL)
659*e4b17023SJohn Marino     return;
660*e4b17023SJohn Marino   ira_assert (ALLOCNO_CLASS (a) == ALLOCNO_CLASS (parent_a));
661*e4b17023SJohn Marino   ira_assert (ALLOCNO_NUM_OBJECTS (a) == ALLOCNO_NUM_OBJECTS (parent_a));
662*e4b17023SJohn Marino   parent_obj = ALLOCNO_OBJECT (parent_a, OBJECT_SUBWORD (obj));
663*e4b17023SJohn Marino   parent_num = OBJECT_CONFLICT_ID (parent_obj);
664*e4b17023SJohn Marino   parent_min = OBJECT_MIN (parent_obj);
665*e4b17023SJohn Marino   parent_max = OBJECT_MAX (parent_obj);
666*e4b17023SJohn Marino   FOR_EACH_BIT_IN_MINMAX_SET (object_conflicts,
667*e4b17023SJohn Marino 			      OBJECT_MIN (obj), OBJECT_MAX (obj), i, asi)
668*e4b17023SJohn Marino     {
669*e4b17023SJohn Marino       ira_object_t another_obj = ira_object_id_map[i];
670*e4b17023SJohn Marino       ira_allocno_t another_a = OBJECT_ALLOCNO (another_obj);
671*e4b17023SJohn Marino       int another_word = OBJECT_SUBWORD (another_obj);
672*e4b17023SJohn Marino 
673*e4b17023SJohn Marino       ira_assert (ira_reg_classes_intersect_p
674*e4b17023SJohn Marino 		  [ALLOCNO_CLASS (a)][ALLOCNO_CLASS (another_a)]);
675*e4b17023SJohn Marino 
676*e4b17023SJohn Marino       another_parent_a = ira_parent_or_cap_allocno (another_a);
677*e4b17023SJohn Marino       if (another_parent_a == NULL)
678*e4b17023SJohn Marino 	continue;
679*e4b17023SJohn Marino       ira_assert (ALLOCNO_NUM (another_parent_a) >= 0);
680*e4b17023SJohn Marino       ira_assert (ALLOCNO_CLASS (another_a)
681*e4b17023SJohn Marino 		  == ALLOCNO_CLASS (another_parent_a));
682*e4b17023SJohn Marino       ira_assert (ALLOCNO_NUM_OBJECTS (another_a)
683*e4b17023SJohn Marino 		  == ALLOCNO_NUM_OBJECTS (another_parent_a));
684*e4b17023SJohn Marino       SET_MINMAX_SET_BIT (conflicts[parent_num],
685*e4b17023SJohn Marino 			  OBJECT_CONFLICT_ID (ALLOCNO_OBJECT (another_parent_a,
686*e4b17023SJohn Marino 							      another_word)),
687*e4b17023SJohn Marino 			  parent_min, parent_max);
688*e4b17023SJohn Marino     }
689*e4b17023SJohn Marino }
690*e4b17023SJohn Marino 
691*e4b17023SJohn Marino /* Build conflict vectors or bit conflict vectors (whatever is more
692*e4b17023SJohn Marino    profitable) of all allocnos from the conflict table.  */
693*e4b17023SJohn Marino static void
build_conflicts(void)694*e4b17023SJohn Marino build_conflicts (void)
695*e4b17023SJohn Marino {
696*e4b17023SJohn Marino   int i;
697*e4b17023SJohn Marino   ira_allocno_t a, cap;
698*e4b17023SJohn Marino 
699*e4b17023SJohn Marino   collected_conflict_objects
700*e4b17023SJohn Marino     = (ira_object_t *) ira_allocate (sizeof (ira_object_t)
701*e4b17023SJohn Marino 					  * ira_objects_num);
702*e4b17023SJohn Marino   for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--)
703*e4b17023SJohn Marino     for (a = ira_regno_allocno_map[i];
704*e4b17023SJohn Marino 	 a != NULL;
705*e4b17023SJohn Marino 	 a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
706*e4b17023SJohn Marino       {
707*e4b17023SJohn Marino 	int j, nregs = ALLOCNO_NUM_OBJECTS (a);
708*e4b17023SJohn Marino 	for (j = 0; j < nregs; j++)
709*e4b17023SJohn Marino 	  {
710*e4b17023SJohn Marino 	    ira_object_t obj = ALLOCNO_OBJECT (a, j);
711*e4b17023SJohn Marino 	    build_object_conflicts (obj);
712*e4b17023SJohn Marino 	    for (cap = ALLOCNO_CAP (a); cap != NULL; cap = ALLOCNO_CAP (cap))
713*e4b17023SJohn Marino 	      {
714*e4b17023SJohn Marino 		ira_object_t cap_obj = ALLOCNO_OBJECT (cap, j);
715*e4b17023SJohn Marino 		gcc_assert (ALLOCNO_NUM_OBJECTS (cap) == ALLOCNO_NUM_OBJECTS (a));
716*e4b17023SJohn Marino 		build_object_conflicts (cap_obj);
717*e4b17023SJohn Marino 	      }
718*e4b17023SJohn Marino 	  }
719*e4b17023SJohn Marino       }
720*e4b17023SJohn Marino   ira_free (collected_conflict_objects);
721*e4b17023SJohn Marino }
722*e4b17023SJohn Marino 
723*e4b17023SJohn Marino 
724*e4b17023SJohn Marino 
725*e4b17023SJohn Marino /* Print hard reg set SET with TITLE to FILE.  */
726*e4b17023SJohn Marino static void
print_hard_reg_set(FILE * file,const char * title,HARD_REG_SET set)727*e4b17023SJohn Marino print_hard_reg_set (FILE *file, const char *title, HARD_REG_SET set)
728*e4b17023SJohn Marino {
729*e4b17023SJohn Marino   int i, start;
730*e4b17023SJohn Marino 
731*e4b17023SJohn Marino   fputs (title, file);
732*e4b17023SJohn Marino   for (start = -1, i = 0; i < FIRST_PSEUDO_REGISTER; i++)
733*e4b17023SJohn Marino     {
734*e4b17023SJohn Marino       if (TEST_HARD_REG_BIT (set, i))
735*e4b17023SJohn Marino 	{
736*e4b17023SJohn Marino 	  if (i == 0 || ! TEST_HARD_REG_BIT (set, i - 1))
737*e4b17023SJohn Marino 	    start = i;
738*e4b17023SJohn Marino 	}
739*e4b17023SJohn Marino       if (start >= 0
740*e4b17023SJohn Marino 	  && (i == FIRST_PSEUDO_REGISTER - 1 || ! TEST_HARD_REG_BIT (set, i)))
741*e4b17023SJohn Marino 	{
742*e4b17023SJohn Marino 	  if (start == i - 1)
743*e4b17023SJohn Marino 	    fprintf (file, " %d", start);
744*e4b17023SJohn Marino 	  else if (start == i - 2)
745*e4b17023SJohn Marino 	    fprintf (file, " %d %d", start, start + 1);
746*e4b17023SJohn Marino 	  else
747*e4b17023SJohn Marino 	    fprintf (file, " %d-%d", start, i - 1);
748*e4b17023SJohn Marino 	  start = -1;
749*e4b17023SJohn Marino 	}
750*e4b17023SJohn Marino     }
751*e4b17023SJohn Marino   putc ('\n', file);
752*e4b17023SJohn Marino }
753*e4b17023SJohn Marino 
754*e4b17023SJohn Marino static void
print_allocno_conflicts(FILE * file,bool reg_p,ira_allocno_t a)755*e4b17023SJohn Marino print_allocno_conflicts (FILE * file, bool reg_p, ira_allocno_t a)
756*e4b17023SJohn Marino {
757*e4b17023SJohn Marino   HARD_REG_SET conflicting_hard_regs;
758*e4b17023SJohn Marino   basic_block bb;
759*e4b17023SJohn Marino   int n, i;
760*e4b17023SJohn Marino 
761*e4b17023SJohn Marino   if (reg_p)
762*e4b17023SJohn Marino     fprintf (file, ";; r%d", ALLOCNO_REGNO (a));
763*e4b17023SJohn Marino   else
764*e4b17023SJohn Marino     {
765*e4b17023SJohn Marino       fprintf (file, ";; a%d(r%d,", ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
766*e4b17023SJohn Marino       if ((bb = ALLOCNO_LOOP_TREE_NODE (a)->bb) != NULL)
767*e4b17023SJohn Marino         fprintf (file, "b%d", bb->index);
768*e4b17023SJohn Marino       else
769*e4b17023SJohn Marino         fprintf (file, "l%d", ALLOCNO_LOOP_TREE_NODE (a)->loop_num);
770*e4b17023SJohn Marino       putc (')', file);
771*e4b17023SJohn Marino     }
772*e4b17023SJohn Marino 
773*e4b17023SJohn Marino   fputs (" conflicts:", file);
774*e4b17023SJohn Marino   n = ALLOCNO_NUM_OBJECTS (a);
775*e4b17023SJohn Marino   for (i = 0; i < n; i++)
776*e4b17023SJohn Marino     {
777*e4b17023SJohn Marino       ira_object_t obj = ALLOCNO_OBJECT (a, i);
778*e4b17023SJohn Marino       ira_object_t conflict_obj;
779*e4b17023SJohn Marino       ira_object_conflict_iterator oci;
780*e4b17023SJohn Marino 
781*e4b17023SJohn Marino       if (OBJECT_CONFLICT_ARRAY (obj) == NULL)
782*e4b17023SJohn Marino 	continue;
783*e4b17023SJohn Marino       if (n > 1)
784*e4b17023SJohn Marino 	fprintf (file, "\n;;   subobject %d:", i);
785*e4b17023SJohn Marino       FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
786*e4b17023SJohn Marino 	{
787*e4b17023SJohn Marino 	  ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
788*e4b17023SJohn Marino 	  if (reg_p)
789*e4b17023SJohn Marino 	    fprintf (file, " r%d,", ALLOCNO_REGNO (conflict_a));
790*e4b17023SJohn Marino 	  else
791*e4b17023SJohn Marino 	    {
792*e4b17023SJohn Marino 	      fprintf (file, " a%d(r%d", ALLOCNO_NUM (conflict_a),
793*e4b17023SJohn Marino 		       ALLOCNO_REGNO (conflict_a));
794*e4b17023SJohn Marino 	      if (ALLOCNO_NUM_OBJECTS (conflict_a) > 1)
795*e4b17023SJohn Marino 		fprintf (file, ",w%d", OBJECT_SUBWORD (conflict_obj));
796*e4b17023SJohn Marino 	      if ((bb = ALLOCNO_LOOP_TREE_NODE (conflict_a)->bb) != NULL)
797*e4b17023SJohn Marino 		fprintf (file, ",b%d", bb->index);
798*e4b17023SJohn Marino 	      else
799*e4b17023SJohn Marino 		fprintf (file, ",l%d",
800*e4b17023SJohn Marino 			 ALLOCNO_LOOP_TREE_NODE (conflict_a)->loop_num);
801*e4b17023SJohn Marino 	      putc (')', file);
802*e4b17023SJohn Marino 	    }
803*e4b17023SJohn Marino 	}
804*e4b17023SJohn Marino       COPY_HARD_REG_SET (conflicting_hard_regs, OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
805*e4b17023SJohn Marino       AND_COMPL_HARD_REG_SET (conflicting_hard_regs, ira_no_alloc_regs);
806*e4b17023SJohn Marino       AND_HARD_REG_SET (conflicting_hard_regs,
807*e4b17023SJohn Marino 			reg_class_contents[ALLOCNO_CLASS (a)]);
808*e4b17023SJohn Marino       print_hard_reg_set (file, "\n;;     total conflict hard regs:",
809*e4b17023SJohn Marino 			  conflicting_hard_regs);
810*e4b17023SJohn Marino 
811*e4b17023SJohn Marino       COPY_HARD_REG_SET (conflicting_hard_regs, OBJECT_CONFLICT_HARD_REGS (obj));
812*e4b17023SJohn Marino       AND_COMPL_HARD_REG_SET (conflicting_hard_regs, ira_no_alloc_regs);
813*e4b17023SJohn Marino       AND_HARD_REG_SET (conflicting_hard_regs,
814*e4b17023SJohn Marino 			reg_class_contents[ALLOCNO_CLASS (a)]);
815*e4b17023SJohn Marino       print_hard_reg_set (file, ";;     conflict hard regs:",
816*e4b17023SJohn Marino 			  conflicting_hard_regs);
817*e4b17023SJohn Marino       putc ('\n', file);
818*e4b17023SJohn Marino     }
819*e4b17023SJohn Marino 
820*e4b17023SJohn Marino }
821*e4b17023SJohn Marino 
822*e4b17023SJohn Marino /* Print information about allocno or only regno (if REG_P) conflicts
823*e4b17023SJohn Marino    to FILE.  */
824*e4b17023SJohn Marino static void
print_conflicts(FILE * file,bool reg_p)825*e4b17023SJohn Marino print_conflicts (FILE *file, bool reg_p)
826*e4b17023SJohn Marino {
827*e4b17023SJohn Marino   ira_allocno_t a;
828*e4b17023SJohn Marino   ira_allocno_iterator ai;
829*e4b17023SJohn Marino 
830*e4b17023SJohn Marino   FOR_EACH_ALLOCNO (a, ai)
831*e4b17023SJohn Marino     print_allocno_conflicts (file, reg_p, a);
832*e4b17023SJohn Marino }
833*e4b17023SJohn Marino 
834*e4b17023SJohn Marino /* Print information about allocno or only regno (if REG_P) conflicts
835*e4b17023SJohn Marino    to stderr.  */
836*e4b17023SJohn Marino void
ira_debug_conflicts(bool reg_p)837*e4b17023SJohn Marino ira_debug_conflicts (bool reg_p)
838*e4b17023SJohn Marino {
839*e4b17023SJohn Marino   print_conflicts (stderr, reg_p);
840*e4b17023SJohn Marino }
841*e4b17023SJohn Marino 
842*e4b17023SJohn Marino 
843*e4b17023SJohn Marino 
844*e4b17023SJohn Marino /* Entry function which builds allocno conflicts and allocno copies
845*e4b17023SJohn Marino    and accumulate some allocno info on upper level regions.  */
846*e4b17023SJohn Marino void
ira_build_conflicts(void)847*e4b17023SJohn Marino ira_build_conflicts (void)
848*e4b17023SJohn Marino {
849*e4b17023SJohn Marino   enum reg_class base;
850*e4b17023SJohn Marino   ira_allocno_t a;
851*e4b17023SJohn Marino   ira_allocno_iterator ai;
852*e4b17023SJohn Marino   HARD_REG_SET temp_hard_reg_set;
853*e4b17023SJohn Marino 
854*e4b17023SJohn Marino   if (ira_conflicts_p)
855*e4b17023SJohn Marino     {
856*e4b17023SJohn Marino       ira_conflicts_p = build_conflict_bit_table ();
857*e4b17023SJohn Marino       if (ira_conflicts_p)
858*e4b17023SJohn Marino 	{
859*e4b17023SJohn Marino 	  ira_object_t obj;
860*e4b17023SJohn Marino 	  ira_object_iterator oi;
861*e4b17023SJohn Marino 
862*e4b17023SJohn Marino 	  build_conflicts ();
863*e4b17023SJohn Marino 	  ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, add_copies);
864*e4b17023SJohn Marino 	  /* We need finished conflict table for the subsequent call.  */
865*e4b17023SJohn Marino 	  if (flag_ira_region == IRA_REGION_ALL
866*e4b17023SJohn Marino 	      || flag_ira_region == IRA_REGION_MIXED)
867*e4b17023SJohn Marino 	    propagate_copies ();
868*e4b17023SJohn Marino 
869*e4b17023SJohn Marino 	  /* Now we can free memory for the conflict table (see function
870*e4b17023SJohn Marino 	     build_object_conflicts for details).  */
871*e4b17023SJohn Marino 	  FOR_EACH_OBJECT (obj, oi)
872*e4b17023SJohn Marino 	    {
873*e4b17023SJohn Marino 	      if (OBJECT_CONFLICT_ARRAY (obj) != conflicts[OBJECT_CONFLICT_ID (obj)])
874*e4b17023SJohn Marino 		ira_free (conflicts[OBJECT_CONFLICT_ID (obj)]);
875*e4b17023SJohn Marino 	    }
876*e4b17023SJohn Marino 	  ira_free (conflicts);
877*e4b17023SJohn Marino 	}
878*e4b17023SJohn Marino     }
879*e4b17023SJohn Marino   base = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, ADDRESS, SCRATCH);
880*e4b17023SJohn Marino   if (! targetm.class_likely_spilled_p (base))
881*e4b17023SJohn Marino     CLEAR_HARD_REG_SET (temp_hard_reg_set);
882*e4b17023SJohn Marino   else
883*e4b17023SJohn Marino     {
884*e4b17023SJohn Marino       COPY_HARD_REG_SET (temp_hard_reg_set, reg_class_contents[base]);
885*e4b17023SJohn Marino       AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs);
886*e4b17023SJohn Marino       AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set);
887*e4b17023SJohn Marino     }
888*e4b17023SJohn Marino   FOR_EACH_ALLOCNO (a, ai)
889*e4b17023SJohn Marino     {
890*e4b17023SJohn Marino       int i, n = ALLOCNO_NUM_OBJECTS (a);
891*e4b17023SJohn Marino 
892*e4b17023SJohn Marino       for (i = 0; i < n; i++)
893*e4b17023SJohn Marino 	{
894*e4b17023SJohn Marino 	  ira_object_t obj = ALLOCNO_OBJECT (a, i);
895*e4b17023SJohn Marino 	  reg_attrs *attrs = REG_ATTRS (regno_reg_rtx [ALLOCNO_REGNO (a)]);
896*e4b17023SJohn Marino 	  tree decl;
897*e4b17023SJohn Marino 
898*e4b17023SJohn Marino 	  if ((! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
899*e4b17023SJohn Marino 	      /* For debugging purposes don't put user defined variables in
900*e4b17023SJohn Marino 		 callee-clobbered registers.  */
901*e4b17023SJohn Marino 	      || (optimize == 0
902*e4b17023SJohn Marino 		  && attrs != NULL
903*e4b17023SJohn Marino 		  && (decl = attrs->decl) != NULL
904*e4b17023SJohn Marino 		  && VAR_OR_FUNCTION_DECL_P (decl)
905*e4b17023SJohn Marino 		  && ! DECL_ARTIFICIAL (decl)))
906*e4b17023SJohn Marino 	    {
907*e4b17023SJohn Marino 	      IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
908*e4b17023SJohn Marino 				call_used_reg_set);
909*e4b17023SJohn Marino 	      IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
910*e4b17023SJohn Marino 				call_used_reg_set);
911*e4b17023SJohn Marino 	    }
912*e4b17023SJohn Marino 	  else if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
913*e4b17023SJohn Marino 	    {
914*e4b17023SJohn Marino 	      IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
915*e4b17023SJohn Marino 				no_caller_save_reg_set);
916*e4b17023SJohn Marino 	      IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
917*e4b17023SJohn Marino 				temp_hard_reg_set);
918*e4b17023SJohn Marino 	      IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
919*e4b17023SJohn Marino 				no_caller_save_reg_set);
920*e4b17023SJohn Marino 	      IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
921*e4b17023SJohn Marino 				temp_hard_reg_set);
922*e4b17023SJohn Marino 	    }
923*e4b17023SJohn Marino 
924*e4b17023SJohn Marino 	  if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
925*e4b17023SJohn Marino 	    {
926*e4b17023SJohn Marino 	      int regno;
927*e4b17023SJohn Marino 
928*e4b17023SJohn Marino 	      /* Allocnos bigger than the saved part of call saved
929*e4b17023SJohn Marino 		 regs must conflict with them.  */
930*e4b17023SJohn Marino 	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
931*e4b17023SJohn Marino 		if (!TEST_HARD_REG_BIT (call_used_reg_set, regno)
932*e4b17023SJohn Marino 		    && HARD_REGNO_CALL_PART_CLOBBERED (regno,
933*e4b17023SJohn Marino 						       obj->allocno->mode))
934*e4b17023SJohn Marino 		  {
935*e4b17023SJohn Marino 		    SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), regno);
936*e4b17023SJohn Marino 		    SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
937*e4b17023SJohn Marino 				      regno);
938*e4b17023SJohn Marino 		  }
939*e4b17023SJohn Marino 	    }
940*e4b17023SJohn Marino 	}
941*e4b17023SJohn Marino     }
942*e4b17023SJohn Marino   if (optimize && ira_conflicts_p
943*e4b17023SJohn Marino       && internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
944*e4b17023SJohn Marino     print_conflicts (ira_dump_file, false);
945*e4b17023SJohn Marino }
946