summaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c73
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"