This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] sh, loop iv optim


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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]