This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [CHKP] Fix for PR79990
- From: Ilya Enkovich <enkovich dot gnu at gmail dot com>
- To: Alexander Ivchenko <aivchenk at gmail dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 20 Apr 2017 20:17:44 +0300
- Subject: Re: [CHKP] Fix for PR79990
- Authentication-results: sourceware.org; auth=none
- References: <CACysShgnUuetyR-7wAqh6wusBz67k-iVu6VGHzEzVvRvS2QW8Q@mail.gmail.com> <CAMbmDYb79XYn1oqP1qjz=_JFrXd8q=DqtEwTv3RdwWyTjwg30Q@mail.gmail.com> <CACysShiZxAEf1OEHkNGZNxRWW+Wv99OXx-9VcNBQknnLEe6NAA@mail.gmail.com> <CAMbmDYYP-58HA9CXMW+XuP7TWsKEkbwjM=xLYN-jLMqqf0xcUg@mail.gmail.com> <CACysShiE3Orf93-gFzaO+BmbAmb3qhcQMB--ai5K1ULzGpxTBA@mail.gmail.com> <CAMbmDYZ+DDk-=hHzg-Qogawdee2R7XzGhEokbcXA5NhgiYs4ww@mail.gmail.com> <CACysShg_2=mMGaX-+CLwn5fXzZFKsgTF6Lcx2UfSPRaphm7zUg@mail.gmail.com>
2017-04-20 12:27 GMT+03:00 Alexander Ivchenko <aivchenk@gmail.com>:
> Thanks for correcting the usage of get_base_address. I fixed that.
> Plus addressed the comment about the avoiding the usage of
> chkp_find_bounds.
>
>
> gcc/testsuite/ChangeLog:
>
> 2017-04-20 Alexander Ivchenko <alexander.ivchenko@intel.com>
>
> * gcc.target/i386/mpx/hard-reg-2-lbv.c: New test.
> * gcc.target/i386/mpx/hard-reg-2-nov.c: New test.
> * gcc.target/i386/mpx/hard-reg-2-ubv.c: New test.
> * gcc.target/i386/mpx/hard-reg-3-1-lbv.c: New test.
> * gcc.target/i386/mpx/hard-reg-3-1-nov.c: New test.
> * gcc.target/i386/mpx/hard-reg-3-1-ubv.c: New test.
> * gcc.target/i386/mpx/hard-reg-3-2-lbv.c: New test.
> * gcc.target/i386/mpx/hard-reg-3-2-nov.c: New test.
> * gcc.target/i386/mpx/hard-reg-3-2-ubv.c: New test.
> * gcc.target/i386/mpx/hard-reg-3-lbv.c: New test.
> * gcc.target/i386/mpx/hard-reg-3-nov.c: New test.
> * gcc.target/i386/mpx/hard-reg-3-ubv.c: New test.
> * gcc.target/i386/mpx/hard-reg-4-lbv.c: New test.
> * gcc.target/i386/mpx/hard-reg-4-nov.c: New test.
> * gcc.target/i386/mpx/hard-reg-4-ubv.c: New test.
> * gcc.target/i386/mpx/hard-reg-5-1-lbv.c: New test.
> * gcc.target/i386/mpx/hard-reg-5-1-nov.c: New test.
> * gcc.target/i386/mpx/hard-reg-5-1-ubv.c: New test.
> * gcc.target/i386/mpx/hard-reg-5-2-lbv.c: New test.
> * gcc.target/i386/mpx/hard-reg-5-2-nov.c: New test.
> * gcc.target/i386/mpx/hard-reg-5-2-ubv.c: New test.
> * gcc.target/i386/mpx/hard-reg-6-lbv.c: New test.
> * gcc.target/i386/mpx/hard-reg-6-nov.c: New test.
> * gcc.target/i386/mpx/hard-reg-6-ubv.c: New test.
>
> gcc/ChangeLog:
>
> 2017-04-20 Alexander Ivchenko <alexander.ivchenko@intel.com>
>
> * tree-chkp.c (chkp_get_hard_register_var_fake_base_address):
> New function to provide a base address for
> chkp_get_hard_register_fake_addr_expr.
> (chkp_get_hard_register_fake_addr_expr): New function to build
> fake address expression for an expr that resides on a hard
> register.
> (chkp_build_addr_expr): Add checks for hard reg cases.
> (chkp_parse_array_and_component_ref): Create/find bounds if the
> var resides on a hard reg.
>
>
> I already had a testcases for struct with a pointer - "hard-reg-4-*".
> Here is the instrumentation of the foo function:
>
> __attribute__((chkp instrumented))
> foo.chkp (int i)
> {
> __bounds_type __bound_tmp.1;
> register struct S2 b __asm__ (*xmm0);
> int k;
> int * _1;
> long unsigned int _2;
> long unsigned int _3;
> int * _4;
> int * _5;
> int _11;
> int * _18;
>
> <bb 4> [0.00%]:
> __bound_tmp.1_17 = __chkp_zero_bounds;
> __bound_tmp.1_14 = __builtin_ia32_bndmk (&k, 4);
> __bound_tmp.1_13 = __builtin_ia32_bndmk (-2147483648B, 16);
>
> <bb 3> [0.00%]:
>
> <bb 2> [0.00%]:
> k = 5;
> b.f3 = &k;
> __builtin_ia32_bndstx (&k, __bound_tmp.1_14, -2147483648B);
> _1 = b.f3;
> __bound_tmp.1_15 = __builtin_ia32_bndldx (-2147483648B, _1);
> _2 = (long unsigned int) i_9(D);
> _3 = _2 * 4;
> _4 = _1 + _3;
> b.f3 = _4;
> __builtin_ia32_bndstx (_4, __bound_tmp.1_15, -2147483648B);
> _5 = b.f3;
> __bound_tmp.1_16 = __builtin_ia32_bndldx (-2147483648B, _5);
> __builtin_ia32_bndcl (_5, __bound_tmp.1_16);
> _18 = _5 + 3;
> __builtin_ia32_bndcu (_18, __bound_tmp.1_16);
> _11 = *_5;
> k ={v} {CLOBBER};
> return _11;
>
> }
>
> Which is the most suspicious one, because we have ldx and stx. I'm not
> sure whether this is OK.
It is not OK because single entry in BT may be used by multiple hardreg
variables. There is a code in chkp_find_bounds_1 to use zero bounds in
case we load bounds from register var. I believe here we should do the
same. In chkp_find_bounds_1 at ARRAY_REF/COMPONENT_REF
case check if addr is register var and use zero bounds.
Thanks,
Ilya
>
> Here is the chkp dump for foo function of newly added hard-reg-6* case:
>
> __attribute__((chkp instrumented))
> foo.chkp (int i, int * kp1, __bounds_type __chkp_bounds_of_kp1)
> {
> __bounds_type __bound_tmp.1;
> int D.2873;
> register struct S2 b __asm__ (*xmm0);
> int k2;
> int * _1;
> long unsigned int _2;
> long unsigned int _3;
> int * _4;
> int * _5;
> int _13;
> int * _31;
>
> <bb 5> [0.00%]:
> __bound_tmp.1_22 = __builtin_ia32_bndmk (&k2, 4);
> __bound_tmp.1_17 = __chkp_zero_bounds;
> __bound_tmp.1_15 = __builtin_ia32_bndmk (-2147483648B, 16);
>
> <bb 4> [0.00%]:
>
> <bb 2> [0.00%]:
> k2 = 5;
> __bound_tmp.1_16 = __builtin_ia32_bndmk (-2147483648B, 16);
> __bound_tmp.1_18 = __builtin_ia32_bndint (__bound_tmp.1_16, __bound_tmp.1_15);
> __builtin_ia32_bndcl (-2147483648B, __bound_tmp.1_18);
> __builtin_ia32_bndcu (-2147483641B, __bound_tmp.1_18);
> b.f[0] = kp1_8(D);
> __builtin_ia32_bndstx (kp1_8(D), __chkp_bounds_of_kp1_19(D), -2147483648B);
> __bound_tmp.1_20 = __builtin_ia32_bndmk (-2147483648B, 16);
> __bound_tmp.1_21 = __builtin_ia32_bndint (__bound_tmp.1_20, __bound_tmp.1_15);
> __builtin_ia32_bndcl (-2147483640B, __bound_tmp.1_21);
> __builtin_ia32_bndcu (-2147483633B, __bound_tmp.1_21);
> b.f[1] = &k2;
> __builtin_ia32_bndstx (&k2, __bound_tmp.1_22, -2147483640B);
> __bound_tmp.1_23 = __builtin_ia32_bndmk (-2147483648B, 16);
> __bound_tmp.1_24 = __builtin_ia32_bndint (__bound_tmp.1_23, __bound_tmp.1_15);
> __builtin_ia32_bndcl (-2147483648B, __bound_tmp.1_24);
> __builtin_ia32_bndcu (-2147483641B, __bound_tmp.1_24);
> _1 = b.f[0];
> __bound_tmp.1_27 = __builtin_ia32_bndldx (-2147483648B, _1);
> _2 = (long unsigned int) i_11(D);
> _3 = _2 * 4;
> _4 = _1 + _3;
> __bound_tmp.1_25 = __builtin_ia32_bndmk (-2147483648B, 16);
> __bound_tmp.1_26 = __builtin_ia32_bndint (__bound_tmp.1_25, __bound_tmp.1_15);
> __builtin_ia32_bndcl (-2147483648B, __bound_tmp.1_26);
> __builtin_ia32_bndcu (-2147483641B, __bound_tmp.1_26);
> b.f[0] = _4;
> __builtin_ia32_bndstx (_4, __bound_tmp.1_27, -2147483648B);
> __bound_tmp.1_28 = __builtin_ia32_bndmk (-2147483648B, 16);
> __bound_tmp.1_29 = __builtin_ia32_bndint (__bound_tmp.1_28, __bound_tmp.1_15);
> __builtin_ia32_bndcl (-2147483648B, __bound_tmp.1_29);
> __builtin_ia32_bndcu (-2147483641B, __bound_tmp.1_29);
> _5 = b.f[0];
> __bound_tmp.1_30 = __builtin_ia32_bndldx (-2147483648B, _5);
> __builtin_ia32_bndcl (_5, __bound_tmp.1_30);
> _31 = _5 + 3;
> __builtin_ia32_bndcu (_31, __bound_tmp.1_30);
> _13 = *_5;
> k2 ={v} {CLOBBER};
>
> <L0> [0.00%]:
> return _13;
> }
>
> ..which looks fine to me. And here is the dump-chkp for the basic case
> of hard-reg-2:
>
> __attribute__((chkp instrumented))
> foo.chkp (int i)
> {
> __bounds_type __bound_tmp.1;
> int D.2863;
> register v16 u __asm__ (*xmm0);
> int _3;
> long unsigned int _6;
> sizetype _7;
> void * _8;
> sizetype _9;
> sizetype _10;
> sizetype _11;
> sizetype _12;
> void * _13;
>
> <bb 5> [0.00%]:
> __bound_tmp.1_5 = __chkp_zero_bounds;
> __bound_tmp.1_4 = __builtin_ia32_bndmk (-2147483648B, 16);
>
> <bb 4> [0.00%]:
>
> <bb 2> [0.00%]:
> _6 = (long unsigned int) i_2(D);
> _7 = _6 * 4;
> _8 = -2147483648B + _7;
> __builtin_ia32_bndcl (_8, __bound_tmp.1_4);
> _9 = (sizetype) i_2(D);
> _10 = _9 + 1;
> _11 = _10 * 4;
> _12 = _11 + 18446744073709551615;
> _13 = -2147483648B + _12;
> __builtin_ia32_bndcu (_13, __bound_tmp.1_4);
> _3 = VIEW_CONVERT_EXPR<int[4]>(u)[i_2(D)];
>
> <L0> [0.00%]:
> return _3;
>
> }
>
> So overall we have these fails (they all have the same backtrace as
> PR80270) and other combinations pass:
>
> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O3 -g (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O3 -g (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto
> -fno-use-linker-plugin -flto-partition=none (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto
> -fno-use-linker-plugin -flto-partition=none (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto
> -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto
> -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O3 -g (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O3 -g (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto
> -fno-use-linker-plugin -flto-partition=none (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto
> -fno-use-linker-plugin -flto-partition=none (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto
> -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto
> -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-4-lbv.c -O0 (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-4-lbv.c -O0 (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-4-nov.c -O0 (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-4-nov.c -O0 (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-4-ubv.c -O0 (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-4-ubv.c -O0 (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O3 -g (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O3 -g (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto
> -fno-use-linker-plugin -flto-partition=none (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto
> -fno-use-linker-plugin -flto-partition=none (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto
> -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto
> -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors)
> FAIL: gcc.target/i386/mpx/hard-reg-6-lbv.c -O0 (internal compiler error)
> FAIL: gcc.target/i386/mpx/hard-reg-6-lbv.c -O0 (test for excess errors)
>
>
>
> Here is the patch itself:
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c
> new file mode 100644
> index 0000000..319e1ec
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c
> @@ -0,0 +1,21 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v16 __attribute__((vector_size(16)));
> +
> +int foo(int i) {
> + register v16 u asm("xmm0");
> + return u[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo (-1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c
> new file mode 100644
> index 0000000..3c6d39a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c
> @@ -0,0 +1,18 @@
> +/* { dg-do run } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +#include "mpx-check.h"
> +
> +typedef int v16 __attribute__((vector_size(16)));
> +
> +int foo (int i) {
> + register v16 u asm ("xmm0");
> + return u[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo (3));
> + printf ("%d\n", foo (0));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c
> new file mode 100644
> index 0000000..7fe76c4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c
> @@ -0,0 +1,21 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v16 __attribute__((vector_size(16)));
> +
> +int foo (int i) {
> + register v16 u asm ("xmm0");
> + return u[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo (5));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c
> new file mode 100644
> index 0000000..7e4451f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c
> @@ -0,0 +1,33 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1;
> + v8 s2f2;
> +};
> +
> +int foo_s2f1 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f1.s1f[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f1 (-1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c
> new file mode 100644
> index 0000000..73bd7fb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c
> @@ -0,0 +1,30 @@
> +/* { dg-do run } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1;
> + v8 s2f2;
> +};
> +
> +int foo_s2f1 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f1.s1f[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f1 (0));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c
> new file mode 100644
> index 0000000..166b6b9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c
> @@ -0,0 +1,33 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1;
> + v8 s2f2;
> +};
> +
> +int foo_s2f1 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f1.s1f[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f1 (3));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c
> new file mode 100644
> index 0000000..7820c2f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c
> @@ -0,0 +1,33 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1;
> + v8 s2f2;
> +};
> +
> +int foo_s2f2 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f2[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f2 (-1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c
> new file mode 100644
> index 0000000..0816e58
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c
> @@ -0,0 +1,30 @@
> +/* { dg-do run } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1;
> + v8 s2f2;
> +};
> +
> +int foo_s2f2 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f2[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f2 (0));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c
> new file mode 100644
> index 0000000..94261a7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c
> @@ -0,0 +1,33 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1;
> + v8 s2f2;
> +};
> +
> +int foo_s2f2 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f2[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f2 (3));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c
> new file mode 100644
> index 0000000..f273d58
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c
> @@ -0,0 +1,27 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v16 __attribute__ ((vector_size (16)));
> +
> +struct S1
> +{
> + v16 s1f1;
> +};
> +
> +int foo_s1f1 (int i)
> +{
> + register struct S1 b asm ("xmm0");
> + return b.s1f1[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s1f1 (-1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c
> new file mode 100644
> index 0000000..aa8f7b9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c
> @@ -0,0 +1,24 @@
> +/* { dg-do run } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#include "mpx-check.h"
> +
> +typedef int v16 __attribute__ ((vector_size (16)));
> +
> +struct S1
> +{
> + v16 s1f1;
> +};
> +
> +int foo_s1f1 (int i)
> +{
> + register struct S1 b asm ("xmm0");
> + return b.s1f1[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s1f1 (0));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c
> new file mode 100644
> index 0000000..3d0c9b2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c
> @@ -0,0 +1,27 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v16 __attribute__ ((vector_size (16)));
> +
> +struct S1
> +{
> + v16 s1f1;
> +};
> +
> +int foo_s1f1 (int i)
> +{
> + register struct S1 b asm ("xmm0");
> + return b.s1f1[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s1f1 (7));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c
> new file mode 100644
> index 0000000..e81b942
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c
> @@ -0,0 +1,31 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S2
> +{
> + v8 s2f2;
> + int* f3;
> +};
> +
> +int foo (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + int k = 5;
> + b.f3 = &k;
> + b.f3 = b.f3 + i;
> + return *b.f3;
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo (-1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c
> new file mode 100644
> index 0000000..4b1f1ac
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c
> @@ -0,0 +1,28 @@
> +/* { dg-do run } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S2
> +{
> + v8 s2f2;
> + int* f3;
> +};
> +
> +int foo (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + int k = 5;
> + b.f3 = &k;
> + b.f3 = b.f3 + i;
> + return *b.f3;
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo (0));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c
> new file mode 100644
> index 0000000..e95e68f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c
> @@ -0,0 +1,31 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S2
> +{
> + v8 s2f2;
> + int* f3;
> +};
> +
> +int foo (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + int k = 5;
> + b.f3 = &k;
> + b.f3 = b.f3 + i;
> + return *b.f3;
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo (1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c
> new file mode 100644
> index 0000000..201b62d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c
> @@ -0,0 +1,32 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1[2];
> +};
> +
> +int foo_s2f1 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f1[0].s1f[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f1 (-1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c
> new file mode 100644
> index 0000000..f94a879
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c
> @@ -0,0 +1,30 @@
> +/* { dg-do run } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1[2];
> +};
> +
> +int foo_s2f1 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f1[0].s1f[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f1 (1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c
> new file mode 100644
> index 0000000..6ab981d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c
> @@ -0,0 +1,32 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1[2];
> +};
> +
> +int foo_s2f1 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f1[0].s1f[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f1 (4));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c
> new file mode 100644
> index 0000000..cc58e8a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c
> @@ -0,0 +1,32 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1[2];
> +};
> +
> +int foo_s2f1 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f1[1].s1f[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f1 (-1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c
> new file mode 100644
> index 0000000..5898c3b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c
> @@ -0,0 +1,30 @@
> +/* { dg-do run } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1[2];
> +};
> +
> +int foo_s2f1 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f1[1].s1f[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f1 (1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c
> new file mode 100644
> index 0000000..2910795
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c
> @@ -0,0 +1,32 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S1
> +{
> + v8 s1f;
> +};
> +
> +struct S2
> +{
> + struct S1 s2f1[2];
> +};
> +
> +int foo_s2f1 (int i)
> +{
> + register struct S2 b asm ("xmm0");
> + return b.s2f1[1].s1f[i];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + printf ("%d\n", foo_s2f1 (4));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-lbv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-lbv.c
> new file mode 100644
> index 0000000..b160915
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-lbv.c
> @@ -0,0 +1,34 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S2
> +{
> + int* f[2];
> +};
> +
> +int foo (int i, int *kp1)
> +{
> + register struct S2 b asm ("xmm0");
> + int k2 = 5;
> +
> + b.f[0] = kp1;
> + b.f[1] = &k2;
> +
> + b.f[1] = b.f[1] + i;
> + return *b.f[1];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + int k1 = 10;
> + printf ("%d\n", foo (-1, &k1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-nov.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-nov.c
> new file mode 100644
> index 0000000..584b3e5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-nov.c
> @@ -0,0 +1,31 @@
> +/* { dg-do run } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S2
> +{
> + int* f[2];
> +};
> +
> +int foo (int i, int *kp1)
> +{
> + register struct S2 b asm ("xmm0");
> + int k2 = 5;
> +
> + b.f[0] = kp1;
> + b.f[1] = &k2;
> +
> + b.f[0] = b.f[0] + i;
> + return *b.f[0];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + int k1 = 10;
> + printf ("%d\n", foo (0, &k1));
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-ubv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-ubv.c
> new file mode 100644
> index 0000000..92fa793
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-ubv.c
> @@ -0,0 +1,34 @@
> +/* { dg-do run } */
> +/* { dg-shouldfail "bounds violation" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +
> +
> +#define SHOULDFAIL
> +
> +#include "mpx-check.h"
> +
> +typedef int v8 __attribute__ ((vector_size (8)));
> +
> +struct S2
> +{
> + int* f[2];
> +};
> +
> +int foo (int i, int *kp1)
> +{
> + register struct S2 b asm ("xmm0");
> + int k2 = 5;
> +
> + b.f[0] = kp1;
> + b.f[1] = &k2;
> +
> + b.f[0] = b.f[0] + i;
> + return *b.f[0];
> +}
> +
> +int mpx_test (int argc, const char **argv)
> +{
> + int k1 = 10;
> + printf ("%d\n", foo (1, &k1));
> + return 0;
> +}
> diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c
> index b1ff218..3ef73a9 100644
> --- a/gcc/tree-chkp.c
> +++ b/gcc/tree-chkp.c
> @@ -327,6 +327,8 @@ static void chkp_parse_array_and_component_ref
> (tree node, tree *ptr,
> bool innermost_bounds);
> static void chkp_parse_bit_field_ref (tree node, location_t loc,
> tree *offset, tree *size);
> +static tree
> +chkp_make_addressed_object_bounds (tree obj, gimple_stmt_iterator *iter);
>
> #define chkp_bndldx_fndecl \
> (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDLDX))
> @@ -679,6 +681,45 @@ chkp_erase_completed_bounds (void)
> chkp_completed_bounds_set = new hash_set<tree>;
> }
>
> +/* This function is used to provide a base address for
> + chkp_get_hard_register_fake_addr_expr. */
> +static tree
> +chkp_get_hard_register_var_fake_base_address ()
> +{
> + tree base = fold_convert (ptr_type_node, integer_zero_node);
> + unsigned HOST_WIDE_INT offset = 1 << (TYPE_PRECISION (ptr_type_node) - 1);
> + return fold_build_pointer_plus_hwi (base, offset);
> +}
> +
> +/* If we check bounds for a hard register variable, we cannot
> + use its address - it is illegal, so instead of that we use
> + this fake value. */
> +static tree
> +chkp_get_hard_register_fake_addr_expr (tree obj)
> +{
> + tree addr = chkp_get_hard_register_var_fake_base_address ();
> + tree outer = obj;
> + while (TREE_CODE (outer) == COMPONENT_REF || TREE_CODE (outer) == ARRAY_REF)
> + {
> + if (TREE_CODE (outer) == COMPONENT_REF)
> + {
> + addr = fold_build_pointer_plus (addr,
> + component_ref_field_offset (outer));
> + outer = TREE_OPERAND (outer, 0);
> + }
> + else if (TREE_CODE (outer) == ARRAY_REF)
> + {
> + tree indx = fold_convert(size_type_node, TREE_OPERAND(outer, 1));
> + tree offset = size_binop (MULT_EXPR,
> + array_ref_element_size (outer), indx);
> + addr = fold_build_pointer_plus (addr, offset);
> + outer = TREE_OPERAND (outer, 0);
> + }
> + }
> +
> + return addr;
> +}
> +
> /* Mark BOUNDS associated with PTR as incomplete. */
> static void
> chkp_register_incomplete_bounds (tree bounds, tree ptr)
> @@ -1044,6 +1085,12 @@ chkp_add_modification_to_stmt_list (tree lhs,
> static tree
> chkp_build_addr_expr (tree obj)
> {
> + /* We first check whether it is a "hard reg case". */
> + tree base = get_base_address (obj);
> + if (VAR_P (base) && DECL_HARD_REGISTER (base))
> + return chkp_get_hard_register_fake_addr_expr (obj);
> +
> + /* If not - return regular ADDR_EXPR. */
> return TREE_CODE (obj) == TARGET_MEM_REF
> ? tree_mem_ref_addr (ptr_type_node, obj)
> : build_fold_addr_expr (obj);
> @@ -3442,6 +3489,13 @@ chkp_parse_array_and_component_ref (tree node, tree *ptr,
> || TREE_CODE (var) == SSA_NAME);
>
> *ptr = chkp_build_addr_expr (var);
> +
> + /* For hard register cases chkp_build_addr_expr returns INTEGER_CST
> + and later on chkp_find_bounds will fail to find proper bounds.
> + In order to avoid that, we find/create bounds right aways using
> + the var itself. */
> + if (DECL_HARD_REGISTER (var))
> + *bounds = chkp_make_addressed_object_bounds (var, iter);
> }
>
> /* In this loop we are trying to find a field access
>
> 2017-04-19 21:32 GMT+02:00 Ilya Enkovich <enkovich.gnu@gmail.com>:
>> 2017-04-19 19:48 GMT+03:00 Alexander Ivchenko <aivchenk@gmail.com>:
>>> Hi,
>>>
>>> Thanks for the comments, that was a good idea to place all the logic inside
>>> of chkp_build_addr_expr function. I followed it and here is what I got:
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> 2017-04-19 Alexander Ivchenko <aivchenk@gmail.com>
>>>
>>> * gcc.target/i386/mpx/hard-reg-2-lbv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-2-nov.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-2-ubv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-3-1-lbv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-3-1-nov.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-3-1-ubv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-3-2-lbv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-3-2-nov.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-3-2-ubv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-3-lbv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-3-nov.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-3-ubv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-4-lbv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-4-nov.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-4-ubv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-5-1-lbv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-5-1-nov.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-5-1-ubv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-5-2-lbv.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-5-2-nov.c: New test.
>>> * gcc.target/i386/mpx/hard-reg-5-2-ubv.c: New test.
>>>
>>> gcc/ChangeLog:
>>>
>>> 2017-04-19 Alexander Ivchenko <aivchenk@gmail.com>
>>>
>>> * tree-chkp.c (chkp_get_hard_register_var_fake_base_address):
>>> New function to provide a base address for.
>>> chkp_get_hard_register_fake_addr_expr
>>> (chkp_get_hard_register_fake_addr_expr): New function to build
>>> fake address expression for an expr that resides on a hard
>>> register.
>>> (chkp_build_addr_expr): Add checks for hard reg cases.
>>> (chkp_parse_array_and_component_ref): Create/find bounds if the
>>> var resides on a hard reg.
>>> (chkp_find_bounds_1): Check for hard register cases.
>>>
>>>
>>>
>>>
>>>
>>> And the patch itself:
>>>
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c
>>> new file mode 100644
>>> index 0000000..319e1ec
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c
>>> @@ -0,0 +1,21 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v16 __attribute__((vector_size(16)));
>>> +
>>> +int foo(int i) {
>>> + register v16 u asm("xmm0");
>>> + return u[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo (-1));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c
>>> new file mode 100644
>>> index 0000000..3c6d39a
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c
>>> @@ -0,0 +1,18 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v16 __attribute__((vector_size(16)));
>>> +
>>> +int foo (int i) {
>>> + register v16 u asm ("xmm0");
>>> + return u[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo (3));
>>> + printf ("%d\n", foo (0));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c
>>> new file mode 100644
>>> index 0000000..7fe76c4
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c
>>> @@ -0,0 +1,21 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v16 __attribute__((vector_size(16)));
>>> +
>>> +int foo (int i) {
>>> + register v16 u asm ("xmm0");
>>> + return u[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo (5));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c
>>> new file mode 100644
>>> index 0000000..7e4451f
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c
>>> @@ -0,0 +1,33 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1;
>>> + v8 s2f2;
>>> +};
>>> +
>>> +int foo_s2f1 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f1.s1f[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f1 (-1));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c
>>> new file mode 100644
>>> index 0000000..73bd7fb
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c
>>> @@ -0,0 +1,30 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1;
>>> + v8 s2f2;
>>> +};
>>> +
>>> +int foo_s2f1 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f1.s1f[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f1 (0));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c
>>> new file mode 100644
>>> index 0000000..166b6b9
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c
>>> @@ -0,0 +1,33 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1;
>>> + v8 s2f2;
>>> +};
>>> +
>>> +int foo_s2f1 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f1.s1f[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f1 (3));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c
>>> new file mode 100644
>>> index 0000000..7820c2f
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c
>>> @@ -0,0 +1,33 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1;
>>> + v8 s2f2;
>>> +};
>>> +
>>> +int foo_s2f2 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f2[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f2 (-1));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c
>>> new file mode 100644
>>> index 0000000..0816e58
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c
>>> @@ -0,0 +1,30 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1;
>>> + v8 s2f2;
>>> +};
>>> +
>>> +int foo_s2f2 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f2[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f2 (0));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c
>>> new file mode 100644
>>> index 0000000..94261a7
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c
>>> @@ -0,0 +1,33 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1;
>>> + v8 s2f2;
>>> +};
>>> +
>>> +int foo_s2f2 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f2[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f2 (3));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c
>>> new file mode 100644
>>> index 0000000..f273d58
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c
>>> @@ -0,0 +1,27 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v16 __attribute__ ((vector_size (16)));
>>> +
>>> +struct S1
>>> +{
>>> + v16 s1f1;
>>> +};
>>> +
>>> +int foo_s1f1 (int i)
>>> +{
>>> + register struct S1 b asm ("xmm0");
>>> + return b.s1f1[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s1f1 (-1));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c
>>> new file mode 100644
>>> index 0000000..aa8f7b9
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c
>>> @@ -0,0 +1,24 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v16 __attribute__ ((vector_size (16)));
>>> +
>>> +struct S1
>>> +{
>>> + v16 s1f1;
>>> +};
>>> +
>>> +int foo_s1f1 (int i)
>>> +{
>>> + register struct S1 b asm ("xmm0");
>>> + return b.s1f1[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s1f1 (0));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c
>>> new file mode 100644
>>> index 0000000..3d0c9b2
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c
>>> @@ -0,0 +1,27 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v16 __attribute__ ((vector_size (16)));
>>> +
>>> +struct S1
>>> +{
>>> + v16 s1f1;
>>> +};
>>> +
>>> +int foo_s1f1 (int i)
>>> +{
>>> + register struct S1 b asm ("xmm0");
>>> + return b.s1f1[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s1f1 (7));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c
>>> new file mode 100644
>>> index 0000000..e81b942
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c
>>> @@ -0,0 +1,31 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S2
>>> +{
>>> + v8 s2f2;
>>> + int* f3;
>>> +};
>>> +
>>> +int foo (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + int k = 5;
>>> + b.f3 = &k;
>>> + b.f3 = b.f3 + i;
>>> + return *b.f3;
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo (-1));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c
>>> new file mode 100644
>>> index 0000000..4b1f1ac
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c
>>> @@ -0,0 +1,28 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S2
>>> +{
>>> + v8 s2f2;
>>> + int* f3;
>>> +};
>>> +
>>> +int foo (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + int k = 5;
>>> + b.f3 = &k;
>>> + b.f3 = b.f3 + i;
>>> + return *b.f3;
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo (0));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c
>>> new file mode 100644
>>> index 0000000..e95e68f
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c
>>> @@ -0,0 +1,31 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S2
>>> +{
>>> + v8 s2f2;
>>> + int* f3;
>>> +};
>>> +
>>> +int foo (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + int k = 5;
>>> + b.f3 = &k;
>>> + b.f3 = b.f3 + i;
>>> + return *b.f3;
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo (1));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c
>>> new file mode 100644
>>> index 0000000..201b62d
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c
>>> @@ -0,0 +1,32 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1[2];
>>> +};
>>> +
>>> +int foo_s2f1 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f1[0].s1f[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f1 (-1));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c
>>> new file mode 100644
>>> index 0000000..f94a879
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c
>>> @@ -0,0 +1,30 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1[2];
>>> +};
>>> +
>>> +int foo_s2f1 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f1[0].s1f[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f1 (1));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c
>>> new file mode 100644
>>> index 0000000..6ab981d
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c
>>> @@ -0,0 +1,32 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1[2];
>>> +};
>>> +
>>> +int foo_s2f1 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f1[0].s1f[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f1 (4));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c
>>> new file mode 100644
>>> index 0000000..cc58e8a
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c
>>> @@ -0,0 +1,32 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1[2];
>>> +};
>>> +
>>> +int foo_s2f1 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f1[1].s1f[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f1 (-1));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c
>>> new file mode 100644
>>> index 0000000..5898c3b
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c
>>> @@ -0,0 +1,30 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1[2];
>>> +};
>>> +
>>> +int foo_s2f1 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f1[1].s1f[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f1 (1));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c
>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c
>>> new file mode 100644
>>> index 0000000..2910795
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c
>>> @@ -0,0 +1,32 @@
>>> +/* { dg-do run } */
>>> +/* { dg-shouldfail "bounds violation" } */
>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>> +
>>> +
>>> +#define SHOULDFAIL
>>> +
>>> +#include "mpx-check.h"
>>> +
>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>> +
>>> +struct S1
>>> +{
>>> + v8 s1f;
>>> +};
>>> +
>>> +struct S2
>>> +{
>>> + struct S1 s2f1[2];
>>> +};
>>> +
>>> +int foo_s2f1 (int i)
>>> +{
>>> + register struct S2 b asm ("xmm0");
>>> + return b.s2f1[1].s1f[i];
>>> +}
>>> +
>>> +int mpx_test (int argc, const char **argv)
>>> +{
>>> + printf ("%d\n", foo_s2f1 (4));
>>> + return 0;
>>> +}
>>> diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c
>>> index b1ff218..6a48a55 100644
>>> --- a/gcc/tree-chkp.c
>>> +++ b/gcc/tree-chkp.c
>>> @@ -679,6 +679,46 @@ chkp_erase_completed_bounds (void)
>>> chkp_completed_bounds_set = new hash_set<tree>;
>>> }
>>>
>>> +/* This function is used to provide a base address for
>>> + chkp_get_hard_register_fake_addr_expr. */
>>> +static tree
>>> +chkp_get_hard_register_var_fake_base_address ()
>>> +{
>>> + tree base = fold_convert (ptr_type_node, integer_zero_node);
>>> + unsigned HOST_WIDE_INT offset = 1 << (TYPE_PRECISION (ptr_type_node) - 1);
>>> + return fold_build_pointer_plus_hwi (base, offset);
>>> +}
>>> +
>>> +/* If we check bounds for a hard register variable, we cannot
>>> + use its address - it is illegal, so instead of that we use
>>> + this fake value. */
>>> +static tree
>>> +chkp_get_hard_register_fake_addr_expr (tree obj)
>>> +{
>>> + tree addr = chkp_get_hard_register_var_fake_base_address ();
>>> + tree outer = obj;
>>> + while (TREE_CODE (outer) == COMPONENT_REF || TREE_CODE (outer) == ARRAY_REF)
>>> + {
>>> + if (TREE_CODE (outer) == COMPONENT_REF)
>>> + {
>>> + addr = fold_build_pointer_plus (addr,
>>> + component_ref_field_offset (outer));
>>> + outer = TREE_OPERAND (outer, 0);
>>> + }
>>> + else if (TREE_CODE (outer) == ARRAY_REF)
>>> + {
>>> + tree indx = fold_convert(size_type_node, TREE_OPERAND(outer, 1));
>>> + tree offset = size_binop (MULT_EXPR,
>>> + array_ref_element_size (outer), indx);
>>> + addr = fold_build_pointer_plus (addr, offset);
>>> + outer = get_base_address (outer);
>>
>> Hi!
>>
>> I don't think get_base_address is what you want here because it goes to
>> the most inner base.
>>
>>> + }
>>> + }
>>> + gcc_assert (VAR_P (outer) && DECL_HARD_REGISTER (outer));
>>> +
>>> + return addr;
>>> +}
>>> +
>>> /* Mark BOUNDS associated with PTR as incomplete. */
>>> static void
>>> chkp_register_incomplete_bounds (tree bounds, tree ptr)
>>> @@ -1044,6 +1084,18 @@ chkp_add_modification_to_stmt_list (tree lhs,
>>> static tree
>>> chkp_build_addr_expr (tree obj)
>>> {
>>> + /* We first check whether it is a "hard reg case". */
>>> + tree outer = obj;
>>> + while (TREE_CODE (outer) == COMPONENT_REF
>>> + || TREE_CODE (outer) == ARRAY_REF)
>>> + if (TREE_CODE (outer) == COMPONENT_REF)
>>> + outer = TREE_OPERAND (outer, 0);
>>> + else
>>> + outer = get_base_address (outer);
>>
>> And here simple call to get_base_address might replace the whole loop.
>>
>>> + if (VAR_P (outer) && DECL_HARD_REGISTER (outer))
>>> + return chkp_get_hard_register_fake_addr_expr (obj);
>>> +
>>> + /* If not - return regular ADDR_EXPR. */
>>> return TREE_CODE (obj) == TARGET_MEM_REF
>>> ? tree_mem_ref_addr (ptr_type_node, obj)
>>> : build_fold_addr_expr (obj);
>>> @@ -3442,6 +3494,13 @@ chkp_parse_array_and_component_ref (tree node, tree *ptr,
>>> || TREE_CODE (var) == SSA_NAME);
>>>
>>> *ptr = chkp_build_addr_expr (var);
>>> +
>>> + /* For hard register cases chkp_build_addr_expr returns INTEGER_CST
>>> + and later on chkp_find_bounds will fail to find proper bounds.
>>> + In order to avoid that, we find/create bounds right aways using
>>> + the var itself. */
>>> + if (DECL_HARD_REGISTER (var))
>>> + *bounds = chkp_find_bounds (var, iter);
>>
>> Current semantics of this call is to get bounds for the pointer read from var.
>> I know we never get here fo pointer vars but still...
>>
>> I propose to just call chkp_make_addressed_object_bounds here instead of
>> chkp_find_bounds to avoid this non-intuitive interpretation of non-pointer
>> hardreg variable in chkp_find_bounds_1.
>>
>> BTW what if we have a structure with a pointer field or vector of pointers?
>> If we read this pointer then we might have some fun trying to find its bounds.
>> Let's make a test! :)
>>
>> Also what code do we produce now? Do we create static bounds variable
>> to hold fake bounds of hard reg variable? Is it initialized statically
>> or dynamically?
>>
>>> }
>>>
>>> /* In this loop we are trying to find a field access
>>> @@ -3639,6 +3698,8 @@ chkp_find_bounds_1 (tree ptr, tree ptr_src,
>>> gimple_stmt_iterator *iter)
>>> addr = chkp_build_addr_expr (ptr_src);
>>> bounds = chkp_build_bndldx (addr, ptr, iter);
>>> }
>>> + else if (VAR_P (ptr) && DECL_HARD_REGISTER (ptr))
>>> + bounds = chkp_make_addressed_object_bounds (ptr_src, iter);
>>> else
>>> bounds = chkp_get_nonpointer_load_bounds ();
>>> break;
>>>
>>>
>>>
>>>
>>>
>>> As before, the following added testcases fail because of PR80270:
>>
>> That makes hard to confirm patch correctness. Please at least check
>> GIMPLE for some of these tests are produced correctly by chkp phase.
>>
>> Overall this version looks much simpler and better. New MPX feature
>> to catch non-memory bounds violation is almost done!
>>
>> Thanks,
>> Ilya
>>
>>>
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O3 -g (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O3 -g (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto
>>> -fno-use-linker-plugin -flto-partition=none (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto
>>> -fno-use-linker-plugin -flto-partition=none (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto
>>> -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto
>>> -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O3 -g (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O3 -g (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto
>>> -fno-use-linker-plugin -flto-partition=none (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto
>>> -fno-use-linker-plugin -flto-partition=none (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto
>>> -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto
>>> -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-4-lbv.c -O0 (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-4-lbv.c -O0 (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-4-nov.c -O0 (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-4-nov.c -O0 (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-4-ubv.c -O0 (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-4-ubv.c -O0 (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O3 -g (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O3 -g (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto
>>> -fno-use-linker-plugin -flto-partition=none (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto
>>> -fno-use-linker-plugin -flto-partition=none (test for excess errors)
>>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto
>>> -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error)
>>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto
>>> -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors)
>>>
>>> hard-reg-4-* looks suspicious to me. May be we need to handle that
>>> case differently, but it is hard to say because of the ICE now.
>>>
>>>
>>> 2017-04-10 23:21 GMT+02:00 Ilya Enkovich <enkovich.gnu@gmail.com>:
>>>> 2017-04-02 23:52 GMT+03:00 Alexander Ivchenko <aivchenk@gmail.com>:
>>>>> Hi,
>>>>>
>>>>> Here is the patch that roughly follows your idea.
>>>>> Some comments:
>>>>>
>>>>> - There are more cases than array_ref overflow. We need to take care
>>>>> of component_ref and both underflows/overflows are possible
>>>>> - I could not make it work with "0" as a fake address, because then
>>>>> catching lower bounds violation is getting hard at O2 and above. E.g.
>>>>> consider this:
>>>>>
>>>>> 0x00000000004005f8 <+8>: bndmk 0x7(%rax),%bnd0
>>>>> 0x00000000004005fd <+13>: mov $0x400734,%edi
>>>>> => 0x0000000000400602 <+18>: bndcl 0xfffffffffffffffc,%bnd0
>>>>> (gdb) p $bnd0
>>>>> $1 = {lbound = 0x0, ubound = 0x7} : size 8
>>>>> 0x000000000040060b <+27>: callq 0x400500 <printf@plt>
>>>>>
>>>>> - bndcu is removed as not necessary and underflowed access is not
>>>>> caught. I used another fake value for lower bound address, which is
>>>>> 2^(bitness - 1)
>>>>
>>>> Hi,
>>>>
>>>> Looks like CHKP optimizations don't let us catch cases when pointer
>>>> arithmetc overflows. Using any fake value doesn't guarantee you don't
>>>> have overflow.
>>>>
>>>> This overoptimization is definately a separate issue. It should be easy
>>>> to write a test where usage of a huge index in array causes
>>>> uncought bounds violation because of removed bndcl/bndcu. You should
>>>> file a bug for that.
>>>>
>>>> If we don't try to work around overflow issues in this patch then using 0
>>>> should be more efficient because it allows you to always use bndcu only
>>>> (you just can't violate zero lower bound).
>>>>
>>>> BTW please don't forget ChangeLogs for your patches.
>>>>
>>>>>
>>>>> - hard-reg-3-[1,2]* tests fail with ICE right now because of PR80270.
>>>>> I will mark them as XFAIL if the patch is approved and the mentioned
>>>>> bug is not fixed
>>>>>
>>>>>
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c
>>>>> new file mode 100644
>>>>> index 0000000..319e1ec
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c
>>>>> @@ -0,0 +1,21 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-shouldfail "bounds violation" } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#define SHOULDFAIL
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v16 __attribute__((vector_size(16)));
>>>>> +
>>>>> +int foo(int i) {
>>>>> + register v16 u asm("xmm0");
>>>>> + return u[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo (-1));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c
>>>>> new file mode 100644
>>>>> index 0000000..3c6d39a
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c
>>>>> @@ -0,0 +1,18 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v16 __attribute__((vector_size(16)));
>>>>> +
>>>>> +int foo (int i) {
>>>>> + register v16 u asm ("xmm0");
>>>>> + return u[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo (3));
>>>>> + printf ("%d\n", foo (0));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c
>>>>> new file mode 100644
>>>>> index 0000000..7fe76c4
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c
>>>>> @@ -0,0 +1,21 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-shouldfail "bounds violation" } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#define SHOULDFAIL
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v16 __attribute__((vector_size(16)));
>>>>> +
>>>>> +int foo (int i) {
>>>>> + register v16 u asm ("xmm0");
>>>>> + return u[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo (5));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c
>>>>> new file mode 100644
>>>>> index 0000000..7e4451f
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c
>>>>> @@ -0,0 +1,33 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-shouldfail "bounds violation" } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#define SHOULDFAIL
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>>>> +
>>>>> +struct S1
>>>>> +{
>>>>> + v8 s1f;
>>>>> +};
>>>>> +
>>>>> +struct S2
>>>>> +{
>>>>> + struct S1 s2f1;
>>>>> + v8 s2f2;
>>>>> +};
>>>>> +
>>>>> +int foo_s2f1 (int i)
>>>>> +{
>>>>> + register struct S2 b asm ("xmm0");
>>>>> + return b.s2f1.s1f[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo_s2f1 (-1));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c
>>>>> new file mode 100644
>>>>> index 0000000..73bd7fb
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c
>>>>> @@ -0,0 +1,30 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>>>> +
>>>>> +struct S1
>>>>> +{
>>>>> + v8 s1f;
>>>>> +};
>>>>> +
>>>>> +struct S2
>>>>> +{
>>>>> + struct S1 s2f1;
>>>>> + v8 s2f2;
>>>>> +};
>>>>> +
>>>>> +int foo_s2f1 (int i)
>>>>> +{
>>>>> + register struct S2 b asm ("xmm0");
>>>>> + return b.s2f1.s1f[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo_s2f1 (0));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c
>>>>> new file mode 100644
>>>>> index 0000000..166b6b9
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c
>>>>> @@ -0,0 +1,33 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-shouldfail "bounds violation" } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#define SHOULDFAIL
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>>>> +
>>>>> +struct S1
>>>>> +{
>>>>> + v8 s1f;
>>>>> +};
>>>>> +
>>>>> +struct S2
>>>>> +{
>>>>> + struct S1 s2f1;
>>>>> + v8 s2f2;
>>>>> +};
>>>>> +
>>>>> +int foo_s2f1 (int i)
>>>>> +{
>>>>> + register struct S2 b asm ("xmm0");
>>>>> + return b.s2f1.s1f[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo_s2f1 (3));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c
>>>>> new file mode 100644
>>>>> index 0000000..7820c2f
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c
>>>>> @@ -0,0 +1,33 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-shouldfail "bounds violation" } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#define SHOULDFAIL
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>>>> +
>>>>> +struct S1
>>>>> +{
>>>>> + v8 s1f;
>>>>> +};
>>>>> +
>>>>> +struct S2
>>>>> +{
>>>>> + struct S1 s2f1;
>>>>> + v8 s2f2;
>>>>> +};
>>>>> +
>>>>> +int foo_s2f2 (int i)
>>>>> +{
>>>>> + register struct S2 b asm ("xmm0");
>>>>> + return b.s2f2[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo_s2f2 (-1));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c
>>>>> new file mode 100644
>>>>> index 0000000..0816e58
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c
>>>>> @@ -0,0 +1,30 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>>>> +
>>>>> +struct S1
>>>>> +{
>>>>> + v8 s1f;
>>>>> +};
>>>>> +
>>>>> +struct S2
>>>>> +{
>>>>> + struct S1 s2f1;
>>>>> + v8 s2f2;
>>>>> +};
>>>>> +
>>>>> +int foo_s2f2 (int i)
>>>>> +{
>>>>> + register struct S2 b asm ("xmm0");
>>>>> + return b.s2f2[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo_s2f2 (0));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c
>>>>> new file mode 100644
>>>>> index 0000000..94261a7
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c
>>>>> @@ -0,0 +1,33 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-shouldfail "bounds violation" } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#define SHOULDFAIL
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>>>> +
>>>>> +struct S1
>>>>> +{
>>>>> + v8 s1f;
>>>>> +};
>>>>> +
>>>>> +struct S2
>>>>> +{
>>>>> + struct S1 s2f1;
>>>>> + v8 s2f2;
>>>>> +};
>>>>> +
>>>>> +int foo_s2f2 (int i)
>>>>> +{
>>>>> + register struct S2 b asm ("xmm0");
>>>>> + return b.s2f2[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo_s2f2 (3));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c
>>>>> new file mode 100644
>>>>> index 0000000..f273d58
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c
>>>>> @@ -0,0 +1,27 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-shouldfail "bounds violation" } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#define SHOULDFAIL
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v16 __attribute__ ((vector_size (16)));
>>>>> +
>>>>> +struct S1
>>>>> +{
>>>>> + v16 s1f1;
>>>>> +};
>>>>> +
>>>>> +int foo_s1f1 (int i)
>>>>> +{
>>>>> + register struct S1 b asm ("xmm0");
>>>>> + return b.s1f1[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo_s1f1 (-1));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c
>>>>> new file mode 100644
>>>>> index 0000000..aa8f7b9
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c
>>>>> @@ -0,0 +1,24 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v16 __attribute__ ((vector_size (16)));
>>>>> +
>>>>> +struct S1
>>>>> +{
>>>>> + v16 s1f1;
>>>>> +};
>>>>> +
>>>>> +int foo_s1f1 (int i)
>>>>> +{
>>>>> + register struct S1 b asm ("xmm0");
>>>>> + return b.s1f1[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo_s1f1 (0));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c
>>>>> new file mode 100644
>>>>> index 0000000..3d0c9b2
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c
>>>>> @@ -0,0 +1,27 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-shouldfail "bounds violation" } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#define SHOULDFAIL
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v16 __attribute__ ((vector_size (16)));
>>>>> +
>>>>> +struct S1
>>>>> +{
>>>>> + v16 s1f1;
>>>>> +};
>>>>> +
>>>>> +int foo_s1f1 (int i)
>>>>> +{
>>>>> + register struct S1 b asm ("xmm0");
>>>>> + return b.s1f1[i];
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo_s1f1 (7));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c
>>>>> new file mode 100644
>>>>> index 0000000..e81b942
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c
>>>>> @@ -0,0 +1,31 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-shouldfail "bounds violation" } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#define SHOULDFAIL
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>>>> +
>>>>> +struct S2
>>>>> +{
>>>>> + v8 s2f2;
>>>>> + int* f3;
>>>>> +};
>>>>> +
>>>>> +int foo (int i)
>>>>> +{
>>>>> + register struct S2 b asm ("xmm0");
>>>>> + int k = 5;
>>>>> + b.f3 = &k;
>>>>> + b.f3 = b.f3 + i;
>>>>> + return *b.f3;
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo (-1));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c
>>>>> new file mode 100644
>>>>> index 0000000..4b1f1ac
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c
>>>>> @@ -0,0 +1,28 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>>>> +
>>>>> +struct S2
>>>>> +{
>>>>> + v8 s2f2;
>>>>> + int* f3;
>>>>> +};
>>>>> +
>>>>> +int foo (int i)
>>>>> +{
>>>>> + register struct S2 b asm ("xmm0");
>>>>> + int k = 5;
>>>>> + b.f3 = &k;
>>>>> + b.f3 = b.f3 + i;
>>>>> + return *b.f3;
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo (0));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c
>>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c
>>>>> new file mode 100644
>>>>> index 0000000..e95e68f
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c
>>>>> @@ -0,0 +1,31 @@
>>>>> +/* { dg-do run } */
>>>>> +/* { dg-shouldfail "bounds violation" } */
>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>> +
>>>>> +
>>>>> +#define SHOULDFAIL
>>>>> +
>>>>> +#include "mpx-check.h"
>>>>> +
>>>>> +typedef int v8 __attribute__ ((vector_size (8)));
>>>>> +
>>>>> +struct S2
>>>>> +{
>>>>> + v8 s2f2;
>>>>> + int* f3;
>>>>> +};
>>>>> +
>>>>> +int foo (int i)
>>>>> +{
>>>>> + register struct S2 b asm ("xmm0");
>>>>> + int k = 5;
>>>>> + b.f3 = &k;
>>>>> + b.f3 = b.f3 + i;
>>>>> + return *b.f3;
>>>>> +}
>>>>> +
>>>>> +int mpx_test (int argc, const char **argv)
>>>>> +{
>>>>> + printf ("%d\n", foo (1));
>>>>> + return 0;
>>>>> +}
>>>>> diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c
>>>>> index b1ff218..15c0da6 100644
>>>>> --- a/gcc/tree-chkp.c
>>>>> +++ b/gcc/tree-chkp.c
>>>>> @@ -679,6 +679,17 @@ chkp_erase_completed_bounds (void)
>>>>> chkp_completed_bounds_set = new hash_set<tree>;
>>>>> }
>>>>>
>>>>> +/* If we check bounds for a hard register variable, we cannot
>>>>> + use its address - it is illegal, so instead of that we use
>>>>> + this fake value. */
>>>>> +static tree
>>>>> +chkp_get_hard_register_var_fake_address ()
>>>>> +{
>>>>> + tree base = fold_convert (ptr_type_node, integer_zero_node);
>>>>> + unsigned HOST_WIDE_INT offset = 1 << (TYPE_PRECISION (ptr_type_node) - 1);
>>>>> + return fold_build_pointer_plus_hwi (base, offset);
>>>>> +}
>>>>> +
>>>>> /* Mark BOUNDS associated with PTR as incomplete. */
>>>>> static void
>>>>> chkp_register_incomplete_bounds (tree bounds, tree ptr)
>>>>> @@ -1040,10 +1051,24 @@ chkp_add_modification_to_stmt_list (tree lhs,
>>>>> stmts->avail--;
>>>>> }
>>>>>
>>>>> -/* Build and return ADDR_EXPR for specified object OBJ. */
>>>>> +/* Build and return ADDR_EXPR for specified object OBJ.
>>>>> + There is a special case for which we cannot return
>>>>> + ADDR_EXPR - if the object is declared to be placed
>>>>> + on a fixed hard register - in this case we cannot
>>>>> + take its address, so we use the object itself. The
>>>>> + caller of this function must be aware of that and
>>>>> + use proper checks if necessary. */
>>>>
>>>> I don't follow the idea of this change.
>>>>
>>>> If we want to use fake address for register vars then why not to
>>>> return this fake value by this function? In case of accessing a
>>>> component of register var we should return fake value + required
>>>> offset then.
>>>>
>>>>> static tree
>>>>> chkp_build_addr_expr (tree obj)
>>>>> {
>>>>> + /* We first check whether it is a "hard reg case". */
>>>>> + tree outer = obj;
>>>>> + while (TREE_CODE (outer) == COMPONENT_REF)
>>>>> + outer = TREE_OPERAND (outer, 0);
>>>>
>>>> What about ARRAY_REF? Probably get_base_address is what you need.
>>>>
>>>>> + if (VAR_P (outer) && DECL_HARD_REGISTER (outer))
>>>>> + return obj;
>>>>> +
>>>>> + /* If not - return regular ADDR_EXPR. */
>>>>> return TREE_CODE (obj) == TARGET_MEM_REF
>>>>> ? tree_mem_ref_addr (ptr_type_node, obj)
>>>>> : build_fold_addr_expr (obj);
>>>>> @@ -3170,6 +3195,11 @@ chkp_get_bounds_for_decl_addr (tree decl)
>>>>> gcc_assert (VAR_P (decl));
>>>>> bounds = chkp_generate_extern_var_bounds (decl);
>>>>> }
>>>>> + else if (VAR_P (decl) && DECL_HARD_REGISTER (decl))
>>>>> + {
>>>>> + tree lb = chkp_get_hard_register_var_fake_address ();
>>>>> + bounds = chkp_make_bounds(lb, DECL_SIZE_UNIT (decl), NULL, false);
>>>>> + }
>>>>> else
>>>>> {
>>>>> tree lb = chkp_build_addr_expr (decl);
>>>>> @@ -3351,6 +3381,8 @@ chkp_narrow_bounds_to_field (tree bounds, tree component,
>>>>> tree field_ptr = chkp_build_addr_expr (component);
>>>>> tree field_bounds;
>>>>>
>>>>> + if (!BOUNDED_P (field_ptr))
>>>>> + field_ptr = chkp_get_hard_register_var_fake_address ();
>>>>
>>>> This gives you fake pointer instead of fake pointer + offset. No?
>>>>
>>>>> field_bounds = chkp_make_bounds (field_ptr, size, iter, false);
>>>>>
>>>>> return chkp_intersect_bounds (field_bounds, bounds, iter);
>>>>> @@ -3639,6 +3671,8 @@ chkp_find_bounds_1 (tree ptr, tree ptr_src,
>>>>> gimple_stmt_iterator *iter)
>>>>> addr = chkp_build_addr_expr (ptr_src);
>>>>> bounds = chkp_build_bndldx (addr, ptr, iter);
>>>>> }
>>>>> + else if (VAR_P (ptr) && DECL_HARD_REGISTER (ptr))
>>>>> + bounds = chkp_make_addressed_object_bounds (ptr_src, iter);
>>>>
>>>> I don't get what this piece of code is for.
>>>>
>>>>> else
>>>>> bounds = chkp_get_nonpointer_load_bounds ();
>>>>> break;
>>>>> @@ -4031,7 +4065,19 @@ chkp_process_stmt (gimple_stmt_iterator *iter, tree node,
>>>>> addr_first,
>>>>> byte_position (field));
>>>>> }
>>>>> - else
>>>>> + else if (VAR_P (ptr) && DECL_HARD_REGISTER (ptr))
>>>>> + {
>>>>> + gcc_assert (TREE_CODE (node) == ARRAY_REF
>>>>> + || TREE_CODE (node) == COMPONENT_REF);
>>>>
>>>> This may never hit because this code is in a switch block filtering
>>>> node to ARRAY_REF and COMPONENT_REF already.
>>>>
>>>>> +
>>>>> + tree base = chkp_get_hard_register_var_fake_address ();
>>>>> + tree indx = fold_convert_loc (loc,
>>>>> + size_type_node,
>>>>> + TREE_OPERAND (node, 1));
>>>>
>>>> Code looks like it expects ARRAY_REF only but COMPONENT_REF
>>>> is also possible.
>>>>
>>>>> + tree offset = size_binop_loc (loc, MULT_EXPR, size, indx);
>>>>
>>>> 'size' here holds a size of memory access, not size of array element.
>>>>
>>>> Overall it looks like all you need is a proper fix in chkp_build_addr_expr
>>>> to use fake value when required. Many (all?) other changes might just
>>>> go away then.
>>>>
>>>> Thanks,
>>>> Ilya
>>>>
>>>>> + addr_first = fold_build_pointer_plus_loc (loc, base, offset);
>>>>> + }
>>>>> + else
>>>>> addr_first = chkp_build_addr_expr (node);
>>>>> }
>>>>> break;
>>>>>
>>>>> 2017-03-23 20:57 GMT+01:00 Ilya Enkovich <enkovich.gnu@gmail.com>:
>>>>>> 2017-03-23 17:18 GMT+03:00 Alexander Ivchenko <aivchenk@gmail.com>:
>>>>>>> Hi,
>>>>>>>
>>>>>>> The patch below attempts to fix the PR. I checked that it did not
>>>>>>> break any of mpx.exp tests, but I did not run the full testing yet.
>>>>>>> Would like to know whether this approach is generally correct or not.
>>>>>>>
>>>>>>> The issue is that we have the hard reg vector variable:
>>>>>>>
>>>>>>> typedef int U __attribute__ ((vector_size (16)));
>>>>>>> register U u asm("xmm0");
>>>>>>>
>>>>>>> and chkp tries to instrument access to it:
>>>>>>>
>>>>>>> return u[i];
>>>>>>>
>>>>>>> by doing that:
>>>>>>>
>>>>>>> __bound_tmp.0_4 = __builtin_ia32_bndmk (&u, 16);
>>>>>>>
>>>>>>> However, you cannot take an address of a register variable (in fact if
>>>>>>> you do that, the compiler will give you "address of register variable
>>>>>>> ‘u’ requested" error), so expand, sensibly, gives an ICE on on &u
>>>>>>> here. I believe that if there is no pointers, pointer bounds checker
>>>>>>> shouldn't get involved into that business. What do you think?
>>>>>>
>>>>>> Hi!
>>>>>>
>>>>>> I think with this patch I can call foo with any index and thus access
>>>>>> some random stack slot. The first thing we should answer is 'do we
>>>>>> want to catch array index overflows in such cases'? If we want to (and
>>>>>> this looks reasonable thing to do because it prevents invalid memory
>>>>>> accesses) then this patch doesn't resolve the problem.
>>>>>>
>>>>>> I'm not sure it can affect the patch, but please consider more complex
>>>>>> cases. E.g.:
>>>>>>
>>>>>> typedef int v8 __attribute__ ((vector_size(8)));
>>>>>>
>>>>>> struct U {
>>>>>> v8 a;
>>>>>> v8 b;
>>>>>> };
>>>>>>
>>>>>> int
>>>>>> foo (int i)
>>>>>> {
>>>>>> register struct U u asm ("xmm0");
>>>>>> return u.b[i];
>>>>>> }
>>>>>>
>>>>>> One way to catch overflow in such cases might be to use some fake
>>>>>> pointer value (e.g. 0) for such not addressible variable. This fake value
>>>>>> would be used as base for memory access and as lower bound. I don't
>>>>>> see other cases except array_ref overflow check where such value
>>>>>> might be used. So this fake value will not be passed somewhere and
>>>>>> will not be stored to Bounds Table.
>>>>>>
>>>>>> Thanks,
>>>>>> Ilya
>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c
>>>>>>> index 75caf83..e39ec9a 100644
>>>>>>> --- a/gcc/tree-chkp.c
>>>>>>> +++ b/gcc/tree-chkp.c
>>>>>>> @@ -3383,6 +3383,7 @@ chkp_parse_array_and_component_ref (tree node, tree *ptr,
>>>>>>> tree comp_to_narrow = NULL_TREE;
>>>>>>> tree last_comp = NULL_TREE;
>>>>>>> bool array_ref_found = false;
>>>>>>> + bool is_register_var = false;
>>>>>>> tree *nodes;
>>>>>>> tree var;
>>>>>>> int len;
>>>>>>> @@ -3440,6 +3441,9 @@ chkp_parse_array_and_component_ref (tree node, tree *ptr,
>>>>>>> || TREE_CODE (var) == STRING_CST
>>>>>>> || TREE_CODE (var) == SSA_NAME);
>>>>>>>
>>>>>>> + if (VAR_P (var) && DECL_HARD_REGISTER (var))
>>>>>>> + is_register_var = true;
>>>>>>> +
>>>>>>> *ptr = chkp_build_addr_expr (var);
>>>>>>> }
>>>>>>>
>>>>>>> @@ -3455,7 +3459,11 @@ chkp_parse_array_and_component_ref (tree node, tree *ptr,
>>>>>>>
>>>>>>> if (TREE_CODE (var) == ARRAY_REF)
>>>>>>> {
>>>>>>> - *safe = false;
>>>>>>> + // Mark it as unsafe, unless the array being accessed
>>>>>>> + // has been explicitly placed on a register: in this
>>>>>>> + // case we cannot take a pointer of this variable,
>>>>>>> + // so we don't instrument the access.
>>>>>>> + *safe = is_register_var;
>>>>>>> array_ref_found = true;
>>>>>>> if (flag_chkp_narrow_bounds
>>>>>>> && !flag_chkp_narrow_to_innermost_arrray
>>>>>>> @@ -4001,6 +4009,19 @@ chkp_process_stmt (gimple_stmt_iterator *iter, tree node,
>>>>>>> bool bitfield;
>>>>>>> tree elt;
>>>>>>>
>>>>>>> + {
>>>>>>> + // We don't instrument accesses to arrays that
>>>>>>> + // are explicitely assigned to hard registers.
>>>>>>> + HOST_WIDE_INT bitsize, bitpos;
>>>>>>> + tree base, offset;
>>>>>>> + machine_mode mode;
>>>>>>> + int unsignedp, reversep, volatilep = 0;
>>>>>>> + base = get_inner_reference (node, &bitsize, &bitpos, &offset, &mode,
>>>>>>> + &unsignedp, &reversep, &volatilep);
>>>>>>> + if (VAR_P (base) && DECL_HARD_REGISTER (base))
>>>>>>> + safe = true;
>>>>>>> + }
>>>>>>> +
>>>>>>> if (safe)
>>>>>>> {
>>>>>>> /* We are not going to generate any checks, so do not
>>>>>>>
>>>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/pr79990.c
>>>>>>> b/gcc/testsuite/gcc.target/i386/mpx/pr79990.c
>>>>>>> new file mode 100644
>>>>>>> index 0000000..a27734d
>>>>>>> --- /dev/null
>>>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/pr79990.c
>>>>>>> @@ -0,0 +1,18 @@
>>>>>>> +/* { dg-do compile } */
>>>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
>>>>>>> +
>>>>>>> +typedef int U __attribute__ ((vector_size (16)));
>>>>>>> +
>>>>>>> +int
>>>>>>> +foo (int i)
>>>>>>> +{
>>>>>>> +#if __SSE2__
>>>>>>> + register
>>>>>>> +#endif
>>>>>>> + U u
>>>>>>> +#if __SSE2__
>>>>>>> + asm ("xmm0")
>>>>>>> +#endif
>>>>>>> + ;
>>>>>>> + return u[i];
>>>>>>> +}
>>>>>>>
>>>>>>> regards,
>>>>>>> Alexander