[llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h

Chris Lattner lattner at cs.uiuc.edu
Fri Mar 24 15:10:52 PST 2006



Changes in directory llvm/utils/TableGen:

DAGISelEmitter.cpp updated: 1.185 -> 1.186
DAGISelEmitter.h updated: 1.60 -> 1.61
---
Log message:

Change approach so that we get codegen for free for intrinsics.  With this,
intrinsics that don't take pointer arguments now work.  For example, we can 
compile this:

int test3( __m128d *A) {
  return _mm_movemask_pd(*A);
}
int test4( __m128 *A) {
  return _mm_movemask_ps(*A);
}

to this:

_test3:
        movl 4(%esp), %eax
        movapd (%eax), %xmm0
        movmskpd %xmm0, %eax
        ret
_test4:
        movl 4(%esp), %eax
        movaps (%eax), %xmm0
        movmskps %xmm0, %eax
        ret



---
Diffs of the changes:  (+94 -38)

 DAGISelEmitter.cpp |  105 +++++++++++++++++++++++++++++++++--------------------
 DAGISelEmitter.h   |   27 +++++++++++++
 2 files changed, 94 insertions(+), 38 deletions(-)


Index: llvm/utils/TableGen/DAGISelEmitter.cpp
diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.185 llvm/utils/TableGen/DAGISelEmitter.cpp:1.186
--- llvm/utils/TableGen/DAGISelEmitter.cpp:1.185	Fri Mar 24 15:52:20 2006
+++ llvm/utils/TableGen/DAGISelEmitter.cpp	Fri Mar 24 17:10:39 2006
@@ -594,6 +594,7 @@
 /// change, false otherwise.  If a type contradiction is found, throw an
 /// exception.
 bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
+  DAGISelEmitter &ISE = TP.getDAGISelEmitter();
   if (isLeaf()) {
     if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue())) {
       // If it's a regclass or something else known, include the type.
@@ -636,8 +637,34 @@
     MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getExtTypes(), TP);
     MadeChange |= UpdateNodeType(MVT::isVoid, TP);
     return MadeChange;
+  } else if (getOperator() == ISE.get_intrinsic_void_sdnode() ||
+             getOperator() == ISE.get_intrinsic_w_chain_sdnode() ||
+             getOperator() == ISE.get_intrinsic_wo_chain_sdnode()) {
+    unsigned IID = 
+    dynamic_cast<IntInit*>(getChild(0)->getLeafValue())->getValue();
+    const CodeGenIntrinsic &Int = ISE.getIntrinsicInfo(IID);
+    bool MadeChange = false;
+    
+    // Apply the result type to the node.
+    MadeChange = UpdateNodeType(Int.ArgVTs[0], TP);
+    
+    if (getNumChildren() != Int.ArgVTs.size())
+      TP.error("Intrinsic '" + getOperator()->getName() + " expects " +
+               utostr(Int.ArgVTs.size()-1) + " operands, not " +
+               utostr(getNumChildren()-1) + " operands!");
+
+    // Apply type info to the intrinsic ID.
+    MVT::ValueType PtrTy = ISE.getTargetInfo().getPointerType();
+    MadeChange |= getChild(0)->UpdateNodeType(PtrTy, TP);
+    
+    for (unsigned i = 1, e = getNumChildren(); i != e; ++i) {
+      MVT::ValueType OpVT = Int.ArgVTs[i];
+      MadeChange |= getChild(i)->UpdateNodeType(OpVT, TP);
+      MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
+    }
+    return MadeChange;
   } else if (getOperator()->isSubClassOf("SDNode")) {
-    const SDNodeInfo &NI = TP.getDAGISelEmitter().getSDNodeInfo(getOperator());
+    const SDNodeInfo &NI = ISE.getSDNodeInfo(getOperator());
     
     bool MadeChange = NI.ApplyTypeConstraints(this, TP);
     for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
@@ -648,8 +675,7 @@
       MadeChange |= UpdateNodeType(MVT::isVoid, TP);
     return MadeChange;  
   } else if (getOperator()->isSubClassOf("Instruction")) {
-    const DAGInstruction &Inst =
-      TP.getDAGISelEmitter().getInstruction(getOperator());
+    const DAGInstruction &Inst = ISE.getInstruction(getOperator());
     bool MadeChange = false;
     unsigned NumResults = Inst.getNumResults();
     
@@ -664,7 +690,7 @@
              "Operands should be register classes!");
 
       const CodeGenRegisterClass &RC = 
