mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-05 06:29:32 +08:00
re PR rtl-optimization/3995 (i386 optimisation: joining tests)
PR opt/3995 * fold-const.c (sign_bit_p): New function. (fold) [EQ_EXPR]: Use this to convert (A & C) == 0 into A >= 0 and (A & C) != 0 into A < 0, when constant C is the sign bit of A's type. Reapply fold when converting (A & C) == C into (A & C) != 0. (fold_binary_op_with_conditional_arg): Fix typo in comment. testsuite/ * gcc.c-torture/execute/20020506-1.c: New test case. From-SVN: r53241
This commit is contained in:
parent
a5a49440f7
commit
1f77b5da98
@ -1,3 +1,12 @@
|
||||
2002-05-06 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR opt/3995
|
||||
* fold-const.c (sign_bit_p): New function.
|
||||
(fold) [EQ_EXPR]: Use this to convert (A & C) == 0 into A >= 0 and
|
||||
(A & C) != 0 into A < 0, when constant C is the sign bit of A's type.
|
||||
Reapply fold when converting (A & C) == C into (A & C) != 0.
|
||||
(fold_binary_op_with_conditional_arg): Fix typo in comment.
|
||||
|
||||
2002-05-07 Neil Booth <neil@daikokuya.demon.co.uk>
|
||||
|
||||
* c-common.c (warn_multichar): New.
|
||||
|
@ -86,6 +86,7 @@ static tree decode_field_reference PARAMS ((tree, HOST_WIDE_INT *,
|
||||
enum machine_mode *, int *,
|
||||
int *, tree *, tree *));
|
||||
static int all_ones_mask_p PARAMS ((tree, int));
|
||||
static tree sign_bit_p PARAMS ((tree, tree));
|
||||
static int simple_operand_p PARAMS ((tree));
|
||||
static tree range_binop PARAMS ((enum tree_code, tree, tree, int,
|
||||
tree, int));
|
||||
@ -2634,6 +2635,55 @@ all_ones_mask_p (mask, size)
|
||||
size_int (precision - size), 0));
|
||||
}
|
||||
|
||||
/* Subroutine for fold: determine if VAL is the INTEGER_CONST that
|
||||
represents the sign bit of EXP's type. If EXP represents a sign
|
||||
or zero extension, also test VAL against the unextended type.
|
||||
The return value is the (sub)expression whose sign bit is VAL,
|
||||
or NULL_TREE otherwise. */
|
||||
|
||||
static tree
|
||||
sign_bit_p (exp, val)
|
||||
tree exp;
|
||||
tree val;
|
||||
{
|
||||
unsigned HOST_WIDE_INT lo;
|
||||
HOST_WIDE_INT hi;
|
||||
int width;
|
||||
tree t;
|
||||
|
||||
/* Tree EXP must have a integral type. */
|
||||
t = TREE_TYPE (exp);
|
||||
if (! INTEGRAL_TYPE_P (t))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Tree VAL must be an integer constant. */
|
||||
if (TREE_CODE (val) != INTEGER_CST
|
||||
|| TREE_CONSTANT_OVERFLOW (val))
|
||||
return NULL_TREE;
|
||||
|
||||
width = TYPE_PRECISION (t);
|
||||
if (width > HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
hi = (unsigned HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT - 1);
|
||||
lo = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hi = 0;
|
||||
lo = (unsigned HOST_WIDE_INT) 1 << (width - 1);
|
||||
}
|
||||
|
||||
if (TREE_INT_CST_HIGH (val) == hi && TREE_INT_CST_LOW (val) == lo)
|
||||
return exp;
|
||||
|
||||
/* Handle extension from a narrower type. */
|
||||
if (TREE_CODE (exp) == NOP_EXPR
|
||||
&& TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))) < width)
|
||||
return sign_bit_p (TREE_OPERAND (exp, 0), val);
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Subroutine for fold_truthop: determine if an operand is simple enough
|
||||
to be evaluated unconditionally. */
|
||||
|
||||
@ -4173,7 +4223,7 @@ count_cond (expr, lim)
|
||||
return MIN (lim, 1 + ctrue + cfalse);
|
||||
}
|
||||
|
||||
/* Transform `a + (b ? x : y)' into `x ? (a + b) : (a + y)'.
|
||||
/* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
|
||||
Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'. Here
|
||||
CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
|
||||
expression, and ARG to `a'. If COND_FIRST_P is non-zero, then the
|
||||
@ -6037,8 +6087,25 @@ fold (expr)
|
||||
&& TREE_CODE (arg0) == BIT_AND_EXPR
|
||||
&& integer_pow2p (TREE_OPERAND (arg0, 1))
|
||||
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
|
||||
return build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
|
||||
arg0, integer_zero_node);
|
||||
return fold (build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
|
||||
arg0, integer_zero_node));
|
||||
|
||||
/* If we have (A & C) != 0 where C is the sign bit of A, convert
|
||||
this into A < 0. Similarly for (A & C) == 0 into A >= 0. */
|
||||
if ((code == EQ_EXPR || code == NE_EXPR)
|
||||
&& TREE_CODE (arg0) == BIT_AND_EXPR
|
||||
&& integer_zerop (arg1))
|
||||
{
|
||||
tree arg00 = sign_bit_p (TREE_OPERAND (arg0, 0),
|
||||
TREE_OPERAND (arg0, 1));
|
||||
if (arg00 != NULL_TREE)
|
||||
{
|
||||
tree stype = (*lang_hooks.types.signed_type) (TREE_TYPE (arg00));
|
||||
return fold (build (code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
|
||||
convert (stype, arg00),
|
||||
convert (stype, integer_zero_node)));
|
||||
}
|
||||
}
|
||||
|
||||
/* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
|
||||
and similarly for >= into !=. */
|
||||
|
@ -1,3 +1,7 @@
|
||||
2002-05-06 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* gcc.c-torture/execute/20020506-1.c: New test case.
|
||||
|
||||
2002-05-07 Neil Booth <neil@daikokuya.demon.co.uk>
|
||||
|
||||
* gcc.dg/cpp/charconst-3.c: Correct tests accordingly.
|
||||
|
333
gcc/testsuite/gcc.c-torture/execute/20020506-1.c
Normal file
333
gcc/testsuite/gcc.c-torture/execute/20020506-1.c
Normal file
@ -0,0 +1,333 @@
|
||||
/* Copyright (C) 2002 Free Software Foundation.
|
||||
|
||||
Test that (A & C1) op C2 optimizations behave correctly where C1 is
|
||||
a constant power of 2, op is == or !=, and C2 is C1 or zero.
|
||||
|
||||
Written by Roger Sayle, 5th May 2002. */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
void test1 (signed char c, int set);
|
||||
void test2 (unsigned char c, int set);
|
||||
void test3 (short s, int set);
|
||||
void test4 (unsigned short s, int set);
|
||||
void test5 (int i, int set);
|
||||
void test6 (unsigned int i, int set);
|
||||
void test7 (long long l, int set);
|
||||
void test8 (unsigned long long l, int set);
|
||||
|
||||
#ifndef LONG_LONG_MAX
|
||||
#define LONG_LONG_MAX __LONG_LONG_MAX__
|
||||
#endif
|
||||
#ifndef LONG_LONG_MIN
|
||||
#define LONG_LONG_MIN (-LONG_LONG_MAX-1)
|
||||
#endif
|
||||
#ifndef ULONG_LONG_MAX
|
||||
#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1)
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
test1 (signed char c, int set)
|
||||
{
|
||||
if ((c & (SCHAR_MAX+1)) == 0)
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
|
||||
if ((c & (SCHAR_MAX+1)) != 0)
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((c & (SCHAR_MAX+1)) == (SCHAR_MAX+1))
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((c & (SCHAR_MAX+1)) != (SCHAR_MAX+1))
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
}
|
||||
|
||||
void
|
||||
test2 (unsigned char c, int set)
|
||||
{
|
||||
if ((c & (SCHAR_MAX+1)) == 0)
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
|
||||
if ((c & (SCHAR_MAX+1)) != 0)
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((c & (SCHAR_MAX+1)) == (SCHAR_MAX+1))
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((c & (SCHAR_MAX+1)) != (SCHAR_MAX+1))
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
}
|
||||
|
||||
void
|
||||
test3 (short s, int set)
|
||||
{
|
||||
if ((s & (SHRT_MAX+1)) == 0)
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
|
||||
if ((s & (SHRT_MAX+1)) != 0)
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((s & (SHRT_MAX+1)) == (SHRT_MAX+1))
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((s & (SHRT_MAX+1)) != (SHRT_MAX+1))
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
}
|
||||
|
||||
void
|
||||
test4 (unsigned short s, int set)
|
||||
{
|
||||
if ((s & (SHRT_MAX+1)) == 0)
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
|
||||
if ((s & (SHRT_MAX+1)) != 0)
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((s & (SHRT_MAX+1)) == (SHRT_MAX+1))
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((s & (SHRT_MAX+1)) != (SHRT_MAX+1))
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
}
|
||||
|
||||
void
|
||||
test5 (int i, int set)
|
||||
{
|
||||
if ((i & (INT_MAX+1U)) == 0)
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
|
||||
if ((i & (INT_MAX+1U)) != 0)
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((i & (INT_MAX+1U)) == (INT_MAX+1U))
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((i & (INT_MAX+1U)) != (INT_MAX+1U))
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
}
|
||||
|
||||
void
|
||||
test6 (unsigned int i, int set)
|
||||
{
|
||||
if ((i & (INT_MAX+1U)) == 0)
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
|
||||
if ((i & (INT_MAX+1U)) != 0)
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((i & (INT_MAX+1U)) == (INT_MAX+1U))
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((i & (INT_MAX+1U)) != (INT_MAX+1U))
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
}
|
||||
|
||||
void
|
||||
test7 (long long l, int set)
|
||||
{
|
||||
if ((l & (LONG_LONG_MAX+1ULL)) == 0)
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
|
||||
if ((l & (LONG_LONG_MAX+1ULL)) != 0)
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((l & (LONG_LONG_MAX+1ULL)) == (LONG_LONG_MAX+1ULL))
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((l & (LONG_LONG_MAX+1ULL)) != (LONG_LONG_MAX+1ULL))
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
}
|
||||
|
||||
void
|
||||
test8 (unsigned long long l, int set)
|
||||
{
|
||||
if ((l & (LONG_LONG_MAX+1ULL)) == 0)
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
|
||||
if ((l & (LONG_LONG_MAX+1ULL)) != 0)
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((l & (LONG_LONG_MAX+1ULL)) == (LONG_LONG_MAX+1ULL))
|
||||
{
|
||||
if (!set) abort ();
|
||||
}
|
||||
else
|
||||
if (set) abort ();
|
||||
|
||||
if ((l & (LONG_LONG_MAX+1ULL)) != (LONG_LONG_MAX+1ULL))
|
||||
{
|
||||
if (set) abort ();
|
||||
}
|
||||
else
|
||||
if (!set) abort ();
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
test1 (0, 0);
|
||||
test1 (SCHAR_MAX, 0);
|
||||
test1 (SCHAR_MIN, 1);
|
||||
test1 (UCHAR_MAX, 1);
|
||||
|
||||
test2 (0, 0);
|
||||
test2 (SCHAR_MAX, 0);
|
||||
test2 (SCHAR_MIN, 1);
|
||||
test2 (UCHAR_MAX, 1);
|
||||
|
||||
test3 (0, 0);
|
||||
test3 (SHRT_MAX, 0);
|
||||
test3 (SHRT_MIN, 1);
|
||||
test3 (USHRT_MAX, 1);
|
||||
|
||||
test4 (0, 0);
|
||||
test4 (SHRT_MAX, 0);
|
||||
test4 (SHRT_MIN, 1);
|
||||
test4 (USHRT_MAX, 1);
|
||||
|
||||
test5 (0, 0);
|
||||
test5 (INT_MAX, 0);
|
||||
test5 (INT_MIN, 1);
|
||||
test5 (UINT_MAX, 1);
|
||||
|
||||
test6 (0, 0);
|
||||
test6 (INT_MAX, 0);
|
||||
test6 (INT_MIN, 1);
|
||||
test6 (UINT_MAX, 1);
|
||||
|
||||
test7 (0, 0);
|
||||
test7 (LONG_LONG_MAX, 0);
|
||||
test7 (LONG_LONG_MIN, 1);
|
||||
test7 (ULONG_LONG_MAX, 1);
|
||||
|
||||
test8 (0, 0);
|
||||
test8 (LONG_LONG_MAX, 0);
|
||||
test8 (LONG_LONG_MIN, 1);
|
||||
test8 (ULONG_LONG_MAX, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user