Bug 79286 - [7 Regression] ira and lra wrong code at -O2 and -Os on i686-linux
Summary: [7 Regression] ira and lra wrong code at -O2 and -Os on i686-linux
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 7.0
: P1 normal
Target Milestone: 7.0
Assignee: Alan Modra
URL: https://gcc.gnu.org/ml/gcc-patches/20...
Keywords: patch, wrong-code
Depends on:
Blocks:
 
Reported: 2017-01-30 16:26 UTC by Zhendong Su
Modified: 2017-05-16 03:22 UTC (History)
4 users (show)

See Also:
Host:
Target: i?86-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-01-30 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Zhendong Su 2017-01-30 16:26:15 UTC
This seems to be a recent regression. 

$ gcc-trunk -v
Using built-in specs.
COLLECT_GCC=gcc-trunk
COLLECT_LTO_WRAPPER=/usr/local/gcc-trunk/libexec/gcc/x86_64-pc-linux-gnu/7.0.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc-source-trunk/configure --enable-languages=c,c++,lto --prefix=/usr/local/gcc-trunk --disable-bootstrap
Thread model: posix
gcc version 7.0.1 20170130 (experimental) [trunk revision 245020] (GCC)
$
$ gcc-trunk -m32 -O2 small.c; ./a.out
$ gcc-trunk -m64 -O3 small.c; ./a.out
$
$ gcc-trunk -m32 -O3 small.c
$ ./a.out
Segmentation fault (core dumped)
$


---------------------------------------------


int printf (const char *, ...);

int a[6], b, c, d, e, f, g, h;
static int i[][8] = { { 0 } };

void fn1 (int l)
{ 
  c = (c & 5) ^ a[(c ^ l) & 5];
}

void fn2 ()
{ 
  fn1 (e >> 5);
  fn1 (e >> 6 & 5);
  c = (c & 5) ^ a[(c ^ 5) & 5];
  fn1 (e >> 2 & 5);
  fn1 (e & 5);
  fn1 (e >> 28 & 5);
}

void fn3 ()
{ 
  int k;
  for (; g < 4; g++)
    { 
      while (d)
        { 
          fn2 ();
          if (k)
            printf ("%d\n", k);
        }
      while (f)
        while (h++)
          k = i[300000000000000000][0];
      while (b)
        while (1)
          d++;
    }
}

int main ()
{ 
  fn3 ();
  return 0;
}
Comment 1 Martin Liška 2017-01-30 22:23:39 UTC
Confirmed, started with r239357.
Comment 2 Martin Liška 2017-01-31 07:07:05 UTC
Reducing the test-case bit more:

$ int a = 0, c = 0;
static int d[][8] = {};

int main ()
{
  int e;
  for (int b = 0; b < 4; b++)
    {
      __builtin_printf ("%d\n", b, e);
      while (a && c++)
	e = d[300000000000000000][0];
    }

  return 0;
}

Problem is that we segfault here:

   │0x8048448 <main+13>             push   %ebx
   │0x8048449 <main+14>             push   %ecx
   │0x804844a <main+15>             mov    $0x0,%ebx
   │0x804844f <main+20>             jmp    0x8048459 <main+30>
   │0x8048451 <main+22>             add    $0x1,%ebx
   │0x8048454 <main+25>             cmp    $0x4,%ebx
   │0x8048457 <main+28>             je     0x804849f <main+100>
   │0x8048459 <main+30>             sub    $0x4,%esp
  >│0x804845c <main+33>             pushl  0x1bc48534

which is I guess d[300000000000000000][0], which is a dead-code that is placed before the printf call first time in 273r.ira:

...
(insn 8 7 9 3 (set (mem:SI (pre_dec:SI (reg/f:SI 7 sp)) [1  S4 A32])
        (mem/u:SI (const:SI (plus:SI (symbol_ref:SI ("d") [flags 0x2]  <var_decl 0x7fc764859f30 d>)
                    (const_int 331350016 [0x13c00000]))) [1 d+331350016 S4 A32])) "tc.c":9 58 {*pushsi2}
     (expr_list:REG_ARGS_SIZE (const_int 8 [0x8])
        (nil)))
(insn 9 8 10 3 (set (mem:SI (pre_dec:SI (reg/f:SI 7 sp)) [1  S4 A32])
        (reg/v:SI 88 [ b ])) "tc.c":9 58 {*pushsi2}
     (expr_list:REG_ARGS_SIZE (const_int 12 [0xc])
        (nil)))
(insn 10 9 11 3 (set (mem/f:SI (pre_dec:SI (reg/f:SI 7 sp)) [2  S4 A32])
        (symbol_ref/f:SI ("*.LC0") [flags 0x2]  <var_decl 0x7fc76322eab0 *.LC0>)) "tc.c":9 58 {*pushsi2}
     (expr_list:REG_ARGS_SIZE (const_int 16 [0x10])
        (nil)))
