This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug optimization/14782] New: [3.3/3.4/hppa64-linux] gcc inlines code incorrectly at -O2


The attached code when compiled with gcc-3.3 or 3.4 at -O2 generates a "ldd -23
(%r3),%r19" sequence which is wrong. Compiling with -O1 or -O2 -fno-gcse works 
around the problem. The offending asm seems to be generated from the if-
statement in loop_unregister_transfer(). Removing the up/down calls make the 
problem go away. This test case was derived from the linux kernel, 
drivers/block/loop.c.

thanks, randolph

-------- 8< cut here 8< -------------
#define __PA_LDCW_ALIGNMENT 16
#define __ldcw_align(a) ({ \
  unsigned long __ret = (unsigned long) a;                              \
  __ret = (__ret + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1); \
  (volatile unsigned int *) __ret;                                      \
})


#define __ldcw(a) ({ \
        unsigned __ret; \
        __asm__ __volatile__("ldcw 0(%1),%0" : "=r" (__ret) : "r" (a)); \
        __ret; \
})

typedef struct {
  volatile unsigned int lock[4];
} spinlock_t;

struct semaphore
{
  spinlock_t sentry;
  int count;
};

struct loop_device
{
  struct loop_func_table *lo_encryption;
  struct semaphore lo_ctl_mutex;
};

static int max_loop = 8;
static struct loop_device *loop_dev;

void __down (struct semaphore *sem);
void __up (struct semaphore *sem);

static inline void _raw_spin_lock (spinlock_t * x)
{
  volatile unsigned int *a = __ldcw_align(&x->lock[0]);

  while (__ldcw(a) == 0)
    while (*a == 0);
}

static inline void _raw_spin_unlock (spinlock_t * x)
{
  volatile unsigned int *a = __ldcw_align(&x->lock[0]);
  *a = 1;
}

inline void down (struct semaphore *sem)
{
  _raw_spin_lock (&sem->sentry);
  if (sem->count > 0) { sem->count--; }
  else { __down (sem); }
  _raw_spin_unlock (&sem->sentry);
}

inline void up (struct semaphore *sem)
{
  _raw_spin_lock (&sem->sentry);
  if (sem->count < 0) { __up (sem); }
  else { sem->count++; }
  _raw_spin_unlock (&sem->sentry);
}

int
loop_unregister_transfer (int number)
{
  struct loop_device *lo = &loop_dev[0];

  for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++)
    {
      down (&lo->lo_ctl_mutex);

      if (lo->lo_encryption == 0)
        loop_release_xfer (lo);

      up (&lo->lo_ctl_mutex);
    }

  return 0;
}
-------- 8< cut here 8< -------------

-- 
           Summary: [3.3/3.4/hppa64-linux] gcc inlines code incorrectly at -
                    O2
           Product: gcc
           Version: 3.4.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: optimization
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: tausq at debian dot org
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: hppa-linux
  GCC host triplet: hppa-linux
GCC target triplet: hppa64-linux


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]