From patchwork Wed Nov 10 23:05:06 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 70718 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 4E295B7122 for ; Thu, 11 Nov 2010 10:05:21 +1100 (EST) Received: (qmail 1964 invoked by alias); 10 Nov 2010 23:05:15 -0000 Received: (qmail 1946 invoked by uid 22791); 10 Nov 2010 23:05:13 -0000 X-SWARE-Spam-Status: No, hits=-5.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_TM, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 10 Nov 2010 23:05:08 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oAAN576O011985 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 10 Nov 2010 18:05:07 -0500 Received: from anchor.twiddle.home (ovpn-113-114.phx2.redhat.com [10.3.113.114]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id oAAN56L4019762; Wed, 10 Nov 2010 18:05:06 -0500 Message-ID: <4CDB2522.10205@redhat.com> Date: Wed, 10 Nov 2010 15:05:06 -0800 From: Richard Henderson User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.12) Gecko/20101027 Fedora/3.1.6-1.fc14 Thunderbird/3.1.6 MIME-Version: 1.0 To: GCC Patches CC: rguenther@suse.de Subject: [patch 2/N] Recognize (-a * b) +- c for FMA conversion X-IsSubscribed: yes 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 Removes a fixme. Required for patch 3, where -mfused-madd is removed from the i386 port. There are existing i386 test cases that exercise this pattern. Ok? r~ From 976c37ad089d74465f1b173517138a0a047336ee Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Nov 2010 13:46:01 -0800 Subject: [PATCH 2/3] Recognize -(a * b) + c -> fma(-a,b,c). --- gcc/tree-ssa-math-opts.c | 107 +++++++++++++++++++++++++++++++++------------ 1 files changed, 78 insertions(+), 29 deletions(-) diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 96140f0..2840150 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -1503,7 +1503,7 @@ convert_mult_to_fma (gimple mul_stmt) { tree mul_result = gimple_assign_lhs (mul_stmt); tree type = TREE_TYPE (mul_result); - gimple use_stmt, fma_stmt; + gimple use_stmt, neguse_stmt, fma_stmt; use_operand_p use_p; imm_use_iterator imm_iter; @@ -1529,17 +1529,12 @@ convert_mult_to_fma (gimple mul_stmt) FOR_EACH_IMM_USE_FAST (use_p, imm_iter, mul_result) { enum tree_code use_code; + tree result = mul_result; + bool negate_p = false; + optab opt; use_stmt = USE_STMT (use_p); - if (!is_gimple_assign (use_stmt)) - return false; - use_code = gimple_assign_rhs_code (use_stmt); - /* ??? We need to handle NEGATE_EXPR to eventually form fnms. */ - if (use_code != PLUS_EXPR - && use_code != MINUS_EXPR) - return false; - /* For now restrict this operations to single basic blocks. In theory we would want to support sinking the multiplication in m = a*b; @@ -1552,32 +1547,82 @@ convert_mult_to_fma (gimple mul_stmt) if (gimple_bb (use_stmt) != gimple_bb (mul_stmt)) return false; - /* We can't handle a * b + a * b. */ - if (gimple_assign_rhs1 (use_stmt) == gimple_assign_rhs2 (use_stmt)) + if (!is_gimple_assign (use_stmt)) return false; - /* If the target doesn't support a * b - c then drop the ball. */ - if (gimple_assign_rhs1 (use_stmt) == mul_result - && use_code == MINUS_EXPR - && optab_handler (fms_optab, TYPE_MODE (type)) == CODE_FOR_nothing) - return false; + use_code = gimple_assign_rhs_code (use_stmt); + + /* A negate on the multiplication leads to FNMA. */ + if (use_code == NEGATE_EXPR) + { + result = gimple_assign_lhs (use_stmt); + + /* Make sure the negate statement becomes dead with this + single transformation. */ + if (!single_imm_use (gimple_assign_lhs (use_stmt), + &use_p, &neguse_stmt)) + return false; + + /* Re-validate. */ + use_stmt = neguse_stmt; + if (gimple_bb (use_stmt) != gimple_bb (mul_stmt)) + return false; + if (!is_gimple_assign (use_stmt)) + return false; + + use_code = gimple_assign_rhs_code (use_stmt); + negate_p = true; + } - /* If the target doesn't support -a * b + c then drop the ball. */ - if (gimple_assign_rhs2 (use_stmt) == mul_result - && use_code == MINUS_EXPR - && optab_handler (fnma_optab, TYPE_MODE (type)) == CODE_FOR_nothing) + /* Determine if the target supports the exact form we found. */ + switch (use_code) + { + case MINUS_EXPR: + if (gimple_assign_rhs1 (use_stmt) == result) + { + opt = negate_p ? fnms_optab : fms_optab; + break; + } + negate_p = !negate_p; + /* FALLTHRU */ + + case PLUS_EXPR: + opt = negate_p ? fnma_optab : fma_optab; + break; + + default: + /* FMA can only be formed from PLUS and MINUS. */ + return false; + } + if (optab_handler (opt, TYPE_MODE (type)) == CODE_FOR_nothing) return false; - /* We don't yet generate -a * b - c below yet. */ + /* We can't handle a * b + a * b. */ + if (gimple_assign_rhs1 (use_stmt) == gimple_assign_rhs2 (use_stmt)) + return false; } FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, mul_result) { - tree addop, mulop1; gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt); + enum tree_code use_code = gimple_assign_rhs_code (use_stmt); + tree addop, mulop1, result = mul_result; + bool negate_p = false; - mulop1 = gimple_assign_rhs1 (mul_stmt); - if (gimple_assign_rhs1 (use_stmt) == mul_result) + if (use_code == NEGATE_EXPR) + { + result = gimple_assign_lhs (use_stmt); + single_imm_use (gimple_assign_lhs (use_stmt), &use_p, &neguse_stmt); + gsi_remove (&gsi, true); + release_defs (use_stmt); + + use_stmt = neguse_stmt; + gsi = gsi_for_stmt (use_stmt); + use_code = gimple_assign_rhs_code (use_stmt); + negate_p = true; + } + + if (gimple_assign_rhs1 (use_stmt) == result) { addop = gimple_assign_rhs2 (use_stmt); /* a * b - c -> a * b + (-c) */ @@ -1593,13 +1638,17 @@ convert_mult_to_fma (gimple mul_stmt) addop = gimple_assign_rhs1 (use_stmt); /* a - b * c -> (-b) * c + a */ if (gimple_assign_rhs_code (use_stmt) == MINUS_EXPR) - mulop1 = force_gimple_operand_gsi (&gsi, - build1 (NEGATE_EXPR, - type, mulop1), - true, NULL_TREE, true, - GSI_SAME_STMT); + negate_p = !negate_p; } + mulop1 = gimple_assign_rhs1 (mul_stmt); + if (negate_p) + mulop1 = force_gimple_operand_gsi (&gsi, + build1 (NEGATE_EXPR, + type, mulop1), + true, NULL_TREE, true, + GSI_SAME_STMT); + fma_stmt = gimple_build_assign_with_ops3 (FMA_EXPR, gimple_assign_lhs (use_stmt), mulop1,