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
This commit is contained in:
parent
f7d3c5f005
commit
8dcb27ed86
6 changed files with 355 additions and 0 deletions
|
@ -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.
|
||||
|
|
111
gcc/fold-const.c
111
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
|
||||
|
|
|
@ -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
|
||||
|
|
119
gcc/testsuite/gcc.c-torture/execute/compare-1.c
Normal file
119
gcc/testsuite/gcc.c-torture/execute/compare-1.c
Normal file
|
@ -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;
|
||||
}
|
||||
|
24
gcc/testsuite/gcc.c-torture/execute/compare-2.c
Normal file
24
gcc/testsuite/gcc.c-torture/execute/compare-2.c
Normal file
|
@ -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;
|
||||
}
|
||||
|
86
gcc/testsuite/gcc.c-torture/execute/compare-3.c
Normal file
86
gcc/testsuite/gcc.c-torture/execute/compare-3.c
Normal file
|
@ -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__ */
|
||||
|
Loading…
Add table
Reference in a new issue