From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 124727 invoked by alias); 24 Jun 2015 00:51:22 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 124560 invoked by uid 89); 24 Jun 2015 00:51:21 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f42.google.com Received: from mail-pa0-f42.google.com (HELO mail-pa0-f42.google.com) (209.85.220.42) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 24 Jun 2015 00:51:20 +0000 Received: by pabvl15 with SMTP id vl15so17441823pab.1 for ; Tue, 23 Jun 2015 17:51:18 -0700 (PDT) X-Received: by 10.68.197.102 with SMTP id it6mr40373742pbc.65.1435107078109; Tue, 23 Jun 2015 17:51:18 -0700 (PDT) Received: from bubble.grove.modra.org (CPE-58-160-155-134.oycza5.sa.bigpond.net.au. [58.160.155.134]) by mx.google.com with ESMTPSA id k9sm24535798pbq.71.2015.06.23.17.51.16 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 23 Jun 2015 17:51:17 -0700 (PDT) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id 0195EEA0074; Wed, 24 Jun 2015 10:21:12 +0930 (ACST) Date: Wed, 24 Jun 2015 00:52:00 -0000 From: Alan Modra To: gcc-patches@gcc.gnu.org Cc: David Edelsohn Subject: [RS6000 2/7] Tidy rotates Message-ID: <20150624005112.GW1723@bubble.grove.modra.org> Mail-Followup-To: gcc-patches@gcc.gnu.org, David Edelsohn References: <20150624004649.GU1723@bubble.grove.modra.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20150624004649.GU1723@bubble.grove.modra.org> User-Agent: Mutt/1.5.23 (2014-03-12) X-IsSubscribed: yes X-SW-Source: 2015-06/txt/msg01642.txt.bz2 Besides various tidies this fixes the wrong mode used for a number of rotate pattern shift counts. Since every other shift and rotate pattern uses SImode for the shift count, these combine patterns won't match anything. The testcase exercises one of these rotate patterns. It requires rtx_cost const_int mode fix to pass, since without that the combine pattern is not seen as profitable. See notes interspersed with changelog. gcc/ * config/rs6000/predicates.md (logical_const_operand): Correct comment. (mask_operand): Note failure to exclude masks only valid in 64-bit insns when used in 'T' constraint. * config/rs6000/rs6000.md (and3_imm_dot): Comment. (and3_imm_dot2): Comment. (and3_mask): Use 'n' constraint rather than 'T'. May as well use 'n' as all we need is something to mop up the leftover cases that match the operand predicate but don't match 'S'. 'T' is ineffective as a constraint anyway. You can't put 'T' before 'S' as per the comment added to mask_operand. (and3_mask_dot): Likewise. Remove redundant insn predicate test. (and3_mask_dot2): Likewise. (andsi3_internal0_nomc): Delete. Covered by and3_mask and bool3, so redundant. (rotldi3_internal4): Use SImode for shift count. (rotldi3_internal5, +split): Likewise. (rotldi3_internal6, +split): Likewise. (ashldi3_internal7): Don't repeat operand predicate test covered by insn predicate. includes_rldicr_lshift_p constrains the operand to a subset of mask64_operand. (ashldi3_internal8, +split): Likewise. (ashldi3_internal9, +split): Likewise. * config/rs6000/rs6000.c (includes_rldic_lshift_p): Remove redundant CONST_INT test. Don't reject all 1's. All 1's is supported by the machine instructions and doesn't cause a problem in print_operand. (includes_rldicr_lshift_p): Likewise. gcc/testsuite/ * gcc.target/powerpc/rotmask.c: New. diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index fd293ab..c408b0f 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -726,7 +726,7 @@ && !satisfies_constraint_L (op)"))) ;; Return 1 if the operand is a constant that can be used as the operand -;; of an OR or XOR. +;; of an AND, OR or XOR. (define_predicate "logical_const_operand" (match_code "const_int") { @@ -764,7 +764,11 @@ if (TARGET_POWERPC64) { - /* Fail if the mask is not 32-bit. */ + /* Fail if the mask is not 32-bit. Note: If constraints are + implemented using mask_operand then they will never fail this + test. const_ints are VOIDmode, which is what is seen here + when called from a constraint. When called as a predicate, + the match_operand mode is seen. */ if (mode == DImode && (c & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0) return 0; diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index c7c24db..5f42192 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -16444,36 +16444,30 @@ includes_rshift_p (rtx shiftop, rtx andop) int includes_rldic_lshift_p (rtx shiftop, rtx andop) { - if (GET_CODE (andop) == CONST_INT) - { - unsigned HOST_WIDE_INT c, lsb, shift_mask; + unsigned HOST_WIDE_INT c, lsb, shift_mask; - c = INTVAL (andop); - if (c == 0 || c == HOST_WIDE_INT_M1U) - return 0; + c = INTVAL (andop); + if (c == 0) + return 0; - shift_mask = HOST_WIDE_INT_M1U; - shift_mask <<= INTVAL (shiftop); + shift_mask = HOST_WIDE_INT_M1U << INTVAL (shiftop); - /* Find the least significant one bit. */ - lsb = c & -c; + /* Find the least significant one bit. */ + lsb = c & -c; - /* It must coincide with the LSB of the shift mask. */ - if (-lsb != shift_mask) - return 0; + /* It must coincide with the LSB of the shift mask. */ + if (-lsb != shift_mask) + return 0; - /* Invert to look for the next transition (if any). */ - c = ~c; + /* Invert to look for the next transition (if any). */ + c = ~c; - /* Remove the low group of ones (originally low group of zeros). */ - c &= -lsb; + /* Remove the low group of ones (originally low group of zeros). */ + c &= -lsb; - /* Again find the lsb, and check we have all 1's above. */ - lsb = c & -c; - return c == -lsb; - } - else - return 0; + /* Again find the lsb, and check we have all 1's above. */ + lsb = c & -c; + return c == -lsb; } /* Return 1 if ANDOP is a mask suitable for use with an rldicr insn @@ -16483,27 +16477,21 @@ includes_rldic_lshift_p (rtx shiftop, rtx andop) int includes_rldicr_lshift_p (rtx shiftop, rtx andop) { - if (GET_CODE (andop) == CONST_INT) - { - unsigned HOST_WIDE_INT c, lsb, shift_mask; + unsigned HOST_WIDE_INT c, lsb, shift_mask; - shift_mask = HOST_WIDE_INT_M1U; - shift_mask <<= INTVAL (shiftop); - c = INTVAL (andop); + shift_mask = HOST_WIDE_INT_M1U << INTVAL (shiftop); + c = INTVAL (andop); - /* Find the least significant one bit. */ - lsb = c & -c; - - /* It must be covered by the shift mask. - This test also rejects c == 0. */ - if ((lsb & shift_mask) == 0) - return 0; + /* Find the least significant one bit. */ + lsb = c & -c; - /* Check we have all 1's above the transition, and reject all 1's. */ - return c == -lsb && lsb != 1; - } - else + /* It must be covered by the shift mask. + This test also rejects c == 0. */ + if ((lsb & shift_mask) == 0) return 0; + + /* Check we have all 1's above the transition. */ + return c == -lsb; } /* Return 1 if operands will generate a valid arguments to rlwimi diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 243a151..f28d48e 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -2921,6 +2921,9 @@ [(set_attr "type" "logical") (set_attr "dot" "yes")]) +;; Differs from and3_imm_mask_dot in that if cr0 is not allocated +;; the splitter will need to trash cr0. So choose and3_imm_mask_dot +;; if possible. (define_insn_and_split "*and3_imm_dot" [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y") (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r") @@ -2947,6 +2950,9 @@ (set_attr "dot" "yes") (set_attr "length" "4,8")]) +;; Differs from and3_imm_mask_dot2 in that if cr0 is not allocated +;; the splitter will need to trash cr0. So choose and3_imm_mask_dot2 +;; if possible. (define_insn_and_split "*and3_imm_dot2" [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y") (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r") @@ -3029,7 +3035,7 @@ (define_insn "*and3_mask" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r") (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r") - (match_operand:GPR 2 "any_mask_operand" "S,T")))] + (match_operand:GPR 2 "any_mask_operand" "S,n")))] "" "@ rldic%B2 %0,%1,0,%S2 @@ -3039,12 +3045,11 @@ (define_insn_and_split "*and3_mask_dot" [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r") - (match_operand:GPR 2 "any_mask_operand" "S,T,S,T")) + (match_operand:GPR 2 "any_mask_operand" "S,n,S,n")) (const_int 0))) (clobber (match_scratch:GPR 0 "=r,r,r,r"))] "(mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff) - && rs6000_gen_cell_microcode - && !logical_const_operand (operands[2], mode)" + && rs6000_gen_cell_microcode" "@ rldic%B2. %0,%1,0,%S2 rlwinm. %0,%1,0,%m2,%M2 @@ -3065,14 +3070,13 @@ (define_insn_and_split "*and3_mask_dot2" [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r") - (match_operand:GPR 2 "any_mask_operand" "S,T,S,T")) + (match_operand:GPR 2 "any_mask_operand" "S,n,S,n")) (const_int 0))) (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r,r") (and:GPR (match_dup 1) (match_dup 2)))] "(mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff) - && rs6000_gen_cell_microcode - && !logical_const_operand (operands[2], mode)" + && rs6000_gen_cell_microcode" "@ rldic%B2. %0,%1,0,%S2 rlwinm. %0,%1,0,%m2,%M2 @@ -3091,18 +3095,6 @@ (set_attr "length" "4,4,8,8")]) - -(define_insn "andsi3_internal0_nomc" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") - (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r") - (match_operand:SI 2 "and_operand" "?r,T")))] - "!rs6000_gen_cell_microcode" - "@ - and %0,%1,%2 - rlwinm %0,%1,0,%m2,%M2" - [(set_attr "type" "logical,shift")]) - - ;; Handle the PowerPC64 rlwinm corner case (define_insn_and_split "*andsi3_internal6" @@ -5786,7 +5778,7 @@ (define_insn "*rotldi3_internal4" [(set (match_operand:DI 0 "gpc_reg_operand" "=r") (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r") - (match_operand:DI 2 "reg_or_cint_operand" "rn")) + (match_operand:SI 2 "reg_or_cint_operand" "rn")) (match_operand:DI 3 "mask64_operand" "n")))] "TARGET_POWERPC64" "rld%I2c%B3 %0,%1,%H2,%S3" @@ -5797,7 +5789,7 @@ [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") (compare:CC (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") - (match_operand:DI 2 "reg_or_cint_operand" "rn,rn")) + (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) (match_operand:DI 3 "mask64_operand" "n,n")) (const_int 0))) (clobber (match_scratch:DI 4 "=r,r"))] @@ -5814,7 +5806,7 @@ [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "") (compare:CC (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "") - (match_operand:DI 2 "reg_or_cint_operand" "")) + (match_operand:SI 2 "reg_or_cint_operand" "")) (match_operand:DI 3 "mask64_operand" "")) (const_int 0))) (clobber (match_scratch:DI 4 ""))] @@ -5832,7 +5824,7 @@ [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y") (compare:CC (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") - (match_operand:DI 2 "reg_or_cint_operand" "rn,rn")) + (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) (match_operand:DI 3 "mask64_operand" "n,n")) (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "=r,r") @@ -5850,7 +5842,7 @@ [(set (match_operand:CC 4 "cc_reg_not_micro_cr0_operand" "") (compare:CC (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "") - (match_operand:DI 2 "reg_or_cint_operand" "")) + (match_operand:SI 2 "reg_or_cint_operand" "")) (match_operand:DI 3 "mask64_operand" "")) (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "") @@ -5947,7 +5939,7 @@ [(set (match_operand:DI 0 "gpc_reg_operand" "=r") (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r") (match_operand:SI 2 "const_int_operand" "i")) - (match_operand:DI 3 "mask64_operand" "n")))] + (match_operand:DI 3 "const_int_operand" "n")))] "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])" "rldicr %0,%1,%H2,%S3" [(set_attr "type" "shift")]) @@ -5957,7 +5949,7 @@ (compare:CC (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") (match_operand:SI 2 "const_int_operand" "i,i")) - (match_operand:DI 3 "mask64_operand" "n,n")) + (match_operand:DI 3 "const_int_operand" "n,n")) (const_int 0))) (clobber (match_scratch:DI 4 "=r,r"))] "TARGET_64BIT && includes_rldicr_lshift_p (operands[2], operands[3])" @@ -5973,7 +5965,7 @@ (compare:CC (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "") (match_operand:SI 2 "const_int_operand" "")) - (match_operand:DI 3 "mask64_operand" "")) + (match_operand:DI 3 "const_int_operand" "")) (const_int 0))) (clobber (match_scratch:DI 4 ""))] "TARGET_POWERPC64 && reload_completed @@ -5991,7 +5983,7 @@ (compare:CC (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") (match_operand:SI 2 "const_int_operand" "i,i")) - (match_operand:DI 3 "mask64_operand" "n,n")) + (match_operand:DI 3 "const_int_operand" "n,n")) (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "=r,r") (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))] @@ -6008,7 +6000,7 @@ (compare:CC (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "") (match_operand:SI 2 "const_int_operand" "")) - (match_operand:DI 3 "mask64_operand" "")) + (match_operand:DI 3 "const_int_operand" "")) (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "") (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))] diff --git a/gcc/testsuite/gcc.target/powerpc/rotmask.c b/gcc/testsuite/gcc.target/powerpc/rotmask.c new file mode 100644 index 0000000..4d1b917 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/rotmask.c @@ -0,0 +1,8 @@ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-not "rotldi" } } */ + +unsigned long f (unsigned long x) +{ + return ((x << 1) | (x >> 63)) & 0xffffffff; +} -- Alan Modra Australia Development Lab, IBM