aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorHerman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>2001-01-22 11:40:31 +0100
committerMichael Hayes <m.hayes@gcc.gnu.org>2001-01-22 10:40:31 +0000
commit0bbcfbafc8aa36f62eb4d347301cf80498ac3464 (patch)
tree2404210dc2f2e256537dd6050491719edb21682f /gcc
parent5078f5eb76d9796bfb97fff2a269508e71b12ad2 (diff)
downloadgcc-0bbcfbafc8aa36f62eb4d347301cf80498ac3464.zip
gcc-0bbcfbafc8aa36f62eb4d347301cf80498ac3464.tar.gz
gcc-0bbcfbafc8aa36f62eb4d347301cf80498ac3464.tar.bz2
c4x.c (c4x_valid_rptb_p, [...]): New functions.
* 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. From-SVN: r39181
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/c4x/c4x.c114
2 files changed, 119 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d68d612..47d9e2e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c
index a23b3c8..3ce7987 100644
--- a/gcc/config/c4x/c4x.c
+++ b/gcc/config/c4x/c4x.c
@@ -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);