OSDN Git Service

Use cute tblgen tricks to make zap handling more powerful. Specifically,
authorChris Lattner <sabre@nondot.org>
Wed, 11 Oct 2006 05:13:56 +0000 (05:13 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 11 Oct 2006 05:13:56 +0000 (05:13 +0000)
when the dag combiner simplifies an and mask, notice this and allow those bits
to be missing from the zap mask.

This compiles Alpha/zapnot4.ll into:

        sll $16,3,$0
        zapnot $0,3,$0
        ret $31,($26),1

instead of:

        ldah $0,1($31)
        lda $0,-8($0)
        sll $16,3,$1
        and $1,$0,$0
        ret $31,($26),1

It would be *really* nice to replace the hunk of code in the
AlphaISelDAGToDAG.cpp file that matches (and (srl (x, C), c2) into
(SRL (ZAPNOTi)) with a similar pattern, but I've spent enough time poking
at alpha.  Make andrew will do this.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30875 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Alpha/AlphaISelDAGToDAG.cpp
lib/Target/Alpha/AlphaInstrInfo.td

index ed66592..51de4e6 100644 (file)
@@ -59,19 +59,57 @@ namespace {
       return x - get_ldah16(x) * IMM_MULT;
     }
 
+    /// get_zapImm - Return a zap mask if X is a valid immediate for a zapnot
+    /// instruction (if not, return 0).  Note that this code accepts partial
+    /// zap masks.  For example (and LHS, 1) is a valid zap, as long we know
+    /// that the bits 1-7 of LHS are already zero.  If LHS is non-null, we are
+    /// in checking mode.  If LHS is null, we assume that the mask has already
+    /// been validated before.
+    uint64_t get_zapImm(SDOperand LHS, uint64_t Constant) {
+      uint64_t BitsToCheck = 0;
+      unsigned Result = 0;
+      for (unsigned i = 0; i != 8; ++i) {
+        if (((Constant >> 8*i) & 0xFF) == 0) {
+          // nothing to do.
+        } else {
+          Result |= 1 << i;
+          if (((Constant >> 8*i) & 0xFF) == 0xFF) {
+            // If the entire byte is set, zapnot the byte.
+          } else if (LHS.Val == 0) {
+            // Otherwise, if the mask was previously validated, we know its okay
+            // to zapnot this entire byte even though all the bits aren't set.
+          } else {
+            // Otherwise we don't know that the it's okay to zapnot this entire
+            // byte.  Only do this iff we can prove that the missing bits are
+            // already null, so the bytezap doesn't need to really null them.
+            BitsToCheck |= ~Constant & (0xFF << 8*i);
+          }
+        }
+      }
+      
+      // If there are missing bits in a byte (for example, X & 0xEF00), check to
+      // see if the missing bits (0x1000) are already known zero if not, the zap
+      // isn't okay to do, as it won't clear all the required bits.
+      if (BitsToCheck &&
+          !getTargetLowering().MaskedValueIsZero(LHS, BitsToCheck))
+        return 0;
+      
+      return Result;
+    }
+    
     static uint64_t get_zapImm(uint64_t x) {
-      unsigned int build = 0;
-      for(int i = 0; i < 8; ++i)
-       {
-         if ((x & 0x00FF) == 0x00FF)
-           build |= 1 << i;
-         else if ((x & 0x00FF) != 0)
-           { build = 0; break; }
-         x >>= 8;
-       }
+      unsigned build = 0;
+      for(int i = 0; i != 8; ++i) {
+        if ((x & 0x00FF) == 0x00FF)
+          build |= 1 << i;
+        else if ((x & 0x00FF) != 0)
+          return 0;
+        x >>= 8;
+      }
       return build;
     }
-
+      
+    
     static uint64_t getNearPower2(uint64_t x) {
       if (!x) return 0;
       unsigned at = CountLeadingZeros_64(x);
@@ -380,10 +418,11 @@ SDNode *AlphaDAGToDAGISel::Select(SDOperand Op) {
       {
        uint64_t sval = SC->getValue();
        uint64_t mval = MC->getValue();
-       if (get_zapImm(mval)) //the result is a zap, let the autogened stuff deal
+        // If the result is a zap, let the autogened stuff handle it.
+       if (get_zapImm(N->getOperand(0), mval))
          break;
-       // given mask X, and shift S, we want to see if there is any zap in the mask
-       // if we play around with the botton S bits
+       // given mask X, and shift S, we want to see if there is any zap in the
+        // mask if we play around with the botton S bits
        uint64_t dontcare = (~0ULL) >> (64 - sval);
        uint64_t mask = mval << sval;
 
index d63d0ba..3f897a7 100644 (file)
@@ -59,8 +59,9 @@ def LL16 : SDNodeXForm<imm, [{ //lda part of constant
 def LH16 : SDNodeXForm<imm, [{ //ldah part of constant (or more if too big)
   return getI64Imm(get_ldah16(N->getValue()));
 }]>;
-def iZAPX : SDNodeXForm<imm, [{ // get imm to ZAPi
-  return getI64Imm(get_zapImm((uint64_t)N->getValue()));
+def iZAPX : SDNodeXForm<and, [{ // get imm to ZAPi
+  ConstantSDNode *RHS = cast<ConstantSDNode>(N->getOperand(1));
+  return getI64Imm(get_zapImm(SDOperand(), RHS->getValue()));
 }]>;
 def nearP2X : SDNodeXForm<imm, [{
   return getI64Imm(Log2_64(getNearPower2((uint64_t)N->getValue())));
@@ -85,10 +86,15 @@ def immSExt16  : PatLeaf<(imm), [{ //imm fits in 16 bit sign extended field
 def immSExt16int  : PatLeaf<(imm), [{ //(int)imm fits in a 16 bit sign extended field
   return ((int64_t)N->getValue() << 48) >> 48 == ((int64_t)N->getValue() << 32) >> 32;
 }], SExt16>;
-def immZAP  : PatLeaf<(imm), [{ //imm is good for zapi
-  uint64_t build = get_zapImm((uint64_t)N->getValue());
-  return build != 0;
-}], iZAPX>;
+
+def zappat : PatFrag<(ops node:$LHS), (and node:$LHS, imm:$L), [{
+  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
+    uint64_t build = get_zapImm(N->getOperand(0), (uint64_t)RHS->getValue());
+    return build != 0;
+  }
+  return false;
+}]>;
+
 def immFPZ  : PatLeaf<(fpimm), [{ //the only fpconstant nodes are +/- 0.0
   return true;
 }]>;
@@ -386,8 +392,12 @@ def XOR      : OForm< 0x11, 0x40, "xor $RA,$RB,$RC",
 def XORi     : OFormL<0x11, 0x40, "xor $RA,$L,$RC",
                       [(set GPRC:$RC, (xor GPRC:$RA, immUExt8:$L))], s_ilog>;
                       
-def ZAPNOTi  : OFormL<0x12, 0x31, "zapnot $RA,$L,$RC", 
-                      [(set GPRC:$RC, (and GPRC:$RA, immZAP:$L))], s_ishf>; 
+def ZAPNOTi  : OFormL<0x12, 0x31, "zapnot $RA,$L,$RC", [], s_ishf>;
+
+// Define the pattern that produces ZAPNOTi.
+def : Pat<(i64 (zappat GPRC:$RA):$imm),
+          (ZAPNOTi GPRC:$RA, (iZAPX GPRC:$imm))>;
+
 
 //Comparison, int
 //So this is a waste of what this instruction can do, but it still saves something