From patchwork Wed Feb 29 12:50:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulrich Weigand X-Patchwork-Id: 143718 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 71367B6F9F for ; Wed, 29 Feb 2012 23:50:51 +1100 (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=1331124652; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Received:Message-Id:Received:Subject:To:Date: From:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=VspRXQ56oJDGTFVeHA6y H2JkSfM=; b=dOj9hRcvzI78xi2e6/GtKpIi9vEZrB8UscGyc8vHU9pXcv/dIu6J spmAzyujWICGr1Rjp5gf8q676Ax/CW76yT8Fk4ky0rQGpP0iPTIc2GnzVq/qIJdA d3T+Yjoe5wc+Nz/AeGh3FpbQxUovhgP2Y/CFIKIEHaA+xPBWPYMs79U= 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:Message-Id:Received:Subject:To:Date:From:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:x-cbid:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=tanZ6bv1GAlSwOvW4ytWzoo+hqVwDCONidYHVeD8wYPSwE3eqXgUez3RByWy15 QUfZCrdabNQOI2RtBPLN4weIyWI0koPn4OglxZC7A9+eRwApZVgNRDAKvqrOSlFU Bcx7zOuLN3dVUXK15Stf+VpVRNsyTAJ1fMoyyGu0dBb2M=; Received: (qmail 479 invoked by alias); 29 Feb 2012 12:50:47 -0000 Received: (qmail 465 invoked by uid 22791); 29 Feb 2012 12:50:45 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL, BAYES_00, MSGID_FROM_MTA_HEADER, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from e06smtp10.uk.ibm.com (HELO e06smtp10.uk.ibm.com) (195.75.94.106) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 29 Feb 2012 12:50:29 +0000 Received: from /spool/local by e06smtp10.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 29 Feb 2012 12:50:27 -0000 Received: from d06nrmr1806.portsmouth.uk.ibm.com (9.149.39.193) by e06smtp10.uk.ibm.com (192.168.101.140) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 29 Feb 2012 12:50:25 -0000 Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by d06nrmr1806.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q1TCoPOv1867966 for ; Wed, 29 Feb 2012 12:50:25 GMT Received: from d06av02.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q1TCoOlL016877 for ; Wed, 29 Feb 2012 05:50:24 -0700 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with SMTP id q1TCoNTX016768; Wed, 29 Feb 2012 05:50:23 -0700 Message-Id: <201202291250.q1TCoNTX016768@d06av02.portsmouth.uk.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Wed, 29 Feb 2012 13:50:23 +0100 Subject: [PATCH, ARM] Generate usat/ssat instructions To: gcc-patches@gcc.gnu.org Date: Wed, 29 Feb 2012 13:50:23 +0100 (CET) From: "Ulrich Weigand" Cc: patches@linaro.org, ramana.radhakrishnan@linaro.org MIME-Version: 1.0 x-cbid: 12022912-4966-0000-0000-0000019B421E 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 Hello, this patch adds support for generating usat/ssat instructions to match code along the lines of: if (a < amin) return amin; else if (a > amax) return amax; else return a; for appropriate values of amin/amax. This type code actually occurs in real-life code (e.g. codecs). Above code is already translated into a sequence of SMIN/SMAX RTX operations by expand. The combine pass is able to fold those into a single RTX pattern, so we only need to make such patterns available to match the instruction. Note that usat/ssat may in addition shift their input operand; this is also supported by the patch. There are already pre-existing patterns that use usat/ssat to implement us_truncate/ss_truncate. Those represent special cases of the general instructions, and are left in place by this patch. (However, some minor fixes e.g. to the sat_shift_operator predicate and insn attributes apply to those patterns too.) Tested on arm-linux-gnueabi with no regressions. OK for 4.8? Bye, Ulrich ChangeLog: gcc/ * config/arm/arm.c (arm_sat_operator_match): New function. * config/arm/arm-protos.h (arm_sat_operator_match): Add prototype. * config/arm/arm.md ("insn" attribute): Add "sat" value. ("SAT", "SATrev"): New code iterators. ("SATlo", "SAThi"): New code iterator attributes. ("*satsi_"): New pattern. ("*satsi__shift"): Likewise. * config/arm/arm-fixed.md ("arm_ssatsihi_shift"): Add "insn" and "shift" attributes. ("arm_usatsihi"): Add "insn" attribute. * config/arm/predicates.md (sat_shift_operator): Allow multiplication by powers of two. Do not allow shift by 32. gcc/testsuite/ * gcc.target/arm/sat-1.c: New test. Index: gcc/testsuite/gcc.target/arm/sat-1.c =================================================================== --- gcc/testsuite/gcc.target/arm/sat-1.c (revision 0) +++ gcc/testsuite/gcc.target/arm/sat-1.c (revision 0) @@ -0,0 +1,64 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-require-effective-target arm_arch_v6_ok } */ +/* { dg-options "-O2 -marm" } */ +/* { dg-add-options arm_arch_v6 } */ + + +static inline int sat1 (int a, int amin, int amax) +{ + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +static inline int sat2 (int a, int amin, int amax) +{ + if (a > amax) return amax; + else if (a < amin) return amin; + else return a; +} + +int u1 (int x) +{ + return sat1 (x, 0, 63); +} + +int us1 (int x) +{ + return sat1 (x >> 5, 0, 63); +} + +int s1 (int x) +{ + return sat1 (x, -64, 63); +} + +int ss1 (int x) +{ + return sat1 (x >> 5, -64, 63); +} + +int u2 (int x) +{ + return sat2 (x, 0, 63); +} + +int us2 (int x) +{ + return sat2 (x >> 5, 0, 63); +} + +int s2 (int x) +{ + return sat2 (x, -64, 63); +} + +int ss2 (int x) +{ + return sat2 (x >> 5, -64, 63); +} + +/* { dg-final { scan-assembler-times "usat" 4 } } */ +/* { dg-final { scan-assembler-times "ssat" 4 } } */ + Index: gcc/config/arm/arm.c =================================================================== --- gcc/config/arm/arm.c (revision 184553) +++ gcc/config/arm/arm.c (working copy) @@ -10041,6 +10041,42 @@ } } +/* Match pair of min/max operators that can be implemented via usat/ssat. */ + +bool +arm_sat_operator_match (rtx lo_bound, rtx hi_bound, + int *mask, bool *signed_sat) +{ + /* The high bound must be a power of two minus one. */ + int log = exact_log2 (INTVAL (hi_bound) + 1); + if (log == -1) + return false; + + /* The low bound is either zero (for usat) or one less than the + negation of the high bound (for ssat). */ + if (INTVAL (lo_bound) == 0) + { + if (mask) + *mask = log; + if (signed_sat) + *signed_sat = false; + + return true; + } + + if (INTVAL (lo_bound) == -INTVAL (hi_bound) - 1) + { + if (mask) + *mask = log + 1; + if (signed_sat) + *signed_sat = true; + + return true; + } + + return false; +} + /* Return 1 if memory locations are adjacent. */ int adjacent_mem_locations (rtx a, rtx b) Index: gcc/config/arm/arm-fixed.md =================================================================== --- gcc/config/arm/arm-fixed.md (revision 184553) +++ gcc/config/arm/arm-fixed.md (working copy) @@ -374,6 +374,8 @@ "TARGET_32BIT && arm_arch6" "ssat%?\\t%0, #16, %2%S1" [(set_attr "predicable" "yes") + (set_attr "insn" "sat") + (set_attr "shift" "1") (set_attr "type" "alu_shift")]) (define_insn "arm_usatsihi" @@ -381,4 +383,5 @@ (us_truncate:HI (match_operand:SI 1 "s_register_operand")))] "TARGET_INT_SIMD" "usat%?\\t%0, #16, %1" - [(set_attr "predicable" "yes")]) + [(set_attr "predicable" "yes") + (set_attr "insn" "sat")]) Index: gcc/config/arm/arm-protos.h =================================================================== --- gcc/config/arm/arm-protos.h (revision 184553) +++ gcc/config/arm/arm-protos.h (working copy) @@ -107,6 +107,7 @@ extern int symbol_mentioned_p (rtx); extern int label_mentioned_p (rtx); extern RTX_CODE minmax_code (rtx); +extern bool arm_sat_operator_match (rtx, rtx, int *, bool *); extern int adjacent_mem_locations (rtx, rtx); extern bool gen_ldm_seq (rtx *, int, bool); extern bool gen_stm_seq (rtx *, int); Index: gcc/config/arm/predicates.md =================================================================== --- gcc/config/arm/predicates.md (revision 184553) +++ gcc/config/arm/predicates.md (working copy) @@ -243,9 +243,11 @@ ;; True for shift operators which can be used with saturation instructions. (define_special_predicate "sat_shift_operator" - (and (match_code "ashift,ashiftrt") - (match_test "GET_CODE (XEXP (op, 1)) == CONST_INT - && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1)) <= 32)") + (and (ior (and (match_code "mult") + (match_test "power_of_two_operand (XEXP (op, 1), mode)")) + (and (match_code "ashift,ashiftrt") + (match_test "GET_CODE (XEXP (op, 1)) == CONST_INT + && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1)) < 32)"))) (match_test "mode == GET_MODE (op)"))) ;; True for MULT, to identify which variant of shift_operator is in use. Index: gcc/config/arm/arm.md =================================================================== --- gcc/config/arm/arm.md (revision 184553) +++ gcc/config/arm/arm.md (working copy) @@ -283,7 +283,7 @@ ;; scheduling information. (define_attr "insn" - "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other" + "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,sat,other" (const_string "other")) ; TYPE attribute is used to detect floating point instructions which, if @@ -3446,6 +3446,60 @@ (const_int 12)))] ) +(define_code_iterator SAT [smin smax]) +(define_code_iterator SATrev [smin smax]) +(define_code_attr SATlo [(smin "1") (smax "2")]) +(define_code_attr SAThi [(smin "2") (smax "1")]) + +(define_insn "*satsi_" + [(set (match_operand:SI 0 "s_register_operand" "=r") + (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r") + (match_operand:SI 1 "const_int_operand" "i")) + (match_operand:SI 2 "const_int_operand" "i")))] + "TARGET_32BIT && arm_arch6 && != + && arm_sat_operator_match (operands[], operands[], NULL, NULL)" +{ + int mask; + bool signed_sat; + if (!arm_sat_operator_match (operands[], operands[], + &mask, &signed_sat)) + gcc_unreachable (); + + operands[1] = GEN_INT (mask); + if (signed_sat) + return "ssat%?\t%0, %1, %3"; + else + return "usat%?\t%0, %1, %3"; +} + [(set_attr "predicable" "yes") + (set_attr "insn" "sat")]) + +(define_insn "*satsi__shift" + [(set (match_operand:SI 0 "s_register_operand" "=r") + (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator" + [(match_operand:SI 4 "s_register_operand" "r") + (match_operand:SI 5 "const_int_operand" "i")]) + (match_operand:SI 1 "const_int_operand" "i")) + (match_operand:SI 2 "const_int_operand" "i")))] + "TARGET_32BIT && arm_arch6 && != + && arm_sat_operator_match (operands[], operands[], NULL, NULL)" +{ + int mask; + bool signed_sat; + if (!arm_sat_operator_match (operands[], operands[], + &mask, &signed_sat)) + gcc_unreachable (); + + operands[1] = GEN_INT (mask); + if (signed_sat) + return "ssat%?\t%0, %1, %4%S3"; + else + return "usat%?\t%0, %1, %4%S3"; +} + [(set_attr "predicable" "yes") + (set_attr "insn" "sat") + (set_attr "shift" "3") + (set_attr "type" "alu_shift")]) ;; Shift and rotation insns