poly_int: bit_field_size/offset
authorRichard Sandiford <richard.sandiford@linaro.org>
Thu, 21 Dec 2017 07:01:38 +0000 (07:01 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 21 Dec 2017 07:01:38 +0000 (07:01 +0000)
verify_expr ensured that the size and offset in gimple BIT_FIELD_REFs
satisfied tree_fits_uhwi_p.  This patch extends that so that they can
be poly_uint64s, and adds helper routines for accessing them when the
verify_expr requirements apply.

2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
    Alan Hayward  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* tree.h (bit_field_size, bit_field_offset): New functions.
* hsa-gen.c (gen_hsa_addr): Use them.
* tree-ssa-forwprop.c (simplify_bitfield_ref): Likewise.
(simplify_vector_constructor): Likewise.
* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Likewise.
* tree-cfg.c (verify_expr): Require the sizes and offsets of a
BIT_FIELD_REF to be poly_uint64s rather than uhwis.
* fold-const.c (fold_ternary_loc): Protect tree_to_uhwi with
tree_fits_uhwi_p.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r255926

gcc/ChangeLog
gcc/fold-const.c
gcc/hsa-gen.c
gcc/tree-cfg.c
gcc/tree-ssa-forwprop.c
gcc/tree-ssa-sccvn.c
gcc/tree.h

index 9c985b247975c39787e7dea423bed7429c8312bd..a3ed3cec0b9ef43b7b990e55c0e069377b44ad05 100644 (file)
@@ -1,3 +1,17 @@
+2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * tree.h (bit_field_size, bit_field_offset): New functions.
+       * hsa-gen.c (gen_hsa_addr): Use them.
+       * tree-ssa-forwprop.c (simplify_bitfield_ref): Likewise.
+       (simplify_vector_constructor): Likewise.
+       * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Likewise.
+       * tree-cfg.c (verify_expr): Require the sizes and offsets of a
+       BIT_FIELD_REF to be poly_uint64s rather than uhwis.
+       * fold-const.c (fold_ternary_loc): Protect tree_to_uhwi with
+       tree_fits_uhwi_p.
+
 2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index 2039d4dd2f9e3deab1a8cad4d6639cf36347d541..b21f35a37360f9df33371dcc232eee0963aaf1a7 100644 (file)
@@ -11632,7 +11632,9 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          fold (nearly) all BIT_FIELD_REFs.  */
       if (CONSTANT_CLASS_P (arg0)
          && can_native_interpret_type_p (type)
-         && BITS_PER_UNIT == 8)
+         && BITS_PER_UNIT == 8
+         && tree_fits_uhwi_p (op1)
+         && tree_fits_uhwi_p (op2))
        {
          unsigned HOST_WIDE_INT bitpos = tree_to_uhwi (op2);
          unsigned HOST_WIDE_INT bitsize = tree_to_uhwi (op1);
index 9284a3cceba2c91cae8e831d346b305763948234..155bcdf1df4af35d9337d7ab300846644d2044c2 100644 (file)
@@ -1959,8 +1959,8 @@ gen_hsa_addr (tree ref, hsa_bb *hbb, HOST_WIDE_INT *output_bitsize = NULL,
       goto out;
     }
   else if (TREE_CODE (ref) == BIT_FIELD_REF
-          && ((tree_to_uhwi (TREE_OPERAND (ref, 1)) % BITS_PER_UNIT) != 0
-              || (tree_to_uhwi (TREE_OPERAND (ref, 2)) % BITS_PER_UNIT) != 0))
+          && (!multiple_p (bit_field_size (ref), BITS_PER_UNIT)
+              || !multiple_p (bit_field_offset (ref), BITS_PER_UNIT)))
     {
       HSA_SORRY_ATV (EXPR_LOCATION (origref),
                     "support for HSA does not implement "
index ae5335bc33699afde4ea2b69db7554894610ef5c..bed49473d53bd7471058e78b72f03d64922d8e62 100644 (file)
@@ -3170,8 +3170,9 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
          tree t0 = TREE_OPERAND (t, 0);
          tree t1 = TREE_OPERAND (t, 1);
          tree t2 = TREE_OPERAND (t, 2);
-         if (!tree_fits_uhwi_p (t1)
-             || !tree_fits_uhwi_p (t2)
+         poly_uint64 size, bitpos;
+         if (!poly_int_tree_p (t1, &size)
+             || !poly_int_tree_p (t2, &bitpos)
              || !types_compatible_p (bitsizetype, TREE_TYPE (t1))
              || !types_compatible_p (bitsizetype, TREE_TYPE (t2)))
            {
@@ -3179,8 +3180,7 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
              return t;
            }
          if (INTEGRAL_TYPE_P (TREE_TYPE (t))
-             && (TYPE_PRECISION (TREE_TYPE (t))
-                 != tree_to_uhwi (t1)))
+             && maybe_ne (TYPE_PRECISION (TREE_TYPE (t)), size))
            {
              error ("integral result type precision does not match "
                     "field size of BIT_FIELD_REF");
@@ -3188,16 +3188,16 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
            }
          else if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
                   && TYPE_MODE (TREE_TYPE (t)) != BLKmode
-                  && (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (t)))
-                      != tree_to_uhwi (t1)))
+                  && maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (t))),
+                               size))
            {
              error ("mode size of non-integral result does not "
                     "match field size of BIT_FIELD_REF");
              return t;
            }
          if (!AGGREGATE_TYPE_P (TREE_TYPE (t0))
-             && (tree_to_uhwi (t1) + tree_to_uhwi (t2)
-                 > tree_to_uhwi (TYPE_SIZE (TREE_TYPE (t0)))))
+             && maybe_gt (size + bitpos,
+                          tree_to_poly_uint64 (TYPE_SIZE (TREE_TYPE (t0)))))
            {
              error ("position plus size exceeds size of referenced object in "
                     "BIT_FIELD_REF");
index 74a54c3fcb0769f17cd043c7228eb0504a549e1c..41ee4098950f2eb2d5e4f538be948d994aed08d8 100644 (file)
@@ -1781,7 +1781,7 @@ simplify_bitfield_ref (gimple_stmt_iterator *gsi)
   gimple *def_stmt;
   tree op, op0, op1, op2;
   tree elem_type;
-  unsigned idx, n, size;
+  unsigned idx, size;
   enum tree_code code;
 
   op = gimple_assign_rhs1 (stmt);
@@ -1816,12 +1816,11 @@ simplify_bitfield_ref (gimple_stmt_iterator *gsi)
     return false;
 
   size = TREE_INT_CST_LOW (TYPE_SIZE (elem_type));
-  n = TREE_INT_CST_LOW (op1) / size;
-  if (n != 1)
+  if (maybe_ne (bit_field_size (op), size))
     return false;
-  idx = TREE_INT_CST_LOW (op2) / size;
 
-  if (code == VEC_PERM_EXPR)
+  if (code == VEC_PERM_EXPR
+      && constant_multiple_p (bit_field_offset (op), size, &idx))
     {
       tree p, m, tem;
       unsigned nelts;
@@ -2074,9 +2073,10 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
            return false;
          orig = ref;
        }
-      if (TREE_INT_CST_LOW (TREE_OPERAND (op1, 1)) != elem_size)
+      unsigned int elt;
+      if (maybe_ne (bit_field_size (op1), elem_size)
+         || !constant_multiple_p (bit_field_offset (op1), elem_size, &elt))
        return false;
-      unsigned int elt = TREE_INT_CST_LOW (TREE_OPERAND (op1, 2)) / elem_size;
       if (elt != i)
        maybe_ident = false;
       sel.quick_push (elt);
index b59d8eb35149112c01e9e252991ba7b8c7772333..89ef26c7a3f616dc46e72b27a2b585300b9eba50 100644 (file)
@@ -779,12 +779,8 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result)
          /* Record bits, position and storage order.  */
          temp.op0 = TREE_OPERAND (ref, 1);
          temp.op1 = TREE_OPERAND (ref, 2);