-        TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(ResultNode);
+        ISE.getTargetInfo().getRegisterClass(ResultNode);
       MadeChange = UpdateNodeType(ConvertVTs(RC.getValueTypes()), TP);
     }
 
@@ -677,7 +703,7 @@
       MVT::ValueType VT;
       if (OperandNode->isSubClassOf("RegisterClass")) {
         const CodeGenRegisterClass &RC = 
-          TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(OperandNode);
+          ISE.getTargetInfo().getRegisterClass(OperandNode);
         //VT = RC.getValueTypeNum(0);
         MadeChange |=getChild(i)->UpdateNodeType(ConvertVTs(RC.getValueTypes()),
                                                  TP);
@@ -691,25 +717,6 @@
       MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
     }
     return MadeChange;
-  } else if (getOperator()->isSubClassOf("Intrinsic")) {
-    const CodeGenIntrinsic &Int = 
-      TP.getDAGISelEmitter().getIntrinsic(getOperator());
-    // FIXME: get type information! 
-    bool MadeChange = false;
-
-    // Apply the result type to the node.
-    MadeChange = UpdateNodeType(Int.ArgVTs[0], TP);
-    
-    if (getNumChildren() != Int.ArgVTs.size()-1)
-      TP.error("Intrinsic '" + getOperator()->getName() + " expects " +
-               utostr(Int.ArgVTs.size()-1) + " operands, not " +
-               utostr(getNumChildren()) + " operands!");
-    for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
-      MVT::ValueType OpVT = Int.ArgVTs[i+1];
-      MadeChange |= getChild(i)->UpdateNodeType(OpVT, TP);
-      MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
-    }
-    return MadeChange;
   } else {
     assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
     
@@ -843,7 +850,7 @@
   
   //  Check to see if this is something that is illegal in an input pattern.
   if (isInputPattern && (Operator->isSubClassOf("Instruction") ||
-      Operator->isSubClassOf("SDNodeXForm")))
+                         Operator->isSubClassOf("SDNodeXForm")))
     error("Cannot use '" + Operator->getName() + "' in an input pattern!");
   
   std::vector<TreePatternNode*> Children;
@@ -887,6 +894,29 @@
     }
   }
   
+  // If the operator is an intrinsic, then this is just syntactic sugar for for
+  // (intrinsic_* <number>, ..children..).  Pick the right intrinsic node, and 
+  // convert the intrinsic name to a number.
+  if (Operator->isSubClassOf("Intrinsic")) {
+    const CodeGenIntrinsic &Int = getDAGISelEmitter().getIntrinsic(Operator);
+    unsigned IID = getDAGISelEmitter().getIntrinsicID(Operator)+1;
+
+    // If this intrinsic returns void, it must have side-effects and thus a
+    // chain.
+    if (Int.ArgVTs[0] == MVT::isVoid) {
+      Operator = getDAGISelEmitter().get_intrinsic_void_sdnode();
+    } else if (Int.ModRef != CodeGenIntrinsic::NoMem) {
+      // Has side-effects, requires chain.
+      Operator = getDAGISelEmitter().get_intrinsic_w_chain_sdnode();
+    } else {
+      // Otherwise, no chain.
+      Operator = getDAGISelEmitter().get_intrinsic_wo_chain_sdnode();
+    }
+    
+    TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID));
+    Children.insert(Children.begin(), IIDNode);
+  }
+  
   return new TreePatternNode(Operator, Children);
 }
 
@@ -944,6 +974,11 @@
     SDNodes.insert(std::make_pair(Nodes.back(), Nodes.back()));
     Nodes.pop_back();
   }
+
+  // Get the buildin intrinsic nodes.
+  intrinsic_void_sdnode     = getSDNodeNamed("intrinsic_void");
+  intrinsic_w_chain_sdnode  = getSDNodeNamed("intrinsic_w_chain");
+  intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain");
 }
 
 /// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms
@@ -1619,13 +1654,10 @@
   }
 
   // Look up interesting info about the node.
-  const SDNodeInfo *NodeInfo = 0;
-  
-  if (!N->getOperator()->isSubClassOf("Intrinsic"))
-    NodeInfo = &ISE.getSDNodeInfo(N->getOperator());
+  const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(N->getOperator());
 
   // If this node is associative, reassociate.
