Bug 21332 - [4.1 Regression] -ftree-vrp makes a loop doesn't execute a body
Summary: [4.1 Regression] -ftree-vrp makes a loop doesn't execute a body
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.1.0
: P1 critical
Target Milestone: 4.1.0
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on: 18373
Blocks:
  Show dependency treegraph
 
Reported: 2005-05-02 10:24 UTC by akr
Modified: 2005-06-02 03:06 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-05-02 11:59:50


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description akr 2005-05-02 10:24:28 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
Comment 1 Andrew Pinski 2005-05-02 11:59:50 UTC
Confirmed, this is a VRP problem.
Comment 2 Serge Belyshev 2005-05-02 12:06:38 UTC
// 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;
}
Comment 3 Steven Bosscher 2005-05-17 08:14:51 UTC
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... 
Comment 4 Steven Bosscher 2005-05-25 15:05:22 UTC
For the record. 
 
http://gcc.gnu.org/ml/gcc-patches/2005-05/msg01805.html 
Comment 5 CVS Commits 2005-06-02 02:57:44 UTC
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

Comment 6 Diego Novillo 2005-06-02 03:06:17 UTC
Fixed.  http://gcc.gnu.org/ml/gcc-patches/2005-06/msg00127.html