From: CECDEV@isnet.INmos.co.UK (LIOCHON)
Subject: help for reloading
Organization: GNUs Not Usenet
Distribution: gnu
Date: Thu, 1 Oct 1992 14:01:28 GMT

I am trying to implement floats and doubles for the ST9
microcontroller, starting from the GCC version 1.39.90
modified by Pierre Willard (TCE LA) to be used on the ST9
8/16 bit microcontroller.
GCC9 (GCC for the ST9 microcontroller) can use 8 16-bit registers
(rr0, rr2, rr4, rr6, rr8, rr10, rr12, rr14).
rr12 is used to store the frame pointer.
A ST9 double is 64-bit long, therefore 4 registers are needed to
store a double.
I got problems in the reloading phase as there are some limitations
within GCC (see below some comments in reload1.c).
I send you a few modifications, which solve partly the problem
although I am not sure it can be of any use to you.
I think my problems come from the fact that machine modes that
require groups of more than 2 consecutive registers are not properly
handled by gcc-1.39.90.

Do you know if these limitations have been removed in more recent
versions of GCC ?

If not, can you suggest me some directions to modify the code : I am
new in the job as a user of GCC.


I can't send you easily the environment in which the bugs occurred :
GCC9 is much different from the standard GCC version and it is still
under development. I hope you can however answer my questions.

			Thank you,


					Robert Jamier
					SGS-THOMSON
					av. des Martyrs
					BP 217
					38019 Grenoble Cedex
					FRANCE

					Phone (033) 76 58 53 05
					Fax (033) 76 58 56 68


extracted from reload1.c :
--------------------------
/* For each class, the machine mode which requires consecutive
   groups of regs of that class.
   If two different modes ever require groups of one class,
   they must be the same size and equally restrictive for that class,
   otherwise we can't handle the complexity.  */

/* If a group of consecutive regs are needed,
   record which machine mode needs them.
   Crash if two dissimilar machine modes both need
   groups of consecutive regs of the same class. */

/* If this reg will not be available for groups,
   pick one that does not foreclose possible groups.
   This is a kludge, and not very general,
   but it should be sufficient to make the 386 work,
   and the problem should not occur on machines with
   more registers.  */

within reload
_____________

I changed :
-----------

if (group_mode[(int) reload_reg_class[i]] != VOIDmode
    &&
    (! modes_equiv_for_class_p (group_mode[(int) reload_reg_class[i]], mode, reload_reg_class[i])
     ||
     group_size[(int) reload_reg_class[i]] != size))
   abort ();

/* Record size and mode of a group of this class.  */
group_size[(int) reload_reg_class[i]] = size;
group_mode[(int) reload_reg_class[i]] = mode;

into :
------

/* Record size and mode of a group of this class.  */
group_size[(int) reload_reg_class[i]] = max(group_size[(int) reload_reg_class[i]], size);
if (group_size[(int) reload_reg_class[i]] == size)
   group_mode[(int) reload_reg_class[i]] = mode;

within possible_group_p
_______________________

I changed :
-----------

/* Nonzero if, after spilling reg REGNO for non-groups,
   it will still be possible to find a group if we still need one.  */

static int
possible_group_p (regno, max_groups)
     int regno;
     int *max_groups;
{
  int i;
  int group = 0;

  for (i = 0; i < (int) N_REG_CLASSES; i++)
    group |= max_groups[i];

  if (group == 0)
    return 1;

  /* Consider each pair of consecutive registers.  */
  for (i = 0; i < FIRST_PSEUDO_REGISTER - 1; i++)
    {
      if (i == regno || i + 1 == regno)
	continue;

      /* A pair of consecutive regs we can still spill does the trick.  */
      if (spill_reg_order[i] < 0 && spill_reg_order[i + 1] < 0
	  && !regs_explicitly_used[i] && !regs_explicitly_used[i + 1]
	  && !fixed_regs[i] && i != FRAME_POINTER_REGNUM
	  && !fixed_regs[i + 1] && i + 1 != FRAME_POINTER_REGNUM)
	return 1;

      /* A pair of one already spilled and one we can spill does it
	 provided the one already spilled is not otherwise reserved.  */
      if (spill_reg_order[i] < 0 && !regs_explicitly_used[i]
	  && !fixed_regs[i] && i != FRAME_POINTER_REGNUM
	  && spill_reg_order[i + 1] >= 0
	  && !counted_for_groups[i + 1]
	  && !counted_for_nongroups[i + 1])
	return 1;
      if (spill_reg_order[i + 1] < 0 && !regs_explicitly_used[i + 1]
	  && !fixed_regs[i + 1] && i + 1 != FRAME_POINTER_REGNUM
	  && spill_reg_order[i] >= 0
	  && !counted_for_groups[i]
	  && !counted_for_nongroups[i])
	return 1;
    }

  return 0;
}

