From patchwork Wed Mar 2 14:27:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Plotnikov X-Patchwork-Id: 85087 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 2D58BB70CD for ; Thu, 3 Mar 2011 01:27:20 +1100 (EST) Received: (qmail 22427 invoked by alias); 2 Mar 2011 14:27:17 -0000 Received: (qmail 22417 invoked by uid 22791); 2 Mar 2011 14:27:16 -0000 X-SWARE-Spam-Status: No, hits=-0.8 required=5.0 tests=AWL, BAYES_00, FSL_RU_URL, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from smtp.ispras.ru (HELO smtp.ispras.ru) (83.149.198.201) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 02 Mar 2011 14:27:09 +0000 Received: from ispserv.ispras.ru (ispserv.ispras.ru [83.149.198.72]) by smtp.ispras.ru (Postfix) with ESMTP id 9FC385D40F4; Wed, 2 Mar 2011 17:15:37 +0300 (MSK) Received: from [10.10.3.60] (winnie.ispras.ru [83.149.198.236]) by ispserv.ispras.ru (Postfix) with ESMTP id 7E5213FC48; Wed, 2 Mar 2011 17:27:05 +0300 (MSK) Message-ID: <4D6E53C8.5090508@ispras.ru> Date: Wed, 02 Mar 2011 17:27:20 +0300 From: Dmitry Plotnikov User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101208 Thunderbird/3.1.7 MIME-Version: 1.0 To: ramana.radhakrishnan@arm.com CC: Ramana Radhakrishnan , Tejas Belagod , gcc-patches@gcc.gnu.org, rearnsha@arm.com, dm@ispras.ru Subject: Re: [PATCH, ARM] VSHL, VSHR, VLSHR immediate values support References: <4C20B1A9.7060506@ispras.ru> <1290530868.9970.0.camel@e102484-lin.cambridge.arm.com> <4CEE5BAD.9080605@ispras.ru> <1290767684.29979.14.camel@e102484-lin.cambridge.arm.com> <4D187523.20102@ispras.ru> <4D6AE2F6.2060102@gmail.com> In-Reply-To: <4D6AE2F6.2060102@gmail.com> 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 On 02/28/2011 02:49 AM, Ramana Radhakrishnan wrote: > Hi Dmitry, > > Sorry about the delayed review of this patch. Can you please > correct the formatting according to a few comments inline below ? > > Can you add some tests to check for the generation of vshl and vlshr > please ? Thanks in advance. > > cheers > Ramana > > Thank you for review! Fixed. New patch attached. Ok now ? gcc/config/arm/ 2010-11-25 Dmitry Plotnikov Dmitry Melnik * arm.c (neon_immediate_valid_for_shift): New function. (neon_output_shift_immediate): New function. * neon.md (vashl3): Modified constraint. (vashr3_imm): New insn pattern. (vlshr3_imm): New insn pattern. (vashr3): Modified constraint. (vlshr3): Modified constraint. * predicates.md (imm_for_neon_lshift_operand): New predicate. (imm_for_neon_rshift_operand): New predicate. (imm_lshift_or_reg_neon): New predicate. (imm_rshift_or_reg_neon): New predicate. gcc/ 2010-11-25 Dmitry Plotnikov Dmitry Melnik * optabs.c (init_optabs): Init optab codes for vashl, vashr, vlshr. gcc/testsuite/ 2010-11-25 Dmitry Plotnikov Dmitry Melnik * gcc.target/arm/neon-vshr-imm-1.c: New testcase. * gcc.target/arm/neon-vshl-imm-1.c: New testcase. * gcc.target/arm/neon-vlshr-imm-1.c: New testcase. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 88c43e3..8b91c45 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -8508,6 +8508,66 @@ neon_immediate_valid_for_logic (rtx op, enum machine_mode mode, int inverse, return 1; } +/* Return TRUE if rtx OP is legal for use in a VSHR or VSHL instruction. If + the immediate is valid, write a constant suitable for using as an operand + to VSHR/VSHL to *MODCONST and the corresponding element width to + *ELEMENTWIDTH. ISLEFTSHIFT is for determine left or right shift, + because they have different limitations. */ + +bool +neon_immediate_valid_for_shift (rtx op, enum machine_mode mode, + rtx *modconst, int *elementwidth, + bool isleftshift) +{ + unsigned int innersize = GET_MODE_SIZE (GET_MODE_INNER (mode)); + unsigned int n_elts = CONST_VECTOR_NUNITS (op), i; + unsigned HOST_WIDE_INT last_elt = 0; + unsigned HOST_WIDE_INT maxshift; + + /* Split vector constant out into a byte vector. */ + for (i = 0; i < n_elts; i++) + { + rtx el = CONST_VECTOR_ELT (op, i); + unsigned HOST_WIDE_INT elpart; + + if (GET_CODE (el) == CONST_INT) + elpart = INTVAL (el); + else if (GET_CODE (el) == CONST_DOUBLE) + return 0; + else + gcc_unreachable (); + + if (i != 0 && elpart != last_elt) + return 0; + + last_elt = elpart; + } + + /* Shift less than element size. */ + maxshift = innersize * 8; + + if (isleftshift) + { + /* Left shift immediate value can be from 0 to -1. */ + if ((last_elt < 0) || (last_elt >= maxshift)) + return 0; + } + else + { + /* Right shift immediate value can be from 1 to . */ + if ((last_elt <= 0) || (last_elt > maxshift)) + return 0; + } + + if (elementwidth) + *elementwidth = innersize * 8; + + if (modconst) + *modconst = CONST_VECTOR_ELT (op, 0); + + return 1; +} + /* Return a string suitable for output of Neon immediate logic operation MNEM. */ @@ -8530,6 +8590,28 @@ neon_output_logic_immediate (const char *mnem, rtx *op2, enum machine_mode mode, return templ; } +/* Return a string suitable for output of Neon immediate shift operation + (VSHR or VSHL) MNEM. */ + +char * +neon_output_shift_immediate (const char *mnem, char sign, rtx *op2, + enum machine_mode mode, int quad, + bool isleftshift) +{ + int width, is_valid; + static char templ[40]; + + is_valid = neon_immediate_valid_for_shift (*op2, mode, op2, &width, isleftshift); + gcc_assert (is_valid != 0); + + if (quad) + sprintf (templ, "%s.%c%d\t%%q0, %%q1, %%2", mnem, sign, width); + else + sprintf (templ, "%s.%c%d\t%%P0, %%P1, %%2", mnem, sign, width); + + return templ; +} + /* Output a sequence of pairwise operations to implement a reduction. NOTE: We do "too much work" here, because pairwise operations work on two registers-worth of operands in one go. Unfortunately we can't exploit those diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index 06bbc52..b87d0a6 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -929,11 +929,53 @@ ; SImode elements. (define_insn "vashl3" + [(set (match_operand:VDQIW 0 "s_register_operand" "=w,w") + (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w,w") + (match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dn")))] + "TARGET_NEON" + { + switch (which_alternative) + { + case 0: return "vshl.\t%0, %1, %2"; + case 1: return neon_output_shift_immediate ("vshl", 'i', &operands[2], + mode, + VALID_NEON_QREG_MODE (mode), + true); + default: gcc_unreachable (); + } + } + [(set (attr "neon_type") + (if_then_else (ne (symbol_ref "") (const_int 0)) + (const_string "neon_vshl_ddd") + (const_string "neon_shift_3")))] +) + +(define_insn "vashr3_imm" [(set (match_operand:VDQIW 0 "s_register_operand" "=w") - (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w") - (match_operand:VDQIW 2 "s_register_operand" "w")))] + (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w") + (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))] "TARGET_NEON" - "vshl.\t%0, %1, %2" + { + return neon_output_shift_immediate ("vshr", 'i', &operands[2], + mode, VALID_NEON_QREG_MODE (mode), + false); + } + [(set (attr "neon_type") + (if_then_else (ne (symbol_ref "") (const_int 0)) + (const_string "neon_vshl_ddd") + (const_string "neon_shift_3")))] +) + +(define_insn "vlshr3_imm" + [(set (match_operand:VDQIW 0 "s_register_operand" "=w") + (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w") + (match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))] + "TARGET_NEON" + { + return neon_output_shift_immediate ("vshr", 'u', &operands[2], + mode, VALID_NEON_QREG_MODE (mode), + false); + } [(set (attr "neon_type") (if_then_else (ne (symbol_ref "") (const_int 0)) (const_string "neon_vshl_ddd") @@ -976,29 +1018,35 @@ (define_expand "vashr3" [(set (match_operand:VDQIW 0 "s_register_operand" "") - (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "") - (match_operand:VDQIW 2 "s_register_operand" "")))] + (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "") + (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))] "TARGET_NEON" { rtx neg = gen_reg_rtx (mode); - - emit_insn (gen_neg2 (neg, operands[2])); - emit_insn (gen_ashl3_signed (operands[0], operands[1], neg)); - + if (REG_P (operands[2])) + { + emit_insn (gen_neg2 (neg, operands[2])); + emit_insn (gen_ashl3_signed (operands[0], operands[1], neg)); + } + else + emit_insn(gen_vashr3_imm (operands[0], operands[1], operands[2])); DONE; }) (define_expand "vlshr3" [(set (match_operand:VDQIW 0 "s_register_operand" "") - (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "") - (match_operand:VDQIW 2 "s_register_operand" "")))] + (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "") + (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))] "TARGET_NEON" { rtx neg = gen_reg_rtx (mode); - - emit_insn (gen_neg2 (neg, operands[2])); - emit_insn (gen_ashl3_unsigned (operands[0], operands[1], neg)); - + if (REG_P (operands[2])) + { + emit_insn (gen_neg2 (neg, operands[2])); + emit_insn (gen_ashl3_unsigned (operands[0], operands[1], neg)); + } + else + emit_insn(gen_vlshr3_imm (operands[0], operands[1], operands[2])); DONE; }) diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index e4c6146..26ff1c5 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -585,6 +585,26 @@ return neon_immediate_valid_for_move (op, mode, NULL, NULL); }) +(define_predicate "imm_for_neon_lshift_operand" + (match_code "const_vector") +{ + return neon_immediate_valid_for_shift (op, mode, NULL, NULL, true); +}) + +(define_predicate "imm_for_neon_rshift_operand" + (match_code "const_vector") +{ + return neon_immediate_valid_for_shift (op, mode, NULL, NULL, false); +}) + +(define_predicate "imm_lshift_or_reg_neon" + (ior (match_operand 0 "s_register_operand") + (match_operand 0 "imm_for_neon_lshift_operand"))) + +(define_predicate "imm_rshift_or_reg_neon" + (ior (match_operand 0 "s_register_operand") + (match_operand 0 "imm_for_neon_rshift_operand"))) + (define_predicate "imm_for_neon_logic_operand" (match_code "const_vector") { diff --git a/gcc/optabs.c b/gcc/optabs.c index 26735dd..012dae7 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6171,6 +6171,9 @@ init_optabs (void) init_optab (usashl_optab, US_ASHIFT); init_optab (ashr_optab, ASHIFTRT); init_optab (lshr_optab, LSHIFTRT); + init_optabv (vashl_optab, ASHIFT); + init_optabv (vashr_optab, ASHIFTRT); + init_optabv (vlshr_optab, LSHIFTRT); init_optab (rotl_optab, ROTATE); init_optab (rotr_optab, ROTATERT); init_optab (smin_optab, SMIN); diff --git a/gcc/testsuite/gcc.target/arm/neon-vlshr-imm-1.c b/gcc/testsuite/gcc.target/arm/neon-vlshr-imm-1.c new file mode 100644 index 0000000..e666371 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/neon-vlshr-imm-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_neon_ok } */ +/* { dg-options "-O2 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize" } */ +/* { dg-final { scan-assembler "vshr\.u32.*#3" } } */ + +/* Verify that VSHR immediate is used. */ +void f1(int n, unsigned int x[], unsigned int y[]) { + int i; + for (i = 0; i < n; ++i) + y[i] = x[i] >> 3; +} diff --git a/gcc/testsuite/gcc.target/arm/neon-vshl-imm-1.c b/gcc/testsuite/gcc.target/arm/neon-vshl-imm-1.c new file mode 100644 index 0000000..913d595 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/neon-vshl-imm-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_neon_ok } */ +/* { dg-options "-O2 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize" } */ +/* { dg-final { scan-assembler "vshl\.i32.*#3" } } */ + +/* Verify that VSHR immediate is used. */ +void f1(int n, int x[], int y[]) { + int i; + for (i = 0; i < n; ++i) + y[i] = x[i] << 3; +} diff --git a/gcc/testsuite/gcc.target/arm/neon-vshr-imm-1.c b/gcc/testsuite/gcc.target/arm/neon-vshr-imm-1.c new file mode 100644 index 0000000..8f22a52 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/neon-vshr-imm-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_neon_ok } */ +/* { dg-options "-O2 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize" } */ +/* { dg-final { scan-assembler "vshr\.i32.*#3" } } */ + +/* Verify that VSHR immediate is used. */ +void f1(int n, int x[], int y[]) { + int i; + for (i = 0; i < n; ++i) + y[i] = x[i] >> 3; +}