From f9d2def016410a2095df6b399097b482f82064a5 Mon Sep 17 00:00:00 2001 From: Feng Xue Date: Tue, 1 Sep 2020 17:17:58 +0800 Subject: [PATCH] tree-optimization/94234 - Fold plusminus_mult expr with multi-use operands 2020-09-03 Feng Xue 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. --- gcc/genmatch.c | 10 ++++++-- gcc/match.pd | 22 ++++++++++-------- gcc/testsuite/gcc.dg/pr94234-2.c | 39 ++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr94234-2.c diff --git a/gcc/genmatch.c b/gcc/genmatch.c index 906d842c4d8..01363e3f09c 100644 --- a/gcc/genmatch.c +++ b/gcc/genmatch.c @@ -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) diff --git a/gcc/match.pd b/gcc/match.pd index 6e45836e32b..46fd880bd37 100644 --- a/gcc/match.pd +++ b/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 diff --git a/gcc/testsuite/gcc.dg/pr94234-2.c b/gcc/testsuite/gcc.dg/pr94234-2.c new file mode 100644 index 00000000000..1f4b194dd43 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94234-2.c @@ -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" } } */ -- 2.30.2