fold-const.c (fold): Move bit_rotate code to the EXPR_PLUS case, falltrought to assocate code.

* fold-const.c (fold): Move bit_rotate code to the EXPR_PLUS case,
        falltrought to assocate code.
        Convert XOR to OR in code like (a&c1)^(a&c2) where c1 and c2 don't have
        bits in common.

        * combine.c (simplify_logical): Convert XOR to IOR if operands have
        no bits in common; remove XOR to ROTATE conversion.

From-SVN: r29998
This commit is contained in:
Jan Hubicka 1999-10-15 06:50:09 +02:00 committed by Jeff Law
parent ce57746769
commit 79e8185c9c
3 changed files with 108 additions and 89 deletions

View File

@ -1,3 +1,13 @@
Thu Oct 14 19:44:08 1999 Jan Hubicka <hubicka@freesoft.cz>
* fold-const.c (fold): Move bit_rotate code to the EXPR_PLUS case,
falltrought to assocate code.
Convert XOR to OR in code like (a&c1)^(a&c2) where c1 and c2 don't have
bits in common.
* combine.c (simplify_logical): Convert XOR to IOR if operands have
no bits in common; remove XOR to ROTATE conversion.
Fri Oct 15 17:40:11 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
* config/c4x/c4x.h (c4x_va_start, c4x_va_arg): Declare.

View File

