OSDN Git Service

* c4x.c (c4x_valid_rptb_p, c4x_label_ref_used_p): New functions.
authorm.hayes <m.hayes@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Jan 2001 10:40:31 +0000 (10:40 +0000)
committerm.hayes <m.hayes@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Jan 2001 10:40:31 +0000 (10:40 +0000)
(c4x_rptb_insert): Call c4x_valid_rptb_p to check if repeat block is
valid.  If not replace it by equivalent insns.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@39181 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/c4x/c4x.c

index d68d612..47d9e2e 100644 (file)
@@ -1,5 +1,11 @@
 2001-01-22 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
 
+       * c4x.c (c4x_valid_rptb_p, c4x_label_ref_used_p): New functions.
+       (c4x_rptb_insert): Call c4x_valid_rptb_p to check if repeat block is
+       valid.  If not replace it by equivalent insns.
+
+2001-01-22 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
        * c4x.c (c4x_check_legit_addr): Only check CONST.  Not if CONST
        contains SYMBOL_REF, LABEL_REF and CONST_INT.
        (c4x_U_constraint, symbolic_address_operand): Likewise.
index a23b3c8..3ce7987 100644 (file)
@@ -187,6 +187,8 @@ static int c4x_arn_mem_operand PARAMS ((rtx, enum machine_mode, unsigned int));
 static void c4x_check_attribute PARAMS ((const char *, tree, tree, tree *));
 static int c4x_parse_pragma PARAMS ((const char *, tree *, tree *));
 static int c4x_r11_set_p PARAMS ((rtx));
+static int c4x_rptb_valid_p PARAMS ((rtx, rtx));
+static int c4x_label_ref_used_p PARAMS ((rtx, rtx));
 
 /* Called to register all of our global variables with the garbage
    collector.  */
@@ -2288,7 +2290,105 @@ c4x_rptb_nop_p (insn)
   there are no instructions in the loop which would cause problems).
   Any additional labels can be emitted at this point.  In addition, if
   the desired loop count register was not allocated, this routine does
-  nothing.  */
+  nothing. 
+
+  Before we can create a repeat block looping instruction we have to
+  verify that there are no jumps outside the loop and no jumps outside
+  the loop go into this loop. This can happen in the basic blocks reorder
+  pass. The C4x cpu can not handle this.  */
+
+static int
+c4x_label_ref_used_p (x, code_label)
+     rtx x, code_label;
+{
+  enum rtx_code code;
+  int i, j;
+  const char *fmt;
+
+  if (x == 0)
+    return 0;
+
+  code = GET_CODE (x);
+  if (code == LABEL_REF)
+    return INSN_UID (XEXP (x,0)) == INSN_UID (code_label);
+
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+       {
+          if (c4x_label_ref_used_p (XEXP (x, i), code_label))
+           return 1;
+       }
+      else if (fmt[i] == 'E')
+        for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+          if (c4x_label_ref_used_p (XVECEXP (x, i, j), code_label))
+           return 1;
+    }
+  return 0;
+}
+
+
+static int
+c4x_rptb_valid_p (insn, start_label)
+     rtx insn, start_label;
+{
+  rtx end = insn;
+  rtx start;
+  rtx tmp;
+
+  /* Find the start label.  */
+  for (; insn; insn = PREV_INSN (insn))
+    if (insn == start_label)
+      break;
+
+  /* Note found then we can not use a rptb or rpts.  The label was
+     probably moved by the basic block reorder pass.  */
+  if (! insn)
+    return 0;
+
+  start = insn;
+  /* If any jump jumps inside this block then we must fail.  */
+  for (insn = PREV_INSN (start); insn; insn = PREV_INSN (insn))
+    {
+      if (GET_CODE (insn) == CODE_LABEL)
+       {
+         for (tmp = NEXT_INSN (start); tmp != end; tmp = NEXT_INSN(tmp))
+           if (GET_CODE (tmp) == JUMP_INSN
+                && c4x_label_ref_used_p (tmp, insn))
+             return 0;
+        }
+    }
+  for (insn = NEXT_INSN (end); insn; insn = NEXT_INSN (insn))
+    {
+      if (GET_CODE (insn) == CODE_LABEL)
+       {
+         for (tmp = NEXT_INSN (start); tmp != end; tmp = NEXT_INSN(tmp))
+           if (GET_CODE (tmp) == JUMP_INSN
+                && c4x_label_ref_used_p (tmp, insn))
+             return 0;
+        }
+    }
+  /* If any jump jumps outside this block then we must fail.  */
+  for (insn = NEXT_INSN (start); insn != end; insn = NEXT_INSN (insn))
+    {
+      if (GET_CODE (insn) == CODE_LABEL)
+       {
+         for (tmp = NEXT_INSN (end); tmp; tmp = NEXT_INSN(tmp))
+           if (GET_CODE (tmp) == JUMP_INSN
+                && c4x_label_ref_used_p (tmp, insn))
+             return 0;
+         for (tmp = PREV_INSN (start); tmp; tmp = PREV_INSN(tmp))
+           if (GET_CODE (tmp) == JUMP_INSN
+                && c4x_label_ref_used_p (tmp, insn))
+             return 0;
+        }
+    }
+
+  /* All checks OK.  */
+  return 1;
+}
+
 
 void
 c4x_rptb_insert (insn)
@@ -2310,6 +2410,18 @@ c4x_rptb_insert (insn)
   /* Extract the start label from the jump pattern (rptb_end).  */
   start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0);
   
+  if (! c4x_rptb_valid_p (insn, start_label))
+    {
+      /* We can not use the rptb insn.  Replace it so reorg can use
+         the delay slots of the jump insn.  */
+      emit_insn_before (gen_addqi3 (count_reg, count_reg, GEN_INT (-1)), insn);
+      emit_insn_before (gen_cmpqi (count_reg, GEN_INT (0)), insn);
+      emit_insn_before (gen_bge (start_label), insn);
+      LABEL_NUSES (start_label)++;
+      delete_insn (insn);
+      return;
+    }
+
   end_label = gen_label_rtx ();
   LABEL_NUSES (end_label)++;
   emit_label_after (end_label, insn);