From ac76659583ab0d9eb96552a540a22e66fdd430f7 Mon Sep 17 00:00:00 2001
From: Andre Simoes Dias Vieira <andsim01@arm.com>
Date: Fri, 23 Oct 2015 15:35:27 +0100
Subject: [PATCH 1/2] backport algorithmic optimization
---
gcc/fold-const.c | 21 ---------
gcc/match.pd | 54 ++++++++++++++++++++++
gcc/testsuite/gcc.dg/tree-ssa/forwprop-33.c | 71 +++++++++++++++++++++++++++++
3 files changed, 125 insertions(+), 21 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/forwprop-33.c
@@ -12080,27 +12080,6 @@ fold_binary_loc (location_t loc,
prec) == 0)
return TREE_OPERAND (arg0, 0);
- /* Fold (X & C2) << C1 into (X << C1) & (C2 << C1)
- (X & C2) >> C1 into (X >> C1) & (C2 >> C1)
- if the latter can be further optimized. */
- if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR)
- && TREE_CODE (arg0) == BIT_AND_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- {
- tree mask = fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 1)),
- arg1);
- tree shift = fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- arg1);
- tem = fold_binary_loc (loc, BIT_AND_EXPR, type, shift, mask);
- if (tem)
- return tem;
- }
-
return NULL_TREE;
case MIN_EXPR:
@@ -389,6 +389,49 @@ along with GCC; see the file COPYING3. If not see
&& (TREE_CODE (@4) != SSA_NAME || has_single_use (@4)))
(bit_xor (bit_and (bit_xor @0 @1) @2) @0)))
+/* ((X inner_op C0) outer_op C1)
+ With X being a tree where value_range has reasoned certain bits to always be
+ zero throughout its computed value range,
+ inner_op = {|,^}, outer_op = {|,^} and inner_op != outer_op
+ where zero_mask has 1's for all bits that are sure to be 0 in
+ and 0's otherwise.
+ if (inner_op == '^') C0 &= ~C1;
+ if ((C0 & ~zero_mask) == 0) then emit (X outer_op (C0 outer_op C1)
+ if ((C1 & ~zero_mask) == 0) then emit (X inner_op (C0 outer_op C1)
+*/
+(for inner_op (bit_ior bit_xor)
+ outer_op (bit_xor bit_ior)
+(simplify
+ (outer_op
+ (inner_op@3 @2 INTEGER_CST@0) INTEGER_CST@1)
+ (with
+ {
+ bool fail = false;
+ wide_int zero_mask_not;
+ wide_int C0;
+ wide_int cst_emit;
+
+ if (TREE_CODE (@2) == SSA_NAME &&
+ (TREE_CODE (@3) != SSA_NAME || has_single_use (@3)))
+ zero_mask_not = get_nonzero_bits (@2);
+ else
+ fail = true;
+
+ if (inner_op == BIT_XOR_EXPR)
+ {
+ C0 = wi::bit_and_not (@0, @1);
+ cst_emit = wi::bit_or (C0, @1);
+ }
+ else
+ {
+ C0 = @0;
+ cst_emit = wi::bit_xor (@0, @1);
+ }
+ }
+ (if (!fail && wi::bit_and (C0, zero_mask_not) == 0)
+ (outer_op @2 { wide_int_to_tree (type, cst_emit); }))
+ (if (!fail && wi::bit_and (@1, zero_mask_not) == 0)
+ (inner_op @2 { wide_int_to_tree (type, cst_emit); })))))
/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */
(simplify
@@ -614,6 +657,17 @@ along with GCC; see the file COPYING3. If not see
(cmp (bit_and (lshift integer_onep @0) integer_onep) integer_zerop)
(icmp @0 { build_zero_cst (TREE_TYPE (@0)); })))
+/* Fold (X {&,^,|} C2) << C1 into (X << C1) {&,^,|} (C2 << C1)
+ (X {&,^,|} C2) >> C1 into (X >> C1) & (C2 >> C1). */
+ (for shift (lshift rshift)
+ (for bit_op (bit_and bit_xor bit_ior)
+ (simplify
+ (shift (convert? (bit_op@4 @0 INTEGER_CST@2)) INTEGER_CST@1)
+ (with { bool fail = !(TREE_CODE (@4) != SSA_NAME || has_single_use (@4)); }
+ (if (!fail && tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (with { tree mask = int_const_binop (shift, fold_convert (type, @2), @1); }
+ (bit_op (shift (convert @0) @1) { mask; })))))))
+
/* Simplifications of conversions. */
/* Basic strip-useless-type-conversions / strip_nops. */
new file mode 100644
@@ -0,0 +1,71 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-forwprop3" } */
+
+unsigned short
+test1 (unsigned short a)
+{
+ a ^= 0x4002;
+ a >>= 1;
+ a |= 0x8000; /* Simplify to ((a >> 1) ^ 0xa001). */
+ return a;
+}
+/* { dg-final { scan-tree-dump "\\^ 40961" "forwprop3" } } */
+
+unsigned short
+test2 (unsigned short a)
+{
+ a |= 0x4002;
+ a <<= 1;
+ a ^= 0x0001; /* Simplify to ((a << 1) | 0x8005). */
+ return a;
+}
+/* { dg-final { scan-tree-dump "\\| 32773" "forwprop3" } } */
+
+unsigned short
+test3 (unsigned short a)
+{
+ a &= 0xd123;
+ a ^= 0x6040;
+ a |= 0xc031; /* Simplify to ((a & 0xd123) | 0xe071). */
+ return a;
+}
+/* { dg-final { scan-tree-dump "\\| 57457" "forwprop3" } } */
+
+unsigned short
+test4 (unsigned short a)
+{
+ a ^= 0x8002;
+ a >>= 1;
+ a |= 0x8000;
+ return a;
+}
+/* { dg-final { scan-tree-dump "\\^ 49153" "forwprop3" } } */
+
+unsigned short
+test5 (unsigned short a)
+{
+ a ^= 0x8002;
+ a >>= 1;
+ a |= 0x8001; /* Only move shift inward: (((a >> 1) ^ 0x4001) | 0x8001). */
+ return a;
+}
+/* { dg-final { scan-tree-dump "\\^ 16385" "forwprop3" } } */
+/* { dg-final { scan-tree-dump "\\| 32769" "forwprop3" } } */
+
+short
+test6 (short a)
+{
+ a &= 0x7fff;
+ a >>= 2;
+ return a;
+}
+/* { dg-final { scan-tree-dump "\\& 8191" "forwprop3" } } */
+
+short
+test7 (short a)
+{
+ a &= 0x8fff;
+ a >>= 2;
+ return a;
+}
+/* { dg-final { scan-tree-dump "\\& -7169" "forwprop3" } } */
--
1.9.1