into :
------

static int
possible_group_p (regno, max_groups, group_size)
     int regno;
     int *max_groups, *group_size;
{
  int i;
  int group = 0;
  int size = 0;

  for (i = 0; i < (int) N_REG_CLASSES; i++)
    {
      group |= max_groups[i];
      size = max(size, group_size[i]);
    }

  if (group == 0)
    return 1;

  if (size == 2)
    /* Consider each pair of consecutive registers.  */
    for (i = 0; i < FIRST_PSEUDO_REGISTER - 1; i++)
      {
	if (i == regno || i + 1 == regno)
	  continue;

	/* A pair of consecutive regs we can still spill does the trick.  */
	if (spill_reg_order[i] < 0 && spill_reg_order[i + 1] < 0
	    && !regs_explicitly_used[i] && !regs_explicitly_used[i + 1]
	    && !fixed_regs[i] && i != FRAME_POINTER_REGNUM
	    && !fixed_regs[i + 1] && i + 1 != FRAME_POINTER_REGNUM)
	  return 1;
	
	/* A pair of one already spilled and one we can spill does it
	   provided the one already spilled is not otherwise reserved.  */
	if (spill_reg_order[i] < 0 && !regs_explicitly_used[i]
	    && !fixed_regs[i] && i != FRAME_POINTER_REGNUM
	    && spill_reg_order[i + 1] >= 0
	    && !counted_for_groups[i + 1]
	    && !counted_for_nongroups[i + 1])
	  return 1;
	if (spill_reg_order[i + 1] < 0 && !regs_explicitly_used[i + 1]
	    && !fixed_regs[i + 1] && i + 1 != FRAME_POINTER_REGNUM
	    && spill_reg_order[i] >= 0
	    && !counted_for_groups[i]
	    && !counted_for_nongroups[i])
	  return 1;
      }
  else
    for (i = 0; i < FIRST_PSEUDO_REGISTER - 1; i++)
      {
	int j;
	for (j = 0; j < size; j++)
	  if ((i+j) == regno)
	    break;
	if ((i+j) == regno)
	  continue;
	for (j = 0; j < size; j++)
	  if (!(spill_reg_order[i+j] < 0 
		&& !regs_explicitly_used[i+j]
		&& !fixed_regs[i+j]
		&& (i+j) != FRAME_POINTER_REGNUM))
	    break;
	if (j == size)
	  return 1;
      }

  return 0;
}

within reload
_____________
/* If this reg will not be available for groups,
   pick one that does not foreclose possible groups.
   This is a kludge, and not very general,
   but it should be sufficient to make the 386 work,
   and the problem should not occur on machines with
   more registers.  */

I changed :
-----------
	  /* Now similarly satisfy all need for single registers.  */

	  while (max_needs[class] > 0 || max_nongroups[class] > 0)
	    {
	      /* Consider the potential reload regs that aren't
		 yet in use as reload regs, in order of preference.
		 Find the most preferred one that's in this class.  */

	      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
		if (potential_reload_regs[i] >= 0
		    && TEST_HARD_REG_BIT (reg_class_contents[class],
					  potential_reload_regs[i])
		    /* If this reg will not be available for groups,
		       pick one that does not foreclose possible groups.
		       This is a kludge, and not very general,
		       but it should be sufficient to make the 386 work,
		       and the problem should not occur on machines with
		       more registers.  */
/* (RJ) for the ST9
		    && (max_nongroups[class] == 0
			|| possible_group_p (potential_reload_regs[i], max_groups, group_size))
*/
		    && possible_group_p (potential_reload_regs[i], max_groups, group_size))
		  break;

	      /* I should be the index in potential_reload_regs
		 of the new reload reg we have found.  */

	      something_changed
		|= new_spill_reg (i, class, max_needs, max_nongroups,
				  global, dumpfile);
	    }



I then got a crash within new_spill_reg :
  if (i >= FIRST_PSEUDO_REGISTER)
    abort ();	/* Caller failed to find any register.  */

What should I do next ?

Newsgroups: gnu.gcc.bug