[llvm-commits] [llvm] r97651 - in /llvm/trunk: include/llvm/CodeGen/SelectionDAGISel.h lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Chris Lattner sabre at nondot.org
Tue Mar 2 23:31:15 PST 2010


Author: lattner
Date: Wed Mar  3 01:31:15 2010
New Revision: 97651

URL: http://llvm.org/viewvc/llvm-project?rev=97651&view=rev
Log:
speed up scope node processing: if the first element of a scope
entry we're about to process is obviously going to fail, don't
bother pushing a scope only to have it immediately be popped.
This avoids a lot of scope stack traffic in common cases.

Unfortunately, this requires duplicating some of the predicate
dispatch.  To avoid duplicating the actual logic I pulled each
predicate out to its own static function which gets used in
both places.

Modified:
    llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h?rev=97651&r1=97650&r2=97651&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h Wed Mar  3 01:31:15 2010
@@ -227,6 +227,8 @@
   /// by tblgen.  Others should not call it.
   void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops);
 
+  
+public:
   // Calls to these predicates are generated by tblgen.
   bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS,
                     int64_t DesiredMaskS) const;
@@ -263,15 +265,16 @@
     return SDValue();
   }
 
+  SDNode *SelectCodeCommon(SDNode *NodeToMatch,
+                           const unsigned char *MatcherTable,
+                           unsigned TableSize);
+  
+private:
   
   // Calls to these functions are generated by tblgen.
   SDNode *Select_INLINEASM(SDNode *N);
   SDNode *Select_UNDEF(SDNode *N);
   SDNode *Select_EH_LABEL(SDNode *N);
-  
-  SDNode *SelectCodeCommon(SDNode *NodeToMatch,
-                           const unsigned char *MatcherTable,
-                           unsigned TableSize);
   void CannotYetSelect(SDNode *N);
   void CannotYetSelectIntrinsic(SDNode *N);
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=97651&r1=97650&r2=97651&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Wed Mar  3 01:31:15 2010
@@ -1845,6 +1845,94 @@
   return Res;
 }
 
