]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR target/46915 (Wrong code is generated for conditional branch followed...
authorJohn David Anglin <dave.anglin@nrc-cnrc.gc.ca>
Wed, 22 Dec 2010 18:46:57 +0000 (18:46 +0000)
committerJohn David Anglin <danglin@gcc.gnu.org>
Wed, 22 Dec 2010 18:46:57 +0000 (18:46 +0000)
Backport from mainline:
2010-12-18  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>

PR target/46915
* config/pa/pa.c (branch_to_delay_slot_p): Use next_active_insn instead
of next_real_insn.  Search forward checking for both ASM_INPUT and
ASM_OPERANDS asms until exit condition is found.
(branch_needs_nop_p): Likewise.
(use_skip_p): New function.
(output_cbranch): Use use_skip_p.
(output_bb, output_bvb): Likewise.

2009-06-25  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>

PR target/40468
* pa.c (branch_to_delay_slot_p, branch_needs_nop_p): New functions.
(output_cbranch): Use new functions.
(output_bb, output_bvb, output_dbra, output_movb): Likewise.

From-SVN: r168177

gcc/ChangeLog
gcc/config/pa/pa.c

index 1c976a0bea61f503d6171ec12fe95ed6bf0120e8..0fe87d8ad36b2e5e065b16815fe6067ace646d3f 100644 (file)
@@ -1,3 +1,24 @@
+2010-12-22 John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       Backport from mainline:
+       2010-12-18  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       PR target/46915
+       * config/pa/pa.c (branch_to_delay_slot_p): Use next_active_insn instead
+       of next_real_insn.  Search forward checking for both ASM_INPUT and
+       ASM_OPERANDS asms until exit condition is found.
+       (branch_needs_nop_p): Likewise.
+       (use_skip_p): New function.
+       (output_cbranch): Use use_skip_p.
+       (output_bb, output_bvb): Likewise.
+
+       2009-06-25  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       PR target/40468
+       * pa.c (branch_to_delay_slot_p, branch_needs_nop_p): New functions.
+       (output_cbranch): Use new functions.
+       (output_bb, output_bvb, output_dbra, output_movb): Likewise.
+
 2010-12-13  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        Backport from mainline:
index 72a61d17e5e0afc18cefcf16a24378efcb8f475f..801b01e45613372fe569600ae7a1fa8bceb30e72 100644 (file)
@@ -6094,6 +6094,95 @@ pa_scalar_mode_supported_p (enum machine_mode mode)
     }
 }
 
+/* Return TRUE if INSN, a jump insn, has an unfilled delay slot and
+   it branches into the delay slot.  Otherwise, return FALSE.  */
+
+static bool
+branch_to_delay_slot_p (rtx insn)
+{
+  rtx jump_insn;
+
+  if (dbr_sequence_length ())
+    return FALSE;
+
+  jump_insn = next_active_insn (JUMP_LABEL (insn));
+  while (insn)
+    {
+      insn = next_active_insn (insn);
+      if (jump_insn == insn)
+       return TRUE;
+
+      /* We can't rely on the length of asms.  So, we return FALSE when
+        the branch is followed by an asm.  */
+      if (!insn
+         || GET_CODE (PATTERN (insn)) == ASM_INPUT
+         || asm_noperands (PATTERN (insn)) >= 0
+         || get_attr_length (insn) > 0)
+       break;
+    }
+
+  return FALSE;
+}
+
+/* Return TRUE if INSN, a forward jump insn, needs a nop in its delay slot.
+
+   This occurs when INSN has an unfilled delay slot and is followed
+   by an asm.  Disaster can occur if the asm is empty and the jump
+   branches into the delay slot.  So, we add a nop in the delay slot
+   when this occurs.  */
+
+static bool
+branch_needs_nop_p (rtx insn)
+{
+  rtx jump_insn;
+
+  if (dbr_sequence_length ())
+    return FALSE;
+
+  jump_insn = next_active_insn (JUMP_LABEL (insn));
+  while (insn)
+    {
+      insn = next_active_insn (insn);
+      if (!insn || jump_insn == insn)
+       return TRUE;
+
+      if (!(GET_CODE (PATTERN (insn)) == ASM_INPUT
+          || asm_noperands (PATTERN (insn)) >= 0)
+         && get_attr_length (insn) > 0)
+       break;
+    }
+
+  return FALSE;
+}
+
+/* Return TRUE if INSN, a forward jump insn, can use nullification
+   to skip the following instruction.  This avoids an extra cycle due
+   to a mis-predicted branch when we fall through.  */
+
+static bool
+use_skip_p (rtx insn)
+{
+  rtx jump_insn = next_active_insn (JUMP_LABEL (insn));
+
+  while (insn)
+    {
+      insn = next_active_insn (insn);
+
+      /* We can't rely on the length of asms, so we can't skip asms.  */
+      if (!insn
+         || GET_CODE (PATTERN (insn)) == ASM_INPUT
+         || asm_noperands (PATTERN (insn)) >= 0)
+       break;
+      if (get_attr_length (insn) == 4
+         && jump_insn == next_active_insn (insn))
+       return TRUE;
+      if (get_attr_length (insn) > 0)
+       break;
+    }
+
+  return FALSE;
+}
+
 /* This routine handles all the normal conditional branch sequences we
    might need to generate.  It handles compare immediate vs compare
    register, nullification of delay slots, varying length branches,
@@ -6105,7 +6194,7 @@ const char *
 output_cbranch (rtx *operands, int negated, rtx insn)
 {
   static char buf[100];
-  int useskip = 0;
+  bool useskip;
   int nullify = INSN_ANNULLED_BRANCH_P (insn);
   int length = get_attr_length (insn);
   int xdelay;
@@ -6119,7 +6208,7 @@ output_cbranch (rtx *operands, int negated, rtx insn)
      slot and the same branch target as this branch.  We could check
      for this but jump optimization should eliminate nop jumps.  It
      is always safe to emit a nop.  */
