From patchwork Sun Aug 27 22:57:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Pinski X-Patchwork-Id: 136989 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a7d1:0:b0:3f2:4152:657d with SMTP id p17csp3014429vqm; Sun, 27 Aug 2023 15:58:55 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHkfu07Fi3BpOKu5falL4Yj+Ctidhn9BKmRaNgwBtdVjEu/L82qDbsmTLvWx7X2jGX7yYak X-Received: by 2002:a05:6512:6d5:b0:500:b9e3:91bd with SMTP id u21-20020a05651206d500b00500b9e391bdmr908524lff.41.1693177135653; Sun, 27 Aug 2023 15:58:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693177135; cv=none; d=google.com; s=arc-20160816; b=rkjnX5v103vueE+OairTNMSLz9JSDnGhmiX0b8fvDcHFOpyEUj+pMzPX4wVAZ2dDi0 hvqNoqSXncHsR+x/8Q6LdaNzRyWY7iXZx/ej/cg5bG7/r8ib3ic16pmNTwTJXFpdy7ak Qhhn2LtH2GR8fZL/0wwa3QdZ8AM/Ie7t9FAObYmKYj1VLD+3GSh9rfGIhfDhYMfok9tv XoFgT7jf1cQAVQLmMunIpXXopFW1GSqZ6LyShZn09PL/ClYimZJsuN7Iyd/u3yKpIL6N 6MG2gXqwskzwuq1l7fw0Hbhem+WqaPwa9Rr0L1L2YfPw/br7+2FDExtcL+1jcAIhcZRw 1UDA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:message-id:date:subject:cc :to:dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=bYUYu+Rll+JbWOHAbPfXVEjRoLZH0KV/Vd5+tgW7vBU=; fh=XbcmRug6/SzczusyoNU1I7Lu5oY0AN2u0mWDzKoxdSs=; b=PfQ0btqvJ6pN/pXtM1c54mURL9kqGz3kp4ExsBHUAyGr0LtbXyaGIeaNIqLmSDlL7H Pm5T84FM8OIQnc7X0/telfUdSqWGJVtAjZj/cD+RSnuEPMHu7rv6ijRneFqeaz3UrUxP UoTA2mq3gOHPv24vVp2YZZfdfxJO79RE3WFvFN/S8r2WnKA8fSXYozMrlTKrcNeJT+NU MaUGABvA3T9pIIazON/P9/UcktbBTjAy4uzEQlRgEp8vKGI6OLTLLR0wiZggyrPCcvCU eLC0rWOQAF6Ne13Zh77I3gErNQXBtePL7+1WqGuTy4lpW4qw3W4YCU5BfzV519bcOJW6 vVTA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b="vjVPDsu/"; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id g14-20020aa7d1ce000000b0052a09569b71si3728500edp.174.2023.08.27.15.58.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Aug 2023 15:58:55 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b="vjVPDsu/"; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8A8173858C53 for ; Sun, 27 Aug 2023 22:58:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8A8173858C53 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1693177134; bh=bYUYu+Rll+JbWOHAbPfXVEjRoLZH0KV/Vd5+tgW7vBU=; h=To:CC:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=vjVPDsu/U6KvHE/4AgZdVeqX87y8yexJ9IfQpvzqoVWD8MGwrw+L8Z2sKvb5U+Osc 6/Y7pZkbxKfaCJE6zM8NwSJcBgYIUNZE7nWo/+5TzWrjFN0oPJYdt0HR1sPo6C/6IY S6van/1BrPXivpLZcbcp8BsvbCW14hq3lBK0ME0c= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by sourceware.org (Postfix) with ESMTPS id 75B0F3858D28 for ; Sun, 27 Aug 2023 22:58:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 75B0F3858D28 Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 37RLV863003987 for ; Sun, 27 Aug 2023 15:58:06 -0700 Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3sqgwkaxbt-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Sun, 27 Aug 2023 15:58:06 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Sun, 27 Aug 2023 15:58:04 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Sun, 27 Aug 2023 15:58:04 -0700 Received: from vpnclient.wrightpinski.org.com (unknown [10.69.242.187]) by maili.marvell.com (Postfix) with ESMTP id 0C7FD3F7061; Sun, 27 Aug 2023 15:58:03 -0700 (PDT) To: CC: Andrew Pinski Subject: [PATCH] IFCOMBINE: Remove outer condition for two same conditionals Date: Sun, 27 Aug 2023 15:57:54 -0700 Message-ID: <20230827225754.3733610-1-apinski@marvell.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 X-Proofpoint-GUID: KK-bRiAjKmJ1SGiXi7N2EbPwj2XhXcPR X-Proofpoint-ORIG-GUID: KK-bRiAjKmJ1SGiXi7N2EbPwj2XhXcPR X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.601,FMLib:17.11.176.26 definitions=2023-08-27_21,2023-08-25_01,2023-05-22_02 X-Spam-Status: No, score=-14.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Pinski via Gcc-patches From: Andrew Pinski Reply-To: Andrew Pinski Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1775424908630961456 X-GMAIL-MSGID: 1775424908630961456 This adds a simple case to remove an outer condition if the two inner condtionals are the same and lead the same location. This can show up due to jump threading or inlining or someone wrote code like this. ifcombine-1.c shows the simple case where this is supposed to solve. Even though PRE can handle some cases, ifcombine is earlier and even runs at -O1. Note in the case of the PR here, it comes from jump threading. OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions. gcc/ChangeLog: PR tree-optimization/110891 * tree-ssa-ifcombine.cc (ifcombine_bb_same): New function. (tree_ssa_ifcombine_bb): Call ifcombine_bb_same. gcc/testsuite/ChangeLog: PR tree-optimization/110891 * gcc.dg/tree-ssa/ifcombine-1.c: New test. * gcc.dg/tree-ssa/pr110891-1.c: New test. --- gcc/testsuite/gcc.dg/tree-ssa/ifcombine-1.c | 27 ++++++ gcc/testsuite/gcc.dg/tree-ssa/pr110891-1.c | 53 +++++++++++ gcc/tree-ssa-ifcombine.cc | 100 ++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ifcombine-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr110891-1.c diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifcombine-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ifcombine-1.c new file mode 100644 index 00000000000..02d08efef87 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifcombine-1.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized -fdump-tree-ifcombine" } */ + +int g(); +int h(); + +int j, l; + +int f(int a, int *b) +{ + if (a == 0) + { + if (b == &j) goto L9; else goto L7; + } + else + { + if (b == &j) goto L9; else goto L7; + } +L7: return g(); +L9: return h(); +} + +/* ifcombine can optimize away the outer most if here. */ +/* { dg-final { scan-tree-dump-times "optimized away the test from bb " 1 "ifcombine" } } */ +/* We should have remove the outer if and one of the inner ifs; leaving us with one if. */ +/* { dg-final { scan-tree-dump-times "if " 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "goto " 3 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110891-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr110891-1.c new file mode 100644 index 00000000000..320d8823077 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr110891-1.c @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void foo(void); +static int a, c = 7, d, o, q; +static int *b = &a, *f, *j = &d, *n = &c, *ae; +static short e, m; +static short *i = &e; +static char r; +void __assert_fail(char *, char *, int, const char *) __attribute__((__noreturn__)); +static const short g(); +static void h(); +static int *k(int) { + (*i)++; + *j ^= *b; + return &a; +} +static void l(unsigned p) { + int *aa = &o; + h(); + o = 5 ^ g() && p; + if (f == &d || f == &c || f == &a) + ; + else { + foo(); + __assert_fail("", "", 3, __PRETTY_FUNCTION__); + } + *aa ^= *n; + if (*aa) + if (!(((p) >= 0) && ((p) <= 0))) { + __builtin_unreachable(); + } + k(p); +} +static const short g() { return q; } +static void h() { + unsigned ag = c; + d = ag > r ? ag : 0; + ae = k(c); + f = ae; + if (ae == &d || ae == &c || ae == &a) + ; + else + __assert_fail("", "", 4, __PRETTY_FUNCTION__); +} +int main() { + l(a); + m || (*b |= 64); + *b &= 5; +} + +/* We should be able to optimize away foo. */ +/* { dg-final { scan-tree-dump-not "foo " "optimized" } } */ diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc index 46b076804f4..f79545b9a0b 100644 --- a/gcc/tree-ssa-ifcombine.cc +++ b/gcc/tree-ssa-ifcombine.cc @@ -666,6 +666,103 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, return false; } +/* Function to remove an outer condition if two inner basic blocks have the same condition and both empty otherwise. */ + +static bool +ifcombine_bb_same (basic_block cond_bb, basic_block outer_cond_bb, + basic_block then_bb, basic_block else_bb) +{ + basic_block inner_cond_bbt = nullptr, inner_cond_bbf = nullptr; + + /* See if the the outer condition is a condition. */ + if (!recognize_if_then_else (outer_cond_bb, &inner_cond_bbt, &inner_cond_bbf)) + return false; + basic_block other_cond_bb; + if (cond_bb == inner_cond_bbt) + other_cond_bb = inner_cond_bbf; + else + other_cond_bb = inner_cond_bbt; + + /* The other bb has to have a single predecessor too. */ + if (!single_pred_p (other_cond_bb)) + return false; + + /* Other inner conditional bb needs to go to the same then and else blocks. */ + if (!recognize_if_then_else (other_cond_bb, &then_bb, &else_bb)) + return false; + + /* Both edges of both inner basic blocks need to have the same values for the incoming phi for both then and else basic blocks. */ + if (!same_phi_args_p (cond_bb, other_cond_bb, else_bb)) + return false; + + if (!same_phi_args_p (cond_bb, other_cond_bb, then_bb)) + return false; + + /* Both inner bbs need to be empty (besides the condition). */ + if (!gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb (cond_bb))) + return false; + if (!gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb (other_cond_bb))) + return false; + + /* All 3 basic blocks need to have a GIMPLE_COND as the last statement. */ + gcond *cond = safe_dyn_cast (*gsi_last_bb (cond_bb)); + if (!cond) + return false; + + gcond *other_cond = safe_dyn_cast (*gsi_last_bb (other_cond_bb)); + if (!other_cond) + return false; + + gcond *outer_cond = safe_dyn_cast (*gsi_last_bb (outer_cond_bb)); + if (!outer_cond) + return false; + + /* If already done the transformation, don't need to do it again. */ + if (gimple_cond_true_p (outer_cond)) + return false; + if (gimple_cond_false_p (outer_cond)) + return false; + + /* Both inner bb have to have the same condition. */ + if (gimple_cond_code (cond) != gimple_cond_code (other_cond) + || !operand_equal_p (gimple_cond_lhs (cond), gimple_cond_lhs (other_cond)) + || !operand_equal_p (gimple_cond_rhs (cond), gimple_cond_rhs (other_cond))) + return false; + + /* Both inner bbs need not to have phi nodes. */ + if (!gimple_seq_empty_p (phi_nodes (cond_bb))) + return false; + + if (!gimple_seq_empty_p (phi_nodes (other_cond_bb))) + return false; + + if (dump_file) + { + fprintf (dump_file, "optimized away the test from bb #%d.\n", outer_cond_bb->index); + } + + /* It does not matter which basic block we use here as both + are the same. Remove the one which we are processing now as + the other one will be processed afterwards and maybe merged in. */ + bool remove_true_cond = inner_cond_bbt == cond_bb; + + /* Remove the bb which is not reachable any more + so the other one could be merged. */ + edge remove_edge = find_edge (outer_cond_bb, remove_true_cond ? inner_cond_bbt : inner_cond_bbf); + edge keep_edge = find_edge (outer_cond_bb, remove_true_cond ? inner_cond_bbf : inner_cond_bbt); + keep_edge->flags |= EDGE_FALLTHRU; + keep_edge->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); + keep_edge->probability = profile_probability::always (); + delete_basic_block (remove_edge->dest); + + /* Eliminate the COND_EXPR at the end of COND_BLOCK. */ + gimple_stmt_iterator gsi = gsi_last_bb (outer_cond_bb); + gsi_remove (&gsi, true); + /* Now merge the outer conditional block with the (old exectued) inner one. */ + merge_blocks (outer_cond_bb, remove_true_cond ? inner_cond_bbf : inner_cond_bbt); + return true; +} + /* Helper function for tree_ssa_ifcombine_bb. Recognize a CFG pattern and dispatch to the appropriate if-conversion helper for a particular set of INNER_COND_BB, OUTER_COND_BB, THEN_BB and ELSE_BB. @@ -780,6 +877,9 @@ tree_ssa_ifcombine_bb (basic_block inner_cond_bb) { basic_block outer_cond_bb = single_pred (inner_cond_bb); + if (ifcombine_bb_same (inner_cond_bb, outer_cond_bb, then_bb, else_bb)) + return true; + if (tree_ssa_ifcombine_bb_1 (inner_cond_bb, outer_cond_bb, then_bb, else_bb, inner_cond_bb)) return true;