]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree.h (STRIP_NOPS, [...]): Use tree_strip_nop_conversions...
authorAdam Nemet <anemet@caviumnetworks.com>
Wed, 17 Jun 2009 22:11:47 +0000 (22:11 +0000)
committerAdam Nemet <nemet@gcc.gnu.org>
Wed, 17 Jun 2009 22:11:47 +0000 (22:11 +0000)
* 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.

From-SVN: r148631

gcc/ChangeLog
gcc/gimple.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/bitfld-5.c [new file with mode: 0644]
gcc/tree-ssa.c
gcc/tree.c
gcc/tree.h

index 21a7483e7610c87fcca2981bac5cc30fb9ed77fe..bd861b0cf962cf76c77c11768edd9969c0ff51cf 100644 (file)
@@ -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.
index b16fb545028816e2ee5989293321263021ba99d1..2010109bc4ebaea5337a6139015f066bcf1836d9 100644 (file)
@@ -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);
 
index 5b7b369c907563cfb5f8a154320276f41f4f09dc..68ae876cab5753a61cc4ad33e97d6508619f6fa4 100644 (file)
@@ -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 (file)
index 0000000..ca88d92
--- /dev/null
@@ -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;
+}
index ada47e16c08195ff8b1b3ef1f9b33b5c0a54c4d4..d63e974cf91fe0cd151533bd432a5b6430b062f9 100644 (file)
@@ -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.
index d68f08e9b6ff232d1354058a8f0e69e5d1c8ab7a..f48512fceeb8c3d60e8fc90be8ce1e0b3d187696 100644 (file)
@@ -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"
index 41b5001834d34ae43189203bdb2cf8be230c1aa6..8aabf79cebe0afd948c99adf6dc938e44fe83706 100644 (file)
@@ -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);
 \f
 /* In cgraph.c */
 extern void change_decl_assembler_name (tree, tree);