public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [CHKP] Fix for PR79990
@ 2017-03-23 14:19 Alexander Ivchenko
  2017-03-23 20:34 ` Ilya Enkovich
  0 siblings, 1 reply; 12+ messages in thread
From: Alexander Ivchenko @ 2017-03-23 14:19 UTC (permalink / raw)
  To: Ilya Enkovich, marxin, GCC Patches

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?




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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [CHKP] Fix for PR79990
  2017-03-23 14:19 [CHKP] Fix for PR79990 Alexander Ivchenko
@ 2017-03-23 20:34 ` Ilya Enkovich
  2017-04-02 20:53   ` Alexander Ivchenko
  0 siblings, 1 reply; 12+ messages in thread
From: Ilya Enkovich @ 2017-03-23 20:34 UTC (permalink / raw)
  To: Alexander Ivchenko; +Cc: marxin, GCC Patches

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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [CHKP] Fix for PR79990
  2017-03-23 20:34 ` Ilya Enkovich
@ 2017-04-02 20:53   ` Alexander Ivchenko
  2017-04-10 21:22     ` Ilya Enkovich
  0 siblings, 1 reply; 12+ messages in thread
From: Alexander Ivchenko @ 2017-04-02 20:53 UTC (permalink / raw)
  To: Ilya Enkovich; +Cc: marxin, GCC Patches

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)

- 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.  */
 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);
+  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 ();
   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);
       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);
+
+    tree base = chkp_get_hard_register_var_fake_address ();
+    tree indx = fold_convert_loc (loc,
+  size_type_node,
+  TREE_OPERAND (node, 1));
+    tree offset = size_binop_loc (loc, MULT_EXPR, size, indx);
+    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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [CHKP] Fix for PR79990
  2017-04-02 20:53   ` Alexander Ivchenko
@ 2017-04-10 21:22     ` Ilya Enkovich
  2017-04-19 16:56       ` Alexander Ivchenko
  0 siblings, 1 reply; 12+ messages in thread
From: Ilya Enkovich @ 2017-04-10 21:22 UTC (permalink / raw)
  To: Alexander Ivchenko; +Cc: marxin, GCC Patches

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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [CHKP] Fix for PR79990
  2017-04-10 21:22     ` Ilya Enkovich
@ 2017-04-19 16:56       ` Alexander Ivchenko
       [not found]         ` <CAMbmDYZ+DDk-=hHzg-Qogawdee2R7XzGhEokbcXA5NhgiYs4ww@mail.gmail.com>
  0 siblings, 1 reply; 12+ messages in thread
From: Alexander Ivchenko @ 2017-04-19 16:56 UTC (permalink / raw)
  To: Ilya Enkovich; +Cc: marxin, GCC Patches

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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [CHKP] Fix for PR79990
       [not found]         ` <CAMbmDYZ+DDk-=hHzg-Qogawdee2R7XzGhEokbcXA5NhgiYs4ww@mail.gmail.com>
@ 2017-04-20  9:54           ` Alexander Ivchenko
  2017-04-20 17:46             ` Ilya Enkovich
  0 siblings, 1 reply; 12+ messages in thread
From: Alexander Ivchenko @ 2017-04-20  9:54 UTC (permalink / raw)
  To: Ilya Enkovich; +Cc: GCC Patches

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.

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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [CHKP] Fix for PR79990
  2017-04-20  9:54           ` Alexander Ivchenko
@ 2017-04-20 17:46             ` Ilya Enkovich
  2017-04-21 18:31               ` Alexander Ivchenko
  0 siblings, 1 reply; 12+ messages in thread
From: Ilya Enkovich @ 2017-04-20 17:46 UTC (permalink / raw)
  To: Alexander Ivchenko; +Cc: GCC Patches

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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [CHKP] Fix for PR79990
  2017-04-20 17:46             ` Ilya Enkovich
@ 2017-04-21 18:31               ` Alexander Ivchenko
  2017-05-09 13:33                 ` Alexander Ivchenko
  0 siblings, 1 reply; 12+ messages in thread
From: Alexander Ivchenko @ 2017-04-21 18:31 UTC (permalink / raw)
  To: Ilya Enkovich; +Cc: GCC Patches

Something like that?

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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [CHKP] Fix for PR79990
  2017-04-21 18:31               ` Alexander Ivchenko
