[CHKP] Fix for PR79990

Submitted by Alexander Ivchenko on April 19, 2017, 4:48 p.m.

Details

Message ID CACysShiE3Orf93-gFzaO+BmbAmb3qhcQMB--ai5K1ULzGpxTBA@mail.gmail.com
State New
Headers show

Commit Message

Alexander Ivchenko April 19, 2017, 4:48 p.m.
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:

       break;





As before, the following added testcases fail because of PR80270:

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

Patch hide | download patch | download mbox

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);
+ }
+    }
+  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);
+  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);
     }

   /* 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 ();