[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#367782: gcc-2.95: i386 -O2 bad code: insn moved across "&&"



Package: gcc-2.95
Version: 1:2.95.4-24
Severity: normal

The file is_pair.c below compiled with

	gcc-2.95 -O2 -S is_pair.c

results in the following in is_pair.s

        movl (%ebx),%edx
        testb $6,%bl
        jne .L10

which I believe is incorrect for the input.

Those insns are from the inlined scm_is_pair.  "x" is %ebx and it's
tested "x & 6" and there's a test on the contents at "*x".  But notice
the fetch *x has been moved back before the "&6" test.  I think this
is wrong.  "(x&6)==0 && (*x...)" should mean *x is not evaluated,
ie. x not dereferenced, until the "x&6" has been checked.

I struck this in the latest version of guile (1.8.0), it results in
segvs in the split_at function in the test suite.  "-O2" is of course
the default optimization level for autoconfed packages, so it wasn't
just me mucking about with flags.

The problem doesn't occur if you turn down to -O1, and I also noticed
that without "noreturn" on scm_wrong_type_arg_msg it's ok (but perhaps
that's only coincidence).

I suppose gcc 2.95 is too old to be of great interest, but while it's
still in debian it'd be nice if it was correct.  The problem doesn't
seem to occur with gcc 4.


-- System Information:
Debian Release: testing/unstable
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: i386 (i586)
Shell:  /bin/sh linked to /bin/dash
Kernel: Linux 2.6.15-1-486
Locale: LANG=en_AU, LC_CTYPE=en_AU (charmap=ISO-8859-1)

Versions of packages gcc-2.95 depends on:
ii  binutils             2.16.1cvs20051214-1 The GNU assembler, linker and bina
ii  cpp-2.95             1:2.95.4-24         The GNU C preprocessor
ii  libc6                2.3.6-7             GNU C Library: Shared libraries

Versions of packages gcc-2.95 recommends:
ii  libc6-dev [libc-dev]          2.3.6-7    GNU C Library: Development Librari

-- no debconf information

typedef unsigned int size_t;
typedef unsigned int		uintptr_t;
typedef uintptr_t scm_t_bits;

typedef struct scm_unused_struct * SCM;

 
enum scm_tc8_tags
{
  scm_tc8_flag = 4  + 0x00,   
  scm_tc8_char = 4  + 0x08,   
  scm_tc8_isym = 4  + 0x10,   
  scm_tc8_iloc = 4  + 0x18    
};

typedef struct scm_t_cell
{
  SCM word_0;
  SCM word_1;
} scm_t_cell;


extern  SCM scm_cons (SCM x, SCM y);
extern  SCM scm_list_2 (SCM e1, SCM e2);
extern  SCM scm_values (SCM args);

extern  void scm_wrong_type_arg_msg (const char *subr, int pos,
				     SCM bad_value, const char *sz) __attribute__ ((noreturn)) ;



extern  int scm_is_pair (SCM x);

extern
inline
int
scm_is_pair (SCM x)
{
  return
    ! (6 & ((scm_t_bits) x))
    &&
    ((1 & ((scm_t_bits) (((SCM *)((scm_t_cell *) (scm_t_bits) x)) [0])))
     == 0);
}



static const char s_scm_srfi1_split_at  [] =   "split-at" ;

SCM
scm_srfi1_split_at (SCM lst, SCM n)
{
  size_t nn;

  SCM pre = ((SCM) ( (( ( 4 ) ) << 8) +   scm_tc8_flag  ))    ;
  SCM *loc = &pre;

  for (nn = scm_to_uint32  (n); nn != 0; nn--)
    {
      if (!(   scm_is_pair  (lst) ))
        scm_wrong_type_arg_msg(s_scm_srfi1_split_at, 1, lst, "pair");


      *loc = scm_cons (((  (  (((SCM *)((scm_t_cell *) (((scm_t_bits) (0? (*(SCM*)0=(   ( (  lst  ) )   )):    ( (  lst  ) )   )) )) ) [  (  0 ) ])  )    ) ) , ((SCM) ( (( ( 4 ) ) << 8) +   scm_tc8_flag  ))    );
      loc = (((  & (((SCM *)((scm_t_cell *) (((scm_t_bits) (0? (*(SCM*)0=(   ( ( *loc ) )   )):    ( ( *loc ) )   )) )) ) [  (  1 ) ])  ) ) ) ;
      lst = ((  (  (((SCM *)((scm_t_cell *) (((scm_t_bits) (0? (*(SCM*)0=(   ( (  lst  ) )   )):    ( (  lst  ) )   )) )) ) [  (  1 ) ])  )    ) ) ;
    }
  return scm_values (scm_list_2 (pre, lst));
}


Reply to: