Bug 47337 - [4.6 Regression] Wrong RTL dce of calls
Summary: [4.6 Regression] Wrong RTL dce of calls
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 4.6.0
: P1 normal
Target Milestone: 4.6.0
Assignee: Jakub Jelinek
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2011-01-18 06:29 UTC by John Regehr
Modified: 2011-01-19 15:15 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2011-01-18 09:22:11


Attachments
gcc46-pr47337.patch (941 bytes, patch)
2011-01-18 09:58 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description John Regehr 2011-01-18 06:29:08 UTC
Valgrind reports some memory safety problems in the 'gcc -O3' execution.

regehr@home:~$ current-gcc -O2 small.c -o small
regehr@home:~$ ./small
g_6 = 0
regehr@home:~$ current-gcc -O3 small.c -o small
regehr@home:~$ ./small
g_6 = 134513352
regehr@home:~$ current-gcc -v
Using built-in specs.
COLLECT_GCC=current-gcc
COLLECT_LTO_WRAPPER=/mnt/z/z/compiler-install/gcc-r168941-install/libexec/gcc/i686-pc-linux-gnu/4.6.0/lto-wrapper
Target: i686-pc-linux-gnu
Configured with: ../configure --with-libelf=/usr/local --enable-lto --prefix=/mnt/z/z/compiler-install/gcc-r168941-install --program-prefix=r168941- --enable-languages=c,c++
Thread model: posix
gcc version 4.6.0 20110118 (experimental) (GCC) 
regehr@home:~$ cat small.c


static unsigned int crc32_tab[256];
static unsigned int crc32_context = 0;
static char g_4 = 0;
static int g_6 = 0;
static long long g_83 = 0;
static int *g_102 = &g_6;

int printf(const char *format, ...);
int strcmp(const char *s1, const char *s2);

static short div(long long p1, long long p2)
{
  return p1 / p2;
}

static char sub(char p1, char p2)
{
  return p1 - p2;
}

static int func_95(int p_96, int p_97)
{
  *g_102 = (p_97 != (short)(p_97 * 3));

  for (g_4 = 0; g_4 < 2; g_4++)
    {
    lbl_210:
      if (g_6)
        {
	  if (g_83)
            {
	      g_83 = 1;
            }
	  else
            {
	      return p_96;
            }
        }
      else
        {
	  g_6 = 1;
	  goto lbl_210;
        }
      g_102 = &g_6;
    }
  return p_96;
}

static void crc32(unsigned long long val, int flag)
{
  if (!flag) {
    crc32_context = crc32_tab[crc32_context & 1];
    crc32_context = crc32_tab[crc32_context & 1];
    crc32_context = crc32_tab[(crc32_context ^ (val & 1)) & 1];
    crc32_context = crc32_tab[(crc32_context ^ (val & 1)) & 1];
  }
}

int main(int argc, char* argv[])
{
  int print_hash_value = 0;
  unsigned int crc = 0;
  int l_338[8];
  int i, j;

  if (argc == 2 && strcmp(argv[1], "1") == 0)
    print_hash_value = 1;

  for (i = 0; i < 256; i++) {
    for (j = 8; j > 0; j--) {
      crc = 1;
    }
    crc32_tab[i] = crc;
  }
  for (i = 0; i < 8; i++)
    l_338[i] = 0;

  g_6 = sub(g_4, g_4);
  g_6 = func_95(g_4, 1 | div(l_338[0], 10));
  crc32(g_6, print_hash_value);
  crc32(g_83, print_hash_value);

  printf("g_6 = %d\n", g_6);
  return 0;
}
Comment 1 Jakub Jelinek 2011-01-18 09:04:46 UTC
Confirmed, goes away with -fno-partial-inlining, happens only with -m32.
From brief look at it it looks like a RTL DCE bug, it removes a __divdi3 call, but takes away with it also a needed unrelated store:
(insn 203 105 204 6 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
                (const_int 8 [0x8])) [0 S4 A32])
        (const_int 10 [0xa])) pr47337.c:14 64 {*movsi_internal}
     (nil))

(insn 204 203 205 6 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
                (const_int 12 [0xc])) [0 S4 A32])
        (const_int 0 [0])) pr47337.c:14 64 {*movsi_internal}
     (nil))

(insn 205 204 206 6 (set (mem:SI (reg/f:SI 7 sp) [0 S4 A32])
        (const_int 0 [0])) pr47337.c:14 64 {*movsi_internal}
     (nil))

(insn 206 205 190 6 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
                (const_int 4 [0x4])) [0 S4 A32])
        (const_int 0 [0])) pr47337.c:14 64 {*movsi_internal}
     (nil))

(insn 190 206 110 6 (set (mem/c:SI (plus:SI (reg/f:SI 7 sp)
                (const_int 28 [0x1c])) [5 S4 A32])
        (reg:SI 2 cx)) pr47337.c:14 64 {*movsi_internal}
     (expr_list:REG_DEAD (reg:SI 2 cx)
        (nil)))

(call_insn/u 110 190 179 6 (set (reg:DI 0 ax)
        (call (mem:QI (symbol_ref:SI ("__divdi3") [flags 0x41]) [0 S1 A8])
            (const_int 16 [0x10]))) pr47337.c:14 927 {*call_value_0}
     (expr_list:REG_UNUSED (reg:DI 0 ax)
        (expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
            (nil)))
    (expr_list:REG_DEP_TRUE (use (mem:DI (reg/f:SI 7 sp) [0 S8 A8]))
        (expr_list:REG_DEP_TRUE (use (mem:DI (plus:SI (reg/f:SI 7 sp)
                        (const_int 8 [0x8])) [0 S8 A8]))
            (nil))))

The sp+0x1c store shouldn't be deleted, but it is.
Comment 2 Jakub Jelinek 2011-01-18 09:58:04 UTC
Created attachment 23016 [details]
gcc46-pr47337.patch

Untested fix.  Thanks for the report.
Comment 3 Jakub Jelinek 2011-01-19 15:13:05 UTC
Author: jakub
Date: Wed Jan 19 15:13:01 2011
New Revision: 168997

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=168997
Log:
	PR rtl-optimization/47337
	* dce.c (check_argument_store): New function.
	(find_call_stack_args): Ignore debug insns.  Use check_argument_store.

	* gcc.c-torture/execute/pr47337.c: New test.

Added:
    trunk/gcc/testsuite/gcc.c-torture/execute/pr47337.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/dce.c
    trunk/gcc/testsuite/ChangeLog
Comment 4 Jakub Jelinek 2011-01-19 15:15:36 UTC
Fixed.