This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Committed] PR27531: Annotate REG_LABEL notes in reload


The following patch resolves PR target/27531 which is a P1 link
failure regression on sparc affecting mainline.  The real credit
for the analyzing the failure and suggesting a fix goes to Steven
Bosscher, as shown in the bugzilla PR.

The problem is that under the correct register pressure, the
register may need to reload a LABEL_REF, but fails to mark the
new move insn with a REG_LABEL note.  For the testcase in the
PR, this causes the reference count of the label to drop to
zero, and the label gets eliminated resulting in a link failure,
as we've assembler instructions that refer to non-existant labels.

One possible solution might be to call mark_all_labels after
reload, to scan the enitre insn stream and update the REG_LABEL notes.
However, a far more efficient approach is to keep these notes
updated incrementally, by annotating any new instructions we
create during reload.  The patch below is a refinement of
StevenB's suggested fix, by calling mark_jump_label unconditionally
at the appropriate place (instead of testing for a LABEL_REF explicitly).
This generalizes the fix to correctly attach REG_LABEL notes even
when the LABEL_REF may be buried inside the new SET_SRC.


The following patch has been tested on both sparc-sun-solaris2.8
and x86_64-unknown-linux-gnu with a full "make bootstrap", all
default languages and regression tested with a top-level "make
-k check" with no new failures.  The register allocation aspect
made creating a dejagnu testcase tricky, but it seemed advantageous
to test the actual link, rather than scan the assembler on sparc.
Let me know if there are portability issues with the test case.

Committed to mainline as revision 114921.
Thanks again to Steven for the heavy lifting.



2006-06-22  Roger Sayle  <roger@eyesopen.com>
	    Steven Bosscher  <stevenb.gcc@gmail.com>

	PR target/27531
	* reload1.c (gen_reload): Call mark_jump_label on the new insns
	generated by gen_move_insn to add REG_LABEL notes if necessary.

	* gcc.dg/pr27531-1.c: New test case.


Index: reload1.c
===================================================================
*** reload1.c	(revision 114739)
--- reload1.c	(working copy)
*************** gen_reload (rtx out, rtx in, int opnum,
*** 7757,7763 ****
      }
    /* If IN is a simple operand, use gen_move_insn.  */
    else if (OBJECT_P (in) || GET_CODE (in) == SUBREG)
!     emit_insn (gen_move_insn (out, in));

  #ifdef HAVE_reload_load_address
    else if (HAVE_reload_load_address)
--- 7757,7767 ----
      }
    /* If IN is a simple operand, use gen_move_insn.  */
    else if (OBJECT_P (in) || GET_CODE (in) == SUBREG)
!     {
!       tem = emit_insn (gen_move_insn (out, in));
!       /* IN may contain a LABEL_REF, if so add a REG_LABEL note.  */
!       mark_jump_label (in, tem, 0);
!     }

  #ifdef HAVE_reload_load_address
    else if (HAVE_reload_load_address)



/* PR target/27531 */
/* This test case stressed the register allocator into reloading a LABEL_REF
   on sparc, but didn't add a REG_LABEL note, ultimately causing the assembly
   output to reference a label that had been eliminated.  */
/* { dg-do link } */
/* { dg-options "-O2" } */
typedef struct _IO_FILE FILE;
char const *RCSname;
void *Locks;
void * Head;
struct Revpairs{
    struct Revpairs * rnext;
};
extern char *strchr(const char *s, int c);
extern int fprintf(FILE *, const char *format, ...);
static void getrevpairs (char*);
static int branchflag;
static struct Revpairs *revlist, *Revlst;

extern int warn(const char *msg, char *argv);
extern int error(const char *msg, int c, char *argv);
extern int recentdate(void *foo, void *bar);

char *t;
int main (int argc, char **argv)
{
    FILE *out;
    char *a, **newargv;
    void *currdate;
    int descflag, selectflag;
    int onlylockflag;
    int onlyRCSflag;
    int shownames;
    descflag = selectflag = shownames = 1;
    onlylockflag = onlyRCSflag = 0;
    while (a = *++argv, 0<--argc)
    {
        switch (*a++)
        {
            case 'L':
                onlylockflag = 1;
            case 'N':
                shownames = 0;
            case 'R':
                t = a;
            case 'b':
                branchflag = 1;
            case 'r':
                getrevpairs(a);
        }
        if (onlylockflag && !Locks)
            fprintf(out, "%s\n", RCSname);
        if (shownames)
            while( currdate)
                recentdate(Head, currdate);
    }
}
void getrevpairs(char *argv)
{
    char c;
    struct Revpairs * nextrevpair;
    int separator;
    if (strchr(argv,':'))
        separator = ':';
    else
    {
        if (strchr(argv,'-') )
            warn("`-' is obsolete in `-r%s'; use `:' instead", argv);
        separator = '-';
    }
    for (;;)
    {
        nextrevpair->rnext = revlist;
        for (;; c = *++argv)
        {
            switch (c)
            {
                default:
                    continue;
                case ' ':
                case '\t':
                case '\n':
                    break;
                case ':':
                case '-':
                    if (c == separator)
                        continue;
            }
            break;
        }
        if (!c)
            break;
        error("missing `,' near `%c%s'", c, argv+1);
    }
}

int warn(const char *msg, char *argv)
{
  t = 0;  /* this function needs side-effects.  */
  return 0;
}

int error(const char *msg, int c, char *argv)
{
  t = 0; /* this function needs side-effects.  */
  return 0;
}

int recentdate(void *foo, void *bar)
{
  t = 0; /* this function needs side-effects.  */
  return 0;
}


Roger
--


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]