From patchwork Fri Apr 1 09:26:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 1612115 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=gMYvjhY9; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KVFFX2Z6Lz9sV6 for ; Fri, 1 Apr 2022 20:27:42 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DB1FF3945C1F for ; Fri, 1 Apr 2022 09:27:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DB1FF3945C1F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1648805259; bh=Wkt1CRxUwREyLKdtv+BqoC/n+wwt0QUJg5ZnW+H/B2M=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=gMYvjhY94IqnWa+x5kZToB5xfgtL0Vn9b+JdIMSJY6+7meyPRLDn8f58tbv7v+tqg sH/mqNjcNVWXNPQnROfWSkOjDWjLWtjr5NsEZMuyf/wgLvhqh4YnNe6LkiKaQPLU5w 3I6QUTtEkinP1o/A1kgD2ECaihjovae8YJi+59Rw= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 91FBE3857811 for ; Fri, 1 Apr 2022 09:26:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 91FBE3857811 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-601-YqrMciKBObuH5bfgzkX5Lg-1; Fri, 01 Apr 2022 05:26:55 -0400 X-MC-Unique: YqrMciKBObuH5bfgzkX5Lg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id A530F28EC122; Fri, 1 Apr 2022 09:26:54 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.194.220]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6058A1400B1C; Fri, 1 Apr 2022 09:26:54 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 2319QpCR003159 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 1 Apr 2022 11:26:51 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 2319Qoic003158; Fri, 1 Apr 2022 11:26:50 +0200 Date: Fri, 1 Apr 2022 11:26:50 +0200 To: Richard Biener Subject: [PATCH] phiopt: Improve value_replacement [PR104645] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.85 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: gcc-patches@gcc.gnu.org Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Hi! The following patch fixes the P1 regression by reusing existing value_replacement code. That function already has code to handle simple preparation statements (casts, and +,&,|,^ binary assignments) before a final binary assignment (which can be much wider range of ops). When we have e.g. if (y_3(D) == 0) goto ; else goto ; : y_4 = y_3(D) & 31; _1 = (int) y_4; _6 = x_5(D) r<< _1; : # _2 = PHI the preparation statements y_4 = y_3(D) & 31; and _1 = (int) y_4; are handled by constant evaluation, passing through y_3(D) = 0 initially and propagating that through the assignments with checking that UB isn't invoked. But the final _6 = x_5(D) r<< _1; assign is handled differently, either through neutral_element_p or absorbing_element_p. In the first function below we now have: [local count: 1073741824]: if (i_2(D) != 0) goto ; [50.00%] else goto ; [50.00%] [local count: 536870913]: _3 = i_2(D) & 1; iftmp.0_4 = (int) _3; [local count: 1073741824]: # iftmp.0_1 = PHI where in GCC 11 we had: : if (i_3(D) != 0) goto ; [INV] else goto ; [INV] : i.1_1 = (int) i_3(D); iftmp.0_5 = i.1_1 & 1; : # iftmp.0_2 = PHI Current value_replacement can handle the latter as the last stmt of middle_bb is a binary op that in this case satisfies absorbing_element_p. But the former we can't handle, as the last stmt in middle_bb is a cast. The patch makes it work in that case by pretending all of middle_bb are the preparation statements and there is no binary assign at the end, so everything is handled through the constant evaluation. We simply set at the start of middle_bb the lhs of comparison virtually to the rhs, propagate it through and at the end see if virtually the arg0 of the PHI is equal to arg1 of it. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? For GCC 13, I think we just should throw away all the neutral/absorbing element stuff and do the constant evaluation of the whole middle_bb and handle that way all the ops we currently handle in neutral/absorbing element. 2022-04-01 Jakub Jelinek PR tree-optimization/104645 * tree-ssa-phiopt.cc (value_replacement): If assign has CONVERT_EXPR_CODE_P rhs_code, treat it like a preparation statement with constant evaluation. * gcc.dg/tree-ssa/pr104645.c: New test. Jakub --- gcc/tree-ssa-phiopt.cc.jj 2022-01-18 11:59:00.089974814 +0100 +++ gcc/tree-ssa-phiopt.cc 2022-03-31 14:38:27.537149245 +0200 @@ -1395,11 +1395,22 @@ value_replacement (basic_block cond_bb, gimple *assign = gsi_stmt (gsi); if (!is_gimple_assign (assign) - || gimple_assign_rhs_class (assign) != GIMPLE_BINARY_RHS || (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)) && !POINTER_TYPE_P (TREE_TYPE (arg0)))) return 0; + if (gimple_assign_rhs_class (assign) != GIMPLE_BINARY_RHS) + { + /* If last stmt of the middle_bb is a conversion, handle it like + a preparation statement through constant evaluation with + checking for UB. */ + enum tree_code sc = gimple_assign_rhs_code (assign); + if (CONVERT_EXPR_CODE_P (sc)) + assign = NULL; + else + return 0; + } + /* Punt if there are (degenerate) PHIs in middle_bb, there should not be. */ if (!gimple_seq_empty_p (phi_nodes (middle_bb))) return 0; @@ -1430,7 +1441,8 @@ value_replacement (basic_block cond_bb, int prep_cnt; for (prep_cnt = 0; ; prep_cnt++) { - gsi_prev_nondebug (&gsi); + if (prep_cnt || assign) + gsi_prev_nondebug (&gsi); if (gsi_end_p (gsi)) break; @@ -1450,7 +1462,8 @@ value_replacement (basic_block cond_bb, || !INTEGRAL_TYPE_P (TREE_TYPE (lhs)) || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1)) || !single_imm_use (lhs, &use_p, &use_stmt) - || use_stmt != (prep_cnt ? prep_stmt[prep_cnt - 1] : assign)) + || ((prep_cnt || assign) + && use_stmt != (prep_cnt ? prep_stmt[prep_cnt - 1] : assign))) return 0; switch (gimple_assign_rhs_code (g)) { @@ -1483,10 +1496,6 @@ value_replacement (basic_block cond_bb, >= 3 * estimate_num_insns (cond, &eni_time_weights)) return 0; - tree lhs = gimple_assign_lhs (assign); - tree rhs1 = gimple_assign_rhs1 (assign); - tree rhs2 = gimple_assign_rhs2 (assign); - enum tree_code code_def = gimple_assign_rhs_code (assign); tree cond_lhs = gimple_cond_lhs (cond); tree cond_rhs = gimple_cond_rhs (cond); @@ -1516,16 +1525,39 @@ value_replacement (basic_block cond_bb, return 0; } + tree lhs, rhs1, rhs2; + enum tree_code code_def; + if (assign) + { + lhs = gimple_assign_lhs (assign); + rhs1 = gimple_assign_rhs1 (assign); + rhs2 = gimple_assign_rhs2 (assign); + code_def = gimple_assign_rhs_code (assign); + } + else + { + gcc_assert (prep_cnt > 0); + lhs = cond_lhs; + rhs1 = NULL_TREE; + rhs2 = NULL_TREE; + code_def = ERROR_MARK; + } + if (((code == NE_EXPR && e1 == false_edge) || (code == EQ_EXPR && e1 == true_edge)) && arg0 == lhs - && ((arg1 == rhs1 - && operand_equal_for_phi_arg_p (rhs2, cond_lhs) - && neutral_element_p (code_def, cond_rhs, true)) - || (arg1 == rhs2 + && ((assign == NULL + && operand_equal_for_phi_arg_p (arg1, cond_rhs)) + || (assign + && arg1 == rhs1 + && operand_equal_for_phi_arg_p (rhs2, cond_lhs) + && neutral_element_p (code_def, cond_rhs, true)) + || (assign + && arg1 == rhs2 && operand_equal_for_phi_arg_p (rhs1, cond_lhs) && neutral_element_p (code_def, cond_rhs, false)) - || (operand_equal_for_phi_arg_p (arg1, cond_rhs) + || (assign + && operand_equal_for_phi_arg_p (arg1, cond_rhs) && ((operand_equal_for_phi_arg_p (rhs2, cond_lhs) && absorbing_element_p (code_def, cond_rhs, true, rhs2)) || (operand_equal_for_phi_arg_p (rhs1, cond_lhs) @@ -1555,8 +1587,11 @@ value_replacement (basic_block cond_bb, gsi_from = gsi_for_stmt (prep_stmt[i]); gsi_move_before (&gsi_from, &gsi); } - gsi_from = gsi_for_stmt (assign); - gsi_move_before (&gsi_from, &gsi); + if (assign) + { + gsi_from = gsi_for_stmt (assign); + gsi_move_before (&gsi_from, &gsi); + } replace_phi_edge_with_variable (cond_bb, e1, phi, lhs); return 2; } --- gcc/testsuite/gcc.dg/tree-ssa/pr104645.c.jj 2022-03-31 15:02:15.116389726 +0200 +++ gcc/testsuite/gcc.dg/tree-ssa/pr104645.c 2022-03-31 15:01:45.674817966 +0200 @@ -0,0 +1,28 @@ +/* PR tree-optimization/104645 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not " = PHI <" "optimized" } } */ + +int +foo (unsigned i) +{ + return i ? i % 2 : 0; +} + +int +bar (unsigned i) +{ + int b = 0; + if (i) + { + unsigned a = i & 1; + b = a; + } + return b; +} + +int +baz (unsigned i) +{ + return i ? i + 4 : 4; +}