re PR middle-end/81502 (In some cases the data is moved to memory unnecessarily ...
authorRichard Biener <rguenther@suse.de>
Fri, 28 Jul 2017 11:27:45 +0000 (11:27 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 28 Jul 2017 11:27:45 +0000 (11:27 +0000)
2017-07-28  Richard Biener  <rguenther@suse.de>

PR tree-optimization/81502
* match.pd: Add pattern combining BIT_INSERT_EXPR with
BIT_FIELD_REF.
* tree-cfg.c (verify_expr): Verify types of BIT_FIELD_REF
size/pos operands.
(verify_gimple_assign_ternary): Likewise for BIT_INSERT_EXPR pos.
* gimple-fold.c (maybe_canonicalize_mem_ref_addr): Use bitsizetype
for BIT_FIELD_REF args.
* fold-const.c (make_bit_field_ref): Likewise.
* tree-vect-stmts.c (vectorizable_simd_clone_call): Likewise.

* gcc.target/i386/pr81502.c: New testcase.

From-SVN: r250659

gcc/ChangeLog
gcc/fold-const.c
gcc/gimple-fold.c
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr81502.c [new file with mode: 0644]
gcc/tree-cfg.c
gcc/tree-vect-stmts.c

index 61d389e541db9d7c76385866094072fdab7931e0..964fa1cdc9cf6b9b75a6459aebb60d03f26a7035 100644 (file)
@@ -1,3 +1,16 @@
+2017-07-28  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/81502
+       * match.pd: Add pattern combining BIT_INSERT_EXPR with
+       BIT_FIELD_REF.
+       * tree-cfg.c (verify_expr): Verify types of BIT_FIELD_REF
+       size/pos operands.
+       (verify_gimple_assign_ternary): Likewise for BIT_INSERT_EXPR pos.
+       * gimple-fold.c (maybe_canonicalize_mem_ref_addr): Use bitsizetype
+       for BIT_FIELD_REF args.
+       * fold-const.c (make_bit_field_ref): Likewise.
+       * tree-vect-stmts.c (vectorizable_simd_clone_call): Likewise.
+
 2017-07-28  Jakub Jelinek  <jakub@redhat.com>
 
        PR sanitizer/80998
index d40b9aaaeb415e805050e039fdd2f24dd9cd5877..ae94659652819b5fde990832d7933a65ec740691 100644 (file)
@@ -3936,7 +3936,7 @@ make_bit_field_ref (location_t loc, tree inner, tree orig_inner, tree type,
     bftype = build_nonstandard_integer_type (bitsize, 0);
 
   result = build3_loc (loc, BIT_FIELD_REF, bftype, inner,
-                      size_int (bitsize), bitsize_int (bitpos));
+                      bitsize_int (bitsize), bitsize_int (bitpos));
   REF_REVERSE_STORAGE_ORDER (result) = reversep;
 
   if (bftype != type)
index d94dc9cd563ca1d4b7d56dd443ef04ba7fd367de..d82d0606cbeff6c20fc500007e3397e4f8b8ccfc 100644 (file)
@@ -4245,7 +4245,7 @@ maybe_canonicalize_mem_ref_addr (tree *t)
                                       TREE_TYPE (*t),
                                       TREE_OPERAND (TREE_OPERAND (*t, 0), 0),
                                       TYPE_SIZE (TREE_TYPE (*t)),
-                                      wide_int_to_tree (sizetype, idx));
+                                      wide_int_to_tree (bitsizetype, idx));
                      res = true;
                    }
                }
index 732b80c04bf732a1418beef1dc55f19c9208f7ad..60f262d59267d24dcbc05023d6e91909a15589a8 100644 (file)
@@ -4178,3 +4178,25 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
         { CONSTRUCTOR_ELT (ctor, idx / k)->value; })
        (BIT_FIELD_REF { CONSTRUCTOR_ELT (ctor, idx / k)->value; }
                       @1 { bitsize_int ((idx % k) * width); })))))))))
