tree-optimization/94234 - Fold plusminus_mult expr with multi-use operands
2020-09-03 Feng Xue <fxue@os.amperecomputing.com> gcc/ PR tree-optimization/94234 * genmatch.c (dt_simplify::gen_1): Emit check on final simplification result when "!" is specified on toplevel output expr. * match.pd ((A * C) +- (B * C) -> (A +- B) * C): Allow folding on expr with multi-use operands if final result is a simple gimple value. gcc/testsuite/ PR tree-optimization/94234 * gcc.dg/pr94234-2.c: New test.
This commit is contained in:
parent
50a71cd018
commit
f9d2def016
3 changed files with 60 additions and 11 deletions
|
@ -3426,8 +3426,14 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
|
|||
/* Re-fold the toplevel result. It's basically an embedded
|
||||
gimple_build w/o actually building the stmt. */
|
||||
if (!is_predicate)
|
||||
fprintf_indent (f, indent,
|
||||
"res_op->resimplify (lseq, valueize);\n");
|
||||
{
|
||||
fprintf_indent (f, indent,
|
||||
"res_op->resimplify (lseq, valueize);\n");
|
||||
if (e->force_leaf)
|
||||
fprintf_indent (f, indent,
|
||||
"if (!maybe_push_res_to_seq (res_op, NULL)) "
|
||||
"goto %s;\n", fail_label);
|
||||
}
|
||||
}
|
||||
else if (result->type == operand::OP_CAPTURE
|
||||
|| result->type == operand::OP_C_EXPR)
|
||||
|
|
22
gcc/match.pd
22
gcc/match.pd
|
@ -2570,15 +2570,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|
|||
(for plusminus (plus minus)
|
||||
(simplify
|
||||
(plusminus (mult:cs@3 @0 @1) (mult:cs@4 @0 @2))
|
||||
(if ((!ANY_INTEGRAL_TYPE_P (type)
|
||||
|| TYPE_OVERFLOW_WRAPS (type)
|
||||
|| (INTEGRAL_TYPE_P (type)
|
||||
&& tree_expr_nonzero_p (@0)
|
||||
&& expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
|
||||
/* If @1 +- @2 is constant require a hard single-use on either
|
||||
original operand (but not on both). */
|
||||
&& (single_use (@3) || single_use (@4)))
|
||||
(mult (plusminus @1 @2) @0)))
|
||||
(if (!ANY_INTEGRAL_TYPE_P (type)
|
||||
|| TYPE_OVERFLOW_WRAPS (type)
|
||||
|| (INTEGRAL_TYPE_P (type)
|
||||
&& tree_expr_nonzero_p (@0)
|
||||
&& expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
|
||||
(if (single_use (@3) || single_use (@4))
|
||||
/* If @1 +- @2 is constant require a hard single-use on either
|
||||
original operand (but not on both). */
|
||||
(mult (plusminus @1 @2) @0)
|
||||
#if GIMPLE
|
||||
(mult! (plusminus @1 @2) @0)
|
||||
#endif
|
||||
)))
|
||||
/* We cannot generate constant 1 for fract. */
|
||||
(if (!ALL_FRACT_MODE_P (TYPE_MODE (type)))
|
||||
(simplify
|
||||
|
|
39
gcc/testsuite/gcc.dg/pr94234-2.c
Normal file
39
gcc/testsuite/gcc.dg/pr94234-2.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-forwprop1" } */
|
||||
|
||||
int use_fn (int a);
|
||||
|
||||
int foo (int n)
|
||||
{
|
||||
int b1 = 8 * (n + 1);
|
||||
int b2 = 8 * n;
|
||||
|
||||
use_fn (b1 ^ b2);
|
||||
|
||||
return b1 - b2;
|
||||
}
|
||||
|
||||
unsigned goo (unsigned m_param, unsigned n_param)
|
||||
{
|
||||
unsigned b1 = m_param * (n_param + 2);
|
||||
unsigned b2 = m_param * (n_param + 1);
|
||||
|
||||
use_fn (b1 ^ b2);
|
||||
|
||||
return b1 - b2;
|
||||
}
|
||||
|
||||
unsigned hoo (unsigned k_param)
|
||||
{
|
||||
unsigned b1 = k_param * 28;
|
||||
unsigned b2 = k_param * 15;
|
||||
unsigned b3 = k_param * 12;
|
||||
|
||||
use_fn (b1 ^ b2 ^ b3);
|
||||
|
||||
return (b1 - b2) - b3;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "return 8;" 1 "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "return m_param" 1 "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump-not "return k_param" "forwprop1" } } */
|
Loading…
Add table
Reference in a new issue