From 491527afb8bcf02fc91fbddc66b27a0dc25c2bd1 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 24 Feb 2017 10:48:38 +0000 Subject: utils.c (fold_bit_position): New function. * gcc-interface/utils.c (fold_bit_position): New function. (rest_of_record_type_compilation): Call it instead of bit_position to compute the field position and remove the call to remove_conversions. (compute_related_constant): Factor out the multiplication in both operands, if any, and streamline the final test. From-SVN: r245704 --- gcc/ada/ChangeLog | 8 +++++++ gcc/ada/gcc-interface/utils.c | 55 +++++++++++++++++++++++++++++++------------ 2 files changed, 48 insertions(+), 15 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 44e525a..ffa4666 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,13 @@ 2017-02-24 Eric Botcazou + * gcc-interface/utils.c (fold_bit_position): New function. + (rest_of_record_type_compilation): Call it instead of bit_position to + compute the field position and remove the call to remove_conversions. + (compute_related_constant): Factor out the multiplication in both + operands, if any, and streamline the final test. + +2017-02-24 Eric Botcazou + * gcc-interface/trans.c (return_value_ok_for_nrv_p): Add sanity check. 2017-02-24 Eric Botcazou diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 0f4d8a4..0a6d6af 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -238,6 +238,7 @@ static GTY ((cache)) hash_table *pad_type_hash_table; static tree merge_sizes (tree, tree, tree, bool, bool); +static tree fold_bit_position (const_tree); static tree compute_related_constant (tree, tree); static tree split_plus (tree, tree *); static tree float_type_for_precision (int, machine_mode); @@ -2041,15 +2042,11 @@ rest_of_record_type_compilation (tree record_type) { tree field_type = TREE_TYPE (old_field); tree field_name = DECL_NAME (old_field); - tree curpos = bit_position (old_field); + tree curpos = fold_bit_position (old_field); tree pos, new_field; bool var = false; unsigned int align = 0; - /* We're going to do some pattern matching below so remove as many - conversions as possible. */ - curpos = remove_conversions (curpos, true); - /* See how the position was modified from the last position. There are two basic cases we support: a value was added @@ -2146,7 +2143,7 @@ rest_of_record_type_compilation (tree record_type) is when there are other components at fixed positions after it (meaning there was a rep clause for every field) and we want to be able to encode them. */ - last_pos = size_binop (PLUS_EXPR, bit_position (old_field), + last_pos = size_binop (PLUS_EXPR, curpos, (TREE_CODE (TREE_TYPE (old_field)) == QUAL_UNION_TYPE) ? bitsize_zero_node @@ -2201,23 +2198,51 @@ merge_sizes (tree last_size, tree first_bit, tree size, bool special, return new_size; } +/* Return the bit position of FIELD, in bits from the start of the record, + and fold it as much as possible. This is a tree of type bitsizetype. */ + +static tree +fold_bit_position (const_tree field) +{ + tree offset = DECL_FIELD_OFFSET (field); + if (TREE_CODE (offset) == MULT_EXPR || TREE_CODE (offset) == PLUS_EXPR) + offset = size_binop (TREE_CODE (offset), + fold_convert (bitsizetype, TREE_OPERAND (offset, 0)), + fold_convert (bitsizetype, TREE_OPERAND (offset, 1))); + else + offset = fold_convert (bitsizetype, offset); + return size_binop (PLUS_EXPR, DECL_FIELD_BIT_OFFSET (field), + size_binop (MULT_EXPR, offset, bitsize_unit_node)); +} + /* Utility function of above to see if OP0 and OP1, both of SIZETYPE, are related by the addition of a constant. Return that constant if so. */ static tree compute_related_constant (tree op0, tree op1) { - tree op0_var, op1_var; - tree op0_con = split_plus (op0, &op0_var); - tree op1_con = split_plus (op1, &op1_var); - tree result = size_binop (MINUS_EXPR, op0_con, op1_con); + tree factor, op0_var, op1_var, op0_cst, op1_cst, result; - if (operand_equal_p (op0_var, op1_var, 0)) - return result; - else if (operand_equal_p (op0, size_binop (PLUS_EXPR, op1_var, result), 0)) - return result; + if (TREE_CODE (op0) == MULT_EXPR + && TREE_CODE (op1) == MULT_EXPR + && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST + && TREE_OPERAND (op1, 1) == TREE_OPERAND (op0, 1)) + { + factor = TREE_OPERAND (op0, 1); + op0 = TREE_OPERAND (op0, 0); + op1 = TREE_OPERAND (op1, 0); + } else - return 0; + factor = NULL_TREE; + + op0_cst = split_plus (op0, &op0_var); + op1_cst = split_plus (op1, &op1_var); + result = size_binop (MINUS_EXPR, op0_cst, op1_cst); + + if (operand_equal_p (op0_var, op1_var, 0)) + return factor ? size_binop (MULT_EXPR, factor, result) : result; + + return NULL_TREE; } /* Utility function of above to split a tree OP which may be a sum, into a -- cgit v1.1