Message ID | mptmtmcuqgb.fsf@arm.com |
---|---|
State | Committed |
Headers |
Return-Path: <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4BBC73857811 for <patchwork@sourceware.org>; Wed, 10 Nov 2021 12:50:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4BBC73857811 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1636548643; bh=FvM4ob9PBjVOZ6IHg2aWTTiM2ttRGiY42iE9UXKuVms=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=NZwGbcZGu1PI+QGsxaVKM+4ZCGJMZwPIU5J+qAp6s4GuQD4yoVyp66+kXH0DDHDlW vsSys6SreuyUkw0SujWEoUqpzB3MNmOcDAOEu7v1hnO2nvja2U8nfjRMxymMUM4L4Y XiU6zvdLT1M3Mkb5HZ1yClVe7i9cXLpxIhfHnvkM= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id 1E0B8385781E for <gcc-patches@gcc.gnu.org>; Wed, 10 Nov 2021 12:48:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1E0B8385781E Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id BD75A101E for <gcc-patches@gcc.gnu.org>; Wed, 10 Nov 2021 04:48:21 -0800 (PST) Received: from localhost (unknown [10.32.98.88]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 647513F5A1 for <gcc-patches@gcc.gnu.org>; Wed, 10 Nov 2021 04:48:21 -0800 (PST) To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [PATCH 1/4] Canonicalize argument order for commutative functions Date: Wed, 10 Nov 2021 12:48:20 +0000 Message-ID: <mptmtmcuqgb.fsf@arm.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> From: Richard Sandiford via Gcc-patches <gcc-patches@gcc.gnu.org> Reply-To: Richard Sandiford <richard.sandiford@arm.com> Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> |
Series |
[1/4] Canonicalize argument order for commutative functions
|
|
Commit Message
Richard Sandiford
Nov. 10, 2021, 12:48 p.m. UTC
This patch uses information about internal functions to canonicalize the argument order of calls. Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? Richard gcc/ * gimple-fold.c: Include internal-fn.h. (fold_stmt_1): If a function maps to an internal one, use first_commutative_argument to canonicalize the order of commutative arguments. gcc/testsuite/ * gcc.dg/fmax-fmin-1.c: New test. --- gcc/gimple-fold.c | 25 ++++++++++++++++++++++--- gcc/testsuite/gcc.dg/fmax-fmin-1.c | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/fmax-fmin-1.c
Comments
On Wed, Nov 10, 2021 at 1:50 PM Richard Sandiford via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > This patch uses information about internal functions to canonicalize > the argument order of calls. > > Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? OK. Note the gimple_resimplifyN functions also canonicalize operand order, currently for is_tree_code only: /* Canonicalize operand order. */ bool canonicalized = false; if (res_op->code.is_tree_code () && (TREE_CODE_CLASS ((enum tree_code) res_op->code) == tcc_comparison || commutative_tree_code (res_op->code)) && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) { std::swap (res_op->ops[0], res_op->ops[1]); if (TREE_CODE_CLASS ((enum tree_code) res_op->code) == tcc_comparison) res_op->code = swap_tree_comparison (res_op->code); canonicalized = true; } that's maybe not the best place. The function assumes the operands are already valueized, so it maybe should be valueization that does the canonicalization - but I think doing it elsewhere made operand order unreliable (we do end up with non-canonical order in the IL sometimes). So maybe you should amend the code in resimplifyN as well. Richard. > Richard > > > gcc/ > * gimple-fold.c: Include internal-fn.h. > (fold_stmt_1): If a function maps to an internal one, use > first_commutative_argument to canonicalize the order of > commutative arguments. > > gcc/testsuite/ > * gcc.dg/fmax-fmin-1.c: New test. > --- > gcc/gimple-fold.c | 25 ++++++++++++++++++++++--- > gcc/testsuite/gcc.dg/fmax-fmin-1.c | 18 ++++++++++++++++++ > 2 files changed, 40 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/fmax-fmin-1.c > > diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c > index a937f130815..6a7d4507c89 100644 > --- a/gcc/gimple-fold.c > +++ b/gcc/gimple-fold.c > @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see > #include "varasm.h" > #include "memmodel.h" > #include "optabs.h" > +#include "internal-fn.h" > > enum strlen_range_kind { > /* Compute the exact constant string length. */ > @@ -6140,18 +6141,36 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) > break; > case GIMPLE_CALL: > { > - for (i = 0; i < gimple_call_num_args (stmt); ++i) > + gcall *call = as_a<gcall *> (stmt); > + for (i = 0; i < gimple_call_num_args (call); ++i) > { > - tree *arg = gimple_call_arg_ptr (stmt, i); > + tree *arg = gimple_call_arg_ptr (call, i); > if (REFERENCE_CLASS_P (*arg) > && maybe_canonicalize_mem_ref_addr (arg)) > changed = true; > } > - tree *lhs = gimple_call_lhs_ptr (stmt); > + tree *lhs = gimple_call_lhs_ptr (call); > if (*lhs > && REFERENCE_CLASS_P (*lhs) > && maybe_canonicalize_mem_ref_addr (lhs)) > changed = true; > + if (*lhs) > + { > + combined_fn cfn = gimple_call_combined_fn (call); > + internal_fn ifn = associated_internal_fn (cfn, TREE_TYPE (*lhs)); > + int opno = first_commutative_argument (ifn); > + if (opno >= 0) > + { > + tree arg1 = gimple_call_arg (call, opno); > + tree arg2 = gimple_call_arg (call, opno + 1); > + if (tree_swap_operands_p (arg1, arg2)) > + { > + gimple_call_set_arg (call, opno, arg2); > + gimple_call_set_arg (call, opno + 1, arg1); > + changed = true; > + } > + } > + } > break; > } > case GIMPLE_ASM: > diff --git a/gcc/testsuite/gcc.dg/fmax-fmin-1.c b/gcc/testsuite/gcc.dg/fmax-fmin-1.c > new file mode 100644 > index 00000000000..e7e0518d8bb > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/fmax-fmin-1.c > @@ -0,0 +1,18 @@ > +/* { dg-options "-O -fdump-tree-optimized" } */ > + > +void > +f1 (double *res, double x, double y) > +{ > + res[0] = __builtin_fmax (x, y); > + res[1] = __builtin_fmax (y, x); > +} > + > +void > +f2 (double *res, double x, double y) > +{ > + res[0] = __builtin_fmin (x, y); > + res[1] = __builtin_fmin (y, x); > +} > + > +/* { dg-final { scan-tree-dump-times {__builtin_fmax} 1 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times {__builtin_fmin} 1 "optimized" } } */ > -- > 2.25.1 >
Sorry for the slow response, was away last week. Richard Biener <richard.guenther@gmail.com> writes: > On Wed, Nov 10, 2021 at 1:50 PM Richard Sandiford via Gcc-patches > <gcc-patches@gcc.gnu.org> wrote: >> >> This patch uses information about internal functions to canonicalize >> the argument order of calls. >> >> Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? > > OK. Note the gimple_resimplifyN functions also canonicalize operand > order, currently for is_tree_code only: > > /* Canonicalize operand order. */ > bool canonicalized = false; > if (res_op->code.is_tree_code () > && (TREE_CODE_CLASS ((enum tree_code) res_op->code) == tcc_comparison > || commutative_tree_code (res_op->code)) > && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) > { > std::swap (res_op->ops[0], res_op->ops[1]); > if (TREE_CODE_CLASS ((enum tree_code) res_op->code) == tcc_comparison) > res_op->code = swap_tree_comparison (res_op->code); > canonicalized = true; > } > > that's maybe not the best place. The function assumes the operands > are already valueized, > so it maybe should be valueization that does the canonicalization - > but I think doing it > elsewhere made operand order unreliable (we do end up with > non-canonical order in > the IL sometimes). > > So maybe you should amend the code in resimplifyN as well. Hmm, yeah, thanks for the heads up. Does this updated version look OK? Tested as before. Thanks, Richard gcc/ * gimple-fold.c: Include internal-fn.h. (fold_stmt_1): If a function maps to an internal one, use first_commutative_argument to canonicalize the order of commutative arguments. * gimple-match-head.c (gimple_resimplify2, gimple_resimplify3) (gimple_resimplify4, gimple_resimplify5): Extend commutativity checks to functions. gcc/testsuite/ * gcc.dg/fmax-fmin-1.c: New test. --- gcc/gimple-fold.c | 25 ++++++++++++-- gcc/gimple-match-head.c | 52 ++++++++++++++++++++---------- gcc/testsuite/gcc.dg/fmax-fmin-1.c | 18 +++++++++++ 3 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/fmax-fmin-1.c diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 44fba12e150..1d8fd74f72c 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see #include "varasm.h" #include "memmodel.h" #include "optabs.h" +#include "internal-fn.h" enum strlen_range_kind { /* Compute the exact constant string length. */ @@ -6109,18 +6110,36 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) break; case GIMPLE_CALL: { - for (i = 0; i < gimple_call_num_args (stmt); ++i) + gcall *call = as_a<gcall *> (stmt); + for (i = 0; i < gimple_call_num_args (call); ++i) { - tree *arg = gimple_call_arg_ptr (stmt, i); + tree *arg = gimple_call_arg_ptr (call, i); if (REFERENCE_CLASS_P (*arg) && maybe_canonicalize_mem_ref_addr (arg)) changed = true; } - tree *lhs = gimple_call_lhs_ptr (stmt); + tree *lhs = gimple_call_lhs_ptr (call); if (*lhs && REFERENCE_CLASS_P (*lhs) && maybe_canonicalize_mem_ref_addr (lhs)) changed = true; + if (*lhs) + { + combined_fn cfn = gimple_call_combined_fn (call); + internal_fn ifn = associated_internal_fn (cfn, TREE_TYPE (*lhs)); + int opno = first_commutative_argument (ifn); + if (opno >= 0) + { + tree arg1 = gimple_call_arg (call, opno); + tree arg2 = gimple_call_arg (call, opno + 1); + if (tree_swap_operands_p (arg1, arg2)) + { + gimple_call_set_arg (call, opno, arg2); + gimple_call_set_arg (call, opno + 1, arg1); + changed = true; + } + } + } break; } case GIMPLE_ASM: diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c index c481a625581..2d9364ca5de 100644 --- a/gcc/gimple-match-head.c +++ b/gcc/gimple-match-head.c @@ -294,18 +294,16 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op, /* Canonicalize operand order. */ bool canonicalized = false; - if (res_op->code.is_tree_code ()) + bool is_comparison + = (res_op->code.is_tree_code () + && TREE_CODE_CLASS (tree_code (res_op->code)) == tcc_comparison); + if ((is_comparison || commutative_binary_op_p (res_op->code, res_op->type)) + && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) { - auto code = tree_code (res_op->code); - if ((TREE_CODE_CLASS (code) == tcc_comparison - || commutative_tree_code (code)) - && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) - { - std::swap (res_op->ops[0], res_op->ops[1]); - if (TREE_CODE_CLASS (code) == tcc_comparison) - res_op->code = swap_tree_comparison (code); - canonicalized = true; - } + std::swap (res_op->ops[0], res_op->ops[1]); + if (is_comparison) + res_op->code = swap_tree_comparison (tree_code (res_op->code)); + canonicalized = true; } /* Limit recursion, see gimple_resimplify1. */ @@ -376,11 +374,11 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op, /* Canonicalize operand order. */ bool canonicalized = false; - if (res_op->code.is_tree_code () - && commutative_ternary_tree_code (tree_code (res_op->code)) - && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) + int argno = first_commutative_argument (res_op->code, res_op->type); + if (argno >= 0 + && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) { - std::swap (res_op->ops[0], res_op->ops[1]); + std::swap (res_op->ops[argno], res_op->ops[argno + 1]); canonicalized = true; } @@ -424,6 +422,16 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op, { /* No constant folding is defined for four-operand functions. */ + /* Canonicalize operand order. */ + bool canonicalized = false; + int argno = first_commutative_argument (res_op->code, res_op->type); + if (argno >= 0 + && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) + { + std::swap (res_op->ops[argno], res_op->ops[argno + 1]); + canonicalized = true; + } + /* Limit recursion, see gimple_resimplify1. */ static unsigned depth; if (depth > 10) @@ -450,7 +458,7 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op, if (maybe_resimplify_conditional_op (seq, res_op, valueize)) return true; - return false; + return canonicalized; } /* Helper that matches and simplifies the toplevel result from @@ -465,6 +473,16 @@ gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op, { /* No constant folding is defined for five-operand functions. */ + /* Canonicalize operand order. */ + bool canonicalized = false; + int argno = first_commutative_argument (res_op->code, res_op->type); + if (argno >= 0 + && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) + { + std::swap (res_op->ops[argno], res_op->ops[argno + 1]); + canonicalized = true; + } + gimple_match_op res_op2 (*res_op); if (gimple_simplify (&res_op2, seq, valueize, res_op->code, res_op->type, @@ -478,7 +496,7 @@ gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op, if (maybe_resimplify_conditional_op (seq, res_op, valueize)) return true; - return false; + return canonicalized; } /* Match and simplify the toplevel valueized operation THIS. diff --git a/gcc/testsuite/gcc.dg/fmax-fmin-1.c b/gcc/testsuite/gcc.dg/fmax-fmin-1.c new file mode 100644 index 00000000000..e7e0518d8bb --- /dev/null +++ b/gcc/testsuite/gcc.dg/fmax-fmin-1.c @@ -0,0 +1,18 @@ +/* { dg-options "-O -fdump-tree-optimized" } */ + +void +f1 (double *res, double x, double y) +{ + res[0] = __builtin_fmax (x, y); + res[1] = __builtin_fmax (y, x); +} + +void +f2 (double *res, double x, double y) +{ + res[0] = __builtin_fmin (x, y); + res[1] = __builtin_fmin (y, x); +} + +/* { dg-final { scan-tree-dump-times {__builtin_fmax} 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times {__builtin_fmin} 1 "optimized" } } */
On Mon, Nov 29, 2021 at 4:40 PM Richard Sandiford <richard.sandiford@arm.com> wrote: > > Sorry for the slow response, was away last week. > > Richard Biener <richard.guenther@gmail.com> writes: > > On Wed, Nov 10, 2021 at 1:50 PM Richard Sandiford via Gcc-patches > > <gcc-patches@gcc.gnu.org> wrote: > >> > >> This patch uses information about internal functions to canonicalize > >> the argument order of calls. > >> > >> Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? > > > > OK. Note the gimple_resimplifyN functions also canonicalize operand > > order, currently for is_tree_code only: > > > > /* Canonicalize operand order. */ > > bool canonicalized = false; > > if (res_op->code.is_tree_code () > > && (TREE_CODE_CLASS ((enum tree_code) res_op->code) == tcc_comparison > > || commutative_tree_code (res_op->code)) > > && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) > > { > > std::swap (res_op->ops[0], res_op->ops[1]); > > if (TREE_CODE_CLASS ((enum tree_code) res_op->code) == tcc_comparison) > > res_op->code = swap_tree_comparison (res_op->code); > > canonicalized = true; > > } > > > > that's maybe not the best place. The function assumes the operands > > are already valueized, > > so it maybe should be valueization that does the canonicalization - > > but I think doing it > > elsewhere made operand order unreliable (we do end up with > > non-canonical order in > > the IL sometimes). > > > > So maybe you should amend the code in resimplifyN as well. > > Hmm, yeah, thanks for the heads up. Does this updated version look OK? > Tested as before. Yes - OK. Thanks, Richard. > Thanks, > Richard > > > gcc/ > * gimple-fold.c: Include internal-fn.h. > (fold_stmt_1): If a function maps to an internal one, use > first_commutative_argument to canonicalize the order of > commutative arguments. > * gimple-match-head.c (gimple_resimplify2, gimple_resimplify3) > (gimple_resimplify4, gimple_resimplify5): Extend commutativity > checks to functions. > > gcc/testsuite/ > * gcc.dg/fmax-fmin-1.c: New test. > --- > gcc/gimple-fold.c | 25 ++++++++++++-- > gcc/gimple-match-head.c | 52 ++++++++++++++++++++---------- > gcc/testsuite/gcc.dg/fmax-fmin-1.c | 18 +++++++++++ > 3 files changed, 75 insertions(+), 20 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/fmax-fmin-1.c > > diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c > index 44fba12e150..1d8fd74f72c 100644 > --- a/gcc/gimple-fold.c > +++ b/gcc/gimple-fold.c > @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see > #include "varasm.h" > #include "memmodel.h" > #include "optabs.h" > +#include "internal-fn.h" > > enum strlen_range_kind { > /* Compute the exact constant string length. */ > @@ -6109,18 +6110,36 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) > break; > case GIMPLE_CALL: > { > - for (i = 0; i < gimple_call_num_args (stmt); ++i) > + gcall *call = as_a<gcall *> (stmt); > + for (i = 0; i < gimple_call_num_args (call); ++i) > { > - tree *arg = gimple_call_arg_ptr (stmt, i); > + tree *arg = gimple_call_arg_ptr (call, i); > if (REFERENCE_CLASS_P (*arg) > && maybe_canonicalize_mem_ref_addr (arg)) > changed = true; > } > - tree *lhs = gimple_call_lhs_ptr (stmt); > + tree *lhs = gimple_call_lhs_ptr (call); > if (*lhs > && REFERENCE_CLASS_P (*lhs) > && maybe_canonicalize_mem_ref_addr (lhs)) > changed = true; > + if (*lhs) > + { > + combined_fn cfn = gimple_call_combined_fn (call); > + internal_fn ifn = associated_internal_fn (cfn, TREE_TYPE (*lhs)); > + int opno = first_commutative_argument (ifn); > + if (opno >= 0) > + { > + tree arg1 = gimple_call_arg (call, opno); > + tree arg2 = gimple_call_arg (call, opno + 1); > + if (tree_swap_operands_p (arg1, arg2)) > + { > + gimple_call_set_arg (call, opno, arg2); > + gimple_call_set_arg (call, opno + 1, arg1); > + changed = true; > + } > + } > + } > break; > } > case GIMPLE_ASM: > diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c > index c481a625581..2d9364ca5de 100644 > --- a/gcc/gimple-match-head.c > +++ b/gcc/gimple-match-head.c > @@ -294,18 +294,16 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op, > > /* Canonicalize operand order. */ > bool canonicalized = false; > - if (res_op->code.is_tree_code ()) > + bool is_comparison > + = (res_op->code.is_tree_code () > + && TREE_CODE_CLASS (tree_code (res_op->code)) == tcc_comparison); > + if ((is_comparison || commutative_binary_op_p (res_op->code, res_op->type)) > + && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) > { > - auto code = tree_code (res_op->code); > - if ((TREE_CODE_CLASS (code) == tcc_comparison > - || commutative_tree_code (code)) > - && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) > - { > - std::swap (res_op->ops[0], res_op->ops[1]); > - if (TREE_CODE_CLASS (code) == tcc_comparison) > - res_op->code = swap_tree_comparison (code); > - canonicalized = true; > - } > + std::swap (res_op->ops[0], res_op->ops[1]); > + if (is_comparison) > + res_op->code = swap_tree_comparison (tree_code (res_op->code)); > + canonicalized = true; > } > > /* Limit recursion, see gimple_resimplify1. */ > @@ -376,11 +374,11 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op, > > /* Canonicalize operand order. */ > bool canonicalized = false; > - if (res_op->code.is_tree_code () > - && commutative_ternary_tree_code (tree_code (res_op->code)) > - && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) > + int argno = first_commutative_argument (res_op->code, res_op->type); > + if (argno >= 0 > + && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) > { > - std::swap (res_op->ops[0], res_op->ops[1]); > + std::swap (res_op->ops[argno], res_op->ops[argno + 1]); > canonicalized = true; > } > > @@ -424,6 +422,16 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op, > { > /* No constant folding is defined for four-operand functions. */ > > + /* Canonicalize operand order. */ > + bool canonicalized = false; > + int argno = first_commutative_argument (res_op->code, res_op->type); > + if (argno >= 0 > + && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) > + { > + std::swap (res_op->ops[argno], res_op->ops[argno + 1]); > + canonicalized = true; > + } > + > /* Limit recursion, see gimple_resimplify1. */ > static unsigned depth; > if (depth > 10) > @@ -450,7 +458,7 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op, > if (maybe_resimplify_conditional_op (seq, res_op, valueize)) > return true; > > - return false; > + return canonicalized; > } > > /* Helper that matches and simplifies the toplevel result from > @@ -465,6 +473,16 @@ gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op, > { > /* No constant folding is defined for five-operand functions. */ > > + /* Canonicalize operand order. */ > + bool canonicalized = false; > + int argno = first_commutative_argument (res_op->code, res_op->type); > + if (argno >= 0 > + && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) > + { > + std::swap (res_op->ops[argno], res_op->ops[argno + 1]); > + canonicalized = true; > + } > + > gimple_match_op res_op2 (*res_op); > if (gimple_simplify (&res_op2, seq, valueize, > res_op->code, res_op->type, > @@ -478,7 +496,7 @@ gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op, > if (maybe_resimplify_conditional_op (seq, res_op, valueize)) > return true; > > - return false; > + return canonicalized; > } > > /* Match and simplify the toplevel valueized operation THIS. > diff --git a/gcc/testsuite/gcc.dg/fmax-fmin-1.c b/gcc/testsuite/gcc.dg/fmax-fmin-1.c > new file mode 100644 > index 00000000000..e7e0518d8bb > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/fmax-fmin-1.c > @@ -0,0 +1,18 @@ > +/* { dg-options "-O -fdump-tree-optimized" } */ > + > +void > +f1 (double *res, double x, double y) > +{ > + res[0] = __builtin_fmax (x, y); > + res[1] = __builtin_fmax (y, x); > +} > + > +void > +f2 (double *res, double x, double y) > +{ > + res[0] = __builtin_fmin (x, y); > + res[1] = __builtin_fmin (y, x); > +} > + > +/* { dg-final { scan-tree-dump-times {__builtin_fmax} 1 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times {__builtin_fmin} 1 "optimized" } } */ > -- > 2.25.1 >
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index a937f130815..6a7d4507c89 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see #include "varasm.h" #include "memmodel.h" #include "optabs.h" +#include "internal-fn.h" enum strlen_range_kind { /* Compute the exact constant string length. */ @@ -6140,18 +6141,36 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) break; case GIMPLE_CALL: { - for (i = 0; i < gimple_call_num_args (stmt); ++i) + gcall *call = as_a<gcall *> (stmt); + for (i = 0; i < gimple_call_num_args (call); ++i) { - tree *arg = gimple_call_arg_ptr (stmt, i); + tree *arg = gimple_call_arg_ptr (call, i); if (REFERENCE_CLASS_P (*arg) && maybe_canonicalize_mem_ref_addr (arg)) changed = true; } - tree *lhs = gimple_call_lhs_ptr (stmt); + tree *lhs = gimple_call_lhs_ptr (call); if (*lhs && REFERENCE_CLASS_P (*lhs) && maybe_canonicalize_mem_ref_addr (lhs)) changed = true; + if (*lhs) + { + combined_fn cfn = gimple_call_combined_fn (call); + internal_fn ifn = associated_internal_fn (cfn, TREE_TYPE (*lhs)); + int opno = first_commutative_argument (ifn); + if (opno >= 0) + { + tree arg1 = gimple_call_arg (call, opno); + tree arg2 = gimple_call_arg (call, opno + 1); + if (tree_swap_operands_p (arg1, arg2)) + { + gimple_call_set_arg (call, opno, arg2); + gimple_call_set_arg (call, opno + 1, arg1); + changed = true; + } + } + } break; } case GIMPLE_ASM: diff --git a/gcc/testsuite/gcc.dg/fmax-fmin-1.c b/gcc/testsuite/gcc.dg/fmax-fmin-1.c new file mode 100644 index 00000000000..e7e0518d8bb --- /dev/null +++ b/gcc/testsuite/gcc.dg/fmax-fmin-1.c @@ -0,0 +1,18 @@ +/* { dg-options "-O -fdump-tree-optimized" } */ + +void +f1 (double *res, double x, double y) +{ + res[0] = __builtin_fmax (x, y); + res[1] = __builtin_fmax (y, x); +} + +void +f2 (double *res, double x, double y) +{ + res[0] = __builtin_fmin (x, y); + res[1] = __builtin_fmin (y, x); +} + +/* { dg-final { scan-tree-dump-times {__builtin_fmax} 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times {__builtin_fmin} 1 "optimized" } } */