aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2002-06-15 16:55:24 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2002-06-15 16:55:24 +0000
commit8dcb27ed86eb249675749e35b1440a8ccfd03881 (patch)
treec9fc91c5bbced804e712ce47aaa7397c5a3ed98d /gcc/fold-const.c
parentf7d3c5f00586f93c1a5a46ebbffa14dce150aae7 (diff)
downloadgcc-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.c111
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