+/// CheckPatternPredicate - Implements OP_CheckPatternPredicate.
+ALWAYS_INLINE static bool
+CheckPatternPredicate(const unsigned char *MatcherTable, unsigned &MatcherIndex,
+                      SelectionDAGISel &SDISel) {
+  return SDISel.CheckPatternPredicate(MatcherTable[MatcherIndex++]);
+}
+
+/// CheckNodePredicate - Implements OP_CheckNodePredicate.
+ALWAYS_INLINE static bool
+CheckNodePredicate(const unsigned char *MatcherTable, unsigned &MatcherIndex,
+                   SelectionDAGISel &SDISel, SDNode *N) {
+  return SDISel.CheckNodePredicate(N, MatcherTable[MatcherIndex++]);
+}
+
+ALWAYS_INLINE static bool
+CheckOpcode(const unsigned char *MatcherTable, unsigned &MatcherIndex,
+            SDNode *N) {
+  return N->getOpcode() == MatcherTable[MatcherIndex++];
+}
+
+ALWAYS_INLINE static bool
+CheckType(const unsigned char *MatcherTable, unsigned &MatcherIndex,
+          SDValue N, const TargetLowering &TLI) {
+  MVT::SimpleValueType VT = (MVT::SimpleValueType)MatcherTable[MatcherIndex++];
+  if (N.getValueType() == VT) return true;
+  
+  // Handle the case when VT is iPTR.
+  return VT == MVT::iPTR && N.getValueType() == TLI.getPointerTy();
+}
+
+ALWAYS_INLINE static bool
+CheckInteger(const unsigned char *MatcherTable, unsigned &MatcherIndex,
+             SDValue N) {
+  int64_t Val = MatcherTable[MatcherIndex++];
+  if (Val & 128)
+    Val = GetVBR(Val, MatcherTable, MatcherIndex);
+  
+  ConstantSDNode *C = dyn_cast<ConstantSDNode>(N);
+  return C != 0 && C->getSExtValue() == Val;
+}
+
+/// IsPredicateKnownToFail - If we know how and can do so without pushing a
+/// scope, evaluate the current node.  If the current predicate is known to
+/// fail, set Result=true and return anything.  If the current predicate is
+/// known to pass, set Result=false and return the MatcherIndex to continue
+/// with.  If the current predicate is unknown, set Result=false and return the
+/// MatcherIndex to continue with. 
+static unsigned IsPredicateKnownToFail(const unsigned char *Table,
+                                       unsigned Index, SDValue N,
+                                       bool &Result, SelectionDAGISel &SDISel) {
+  switch (Table[Index++]) {
+  default:
+    Result = false;
+    return Index-1;  // Could not evaluate this predicate.
+  
+  case SelectionDAGISel::OPC_CheckPatternPredicate:
+    Result = !CheckPatternPredicate(Table, Index, SDISel);
+    return Index;
+  case SelectionDAGISel::OPC_CheckPredicate:
+    Result = !CheckNodePredicate(Table, Index, SDISel, N.getNode());
+    return Index;
+  case SelectionDAGISel::OPC_CheckOpcode:
+    Result = !::CheckOpcode(Table, Index, N.getNode());
+    return Index;
+  case SelectionDAGISel::OPC_CheckType:
+    Result = !::CheckType(Table, Index, N, SDISel.TLI);
+    return Index;
+  case SelectionDAGISel::OPC_CheckChild0Type:
+  case SelectionDAGISel::OPC_CheckChild1Type:
+  case SelectionDAGISel::OPC_CheckChild2Type:
+  case SelectionDAGISel::OPC_CheckChild3Type:
+  case SelectionDAGISel::OPC_CheckChild4Type:
+  case SelectionDAGISel::OPC_CheckChild5Type:
+  case SelectionDAGISel::OPC_CheckChild6Type:
+  case SelectionDAGISel::OPC_CheckChild7Type: {
+    unsigned ChildNo = Table[Index-1] - SelectionDAGISel::OPC_CheckChild0Type;
+    if (ChildNo >= N.getNumOperands())
+      Result = true;  // Match fails if out of range child #.
+    else
+      Result = !::CheckType(Table, Index, N.getOperand(ChildNo), SDISel.TLI);
+    return Index;
+  }
+  case SelectionDAGISel::OPC_CheckInteger:
+    Result = !::CheckInteger(Table, Index, N);
+    return Index;
+  }
+}
+
 
 struct MatchScope {
   /// FailIndex - If this match fails, this is the index to continue with.
@@ -1978,16 +2066,50 @@
     BuiltinOpcodes Opcode = (BuiltinOpcodes)MatcherTable[MatcherIndex++];
     switch (Opcode) {
     case OPC_Scope: {
-      unsigned NumToSkip = MatcherTable[MatcherIndex++];
-      if (NumToSkip & 128)
-        NumToSkip = GetVBR(NumToSkip, MatcherTable, MatcherIndex);
-      assert(NumToSkip != 0 &&
-             "First entry of OPC_Scope shouldn't be 0, scope has no children?");
+      // Okay, the semantics of this operation are that we should push a scope
+      // then evaluate the first child.  However, pushing a scope only to have
+      // the first check fail (which then pops it) is inefficient.  If we can
+      // determine immediately that the first check (or first several) will
+      // immediately fail, don't even bother pushing a scope for them.
+      unsigned FailIndex;
+      
+      while (1) {
+        unsigned NumToSkip = MatcherTable[MatcherIndex++];
+        if (NumToSkip & 128)
+          NumToSkip = GetVBR(NumToSkip, MatcherTable, MatcherIndex);
+        // Found the end of the scope with no match.
+        if (NumToSkip == 0) {
+          FailIndex = 0;
+          break;
+        }
+        
+        FailIndex = MatcherIndex+NumToSkip;
+        
+        // If we can't evaluate this predicate without pushing a scope (e.g. if
+        // it is a 'MoveParent') or if the predicate succeeds on this node, we
+        // push the scope and evaluate the full predicate chain.
+        bool Result;
+        MatcherIndex = IsPredicateKnownToFail(MatcherTable, MatcherIndex, N,
+                                              Result, *this);
+        if (!Result)
+          break;
+        
+        DEBUG(errs() << "  Skipped scope entry at index " << MatcherIndex
+              << " continuing at " << FailIndex << "\n");
 
+        
+        // Otherwise, we know that this case of the Scope is guaranteed to fail,
+        // move to the next case.
+        MatcherIndex = FailIndex;
+      }
+      
+      // If the whole scope failed to match, bail.
+      if (FailIndex == 0) break;
+      
       // Push a MatchScope which indicates where to go if the first child fails
       // to match.
       MatchScope NewEntry;
-      NewEntry.FailIndex = MatcherIndex+NumToSkip;
+      NewEntry.FailIndex = FailIndex;
       NewEntry.NodeStack.append(NodeStack.begin(), NodeStack.end());
       NewEntry.NumRecordedNodes = RecordedNodes.size();
       NewEntry.NumMatchedMemRefs = MatchedMemRefs.size();
@@ -2049,10 +2171,12 @@
       continue;
     }
     case OPC_CheckPatternPredicate:
-      if (!CheckPatternPredicate(MatcherTable[MatcherIndex++])) break;
+      if (!::CheckPatternPredicate(MatcherTable, MatcherIndex, *this)) break;
       continue;
     case OPC_CheckPredicate:
-      if (!CheckNodePredicate(N.getNode(), MatcherTable[MatcherIndex++])) break;
+      if (!::CheckNodePredicate(MatcherTable, MatcherIndex, *this,
+                                N.getNode()))
+        break;
       continue;
     case OPC_CheckComplexPat:
       if (!CheckComplexPattern(NodeToMatch, N, 
@@ -2060,7 +2184,11 @@
         break;
       continue;
     case OPC_CheckOpcode:
-      if (N->getOpcode() != MatcherTable[MatcherIndex++]) break;
+      if (!::CheckOpcode(MatcherTable, MatcherIndex, N.getNode())) break;
+      continue;
+        
+    case OPC_CheckType:
+      if (!::CheckType(MatcherTable, MatcherIndex, N, TLI)) break;
       continue;
         
     case OPC_SwitchOpcode: {
@@ -2091,17 +2219,6 @@
       continue;
     }
         
-    case OPC_CheckType: {
-      MVT::SimpleValueType VT =
-        (MVT::SimpleValueType)MatcherTable[MatcherIndex++];
-      if (N.getValueType() != VT) {
-        // Handle the case when VT is iPTR.
-        if (VT != MVT::iPTR || N.getValueType() != TLI.getPointerTy())
-          break;
-      }
-      continue;
-    }
-        
     case OPC_SwitchType: {
       MVT::SimpleValueType CurNodeVT = N.getValueType().getSimpleVT().SimpleTy;
       unsigned SwitchStart = MatcherIndex-1; (void)SwitchStart;
@@ -2141,15 +2258,8 @@
       unsigned ChildNo = Opcode-OPC_CheckChild0Type;
       if (ChildNo >= N.getNumOperands())
         break;  // Match fails if out of range child #.
-      
-      MVT::SimpleValueType VT =
-        (MVT::SimpleValueType)MatcherTable[MatcherIndex++];
-      EVT ChildVT = N.getOperand(ChildNo).getValueType();
-      if (ChildVT != VT) {
-        // Handle the case when VT is iPTR.
-        if (VT != MVT::iPTR || ChildVT != TLI.getPointerTy())
-          break;
-      }
+      if (!::CheckType(MatcherTable, MatcherIndex, N.getOperand(ChildNo), TLI))
+        break;
       continue;
     }
     case OPC_CheckCondCode:
@@ -2166,16 +2276,9 @@
       }
       continue;
     }
-    case OPC_CheckInteger: {
-      int64_t Val = MatcherTable[MatcherIndex++];
-      if (Val & 128)
-        Val = GetVBR(Val, MatcherTable, MatcherIndex);
-      
-      ConstantSDNode *C = dyn_cast<ConstantSDNode>(N);
-      if (C == 0 || C->getSExtValue() != Val)
-        break;
+    case OPC_CheckInteger:
+      if (!::CheckInteger(MatcherTable, MatcherIndex, N)) break;
       continue;
-    }        
     case OPC_CheckAndImm: {
       int64_t Val = MatcherTable[MatcherIndex++];
       if (Val & 128)





More information about the llvm-commits mailing list