Hi,
For now set_autoinc_for_original_candidates only searches auto-inc uses
before candidate's increment, causing pre-increment opportunities missed for
original candidates.  This is a straightforward fix by searching after
candidate's increment too.
The patch also includes a test case to illustrate the problem.  Without the
patch, assembly of the test is:
foo:
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        movw    r3, #:lower16:__ctype_ptr__
        ldrb    r2, [r0]        @ zero_extendqisi2
        movt    r3, #:upper16:__ctype_ptr__
        ldr     r1, [r3]
        adds    r3, r1, r2
        ldrb    r3, [r3, #1]    @ zero_extendqisi2
        lsls    r3, r3, #29
        bmi     .L2
        adds    r3, r0, #1
.L3:
        mov     r0, r3
        adds    r3, r3, #1
        ldrb    r2, [r0]        @ zero_extendqisi2
        add     r2, r2, r1
        ldrb    r2, [r2, #1]    @ zero_extendqisi2
        lsls    r2, r2, #29
        bpl     .L3
.L2:
        bx      lr
        .size   foo, .-foo

Which can be optimized into below:
foo:
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        movw    r3, #:lower16:__ctype_ptr__
        ldrb    r1, [r0]        @ zero_extendqisi2
        movt    r3, #:upper16:__ctype_ptr__
        ldr     r2, [r3]
        adds    r3, r2, r1
        ldrb    r3, [r3, #1]    @ zero_extendqisi2
        lsls    r1, r3, #29
        bmi     .L2
.L3:
        ldrb    r3, [r0, #1]!   @ zero_extendqisi2
        add     r3, r3, r2
        ldrb    r3, [r3, #1]    @ zero_extendqisi2
        lsls    r3, r3, #29
        bpl     .L3
.L2:
        bx      lr
        .size   foo, .-foo

Bootstrapped and tested on arm a15, is it OK?

Thanks.
bin

2013-09-02  Bin Cheng  <bin.ch...@arm.com>

        * tree-ssa-loop-ivopts.c (set_autoinc_for_original_candidates):
        Find auto-increment use both before and after candidate.

gcc/testsuite/ChangeLog
2013-09-02  Bin Cheng  <bin.ch...@arm.com>

        * gcc.target/arm/ivopts-orig_biv-inc.c: New test.
Index: gcc/testsuite/gcc.target/arm/ivopts-orig_biv-inc.c
===================================================================
--- gcc/testsuite/gcc.target/arm/ivopts-orig_biv-inc.c  (revision 0)
+++ gcc/testsuite/gcc.target/arm/ivopts-orig_biv-inc.c  (revision 0)
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
+/* { dg-skip-if "" { arm_thumb1 } } */
+
+extern char *__ctype_ptr__;
+
+unsigned char * foo(unsigned char *ReadPtr)
+{
+
+ unsigned char c;
+
+ while (!(((__ctype_ptr__+sizeof(""[*ReadPtr]))[(int)(*ReadPtr)])&04) == 
(!(0)))
+  ReadPtr++;
+
+ return ReadPtr;
+}
+
+/* { dg-final { scan-tree-dump-times "original biv" 2 "ivopts"} } */
+/* { dg-final { cleanup-tree-dump "ivopts" } } */
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c  (revision 200774)
+++ gcc/tree-ssa-loop-ivopts.c  (working copy)
@@ -4876,22 +4876,36 @@ set_autoinc_for_original_candidates (struct ivopts
   for (i = 0; i < n_iv_cands (data); i++)
     {
       struct iv_cand *cand = iv_cand (data, i);
-      struct iv_use *closest = NULL;
+      struct iv_use *closest_before = NULL;
+      struct iv_use *closest_after = NULL;
       if (cand->pos != IP_ORIGINAL)
        continue;
+
       for (j = 0; j < n_iv_uses (data); j++)
        {
          struct iv_use *use = iv_use (data, j);
          unsigned uid = gimple_uid (use->stmt);
-         if (gimple_bb (use->stmt) != gimple_bb (cand->incremented_at)
-             || uid > gimple_uid (cand->incremented_at))
+
+         if (gimple_bb (use->stmt) != gimple_bb (cand->incremented_at))
            continue;
-         if (closest == NULL || uid > gimple_uid (closest->stmt))
-           closest = use;
+
+         if (uid < gimple_uid (cand->incremented_at)
+             && (closest_before == NULL
+                 || uid > gimple_uid (closest_before->stmt)))
+           closest_before = use;
+
+         if (uid > gimple_uid (cand->incremented_at)
+             && (closest_after == NULL
+                 || uid < gimple_uid (closest_after->stmt)))
+           closest_after = use;
        }
-      if (closest == NULL || !autoinc_possible_for_pair (data, closest, cand))
-       continue;
-      cand->ainc_use = closest;
+
+      if (closest_before != NULL
+         && autoinc_possible_for_pair (data, closest_before, cand))
+       cand->ainc_use = closest_before;
+      else if (closest_after != NULL
+              && autoinc_possible_for_pair (data, closest_after, cand))
+       cand->ainc_use = closest_after;
     }
 }
 

Reply via email to