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;
}
}