+
+/* Simplify a bit extraction from a bit insertion for the cases with
+   the inserted element fully covering the extraction or the insertion
+   not touching the extraction.  */
+(simplify
+ (BIT_FIELD_REF (bit_insert @0 @1 @ipos) @rsize @rpos)
+ (with
+  {
+    unsigned HOST_WIDE_INT isize;
+    if (INTEGRAL_TYPE_P (TREE_TYPE (@1)))
+      isize = TYPE_PRECISION (TREE_TYPE (@1));
+    else
+      isize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (@1)));
+  }
+  (switch
+   (if (wi::leu_p (@ipos, @rpos)
+        && wi::leu_p (wi::add (@rpos, @rsize), wi::add (@ipos, isize)))
+    (BIT_FIELD_REF @1 @rsize { wide_int_to_tree (bitsizetype,
+                                                 wi::sub (@rpos, @ipos)); }))
+   (if (wi::geu_p (@ipos, wi::add (@rpos, @rsize))
+        || wi::geu_p (@rpos, wi::add (@ipos, isize)))
+    (BIT_FIELD_REF @0 @rsize @rpos)))))
index 5c41f4385371e11a78a460c449819f6d1083c233..396f0b1fa982be98166b7833a9b98cdcae3ab3b3 100644 (file)
@@ -1,3 +1,8 @@
+2017-07-28  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/81502
+       * gcc.target/i386/pr81502.c: New testcase.
+
 2017-07-28  Martin Liska  <mliska@suse.cz>
 
        PR sanitizer/81460
diff --git a/gcc/testsuite/gcc.target/i386/pr81502.c b/gcc/testsuite/gcc.target/i386/pr81502.c
new file mode 100644 (file)
index 0000000..d28791a
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-O2 -msse2" } */
+
+#include <emmintrin.h>
+
+#define SIZE (sizeof (void *))
+
+static int foo(unsigned char (*foo)[SIZE])
+{
+  __m128i acc = _mm_set_epi32(0, 0, 0, 0);
+  size_t i = 0;
+  for(; i + sizeof(__m128i) <= SIZE; i += sizeof(__m128i)) {
+      __m128i word;
+      __builtin_memcpy(&word, foo + i, sizeof(__m128i));
+      acc = _mm_add_epi32(word, acc);
+  }
+  if (i != SIZE) {
+      __m128i word = _mm_set_epi32(0, 0, 0, 0);
+      __builtin_memcpy(&word, foo + i, SIZE - i); // (1)
+      acc = _mm_add_epi32(word, acc);
+  }
+  int res;
+  __builtin_memcpy(&res, &acc, sizeof(res));
+  return res;
+}
+
+int bar(void *ptr)
+{
+  unsigned char buf[SIZE];
+  __builtin_memcpy(buf, &ptr, SIZE);
+  return foo((unsigned char(*)[SIZE])buf);
+}
+
+/* { dg-final { scan-assembler-times "mov" 1 } } */
index f664ffe119a222a988a55b592639629bfe4dd2ba..733c92fcdd0914bf3957bcc6ca69704927661c61 100644 (file)
@@ -3054,7 +3054,9 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
          tree t1 = TREE_OPERAND (t, 1);
          tree t2 = TREE_OPERAND (t, 2);
          if (!tree_fits_uhwi_p (t1)
-             || !tree_fits_uhwi_p (t2))
+             || !tree_fits_uhwi_p (t2)
+             || !types_compatible_p (bitsizetype, TREE_TYPE (t1))
+             || !types_compatible_p (bitsizetype, TREE_TYPE (t2)))
            {
              error ("invalid position or size operand to BIT_FIELD_REF");
              return t;
@@ -4248,6 +4250,7 @@ verify_gimple_assign_ternary (gassign *stmt)
          return true;
        }
       if (! tree_fits_uhwi_p (rhs3)
+         || ! types_compatible_p (bitsizetype, TREE_TYPE (rhs3))
          || ! tree_fits_uhwi_p (TYPE_SIZE (rhs2_type)))
        {
          error ("invalid position or size in BIT_INSERT_EXPR");
index 8a631046cc8e82797fd7e052216e9fcd028088e6..18dd1a4df32bfe64f24241f5a18e9d37863c6397 100644 (file)
@@ -3531,7 +3531,7 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
                      arginfo[i].op = vec_oprnd0;
                      vec_oprnd0
                        = build3 (BIT_FIELD_REF, atype, vec_oprnd0,
-                                 size_int (prec),
+                                 bitsize_int (prec),
                                  bitsize_int ((m & (k - 1)) * prec));
                      new_stmt
                        = gimple_build_assign (make_ssa_name (atype),
@@ -3692,7 +3692,7 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
                    }
                  else
                    t = build3 (BIT_FIELD_REF, vectype, new_temp,
-                               size_int (prec), bitsize_int (l * prec));
+                               bitsize_int (prec), bitsize_int (l * prec));
                  new_stmt
                    = gimple_build_assign (make_ssa_name (vectype), t);
                  vect_finish_stmt_generation (stmt, new_stmt, gsi);