Given the following code:

------------------------------------------------------------------------------
typedef unsigned int size_t;
typedef unsigned long long uint64;

extern "C" {
extern void *memcpy (void *__restrict __dest,
      __const void *__restrict __src, size_t __n) /*throw ()*/;
}

extern void foo (void* p);

inline uint64
ghtonll(uint64 x)
{
 // __r is allocated the same stack slot as dest below
 union { unsigned long long int __ll;
         unsigned long int __l[2]; } __w, __r;
 __w.__ll = x;
 __r.__l[0] = (
   {
     register unsigned int __v;
     __asm__ __volatile__ ("bswap %0" : "=r" (__v) :
                           "0" ((unsigned int) (__w.__l[1])));
     __v; });

 __r.__l[1] = (
   {
     register unsigned int __v;
     __asm__ __volatile__ ("bswap %0" : "=r" (__v) :
                           "0" ((unsigned int) (__w.__l[0])));
     __v; });

 return __r.__ll;
}

inline uint64
double_2_uint64 (const double *source)
{
 uint64 dest;  // allocated the same stack slot as __r above
 memcpy(&dest, source, sizeof(dest));
 return dest;
}

inline void
KeyFromUint64(uint64 fp) {
 uint64 norder;
 norder = ghtonll (fp);
 foo((char*)(&norder));
}

void
KeyFromDouble(double x) {
 uint64 n = double_2_uint64 (&x);
 if (n >= 42) {
   n += 1;
 }

 KeyFromUint64(n);
}
---

Here is what gcc -O2 -fdump-tree-all (version 4.2) in at the end of the tree
passes.
Please take note of the assignment to dest after that of norder.

;; Function void KeyFromDouble(double) (_Z13KeyFromDoubled)

void KeyFromDouble(double) (x)
{
 uint64 n.50;
 char * norder.2;
 uint64 norder;
 register unsigned int __v;
 register unsigned int __v;
 union ._0 __r;
 union ._0 __w;
 uint64 dest;
 uint64 n;

<bb 2>:
 n.50 = VIEW_CONVERT_EXPR<uint64>(x);
 if (n.50 > 41) goto <L0>; else goto <L5>;

<L5>:;
 n = n.50;
 goto <bb 5> (<L1>);

<L0>:;
 n = n.50 + 1;

<L1>:;
 __w.__ll = n;
 __asm__ __volatile__("bswap %0":"=r" __v:"0" __w.__l[1]);
 __r.__l[0] = __v;
 __asm__ __volatile__("bswap %0":"=r" __v:"0" __w.__l[0]);
 __r.__l[1] = __v;
 norder = __r.__ll;
 norder.2 = (char *) &norder;
 dest = n.50;
 foo (norder.2);
 return;

}
----
Here is part of the RTL expansion:

(insn 45 43 47 9 (set (mem/c/i:DI (plus:SI (reg/f:SI 54 virtual-stack-vars)
               (const_int -8 [0xfffffff8])) [3 norder+0 S8 A32])
       (reg/v:DI 64 [ __r ])) -1 (nil)
   (nil))

(insn 47 45 49 9 (parallel [
           (set (reg:SI 59 [ norder.2 ])
               (plus:SI (reg/f:SI 54 virtual-stack-vars)
                   (const_int -8 [0xfffffff8])))
           (clobber (reg:CC 17 flags))
       ]) -1 (nil)
   (nil))

(insn 49 47 51 9 (set (mem/c/i:DI (plus:SI (reg/f:SI 54 virtual-stack-vars)
               (const_int -8 [0xfffffff8])) [3 dest+0 S8 A32])
       (reg/v:DI 58 [ n.50 ])) -1 (nil)
   (nil))

Both dest & norder are assigned the same memory location
(virtual-stack-vars - 8). So later lifeness analysis thinks that the
first assignment is dead and it removes it. norder contains results of
bswap but gcc cannot remove the asm statement. However, since the
output of the asms are dead so they both got eax as the output
register.


-- 
           Summary: Incorrect stack sharing causing removal of live code
           Product: gcc
           Version: 4.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: dnovillo at gcc dot gnu dot org
 GCC build triplet: x86_64-unknown-linux-gnu
  GCC host triplet: x86_64-unknown-linux-gnu
GCC target triplet: x86_64-unknown-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32327

Reply via email to