From: Adam Nemet Date: Wed, 17 Jun 2009 22:11:47 +0000 (+0000) Subject: tree.h (STRIP_NOPS, [...]): Use tree_strip_nop_conversions... X-Git-Tag: releases/gcc-4.5.0~5147 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=23314e77ec9e3dfea806f31b6dd65920f628f207;p=thirdparty%2Fgcc.git tree.h (STRIP_NOPS, [...]): Use tree_strip_nop_conversions... * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 21a7483e7610..bd861b0cf962 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2009-06-17 Adam Nemet + + * 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 * config/rs6000/constraints.md: register_constraint "d": New. diff --git a/gcc/gimple.h b/gcc/gimple.h index b16fb5450288..2010109bc4eb 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 5b7b369c9075..68ae876cab57 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2009-06-17 Adam Nemet + + * gcc.c-torture/execute/bitfld-5.c: New test. + 2009-06-17 David Daney * 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 000000000000..ca88d92214ed --- /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 ada47e16c081..d63e974cf91f 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 d68f08e9b6ff..f48512fceeb8 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 41b5001834d3..8aabf79cebe0 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);