Bug 52731 - internal compiler error: in ia64_st_address_bypass_p, at config/ia64/ia64.c:9357
Summary: internal compiler error: in ia64_st_address_bypass_p, at config/ia64/ia64.c:9357
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-03-26 19:37 UTC by Anders Widell
Modified: 2019-06-03 00:08 UTC (History)
1 user (show)

See Also:
Host:
Target: ia64-unknown-linux-gnu
Build:
Known to work:
Known to fail: 4.7.0
Last reconfirmed:


Attachments
Preprocessed test case (202 bytes, application/octet-stream)
2012-03-26 19:37 UTC, Anders Widell
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Anders Widell 2012-03-26 19:37:11 UTC
Created attachment 27004 [details]
Preprocessed test case

Internal compiler error in GCC 4.7.0 on IA64. Fault exists also in older versions of GCC.

Target: ia64-unknown-linux-gnu
Configured with: /home/user/build/gcc-4.7.0/configure --prefix=/home/user/software --with-gmp=/home/user/software --with-mpfr=/home/user/software --with-mpc=/home/user/software --with-system-libunwind --enable-languages=c,c++

$ gcc -c -O2 ia64_8451.cc
ia64_8451.cc: In function 'void fun(long unsigned int)':
ia64_8451.cc:16:1: internal compiler error: in ia64_st_address_bypass_p, at config/ia64/ia64.c:9357
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
$ cat ia64_8451.cc
char* area;
long int area_size;
char* base;

void fun(unsigned long int addr)
{
   unsigned long int size32 = (addr + 4096 - 1) & ~(4096 - 1);
   unsigned long int size = size32 * sizeof(unsigned int);

   if (size > 0) {
      size = (size + 16384 -1) & ~(16384 - 1);
   }

   area_size = size;
   area = base + size;
}
$
Comment 1 Yukhin Kirill 2013-11-19 13:15:39 UTC
Reproduced on recent trunk.

It seems that we have in ia64.c:
int
ia64_st_address_bypass_p (rtx producer, rtx consumer)
{
  rtx dest, reg, mem;

  gcc_assert (producer && consumer);
  dest = ia64_single_set (producer);
  gcc_assert (dest);
  ...

The problem is that we have as `producer':
(insn 18 17 4 2 (cond_exec (eq (reg:BI 262 p6 [351])
            (const_int 0 [0]))
        (parallel [
                (set (reg:DI 16 r16 [orig:346 D.1446 ] [346])
                    (reg/v:DI 112 r32 [orig:340 size ] [340]))
                (set (reg/v:DI 112 r32 [orig:340 size ] [340])
                    (reg/v:DI 112 r32 [orig:340 size ] [340]))
            ])) 1188 {*p epilogue_deallocate_stack}
     (nil))

ia64_single_set can handle cond_exec (this is actually its purpose).
But it (after going into cond_exec) calls rtlanal.c's `single_set_2',
which returns non zero if we have only one *live* set expr after
the insn. It returns 0 otherwise (this case), which in turn triggers
assert in `ia64_st_address_bypass_p'.

I think, we could fix `ia64_st_address_bypass_p' not to use
`ia64_single_set', but iterate through all set exprs in producer.
Comment 2 Jason Duerstock 2019-06-03 00:08:51 UTC
I just tested this against 8.3.0 and it does not occur.