From 5a1df389a675c8f9bb73afc95132751508e24762 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 24 Mar 2006 23:10:39 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27090 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/DAGISelEmitter.cpp | 105 +++++++++++++++++++----------- utils/TableGen/DAGISelEmitter.h | 27 ++++++++ 2 files changed, 94 insertions(+), 38 deletions(-) diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index b053dbddc17..aba54284f95 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -594,6 +594,7 @@ static std::vector getIntrinsicType(Record *R, bool NotRegisters, /// 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(getLeafValue())) { // If it's a regclass or something else known, include the type. @@ -636,8 +637,34 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { 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(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 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { 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 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { "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 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { 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 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { 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 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { // 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 Children; @@ -887,6 +894,29 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { } } + // If the operator is an intrinsic, then this is just syntactic sugar for for + // (intrinsic_* , ..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 @@ void DAGISelEmitter::ParseNodeInfo() { 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 @@ static void GenerateVariantsOf(TreePatternNode *N, } // 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 MaximalChildren; GatherChildrenOfAssociativeOpcode(N, MaximalChildren); @@ -1686,7 +1718,7 @@ static void GenerateVariantsOf(TreePatternNode *N, 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 @@ static void RemoveAllTypes(TreePatternNode *N) { 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 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) { for (std::map, 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 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) { for (std::map, 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())), ' ') diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h index 10b997d92a3..8ed66be800a 100644 --- a/utils/TableGen/DAGISelEmitter.h +++ b/utils/TableGen/DAGISelEmitter.h @@ -421,6 +421,10 @@ private: std::map PatternFragments; std::map 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 @@ public: 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 @@ public: 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);