@ 2017-05-09 13:33                 ` Alexander Ivchenko
  2017-05-10 17:20                   ` Ilya Enkovich
  2017-06-08 19:45                   ` [PATCH] Fix mpx testcases (Re: [CHKP] Fix for PR79990) Jakub Jelinek
  0 siblings, 2 replies; 12+ messages in thread
From: Alexander Ivchenko @ 2017-05-09 13:33 UTC (permalink / raw)
  To: Ilya Enkovich; +Cc: GCC Patches

Hi,

Here is the latest version of the patch with all comments addressed:

gcc/ChangeLog:

2017-05-09  Alexander Ivchenko  <aivchenk@gmail.com>

        * tree-chkp.c (chkp_get_hard_register_var_fake_base_address):
New function.
        (chkp_get_hard_register_fake_addr_expr): Ditto.
        (chkp_build_addr_expr): Add check for hard reg case.
        (chkp_parse_array_and_component_ref): Ditto.
        (chkp_find_bounds_1): Ditto.
        (chkp_process_stmt): Don't generate bounds store for
hard reg case.


gcc/testsuite/ChangeLog:

2017-05-09  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-1-lbv.c: New test.
        * gcc.target/i386/mpx/hard-reg-4-1-nov.c: New test.
        * gcc.target/i386/mpx/hard-reg-4-1-ubv.c: New test.
        * gcc.target/i386/mpx/hard-reg-4-2-lbv.c: New test.
        * gcc.target/i386/mpx/hard-reg-4-2-nov.c: New test.
        * gcc.target/i386/mpx/hard-reg-4-2-ubv.c: New test.


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-1-lbv.c
b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-1-lbv.c
new file mode 100644
index 0000000..201b62d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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-4-1-nov.c
b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-1-nov.c
new file mode 100644
index 0000000..f94a879
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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-4-1-ubv.c
b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-1-ubv.c
new file mode 100644
index 0000000..6ab981d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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-4-2-lbv.c
b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-2-lbv.c
new file mode 100644
index 0000000..cc58e8a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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-4-2-nov.c
b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-2-nov.c
new file mode 100644
index 0000000..5898c3b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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-4-2-ubv.c
b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-2-ubv.c
new file mode 100644
index 0000000..2910795
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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 23f5af9..852ca7b 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 (VAR_P (var) && DECL_HARD_REGISTER (var))
+ *bounds = chkp_make_addressed_object_bounds (var, iter);
     }

   /* In this loop we are trying to find a field access
@@ -3646,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
   || TREE_CODE (addr) == TARGET_MEM_REF)
@@ -3989,6 +4048,7 @@ chkp_process_stmt (gimple_stmt_iterator *iter, tree node,
   tree addr_last = NULL_TREE; /* address of the last accessed byte */
   tree ptr = NULL_TREE; /* a pointer used for dereference */
   tree bounds = NULL_TREE;
+  bool reg_store = false;

   /* We do not need instrumentation for clobbers.  */
   if (dirflag == integer_one_node
@@ -4103,6 +4163,13 @@ chkp_process_stmt (gimple_stmt_iterator *iter, tree node,
       addr_last = fold_build_pointer_plus_loc (loc, addr_last, access_offs);
     }

+  if (dirflag == integer_one_node)
+    {
+      tree base = get_base_address (node);
+      if (VAR_P (base) && DECL_HARD_REGISTER (base))
+ reg_store = true;
+    }
+
   /* Generate bndcl/bndcu checks if memory access is not safe.  */
   if (!safe)
     {
@@ -4117,6 +4184,7 @@ chkp_process_stmt (gimple_stmt_iterator *iter, tree node,

   /* We need to store bounds in case pointer is stored.  */
   if (dirflag == integer_one_node
+      && !reg_store
       && chkp_type_has_pointer (node_type)
       && flag_chkp_store_bounds)
     {

Is it OK?

thanks,
Alexander

2017-04-21 17:13 GMT+02:00 Alexander Ivchenko <aivchenk@gmail.com>:
> Something like that?
>
> 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
>           || 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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [CHKP] Fix for PR79990
  2017-05-09 13:33                 ` Alexander Ivchenko
