diff mbox

[CHKP] Fix for PR79990

Message ID CACysShggeodsjLKfm1vChGi6O+Fj3B5NFdNnamQAeB0TKE_h7A@mail.gmail.com
State New
Headers show

Commit Message

Alexander Ivchenko April 21, 2017, 3:13 p.m. UTC
Something like that?

          || TREE_CODE (addr) == TARGET_MEM_REF)

Here is the tree-chkp dump of the same function after this change:

__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;

  <bb 4> [0.00%]:
  __bound_tmp.1_15 = __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;
  _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;
  _11 = *_5;
  k ={v} {CLOBBER};
  return _11;

}

Doesn't work.. let me look a little deeper.

Alexander

2017-04-20 19:17 GMT+02:00 Ilya Enkovich <enkovich.gnu@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
diff mbox

Patch

diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c
index 3ef73a9..3fb76bc 100644
--- a/gcc/tree-chkp.c
+++ b/gcc/tree-chkp.c
@@ -3700,6 +3700,11 @@  chkp_find_bounds_1 (tree ptr, tree ptr_src,
gimple_stmt_iterator *iter)
     case ARRAY_REF:
     case COMPONENT_REF:
       addr = get_base_address (ptr_src);
+      if (VAR_P (addr) && DECL_HARD_REGISTER (addr))
+       {
+         bounds = chkp_get_zero_bounds ();
+         break;
+       }
       if (DECL_P (addr)
          || TREE_CODE (addr) == MEM_REF