diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/combine.c | 23 | ||||
-rw-r--r-- | gcc/fold-const.c | 164 |
3 files changed, 108 insertions, 89 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5f144b450d6..af463a9c3ae 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/combine.c b/gcc/combine.c index a7b9c0c6d4a..7273e8f237e 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -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: diff --git a/gcc/fold-const.c b/gcc/fold-const.c index e38aabde03c..5ea6129de80 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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: |