[PATCH] sh, loop iv optim
Christian BRUEL
christian.bruel@st.com
Mon Jun 4 07:42:00 GMT 2007
ahhhhh. yes this is true, loop-doloop.c should do the job. Thank you for
the info, and your comments.
Kaz, it loos like we are missing a doloop_end pattern definition in the
sh description. I'm giving it a try.
Best Regards,
Christian
Zdenek Dvorak wrote:
> Hello,
>
>
>>This patch provides an option, -f[no-]invert-ivs, that allows a loop
>>exit to be tested against zero. This is very useful for architectures
>>having a decrement and test instruction.
>
>
> we already have this optimization, see loop-doloop.c. You should find
> out why it does not work for you on sh. Nevertheless, some more comments:
>
>
>>Also, this optimisation exhibited a bug with the initialization of the
>>number of iterations in loop-iv.c:iv_number_of_iterations that was
>>handling the difference between pointers as a unsigned entity.
>
>
> That is correct, any differences computed in iv_number_of_iterations are
> unsigned.
>
>
>>as such
>>the logical right shift was losing the sign bit. This case happened with
>>a loop like
>>while (end > start) with an initial value of start > end.
>
>
> You need to check that noloop_assumptions is false before using
> the result of iv_number_of_iterations. I.e.,
>
>
>>In this case
>>the loop's number of iterations should be negative. To fix it I force
>>the desc->signed_p to one when making a difference between two pointers
>>and use a div instead of udiv. The code is less optimized but should be
>>safe.
>
>
> this change is wrong.
>
>
>> * loop-iv.c (iv_number_of_iterations): Make diffs between pointers
>> signed.
>> (exit_on_zero_cond): New function.
>> (need_guarded_loop): New function.
>> (may_invert_loop): New function.
>> (invert_loops): New function.
>
>
> New passes should be put to separate files.
>
>
>>+ for (i = 0; i < loop->num_nodes; i++)
>>+ {
>>+ basic_block bb;
>>+
>>+ bb = bbs[i];
>>+
>>+ /* Find the first conditional jump in the loop that depends on an iv. */
>
>
> You would probably want to check here whether there is a loop exit edge
> from this bb, here.
>
>
>>+ cond = get_condition (BB_END (bb), &at, false, false);
>>+ if (cond)
>>+ {
>>+ /* we want only the iv used as condition */
>>+ for (i = 0; i < 2; i++)
>>+ {
>>+ rtx op = XEXP (cond, i);
>>+
>>+ if (!CONSTANT_P (op) && iv_analyze_biv (op, &iv)
>>+ && iv.step != const0_rtx && !iv.first_special)
>>+ {
>>+ edge_iterator ei;
>>+ edge e;
>>+
>>+ FOR_EACH_EDGE (e, ei, bb->succs)
>>+ {
>>+ basic_block bbe = e->dest;
>>+
>>+ /* if this is an exit jump, take it when new iv
>>+ reaches 0. */
>>+ if (LABEL_P (BB_HEAD (bbe))
>>+ && BB_HEAD (bbe) == JUMP_LABEL (BB_END (bb)))
>>+ {
>>+ *edgep = e;
>>+ return cond;
>>+ }
>
>
> This is weird, I am not quite sure what are you trying to achieve. If
> you are trying to find the edge taken when the condition is true, you
> should look for the edge without EDGE_FALLTHRU flag.
>
>
>>+/* Check if the number of iterations that will be decremented could be negative
>>+ and thus the first decrement and test would miss the first exit. */
>>+
>>+static bool
>>+need_guarded_loop (struct loop *loop, rtx cond)
>>+{
>>+ struct niter_desc *desc;
>>+ enum rtx_code code = GET_CODE (cond);
>>+
>>+ desc = get_simple_loop_desc (loop);
>>+
>>+ if (CONSTANT_P (desc->niter_expr) || code == EQ || code == NE)
>>+ return false;
>>+
>>+ return true;
>>+}
>
>
> You want to check desc->noloop_assumptions here, instead.
>
> Zdenek
>
More information about the Gcc-patches
mailing list