GCC Bugzilla – Bug 21332
[4.1 Regression] -ftree-vrp makes a loop doesn't execute a body
Last modified: 2005-06-02 03:06:17 UTC
4.1.0 20050502 (experimental) seems have a problem with optimization. The for loop in the else clause in the main doesn't execute the loop body. % cat t.c extern int printf (__const char *__restrict __format, ...); int f() { return -2; } int main(int argc, char **argv) { int c = f(); long i; if (c > 0) { for (i=0;i<c;i++) { f(); } } else { c = -c; printf("beg %d\n", c); for (i=0;i<c;i++) { printf("%d\n", i); } printf("end %d\n", i); } return 0; } % gcc -v -O2 t.c Using built-in specs. Target: i686-pc-linux-gnu Configured with: ../gcc/configure --prefix=/home/src/gcc/trunk --enable-languages=c Thread model: posix gcc version 4.1.0 20050502 (experimental) /home/src/gcc/trunk/libexec/gcc/i686-pc-linux-gnu/4.1.0/cc1 -quiet -v t.c -quiet -dumpbase t.c -mtune=pentiumpro -auxbase t -O2 -version -o /tmp/cc6LaTqE.s ignoring nonexistent directory "/home/src/gcc/trunk/lib/gcc/i686-pc-linux-gnu/4.1.0/../../../../i686-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/local/include /home/src/gcc/trunk/include /home/src/gcc/trunk/lib/gcc/i686-pc-linux-gnu/4.1.0/include /usr/include End of search list. GNU C version 4.1.0 20050502 (experimental) (i686-pc-linux-gnu) compiled by GNU C version 4.1.0 20050502 (experimental). GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 as -V -Qy -o /tmp/cc6jWNoa.o /tmp/cc6LaTqE.s GNU assembler version 2.15 (i386-linux) using BFD version 2.15 /home/src/gcc/trunk/libexec/gcc/i686-pc-linux-gnu/4.1.0/collect2 --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /home/src/gcc/trunk/lib/gcc/i686-pc-linux-gnu/4.1.0/crtbegin.o -L/home/src/gcc/trunk/lib/gcc/i686-pc-linux-gnu/4.1.0 -L/home/src/gcc/trunk/lib/gcc/i686-pc-linux-gnu/4.1.0/../../.. /tmp/cc6jWNoa.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /home/src/gcc/trunk/lib/gcc/i686-pc-linux-gnu/4.1.0/crtend.o /usr/lib/crtn.o % ./a.out beg 2 end 0 It works well without optimization as follows. % gcc t.c % ./a.out beg 2 0 1 end 2
Confirmed, this is a VRP problem.
// this testcase fails also on amd64: extern void abort (void); int f () { return -1; } int main () { int b, c, i; b = 0; c = f (); if (c <= 0) { c = -c; for (i = 0; i < c; i++) b = 1; if (!b) abort (); } return 0; }
SSA form after inserting ASSERT_EXPRs main () { int i; int c; int b; int D.1576; <bb 0>: c_4 = f (); if (c_4 <= 0) goto <L0>; else goto <L8>; <L0>:; c_8 = ASSERT_EXPR <c_4, c_4 <= 0>; c_7 = -c_8; goto <bb 3> (<L2>); <L1>:; i_5 = ASSERT_EXPR <i_2, i_2 < c_7>; i_10 = i_5 + 1; # i_2 = PHI <0(1), i_10(2)>; # b_1 = PHI <0(1), 1(2)>; <L2>:; if (i_2 < c_7) goto <L1>; else goto <L3>; <L3>:; i_9 = ASSERT_EXPR <i_2, i_2 >= c_7>; if (b_1 == 0) goto <L4>; else goto <L5>; <L4>:; abort (); <L8>:; c_3 = ASSERT_EXPR <c_4, c_4 > 0>; <L5>:; return 0; } ... Visiting statement: c_8 = ASSERT_EXPR <c_4, c_4 <= 0>; (analyze_scalar_evolution (loop_nb = 0) (scalar = c_8) (get_scalar_evolution (scalar = c_8) (scalar_evolution = )) (analyze_scalar_evolution (loop_nb = 0) (scalar = c_4) (get_scalar_evolution (scalar = c_4) (scalar_evolution = c_4)) (set_scalar_evolution (scalar = c_4) (scalar_evolution = c_4)) ) (set_scalar_evolution (scalar = c_8) (scalar_evolution = c_4)) ) Found new range [-2147483648, 0] for c_8 Visiting statement: c_7 = -c_8; (analyze_scalar_evolution (loop_nb = 0) (scalar = c_7) (get_scalar_evolution (scalar = c_7) (scalar_evolution = )) (analyze_scalar_evolution (loop_nb = 0) (scalar = c_8) (get_scalar_evolution (scalar = c_8) (scalar_evolution = c_4)) (set_scalar_evolution (scalar = c_8) (scalar_evolution = c_4)) ) (set_scalar_evolution (scalar = c_7) (scalar_evolution = -c_4)) ) Found new range [-080000000, 0] for c_7 // !?!?!?!?! ... Value ranges after VRP: b_1: [0, 0] i_2: [0, 0] c_3: [1, 2147483647] c_4: VARYING <retval>_6: VARYING c_7: [-080000000, 0] c_8: [-2147483648, 0] i_9: [c_7, 2147483647] Function after VRP: main () { int i; int c; int b; int D.1576; <bb 0>: c_4 = f (); if (c_4 <= 0) goto <L0>; else goto <L8>; <L0>:; c_8 = c_4; c_7 = -c_8; # i_2 = PHI <0(1)>; # b_1 = PHI <0(1)>; <L2>:; i_9 = i_2; abort (); <L8>:; c_3 = c_4; return 0; } This may actually be a scev bug...
For the record. http://gcc.gnu.org/ml/gcc-patches/2005-05/msg01805.html
Subject: Bug 21332 CVSROOT: /cvs/gcc Module name: gcc Changes by: dnovillo@gcc.gnu.org 2005-06-02 02:57:15 Modified files: gcc : ChangeLog fold-const.c tree-flow.h tree-ssa-ccp.c tree-ssa-copy.c tree-ssa-propagate.c tree-ssa-propagate.h tree-vrp.c tree.h gcc/testsuite : ChangeLog gcc/testsuite/gcc.dg/tree-ssa: pr14841.c pr21658.c Added files: gcc/testsuite/gcc.dg/tree-ssa: pr14341.c pr20701.c pr21029.c pr21086.c pr21090.c pr21332.c pr21458.c vrp01.c vrp02.c vrp03.c vrp04.c vrp05.c vrp06.c vrp07.c vrp08.c vrp09.c vrp10.c vrp11.c vrp12.c vrp13.c Log message: 2005-06-01 Diego Novillo <dnovillo@redhat.com> PR 14341, PR 21332, PR 20701, PR 21029, PR 21086, PR 21090 PR 21289, PR 21348, PR 21367, PR 21368, PR 21458. * fold-const.c (invert_tree_comparison): Make extern. * tree-flow.h (enum value_range_type): Move to tree-ssa-propagate. (struct value_range_def): Limewise. (get_value_range): Remove. (dump_value_range): Remove. (dump_all_value_ranges): Remove. (debug_all_value_ranges): Remove. (vrp_evaluate_conditional): Declare. * tree-ssa-propagate.c (struct prop_stats_d): Add field num_pred_folded. (substitute_and_fold): Add argument use_ranges_p. Update all callers. If use_ranges_p is true, call fold_predicate_in to fold predicates using range information. Ignore ASSERT_EXPRs. Change debugging output to only show statements that have been folded. (replace_phi_args_in): Move debugging output code from substitute and fold. (fold_predicate_in): New local function. * tree-ssa-propagate.h (enum value_range_type): Move from tree-flow.h. (struct value_range_d): Likewise. Add field 'equiv'. (value_range_t): Rename from value_range. * tree-vrp.c (found_in_subgraph): Rename from found. (get_opposite_operand): Remove. (struct assert_locus_d): Declare. (assert_locus_t): Declare. (need_assert_for): Declare. (asserts_for): Declare. (blocks_visited): Declare. (vr_value): Declare. (set_value_range): Add argument 'equiv'. Don't drop to VARYING ranges that cover all values in the type. Make deep copy of equivalence set 'equiv'. (copy_value_range): New local function. (set_value_range_to_undefined): New local function. (compare_values): Return -2 if either value has overflowed. (range_includes_zero_p): New local function. (extract_range_from_assert): Flip the predicate code if the name being asserted is on the RHS of the predicate. Avoid creating unnecessary symbolic ranges if the comparison includes another name with a known numeric range. Update the equivalnce set of the new range when asserting EQ_EXPR predicates. (extract_range_from_ssa_name): Update the equivalence set of the new range with VAR. (extract_range_from_binary_expr): Also handle TRUTH_*_EXPR. If -fwrapv is used, set the resulting range to VARYING if the operation overflows. Otherwise, use TYPE_MIN_VALUE and TYPE_MAX_VALUE to represent -INF and +INF. Fix handling of *_DIV_EXPR. (extract_range_from_unary_expr): Handle MINUS_EXPR and ABS_EXPR properly by switching the range around if necessary. (extract_range_from_comparison): New local function. (extract_range_from_expr): Call it. (adjust_range_with_scev): Do not adjust the range if using wrapping arithmetic (-fwrapv). (dump_value_range): Also show equivalence set. Show -INF and +INF for TYPE_MIN_VALUE and TYPE_MAX_VALUE. (build_assert_expr_for): Also build ASSERT_EXPR for EQ_EXPR. (infer_value_range): Change return value to bool. Add arguments 'comp_code_p' and 'val_p'. Do not attempt to infer ranges from statements that may throw. Store the comparison code in comp_code_p. Store the other operand to be used in the predicate in val_p. (dump_asserts_for): New. (debug_asserts_for): New. (dump_all_asserts): New. (debug_all_asserts): New. (register_new_assert_for): New. (register_edge_assert_for): New. (find_conditional_asserts): New. (find_assert_locations): New. (process_assert_insertions_for): New. (process_assert_insertions): New. (insert_range_assertions): Initialize found_in_subgraph, blocks_visited, need_assert_for and asserts_for. Call find_assert_locations and process_assert_insertions. (remove_range_assertions): Add more documentation. (vrp_initialize): Change return type to void. Do not try to guess if running VRP is worth it. (compare_name_with_value): New. (compare_names): New. (vrp_evaluate_conditional): Add argument 'use_equiv_p'. If use_equiv_p is true, call compare_names and compare_name_with_value to compare all the ranges for every name in the equivalence set of the predicate operands. Update all callers. (vrp_meet): Try harder not to derive a VARYING range. If two values meet, the resulting equivalence set is the intersection of the two equivalence sets. (vrp_visit_phi_node): Call copy_value_range to get the current range information of the LHS. (vrp_finalize): Create a value vector representing all the names that ended up with exactly one value in their range. Call substitute_and_fold. (execute_vrp): Document equivalence sets in ranges. * tree.h (SSA_NAME_VALUE_RANGE): Remove. (struct tree_ssa_name): Remove field value_range. (invert_tree_comparison): Declare. testsuite/ChangeLog 2005-06-01 Diego Novillo <dnovillo@redhat.com> PR 14341, PR 21332, PR 20701, PR 21086, PR 21090 PR 21289, PR 21348, PR 21367, PR 21368, PR 21458. * gcc.dg/tree-ssa/pr14341.c: New test. * gcc.dg/tree-ssa/pr14841.c: New test. * gcc.dg/tree-ssa/pr20701.c: New test. * gcc.dg/tree-ssa/pr21086.c: New test. * gcc.dg/tree-ssa/pr21090.c: New test. * gcc.dg/tree-ssa/pr21332.c: New test. * gcc.dg/tree-ssa/pr21458.c: New test. * gcc.dg/tree-ssa/pr21658.c: New test. * gcc.dg/tree-ssa/vrp01.c: New test. * gcc.dg/tree-ssa/vrp02.c: New test. * gcc.dg/tree-ssa/vrp03.c: New test. * gcc.dg/tree-ssa/vrp04.c: New test. * gcc.dg/tree-ssa/vrp05.c: New test. * gcc.dg/tree-ssa/vrp06.c: New test. * gcc.dg/tree-ssa/vrp07.c: New test. * gcc.dg/tree-ssa/vrp08.c: New test. * gcc.dg/tree-ssa/vrp09.c: New test. * gcc.dg/tree-ssa/vrp10.c: New test. * gcc.dg/tree-ssa/vrp11.c: New test. * gcc.dg/tree-ssa/vrp12.c: New test. * gcc.dg/tree-ssa/vrp13.c: New test. 2005-06-01 Alexandre Oliva <aoliva@redhat.com> PR 21029 * gcc.dg/tree-ssa/pr21029.c: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.8989&r2=2.8990 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/fold-const.c.diff?cvsroot=gcc&r1=1.589&r2=1.590 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-flow.h.diff?cvsroot=gcc&r1=2.114&r2=2.115 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-ccp.c.diff?cvsroot=gcc&r1=2.77&r2=2.78 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-copy.c.diff?cvsroot=gcc&r1=2.32&r2=2.33 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-propagate.c.diff?cvsroot=gcc&r1=2.22&r2=2.23 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-propagate.h.diff?cvsroot=gcc&r1=2.3&r2=2.4 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-vrp.c.diff?cvsroot=gcc&r1=2.18&r2=2.19 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree.h.diff?cvsroot=gcc&r1=1.732&r2=1.733 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.5574&r2=1.5575 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr14341.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21029.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21090.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21332.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp03.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp06.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp10.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp11.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp12.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp13.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c.diff?cvsroot=gcc&r1=1.1&r2=1.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21658.c.diff?cvsroot=gcc&r1=1.1&r2=1.2
Fixed. http://gcc.gnu.org/ml/gcc-patches/2005-06/msg00127.html