------- Comment #7 from kkojima at gcc dot gnu dot org  2010-04-16 22:34 -------
Created an attachment (id=20404)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=20404&action=view)
A bit reduced test case

It seems that we see a yet another corner case for find_barrier.
Also it looks latent on the trunk and 4.5.  Here is what is going
on, I guess.

For PIC, sh.c:fixup_mova replaces casesi_worker_1 insn with
casesi_worker_2 insn and a constant table entry is added to
a constant pool.  In the problematic case, find_barrier inserts
this constant pool in the middle of insns for casesi_worker_2.
Then the constant pool including the above constant table entry
is put before some of those insns.
This results a code sequence like

        mov.l   .L94,r0         ! insn for casesi_worker_2
        ...
CP:
        .long   bar
        ...
.L94:
        .long   .L24-.L86
        .align 5
.L87:
        add     r0,r1           ! insn for casesi_worker_2
        mova    .L86,r0         ! insn for casesi_worker_2
        mov.b   @(r0,r1),r1     ! insn for casesi_worker_2

        ...
.L24:
        .byte   .L22-.L25
        .byte   .L23-.L25
        ...

otherCP:
.L86:

which looks unexpected to the range computation in find_barrier.
It seems that the constant entry .long .L24-.L86 was assumed to
be put after the label .L86.  The patch below is an experimental
one to avoid the issue, though there would be better ways.

--- ORIG/gcc-4_4-branch/gcc/config/sh/sh.c      2010-04-15 19:59:21.000000000
+0900
+++ gcc-4_4-branch/gcc/config/sh/sh.c   2010-04-16 19:46:26.000000000 +0900
@@ -3884,6 +3884,7 @@ find_barrier (int num_mova, rtx mova, rt
   int si_limit;
   int hi_limit;
   rtx orig = from;
+  rtx last_symoff = NULL_RTX;

   /* For HImode: range is 510, add 4 because pc counts from address of
      second instruction after this one, subtract 2 for the jump instruction
@@ -4013,8 +4014,17 @@ find_barrier (int num_mova, rtx mova, rt

       if (mova_p (from))
        {
+         rtx src;
+
          switch (untangle_mova (&num_mova, &mova, from))
            {
+             case 1:
+               src = SET_SRC (PATTERN (from));
+               if (GET_CODE (src) == CONST
+                   && GET_CODE (XEXP (src, 0)) == UNSPEC
+                   && XINT (XEXP (src, 0), 1) == UNSPEC_SYMOFF)
+                 last_symoff = from;
+               break;
              case 0:   return find_barrier (0, 0, mova);
              case 2:
                {
@@ -4120,6 +4130,9 @@ find_barrier (int num_mova, rtx mova, rt
         so we'll make one.  */
       rtx label = gen_label_rtx ();

+      if (last_symoff)
+       from = last_symoff;
+
       /* If we exceeded the range, then we must back up over the last
         instruction we looked at.  Otherwise, we just need to undo the
         NEXT_INSN at the end of the loop.  */


-- 


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

Reply via email to