-         if (tree_fits_shwi_p (TREE_OPERAND (ref, 2)))
-           {
-             HOST_WIDE_INT off = tree_to_shwi (TREE_OPERAND (ref, 2));
-             if (off % BITS_PER_UNIT == 0)
-               temp.off = off / BITS_PER_UNIT;
-           }
+         if (!multiple_p (bit_field_offset (ref), BITS_PER_UNIT, &temp.off))
+           temp.off = -1;
          temp.reverse = REF_REVERSE_STORAGE_ORDER (ref);
          break;
        case COMPONENT_REF:
index 5ac1f2594f072915942b39f670e96607c1df7a24..e8a2470106e437c147f7ee89cf7e9dc07da7d276 100644 (file)
@@ -4784,6 +4784,24 @@ poly_int_tree_p (const_tree t)
   return (TREE_CODE (t) == INTEGER_CST || POLY_INT_CST_P (t));
 }
 
+/* Return the bit size of BIT_FIELD_REF T, in cases where it is known
+   to be a poly_uint64.  (This is always true at the gimple level.)  */
+
+inline poly_uint64
+bit_field_size (const_tree t)
+{
+  return tree_to_poly_uint64 (TREE_OPERAND (t, 1));
+}
+
+/* Return the starting bit offset of BIT_FIELD_REF T, in cases where it is
+   known to be a poly_uint64.  (This is always true at the gimple level.)  */
+
+inline poly_uint64
+bit_field_offset (const_tree t)
+{
+  return tree_to_poly_uint64 (TREE_OPERAND (t, 2));
+}
+
 extern tree strip_float_extensions (tree);
 extern int really_constant_p (const_tree);
 extern bool ptrdiff_tree_p (const_tree, poly_int64_pod *);