Bug 18298 - [4.0 Regression] bad code from lim ssa pass with strcmp
Summary: [4.0 Regression] bad code from lim ssa pass with strcmp
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.0.0
: P3 normal
Target Milestone: 4.0.0
Assignee: Andrew Pinski
URL:
Keywords: alias, wrong-code
Depends on:
Blocks:
 
Reported: 2004-11-04 15:59 UTC by snyder
Modified: 2004-11-30 15:38 UTC (History)
2 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2004-11-04 16:06:10


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description snyder 2004-11-04 15:59:05 UTC

When i build the example below with -O1 or above, it goes into an infinite
loop:

$ g++ -o x -O1 x.cc
$ ./x
... doesn't exit 

At -O0, it exits as expected:


$ g++ -o x -O0 x.cc
$ ./x
$


Here's the code that's generated (eh-related labels removed for clarity).
As you can see, there's an obvious infinite loop...


main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$8, %esp
	andl	$-16, %esp
	subl	$16, %esp
	movzbl	s, %eax
	testb	%al, %al
	je	.L2
.L5:
	jmp	.L5     ; <-- infinite loop!
.L2:
	movb	%al, s
	movl	$0, %eax
	leave
	ret


The problem seems to be introduced in the `lim' ssa pass, where this
(from t44.loopinit):

int main() ()
{
  const unsigned char * prephitmp.3;
  const unsigned char * pretmp.2;
  const unsigned char * D.1593;
  const unsigned char D.1594;
  int D.1595;
  int D.1590;
  int D.1589;
  const char * str;
  int D.1578;
  bool D.1575;
  bool retval.0;
  int D.1588;

<bb 0>:
  pretmp.2_13 = (const unsigned char *) &s[0];
  goto <bb 2> (<L1>);

<L0>:;
  s[0] = 0;

  # prephitmp.3_14 = PHI <pretmp.2_13(0), D.1593_6(1)>;
<L1>:;
  D.1593_6 = pretmp.2_13;
  D.1594_3 = *D.1593_6;
  D.1595_12 = (int) D.1594_3;
  D.1590_4 = D.1595_12;
  if (D.1590_4 != 0) goto <L0>; else goto <L3>;

<L3>:;
  return 0;

}



gets transformed to this (from t45.lim):


int main() ()
{
  char lsm_tmp.4;
  const unsigned char * prephitmp.3;
  const unsigned char * pretmp.2;
  const unsigned char * D.1593;
  const unsigned char D.1594;
  int D.1595;
  int D.1590;
  int D.1589;
  const char * str;
  int D.1578;
  bool D.1575;
  bool retval.0;
  int D.1588;

<bb 0>:
  pretmp.2_13 = (const unsigned char *) &s[0];
  D.1593_6 = pretmp.2_13;
  D.1594_3 = *D.1593_6;
  D.1595_12 = (int) D.1594_3;
  D.1590_4 = D.1595_12;
  lsm_tmp.4_15 = s[0];
  goto <bb 2> (<L1>);

<L0>:;
  lsm_tmp.4_17 = 0;

  # lsm_tmp.4_18 = PHI <lsm_tmp.4_15(0), lsm_tmp.4_17(1)>;
  # prephitmp.3_14 = PHI <pretmp.2_13(0), D.1593_6(1)>;
<L1>:;
  if (D.1590_4 != 0) goto <L0>; else goto <L3>;

  # lsm_tmp.4_19 = PHI <lsm_tmp.4_18(2)>;
<L3>:;
  s[0] = lsm_tmp.4_19;
  return 0;

}


Note that the variable being tested at L1 (D.1590_4) never changes.


This feels like it may be related to bugs 17133/17425, but the patch
for that doesn't fix this.

Environment:
System: Linux karma 2.6.8.1 #20 Mon Sep 13 23:48:47 EDT 2004 i686 i686 i386 GNU/Linux
Architecture: i686

	<machine, os, target, libraries (multiple lines)>
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: /home/sss/gcc/gcc/configure --prefix=/usr/local/gcc --enable-threads=posix --enable-long-long --enable-languages=c,c++,f95

How-To-Repeat:

Compile and run with -O1 or above.
-------------------------------------------
extern "C" int strcmp (const char*, const char*);

char s[2048] = "a";

inline bool foo(const char *str) {
  return !strcmp(s,str);
}


int main() {
  while(!(foo(""))) {
    s[0] = '\0';
  }
  return 0;
}
-------------------------------------------
Comment 1 snyder 2004-11-04 15:59:05 UTC
Fix:
	<how to correct or work around the problem, if known (multiple lines)>
Comment 2 Andrew Pinski 2004-11-04 16:06:09 UTC
Confirmed, this is an aliasing problem:
  D.1589_6 = (const unsigned char *) &s[0];
  D.1590_3 = *D.1589_6;

There is no VUSE on the second statement.
Comment 3 Andrew Pinski 2004-11-04 18:04:51 UTC
The problem is that fold all builtins is not creating the operands on the statement, if you write the code 
as fab would create it is right.  I am looking into fixing the problem right now.
Comment 4 Andrew Pinski 2004-11-04 20:25:04 UTC
Adding a may_alias pass after fold all builtins makes this testcase works (I don't know if this is correct 
fix or not):
Index: tree-optimize.c
===============================================================
====
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 2.61
diff -u -p -r2.61 tree-optimize.c
--- tree-optimize.c	2 Nov 2004 00:23:04 -0000	2.61
+++ tree-optimize.c	4 Nov 2004 20:23:32 -0000
@@ -371,6 +371,7 @@ init_tree_optimization_passes (void)
   NEXT_PASS (pass_ccp);
   NEXT_PASS (pass_redundant_phi);
   NEXT_PASS (pass_fold_builtins);
+  NEXT_PASS (pass_may_alias);
   NEXT_PASS (pass_split_crit_edges);
   NEXT_PASS (pass_pre);
   NEXT_PASS (pass_loop);
Comment 5 Diego Novillo 2004-11-29 23:01:21 UTC
(In reply to comment #4)
> Adding a may_alias pass after fold all builtins makes this testcase works
> (I don't know if this is correct fix or not):
>
Unfortunately, it is.  It's a bit heavy handed for my taste, but we have little
choice.  Folding builtins has the potential of introducing almost arbitrary
GIMPLE code.  We don't have much control over what it can be generated.

For 4.1, I would like to convert the may_alias pass into a TODO so that it can
be triggered by passes that knowingly introduce new aliasing.  For now, your
patch is fine (provided you test it again and add a testcase).  Please add a
FIXME comment, as well.


Diego.
Comment 6 Andrew Pinski 2004-11-29 23:03:35 UTC
Mine, as my patch fixes it.
Comment 7 Andrew Pinski 2004-11-30 15:38:35 UTC
Fixed.
Comment 8 CVS Commits 2004-11-30 15:39:30 UTC
Subject: Bug 18298

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	pinskia@gcc.gnu.org	2004-11-30 15:38:45

Modified files:
	gcc            : ChangeLog tree-optimize.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/gcc.c-torture/execute: p18298.c 

Log message:
	2004-11-30  Andrew Pinski  <pinskia@physics.uc.edu>
	
	PR tree-opt/18298
	* tree-optimize.c (init_tree_optimization_passes): Add a may_alias
	pass right after fold builtins.
	2004-11-30  Andrew Pinski  <pinskia@physics.uc.edu>
	
	PR tree-opt/18298
	* gcc.c-torture/execute/p18298.c: New test.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.6650&r2=2.6651
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-optimize.c.diff?cvsroot=gcc&r1=2.64&r2=2.65
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4689&r2=1.4690
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.c-torture/execute/p18298.c.diff?cvsroot=gcc&r1=NONE&r2=1.1