-  if (NodeInfo && NodeInfo->hasProperty(SDNodeInfo::SDNPAssociative)) {
+  if (NodeInfo.hasProperty(SDNodeInfo::SDNPAssociative)) {
     // Reassociate by pulling together all of the linked operators 
     std::vector<TreePatternNode*> MaximalChildren;
     GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
@@ -1686,7 +1718,7 @@
   CombineChildVariants(N, ChildVariants, OutVariants, ISE);
 
   // If this node is commutative, consider the commuted order.
-  if (NodeInfo && NodeInfo->hasProperty(SDNodeInfo::SDNPCommutative)) {
+  if (NodeInfo.hasProperty(SDNodeInfo::SDNPCommutative)) {
     assert(N->getNumChildren()==2 &&"Commutative but doesn't have 2 children!");
     // Consider the commuted order.
     CombineChildVariants(N, ChildVariants[1], ChildVariants[0],
@@ -1886,7 +1918,10 @@
 
 Record *DAGISelEmitter::getSDNodeNamed(const std::string &Name) const {
   Record *N = Records.getDef(Name);
-  assert(N && N->isSubClassOf("SDNode") && "Bad argument");
+  if (!N || !N->isSubClassOf("SDNode")) {
+    std::cerr << "Error getting SDNode '" << Name << "'!\n";
+    exit(1);
+  }
   return N;
 }
 
@@ -2986,9 +3021,6 @@
   for (std::map<Record*, std::vector<PatternToMatch*>,
        CompareByRecordName>::iterator PBOI = PatternsByOpcode.begin(),
        E = PatternsByOpcode.end(); PBOI != E; ++PBOI) {
-    if (PBOI->first->isSubClassOf("Intrinsic"))
-      continue;   // Skip intrinsics here.
-    
     const std::string &OpName = PBOI->first->getName();
     OS << "void Select_" << OpName << "(SDOperand &Result, SDOperand N) {\n";
     
@@ -3235,9 +3267,6 @@
   for (std::map<Record*, std::vector<PatternToMatch*>,
                 CompareByRecordName>::iterator PBOI = PatternsByOpcode.begin(),
        E = PatternsByOpcode.end(); PBOI != E; ++PBOI) {
-    if (PBOI->first->isSubClassOf("Intrinsic"))
-      continue;
-    
     const SDNodeInfo &OpcodeInfo = getSDNodeInfo(PBOI->first);
     OS << "  case " << OpcodeInfo.getEnumName() << ": "
        << std::string(std::max(0, int(24-OpcodeInfo.getEnumName().size())), ' ')


Index: llvm/utils/TableGen/DAGISelEmitter.h
diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.60 llvm/utils/TableGen/DAGISelEmitter.h:1.61
--- llvm/utils/TableGen/DAGISelEmitter.h:1.60	Fri Mar 24 15:48:51 2006
+++ llvm/utils/TableGen/DAGISelEmitter.h	Fri Mar 24 17:10:39 2006
@@ -421,6 +421,10 @@
   std::map<Record*, TreePattern*> PatternFragments;
   std::map<Record*, DAGInstruction> Instructions;
   
+  // Specific SDNode definitions:
+  Record *intrinsic_void_sdnode;
+  Record *intrinsic_w_chain_sdnode, *intrinsic_wo_chain_sdnode;
+  
   /// PatternsToMatch - All of the things we are matching on the DAG.  The first
   /// value is the pattern to match, the second pattern is the result to
   /// emit.
@@ -457,6 +461,18 @@
     abort();
   }
   
+  const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const {
+    assert(IID-1 < Intrinsics.size() && "Bad intrinsic ID!");
+    return Intrinsics[IID-1];
+  }
+  
+  unsigned getIntrinsicID(Record *R) const {
+    for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
+      if (Intrinsics[i].TheDef == R) return i;
+    assert(0 && "Unknown intrinsic!");
+    abort();
+  }
+  
   TreePattern *getPatternFragment(Record *R) const {
     assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
     return PatternFragments.find(R)->second;
@@ -467,6 +483,17 @@
     return Instructions.find(R)->second;
   }
   
+  Record *get_intrinsic_void_sdnode() const {
+    return intrinsic_void_sdnode;
+  }
+  Record *get_intrinsic_w_chain_sdnode() const {
+    return intrinsic_w_chain_sdnode;
+  }
+  Record *get_intrinsic_wo_chain_sdnode() const {
+    return intrinsic_wo_chain_sdnode;
+  }
+
+  
 private:
   void ParseNodeInfo();
   void ParseNodeTransforms(std::ostream &OS);






More information about the llvm-commits mailing list