diff options
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/gcc/tree.c b/gcc/tree.c index d68f08e9b6f..f48512fceeb 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -9460,5 +9460,78 @@ list_equal_p (const_tree t1, const_tree t2) return !t1 && !t2; } +/* Return true iff conversion in EXP generates no instruction. Mark + it inline so that we fully inline into the stripping functions even + though we have two uses of this function. */ + +static inline bool +tree_nop_conversion (const_tree exp) +{ + tree outer_type, inner_type; + + if (!CONVERT_EXPR_P (exp) + && TREE_CODE (exp) != NON_LVALUE_EXPR) + return false; + if (TREE_OPERAND (exp, 0) == error_mark_node) + return false; + + outer_type = TREE_TYPE (exp); + inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); + + /* Use precision rather then machine mode when we can, which gives + the correct answer even for submode (bit-field) types. */ + if ((INTEGRAL_TYPE_P (outer_type) + || POINTER_TYPE_P (outer_type) + || TREE_CODE (outer_type) == OFFSET_TYPE) + && (INTEGRAL_TYPE_P (inner_type) + || POINTER_TYPE_P (inner_type) + || TREE_CODE (inner_type) == OFFSET_TYPE)) + return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type); + + /* Otherwise fall back on comparing machine modes (e.g. for + aggregate types, floats). */ + return TYPE_MODE (outer_type) == TYPE_MODE (inner_type); +} + +/* Return true iff conversion in EXP generates no instruction. Don't + consider conversions changing the signedness. */ + +static bool +tree_sign_nop_conversion (const_tree exp) +{ + tree outer_type, inner_type; + + if (!tree_nop_conversion (exp)) + return false; + + outer_type = TREE_TYPE (exp); + inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); + + return (TYPE_UNSIGNED (outer_type) == TYPE_UNSIGNED (inner_type) + && POINTER_TYPE_P (outer_type) == POINTER_TYPE_P (inner_type)); +} + +/* Strip conversions from EXP according to tree_nop_conversion and + return the resulting expression. */ + +tree +tree_strip_nop_conversions (tree exp) +{ + while (tree_nop_conversion (exp)) + exp = TREE_OPERAND (exp, 0); + return exp; +} + +/* Strip conversions from EXP according to tree_sign_nop_conversion + and return the resulting expression. */ + +tree +tree_strip_sign_nop_conversions (tree exp) +{ + while (tree_sign_nop_conversion (exp)) + exp = TREE_OPERAND (exp, 0); + return exp; +} + #include "gt-tree.h" |