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 | |
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')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/fold-const.c | 111 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/compare-1.c | 119 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/compare-2.c | 24 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/compare-3.c | 86 |
6 files changed, 355 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 75ee853..b190a54 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2002-06-15 Roger Sayle <roger@eyesopen.com> + + * 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. + 2002-06-15 Aldy Hernandez <aldyh@redhat.com> * tm.texi (MEMBER_TYPE_FORCES_BLK): Document MODE argument. 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ee641bc..68a9cc1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2002-06-15 Roger Sayle <roger@eyesopen.com> + + * 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. + 2002-06-13 Richard Henderson <rth@redhat.com> * g++.old-deja/g++.abi/vtable2.C (INC_VDATA): New. Define for diff --git a/gcc/testsuite/gcc.c-torture/execute/compare-1.c b/gcc/testsuite/gcc.c-torture/execute/compare-1.c new file mode 100644 index 0000000..78b4650 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/compare-1.c @@ -0,0 +1,119 @@ +/* Copyright (C) 2002 Free Software Foundation. + + Test for correctness of composite comparisons. + + Written by Roger Sayle, 3rd June 2002. */ + +extern void abort (void); + +int ieq (int x, int y, int ok) +{ + if ((x<=y) && (x>=y)) + { + if (!ok) abort (); + } + else + if (ok) abort (); + + if ((x<=y) && (x==y)) + { + if (!ok) abort (); + } + else + if (ok) abort (); + + if ((x<=y) && (y<=x)) + { + if (!ok) abort (); + } + else + if (ok) abort (); + + if ((y==x) && (x<=y)) + { + if (!ok) abort (); + } + else + if (ok) abort (); +} + +int ine (int x, int y, int ok) +{ + if ((x<y) || (x>y)) + { + if (!ok) abort (); + } + else + if (ok) abort (); +} + +int ilt (int x, int y, int ok) +{ + if ((x<y) && (x!=y)) + { + if (!ok) abort (); + } + else + if (ok) abort (); +} + +int ile (int x, int y, int ok) +{ + if ((x<y) || (x==y)) + { + if (!ok) abort (); + } + else + if (ok) abort (); +} + +int igt (int x, int y, int ok) +{ + if ((x>y) && (x!=y)) + { + if (!ok) abort (); + } + else + if (ok) abort (); +} + +int ige (int x, int y, int ok) +{ + if ((x>y) || (x==y)) + { + if (!ok) abort (); + } + else + if (ok) abort (); +} + +int +main () +{ + ieq (1, 4, 0); + ieq (3, 3, 1); + ieq (5, 2, 0); + + ine (1, 4, 1); + ine (3, 3, 0); + ine (5, 2, 1); + + ilt (1, 4, 1); + ilt (3, 3, 0); + ilt (5, 2, 0); + + ile (1, 4, 1); + ile (3, 3, 1); + ile (5, 2, 0); + + igt (1, 4, 0); + igt (3, 3, 0); + igt (5, 2, 1); + + ige (1, 4, 0); + ige (3, 3, 1); + ige (5, 2, 1); + + return 0; +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/compare-2.c b/gcc/testsuite/gcc.c-torture/execute/compare-2.c new file mode 100644 index 0000000..858df29 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/compare-2.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2002 Free Software Foundation. + + Ensure that the composite comparison optimization doesn't misfire + and attempt to combine a signed comparison with an unsigned one. + + Written by Roger Sayle, 3rd June 2002. */ + +extern void abort (void); + +int +foo (int x, int y) +{ + /* If miscompiled the following may become "x == y". */ + return (x<=y) && ((unsigned int)x >= (unsigned int)y); +} + +int +main () +{ + if (! foo (-1,0)) + abort (); + return 0; +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/compare-3.c b/gcc/testsuite/gcc.c-torture/execute/compare-3.c new file mode 100644 index 0000000..6549c90 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/compare-3.c @@ -0,0 +1,86 @@ +/* Copyright (C) 2002 Free Software Foundation. + + Test for composite comparison always true/false optimization. + + Written by Roger Sayle, 7th June 2002. */ + +extern void link_error0 (); +extern void link_error1 (); + +void +test1 (int x, int y) +{ + if ((x==y) && (x!=y)) + link_error0(); +} + +void +test2 (int x, int y) +{ + if ((x<y) && (x>y)) + link_error0(); +} + +void +test3 (int x, int y) +{ + if ((x<y) && (y<x)) + link_error0(); +} + +void +test4 (int x, int y) +{ + if ((x==y) || (x!=y)) + { + } + else + link_error1 (); +} + +void +test5 (int x, int y) +{ + if ((x>=y) || (x<y)) + { + } + else + link_error1 (); +} + +void +test6 (int x, int y) +{ + if ((x<=y) || (y<x)) + { + } + else + link_error1 (); +} + +void +all_tests (int x, int y) +{ + test1 (x, y); + test2 (x, y); + test3 (x, y); + test4 (x, y); + test5 (x, y); + test6 (x, y); +} + +int +main () +{ + all_tests (0, 0); + all_tests (1, 2); + all_tests (4, 3); + + return 0; +} + +#ifndef __OPTIMIZE__ +void link_error0() {} +void link_error1() {} +#endif /* ! __OPTIMIZE__ */ + |