From e1e2e653d7fdcf6c9f1cafb76fbb016c1879029d Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 11 Nov 2004 17:03:36 +0000 Subject: [PATCH] re PR target/16457 (PowerPC - Combine two rldicr instructions into a single rlwinm.) .: PR target/16457 * config/rs6000/rs6000.c (mask64_2_operand): Stub to call mask64_1or2_operand. (mask64_1or_2_operand): Broken out of mask64_2_operand, add flag to spot rlwinm opportunities. (and64_2_operand): Use mask_1or2_operand. * config/rs6000/rs6000.md (anddi3): Use rlwinm when possible. testsuite: PR target/16457 * gcc.dg/ppc-and-1: New From-SVN: r90481 --- gcc/ChangeLog | 10 ++++++++++ gcc/config/rs6000/rs6000.c | 32 +++++++++++++++++++++++--------- gcc/config/rs6000/rs6000.md | 16 ++++++++-------- gcc/testsuite/ChangeLog | 3 +++ gcc/testsuite/gcc.dg/ppc-and-1.c | 20 ++++++++++++++++++++ 5 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/ppc-and-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index accb4dedeb8..21599f4ac20 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2004-11-11 Nathan Sidwell + + PR target/16457 + * config/rs6000/rs6000.c (mask64_2_operand): Stub to call + mask64_1or2_operand. + (mask64_1or2_operand): Broken out of mask64_2_operand, add flag + to spot rlwinm opportunities. + (and64_2_operand): Use mask_1or2_operand. + * config/rs6000/rs6000.md (anddi3): Use rlwinm when possible. + 2004-11-11 Dorit Naishlos * tree-vectorizer.c (update_phi_nodes_for_guard): Call reverse_phis. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 02b37fe078e..ada49ce5ecd 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -2708,23 +2708,26 @@ mask64_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) return 0; } -/* Like mask64_operand, but allow up to three transitions. This - predicate is used by insn patterns that generate two rldicl or - rldicr machine insns. */ - -int -mask64_2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +static int +mask64_1or2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED, + bool allow_one) { if (GET_CODE (op) == CONST_INT) { HOST_WIDE_INT c, lsb; - + bool one_ok; + c = INTVAL (op); /* Disallow all zeros. */ if (c == 0) return 0; + /* We can use a single rlwinm insn if no upper bits of C are set + AND there are zero, one or two transitions in the _whole_ of + C. */ + one_ok = !(c & ~(HOST_WIDE_INT)0xffffffff); + /* We don't change the number of transitions by inverting, so make sure we start with the LS bit zero. */ if (c & 1) @@ -2748,6 +2751,9 @@ mask64_2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) /* Erase second transition. */ c &= -lsb; + if (one_ok && !(allow_one || c)) + return 0; + /* Find the third transition (if any). */ lsb = c & -c; @@ -2757,6 +2763,14 @@ mask64_2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) return 0; } +/* Like mask64_operand, but allow up to three transitions. This + predicate is used by insn patterns that generate two rldicl or + rldicr machine insns. */ +int mask64_2_operand (rtx op, enum machine_mode mode) +{ + return mask64_1or2_operand (op, mode, false); +} + /* Generates shifts and masks for a pair of rldicl or rldicr insns to implement ANDing by the mask IN. */ void @@ -2846,9 +2860,9 @@ int and64_2_operand (rtx op, enum machine_mode mode) { if (fixed_regs[CR0_REGNO]) /* CR0 not available, don't do andi./andis. */ - return gpc_reg_operand (op, mode) || mask64_2_operand (op, mode); + return gpc_reg_operand (op, mode) || mask64_1or2_operand (op, mode, true); - return logical_operand (op, mode) || mask64_2_operand (op, mode); + return logical_operand (op, mode) || mask64_1or2_operand (op, mode, true); } /* Return 1 if the operand is either a non-special register or a diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 6b1c0b656cc..1902f5ddec0 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -7197,19 +7197,20 @@ "") (define_insn "anddi3" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r") - (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r") - (match_operand:DI 2 "and64_2_operand" "?r,S,K,J,t"))) - (clobber (match_scratch:CC 3 "=X,X,x,x,X"))] + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r") + (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r") + (match_operand:DI 2 "and64_2_operand" "?r,S,T,K,J,t"))) + (clobber (match_scratch:CC 3 "=X,X,X,x,x,X"))] "TARGET_POWERPC64" "@ and %0,%1,%2 rldic%B2 %0,%1,0,%S2 + rlwinm %0,%1,0,%m2,%M2 andi. %0,%1,%b2 andis. %0,%1,%u2 #" - [(set_attr "type" "*,*,compare,compare,*") - (set_attr "length" "4,4,4,4,8")]) + [(set_attr "type" "*,*,*,compare,compare,*") + (set_attr "length" "4,4,4,4,4,8")]) (define_split [(set (match_operand:DI 0 "gpc_reg_operand" "") @@ -7227,10 +7228,9 @@ (and:DI (rotate:DI (match_dup 0) (match_dup 6)) (match_dup 7)))] - " { build_mask64_2_operands (operands[2], &operands[4]); -}") +}) (define_insn "*anddi3_internal2" [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 64da733025f..776f8e4e448 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2004-11-11 Nathan Sidwell + PR target/16457 + * gcc.dg/ppc-and-1: New + PR target/16796 * gcc.dg/ppc-mov-1.c: New. diff --git a/gcc/testsuite/gcc.dg/ppc-and-1.c b/gcc/testsuite/gcc.dg/ppc-and-1.c new file mode 100644 index 00000000000..88a4b7a88cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/ppc-and-1.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target powerpc64-*-* } } */ +/* { dg-options "-m64 -O2" } */ + +/* { dg-final { scan-assembler "rlwinm \[0-9\]+,\[0-9\]+,0,0,30" } } */ +/* { dg-final { scan-assembler "rlwinm \[0-9\]+,\[0-9\]+,0,29,30" } } */ +/* { dg-final { scan-assembler-not "rldicr" } } */ + +/* Origin:Pete Steinmetz */ + +/* PR 16457 - use rlwinm insn. */ + +char *foo1 (char *p, unsigned int x) +{ + return p - (x & ~1); +} + +char *foo2 (char *p, unsigned int x) +{ + return p - (x & 6); +} -- 2.30.2