diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 75ee8530177..b190a54807e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2002-06-15 Roger Sayle + + * 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 * tm.texi (MEMBER_TYPE_FORCES_BLK): Document MODE argument. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 5c04d78a90d..f9f3a649433 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 + + * 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 * 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 00000000000..78b465024ea --- /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 ((xy)) + { + if (!ok) abort (); + } + else + if (ok) abort (); +} + +int ilt (int x, int y, int ok) +{ + if ((xy) && (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 00000000000..858df294eca --- /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 00000000000..6549c904b52 --- /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 ((xy)) + link_error0(); +} + +void +test3 (int x, int y) +{ + if ((x=y) || (x