summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornemet <nemet@138bc75d-0d04-0410-961f-82ee72b054a4>2009-06-17 22:11:47 +0000
committernemet <nemet@138bc75d-0d04-0410-961f-82ee72b054a4>2009-06-17 22:11:47 +0000
commit981128818185336c368753f779a1bc29d26c1c89 (patch)
tree891864d93af2879f6eb0fac88b1eb64c1454dc24
parent40cbc4331f565ae3a02b927dfdfa5d28db916a1f (diff)
downloadgcc-981128818185336c368753f779a1bc29d26c1c89.tar.gz
* tree.h (STRIP_NOPS, STRIP_SIGN_NOPS,
STRIP_USELESS_TYPE_CONVERSION): Use tree_strip_nop_conversions, tree_strip_sign_nop_conversions and tree_ssa_strip_useless_type_conversions rather than stripping the operations here. (tree_strip_nop_conversions, tree_strip_sign_nop_conversions): Declare them. * gimple.h (tree_ssa_strip_useless_type_conversions): Declare it. * tree-ssa.c (tree_ssa_strip_useless_type_conversions): New function. * tree.c (tree_nop_conversion, tree_sign_nop_conversion, tree_strip_nop_conversions, tree_strip_sign_nop_conversions): New functions. testsuite/ * gcc.c-torture/execute/bitfld-5.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@148631 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/gimple.h1
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/bitfld-5.c35
-rw-r--r--gcc/tree-ssa.c12
-rw-r--r--gcc/tree.c73
-rw-r--r--gcc/tree.h32
7 files changed, 150 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 21a7483e761..bd861b0cf96 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2009-06-17 Adam Nemet <anemet@caviumnetworks.com>
+
+ * tree.h (STRIP_NOPS, STRIP_SIGN_NOPS,
+ STRIP_USELESS_TYPE_CONVERSION): Use tree_strip_nop_conversions,
+ tree_strip_sign_nop_conversions and
+ tree_ssa_strip_useless_type_conversions rather than stripping
+ the operations here.
+ (tree_strip_nop_conversions, tree_strip_sign_nop_conversions):
+ Declare them.
+ * gimple.h (tree_ssa_strip_useless_type_conversions): Declare it.
+ * tree-ssa.c (tree_ssa_strip_useless_type_conversions): New function.
+ * tree.c (tree_nop_conversion, tree_sign_nop_conversion,
+ tree_strip_nop_conversions, tree_strip_sign_nop_conversions): New
+ functions.
+
2009-06-17 Michael Eager <eager@eagercon.com>
* config/rs6000/constraints.md: register_constraint "d": New.
diff --git a/gcc/gimple.h b/gcc/gimple.h
index b16fb545028..2010109bc4e 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -997,6 +997,7 @@ extern bool validate_gimple_arglist (const_gimple, ...);
/* In tree-ssa.c */
extern bool tree_ssa_useless_type_conversion (tree);
+extern tree tree_ssa_strip_useless_type_conversions (tree);
extern bool useless_type_conversion_p (tree, tree);
extern bool types_compatible_p (tree, tree);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5b7b369c907..68ae876cab5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2009-06-17 Adam Nemet <anemet@caviumnetworks.com>
+
+ * gcc.c-torture/execute/bitfld-5.c: New test.
+
2009-06-17 David Daney <ddaney@caviumnetworks.com>
* gcc.dg/builtin-unreachable-3.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/bitfld-5.c b/gcc/testsuite/gcc.c-torture/execute/bitfld-5.c
new file mode 100644
index 00000000000..ca88d92214e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/bitfld-5.c
@@ -0,0 +1,35 @@
+/* See http://gcc.gnu.org/ml/gcc/2009-06/msg00072.html. */
+
+extern void abort (void);
+
+struct s
+{
+ unsigned long long a:2;
+ unsigned long long b:40;
+ unsigned long long c:22;
+};
+
+__attribute__ ((noinline)) void
+g (unsigned long long a, unsigned long long b)
+{
+ asm ("");
+ if (a != b)
+ abort ();
+}
+
+__attribute__ ((noinline)) void
+f (struct s s, unsigned long long b)
+{
+ asm ("");
+ g (((unsigned long long) (s.b-8)) + 8, b);
+}
+
+int
+main ()
+{
+ struct s s = {1, 10, 3};
+ struct s t = {1, 2, 3};
+ f (s, 10);
+ f (t, 0x10000000002);
+ return 0;
+}
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index ada47e16c08..d63e974cf91 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1079,6 +1079,18 @@ tree_ssa_useless_type_conversion (tree expr)
return false;
}
+/* Strip conversions from EXP according to
+ tree_ssa_useless_type_conversion and return the resulting
+ expression. */
+
+tree
+tree_ssa_strip_useless_type_conversions (tree exp)
+{
+ while (tree_ssa_useless_type_conversion (exp))
+ exp = TREE_OPERAND (exp, 0);
+ return exp;
+}
+
/* Internal helper for walk_use_def_chains. VAR, FN and DATA are as
described in walk_use_def_chains.
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"
diff --git a/gcc/tree.h b/gcc/tree.h
index 41b5001834d..8aabf79cebe 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -966,30 +966,17 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
case NOP_EXPR: \
case CONVERT_EXPR
-/* Given an expression as a tree, strip any NON_LVALUE_EXPRs and NOP_EXPRs
- that don't change the machine mode. */
+/* Given an expression as a tree, strip any conversion that generates
+ no instruction. Accepts both tree and const_tree arguments since
+ we are not modifying the tree itself. */
-#define STRIP_NOPS(EXP) \
- while ((CONVERT_EXPR_P (EXP) \
- || TREE_CODE (EXP) == NON_LVALUE_EXPR) \
- && TREE_OPERAND (EXP, 0) != error_mark_node \
- && (TYPE_MODE (TREE_TYPE (EXP)) \
- == TYPE_MODE (TREE_TYPE (TREE_OPERAND (EXP, 0))))) \
- (EXP) = TREE_OPERAND (EXP, 0)
+#define STRIP_NOPS(EXP) \
+ (EXP) = tree_strip_nop_conversions (CONST_CAST_TREE (EXP))
/* Like STRIP_NOPS, but don't let the signedness change either. */
#define STRIP_SIGN_NOPS(EXP) \
- while ((CONVERT_EXPR_P (EXP) \
- || TREE_CODE (EXP) == NON_LVALUE_EXPR) \
- && TREE_OPERAND (EXP, 0) != error_mark_node \
- && (TYPE_MODE (TREE_TYPE (EXP)) \
- == TYPE_MODE (TREE_TYPE (TREE_OPERAND (EXP, 0)))) \
- && (TYPE_UNSIGNED (TREE_TYPE (EXP)) \
- == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (EXP, 0)))) \
- && (POINTER_TYPE_P (TREE_TYPE (EXP)) \
- == POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (EXP, 0))))) \
- (EXP) = TREE_OPERAND (EXP, 0)
+ (EXP) = tree_strip_sign_nop_conversions (CONST_CAST_TREE (EXP))
/* Like STRIP_NOPS, but don't alter the TREE_TYPE either. */
@@ -1004,9 +991,8 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
/* Remove unnecessary type conversions according to
tree_ssa_useless_type_conversion. */
-#define STRIP_USELESS_TYPE_CONVERSION(EXP) \
- while (tree_ssa_useless_type_conversion (EXP)) \
- EXP = TREE_OPERAND (EXP, 0)
+#define STRIP_USELESS_TYPE_CONVERSION(EXP) \
+ (EXP) = tree_ssa_strip_useless_type_conversions (EXP)
/* Nonzero if TYPE represents an integral type. Note that we do not
include COMPLEX types here. Keep these checks in ascending code
@@ -4632,6 +4618,8 @@ extern bool stdarg_p (tree);
extern bool prototype_p (tree);
extern bool auto_var_in_fn_p (const_tree, const_tree);
extern tree build_low_bits_mask (tree, unsigned);
+extern tree tree_strip_nop_conversions (tree);
+extern tree tree_strip_sign_nop_conversions (tree);
/* In cgraph.c */
extern void change_decl_assembler_name (tree, tree);