@ 2017-05-10 17:20                   ` Ilya Enkovich
  2017-06-08 19:45                   ` [PATCH] Fix mpx testcases (Re: [CHKP] Fix for PR79990) Jakub Jelinek
  1 sibling, 0 replies; 12+ messages in thread
From: Ilya Enkovich @ 2017-05-10 17:20 UTC (permalink / raw)
  To: Alexander Ivchenko; +Cc: GCC Patches

2017-05-09 16:29 GMT+03:00 Alexander Ivchenko <aivchenk@gmail.com>:
> Hi,
>
> Here is the latest version of the patch with all comments addressed:
>
> gcc/ChangeLog:
>
> 2017-05-09  Alexander Ivchenko  <aivchenk@gmail.com>
>
>         * tree-chkp.c (chkp_get_hard_register_var_fake_base_address):
> New function.
>         (chkp_get_hard_register_fake_addr_expr): Ditto.
>         (chkp_build_addr_expr): Add check for hard reg case.
>         (chkp_parse_array_and_component_ref): Ditto.
>         (chkp_find_bounds_1): Ditto.
>         (chkp_process_stmt): Don't generate bounds store for
> hard reg case.
>
>
> gcc/testsuite/ChangeLog:
>
> 2017-05-09  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-1-lbv.c: New test.
>         * gcc.target/i386/mpx/hard-reg-4-1-nov.c: New test.
>         * gcc.target/i386/mpx/hard-reg-4-1-ubv.c: New test.
>         * gcc.target/i386/mpx/hard-reg-4-2-lbv.c: New test.
>         * gcc.target/i386/mpx/hard-reg-4-2-nov.c: New test.
>         * gcc.target/i386/mpx/hard-reg-4-2-ubv.c: New test.
>
>
> 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-1-lbv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-1-lbv.c
> new file mode 100644
> index 0000000..201b62d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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-4-1-nov.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-1-nov.c
> new file mode 100644
> index 0000000..f94a879
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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-4-1-ubv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-1-ubv.c
> new file mode 100644
> index 0000000..6ab981d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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-4-2-lbv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-2-lbv.c
> new file mode 100644
> index 0000000..cc58e8a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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-4-2-nov.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-2-nov.c
> new file mode 100644
> index 0000000..5898c3b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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-4-2-ubv.c
> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-2-ubv.c
> new file mode 100644
> index 0000000..2910795
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-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 23f5af9..852ca7b 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 (VAR_P (var) && DECL_HARD_REGISTER (var))
> + *bounds = chkp_make_addressed_object_bounds (var, iter);
>      }
>
>    /* In this loop we are trying to find a field access
> @@ -3646,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
>    || TREE_CODE (addr) == TARGET_MEM_REF)
> @@ -3989,6 +4048,7 @@ chkp_process_stmt (gimple_stmt_iterator *iter, tree node,
>    tree addr_last = NULL_TREE; /* address of the last accessed byte */
>    tree ptr = NULL_TREE; /* a pointer used for dereference */
>    tree bounds = NULL_TREE;
> +  bool reg_store = false;
>
>    /* We do not need instrumentation for clobbers.  */
>    if (dirflag == integer_one_node
> @@ -4103,6 +4163,13 @@ chkp_process_stmt (gimple_stmt_iterator *iter, tree node,
>        addr_last = fold_build_pointer_plus_loc (loc, addr_last, access_offs);
>      }
>
> +  if (dirflag == integer_one_node)
> +    {
> +      tree base = get_base_address (node);
> +      if (VAR_P (base) && DECL_HARD_REGISTER (base))
> + reg_store = true;
> +    }
> +
>    /* Generate bndcl/bndcu checks if memory access is not safe.  */
>    if (!safe)
>      {
> @@ -4117,6 +4184,7 @@ chkp_process_stmt (gimple_stmt_iterator *iter, tree node,
>
>    /* We need to store bounds in case pointer is stored.  */
>    if (dirflag == integer_one_node
> +      && !reg_store
>        && chkp_type_has_pointer (node_type)
>        && flag_chkp_store_bounds)
>      {
>
> Is it OK?

Hi,

The patch is OK.

Ilya

>
> thanks,
> Alexander
>
> 2017-04-21 17:13 GMT+02:00 Alexander Ivchenko <aivchenk@gmail.com>:

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] Fix mpx testcases (Re: [CHKP] Fix for PR79990)
  2017-05-09 13:33                 ` Alexander Ivchenko
  2017-05-10 17:20                   ` Ilya Enkovich
@ 2017-06-08 19:45                   ` Jakub Jelinek
  2017-06-08 20:02                     ` Ilya Enkovich
  1 sibling, 1 reply; 12+ messages in thread
From: Jakub Jelinek @ 2017-06-08 19:45 UTC (permalink / raw)
  To: Uros Bizjak, Kirill Yukhin, Alexander Ivchenko; +Cc: Ilya Enkovich, GCC Patches

On Tue, May 09, 2017 at 03:29:40PM +0200, Alexander Ivchenko wrote:
> 2017-05-09  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.

These tests fail for me on i686, without -msse2 there is no
"xmm0" register one can use.

The following patch fixes it, tested on x86_64-linux and i686-linux,
ok for trunk?

2017-06-08  Jakub Jelinek  <jakub@redhat.com>

	* gcc.target/i386/mpx/hard-reg-1-nov.c (mpx_test): Use "esp"
	instead of "rsp" for -m32.
	* gcc.target/i386/mpx/hard-reg-2-lbv.c: Require sse2_runtime effective
	target, add -msse2 to dg-options.
	* gcc.target/i386/mpx/hard-reg-2-nov.c: Likewise.
	* gcc.target/i386/mpx/hard-reg-2-ubv.c: Likewise.

--- gcc/testsuite/gcc.target/i386/mpx/hard-reg-1-nov.c.jj	2015-03-10 16:56:41.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/mpx/hard-reg-1-nov.c	2017-06-08 21:37:00.357993146 +0200
@@ -13,7 +13,11 @@ int rd (int *p, int i)
 
 int mpx_test (int argc, const char **argv)
 {
+#ifdef __x86_64__
   register int *frame __asm__("rsp");
+#else
+  register int *frame __asm__("esp");
+#endif
   rd (frame, 1);
 
   return 0;
--- gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c.jj	2017-06-08 17:53:25.000000000 +0200
+++ gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c	2017-06-08 21:37:23.772718716 +0200
@@ -1,6 +1,6 @@
-/* { dg-do run } */
+/* { dg-do run { target sse2_runtime } } */
 /* { dg-shouldfail "bounds violation" } */
-/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
+/* { dg-options "-fcheck-pointer-bounds -mmpx -msse2" } */
 
 
 #define SHOULDFAIL
--- gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c.jj	2017-06-08 17:53:25.000000000 +0200
+++ gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c	2017-06-08 21:37:35.517581062 +0200
@@ -1,5 +1,5 @@
-/* { dg-do run } */
-/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-options "-fcheck-pointer-bounds -mmpx -msse2" } */
 
 #include "mpx-check.h"
 
--- gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c.jj	2017-06-08 17:53:25.000000000 +0200
+++ gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c	2017-06-08 21:37:49.910412372 +0200
@@ -1,6 +1,6 @@
-/* { dg-do run } */
+/* { dg-do run { target sse2_runtime } } */
 /* { dg-shouldfail "bounds violation" } */
-/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
+/* { dg-options "-fcheck-pointer-bounds -mmpx -msse2" } */
 
 
 #define SHOULDFAIL


	Jakub

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Fix mpx testcases (Re: [CHKP] Fix for PR79990)
  2017-06-08 19:45                   ` [PATCH] Fix mpx testcases (Re: [CHKP] Fix for PR79990) Jakub Jelinek
@ 2017-06-08 20:02                     ` Ilya Enkovich
  0 siblings, 0 replies; 12+ messages in thread
From: Ilya Enkovich @ 2017-06-08 20:02 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Uros Bizjak, Kirill Yukhin, Alexander Ivchenko, GCC Patches

2017-06-08 22:45 GMT+03:00 Jakub Jelinek <jakub@redhat.com>:
> On Tue, May 09, 2017 at 03:29:40PM +0200, Alexander Ivchenko wrote:
>> 2017-05-09  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.
>
> These tests fail for me on i686, without -msse2 there is no
> "xmm0" register one can use.
>
> The following patch fixes it, tested on x86_64-linux and i686-linux,
> ok for trunk?

OK. Thanks for the fix.

Ilya

>
> 2017-06-08  Jakub Jelinek  <jakub@redhat.com>
>
>         * gcc.target/i386/mpx/hard-reg-1-nov.c (mpx_test): Use "esp"
>         instead of "rsp" for -m32.
>         * gcc.target/i386/mpx/hard-reg-2-lbv.c: Require sse2_runtime effective
>         target, add -msse2 to dg-options.
>         * gcc.target/i386/mpx/hard-reg-2-nov.c: Likewise.
>         * gcc.target/i386/mpx/hard-reg-2-ubv.c: Likewise.
>
> --- gcc/testsuite/gcc.target/i386/mpx/hard-reg-1-nov.c.jj       2015-03-10 16:56:41.000000000 +0100
> +++ gcc/testsuite/gcc.target/i386/mpx/hard-reg-1-nov.c  2017-06-08 21:37:00.357993146 +0200
> @@ -13,7 +13,11 @@ int rd (int *p, int i)
>
>  int mpx_test (int argc, const char **argv)
>  {
> +#ifdef __x86_64__
>    register int *frame __asm__("rsp");
> +#else
> +  register int *frame __asm__("esp");
> +#endif
>    rd (frame, 1);
>
>    return 0;
> --- gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c.jj       2017-06-08 17:53:25.000000000 +0200
> +++ gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c  2017-06-08 21:37:23.772718716 +0200
> @@ -1,6 +1,6 @@
> -/* { dg-do run } */
> +/* { dg-do run { target sse2_runtime } } */
>  /* { dg-shouldfail "bounds violation" } */
> -/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx -msse2" } */
>
>
>  #define SHOULDFAIL
> --- gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c.jj       2017-06-08 17:53:25.000000000 +0200
> +++ gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c  2017-06-08 21:37:35.517581062 +0200
> @@ -1,5 +1,5 @@
> -/* { dg-do run } */
> -/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +/* { dg-do run { target sse2_runtime } } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx -msse2" } */
>
>  #include "mpx-check.h"
>
> --- gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c.jj       2017-06-08 17:53:25.000000000 +0200
> +++ gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c  2017-06-08 21:37:49.910412372 +0200
> @@ -1,6 +1,6 @@
> -/* { dg-do run } */
> +/* { dg-do run { target sse2_runtime } } */
>  /* { dg-shouldfail "bounds violation" } */
> -/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
> +/* { dg-options "-fcheck-pointer-bounds -mmpx -msse2" } */
>
>
>  #define SHOULDFAIL
>
>
>         Jakub

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-06-08 20:02 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-23 14:19 [CHKP] Fix for PR79990 Alexander Ivchenko
2017-03-23 20:34 ` Ilya Enkovich
2017-04-02 20:53   ` Alexander Ivchenko
2017-04-10 21:22     ` Ilya Enkovich
2017-04-19 16:56       ` Alexander Ivchenko
     [not found]         ` <CAMbmDYZ+DDk-=hHzg-Qogawdee2R7XzGhEokbcXA5NhgiYs4ww@mail.gmail.com>
2017-04-20  9:54           ` Alexander Ivchenko
2017-04-20 17:46             ` Ilya Enkovich
2017-04-21 18:31               ` Alexander Ivchenko
2017-05-09 13:33                 ` Alexander Ivchenko
2017-05-10 17:20                   ` Ilya Enkovich
2017-06-08 19:45                   ` [PATCH] Fix mpx testcases (Re: [CHKP] Fix for PR79990) Jakub Jelinek
2017-06-08 20:02                     ` Ilya Enkovich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).