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. Environment: System: Linux fftw.org 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 How-To-Repeat: 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 weird...it is distilled from other code (www.fftw.org), 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) \ (((PTRINT(UNTAINT(p)) % ALIGNMENT) == 0) && !(PTRINT(p) & TAINT_BIT)) const union fvec foo = {{-0.0, 0.0, -0.0, 0.0}}; int main(void) { return !ALIGNED(&foo); }
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; }
This looks like fold_truthop bug, will look at it.
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 optimization. Another problem is that case POINTER_TYPE: case REFERENCE_TYPE: if (integer_zerop (expr)) expr = integer_zero_node; else expr = fold (build1 (CONVERT_EXPR, lang_hooks.types.type_for_size (POINTER_SIZE, 0), expr)); 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.
Patch here: <http://gcc.gnu.org/ml/gcc-patches/2005-02/msg00810.html>
Subject: Bug 19857 CVSROOT: /cvs/gcc Module name: gcc Changes by: jakub@gcc.gnu.org 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. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.7491&r2=2.7492 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/convert.c.diff?cvsroot=gcc&r1=1.54&r2=1.55 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/fold-const.c.diff?cvsroot=gcc&r1=1.512&r2=1.513 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.5039&r2=1.5040 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.c-torture/execute/20050215-1.c.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/20050215-1.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
Fixed.