re PR target/16457 (PowerPC - Combine two rldicr instructions into a single rlwinm.)
authorNathan Sidwell <nathan@codesourcery.com>
Thu, 11 Nov 2004 17:03:36 +0000 (17:03 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 11 Nov 2004 17:03:36 +0000 (17:03 +0000)
.: 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
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/ppc-and-1.c [new file with mode: 0644]

index accb4dedeb8bd1745c7074bb82ce07c29f7eca38..21599f4ac204ccbc4e1ab8f7e806a4702f30e236 100644 (file)
@@ -1,3 +1,13 @@
+2004-11-11  Nathan Sidwell  <nathan@codesourcery.com>
+
+       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  <dorit@il.ibm.com>
 
        * tree-vectorizer.c (update_phi_nodes_for_guard): Call reverse_phis.
index 02b37fe078e3c6ff7c3b84c6118ff34223fc5340..ada49ce5ecdba802f051ef9e6cb4a7302ff65aef 100644 (file)
@@ -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
index 6b1c0b656ccf7b91b13093fdb3aa6f84c96ef6ed..1902f5ddec092e56b7e3e33d3f94afe87fcfd867 100644 (file)
   "")
 
 (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" "")
        (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")
index 64da733025fb6ad5bed2888c50bdd72314eec342..776f8e4e4480e68f7e6379da85a8e63cb36da419 100644 (file)
@@ -1,5 +1,8 @@
 2004-11-11  Nathan Sidwell  <nathan@codesourcery.com>
 
+       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 (file)
index 0000000..88a4b7a
--- /dev/null
@@ -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 <steinmtz@us.ibm.com> */
+
+/* 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);
+}