From 0bbcfbafc8aa36f62eb4d347301cf80498ac3464 Mon Sep 17 00:00:00 2001 From: "Herman A.J. ten Brugge" Date: Mon, 22 Jan 2001 11:40:31 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 6 +++ gcc/config/c4x/c4x.c | 114 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d68d6127e54..47d9e2e9d29 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2001-01-22 Herman A.J. ten Brugge + + * 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 * c4x.c (c4x_check_legit_addr): Only check CONST. Not if CONST diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index a23b3c8e536..3ce7987c06d 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); -- 2.30.2