diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5ad69839f88..9e61921fc06 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2016-02-06 Richard Henderson + + PR c/69643 + * tree.c (tree_nop_conversion_p): Do not strip casts into or + out of non-standard address spaces. + 2016-02-05 Jakub Jelinek PR rtl-optimization/69691 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 61306d0fdd0..d8f088d1bd7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-02-06 Richard HEnderson + + PR c/69643 + * gcc.target/i386/addr-space-4.c: New. + * gcc.target/i386/addr-space-5.c: New. + 2016-02-05 Mikael Morin PR fortran/66089 diff --git a/gcc/testsuite/gcc.target/i386/addr-space-4.c b/gcc/testsuite/gcc.target/i386/addr-space-4.c new file mode 100644 index 00000000000..3e0966db69a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/addr-space-4.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ +/* { dg-final { scan-assembler "gs:" } } */ + +#define uintptr_t __SIZE_TYPE__ + +struct S { int a, b, c; }; + +extern struct S __seg_gs s; + +int foo (void) +{ + int r; + r = s.c; + return r; +} diff --git a/gcc/testsuite/gcc.target/i386/addr-space-5.c b/gcc/testsuite/gcc.target/i386/addr-space-5.c new file mode 100644 index 00000000000..4f73f95aa3f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/addr-space-5.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ +/* { dg-final { scan-assembler "gs:" } } */ + +#define uintptr_t __SIZE_TYPE__ + +struct S { int a, b, c; }; + +extern struct S s; + +int ct_state3 (void) +{ + int r; + r = *((int __seg_gs *) (uintptr_t) &s.c); + return r; +} diff --git a/gcc/tree.c b/gcc/tree.c index fa7646b14e1..07cb9d9765c 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -12219,6 +12219,23 @@ block_ultimate_origin (const_tree block) bool tree_nop_conversion_p (const_tree outer_type, const_tree inner_type) { + /* Do not strip casts into or out of differing address spaces. */ + if (POINTER_TYPE_P (outer_type) + && TYPE_ADDR_SPACE (TREE_TYPE (outer_type)) != ADDR_SPACE_GENERIC) + { + if (!POINTER_TYPE_P (inner_type) + || (TYPE_ADDR_SPACE (TREE_TYPE (outer_type)) + != TYPE_ADDR_SPACE (TREE_TYPE (inner_type)))) + return false; + } + else if (POINTER_TYPE_P (inner_type) + && TYPE_ADDR_SPACE (TREE_TYPE (inner_type)) != ADDR_SPACE_GENERIC) + { + /* We already know that outer_type is not a pointer with + a non-generic address space. */ + return false; + } + /* Use precision rather then machine mode when we can, which gives the correct answer even for submode (bit-field) types. */ if ((INTEGRAL_TYPE_P (outer_type)