diff options
author | Roger Sayle <roger@eyesopen.com> | 2002-06-15 16:55:24 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2002-06-15 16:55:24 +0000 |
commit | 8dcb27ed86eb249675749e35b1440a8ccfd03881 (patch) | |
tree | c9fc91c5bbced804e712ce47aaa7397c5a3ed98d /gcc/fold-const.c | |
parent | f7d3c5f00586f93c1a5a46ebbffa14dce150aae7 (diff) | |
download | gcc-8dcb27ed86eb249675749e35b1440a8ccfd03881.zip gcc-8dcb27ed86eb249675749e35b1440a8ccfd03881.tar.gz gcc-8dcb27ed86eb249675749e35b1440a8ccfd03881.tar.bz2 |
fold-const.c (comparison_to_compcode): New function to convert an comparison TREE CODE into a bit-based representation.
* fold-const.c (comparison_to_compcode): New function to convert
an comparison TREE CODE into a bit-based representation.
(compcode_to_comparison): New function to convert from this bit
based representation back to a comparison TREE CODE.
(fold_truthop): Simplify (x<y) && (x==y) and related composite
comparisons.
* gcc.c-tortuture/execute/compare-1.c: New test case.
* gcc.c-tortuture/execute/compare-2.c: New test case.
* gcc.c-tortuture/execute/compare-3.c: New test case.
From-SVN: r54647
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 5c04d78..f9f3a64 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -72,6 +72,8 @@ static int size_htab_eq PARAMS ((const void *, const void *)); static tree fold_convert PARAMS ((tree, tree)); static enum tree_code invert_tree_comparison PARAMS ((enum tree_code)); static enum tree_code swap_tree_comparison PARAMS ((enum tree_code)); +static int comparison_to_compcode PARAMS ((enum tree_code)); +static enum tree_code compcode_to_comparison PARAMS ((int)); static int truth_value_p PARAMS ((enum tree_code)); static int operand_equal_for_comparison_p PARAMS ((tree, tree, tree)); static int twoval_comparison_p PARAMS ((tree, tree *, tree *, int *)); @@ -115,6 +117,18 @@ static bool fold_real_zero_addition_p PARAMS ((tree, tree, int)); #define CHARMASK 0x7f #endif +/* The following constants represent a bit based encoding of GCC's + comparison operators. This encoding simplifies transformations + on relational comparison operators, such as AND and OR. */ +#define COMPCODE_FALSE 0 +#define COMPCODE_LT 1 +#define COMPCODE_EQ 2 +#define COMPCODE_LE 3 +#define COMPCODE_GT 4 +#define COMPCODE_NE 5 +#define COMPCODE_GE 6 +#define COMPCODE_TRUE 7 + /* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring overflow. Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1. Then this yields nonzero if overflow occurred during the @@ -1709,6 +1723,61 @@ swap_tree_comparison (code) } } + +/* Convert a comparison tree code from an enum tree_code representation + into a compcode bit-based encoding. This function is the inverse of + compcode_to_comparison. */ + +static int +comparison_to_compcode (code) + enum tree_code code; +{ + switch (code) + { + case LT_EXPR: + return COMPCODE_LT; + case EQ_EXPR: + return COMPCODE_EQ; + case LE_EXPR: + return COMPCODE_LE; + case GT_EXPR: + return COMPCODE_GT; + case NE_EXPR: + return COMPCODE_NE; + case GE_EXPR: + return COMPCODE_GE; + default: + abort (); + } +} + +/* Convert a compcode bit-based encoding of a comparison operator back + to GCC's enum tree_code representation. This function is the + inverse of comparison_to_compcode. */ + +static enum tree_code +compcode_to_comparison (code) + int code; +{ + switch (code) + { + case COMPCODE_LT: + return LT_EXPR; + case COMPCODE_EQ: + return EQ_EXPR; + case COMPCODE_LE: + return LE_EXPR; + case COMPCODE_GT: + return GT_EXPR; + case COMPCODE_NE: + return NE_EXPR; + case COMPCODE_GE: + return GE_EXPR; + default: + abort (); + } +} + /* Return nonzero if CODE is a tree code that represents a truth value. */ static int @@ -3498,6 +3567,48 @@ fold_truthop (code, truth_type, lhs, rhs) rl_arg = TREE_OPERAND (rhs, 0); rr_arg = TREE_OPERAND (rhs, 1); + /* Simplify (x<y) && (x==y) into (x<=y) and related optimizations. */ + if (simple_operand_p (ll_arg) + && simple_operand_p (lr_arg) + && !FLOAT_TYPE_P (TREE_TYPE (ll_arg))) + { + int compcode; + + if (operand_equal_p (ll_arg, rl_arg, 0) + && operand_equal_p (lr_arg, rr_arg, 0)) + { + int lcompcode, rcompcode; + + lcompcode = comparison_to_compcode (lcode); + rcompcode = comparison_to_compcode (rcode); + compcode = (code == TRUTH_AND_EXPR) + ? lcompcode & rcompcode + : lcompcode | rcompcode; + } + else if (operand_equal_p (ll_arg, rr_arg, 0) + && operand_equal_p (lr_arg, rl_arg, 0)) + { + int lcompcode, rcompcode; + + rcode = swap_tree_comparison (rcode); + lcompcode = comparison_to_compcode (lcode); + rcompcode = comparison_to_compcode (rcode); + compcode = (code == TRUTH_AND_EXPR) + ? lcompcode & rcompcode + : lcompcode | rcompcode; + } + else + compcode = -1; + + if (compcode == COMPCODE_TRUE) + return convert (truth_type, integer_one_node); + else if (compcode == COMPCODE_FALSE) + return convert (truth_type, integer_zero_node); + else if (compcode != -1) + return build (compcode_to_comparison (compcode), + truth_type, ll_arg, lr_arg); + } + /* If the RHS can be evaluated unconditionally and its operands are simple, it wins to evaluate the RHS unconditionally on machines with expensive branches. In this case, this isn't a comparison |