This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][C] Gimplify &ARRAY as (T *)&ARRAY with fixed ADDR_EXPR type
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 6 Apr 2009 17:18:44 +0200 (CEST)
- Subject: [PATCH][C] Gimplify &ARRAY as (T *)&ARRAY with fixed ADDR_EXPR type
This fixes the long standing bug of the C frontend generating invalid
GENERIC trees for array-to-pointer decay. The frontend emits
ADDR_EXPRs of pointer-to-element type with the object having the
address taken as an array. The fixup is done during c_gimplify_expr
which adjusts the type of the ADDR_EXPR and pre-pends a conversion
to the desired type.
The patch also gets rid of the hack in the gimple type verifier and
adjusts a few vectorizer testcases where PRE now can properly CSE
reads from constant initializers.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress together
with the address-to-array folding patch sent earlier.
Ok for trunk?
(You may remember two or three tries to fix this in the frontend
rather than in the gimplifier - but this runs into tons of issues
with existing warning code, thus now this more pragmatic approach)
Thanks,
Richard.
2009-04-06 Richard Guenther <rguenther@suse.de>
* c-gimplify.c (c_gimplify_expr): Fix the invalid GENERIC
&ARRAY addresses by adjusting their types and prepending
a conversion.
* tree-cfg.c (verify_gimple_assign_single): Verify that
addresses are correct.
* gcc.dg/vect/vect-54.c: Make constant input data file-scope
to prevent constant propagation.
* gcc.dg/vect/vect-56.c: Likewise.
* gcc.dg/vect/vect-58.c: Likewise.
* gcc.dg/vect/vect-60.c: Likewise.
* gcc.dg/vect/no-vfa-vect-57.c: Likewise.
* gcc.dg/vect/no-vfa-vect-61.c: Likewise.
Index: gcc/c-gimplify.c
===================================================================
*** gcc/c-gimplify.c.orig 2009-04-06 16:18:47.000000000 +0200
--- gcc/c-gimplify.c 2009-04-06 16:19:16.000000000 +0200
*************** c_gimplify_expr (tree *expr_p, gimple_se
*** 196,200 ****
--- 196,214 ----
&& !warn_init_self)
TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
+ /* The C frontend is the only one producing &ARRAY with pointer-to-element
+ type. This is invalid in gimple, so produce a properly typed
+ ADDR_EXPR instead and wrap a conversion around it. */
+ if (code == ADDR_EXPR
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (*expr_p, 0))) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (*expr_p))) != ARRAY_TYPE)
+ {
+ tree type = TREE_TYPE (*expr_p);
+ TREE_TYPE (*expr_p)
+ = build_pointer_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0)));
+ *expr_p = build1 (NOP_EXPR, type, *expr_p);
+ return GS_OK;
+ }
+
return GS_UNHANDLED;
}
Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c.orig 2009-04-06 16:18:47.000000000 +0200
--- gcc/tree-cfg.c 2009-04-06 16:19:16.000000000 +0200
*************** verify_gimple_assign_single (gimple stmt
*** 3697,3707 ****
return true;
}
! if (!one_pointer_to_useless_type_conversion_p (lhs_type, TREE_TYPE (op))
! /* FIXME: a longstanding wart, &a == &a[0]. */
! && (TREE_CODE (TREE_TYPE (op)) != ARRAY_TYPE
! || !one_pointer_to_useless_type_conversion_p (lhs_type,
! TREE_TYPE (TREE_TYPE (op)))))
{
error ("type mismatch in address expression");
debug_generic_stmt (lhs_type);
--- 3697,3704 ----
return true;
}
! if (!one_pointer_to_useless_type_conversion_p (lhs_type,
! TREE_TYPE (op)))
{
error ("type mismatch in address expression");
debug_generic_stmt (lhs_type);
Index: gcc/testsuite/gcc.dg/vect/vect-54.c
===================================================================
*** gcc/testsuite/gcc.dg/vect/vect-54.c.orig 2009-04-06 16:18:47.000000000 +0200
--- gcc/testsuite/gcc.dg/vect/vect-54.c 2009-04-06 16:19:16.000000000 +0200
*************** void bar (float *pa, float *pb, float *p
*** 26,38 ****
vect-58.c is similar to this one with one difference:
the loop bound is unknown. */
__attribute__ ((noinline)) int
main1 ()
{
int i;
float a[N] __attribute__ ((__aligned__(16)));
- float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
- float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
float *pa = a;
float *pb = b;
float *pc = c;
--- 26,39 ----
vect-58.c is similar to this one with one difference:
the loop bound is unknown. */
+ float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
+ float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+
__attribute__ ((noinline)) int
main1 ()
{
int i;
float a[N] __attribute__ ((__aligned__(16)));
float *pa = a;
float *pb = b;
float *pc = c;
Index: gcc/testsuite/gcc.dg/vect/vect-56.c
===================================================================
*** gcc/testsuite/gcc.dg/vect/vect-56.c.orig 2009-04-06 16:18:47.000000000 +0200
--- gcc/testsuite/gcc.dg/vect/vect-56.c 2009-04-06 16:19:16.000000000 +0200
*************** void bar (float *pa, float *pb, float *p
*** 30,42 ****
vect-57.c is similar to this one with two differences:
aliasing is a problem, and the write access has unknown alignment. */
__attribute__ ((noinline)) int
main1 ()
{
int i;
float a[N] __attribute__ ((__aligned__(16)));
- float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
- float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
float *pa = a;
float *pb = b;
float *pc = c;
--- 30,43 ----
vect-57.c is similar to this one with two differences:
aliasing is a problem, and the write access has unknown alignment. */
+ float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
+ float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+
__attribute__ ((noinline)) int
main1 ()
{
int i;
float a[N] __attribute__ ((__aligned__(16)));
float *pa = a;
float *pb = b;
float *pc = c;
Index: gcc/testsuite/gcc.dg/vect/vect-58.c
===================================================================
*** gcc/testsuite/gcc.dg/vect/vect-58.c.orig 2009-04-06 16:18:47.000000000 +0200
--- gcc/testsuite/gcc.dg/vect/vect-58.c 2009-04-06 16:19:16.000000000 +0200
*************** void bar (float *pa, float *pb, float *p
*** 26,36 ****
vect-54.c is similar to this one with one difference:
the loop bound is known. */
__attribute__ ((noinline)) int
main1 (int n)
{
int i;
- float a[N] __attribute__ ((__aligned__(16))); float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
float *pa = a;
float *pb = b;
float *pc = c;
--- 26,37 ----
vect-54.c is similar to this one with one difference:
the loop bound is known. */
+ float a[N] __attribute__ ((__aligned__(16))); float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+
__attribute__ ((noinline)) int
main1 (int n)
{
int i;
float *pa = a;
float *pb = b;
float *pc = c;
Index: gcc/testsuite/gcc.dg/vect/vect-60.c
===================================================================
*** gcc/testsuite/gcc.dg/vect/vect-60.c.orig 2009-04-06 16:18:47.000000000 +0200
--- gcc/testsuite/gcc.dg/vect/vect-60.c 2009-04-06 16:19:16.000000000 +0200
*************** void bar (float *pa, float *pb, float *p
*** 30,42 ****
vect-61.c is similar to this one with two differences:
aliasing is not a problem, and the write access has unknown alignment. */
__attribute__ ((noinline)) int
main1 (int n)
{
int i;
float a[N] __attribute__ ((__aligned__(16)));
- float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
- float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
float *pa = a;
float *pb = b;
float *pc = c;
--- 30,43 ----
vect-61.c is similar to this one with two differences:
aliasing is not a problem, and the write access has unknown alignment. */
+ float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
+ float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+
__attribute__ ((noinline)) int
main1 (int n)
{
int i;
float a[N] __attribute__ ((__aligned__(16)));
float *pa = a;
float *pb = b;
float *pc = c;
Index: gcc/testsuite/gcc.dg/vect/no-vfa-vect-57.c
===================================================================
*** gcc/testsuite/gcc.dg/vect/no-vfa-vect-57.c.orig 2009-04-06 16:18:47.000000000 +0200
--- gcc/testsuite/gcc.dg/vect/no-vfa-vect-57.c 2009-04-06 16:35:36.000000000 +0200
***************
*** 1,6 ****
--- 1,7 ----
/* { dg-require-effective-target vect_float } */
#include <stdarg.h>
+ #include <string.h>
#include "tree-vect.h"
#define N 256
*************** void bar (float *pa, float *pb, float *p
*** 20,25 ****
--- 21,35 ----
return;
}
+ __attribute__ ((noinline))
+ void foo (float *pb, float *pc)
+ {
+ float b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
+ float c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+ memcpy (pb, b, sizeof (b));
+ memcpy (pc, c, sizeof (c));
+ }
+
/* Unaligned pointer read accesses with known alignment,
and an unaligned write access with unknown alignment.
The loop bound is known and divisible by the vectorization factor.
*************** __attribute__ ((noinline)) int
*** 33,43 ****
main1 (float *pa)
{
int i;
! float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
! float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
float *pb = b;
float *pc = c;
for (i = 0; i < N/2; i++)
{
pa[i] = pb[i+1] * pc[i+1];
--- 43,55 ----
main1 (float *pa)
{
int i;
! float b[N] __attribute__ ((__aligned__(16)));
! float c[N] __attribute__ ((__aligned__(16)));
float *pb = b;
float *pc = c;
+ foo (pb, pc);
+
for (i = 0; i < N/2; i++)
{
pa[i] = pb[i+1] * pc[i+1];
Index: gcc/testsuite/gcc.dg/vect/no-vfa-vect-61.c
===================================================================
*** gcc/testsuite/gcc.dg/vect/no-vfa-vect-61.c.orig 2009-04-06 16:18:47.000000000 +0200
--- gcc/testsuite/gcc.dg/vect/no-vfa-vect-61.c 2009-04-06 16:40:02.000000000 +0200
***************
*** 2,7 ****
--- 2,8 ----
/* { dg-require-effective-target vect_float } */
#include <stdarg.h>
+ #include <string.h>
#include "tree-vect.h"
#define N 256
*************** void bar (float *pa, float *pb, float *p
*** 21,26 ****
--- 22,36 ----
return;
}
+ __attribute__ ((noinline))
+ void foo (float *pb, float *pc)
+ {
+ float b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
+ float c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+ memcpy (pb, b, sizeof (b));
+ memcpy (pc, c, sizeof (c));
+ }
+
/* Unaligned pointer read accesses with known alignment,
and an unaligned write access with unknown alignment.
The loop bound is iunknown.
*************** __attribute__ ((noinline)) int
*** 34,44 ****
main1 (int n , float *pa)
{
int i;
! float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
! float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
float *pb = b;
float *pc = c;
for (i = 0; i < n/2; i++)
{
pa[i] = pb[i+1] * pc[i+1];
--- 44,56 ----
main1 (int n , float *pa)
{
int i;
! float b[N] __attribute__ ((__aligned__(16)));
! float c[N] __attribute__ ((__aligned__(16)));
float *pb = b;
float *pc = c;
+ foo (pb, pc);
+
for (i = 0; i < n/2; i++)
{
pa[i] = pb[i+1] * pc[i+1];