(call_insn 11 10 12 3 (set (reg:SI 0 ax)
        (call (mem:QI (symbol_ref:SI ("printf") [flags 0x41]  <function_decl 0x7fc76318be00 __builtin_printf>) [0 __builtin_printf S1 A8])
            (const_int 16 [0x10]))) "tc.c":9 663 {*call_value}
     (expr_list:REG_UNUSED (reg:SI 0 ax)
        (nil))
    (nil))

That points to a different commit, I'll bisect that.
Comment 3 Richard Biener 2017-01-31 08:25:39 UTC
Mine (looks like a latent issue though).
Comment 4 Martin Liška 2017-01-31 08:37:24 UTC
My small test-case started to segfault with r235660.
Comment 5 Richard Biener 2017-01-31 09:04:21 UTC
Unassigning then.
Comment 6 Alan Modra 2017-02-02 00:37:15 UTC
The testcase in comment #2 fails with x86 -m32 -Os even after fixing the ira failure, due to lra doing
"Changing pseudo 89 in operand 1 of insn 9 on equiv [const(`d'+0x13c00000)]"
This puts the load of d[300...0][0] before the printf, just like the ira bug.
The -Os failure is a regression from gcc-3.4
Comment 7 Jeffrey A. Law 2017-02-16 22:57:22 UTC
Author: law
Date: Thu Feb 16 22:56:51 2017
New Revision: 245521

URL: https://gcc.gnu.org/viewcvs?rev=245521&root=gcc&view=rev
Log:
2017-02-16  Alan Modra  <amodra@gmail.com>

	PR rtl-optimization/79286
	* ira.c (def_dominates_uses): New function.
	(update_equiv_regs): Don't create an equivalence for insns that
	may trap where the register def does not dominate the use.

	* gcc.c-torture/execute/pr79286.c: New.

Added:
    trunk/gcc/testsuite/gcc.c-torture/execute/pr79286.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/ira.c
    trunk/gcc/testsuite/ChangeLog
Comment 8 Jeffrey A. Law 2017-02-16 22:59:19 UTC
Fixed by Alan's patch on the trunk.
Comment 9 Dominique d'Humieres 2017-02-21 19:14:19 UTC
See https://gcc.gnu.org/ml/gcc-patches/2017-02/msg01172.html.
Comment 10 Jeffrey A. Law 2017-02-24 15:36:42 UTC
Author: law
Date: Fri Feb 24 15:36:10 2017
New Revision: 245714

URL: https://gcc.gnu.org/viewcvs?rev=245714&root=gcc&view=rev
Log:
	PR rtl-optimizatoin/79286
	* ira.c (update_equiv_regs): Drop may_trap_p exception to
	dominance test.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/ira.c
Comment 11 Jeffrey A. Law 2017-02-24 15:42:15 UTC
Darwin issues should be fixed now too.
Comment 12 Bernd Edlinger 2017-02-25 08:02:09 UTC
Hi Jeff,

it looks like it is possible that may_trap_p returns
always wrong information if -m32 -fPIC is used.

What do you think about this?

Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	(revision 245714)
+++ gcc/rtlanal.c	(working copy)
@@ -645,8 +645,23 @@
     case PLUS:
       /* An address is assumed not to trap if:
          - it is the pic register plus a constant.  */
-      if (XEXP (x, 0) == pic_offset_table_rtx && CONSTANT_P (XEXP (x, 1)))
-	return 0;
+      if (XEXP (x, 0) == pic_offset_table_rtx
+	  && GET_CODE (XEXP (x, 1)) == CONST)
+	{
+	  x = XEXP (XEXP (x, 1), 0);
+	  if (GET_CODE (x) == UNSPEC
+	      && GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF)
+	    return rtx_addr_can_trap_p_1(XVECEXP (x, 0, 0),
+					 offset, size, mode, unaligned_mems);
+	  if (GET_CODE (x) == PLUS
+	      && GET_CODE (XEXP (x, 0)) == UNSPEC
+	      && GET_CODE (XVECEXP (XEXP (x, 0), 0, 0)) == SYMBOL_REF
+	      && CONST_INT_P (XEXP (x, 1)))
+	    return rtx_addr_can_trap_p_1(XVECEXP (XEXP (x, 0), 0, 0),
+					 offset + INTVAL (XEXP (x, 1)),
+					 size, mode, unaligned_mems);
+	  return 1;
+	}
 
       /* - or it is an address that can't trap plus a constant integer.  */
       if (CONST_INT_P (XEXP (x, 1))
Comment 13 Alan Modra 2017-05-16 03:22:49 UTC
I think we're done here.