From 3d1d4d838fed9af45aea9fa99f8954585fee7c23 Mon Sep 17 00:00:00 2001 From: Andre Simoes Dias Vieira Date: Wed, 2 Sep 2015 16:47:38 +0100 Subject: [PATCH] algorithmic optimization v2 --- gcc/match.pd | 70 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/forwprop-33.c | 42 +++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/forwprop-33.c diff --git a/gcc/match.pd b/gcc/match.pd index fb4b342d31d26a03bc756c538f6635f2acf6ddb2..6138591c0cef1814dcbd6313dedaa95a91700dc2 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -710,6 +710,76 @@ along with GCC; see the file COPYING3. If not see && tree_nop_conversion_p (type, TREE_TYPE (@1))) (convert (bit_and (bit_not @1) @0)))) +/* (X bit_op C0) rshift C1 -> (X rshift C0) bit_op (C0 rshift C1) */ +(for bit_op (bit_ior bit_xor bit_and) +(simplify + (rshift (bit_op:s @0 INTEGER_CST@1) INTEGER_CST@2) + (bit_op + (rshift @0 @2) + { wide_int_to_tree (type, wi::rshift (@1, @2, TYPE_SIGN (type))); }))) + +/* (X bit_op C0) lshift C1 -> (X lshift C0) bit_op (C0 lshift C1) */ +(for bit_op (bit_ior bit_xor bit_and) +(simplify + (lshift (bit_op:s @0 INTEGER_CST@1) INTEGER_CST@2) + (bit_op + (lshift @0 @2) + { wide_int_to_tree (type, wi::lshift (@1, @2)); }))) + + +/* ((X op0 C0) op1 C1) op2 C2) + with op0 = {&, >>, <<}, op1 = {|,^}, op2 = {|,^} and op1 != op2 + zero_mask has 1's for all bits that are sure to be 0 in (X op0 C0) + and 0's otherwise. + if (op1 == '^') C1 &= ~C2; + if ((C1 & ~zero_mask) == 0) then emit (X op0 C0) op2 (C1 op2 C2) + if ((C2 & ~zero_mask) == 0) then emit (X op0 C0) op1 (C1 op2 C2) +*/ +(for op0 (rshift lshift bit_and) + (for op1 (bit_ior bit_xor) + op2 (bit_xor bit_ior) +(simplify + (op2 + (op1:s + (op0:s @0 INTEGER_CST@1) INTEGER_CST@2) INTEGER_CST@3) + (if (!(op0 == RSHIFT_EXPR && !TYPE_UNSIGNED (type)) && wi::fits_uhwi_p (@1)) + (with + { + unsigned int prec = TYPE_PRECISION (type); + wide_int zero_mask_not; + wide_int C1; + wide_int cst_emit; + if (op0 == BIT_AND_EXPR) + { + zero_mask_not = @1; + } + else if (op0 == LSHIFT_EXPR) + { + zero_mask_not = wi::bit_not (wi::mask (tree_to_uhwi (@1), false, + prec)); + } + else if (op0 == RSHIFT_EXPR) + { + unsigned HOST_WIDE_INT m = prec - tree_to_uhwi (@1); + zero_mask_not = wi::bit_not (wi::mask (m, true, prec)); + } + + if (op1 == BIT_XOR_EXPR) + { + C1 = wi::bit_and_not (@2, @3); + cst_emit = wi::bit_or (C1, @3); + } + else + { + C1 = @2; + cst_emit = wi::bit_xor (@2, @3); + } + } + (if (wi::eq_p (wi::bit_and (C1, zero_mask_not), wi::zero (prec))) + (op2 (op0 @0 @1) { wide_int_to_tree (type, cst_emit); }) + (if (wi::eq_p (wi::bit_and (@3, zero_mask_not), wi::zero (prec))) + (op1 (op0 @0 @1) { wide_int_to_tree (type, cst_emit); })))))))) + /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */ (simplify (pointer_plus (pointer_plus:s @0 @1) @3) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-33.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-33.c new file mode 100644 index 0000000000000000000000000000000000000000..c8940d62a7a9370e9d2b911badfc6d085f988304 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-33.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-forwprop1" } */ + +unsigned short +foo (unsigned short a) +{ + a ^= 0x4002; + a >>= 1; + a |= 0x8000; /* Simplify to ((a >> 1) ^ 0xa001). */ + return a; +} +/* { dg-final { scan-tree-dump "\\^ 40961" "forwprop1" } } */ + +unsigned short +bar (unsigned short a) +{ + a |= 0x4002; + a <<= 1; + a ^= 0x0001; /* Simplify to ((a << 1) | 0x8005). */ + return a; +} +/* { dg-final { scan-tree-dump "\\| 32773" "forwprop1" } } */ + +unsigned short +baz (unsigned short a) +{ + a &= 0xd123; + a ^= 0x6040; + a |= 0xc031; /* Simplify to ((a & 0xd123) | 0xe071). */ + return a; +} +/* { dg-final { scan-tree-dump "\\| 57457" "forwprop1" } } */ + +short +qux (short a) +{ + a ^= 0x8002; + a >>= 1; + a |= 0x8000; /* Only move shift inward: (((a >> 1) ^ 0x4001 |) 0x8000). */ + return a; +} +/* { dg-final { scan-tree-dump "\\^ -16383" "forwprop1" } } */ -- 1.9.1