Commit 8dcb27ed by Roger Sayle Committed by Roger Sayle

fold-const.c (comparison_to_compcode): New function to convert an comparison…

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
parent f7d3c5f0
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> 2002-06-15 Aldy Hernandez <aldyh@redhat.com>
* tm.texi (MEMBER_TYPE_FORCES_BLK): Document MODE argument. * tm.texi (MEMBER_TYPE_FORCES_BLK): Document MODE argument.
......
...@@ -72,6 +72,8 @@ static int size_htab_eq PARAMS ((const void *, const void *)); ...@@ -72,6 +72,8 @@ static int size_htab_eq PARAMS ((const void *, const void *));
static tree fold_convert PARAMS ((tree, tree)); static tree fold_convert PARAMS ((tree, tree));
static enum tree_code invert_tree_comparison PARAMS ((enum tree_code)); static enum tree_code invert_tree_comparison PARAMS ((enum tree_code));
static enum tree_code swap_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 truth_value_p PARAMS ((enum tree_code));
static int operand_equal_for_comparison_p PARAMS ((tree, tree, tree)); static int operand_equal_for_comparison_p PARAMS ((tree, tree, tree));
static int twoval_comparison_p PARAMS ((tree, tree *, tree *, int *)); 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)); ...@@ -115,6 +117,18 @@ static bool fold_real_zero_addition_p PARAMS ((tree, tree, int));
#define CHARMASK 0x7f #define CHARMASK 0x7f
#endif #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 /* 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, 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 and SUM1. Then this yields nonzero if overflow occurred during the
...@@ -1709,6 +1723,61 @@ swap_tree_comparison (code) ...@@ -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. */ /* Return nonzero if CODE is a tree code that represents a truth value. */
static int static int
...@@ -3498,6 +3567,48 @@ fold_truthop (code, truth_type, lhs, rhs) ...@@ -3498,6 +3567,48 @@ fold_truthop (code, truth_type, lhs, rhs)
rl_arg = TREE_OPERAND (rhs, 0); rl_arg = TREE_OPERAND (rhs, 0);
rr_arg = TREE_OPERAND (rhs, 1); 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 /* If the RHS can be evaluated unconditionally and its operands are
simple, it wins to evaluate the RHS unconditionally on machines simple, it wins to evaluate the RHS unconditionally on machines
with expensive branches. In this case, this isn't a comparison with expensive branches. In this case, this isn't a comparison
......
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> 2002-06-13 Richard Henderson <rth@redhat.com>
* g++.old-deja/g++.abi/vtable2.C (INC_VDATA): New. Define for * g++.old-deja/g++.abi/vtable2.C (INC_VDATA): New. Define for
......
/* 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;
}
/* 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;
}
/* 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__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment