diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr48702.c | 47 | ||||
-rw-r--r-- | gcc/tree-ssa-address.c | 7 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 9 |
5 files changed, 70 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f4047ef..ed1dda3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2011-05-26 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/48702 + * tree-ssa-address.c (create_mem_ref_raw): Create MEM_REFs + only when we know the base address is within bounds. + * tree-ssa-alias.c (indirect_ref_may_alias_decl_p): Do not + assume the base address of TARGET_MEM_REFs is in bounds. + 2011-05-26 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> PR target/49099 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5acf08e..089406d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-05-26 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/48702 + * gcc.dg/torture/pr48702.c: New testcase. + 2011-05-26 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> PR gcov-profile/48845 diff --git a/gcc/testsuite/gcc.dg/torture/pr48702.c b/gcc/testsuite/gcc.dg/torture/pr48702.c new file mode 100644 index 0000000..1ec371d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr48702.c @@ -0,0 +1,47 @@ +/* { dg-do run } */ + +extern void abort (void); + +#define LEN 4 + +static inline void unpack(int array[LEN]) +{ + int ii, val; + val = 1; + for (ii = 0; ii < LEN; ii++) { + array[ii] = val % 2; + val = val / 2; + } +} + +static inline int pack(int array[LEN]) +{ + int ans, ii; + ans = 0; + for (ii = LEN-1; ii >= 0; ii--) { + ans = 2 * ans + array[ii]; + } + return ans; +} + +int __attribute__((noinline)) +foo() +{ + int temp, ans; + int array[LEN]; + unpack(array); + temp = array[0]; + array[0] = array[2]; + array[2] = temp; + ans = pack(array); + return ans; +} + +int main(void) +{ + int val; + val = foo(); + if (val != 4) + abort (); + return 0; +} diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c index 07d1d4d..2e6eabc 100644 --- a/gcc/tree-ssa-address.c +++ b/gcc/tree-ssa-address.c @@ -361,8 +361,11 @@ create_mem_ref_raw (tree type, tree alias_ptr_type, struct mem_address *addr, index2 = addr->base; } - /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF. */ - if (alias_ptr_type + /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF. + ??? As IVOPTs does not follow restrictions to where the base + pointer may point to create a MEM_REF only if we know that + base is valid. */ + if (TREE_CODE (base) == ADDR_EXPR && (!index2 || integer_zerop (index2)) && (!addr->index || integer_zerop (addr->index))) return fold_build2 (MEM_REF, type, base, addr->offset); diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 3656b39..02b3ca0 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -745,11 +745,12 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, the pointer access is beyond the extent of the variable access. (the pointer base cannot validly point to an offset less than zero of the variable). - They also cannot alias if the pointer may not point to the decl. */ - if ((TREE_CODE (base1) != TARGET_MEM_REF - || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1))) + ??? IVOPTs creates bases that do not honor this restriction, + so do not apply this optimization for TARGET_MEM_REFs. */ + if (TREE_CODE (base1) != TARGET_MEM_REF && !ranges_overlap_p (MAX (0, offset1p), -1, offset2p, max_size2)) return false; + /* They also cannot alias if the pointer may not point to the decl. */ if (!ptr_deref_may_alias_decl_p (ptr1, base2)) return false; @@ -799,7 +800,7 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, if (!ref2) return true; - /* If the decl is accressed via a MEM_REF, reconstruct the base + /* If the decl is accessed via a MEM_REF, reconstruct the base we can use for TBAA and an appropriately adjusted offset. */ dbase2 = ref2; while (handled_component_p (dbase2)) |