From e7301f5fcbfa649beb05da1e3508db7fc7c4d26b Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 21 Dec 2017 07:01:38 +0000 Subject: [PATCH] poly_int: bit_field_size/offset 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 Alan Hayward David Sherwood 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 Co-Authored-By: David Sherwood From-SVN: r255926 --- gcc/ChangeLog | 14 ++++++++++++++ gcc/fold-const.c | 4 +++- gcc/hsa-gen.c | 4 ++-- gcc/tree-cfg.c | 16 ++++++++-------- gcc/tree-ssa-forwprop.c | 14 +++++++------- gcc/tree-ssa-sccvn.c | 8 ++------ gcc/tree.h | 18 ++++++++++++++++++ 7 files changed, 54 insertions(+), 24 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9c985b24797..a3ed3cec0b9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2017-12-21 Richard Sandiford + Alan Hayward + David Sherwood + + * 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 Alan Hayward David Sherwood diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 2039d4dd2f9..b21f35a3736 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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); diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index 9284a3cceba..155bcdf1df4 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -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 " diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index ae5335bc336..bed49473d53 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -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"); diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 74a54c3fcb0..41ee4098950 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -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); diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index b59d8eb3514..89ef26c7a3f 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -779,12 +779,8 @@ copy_reference_ops_from_ref (tree ref, vec *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: diff --git a/gcc/tree.h b/gcc/tree.h index 5ac1f2594f0..e8a2470106e 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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 *); -- 2.30.2