From: Roger Sayle Date: Mon, 13 Feb 2006 18:33:32 +0000 (+0000) Subject: re PR middle-end/24427 (missing optimization opportunity with binary operators) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=840992bdc20effc919b96522ab4f82fd96087939;p=gcc.git re PR middle-end/24427 (missing optimization opportunity with binary operators) PR middle-end/24427 * fold-const.c (fold_binary) : Transform (X&C1)|C2 into (X,C2) if C1 is a subset of the bits of C2. Transform (X&C1)|C2 into X|C2 if C1|C2 == ~0. Canonicalize (X&C1)|C2 as (X&(C1&~C2))|C2. : Canonicalize (X|C1)&C2 as (X&C2)|(C1&C2). * gcc.dg/tree-ssa/andor-1.c: New test case. From-SVN: r110918 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2c8fe9527c9..a5c9761dc46 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2006-02-13 Roger Sayle + + PR middle-end/24427 + * fold-const.c (fold_binary) : Transform (X&C1)|C2 + into (X,C2) if C1 is a subset of the bits of C2. Transform + (X&C1)|C2 into X|C2 if C1|C2 == ~0. Canonicalize (X&C1)|C2 as + (X&(C1&~C2))|C2. + : Canonicalize (X|C1)&C2 as (X&C2)|(C1&C2). + 2006-02-13 Josh Conner PR target/25376 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 67991076577..03c9d1c17e5 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8114,6 +8114,53 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return omit_one_operand (type, t1, arg0); } + /* Canonicalize (X & C1) | C2. */ + if (TREE_CODE (arg0) == BIT_AND_EXPR + && TREE_CODE (arg1) == INTEGER_CST + && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST) + { + unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, mlo, mhi; + int width = TYPE_PRECISION (type); + hi1 = TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)); + lo1 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)); + hi2 = TREE_INT_CST_HIGH (arg1); + lo2 = TREE_INT_CST_LOW (arg1); + + /* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2). */ + if ((hi1 & hi2) == hi1 && (lo1 & lo2) == lo1) + return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0)); + + if (width > HOST_BITS_PER_WIDE_INT) + { + mhi = (unsigned HOST_WIDE_INT) -1 + >> (2 * HOST_BITS_PER_WIDE_INT - width); + mlo = -1; + } + else + { + mhi = 0; + mlo = (unsigned HOST_WIDE_INT) -1 + >> (HOST_BITS_PER_WIDE_INT - width); + } + + /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2. */ + if ((~(hi1 | hi2) & mhi) == 0 && (~(lo1 | lo2) & mlo) == 0) + return fold_build2 (BIT_IOR_EXPR, type, + TREE_OPERAND (arg0, 0), arg1); + + /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2. */ + hi1 &= mhi; + lo1 &= mlo; + if ((hi1 & ~hi2) != hi1 || (lo1 & ~lo2) != lo1) + return fold_build2 (BIT_IOR_EXPR, type, + fold_build2 (BIT_AND_EXPR, type, + TREE_OPERAND (arg0, 0), + build_int_cst_wide (type, + lo1 & ~lo2, + hi1 & ~hi2)), + arg1); + } + t1 = distribute_bit_expr (code, type, arg0, arg1); if (t1 != NULL_TREE) return t1; @@ -8256,6 +8303,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)) return omit_one_operand (type, integer_zero_node, arg0); + /* Canonicalize (X | C1) & C2 as (X & C2) | (C1 & C2). */ + if (TREE_CODE (arg0) == BIT_IOR_EXPR + && TREE_CODE (arg1) == INTEGER_CST + && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST) + return fold_build2 (BIT_IOR_EXPR, type, + fold_build2 (BIT_AND_EXPR, type, + TREE_OPERAND (arg0, 0), arg1), + fold_build2 (BIT_AND_EXPR, type, + TREE_OPERAND (arg0, 1), arg1)); + t1 = distribute_bit_expr (code, type, arg0, arg1); if (t1 != NULL_TREE) return t1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3338042a72c..03caacb0f1a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-02-13 Roger Sayle + + PR middle-end/24427 + * gcc.dg/tree-ssa/andor-1.c: New test case. + 2006-02-13 Josh Conner PR target/25376 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/andor-1.c b/gcc/testsuite/gcc.dg/tree-ssa/andor-1.c new file mode 100644 index 00000000000..1a53857401c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/andor-1.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-original" } */ + +unsigned int test1(unsigned int a) +{ + return (a & 1) | 1; +} + +int test2(int b) +{ + return (b & 1) | 1; +} + +unsigned int test3(unsigned int c) +{ + return (c | 1) & 1; +} + +int test4(int d) +{ + return (d | 1) & 1; +} + +unsigned int test5(unsigned int e) +{ + return (e | 4) & 6; +} + +int test6(int f) +{ + return (f | 4) & 6; +} + +unsigned int test7(unsigned int g) +{ + return (g & -2) | 1; +} + +int test8(int h) +{ + return (h & -2) | 1; +} + +unsigned int test9(unsigned int i) +{ + return (i & 3) | 1; +} + +int test10(int j) +{ + return (j & 3) | 1; +} + +/* { dg-final { scan-tree-dump-times "a \& 1 \\| 1" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "b \& 1 \\| 1" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "\\(c \\| 1\\) \& 1" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "\\(d \\| 1\\) \& 1" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "e \& 2 \\| 4" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "f \& 2 \\| 4" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "g \\| 1" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "h \\| 1" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "i \& 2 \\| 1" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "j \& 2 \\| 1" 1 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ +