This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][4.2] Fix PR32500, wrong code with VRP (number of iterations analysis)
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 4 Jul 2007 14:39:17 +0200 (CEST)
- Subject: [PATCH][4.2] Fix PR32500, wrong code with VRP (number of iterations analysis)
This fixes PR32500 where we incorrectly derive a number of iterations from
undefined conditions in a basic block that is not always executed. Fixed
by backporting from mainline the check that restricts this to blocks that
are always executed. I didn't backport the rewrite of number of
iterations analysis to still use them for a hint though.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the
4.2 branch, testcase added to trunk as well.
Richard.
2007-07-04 Richard Guenther <rguenther@suse.de>
PR tree-optimization/32500
* tree-ssa-loop-niter.c (infer_loop_bounds_from_undefined):
Only use basic blocks that are always executed to infer loop bounds.
* gcc.c-torture/execute/pr32500.c: New testcase.
Index: tree-ssa-loop-niter.c
===================================================================
*** tree-ssa-loop-niter.c (revision 126260)
--- tree-ssa-loop-niter.c (working copy)
*************** infer_loop_bounds_from_undefined (struct
*** 1747,1752 ****
--- 1747,1758 ----
{
bb = bbs[i];
+ /* If BB is not executed in each iteration of the loop, we cannot
+ use the operations in it to infer reliable upper bound on the
+ # of iterations of the loop. */
+ if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
+ continue;
+
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree stmt = bsi_stmt (bsi);
Index: testsuite/gcc.c-torture/execute/pr32500.c
===================================================================
*** testsuite/gcc.c-torture/execute/pr32500.c (revision 0)
--- testsuite/gcc.c-torture/execute/pr32500.c (revision 0)
***************
*** 0 ****
--- 1,26 ----
+ extern void abort(void);
+ extern void exit(int);
+ void foo(int) __attribute__((noinline));
+ void bar(void) __attribute__((noinline));
+
+ /* Make sure foo is not inlined or considered pure/const. */
+ int x;
+ void foo(int i) { x = i; }
+ void bar(void) { exit(0); }
+
+ int
+ main(int argc, char *argv[])
+ {
+ int i;
+ int numbers[4] = { 0xdead, 0xbeef, 0x1337, 0x4242 };
+
+ for (i = 1; i <= 12; i++) {
+ if (i <= 4)
+ foo(numbers[i]);
+ else if (i >= 7 && i <= 9)
+ bar();
+ }
+
+ abort();
+ }
+