-  if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
+  if (branch_to_delay_slot_p (insn))
     return "nop";
 
   /* The doubleword form of the cmpib instruction doesn't have the LEU
@@ -6143,12 +6232,7 @@ output_cbranch (rtx *operands, int negated, rtx insn)
   /* A forward branch over a single nullified insn can be done with a
      comclr instruction.  This avoids a single cycle penalty due to
      mis-predicted branch if we fall through (branch not taken).  */
-  if (length == 4
-      && next_real_insn (insn) != 0
-      && get_attr_length (next_real_insn (insn)) == 4
-      && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
-      && nullify)
-    useskip = 1;
+  useskip = (length == 4 && nullify) ? use_skip_p (insn) : FALSE;
 
   switch (length)
     {
@@ -6168,7 +6252,12 @@ output_cbranch (rtx *operands, int negated, rtx insn)
        if (useskip)
          strcat (buf, " %2,%r1,%%r0");
        else if (nullify)
-         strcat (buf, ",n %2,%r1,%0");
+         {
+           if (branch_needs_nop_p (insn))
+             strcat (buf, ",n %2,%r1,%0%#");
+           else
+             strcat (buf, ",n %2,%r1,%0");
+         }
        else
          strcat (buf, " %2,%r1,%0");
        break;
@@ -6431,7 +6520,7 @@ const char *
 output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
 {
   static char buf[100];
-  int useskip = 0;
+  bool useskip;
   int nullify = INSN_ANNULLED_BRANCH_P (insn);
   int length = get_attr_length (insn);
   int xdelay;
@@ -6441,7 +6530,7 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
      is only used when optimizing; jump optimization should eliminate the
      jump.  But be prepared just in case.  */
 
-  if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
+  if (branch_to_delay_slot_p (insn))
     return "nop";
 
   /* If this is a long branch with its delay slot unfilled, set `nullify'
@@ -6457,13 +6546,7 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
   /* A forward branch over a single nullified insn can be done with a
      extrs instruction.  This avoids a single cycle penalty due to
      mis-predicted branch if we fall through (branch not taken).  */
-
-  if (length == 4
-      && next_real_insn (insn) != 0
-      && get_attr_length (next_real_insn (insn)) == 4
-      && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
-      && nullify)
-    useskip = 1;
+  useskip = (length == 4 && nullify) ? use_skip_p (insn) : FALSE;
 
   switch (length)
     {
@@ -6487,11 +6570,21 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
        if (useskip)
          strcat (buf, " %0,%1,1,%%r0");
        else if (nullify && negated)
-         strcat (buf, ",n %0,%1,%3");
+         {
+           if (branch_needs_nop_p (insn))
+             strcat (buf, ",n %0,%1,%3%#");
+           else
+             strcat (buf, ",n %0,%1,%3");
+         }
        else if (nullify && ! negated)
-         strcat (buf, ",n %0,%1,%2");
+         {
+           if (branch_needs_nop_p (insn))
+             strcat (buf, ",n %0,%1,%2%#");
+           else
+             strcat (buf, ",n %0,%1,%2");
+         }
        else if (! nullify && negated)
-         strcat (buf, "%0,%1,%3");
+         strcat (buf, " %0,%1,%3");
        else if (! nullify && ! negated)
          strcat (buf, " %0,%1,%2");
        break;
@@ -6612,7 +6705,7 @@ const char *
 output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
 {
   static char buf[100];
-  int useskip = 0;
+  bool useskip;
   int nullify = INSN_ANNULLED_BRANCH_P (insn);
   int length = get_attr_length (insn);
   int xdelay;
@@ -6622,7 +6715,7 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
      is only used when optimizing; jump optimization should eliminate the
      jump.  But be prepared just in case.  */
 
-  if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
+  if (branch_to_delay_slot_p (insn))
     return "nop";
 
   /* If this is a long branch with its delay slot unfilled, set `nullify'
@@ -6638,13 +6731,7 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
   /* A forward branch over a single nullified insn can be done with a
      extrs instruction.  This avoids a single cycle penalty due to
      mis-predicted branch if we fall through (branch not taken).  */
-
-  if (length == 4
-      && next_real_insn (insn) != 0
-      && get_attr_length (next_real_insn (insn)) == 4
-      && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
-      && nullify)
-    useskip = 1;
+  useskip = (length == 4 && nullify) ? use_skip_p (insn) : FALSE;
 
   switch (length)
     {
@@ -6668,11 +6755,21 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
        if (useskip)
          strcat (buf, "{ %0,1,%%r0| %0,%%sar,1,%%r0}");
        else if (nullify && negated)
-         strcat (buf, "{,n %0,%3|,n %0,%%sar,%3}");
+         {
+           if (branch_needs_nop_p (insn))
+             strcat (buf, "{,n %0,%3%#|,n %0,%%sar,%3%#}");
+           else
+             strcat (buf, "{,n %0,%3|,n %0,%%sar,%3}");
+         }
        else if (nullify && ! negated)
-         strcat (buf, "{,n %0,%2|,n %0,%%sar,%2}");
+         {
+           if (branch_needs_nop_p (insn))
+             strcat (buf, "{,n %0,%2%#|,n %0,%%sar,%2%#}");
+           else
+             strcat (buf, "{,n %0,%2|,n %0,%%sar,%2}");
+         }
        else if (! nullify && negated)
-         strcat (buf, "{%0,%3|%0,%%sar,%3}");
+         strcat (buf, "{ %0,%3| %0,%%sar,%3}");
        else if (! nullify && ! negated)
          strcat (buf, "{ %0,%2| %0,%%sar,%2}");
        break;
@@ -6794,7 +6891,7 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
   /* A conditional branch to the following instruction (e.g. the delay slot) is
      asking for a disaster.  Be prepared!  */
 
-  if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
+  if (branch_to_delay_slot_p (insn))
     {
       if (which_alternative == 0)
        return "ldo %1(%0),%0";
@@ -6831,7 +6928,12 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
        {
        case 4:
          if (nullify)
-           return "addib,%C2,n %1,%0,%3";
+           {
+             if (branch_needs_nop_p (insn))
+               return "addib,%C2,n %1,%0,%3%#";
+             else
+               return "addib,%C2,n %1,%0,%3";
+           }
          else
            return "addib,%C2 %1,%0,%3";
       
@@ -6939,7 +7041,7 @@ output_movb (rtx *operands, rtx insn, int which_alternative,
   /* A conditional branch to the following instruction (e.g. the delay slot) is
      asking for a disaster.  Be prepared!  */
 
-  if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
+  if (branch_to_delay_slot_p (insn))
     {
       if (which_alternative == 0)
        return "copy %1,%0";
@@ -6977,7 +7079,12 @@ output_movb (rtx *operands, rtx insn, int which_alternative,
        {
        case 4:
          if (nullify)
-           return "movb,%C2,n %1,%0,%3";
+           {
+             if (branch_needs_nop_p (insn))
+               return "movb,%C2,n %1,%0,%3%#";
+             else
+               return "movb,%C2,n %1,%0,%3";
+           }
          else
            return "movb,%C2 %1,%0,%3";