From patchwork Tue Oct 12 18:04:49 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Froyd X-Patchwork-Id: 67604 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 A8C56B6EF0 for ; Wed, 13 Oct 2010 05:05:10 +1100 (EST) Received: (qmail 22669 invoked by alias); 12 Oct 2010 18:05:05 -0000 Received: (qmail 22561 invoked by uid 22791); 12 Oct 2010 18:05:01 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL, BAYES_00, TW_SR, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 12 Oct 2010 18:04:54 +0000 Received: (qmail 18265 invoked from network); 12 Oct 2010 18:04:52 -0000 Received: from unknown (HELO codesourcery.com) (froydnj@127.0.0.2) by mail.codesourcery.com with ESMTPA; 12 Oct 2010 18:04:52 -0000 Date: Tue, 12 Oct 2010 14:04:49 -0400 From: Nathan Froyd To: gcc-patches@gcc.gnu.org Cc: dje.gcc@gmail.com Subject: [PATCH,rs6000] inform combine about extra isel alternatives Message-ID: <20101012180448.GB24720@nightcrawler> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) 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 My patch to permit isel to accommodate a constant 0 operand: http://gcc.gnu.org/ml/gcc-patches/2010-07/msg01298.html has one small problem: patterns with comparisons that isel can't handle are assumed to be invalid. They were permitted before the patch, but not afterwards. However, they are still useful for combine's purposes. This patch introduces two patterns for combine's purposes; a new predicate is needed to constrain the comparison appropriately. The tweak to output_isel is necessary to reverse the sense of the condition before outputting the assembly. (The PUT_CODE there is gross, but such a construct was used prior to my July patch.) Finally, the addition of NE to rs6000_rtx_costs is to ensure that we think: (if_then_else (ne (compare (reg:CC N) 0)) ... ...) as just as cheap as the EQ variant. Otherwise, combine will probably reject the NE version as being too expensive (0 will be considered as COST_N_INSNS(2) or more). A typical example of what we gain as a result looks like: - rlwinm 9,9,0,31,31 srwi 10,3,1 xori 11,4,16386 srwi 11,11,1 ori 11,11,32768 srwi 4,4,1 - cmpwi 7,9,1 - isel 0,11,4,30 + andi. 0,9,1 + isel 0,4,11,2 The rlwinm+cmpwi has been replaced in favor of andi.. This assembly is faster and equivalent to what 4.5 generates. Testing on powerpc-linux-gnu in progress. OK to commit? -Nathan * config/rs6000/predicates.md (scc_rev_comparison_operator): New. * config/rs6000/rs6000.md (*isel_reversed_signed_): New. (*isel_reversed_unsigned_): New. * config/rs6000/rs6000.c (output_isel): Accept GE/GEU/LE/LEU/NE as valid comparisons and adjust operands and output appropriately. (rs6000_rtx_costs) : Accept NE as a cost-0 outer_code. Index: config/rs6000/predicates.md =================================================================== --- config/rs6000/predicates.md (revision 165389) +++ config/rs6000/predicates.md (working copy) @@ -903,6 +903,12 @@ (define_predicate "scc_comparison_operat (and (match_operand 0 "branch_comparison_operator") (match_code "eq,lt,gt,ltu,gtu,unordered"))) +;; Return 1 if OP is a comparison operation whose inverse would be valid for +;; an SCC insn. +(define_predicate "scc_rev_comparison_operator" + (and (match_operand 0 "branch_comparison_operator") + (match_code "ne,le,ge,leu,geu,ordered"))) + ;; Return 1 if OP is a comparison operation that is valid for a branch ;; insn, which is true if the corresponding bit in the CC register is set. (define_predicate "branch_positive_comparison_operator" Index: config/rs6000/rs6000.c =================================================================== --- config/rs6000/rs6000.c (revision 165389) +++ config/rs6000/rs6000.c (working copy) @@ -17159,7 +17159,13 @@ output_isel (rtx *operands) code = GET_CODE (operands[1]); - gcc_assert (!(code == GE || code == GEU || code == LE || code == LEU || code == NE)); + if (code == GE || code == GEU || code == LE || code == LEU || code == NE) + { + gcc_assert (GET_CODE (operands[2]) == REG + && GET_CODE (operands[3]) == REG); + PUT_CODE (operands[1], reverse_condition (code)); + return "isel %0,%3,%2,%j1"; + } return "isel %0,%2,%3,%j1"; } @@ -25731,7 +25737,7 @@ rs6000_rtx_costs (rtx x, int code, int o || (outer_code == COMPARE && (satisfies_constraint_I (x) || satisfies_constraint_K (x))) - || (outer_code == EQ + || ((outer_code == EQ || outer_code == NE) && (satisfies_constraint_I (x) || satisfies_constraint_K (x) || (mode == SImode Index: config/rs6000/rs6000.md =================================================================== --- config/rs6000/rs6000.md (revision 165389) +++ config/rs6000/rs6000.md (working copy) @@ -6126,6 +6126,38 @@ (define_insn "isel_unsigned_" [(set_attr "type" "isel") (set_attr "length" "4")]) +;; These patterns can be useful for combine; they let combine know that +;; isel can handle reversed comparisons so long as the operands are +;; registers. + +(define_insn "*isel_reversed_signed_" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (if_then_else:GPR + (match_operator 1 "scc_rev_comparison_operator" + [(match_operand:CC 4 "cc_reg_operand" "y") + (const_int 0)]) + (match_operand:GPR 2 "gpc_reg_operand" "b") + (match_operand:GPR 3 "gpc_reg_operand" "b")))] + "TARGET_ISEL" + "* +{ return output_isel (operands); }" + [(set_attr "type" "isel") + (set_attr "length" "4")]) + +(define_insn "*isel_reversed_unsigned_" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (if_then_else:GPR + (match_operator 1 "scc_rev_comparison_operator" + [(match_operand:CCUNS 4 "cc_reg_operand" "y") + (const_int 0)]) + (match_operand:GPR 2 "gpc_reg_operand" "b") + (match_operand:GPR 3 "gpc_reg_operand" "b")))] + "TARGET_ISEL" + "* +{ return output_isel (operands); }" + [(set_attr "type" "isel") + (set_attr "length" "4")]) + (define_expand "movsfcc" [(set (match_operand:SF 0 "gpc_reg_operand" "") (if_then_else:SF (match_operand 1 "comparison_operator" "")