User account creation filtered due to spam.

Bug 19857

Summary: [4.0 Regression] alignment check of SSE constant fails in simple test program
Product: gcc Reporter: stevenj <stevenj>
Component: middle-endAssignee: Jakub Jelinek <jakub>
Severity: normal CC: gcc-bugs
Priority: P2 Keywords: patch, wrong-code
Version: 4.0.0   
Target Milestone: 4.0.0   
Host: Target:
Build: Known to work: 3.3.2
Known to fail: 4.0.0 Last reconfirmed: 2005-02-10 17:21:35
Bug Depends on:    
Bug Blocks: 19858    

Description 2005-02-09 17:04:04 UTC
When I compile a simple test program that declares an SSE constant and checks
that it is 8-byte aligned (see below), the alignment check fails in the
gcc 4.0 snapshot (it succeeds in 3.3.5).

I'm not sure whether the constant is actually misaligned or the alignment
check itself is miscompiled...changing the check slightly makes it succeed.

System: Linux 2.6.3-1-686-smp #2 SMP Tue Feb 24 20:29:08 EST 2004 i686 GNU/Linux
Architecture: i686

host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: ../configure --prefix=/home/stevenj/gcc4


Compile the following code with 'gcc -O3 -msse -o bug bug.c' and run
with './bug && echo ok' ... output *should* be "ok" (ALIGNED==true),
but is not.

(Yes, the way the alignment check is performed looks kinda
is distilled from other code (, obviously...but it should
still pass for any 8-byte aligned quantity.)

Thanks for looking into this,

Steven G. Johnson

typedef float V __attribute__ ((vector_size (16)));
union fvec {
     float f[4];
     V v;

typedef unsigned int uintptr_t;
#define ALIGNMENT 8
#define TAINT_BIT 1
#define UNTAINT(p) ((float *) (((uintptr_t) (p)) & ~(uintptr_t)3))
#define PTRINT(p) ((uintptr_t)(p))
#define ALIGNED(p) \

const union fvec foo = {{-0.0, 0.0, -0.0, 0.0}};

int main(void)
     return !ALIGNED(&foo);
Comment 1 Andrew Pinski 2005-02-09 21:24:32 UTC
Confirmed, here is a testcase which uses abort:
typedef float V __attribute__ ((vector_size (16)));
typedef __SIZE_TYPE__ uintptr_t;
V foo;
void abort (void);

int main(void)
  V *foo2 = &foo;
  if (!(((((uintptr_t)(((float *) (((uintptr_t) foo2) & ~(uintptr_t)3)))) % 8) == 0) && !(((uintptr_t)foo2) & 1)))
   abort ();
  return 0;

Comment 2 Jakub Jelinek 2005-02-10 17:21:34 UTC
This looks like fold_truthop bug, will look at it.
Comment 3 Jakub Jelinek 2005-02-10 18:07:08 UTC
Actually, I see there multiple problems elsewhere.
First is on
int i;
int foo (void)
  return i & ~(unsigned int)3;
First is that
          if (change)
            return fold (build2 (BIT_AND_EXPR, type,
                                 fold_convert (type, and0),
                                 fold_convert (type, and1)));
folds (int) ((unsigned)i & ~(unsigned)3) into i & (int)~(unsigned)3 where
(int)~(unsigned)3 is -4 with TREE_OVERFLOW set.  But there is no overflow
in the original program, so we shouldn't IMHO create one as part of this

Another problem is that
    case POINTER_TYPE:
      if (integer_zerop (expr))
        expr = integer_zero_node;
        expr = fold (build1 (CONVERT_EXPR,
                             lang_hooks.types.type_for_size (POINTER_SIZE, 0),

      return convert_to_integer (type, expr);
unconditionally converts to signed type as wide as pointer (== intptr_t) instead
of considering TYPE_UNSIGNED (type).

As the result of these 2, fold_truthop is presented with ll_mask and ll_and_mask
TREE_OVERFLOW -4 and given that gets confused into believing the whole comparison
is always 0.
Comment 4 Jakub Jelinek 2005-02-15 11:42:18 UTC
Patch here: <>
Comment 5 CVS Commits 2005-02-16 13:54:49 UTC
Subject: Bug 19857

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	2005-02-16 13:54:31

Modified files:
	gcc            : ChangeLog convert.c fold-const.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/gcc.c-torture/execute: 20050215-1.c 
	gcc/testsuite/gcc.dg/tree-ssa: 20050215-1.c 

Log message:
	PR middle-end/19857
	* fold-const.c (fold): Don't optimize (T)(x & cst) to
	(T)x & (T)cst if (T)cst overflows.
	* convert.c (convert_to_integer) <case POINTER_TYPE>: Pass
	TYPE_UNSIGNED (type) as type_for_size's UNSIGNEDP argument.
	* gcc.dg/tree-ssa/20050215-1.c: New test.
	* gcc.c-torture/execute/20050215-1.c: New test.


Comment 6 Jakub Jelinek 2005-02-16 13:58:01 UTC