@ -5163,6 +5163,15 @@ simplify_logical (x, last)
break;
case XOR:
/* If we are XORing two things that have no bits in common,
convert them into an IOR. This helps to detect rotation encoded
using those methods and possibly other simplifications. */
if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& (nonzero_bits (op0, mode)
& nonzero_bits (op1, mode)) == 0)
return (gen_binary (IOR, mode, op0, op1));
/* Convert (XOR (NOT x) (NOT y)) to (XOR x y).
Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for
(NOT y). */
@ -5232,20 +5241,6 @@ simplify_logical (x, last)
return gen_rtx_combine (reverse_condition (GET_CODE (op0)),
mode, XEXP (op0, 0), XEXP (op0, 1));
/* Convert (xor (ashift A CX) (lshiftrt A CY)) where CX+CY equals the
mode size to (rotate A CX). */
if (((GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
|| (GET_CODE (op1) == ASHIFT && GET_CODE (op0) == LSHIFTRT))
&& rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
&& GET_CODE (XEXP (op0, 1)) == CONST_INT
&& GET_CODE (XEXP (op1, 1)) == CONST_INT
&& (INTVAL (XEXP (op0, 1)) + INTVAL (XEXP (op1, 1))
== GET_MODE_BITSIZE (mode)))
return gen_rtx_ROTATE (mode, XEXP (op0, 0),
(GET_CODE (op0) == ASHIFT
? XEXP (op0, 1) : XEXP (op1, 1)));
break;
default:

View File

@ -4874,6 +4874,74 @@ fold (expr)
else if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1)))
return non_lvalue (convert (type, arg0));
bit_rotate:
/* (A << C1) + (A >> C2) if A is unsigned and C1+C2 is the size of A
is a rotate of A by C1 bits. */
/* (A << B) + (A >> (Z - B)) if A is unsigned and Z is the size of A
is a rotate of A by B bits. */
{
register enum tree_code code0, code1;
code0 = TREE_CODE (arg0);
code1 = TREE_CODE (arg1);
if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
|| (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
&& operand_equal_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1,0), 0)
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
register tree tree01, tree11;
register enum tree_code code01, code11;
tree01 = TREE_OPERAND (arg0, 1);
tree11 = TREE_OPERAND (arg1, 1);
STRIP_NOPS (tree01);
STRIP_NOPS (tree11);
code01 = TREE_CODE (tree01);
code11 = TREE_CODE (tree11);
if (code01 == INTEGER_CST
&& code11 == INTEGER_CST
&& TREE_INT_CST_HIGH (tree01) == 0
&& TREE_INT_CST_HIGH (tree11) == 0
&& ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
code0 == LSHIFT_EXPR ? tree01 : tree11);
else if (code11 == MINUS_EXPR)
{
tree tree110, tree111;
tree110 = TREE_OPERAND (tree11, 0);
tree111 = TREE_OPERAND (tree11, 1);
STRIP_NOPS (tree110);
STRIP_NOPS (tree111);
if (TREE_CODE (tree110) == INTEGER_CST
&& TREE_INT_CST_HIGH (tree110) == 0
&& (TREE_INT_CST_LOW (tree110)
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
&& operand_equal_p (tree01, tree111, 0))
return build ((code0 == LSHIFT_EXPR
? LROTATE_EXPR
: RROTATE_EXPR),
type, TREE_OPERAND (arg0, 0), tree01);
}
else if (code01 == MINUS_EXPR)
{
tree tree010, tree011;
tree010 = TREE_OPERAND (tree01, 0);
tree011 = TREE_OPERAND (tree01, 1);
STRIP_NOPS (tree010);
STRIP_NOPS (tree011);
if (TREE_CODE (tree010) == INTEGER_CST
&& TREE_INT_CST_HIGH (tree010) == 0
&& (TREE_INT_CST_LOW (tree010)
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
&& operand_equal_p (tree11, tree011, 0))
return build ((code0 != LSHIFT_EXPR
? LROTATE_EXPR
: RROTATE_EXPR),
type, TREE_OPERAND (arg0, 0), tree11);
}
}
}
associate:
/* In most languages, can't associate operations on floats
@ -5107,9 +5175,6 @@ fold (expr)
case BIT_IOR_EXPR:
bit_ior:
{
register enum tree_code code0, code1;
if (integer_all_onesp (arg1))
return omit_one_operand (type, arg1, arg0);
if (integer_zerop (arg1))
@ -5118,85 +5183,34 @@ fold (expr)
if (t1 != NULL_TREE)
return t1;
bit_rotate:
/* (A << C1) | (A >> C2) if A is unsigned and C1+C2 is the size of A
is a rotate of A by C1 bits. */
/* (A << B) | (A >> (Z - B)) if A is unsigned and Z is the size of A
is a rotate of A by B bits. */
/* Both transformations noted above also apply to when the inner
operation is an XOR. */
code0 = TREE_CODE (arg0);
code1 = TREE_CODE (arg1);
if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
|| (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
&& operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1,0), 0)
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
register tree tree01, tree11;
register enum tree_code code01, code11;
tree01 = TREE_OPERAND (arg0, 1);
tree11 = TREE_OPERAND (arg1, 1);
STRIP_NOPS (tree01);
STRIP_NOPS (tree11);
code01 = TREE_CODE (tree01);
code11 = TREE_CODE (tree11);
if (code01 == INTEGER_CST
&& code11 == INTEGER_CST
&& TREE_INT_CST_HIGH (tree01) == 0
&& TREE_INT_CST_HIGH (tree11) == 0
&& ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
code0 == LSHIFT_EXPR ? tree01 : tree11);
else if (code11 == MINUS_EXPR)
{
tree tree110, tree111;
tree110 = TREE_OPERAND (tree11, 0);
tree111 = TREE_OPERAND (tree11, 1);
STRIP_NOPS (tree110);
STRIP_NOPS (tree111);
if (TREE_CODE (tree110) == INTEGER_CST
&& TREE_INT_CST_HIGH (tree110) == 0
&& (TREE_INT_CST_LOW (tree110)
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
&& operand_equal_p (tree01, tree111, 0))
return build ((code0 == LSHIFT_EXPR
? LROTATE_EXPR
: RROTATE_EXPR),
type, TREE_OPERAND (arg0, 0), tree01);
}
else if (code01 == MINUS_EXPR)
{
tree tree010, tree011;
tree010 = TREE_OPERAND (tree01, 0);
tree011 = TREE_OPERAND (tree01, 1);
STRIP_NOPS (tree010);
STRIP_NOPS (tree011);
if (TREE_CODE (tree010) == INTEGER_CST
&& TREE_INT_CST_HIGH (tree010) == 0
&& (TREE_INT_CST_LOW (tree010)
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
&& operand_equal_p (tree11, tree011, 0))
return build ((code0 != LSHIFT_EXPR
? LROTATE_EXPR
: RROTATE_EXPR),
type, TREE_OPERAND (arg0, 0), tree11);
}
}
goto associate;
}
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
goto bit_rotate;
case BIT_XOR_EXPR:
if (integer_zerop (arg1))
return non_lvalue (convert (type, arg0));
if (integer_all_onesp (arg1))
return fold (build1 (BIT_NOT_EXPR, type, arg0));
/* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
with a constant, and the two constants have no bits in common,
we should treat this as a BIT_IOR_EXPR since this may produce more
simplifications. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& TREE_CODE (arg1) == BIT_AND_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
&& integer_zerop (const_binop (BIT_AND_EXPR,
TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 1), 0)))
{
code = BIT_IOR_EXPR;
goto bit_ior;
}
/* See if this can be simplified into a rotate first. If that
is unsuccessful we will jump to the association code. */
is unsuccessful continue in the association code. */
goto bit_rotate;
case BIT_AND_EXPR: