------- Comment #19 from ebotcazou at gcc dot gnu dot org  2008-09-02 17:35 
-------
> I've looked at the cgraphbuild.i code and I think something is wrong with
> inlining.  There are two paths achieving L21 with different stack 
> adjustments. 
> Here is the code.  I marked insns adjusting SP by -> and the two insns should
> refer to the same location by !

Isn't that supposed to be detected by reload?

/* For each label, we record the offset of each elimination.  If we reach
   a label by more than one path and an offset differs, we cannot do the
   elimination.  This information is indexed by the difference of the
   number of the label and the first label number.  We can't offset the
   pointer itself as this can cause problems on machines with segmented
   memory.  The first table is an array of flags that records whether we
   have yet encountered a label and the second table is an array of arrays,
   one entry in the latter array for each elimination.  */

static int first_label_num;
static char *offsets_known_at;
static HOST_WIDE_INT (*offsets_at)[NUM_ELIMINABLE_REGS];

/* This function handles the tracking of elimination offsets around branches.

   X is a piece of RTL being scanned.

   INSN is the insn that it came from, if any.

   INITIAL_P is nonzero if we are to set the offset to be the initial
   offset and zero if we are setting the offset of the label to be the
   current offset.  */

static void
set_label_offsets (rtx x, rtx insn, int initial_p)
{
  enum rtx_code code = GET_CODE (x);
  rtx tem;
  unsigned int i;
  struct elim_table *p;

  switch (code)
    {
    case LABEL_REF:
      if (LABEL_REF_NONLOCAL_P (x))
        return;

      x = XEXP (x, 0);

      /* ... fall through ...  */

    case CODE_LABEL:
      /* If we know nothing about this label, set the desired offsets.  Note
         that this sets the offset at a label to be the offset before a label
         if we don't know anything about the label.  This is not correct for
         the label after a BARRIER, but is the best guess we can make.  If
         we guessed wrong, we will suppress an elimination that might have
         been possible had we been able to guess correctly.  */

      if (! offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num])
        {
          for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
            offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
              = (initial_p ? reg_eliminate[i].initial_offset
                 : reg_eliminate[i].offset);
          offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num] = 1;
        }

      /* Otherwise, if this is the definition of a label and it is
         preceded by a BARRIER, set our offsets to the known offset of
         that label.  */

      else if (x == insn
               && (tem = prev_nonnote_insn (insn)) != 0
               && BARRIER_P (tem))
        set_offsets_for_label (insn);
      else
        /* If neither of the above cases is true, compare each offset
           with those previously recorded and suppress any eliminations
           where the offsets disagree.  */

        for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
          if (offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
              != (initial_p ? reg_eliminate[i].initial_offset
                  : reg_eliminate[i].offset))
            reg_eliminate[i].can_eliminate = 0;

      return;


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37296

Reply via email to