From f1c374cbf13459be57011c157b5ebba66cc1e02d Mon Sep 17 00:00:00 2001 From: Michael Hayes Date: Tue, 20 Oct 1998 03:18:57 +0000 Subject: [PATCH] c4x.c (c4x_parallel_process): Disable until BCT loop optimization stable for the C4x. * config/c4x/c4x.c (c4x_parallel_process): Disable until BCT loop optimization stable for the C4x. (c4x_rptb_info_t, c4x_dump, c4x_rptb_in_range, c4x_rptb_unjumped_loop, c4x_rptb_find_comp_and_jump, c4x_rptb_loop_info_get, c4x_rptb_emit_init, c4x_rptb_process): Deleted (superceded by BCT loop optimization). (c4x_address_conflict): Be more paranoid when packing a volatile memref in a parallel load/store. From-SVN: r23196 --- gcc/ChangeLog | 11 + gcc/config/c4x/c4x.c | 564 +------------------------------------------ 2 files changed, 21 insertions(+), 554 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8753149652f..a532b2ab228 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +Tue Oct 20 22:16:11 1998 Michael Hayes + + * config/c4x/c4x.c (c4x_parallel_process): Disable until BCT + loop optimization stable for the C4x. + (c4x_rptb_info_t, c4x_dump, c4x_rptb_in_range, c4x_rptb_unjumped_loop, + c4x_rptb_find_comp_and_jump, c4x_rptb_loop_info_get, + c4x_rptb_emit_init, c4x_rptb_process): Deleted (superceded by BCT + loop optimization). + (c4x_address_conflict): Be more paranoid when packing a volatile + memref in a parallel load/store. + Tue Oct 20 21:56:05 1998 Michael Hayes * config/c4x/c4x.md (repeat_block_top, repeat_block_end, diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index 312c2daa154..8de1fc0dc43 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -132,22 +132,6 @@ enum machine_mode c4x_caller_save_map[FIRST_PSEUDO_REGISTER] = }; -/* rptb_info has enough information to compute rtx for loop counter. */ -typedef struct -{ - int loop_count; /* Positive if loop count is constant */ - /* The rest of fields are meaningless if loop_count is set */ - rtx start_value; /* Starting value for biv */ - rtx end_value; /* Limit for biv */ - int swap_p; /* 1 for count down */ - int incr; /* Increment for biv -- must be constant */ - int shift; /* log2(incr) */ - int off_by_one; /* 1 for "<", 0 for "<=" */ - int unsigned_p; /* True if unsigned comparison at loop end */ - rtx loop_start; -} -c4x_rptb_info_t; - /* Test and compare insns in c4x.md store the information needed to generate branch and scc insns here. */ @@ -167,29 +151,6 @@ tree pure_tree = NULL_TREE; tree noreturn_tree = NULL_TREE; tree interrupt_tree = NULL_TREE; -static void -c4x_dump (file, s) - FILE * file; - const char *s; - ... -{ -#ifndef __STDC__ - char *s; -#endif - va_list ap; - - if (!file) - return; - - VA_START (ap, s); - -#ifndef __STDC__ - s = va_arg (ap, char *); -#endif - - vfprintf (file, s, ap); - va_end (ap); -} /* Override command line options. Called once after all options have been parsed. @@ -3204,14 +3165,9 @@ c4x_address_conflict (op0, op1, store0, store1) if (!TARGET_DEVEL && base0 == base1 && (incdec0 || incdec1)) return 1; - /* It is not worthwhile having parallel loads from the same address - unless we could be sure that both locations were in internal - memory. We allow this for peepholes (after reload has completed - since we are going to be executing two insns to the same address - anyhow) but steer the combiner away from doing this since it seems - to get the wrong idea. */ - if (!store0 && !store1 && base0 == base1 && disp0 == disp1 - && !reload_completed) + /* We can not optimize the case where op1 and op2 refer to the same + address. */ + if (base0 == base1 && disp0 == disp1 && index0 == index1) return 1; /* No conflict. */ @@ -4623,8 +4579,14 @@ c4x_parallel_process (loop_start, loop_end) if (!(loop_count_set = single_set (loop_count))) return 0; +#if 0 + /* Disable this optimisation until REG_LOOP_COUNT note + added. */ if (!find_reg_note (loop_count, REG_LOOP_COUNT, NULL_RTX)) return 0; +#else + return 0; +#endif loop_count_reg = SET_DEST (loop_count_set); @@ -4912,470 +4874,6 @@ c4x_combine_parallel (insns) } -/* True if INSN is between START and END. If END precedes START - something has gone awry. */ - -static int -c4x_rptb_in_range (insn, start, end) - rtx insn, start, end; -{ - rtx this; - - for (this = start; ; this = NEXT_INSN (this)) - { - if (this == insn) - return 1; - if (this == end) - return 0; - if (this == NULL_RTX) - fatal_insn ("c4x_rptb_in_range: Repeat block error", start); - } -} - - -/* Returns true if there are no jumps crossing the loop boundary and - no calls anywhere. */ - -int -c4x_rptb_unjumped_loop_p (loop_start, loop_end) - rtx loop_start, loop_end; -{ - rtx insn; - rtx continue_label = NULL_RTX; - rtx continue_note = NULL_RTX; /* Loop continue note if there is one. */ - - /* Scan loop backwards. */ - for (insn = PREV_INSN (loop_end); insn && insn != loop_start; - insn = PREV_INSN (insn)) - { - switch (GET_CODE (insn)) - { - case JUMP_INSN: - { - rtx jump_label = JUMP_LABEL (insn); - - /* We don't like jumps out of the loop. We also look - for jumps to the end of loop, say from a continue - statement. */ - if (continue_note - && jump_label == next_nonnote_insn (continue_note)) - continue_label = jump_label; - else if (!c4x_rptb_in_range (jump_label, loop_start, - continue_note ? continue_note : - loop_end)) - return 0; - } - /* Fall through */ - - case INSN: - if (0 && volatile_refs_p (PATTERN (insn))) - { - c4x_dump (loop_dump_stream, - "Repeat block: Volatile memory ref within loop\n"); - return 0; - } - - /* The C4x movstrqi_large pattern clobbers RC, RE, RS. - This should be generalised to check for insns that use - these registers within the loop. */ - if (recog_memoized (insn) == CODE_FOR_movstrqi_large) - { - c4x_dump (loop_dump_stream, - "Repeat block: Memory copy within loop\n"); - return 0; - } - break; - - /* It is not worthwhile preserving the zero overhead loop - context across calls. */ - case CALL_INSN: - /* We could allow a libcall with no side effects??? */ - c4x_dump (loop_dump_stream, "Repeat block: Call within loop\n"); - return 0; - - case NOTE: - switch (NOTE_LINE_NUMBER (insn)) - { - case NOTE_INSN_LOOP_CONT: - if (continue_note == NULL_RTX) - continue_note = insn; - - /* Check for empty loop which would throw c4x_rptb_nop_p. - GCC doesn't optimise empty loops away since user - may be trying to implement a simple but crude delay. */ - if (GET_CODE (PREV_INSN (insn)) == NOTE - && NOTE_LINE_NUMBER (PREV_INSN (insn)) == NOTE_INSN_LOOP_BEG) - { - c4x_dump (loop_dump_stream, "Repeat block: Empty loop\n"); - return 0; - } - break; - - /* If we find a LOOP_END note, then we are not in the - innermost loop. */ - case NOTE_INSN_LOOP_END: - return 0; - - default: - continue; - } - default: - continue; - } - } - if (insn == NULL_RTX) - fatal("Repeat block: Inconsistent loop"); - - c4x_dump (loop_dump_stream, "Repeat block: Unjumped loop\n"); - if (continue_label) - c4x_dump (loop_dump_stream, "Repeat block: Continue_label %d\n", - INSN_UID (continue_label)); - return 1; -} - - -/* Find and record in PCOMP and PJUMP the final comparison and jump - insns of the loop specified by LOOP_END. Return 1 if both have been - found, otherwise return 0. */ - -static int -c4x_rptb_find_comp_and_jump (loop_end, pcomp, pjump) - rtx loop_end; - rtx *pcomp, *pjump; -{ - rtx final_comp, comp_pat; - rtx final_jump = prev_nonnote_insn (loop_end); - - if (!final_jump) - return 0; - - final_comp = PREV_INSN (final_jump); - if (!final_comp) - return 0; - - if ((GET_CODE (final_comp) != INSN)) - return 0; - - comp_pat = PATTERN (final_comp); - - if ((GET_CODE (comp_pat) != SET) - || GET_CODE (XEXP (comp_pat, 0)) != REG - || REGNO (XEXP (comp_pat, 0)) != ST_REGNO) - return 0; - - *pcomp = final_comp; - *pjump = final_jump; - return 1; -} - - -/* Determine if the loop count is computable for a repeat loop. */ - -static int -c4x_rptb_loop_info_get (loop_start, loop_end, loop_info) - rtx loop_start, loop_end; - c4x_rptb_info_t *loop_info; -{ - rtx iteration_var, initial_value, increment, comparison; - enum rtx_code cc; /* Comparison code */ - rtx comparison_value; - - loop_info->loop_start = loop_start; - loop_info->loop_count = loop_iterations (loop_start, loop_end); - - /* If the number of loop cycles does not need calculating at - run-time then things are easy... Note that the repeat count - value must be a positive integer for the RPTB instruction. If - loop_count is zero then we don't have a constant count. */ - if (loop_info->loop_count > 0) - return 1; - if (loop_info->loop_count < 0) - { - c4x_dump (loop_dump_stream, "Repeat block: Negative loop count %d\n", - loop_info->loop_count); - return 0; - } - - comparison = get_condition_for_loop (prev_nonnote_insn (loop_end)); - if (comparison == NULL_RTX) - { - c4x_dump (loop_dump_stream, "Repeat block: Cannot find comparison\n"); - return 0; - } - cc = GET_CODE (comparison); - - /* Only allow a register as the iteration value. */ - iteration_var = XEXP (comparison, 0); - if (GET_CODE (iteration_var) != REG) - { - c4x_dump (loop_dump_stream, "Repeat block: Non reg. iteration value\n"); - return 0; - } - - c4x_dump (loop_dump_stream, "Repeat block: Iteration value regno = %d\n", - REGNO (iteration_var)); - - /* The comparison value must not change on the fly. */ - comparison_value = XEXP (comparison, 1); - if (!invariant_p (comparison_value)) - { - c4x_dump (loop_dump_stream, "Repeat block: Comparison value variant\n"); - return 0; - } - - /* This routine in unroll.c does the hard work of finding the - initial value and increment for us. Currently it won't find the - intitial value or increment for do {} while; or while() {} do; - loops. This is because the iteration_var we find in the - comparison insn is a GIV rather than a BIV and iteration_info does - not like GIVs. We could scan all the BIVs like check_dbra_loop() - does... */ - - iteration_info (iteration_var, &initial_value, &increment, - loop_start, loop_end); - if (initial_value == NULL_RTX || increment == NULL_RTX) - { - c4x_dump (loop_dump_stream, "Repeat block: Cannot determine initial" - " value or increment\n"); - return 0; - } - - /* Only allow constant integer increment, not a variable. */ - if (GET_CODE (increment) != CONST_INT) - { - c4x_dump (loop_dump_stream, "Repeat block: Increment not constant\n"); - return 0; - } - - loop_info->incr = INTVAL (increment); - - /* If the increment is not a power of 2, (i.e, 1, 2, 4, etc.) then - we will need to emit a divide instruction rather than a right - shift to calculate the loop count. */ - if ((loop_info->shift = exact_log2 (abs (loop_info->incr))) < 0) - { - c4x_dump (loop_dump_stream, "Repeat block: Increment not power of 2\n"); - return 0; - } - - /* The front end changes GT to NE for unsigned numbers, so we - "undo" this here for clarity. */ - loop_info->unsigned_p = 0; - if (GET_CODE (increment) == CONST_INT - && INTVAL (increment) == -1 && cc == NE) - { - loop_info->unsigned_p = 1; - cc = GT; - } - - if (!(cc == LT || cc == LE || cc == LTU || cc == LEU - || cc == GT || cc == GE || cc == GTU || cc == GEU)) - { - c4x_dump (loop_dump_stream, "Repeat block: Invalid comparison\n"); - return 0; - } - - loop_info->swap_p = (cc == GT || cc == GE || cc == GTU || cc == GEU); - if (loop_info->swap_p) - { - loop_info->start_value = comparison_value; - loop_info->end_value = initial_value; - loop_info->incr = -loop_info->incr; - } - else - { - loop_info->start_value = initial_value; - loop_info->end_value = comparison_value; - } - - /* Check if loop won't terminate? */ - if (loop_info->incr <= 0) - { - c4x_dump (loop_dump_stream, "Repeat block: Increment negative\n"); - return 0; - } - - loop_info->off_by_one = (cc == LT || cc == LTU || cc == GT || cc == GTU); - - - /* We have a switch to allow an unsigned loop counter. - We'll normally disallow this case since the the repeat - count for the RPTB instruction must be less than 0x80000000. */ - if (loop_info->unsigned_p && !TARGET_LOOP_UNSIGNED) - { - c4x_dump (loop_dump_stream, "Repeat block: Unsigned comparison\n"); - return 0; - } - - return 1; -} - - -/* Emit insn(s) to compute loop iteration count. */ - -static rtx -c4x_rptb_emit_init (loop_info) - c4x_rptb_info_t *loop_info; -{ - rtx result; - int adjust; - rtx seq_start; - - /* If have a known constant loop count, things are easy... */ - if (loop_info->loop_count > 0) - return GEN_INT (loop_info->loop_count - 1); - - if (loop_info->shift < 0) - abort (); - - start_sequence (); - - result = loop_info->end_value; - if (loop_info->start_value != const0_rtx) - { - /* end_value - start_value */ - result = expand_binop (QImode, sub_optab, - result, loop_info->start_value, - 0, loop_info->unsigned_p, OPTAB_DIRECT); - } - - adjust = loop_info->incr - loop_info->off_by_one; - if (adjust > 0) - { - /* end_value - start_value + adjust */ - result = expand_binop (QImode, add_optab, - result, GEN_INT (adjust), - 0, loop_info->unsigned_p, OPTAB_DIRECT); - } - - if (loop_info->shift > 0) - { - /* (end_value - start_value + adjust) >> shift */ - result = expand_binop (QImode, loop_info->unsigned_p ? - lshr_optab : ashr_optab, result, - GEN_INT (loop_info->shift), - 0, loop_info->unsigned_p, OPTAB_DIRECT); - } - - /* ((end_value - start_value + adjust) >> shift) - 1 */ - result = expand_binop (QImode, sub_optab, - result, GEN_INT (1), - 0, loop_info->unsigned_p, OPTAB_DIRECT); - - seq_start = get_insns (); - end_sequence (); - - emit_insns_before (seq_start, loop_info->loop_start); - return result; -} - - -/* This routine checks for suitable loops that can use zero overhead - looping and emits insns marking the start and end of the loop - as well as an insn for initialising the loop counter. */ - -void -c4x_rptb_process (loop_start, loop_end) - rtx loop_start, loop_end; -{ - rtx iteration_count; - rtx start_label; - rtx end_label; - rtx comp_insn; - rtx jump_insn; - c4x_rptb_info_t info; - - if (!TARGET_RPTB) - return; - - /* Check that there are no jumps crossing loop boundary or calls. */ - if (!c4x_rptb_unjumped_loop_p (loop_start, loop_end)) - return; - - start_label = next_nonnote_insn (loop_start); - if (GET_CODE (start_label) != CODE_LABEL) - return; - - /* Find comparison and jump insns. */ - if (!c4x_rptb_find_comp_and_jump (loop_end, &comp_insn, &jump_insn)) - return; - - /* If we don't jump back to start label, then the loop is no good. */ - if (start_label != JUMP_LABEL (jump_insn)) - return; - - /* Check that number of loops is computable. */ - if (!c4x_rptb_loop_info_get (loop_start, loop_end, &info)) - return; - - c4x_dump (loop_dump_stream, "Repeat block: Loop start at %d, end at %d\n", - INSN_UID (loop_start), INSN_UID (loop_end)); - - if (info.loop_count > 0) - c4x_dump (loop_dump_stream, "Repeat block: Loop count = %d\n", - info.loop_count); - else - c4x_dump (loop_dump_stream, - "Repeat block: incr %d, shift %d, swap_p %d," - " off_by_one %d, unsigned_p %d\n", - info.incr, info.shift, info.swap_p, - info.off_by_one, info.unsigned_p); - - /* Emit insns to compute loop iteration count. */ - iteration_count = c4x_rptb_emit_init (&info); - if (iteration_count == NULL_RTX) - abort (); - - /* Add label at end of loop, immediately after jump insn. */ - end_label = gen_label_rtx (); - emit_label_after (end_label, jump_insn); - - /* Add label to forced label list to prevent jump optimisation - coalescing end_label with bypass_label since we need these destinct if - we are to sink insns out of the loop. */ - if (GET_CODE (NEXT_INSN (loop_end)) == CODE_LABEL) - { - rtx bypass_label; - - bypass_label = NEXT_INSN (loop_end); -#if 0 - forced_labels = gen_rtx_EXPR_LIST (VOIDmode, - end_label, forced_labels); - forced_labels = gen_rtx_EXPR_LIST (VOIDmode, - bypass_label, forced_labels); -#endif - emit_insn_after (gen_repeat_block_filler (), end_label); - - c4x_dump (loop_dump_stream, - "Repeat block: Start label at %d, end label at %d," - " bypass label at %d\n", - INSN_UID (start_label), INSN_UID (end_label), - INSN_UID (bypass_label)); - } - else - { - emit_insn_after (gen_repeat_block_filler (), end_label); - c4x_dump (loop_dump_stream, - "Repeat block: Start label at %d, end label at %d\n", - INSN_UID (start_label), INSN_UID (end_label)); - } - - /* Create pattern for repeat_block_top and insert at top of loop. */ - emit_insn_before (gen_repeat_block_top (const0_rtx, iteration_count, - start_label, end_label), - start_label); - - /* Replace the jump instruction with repeat_block_end insn. */ - PATTERN (jump_insn) = gen_repeat_block_end (const0_rtx, start_label); - - /* The insn is unrecognizable after the surgery. */ - INSN_CODE (jump_insn) = -1; - - /* Delete the comparison insn. */ - delete_insn (comp_insn); -} - - /* !!! FIXME to emit RPTS correctly. */ int c4x_rptb_rpts_p (insn, op) @@ -5410,7 +4908,7 @@ c4x_rptb_rpts_p (insn, op) if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') return 0; - if (recog_memoized (insn) != CODE_FOR_repeat_block_end) + if (recog_memoized (insn) != CODE_FOR_rptb_end) return 0; if (TARGET_RPTS) @@ -5419,48 +4917,6 @@ c4x_rptb_rpts_p (insn, op) return (GET_CODE (op) == CONST_INT) && TARGET_RPTS_CYCLES (INTVAL (op)); } -/* - Loop structure of `for' loops: - - Check if iterations required - If not, jump to BYPASS_LABEL - - NOTE_INSN_LOOP_BEG - <<> - START_LABEL: - {NOTE_BLOCK_BEGIN} - - Body of loop - - {NOTE_BLOCK_END} - {NOTE_INSN_LOOP_CONT} - - Increment loop counters here - - {NOTE_INSN_LOOP_VTOP} - <<>> - Exit test here <<>> - If not exiting jump to START_LABEL <<>> - <<> - - NOTE_INSN_LOOP_END - - BYPASS_LABEL: - - Note that NOTE_INSN_LOOP_VTOP is only required for loops such as - for loops, where it necessary to duplicate the exit test. This - position becomes another virtual start of the loop when considering - invariants. - - Note that if there is nothing in the loop body we get: - - NOTE_INSN_LOOP_BEG - NOTE_INSN_LOOP_CONT - START_LABEL: - NOTE_INSN_LOOP_VTOP - ... - */ - /* Adjust the cost of a scheduling dependency. Return the new cost of a dependency LINK or INSN on DEP_INSN. COST is the current cost. -- 2.30.2