This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [CHKP] Fix for PR79990


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]