From patchwork Tue Apr 17 15:10:12 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bill Schmidt X-Patchwork-Id: 153233 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 886FCB6FE2 for ; Wed, 18 Apr 2012 01:19:57 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1335280797; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Received:Received:Message-ID:Subject:From:To: Cc:Date:Content-Type:Content-Transfer-Encoding:Mime-Version: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=0SQT5CQoBJ+yqsMdEym8 5oBraaQ=; b=GaypM21jj9aTHmMrKVwhmLAIXeN7A8tjQGepRrOj3fIIZltRszKd idEuriwoRyGb9wn9TelhbF+5DLL3yf2FVp6VasLrgN0RXpH3QPDOuFkVPQjf3kTs i6Ni3d6Z8Ysorh+jSBeuwlC9rpWchkUBDRL+PPF4iXYp64KNAY/6f9E= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Received:Received:Message-ID:Subject:From:To:Cc:Date:Content-Type:Content-Transfer-Encoding:Mime-Version:X-Content-Scanned:x-cbid:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=Z/p/OcouKgTuFiL/Ahb1y7/6SRC2zKlhRFNuaRwK/6NzNtm4tSChbG72pxmNCq bvl+Kg27d0g8PbMjkweyaHar/xO6kDD3xfonRcdSp6azViIv41aHeJLG2cfUmOBF aY0CAbdkfmPgckfUbZa3NXU/x8YoNCJNQYlXylbUu3+E4=; Received: (qmail 18811 invoked by alias); 17 Apr 2012 15:19:36 -0000 Received: (qmail 18793 invoked by uid 22791); 17 Apr 2012 15:19:30 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, TW_FN, TW_TM, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from e2.ny.us.ibm.com (HELO e2.ny.us.ibm.com) (32.97.182.142) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 17 Apr 2012 15:18:59 +0000 Received: from /spool/local by e2.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 17 Apr 2012 11:18:57 -0400 Received: from d01dlp02.pok.ibm.com (9.56.224.85) by e2.ny.us.ibm.com (192.168.1.102) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 17 Apr 2012 11:10:36 -0400 Received: from d01relay05.pok.ibm.com (d01relay05.pok.ibm.com [9.56.227.237]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id D6BB66E8057 for ; Tue, 17 Apr 2012 11:10:16 -0400 (EDT) Received: from d01av01.pok.ibm.com (d01av01.pok.ibm.com [9.56.224.215]) by d01relay05.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q3HFAGDN228278 for ; Tue, 17 Apr 2012 11:10:16 -0400 Received: from d01av01.pok.ibm.com (loopback [127.0.0.1]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q3HKf8cm002327 for ; Tue, 17 Apr 2012 16:41:08 -0400 Received: from [9.76.41.15] (sig-9-76-41-15.mts.ibm.com [9.76.41.15]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q3HKf46N002098; Tue, 17 Apr 2012 16:41:06 -0400 Message-ID: <1334675412.19102.87.camel@gnopaine> Subject: [PATCH] Allow un-distribution with repeated factors (PR52976 follow-up) From: "William J. Schmidt" To: gcc-patches@gcc.gnu.org Cc: rguenther@suse.de, bergner@vnet.ibm.com Date: Tue, 17 Apr 2012 10:10:12 -0500 Mime-Version: 1.0 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12041715-5112-0000-0000-000007245D90 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org The emergency reassociation patch for PR52976 disabled un-distribution in the presence of repeated factors to avoid ICEs in zero_one_operation. This patch fixes such cases properly by teaching zero_one_operation about __builtin_pow* calls. Bootstrapped with no new regressions on powerpc64-linux. Also built SPEC cpu2000 and cpu2006 successfully. Ok for trunk? Thanks, Bill gcc: 2012-04-17 Bill Schmidt * tree-ssa-reassoc.c (stmt_is_power_of_op): New function. (decrement_power): Likewise. (propagate_op_to_single_use): Likewise. (zero_one_operation): Handle __builtin_pow* calls in linearized expression trees; factor logic into propagate_op_to_single_use. (undistribute_ops_list): Allow operands with repeat counts > 1. gcc/testsuite: 2012-04-17 Bill Schmidt gfortran.dg/reassoc_7.f: New test. gfortran.dg/reassoc_8.f: Likewise. gfortran.dg/reassoc_9.f: Likewise. gfortran.dg/reassoc_10.f: Likewise. Index: gcc/testsuite/gfortran.dg/reassoc_10.f =================================================================== --- gcc/testsuite/gfortran.dg/reassoc_10.f (revision 0) +++ gcc/testsuite/gfortran.dg/reassoc_10.f (revision 0) @@ -0,0 +1,17 @@ +! { dg-do compile } +! { dg-options "-O3 -ffast-math -fdump-tree-optimized" } + + SUBROUTINE S55199(P,Q,Dvdph) + implicit none + real(8) :: c1,c2,c3,P,Q,Dvdph + c1=0.1d0 + c2=0.2d0 + c3=0.3d0 + Dvdph = c1 + 2.*P*c2 + 3.*P**2*Q**3*c3 + END + +! There should be five multiplies following un-distribution +! and power expansion. + +! { dg-final { scan-tree-dump-times " \\\* " 5 "optimized" } } +! { dg-final { cleanup-tree-dump "optimized" } } Index: gcc/testsuite/gfortran.dg/reassoc_7.f =================================================================== --- gcc/testsuite/gfortran.dg/reassoc_7.f (revision 0) +++ gcc/testsuite/gfortran.dg/reassoc_7.f (revision 0) @@ -0,0 +1,16 @@ +! { dg-do compile } +! { dg-options "-O3 -ffast-math -fdump-tree-optimized" } + + SUBROUTINE S55199(P,Dvdph) + implicit none + real(8) :: c1,c2,c3,P,Dvdph + c1=0.1d0 + c2=0.2d0 + c3=0.3d0 + Dvdph = c1 + 2.*P*c2 + 3.*P**2*c3 + END + +! There should be two multiplies following un-distribution. + +! { dg-final { scan-tree-dump-times " \\\* " 2 "optimized" } } +! { dg-final { cleanup-tree-dump "optimized" } } Index: gcc/testsuite/gfortran.dg/reassoc_8.f =================================================================== --- gcc/testsuite/gfortran.dg/reassoc_8.f (revision 0) +++ gcc/testsuite/gfortran.dg/reassoc_8.f (revision 0) @@ -0,0 +1,17 @@ +! { dg-do compile } +! { dg-options "-O3 -ffast-math -fdump-tree-optimized" } + + SUBROUTINE S55199(P,Dvdph) + implicit none + real(8) :: c1,c2,c3,P,Dvdph + c1=0.1d0 + c2=0.2d0 + c3=0.3d0 + Dvdph = c1 + 2.*P**2*c2 + 3.*P**3*c3 + END + +! There should be three multiplies following un-distribution +! and power expansion. + +! { dg-final { scan-tree-dump-times " \\\* " 3 "optimized" } } +! { dg-final { cleanup-tree-dump "optimized" } } Index: gcc/testsuite/gfortran.dg/reassoc_9.f =================================================================== --- gcc/testsuite/gfortran.dg/reassoc_9.f (revision 0) +++ gcc/testsuite/gfortran.dg/reassoc_9.f (revision 0) @@ -0,0 +1,17 @@ +! { dg-do compile } +! { dg-options "-O3 -ffast-math -fdump-tree-optimized" } + + SUBROUTINE S55199(P,Dvdph) + implicit none + real(8) :: c1,c2,c3,P,Dvdph + c1=0.1d0 + c2=0.2d0 + c3=0.3d0 + Dvdph = c1 + 2.*P**2*c2 + 3.*P**4*c3 + END + +! There should be three multiplies following un-distribution +! and power expansion. + +! { dg-final { scan-tree-dump-times " \\\* " 3 "optimized" } } +! { dg-final { cleanup-tree-dump "optimized" } } Index: gcc/tree-ssa-reassoc.c =================================================================== --- gcc/tree-ssa-reassoc.c (revision 186495) +++ gcc/tree-ssa-reassoc.c (working copy) @@ -1020,6 +1020,98 @@ oecount_cmp (const void *p1, const void *p2) return c1->id - c2->id; } +/* Return TRUE iff STMT represents a builtin call that raises OP + to some exponent. */ + +static bool +stmt_is_power_of_op (gimple stmt, tree op) +{ + tree fndecl; + + if (!is_gimple_call (stmt)) + return false; + + fndecl = gimple_call_fndecl (stmt); + + if (!fndecl + || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL) + return false; + + switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))) + { + CASE_FLT_FN (BUILT_IN_POW): + CASE_FLT_FN (BUILT_IN_POWI): + return (operand_equal_p (gimple_call_arg (stmt, 0), op, 0)); + + default: + return false; + } +} + +/* Given STMT which is a __builtin_pow* call, decrement its exponent + in place and return the result. Assumes that stmt_is_power_of_op + was previously called for STMT and returned TRUE. */ + +static HOST_WIDE_INT +decrement_power (gimple stmt) +{ + REAL_VALUE_TYPE c, cint; + HOST_WIDE_INT power; + tree arg1; + + switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))) + { + CASE_FLT_FN (BUILT_IN_POW): + arg1 = gimple_call_arg (stmt, 1); + c = TREE_REAL_CST (arg1); + power = real_to_integer (&c) - 1; + real_from_integer (&cint, VOIDmode, power, 0, 0); + gimple_call_set_arg (stmt, 1, build_real (TREE_TYPE (arg1), cint)); + return power; + + CASE_FLT_FN (BUILT_IN_POWI): + arg1 = gimple_call_arg (stmt, 1); + power = TREE_INT_CST_LOW (arg1) - 1; + gimple_call_set_arg (stmt, 1, build_int_cst (TREE_TYPE (arg1), power)); + return power; + + default: + gcc_unreachable (); + } +} + +/* Find the single immediate use of STMT's LHS, and replace it + with OP. Remove STMT. If STMT's LHS is the same as *DEF, + replace *DEF with OP as well. */ + +static void +propagate_op_to_single_use (tree op, gimple stmt, tree *def) +{ + tree lhs; + gimple use_stmt; + use_operand_p use; + gimple_stmt_iterator gsi; + + if (is_gimple_call (stmt)) + lhs = gimple_call_lhs (stmt); + else + lhs = gimple_assign_lhs (stmt); + + gcc_assert (has_single_use (lhs)); + single_imm_use (lhs, &use, &use_stmt); + if (lhs == *def) + *def = op; + SET_USE (use, op); + if (TREE_CODE (op) != SSA_NAME) + update_stmt (use_stmt); + gsi = gsi_for_stmt (stmt); + gsi_remove (&gsi, true); + release_defs (stmt); + + if (is_gimple_call (stmt)) + unlink_stmt_vdef (stmt); +} + /* Walks the linear chain with result *DEF searching for an operation with operand OP and code OPCODE removing that from the chain. *DEF is updated if there is only one operand but no operation left. */ @@ -1031,8 +1123,18 @@ zero_one_operation (tree *def, enum tree_code opco do { - tree name = gimple_assign_rhs1 (stmt); + tree name; + if (opcode == MULT_EXPR + && stmt_is_power_of_op (stmt, op)) + { + if (decrement_power (stmt) == 1) + propagate_op_to_single_use (op, stmt, def); + return; + } + + name = gimple_assign_rhs1 (stmt); + /* If this is the operation we look for and one of the operands is ours simply propagate the other operand into the stmts single use. */ @@ -1040,24 +1142,27 @@ zero_one_operation (tree *def, enum tree_code opco && (name == op || gimple_assign_rhs2 (stmt) == op)) { - gimple use_stmt; - use_operand_p use; - gimple_stmt_iterator gsi; if (name == op) name = gimple_assign_rhs2 (stmt); - gcc_assert (has_single_use (gimple_assign_lhs (stmt))); - single_imm_use (gimple_assign_lhs (stmt), &use, &use_stmt); - if (gimple_assign_lhs (stmt) == *def) - *def = name; - SET_USE (use, name); - if (TREE_CODE (name) != SSA_NAME) - update_stmt (use_stmt); - gsi = gsi_for_stmt (stmt); - gsi_remove (&gsi, true); - release_defs (stmt); + propagate_op_to_single_use (name, stmt, def); return; } + /* We might have a multiply of two __builtin_pow* calls, and + the operand might be hiding in the rightmost one. */ + if (opcode == MULT_EXPR + && gimple_assign_rhs_code (stmt) == opcode + && TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME) + { + gimple stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt)); + if (stmt_is_power_of_op (stmt2, op)) + { + if (decrement_power (stmt2) == 1) + propagate_op_to_single_use (op, stmt2, def); + return; + } + } + /* Continue walking the chain. */ gcc_assert (name != op && TREE_CODE (name) == SSA_NAME); @@ -1222,7 +1327,6 @@ undistribute_ops_list (enum tree_code opcode, dcode = gimple_assign_rhs_code (oe1def); if ((dcode != MULT_EXPR && dcode != RDIV_EXPR) - || oe1->count != 1 || !is_reassociable_op (oe1def, dcode, loop)) continue; @@ -1266,8 +1370,6 @@ undistribute_ops_list (enum tree_code opcode, oecount c; void **slot; size_t idx; - if (oe1->count != 1) - continue; c.oecode = oecode; c.cnt = 1; c.id = next_oecount_id++; @@ -1336,7 +1438,7 @@ undistribute_ops_list (enum tree_code opcode, FOR_EACH_VEC_ELT (operand_entry_t, subops[i], j, oe1) { - if (oe1->op == c->op && oe1->count == 1) + if (oe1->op == c->op) { SET_BIT (candidates2, i); ++nr_candidates2;