3.4.4.3.5. OPC_MorphNodeTo等
下面的OPC_EmitCopyToReg表示将值拷贝到一个物理寄存器的一个操作,3081行通过目标机器SelectionDAG实例的getCopyToReg()方法在Chain与glue的链上插入CopyToReg的节点。3093行的RunSDNodeXForm()是前面为目标机器生成的执行SDNodeXForm所代表操作的方法。
SelectionDAGISel::SelectCodeCommon(续)
3073 case OPC_EmitCopyToReg: {
3074 unsigned RecNo = MatcherTable[MatcherIndex++];
3075 assert(RecNo < RecordedNodes.size() && "Invalid EmitCopyToReg");
3076 unsigned DestPhysReg = MatcherTable[MatcherIndex++];
3077
3078 if (!InputChain.getNode())
3079 InputChain = CurDAG->getEntryNode();
3080
3081 InputChain = CurDAG->getCopyToReg(InputChain, SDLoc(NodeToMatch),
3082 DestPhysReg, RecordedNodes[RecNo].first,
3083 InputGlue);
3084
3085 InputGlue = InputChain.getValue(1);
3086 continue;
3087 }
3088
3089 case OPC_EmitNodeXForm: {
3090 unsigned XFormNo = MatcherTable[MatcherIndex++];
3091 unsigned RecNo = MatcherTable[MatcherIndex++];
3092 assert(RecNo < RecordedNodes.size() && "Invalid EmitNodeXForm");
3093 SDValue Res = RunSDNodeXForm(RecordedNodes[RecNo].first, XFormNo);
3094 RecordedNodes.push_back(std::pair<SDValue,SDNode*>(Res, nullptr));
3095 continue;
3096 }
case OPC_Coverage: { <- v7.0增加
// This is emitted right before MorphNode/EmitNode.
// So it should be safe to assume that this node has been selected
unsigned index = MatcherTable[MatcherIndex++];
index |= (MatcherTable[MatcherIndex++] << 8);
dbgs() << "COVERED: " << getPatternForIndex(index) << "\n";
dbgs() << "INCLUDED: " << getIncludePathForIndex(index) << "\n";
continue;
}
3097
3098 case OPC_EmitNode:
3099 case OPC_MorphNodeTo: {
case OPC_EmitNode0: case OPC_EmitNode1: case OPC_EmitNode2: <- v7.0增加
case OPC_MorphNodeTo0: case OPC_MorphNodeTo1: case OPC_MorphNodeTo2: {
3100 uint16_t TargetOpc = MatcherTable[MatcherIndex++];
3101 TargetOpc |= (unsigned short)MatcherTable[MatcherIndex++] << 8;
3102 unsigned EmitNodeInfo = MatcherTable[MatcherIndex++];
3103 // Get the result VT list.
3104 unsigned NumVTs = MatcherTable[MatcherIndex++]; <- v7.0删除
unsigned NumVTs; <- v7.0增加
// If this is one of the compressed forms, get the number of VTs based
// on the Opcode. Otherwise read the next byte from the table.
if (Opcode >= OPC_MorphNodeTo0 && Opcode <= OPC_MorphNodeTo2)
NumVTs = Opcode - OPC_MorphNodeTo0;
else if (Opcode >= OPC_EmitNode0 && Opcode <= OPC_EmitNode2)
NumVTs = Opcode - OPC_EmitNode0;
else
NumVTs = MatcherTable[MatcherIndex++];
3105 SmallVector<EVT, 4> VTs;
3106 for (unsigned i = 0; i != NumVTs; ++i) {
3107 MVT::SimpleValueType VT =
3108 (MVT::SimpleValueType)MatcherTable[MatcherIndex++];
3109 if (VT == MVT::iPTR)
3110 VT = TLI->getPointerTy(CurDAG->getDataLayout()).SimpleTy;
3111 VTs.push_back(VT);
3112 }
3113
3114 if (EmitNodeInfo & OPFL_Chain)
3115 VTs.push_back(MVT::Other);
3116 if (EmitNodeInfo & OPFL_GlueOutput)
3117 VTs.push_back(MVT::Glue);
3118
3119 // This is hot code, so optimize the two most common cases of 1 and 2
3120 // results.
3121 SDVTList VTList;
3122 if (VTs.size() == 1)
3123 VTList = CurDAG->getVTList(VTs[0]);
3124 else if (VTs.size() == 2)
3125 VTList = CurDAG->getVTList(VTs[0], VTs[1]);
3126 else
3127 VTList = CurDAG->getVTList(VTs);
3128
3129 // Get the operand list.
3130 unsigned NumOps = MatcherTable[MatcherIndex++];
3131 SmallVector<SDValue, 8> Ops;
3132 for (unsigned i = 0; i != NumOps; ++i) {
3133 unsigned RecNo = MatcherTable[MatcherIndex++];
3134 if (RecNo & 128)
3135 RecNo = GetVBR(RecNo, MatcherTable, MatcherIndex);
3136
3137 assert(RecNo < RecordedNodes.size() && "Invalid EmitNode");
3138 Ops.push_back(RecordedNodes[RecNo].first);
3139 }
3140
3141 // If there are variadic operands to add, handle them now.
3142 if (EmitNodeInfo & OPFL_VariadicInfo) {
3143 // Determine the start index to copy from.
3144 unsigned FirstOpToCopy = getNumFixedFromVariadicInfo(EmitNodeInfo);
3145 FirstOpToCopy += (EmitNodeInfo & OPFL_Chain) ? 1 : 0;
3146 assert(NodeToMatch->getNumOperands() >= FirstOpToCopy &&
3147 "Invalid variadic node");
3148 // Copy all of the variadic operands, not including a potential glue
3149 // input.
3150 for (unsigned i = FirstOpToCopy, e = NodeToMatch->getNumOperands();
3151 i != e; ++i) {
3152 SDValue V = NodeToMatch->getOperand(i);
3153 if (V.getValueType() == MVT::Glue) break;
3154 Ops.push_back(V);
3155 }
3156 }
3157
3158 // If this has chain/glue inputs, add them.
3159 if (EmitNodeInfo & OPFL_Chain)
3160 Ops.push_back(InputChain);
3161 if ((EmitNodeInfo & OPFL_GlueInput) && InputGlue.getNode() != nullptr)
3162 Ops.push_back(InputGlue);
3163
3164 // Create the node.
3165 SDNode *Res = nullptr; <- v7.0删除
3166 if (Opcode != OPC_MorphNodeTo) {
3167 // If this is a normal EmitNode command, just create the new node and
3168 // add the results to the RecordedNodes list.
3169 Res = CurDAG->getMachineNode(TargetOpc, SDLoc(NodeToMatch),
3170 VTList, Ops);
3171
3172 // Add all the non-glue/non-chain results to the RecordedNodes list.
3173 for (unsigned i = 0, e = VTs.size(); i != e; ++i) {
3174 if (VTs[i] == MVT::Other || VTs[i] == MVT::Glue) break;
3175 RecordedNodes.push_back(std::pair<SDValue,SDNode*>(SDValue(Res, i),
3176 nullptr));
3177 }
3178
3179 } else if (NodeToMatch->getOpcode() != ISD::DELETED_NODE) {
3180 Res = MorphNode(NodeToMatch, TargetOpc, VTList, Ops, EmitNodeInfo);
3181 } else {
3182 // NodeToMatch was eliminated by CSE when the target changed the DAG.
3183 // We will visit the equivalent node later.
3184 DEBUG(dbgs() << "Node was eliminated by CSE\n");
3185 return nullptr;
3186 }
MachineSDNode *Res = nullptr; <- v7.0增加
bool IsMorphNodeTo = Opcode == OPC_MorphNodeTo ||
(Opcode >= OPC_MorphNodeTo0 && Opcode <= OPC_MorphNodeTo2);
if (!IsMorphNodeTo) {
// If this is a normal EmitNode command, just create the new node and
// add the results to the RecordedNodes list.
Res = CurDAG->getMachineNode(TargetOpc, SDLoc(NodeToMatch),
VTList, Ops);
// Add all the non-glue/non-chain results to the RecordedNodes list.
for (unsigned i = 0, e = VTs.size(); i != e; ++i) {
if (VTs[i] == MVT::Other || VTs[i] == MVT::Glue) break;
RecordedNodes.push_back(std::pair<SDValue,SDNode*>(SDValue(Res, i),
nullptr));
}
} else {
assert(NodeToMatch->getOpcode() != ISD::DELETED_NODE &&
"NodeToMatch was removed partway through selection");
SelectionDAG::DAGNodeDeletedListener NDL(*CurDAG, [&](SDNode *N,
SDNode *E) {
CurDAG->salvageDebugInfo(*N);
auto &Chain = ChainNodesMatched;
assert((!E || !is_contained(Chain, N)) &&
"Chain node replaced during MorphNode");
Chain.erase(std::remove(Chain.begin(), Chain.end(), N), Chain.end());
});
à Res = cast<MachineSDNode>(MorphNode(NodeToMatch, TargetOpc, VTList,
Ops, EmitNodeInfo));
}
注意在v7.0代码里,à行的cast<MachineSDNode>是为了确定SDNode实例的NodeType小于0(即选择成功,因为如果这个SDNode实例与MachineSDNode不等价,cast()方法将触发断言。参考MachineSDNode的classof()方法),并不是为了真正将SDNode指针转换为MachineSDNode指针。
而到了遇见OPC_EmitNode或OPC_MorphNodeTo时,表示匹配马上就要完成了,要为匹配成功的指令生成代表其结果的MachineSDNode,这个节点将代替被匹配成功的DAG。
我们前面看到OPC_MorphNodeTo后面跟的是这么一串内容:
/*1792*/ OPC_MorphNodeTo, TARGET_VAL(X86::SHR16mi), 0|OPFL_Chain|OPFL_MemRefs,
1/*#VTs*/, MVT::i32, 6/*#Ops*/, 4, 5, 6, 7, 8, 9,
// Src: (st (srl:i16 (ld:i16 addr:iPTR:$dst)<<P:Predicate_unindexedload>><<P:Predicate_loadi16>>, (imm:i8):$src), addr:iPTR:$dst)<<P:Predicate_unindexedstore>><<P:Predicate_store>> - Complexity = 50
// Dst: (SHR16mi:i32 addr:iPTR:$dst, (imm:i8):$src)
首先是表示目标机器上所对应的指令助记符(2个字节),它是将要生成的MachineSDNode的NodeType(实际上这些枚举值是根据TD里对应指令定义的名字生成的)。随后是记录该操作属性的字节。接下来就是结果类型数组,以及操作数列表。3100~3165行都是解析这些字节,准备参数列表Ops。注意3138行,Ops也是来自由容器RecordedNodes里记录的SDNode实例。
对于OPC_EmitNode,匹配真正结束要等到OPC_CompleteMatch出现,因此在3166~3176行准备一个具有指定操作码的MachineSDNode实例,将代表结果的SDValue实例记录到RecordedNodes,OPC_CompleteMatch将使用这些结果。至于OPC_MorphNodeTo,它是OPC_EmitNode与OPC_CompleteMatch的合体,因此通过下面的方法来了结这次的匹配。
2232 SDNode *SelectionDAGISel::
2233 MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTList,
2234 ArrayRef<SDValue> Ops, unsigned EmitNodeInfo) {
2235 // It is possible we're using MorphNodeTo to replace a node with no
2236 // normal results with one that has a normal result (or we could be
2237 // adding a chain) and the input could have glue and chains as well.
2238 // In this case we need to shift the operands down.
2239 // FIXME: This is a horrible hack and broken in obscure cases, no worse
2240 // than the old isel though.
2241 int OldGlueResultNo = -1, OldChainResultNo = -1;
2242
2243 unsigned NTMNumResults = Node->getNumValues();
2244 if (Node->getValueType(NTMNumResults-1) == MVT::Glue) {
2245 OldGlueResultNo = NTMNumResults-1;
2246 if (NTMNumResults != 1 &&
2247 Node->getValueType(NTMNumResults-2) == MVT::Other)
2248 OldChainResultNo = NTMNumResults-2;
2249 } else if (Node->getValueType(NTMNumResults-1) == MVT::Other)
2250 OldChainResultNo = NTMNumResults-1;
2251
2252 // Call the underlying SelectionDAG routine to do the transmogrification. Note
2253 // that this deletes operands of the old node that become dead.
2254 SDNode *Res = CurDAG->MorphNodeTo(Node, ~TargetOpc, VTList, Ops);
2255
2256 // MorphNodeTo can operate in two ways: if an existing node with the
2257 // specified operands exists, it can just return it. Otherwise, it
2258 // updates the node in place to have the requested operands.
2259 if (Res == Node) {
2260 // If we updated the node in place, reset the node ID. To the isel,
2261 // this should be just like a newly allocated machine node.
2262 Res->setNodeId(-1);
2263 }
2264
2265 unsigned ResNumResults = Res->getNumValues();
2266 // Move the glue if needed.
2267 if ((EmitNodeInfo & OPFL_GlueOutput) && OldGlueResultNo != -1 &&
2268 (unsigned)OldGlueResultNo != ResNumResults-1)
2269 CurDAG->ReplaceAllUsesOfValueWith(SDValue(Node, OldGlueResultNo), <- v7.0删除
2270 SDValue(Res, ResNumResults-1));
ReplaceUses(SDValue(Node, OldGlueResultNo), <- v7.0增加
SDValue(Res, ResNumResults - 1));
2271
2272 if ((EmitNodeInfo & OPFL_GlueOutput) != 0)
2273 --ResNumResults;
2274
2275 // Move the chain reference if needed.
2276 if ((EmitNodeInfo & OPFL_Chain) && OldChainResultNo != -1 &&
2277 (unsigned)OldChainResultNo != ResNumResults-1)
2278 CurDAG->ReplaceAllUsesOfValueWith(SDValue(Node, OldChainResultNo), <- v7.0删除
2279 SDValue(Res, ResNumResults-1));
ReplaceUses(SDValue(Node, OldChainResultNo), <- v7.0增加
SDValue(Res, ResNumResults - 1));
2280
2281 // Otherwise, no replacement happened because the node already exists. Replace
2282 // Uses of the old node with the new one.
2283 if (Res != Node) <- v7.0删除
2284 CurDAG->ReplaceAllUsesWith(Node, Res);
if (Res != Node) { <- v7.0增加
ReplaceNode(Node, Res);
} else {
EnforceNodeIdInvariant(Res);
}
2285
2286 return Res;
2287 }
因为结果是目标机器相关的,因此由目标机器SelectionDAG的MorphNodeTo()方法来构建表示匹配结果的SDNode实例。注意在2254行的调用时将TargetOpc取反,这样很容易通过NodeType是否小于0来判断SDNode实例是否是指令选择的结果(在下面5840行赋值为TargetOpc)。
5824 SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
5825 SDVTList VTs, ArrayRef<SDValue> Ops) {
5826 unsigned NumOps = Ops.size();
5827 // If an identical node already exists, use it.
5828 void *IP = nullptr;
5829 if (VTs.VTs[VTs.NumVTs-1] != MVT::Glue) {
5830 FoldingSetNodeID ID;
5831 AddNodeIDNode(ID, Opc, VTs, Ops);
5832 if (SDNode *ON = FindNodeOrInsertPos(ID, N->getDebugLoc(), IP))
5833 return UpdadeSDLocOnMergedSDNode(ON, SDLoc(N));
5834 }
5835
5836 if (!RemoveNodeFromCSEMaps(N))
5837 IP = nullptr;
5838
5839 // Start the morphing.
5840 N->NodeType = Opc;
5841 N->ValueList = VTs.VTs;
5842 N->NumValues = VTs.NumVTs;
5843
5844 // Clear the operands list, updating used nodes to remove this from their
5845 // use list. Keep track of any operands that become dead as a result.
5846 SmallPtrSet<SDNode*, 16> DeadNodeSet;
5847 for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) {
5848 SDUse &Use = *I++;
5849 SDNode *Used = Use.getNode();
5850 Use.set(SDValue());
5851 if (Used->use_empty())
5852 DeadNodeSet.insert(Used);
5853 }
5854
5855 if (MachineSDNode *MN = dyn_cast<MachineSDNode>(N)) { <- v7.0删除
5856 // Initialize the memory references information.
5857 MN->setMemRefs(nullptr, nullptr);
5858 // If NumOps is larger than the # of operands we can have in a <- v7.0删除
5859 // MachineSDNode, reallocate the operand list.
5860 if (NumOps > MN->NumOperands || !MN->OperandsNeedDelete) {
5861 if (MN->OperandsNeedDelete)
5862 delete[] MN->OperandList;
5863 if (NumOps > array_lengthof(MN->LocalOperands))
5864 // We're creating a final node that will live unmorphed for the
5865 // remainder of the current SelectionDAG iteration, so we can allocate
5866 // the operands directly out of a pool with no recycling metadata.
5867 MN->InitOperands(OperandAllocator.Allocate<SDUse>(NumOps),
5868 Ops.data(), NumOps);
5869 else
5870 MN->InitOperands(MN->LocalOperands, Ops.data(), NumOps);
5871 MN->OperandsNeedDelete = false;
5872 } else
5873 MN->InitOperands(MN->OperandList, Ops.data(), NumOps);
5874 } else {
5875 // If NumOps is larger than the # of operands we currently have, reallocate
5876 // the operand list.
5877 if (NumOps > N->NumOperands) {
5878 if (N->OperandsNeedDelete)
5879 delete[] N->OperandList;
5880 N->InitOperands(new SDUse[NumOps], Ops.data(), NumOps);
5881 N->OperandsNeedDelete = true;
5882 } else
5883 N->InitOperands(N->OperandList, Ops.data(), NumOps);
5884 }
// Swap for an appropriately sized array from the recycler. <- v7.0增加
removeOperands(N);
createOperands(N, Ops);
5885
5886 // Delete any nodes that are still dead after adding the uses for the
5887 // new operands.
5888 if (!DeadNodeSet.empty()) {
5889 SmallVector<SDNode *, 16> DeadNodes;
5890 for (SDNode *N : DeadNodeSet)
5891 if (N->use_empty())
5892 DeadNodes.push_back(N);
5893 RemoveDeadNodes(DeadNodes);
5894 }
5895
5896 if (IP)
5897 CSEMap.InsertNode(N, IP); // Memoize the new node.
5898 return N;
5899 }
如果选中的指令不修改标志寄存器,就可以首先检查是否存在相同的MachineSDNode。5830行的FoldingSetNodeID()用于收集一个节点中所有的数据比特,然后为这个节点产生一个哈希值。因为SDNode是从FoldingSetNode派生的,所以适用这样的方法。
为了理解这段代码,我们需要深入5832行FoldingSet的GetOrInsertNode()方法。它的定义看上去不复杂。但这是一个模板类的方法,这里的T是在定义CSEMap时给出的,即SDNode。
444 T *GetOrInsertNode(Node *N) {
445 return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N));
446 }
FoldingSet所用到的哈希表的具体实现由基类FoldingSetImpl提供,它不是模板类(在v7.0中它也被实现为模板,原来FoldingSetImpl的功能移到了基类FoldingSetBase中。因为v7.0还定义了另一个派生类ContextualFoldingSet)。
380 FoldingSetImpl::Node *FoldingSetImpl::GetOrInsertNode(FoldingSetImpl::Node *N) {
381 FoldingSetNodeID ID;
382 GetNodeProfile(N, ID);
383 void *IP;
384 if (Node *E = FindNodeOrInsertPos(ID, IP))
385 return E;
386 InsertNode(N, IP);
387 return N;
388 }
381行的FoldingSetNodeID唯一的数据成员是SmallVector<unsigned, 32> Bits,用来收集使得特定节点能被唯一识别的比特数据。它还提供了一个ComputeHash()方法来根据这些比特位计算哈希值。382行FoldingSet的GetNodeProfile()就是根据FoldingSet中不同的节点类型填充这些比特。
400 void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override {
401 T *TN = static_cast<T *>(N);
402 FoldingSetTrait<T>::Profile(*TN, ID);
403 }
402行的FoldingSetTrait使用的是非特化的模板类定义(对指针类型特化了):
240 template<typename T> struct FoldingSetTrait
241 : public DefaultFoldingSetTrait<T> {};
因此,402行的Profile方法是基类DefaultFoldingSetTrait提供的:
212 static void Profile(const T &X, FoldingSetNodeID &ID) {
213 X.Profile(ID);
214 }
这里的X是FoldingSet模板类具现时指定的模板参数,对于CSEMap,就是SDNode。因此,213行调用的是下面的方法:
6597 void SDNode::Profile(FoldingSetNodeID &ID) const {
6598 AddNodeIDNode(ID, this);
6599 }
AddNodeIDNode()的定义则是:
565 static void AddNodeIDNode(FoldingSetNodeID &ID, const SDNode *N) {
566 AddNodeIDOpcode(ID, N->getOpcode());
567 // Add the return value info.
568 AddNodeIDValueTypes(ID, N->getVTList());
569 // Add the operand info.
570 AddNodeIDOperands(ID, N->ops());
571
572 // Handle SDNode leafs with special info.
573 AddNodeIDCustom(ID, N);
574 }
它分别调用了这些方法:
372 static void AddNodeIDOpcode(FoldingSetNodeID &ID, unsigned OpC) {
373 ID.AddInteger(OpC);
374 }
378 static void AddNodeIDValueTypes(FoldingSetNodeID &ID, SDVTList VTList) {
379 ID.AddPointer(VTList.VTs);
380 }
394 static void AddNodeIDOperands(FoldingSetNodeID &ID,
395 ArrayRef<SDValue> Ops) {
396 for (auto& Op : Ops) {
397 ID.AddPointer(Op.getNode());
398 ID.AddInteger(Op.getResNo());
399 }
400 }
429 static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) {
430 switch (N->getOpcode()) {
431 case ISD::TargetExternalSymbol:
432 case ISD::ExternalSymbol:
433 case ISD::MCSymbol:
434 llvm_unreachable("Should only be used on nodes with operands");
435 default: break; // Normal nodes don't need extra info.
436 case ISD::TargetConstant:
437 case ISD::Constant: {
438 const ConstantSDNode *C = cast<ConstantSDNode>(N);
439 ID.AddPointer(C->getConstantIntValue());
440 ID.AddBoolean(C->isOpaque());
441 break;
442 }
443 case ISD::TargetConstantFP:
444 case ISD::ConstantFP: {
445 ID.AddPointer(cast<ConstantFPSDNode>(N)->getConstantFPValue());
446 break;
447 }
448 case ISD::TargetGlobalAddress:
449 case ISD::GlobalAddress:
450 case ISD::TargetGlobalTLSAddress:
451 case ISD::GlobalTLSAddress: {
452 const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
453 ID.AddPointer(GA->getGlobal());
454 ID.AddInteger(GA->getOffset());
455 ID.AddInteger(GA->getTargetFlags());
456 ID.AddInteger(GA->getAddressSpace()); <- v7.0删除
457 break;
458 }
459 case ISD::BasicBlock:
460 ID.AddPointer(cast<BasicBlockSDNode>(N)->getBasicBlock());
461 break;
462 case ISD::Register:
463 ID.AddInteger(cast<RegisterSDNode>(N)->getReg());
464 break;
465 case ISD::RegisterMask:
466 ID.AddPointer(cast<RegisterMaskSDNode>(N)->getRegMask());
467 break;
468 case ISD::SRCVALUE:
469 ID.AddPointer(cast<SrcValueSDNode>(N)->getValue());
470 break;
471 case ISD::FrameIndex:
472 case ISD::TargetFrameIndex:
473 ID.AddInteger(cast<FrameIndexSDNode>(N)->getIndex());
474 break;
475 case ISD::JumpTable:
476 case ISD::TargetJumpTable:
477 ID.AddInteger(cast<JumpTableSDNode>(N)->getIndex());
478 ID.AddInteger(cast<JumpTableSDNode>(N)->getTargetFlags());
479 break;
480 case ISD::ConstantPool:
481 case ISD::TargetConstantPool: {
482 const ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(N);
483 ID.AddInteger(CP->getAlignment());
484 ID.AddInteger(CP->getOffset());
485 if (CP->isMachineConstantPoolEntry())
486 CP->getMachineCPVal()->addSelectionDAGCSEId(ID);
487 else
488 ID.AddPointer(CP->getConstVal());
489 ID.AddInteger(CP->getTargetFlags());
490 break;
491 }
492 case ISD::TargetIndex: {
493 const TargetIndexSDNode *TI = cast<TargetIndexSDNode>(N);
494 ID.AddInteger(TI->getIndex());
495 ID.AddInteger(TI->getOffset());
496 ID.AddInteger(TI->getTargetFlags());
497 break;
498 }
499 case ISD::LOAD: {
500 const LoadSDNode *LD = cast<LoadSDNode>(N);
501 ID.AddInteger(LD->getMemoryVT().getRawBits());
502 ID.AddInteger(LD->getRawSubclassData());
503 ID.AddInteger(LD->getPointerInfo().getAddrSpace());
504 break;
505 }
506 case ISD::STORE: {
507 const StoreSDNode *ST = cast<StoreSDNode>(N);
508 ID.AddInteger(ST->getMemoryVT().getRawBits());
509 ID.AddInteger(ST->getRawSubclassData());
510 ID.AddInteger(ST->getPointerInfo().getAddrSpace());
511 break;
512 }
case ISD::MLOAD: { <- v7.0增加
const MaskedLoadSDNode *MLD = cast<MaskedLoadSDNode>(N);
ID.AddInteger(MLD->getMemoryVT().getRawBits());
ID.AddInteger(MLD->getRawSubclassData());
ID.AddInteger(MLD->getPointerInfo().getAddrSpace());
break;
}
case ISD::MSTORE: {
const MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
ID.AddInteger(MST->getMemoryVT().getRawBits());
ID.AddInteger(MST->getRawSubclassData());
ID.AddInteger(MST->getPointerInfo().getAddrSpace());
break;
}
case ISD::MGATHER: {
const MaskedGatherSDNode *MG = cast<MaskedGatherSDNode>(N);
ID.AddInteger(MG->getMemoryVT().getRawBits());
ID.AddInteger(MG->getRawSubclassData());
ID.AddInteger(MG->getPointerInfo().getAddrSpace());
break;
}
case ISD::MSCATTER: {
const MaskedScatterSDNode *MS = cast<MaskedScatterSDNode>(N);
ID.AddInteger(MS->getMemoryVT().getRawBits());
ID.AddInteger(MS->getRawSubclassData());
ID.AddInteger(MS->getPointerInfo().getAddrSpace());
break;
}
513 case ISD::ATOMIC_CMP_SWAP:
514 case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS:
515 case ISD::ATOMIC_SWAP:
516 case ISD::ATOMIC_LOAD_ADD:
517 case ISD::ATOMIC_LOAD_SUB:
518 case ISD::ATOMIC_LOAD_AND:
519 case ISD::ATOMIC_LOAD_OR:
520 case ISD::ATOMIC_LOAD_XOR:
521 case ISD::ATOMIC_LOAD_NAND:
522 case ISD::ATOMIC_LOAD_MIN:
523 case ISD::ATOMIC_LOAD_MAX:
524 case ISD::ATOMIC_LOAD_UMIN:
525 case ISD::ATOMIC_LOAD_UMAX:
526 case ISD::ATOMIC_LOAD:
527 case ISD::ATOMIC_STORE: {
528 const AtomicSDNode *AT = cast<AtomicSDNode>(N);
529 ID.AddInteger(AT->getMemoryVT().getRawBits());
530 ID.AddInteger(AT->getRawSubclassData());
531 ID.AddInteger(AT->getPointerInfo().getAddrSpace());
532 break;
533 }
534 case ISD::PREFETCH: {
535 const MemSDNode *PF = cast<MemSDNode>(N);
536 ID.AddInteger(PF->getPointerInfo().getAddrSpace());
537 break;
538 }
539 case ISD::VECTOR_SHUFFLE: {
540 const ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(N);
541 for (unsigned i = 0, e = N->getValueType(0).getVectorNumElements();
542 i != e; ++i)
543 ID.AddInteger(SVN->getMaskElt(i));
544 break;
545 }
546 case ISD::TargetBlockAddress:
547 case ISD::BlockAddress: {
548 const BlockAddressSDNode *BA = cast<BlockAddressSDNode>(N);
549 ID.AddPointer(BA->getBlockAddress());
550 ID.AddInteger(BA->getOffset());
551 ID.AddInteger(BA->getTargetFlags());
552 break;
553 }
554 } // end switch (N->getOpcode())
555
556 AddNodeIDFlags(ID, N);
557
558 // Target specific memory nodes could also have address spaces to check.
559 if (N->isTargetMemoryOpcode())
560 ID.AddInteger(cast<MemSDNode>(N)->getPointerInfo().getAddrSpace());
561 }
除了记录操作码、操作数地址、返回值地址、类型,方法AddNodeIDCustom()还根据SDNode的派生类型进行进一步的记录,以确保有更好的区分度。这里的哈希方法采用了N3333[1]所提出的算法与接口,它确保k1==k2,就必然有h (k1) == h (k2)。那么FoldingSetImpl::GetOrInsertNode()所调用的FindNodeOrInsertPos()方法涵盖了下列的方法调用:
451 T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
452 return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos));
453 }
下面288行的GetBucketFor()方法返回该哈希值所对应的桶,这个桶是哈希值相同的SDNode对象组成的链表。
284 FoldingSetImpl::Node
285 *FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
286 void *&InsertPos) {
287 unsigned IDHash = ID.ComputeHash();
288 void **Bucket = GetBucketFor(IDHash, Buckets, NumBuckets);
289 void *Probe = *Bucket;
290
291 InsertPos = nullptr;
292
293 FoldingSetNodeID TempID;
294 while (Node *NodeInBucket = GetNextPtr(Probe)) {
295 if (NodeEquals(NodeInBucket, ID, IDHash, TempID))
296 return NodeInBucket;
297 TempID.clear();
298
299 Probe = NodeInBucket->getNextInBucket();
300 }
301
302 // Didn't find the node, return null with the bucket as the InsertPos.
303 InsertPos = Bucket;
304 return nullptr;
305 }
295行的NodeEquals()是FoldingSet的方法,它的定义如下:
406 bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
407 FoldingSetNodeID &TempID) const override {
408 T *TN = static_cast<T *>(N);
409 return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID);
410 }
409行的Equals有多个特化版本,我们只看非特化版本,它来自基类DefaultFoldingSetTrait。
358 template<typename T>
359 inline bool
360 DefaultFoldingSetTrait<T>::Equals(T &X, const FoldingSetNodeID &ID,
361 unsigned /*IDHash*/,
362 FoldingSetNodeID &TempID) {
363 FoldingSetTrait<T>::Profile(X, TempID);
364 return TempID == ID;
365 }
在这里我们又看到了Profile()这个方法,前面我们就是使用这个方法来收集计算哈希值所需要的比特位的。在364行通过FoldingSetNodeID的比较操作符来比较这两个FoldingSetNodeID实例:
152 bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS) const {
153 return *this == FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size());
154 }
158 bool FoldingSetNodeID::operator==(FoldingSetNodeIDRef RHS) const {
159 return FoldingSetNodeIDRef(Bits.data(), Bits.size()) == RHS;
160 }
34 bool FoldingSetNodeIDRef::operator==(FoldingSetNodeIDRef RHS) const {
35 if (Size != RHS.Size) return false;
36 return memcmp(Data, RHS.Data, Size*sizeof(*Data)) == 0;
37 }
看到最终我们是通过比较比特位来确定两个对象是否相等。因为不是使用地址作为比较的标准,因此存在不同的SDNode实例按上述标准是相同的情况。
如果没有存在的相同实例,或者选中指令会修改标志寄存器,就要进入5836行,通过方法RemoveNodeFromCSEMaps()将这个SDNode实例从CSEMap(或者别的容器)删除。如果SDNode没有记录,在5837行将IP置0。
778 bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
779 bool Erased = false;
780 switch (N->getOpcode()) {
781 case ISD::HANDLENODE: return false; // noop.
782 case ISD::CONDCODE:
783 assert(CondCodeNodes[cast<CondCodeSDNode>(N)->get()] &&
784 "Cond code doesn't exist!");
785 Erased = CondCodeNodes[cast<CondCodeSDNode>(N)->get()] != nullptr;
786 CondCodeNodes[cast<CondCodeSDNode>(N)->get()] = nullptr;
787 break;
788 case ISD::ExternalSymbol:
789 Erased = ExternalSymbols.erase(cast<ExternalSymbolSDNode>(N)->getSymbol());
790 break;
791 case ISD::TargetExternalSymbol: {
792 ExternalSymbolSDNode *ESN = cast<ExternalSymbolSDNode>(N);
793 Erased = TargetExternalSymbols.erase(
794 std::pair<std::string,unsigned char>(ESN->getSymbol(),
795 ESN->getTargetFlags()));
796 break;
797 }
798 case ISD::MCSymbol: {
799 auto *MCSN = cast<MCSymbolSDNode>(N);
800 Erased = MCSymbols.erase(MCSN->getMCSymbol());
801 break;
802 }
803 case ISD::VALUETYPE: {
804 EVT VT = cast<VTSDNode>(N)->getVT();
805 if (VT.isExtended()) {
806 Erased = ExtendedValueTypeNodes.erase(VT);
807 } else {
808 Erased = ValueTypeNodes[VT.getSimpleVT().SimpleTy] != nullptr;
809 ValueTypeNodes[VT.getSimpleVT().SimpleTy] = nullptr;
810 }
811 break;
812 }
813 default:
814 // Remove it from the CSE Map.
815 assert(N->getOpcode() != ISD::DELETED_NODE && "DELETED_NODE in CSEMap!");
816 assert(N->getOpcode() != ISD::EntryToken && "EntryToken in CSEMap!");
817 Erased = CSEMap.RemoveNode(N);
818 break;
819 }
820 #ifndef NDEBUG
821 // Verify that the node was actually in one of the CSE maps, unless it has a
822 // flag result (which cannot be CSE'd) or is one of the special cases that are
823 // not subject to CSE.
824 if (!Erased && N->getValueType(N->getNumValues()-1) != MVT::Glue &&
825 !N->isMachineOpcode() && !doNotCSE(N)) {
826 N->dump(this);
827 dbgs() << "\n";
828 llvm_unreachable("Node is not in map!");
829 }
830 #endif
831 return Erased;
832 }
SelectionDAG::MorphNodeTo()接下来在5847行循环检查当前节点是唯一使用者的节点,将它们记录到DeadNodeSet容器,为后面回收它们做准备。接着,为这个节点重新准备操作数,这些操作数就是参数Ops,它是SelectionDAGISel对象RecordedNodes容器中已经选择好的SDValue对象。SDNode的方法InitOperands()将更新其中的OperandList。
812 void InitOperands(SDUse *Ops, const SDValue *Vals, unsigned N) {
813 for (unsigned i = 0; i != N; ++i) {
814 Ops[i].setUser(this);
815 Ops[i].setInitial(Vals[i]);
816 }
817 NumOperands = N;
818 assert(NumOperands == N &&
819 "NumOperands wasn't wide enough for its operands!");
820 OperandList = Ops;
821 checkForCycles(this);
822 }
注意,如果选中指令会修改标志寄存器,那么在上面的处理中,先从容器中(CSEMap或其他)删除它。然后在下面的ReplaceAllUsesOfValueWith()调用里,通过AddModifiedNodeToCSEMaps()方法将它加入CSEMap。
SelectionDAG::MorphNodeTo()将处理后的SDNode实例返回给SelectionDAGISel::MorphNode()的变量Res。除非已有相同的对象存在,SelectionDAGISel::MorphNode()的2259行条件总是满足的,这样重置这个对象的NodeId,使得在指令选择器看来这是个新的节点。
V7.0删除了SelectionDAG::MorphNodeTo()从5858到5884行的代码。取而代之,调用了下面的函数。首先是通过SelectionDAG::removeOperands()释放NodeToMatch的操作数,而不是将类型局限于MachineSDNode。 366 void removeOperands(SDNode *Node) { 367 if (!Node->OperandList) 368 return; 369 OperandRecycler.deallocate( 370 ArrayRecycler<SDUse>::Capacity::get(Node->NumOperands), 371 Node->OperandList); 372 Node->NumOperands = 0; 373 Node->OperandList = nullptr; 374 } 然后通过SelectionDAG::createOperands()为NodeToMatch设置前面准备好的操作数。注意,这里的操作数包含了更新的链节点与黏结节点,因此不再需要OPC_MarkGlueResults类型的Matcher来对黏结节点进行特别处理。 8682 void SelectionDAG::createOperands(SDNode *Node, ArrayRef<SDValue> Vals) { 8683 assert(!Node->OperandList && "Node already has operands"); 8684 SDUse *Ops = OperandRecycler.allocate( 8685 ArrayRecycler<SDUse>::Capacity::get(Vals.size()), OperandAllocator); 8686 8687 bool IsDivergent = false; 8688 for (unsigned I = 0; I != Vals.size(); ++I) { 8689 Ops[I].setUser(Node); 8690 Ops[I].setInitial(Vals[I]); 8691 if (Ops[I].Val.getValueType() != MVT::Other) // Skip Chain. It does not carry divergence. 8692 IsDivergent = IsDivergent || Ops[I].getNode()->isDivergent(); 8693 } 8694 Node->NumOperands = Vals.size(); 8695 Node->OperandList = Ops; 8696 IsDivergent |= TLI->isSDNodeSourceOfDivergence(Node, FLI, DA); 8697 if (!TLI->isSDNodeAlwaysUniform(Node)) 8698 Node->SDNodeBits.IsDivergent = IsDivergent; 8699 checkForCycles(Node); 8700 } V7.0引入了一个FunctionPass——DivergenceAnalysis。用于检查GPU程序里的分支是否发散。SDNode的IsDivergent域用于保存这个分析的结果。8699行的checkForCycles()检查这个SDNode节点是否构成了一个环(SelectionDAG是不允许这样的,DAG本身就不能是环)。 |
接下来,在2267行,如果选择指令会使用标志寄存器,而且选中指令产生个数不同的结果,因为标志寄存器的结果(glue)总是最后一个结果,就要将这个旧值在使用的地方替换为新值。对链节点的处理也是类似的,最后如果SelectionDAG::MorphNodeTo()生成了新节点,也要在使用的地方替换旧节点。
6295 void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
6296 // Handle the really simple, really trivial case efficiently.
6297 if (From == To) return;
6298
6299 // Handle the simple, trivial, case efficiently.
6300 if (From.getNode()->getNumValues() == 1) {
6301 ReplaceAllUsesWith(From, To);
6302 return;
6303 }
6304
6305 // Iterate over just the existing users of From. See the comments in
6306 // the ReplaceAllUsesWith above.
6307 SDNode::use_iterator UI = From.getNode()->use_begin(),
6308 UE = From.getNode()->use_end();
6309 RAUWUpdateListener Listener(*this, UI, UE);
6310 while (UI != UE) {
6311 SDNode *User = *UI;
6312 bool UserRemovedFromCSEMaps = false;
6313
6314 // A user can appear in a use list multiple times, and when this
6315 // happens the uses are usually next to each other in the list.
6316 // To help reduce the number of CSE recomputations, process all
6317 // the uses of this user that we can find this way.
6318 do {
6319 SDUse &Use = UI.getUse();
6320
6321 // Skip uses of different values from the same node.
6322 if (Use.getResNo() != From.getResNo()) {
6323 ++UI;
6324 continue;
6325 }
6326
6327 // If this node hasn't been modified yet, it's still in the CSE maps,
6328 // so remove its old self from the CSE maps.
6329 if (!UserRemovedFromCSEMaps) {
6330 RemoveNodeFromCSEMaps(User);
6331 UserRemovedFromCSEMaps = true;
6332 }
6333
6334 ++UI;
6335 Use.set(To);
if (To->isDivergent() != From->isDivergent()) ß v7.0增加
updateDivergence(User)
6336 } while (UI != UE && *UI == User);
6337
6338 // We are iterating over all uses of the From node, so if a use
6339 // doesn't use the specific value, no changes are made.
6340 if (!UserRemovedFromCSEMaps)
6341 continue;
6342
6343 // Now that we have modified User, add it back to the CSE maps. If it
6344 // already exists there, recursively merge the results together.
6345 AddModifiedNodeToCSEMaps(User);
6346 }
6347
6348 // If we just RAUW'd the root, take note.
6349 if (From == getRoot())
6350 setRoot(To);
6351 }
如果节点只有一个结果,调用ReplaceAllUsesWith()方法就可以了,我们后面再来看这个方法。如果有多个结果,从6307行开始遍历这些结果的使用者。在6309行创建一个RAUWUpdateListener对象,这个对象的定义如下:
6139 class RAUWUpdateListener : public SelectionDAG::DAGUpdateListener {
6140 SDNode::use_iterator &UI;
6141 SDNode::use_iterator &UE;
6142
6143 void NodeDeleted(SDNode *N, SDNode *E) override {
6144 // Increment the iterator as needed.
6145 while (UI != UE && N == *UI)
6146 ++UI;
6147 }
6148
6149 public:
6150 RAUWUpdateListener(SelectionDAG &d,
6151 SDNode::use_iterator &ui,
6152 SDNode::use_iterator &ue)
6153 : SelectionDAG::DAGUpdateListener(d), UI(ui), UE(ue) {}
6154 };
基类SelectionDAG::DAGUpdateListener的定义则是:
225 struct DAGUpdateListener {
226 DAGUpdateListener *const Next;
227 SelectionDAG &DAG;
228
229 explicit DAGUpdateListener(SelectionDAG &D)
230 : Next(D.UpdateListeners), DAG(D) {
231 DAG.UpdateListeners = this;
232 }
233
234 virtual ~DAGUpdateListener() {
235 assert(DAG.UpdateListeners == this &&
236 "DAGUpdateListeners must be destroyed in LIFO order");
237 DAG.UpdateListeners = Next;
238 }
239
240 /// The node N that was deleted and, if E is not null, an
241 /// equivalent node E that replaced it.
242 virtual void NodeDeleted(SDNode *N, SDNode *E);
243
244 /// The node N that was updated.
245 virtual void NodeUpdated(SDNode *N);
246 };
基类的构造函数将自己加入SelectionDAG对象的UpdateListeners更新监听者。当SelectionDAG删除一个指定SDNode对象时,它将依次调用UpdateListeners注册对象的NodeDeleted()方法来处理这个对象。而当SelectionDAG修改一个SDNode对象时,它将依次调用UpdateListeners注册对象的NodeUpdated()方法来处理这个对象。对RAUWUpdateListener来说,它的NodeUpdated()方法在迭代器SDNode::use_iterator所指向的对象被删除时,使该迭代器指向下一个对象。NodeUpdated()方法则是空的。
RAUWUpdateListener使用的迭代器SDNode::use_iterator用于遍历一个指定SDNode对象的使用者。在6307与6308行使用了这些SDNode的方法来准备这个迭代器:
513 use_iterator use_begin() const {
514 return use_iterator(UseList);
515 }
516
517 static use_iterator use_end() { return use_iterator(nullptr); }
UI保存了SDNode的SDUse*类型成员UseList。在6311行,SDNode::use_iterator的提领方法返回当前SDUse的所援引的SDNode对象。
496 SDNode *operator*() const {
497 assert(Op && "Cannot dereference end iterator!");
498 return Op->getUser();
499 }
Op的类型是SDUse*,操作符*返回的是一个SDNode指针。因此6336行的第二个条件是确保该循环所访问的所有SDUse都是援引同一个SDNode实例(即User,它本身就是一个指针)。这样,6319行拿到的Use总是同一个,即都援引User(迭代器SDNode::use_iterator的getUse方法返回Op的引用)。在6335行将这些SDUse实例所援引的SDValue对象从From改为To。
在6345行向CSEMap加入修改后的User。如果CSEMap中存在与User哈希值相同的匹配节点(但不是同一个对象),将会进入下面845行的分支,用User(即参数N)替换这个对象。
839 void
840 SelectionDAG::AddModifiedNodeToCSEMaps(SDNode *N) {
841 // For node types that aren't CSE'd, just act as if no identical node
842 // already exists.
843 if (!doNotCSE(N)) {
844 SDNode *Existing = CSEMap.GetOrInsertNode(N);
845 if (Existing != N) {
846 // If there was already an existing matching node, use ReplaceAllUsesWith
847 // to replace the dead one with the existing one. This can cause
848 // recursive merging of other unrelated nodes down the line.
849 ReplaceAllUsesWith(N, Existing);
850
851 // N is now dead. Inform the listeners and delete it.
852 for (DAGUpdateListener *DUL = UpdateListeners; DUL; DUL = DUL->Next)
853 DUL->NodeDeleted(N, Existing);
854 DeleteNodeNotInCSEMaps(N);
855 return;
856 }
857 }
858
859 // If the node doesn't already exist, we updated it. Inform listeners.
860 for (DAGUpdateListener *DUL = UpdateListeners; DUL; DUL = DUL->Next)
861 DUL->NodeUpdated(N);
862 }
对不能CSE由处理的节点(黏结节点、HANDLENODE以及EH_LABEL节点),则需要依次调用UpdateListeners注册对象的NodeUpdated()方法处理这个对象。这里的RAUWUpdateListener的NodeUpdated()方法是空的。
SelectionDAG::ReplaceAllUsesWith()的定义与上面的SelectionDAG::ReplaceAllUsesOfValueWith()非常类似。SelectionDAG定义的几个ReplaceAllUsesWith()类型的方法都可视为一个功能的几个便利封装。
6210 void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
6211 #ifndef NDEBUG
6212 for (unsigned i = 0, e = From->getNumValues(); i != e; ++i)
6213 assert((!From->hasAnyUseOfValue(i) ||
6214 From->getValueType(i) == To->getValueType(i)) &&
6215 "Cannot use this version of ReplaceAllUsesWith!");
6216 #endif
6217
6218 // Handle the trivial case.
6219 if (From == To)
6220 return;
6221
6222 // Iterate over just the existing users of From. See the comments in
6223 // the ReplaceAllUsesWith above.
6224 SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
6225 RAUWUpdateListener Listener(*this, UI, UE);
6226 while (UI != UE) {
6227 SDNode *User = *UI;
6228
6229 // This node is about to morph, remove its old self from the CSE maps.
6230 RemoveNodeFromCSEMaps(User);
6231
6232 // A user can appear in a use list multiple times, and when this
6233 // happens the uses are usually next to each other in the list.
6234 // To help reduce the number of CSE recomputations, process all
6235 // the uses of this user that we can find this way.
6236 do {
6237 SDUse &Use = UI.getUse();
6238 ++UI;
6239 Use.setNode(To);
if (To->isDivergent() != From->isDivergent()) ß v7.0增加
updateDivergence(User);
6240 } while (UI != UE && *UI == User);
6241
6242 // Now that we have modified User, add it back to the CSE maps. If it
6243 // already exists there, recursively merge the results together.
6244 AddModifiedNodeToCSEMaps(User);
6245 }
6246
6247 // If we just RAUW'd the root, take note.
6248 if (From == getRoot().getNode())
6249 setRoot(SDValue(To, getRoot().getResNo()));
6250 }
替代是一个迭代的过程,在6244行会对From的所有使用者调用AddModifiedNodeToCSEMaps(),而在这个函数里则又会对这些使用者的使用者递归调用自己,直到最终一级的使用者(即没有对它们的使用)。SelectDAG是一个有根的DAG,因此类SelectDAG中成员Root(SDValue类型)记录这个根。6248行的getRoot()方法只是返回这个成员的引用。而setRoot()方法则是设置这个成员,同时需要检查设置这个根是否会导致环。
因为这个广泛而深入的递归过程,在AddModifiedNodeToCSEMaps()以及ReplaceAllUsesWith()中都存在一个do while循环来处理援引同一个的SDUse对象,以减少递归的次数。
至于SelectionDAG::ReplaceAllUsesOfValueWith()所使用的另一个版本的ReplaceAllUsesWith(),则有如下的定义。事实上,这些ReplaceAllUsesWith()的定义都是类似的。
6163 void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To) {
6164 SDNode *From = FromN.getNode();
6165 assert(From->getNumValues() == 1 && FromN.getResNo() == 0 &&
6166 "Cannot replace with this method!");
6167 assert(From != To.getNode() && "Cannot replace uses of with self");
6168
6169 // Iterate over all the existing uses of From. New uses will be added
6170 // to the beginning of the use list, which we avoid visiting.
6171 // This specifically avoids visiting uses of From that arise while the
6172 // replacement is happening, because any such uses would be the result
6173 // of CSE: If an existing node looks like From after one of its operands
6174 // is replaced by To, we don't want to replace of all its users with To
6175 // too. See PR3018 for more info.
6176 SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
6177 RAUWUpdateListener Listener(*this, UI, UE);
6178 while (UI != UE) {
6179 SDNode *User = *UI;
6180
6181 // This node is about to morph, remove its old self from the CSE maps.
6182 RemoveNodeFromCSEMaps(User);
6183
6184 // A user can appear in a use list multiple times, and when this
6185 // happens the uses are usually next to each other in the list.
6186 // To help reduce the number of CSE recomputations, process all
6187 // the uses of this user that we can find this way.
6188 do {
6189 SDUse &Use = UI.getUse();
6190 ++UI;
6191 Use.set(To);
6192 } while (UI != UE && *UI == User);
6193
6194 // Now that we have modified User, add it back to the CSE maps. If it
6195 // already exists there, recursively merge the results together.
6196 AddModifiedNodeToCSEMaps(User);
6197 }
6198
6199 // If we just RAUW'd the root, take note.
6200 if (FromN == getRoot())
6201 setRoot(To);
6202 }
在SelectionDAGISel:: MorphNode()中v7.0以ReplaceUses()替换了ReplaceAllUsesOfValueWith()。 220 void ReplaceUses(SDNode *F, SDNode *T) { 221 CurDAG->ReplaceAllUsesWith(F, T); 222 EnforceNodeIdInvariant(T); 223 } 这个方法除了调用ReplaceAllUsesOfValueWith(),还调用下面的方法将选中节点的NodeId置为负数。 984 void SelectionDAGISel::EnforceNodeIdInvariant(SDNode *Node) { 985 SmallVector<SDNode *, 4> Nodes; 986 Nodes.push_back(Node); 987 988 while (!Nodes.empty()) { 989 SDNode *N = Nodes.pop_back_val(); 990 for (auto *U : N->uses()) { 991 auto UId = U->getNodeId(); 992 if (UId > 0) { 993 InvalidateNodeId(U); 994 Nodes.push_back(U); 995 } 996 } 997 } 998 } InvalidateNodeId()的做法与我们前面看到的NodeId是一致的。 1003 void SelectionDAGISel::InvalidateNodeId(SDNode *N) { 1004 int InvalidId = -(N->getNodeId() + 1); 1005 N->setNodeId(InvalidId); 1006 } |
回到SelectCodeCommon()。不管是OPC_MorphNodeTo,还是OPC_EmitNode,得到了Res后都要进入下面的代码,设置对内存使用的信息。3206行得到的MCInstrDesc实例取决于目标机器,对于X86,它实际上指向数组X86Insts中对应该指令的项。这个数组是由TableGen处理选项“-gen-instr-info”时生成的,包含了目标机器每条指令的有关信息。这里暂时不深入细节。
SelectionDAGISel::SelectCodeCommon(续)
3188 // If the node had chain/glue results, update our notion of the current
3189 // chain and glue.
3190 if (EmitNodeInfo & OPFL_GlueOutput) {
3191 InputGlue = SDValue(Res, VTs.size()-1);
3192 if (EmitNodeInfo & OPFL_Chain)
3193 InputChain = SDValue(Res, VTs.size()-2);
3194 } else if (EmitNodeInfo & OPFL_Chain)
3195 InputChain = SDValue(Res, VTs.size()-1);
3196
3197 // If the OPFL_MemRefs glue is set on this node, slap all of the
3198 // accumulated memrefs onto it.
3199 //
3200 // FIXME: This is vastly incorrect for patterns with multiple outputs
3201 // instructions that access memory and for ComplexPatterns that match
3202 // loads.
3203 if (EmitNodeInfo & OPFL_MemRefs) {
3204 // Only attach load or store memory operands if the generated
3205 // instruction may load or store.
3206 const MCInstrDesc &MCID = TII->get(TargetOpc);
3207 bool mayLoad = MCID.mayLoad();
3208 bool mayStore = MCID.mayStore();
3209
3210 unsigned NumMemRefs = 0;
3211 for (SmallVectorImpl<MachineMemOperand *>::const_iterator I =
3212 MatchedMemRefs.begin(), E = MatchedMemRefs.end(); I != E; ++I) {
3213 if ((*I)->isLoad()) {
3214 if (mayLoad)
3215 ++NumMemRefs;
3216 } else if ((*I)->isStore()) {
3217 if (mayStore)
3218 ++NumMemRefs;
3219 } else {
3220 ++NumMemRefs;
3221 }
3222 }
3223
3224 MachineSDNode::mmo_iterator MemRefs =
3225 MF->allocateMemRefsArray(NumMemRefs);
3226
3227 MachineSDNode::mmo_iterator MemRefsPos = MemRefs;
3228 for (SmallVectorImpl<MachineMemOperand *>::const_iterator I =
3229 MatchedMemRefs.begin(), E = MatchedMemRefs.end(); I != E; ++I) {
3230 if ((*I)->isLoad()) {
3231 if (mayLoad)
3232 *MemRefsPos++ = *I;
3233 } else if ((*I)->isStore()) {
3234 if (mayStore)
3235 *MemRefsPos++ = *I;
3236 } else {
3237 *MemRefsPos++ = *I;
3238 }
3239 }
3240
3241 cast<MachineSDNode>(Res) <- v7.0删除
3242 ->setMemRefs(MemRefs, MemRefs + NumMemRefs);
Res->setMemRefs(MemRefs, MemRefs + NumMemRefs); <- v7.0增加
3243 }
3244
3245 DEBUG(dbgs() << " "
3246 << (Opcode == OPC_MorphNodeTo ? "Morphed" : "Created")
3247 << " node: "; Res->dump(CurDAG); dbgs() << "\n");
3248
3249 // If this was a MorphNodeTo then we're completely done!
3250 if (Opcode == OPC_MorphNodeTo) { <- v7.0删除
3241 // Update chain and glue uses.
3242 UpdateChainsAndGlue(NodeToMatch, InputChain, ChainNodesMatched,
3243 InputGlue, GlueResultNodesMatched, true);
3244 return Res;
3245 }
if (IsMorphNodeTo) { <- v7.0增加
// Update chain uses.
UpdateChains(Res, InputChain, ChainNodesMatched, true);
return;
}
3246
3247 continue;
3248 }
注意,OPC_MorphNodeTo从3244行退出SelectCodeCommon()。而OPC_EmitNode则仍然要继续前进,在3247行继续大循环。不过OPC_MorphNodeTo在退出前,先要执行下面的方法,更新Chain与glue操作数。
作为参数的容器ChainNodesMatched与GlueResultNodesMatched都是大循环里加入的使用当前匹配DAG的Chain或glue的SDNode对象。如果当前匹配DAG包含了链并修改标志寄存器,InputChain在上面3193及3195行,InputGlue在3191行产生,都是对Res结果的援引。否则,InputChain就是对ChainNodesMatched执行HandleMergeInputChains()的结果。InputGlue则来自OPC_CaptureGlueInput项(表示当前节点具有输入glue,因此InputGlue指向这个节点)。这里将InputChain与InputGlue更新到它们的使用者。
1983 void SelectionDAGISel::
1984 UpdateChainsAndGlue(SDNode *NodeToMatch, SDValue InputChain,
1985 const SmallVectorImpl<SDNode*> &ChainNodesMatched,
1986 SDValue InputGlue,
1987 const SmallVectorImpl<SDNode*> &GlueResultNodesMatched,
1988 bool isMorphNodeTo) {
1989 SmallVector<SDNode*, 4> NowDeadNodes;
1990
1991 // Now that all the normal results are replaced, we replace the chain and
1992 // glue results if present.
1993 if (!ChainNodesMatched.empty()) {
1994 assert(InputChain.getNode() &&
1995 "Matched input chains but didn't produce a chain");
1996 // Loop over all of the nodes we matched that produced a chain result.
1997 // Replace all the chain results with the final chain we ended up with.
1998 for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) {
1999 SDNode *ChainNode = ChainNodesMatched[i];
2000
2001 // If this node was already deleted, don't look at it.
2002 if (ChainNode->getOpcode() == ISD::DELETED_NODE)
2003 continue;
2004
2005 // Don't replace the results of the root node if we're doing a
2006 // MorphNodeTo.
2007 if (ChainNode == NodeToMatch && isMorphNodeTo)
2008 continue;
2009
2010 SDValue ChainVal = SDValue(ChainNode, ChainNode->getNumValues()-1);
2011 if (ChainVal.getValueType() == MVT::Glue)
2012 ChainVal = ChainVal.getValue(ChainVal->getNumValues()-2);
2013 assert(ChainVal.getValueType() == MVT::Other && "Not a chain?");
2014 CurDAG->ReplaceAllUsesOfValueWith(ChainVal, InputChain);
2015
2016 // If the node became dead and we haven't already seen it, delete it.
2017 if (ChainNode->use_empty() &&
2018 !std::count(NowDeadNodes.begin(), NowDeadNodes.end(), ChainNode))
2019 NowDeadNodes.push_back(ChainNode);
2020 }
2021 }
2022
2023 // If the result produces glue, update any glue results in the matched
2024 // pattern with the glue result.
2025 if (InputGlue.getNode()) {
2026 // Handle any interior nodes explicitly marked.
2027 for (unsigned i = 0, e = GlueResultNodesMatched.size(); i != e; ++i) {
2028 SDNode *FRN = GlueResultNodesMatched[i];
2029
2030 // If this node was already deleted, don't look at it.
2031 if (FRN->getOpcode() == ISD::DELETED_NODE)
2032 continue;
2033
2034 assert(FRN->getValueType(FRN->getNumValues()-1) == MVT::Glue &&
2035 "Doesn't have a glue result");
2036 CurDAG->ReplaceAllUsesOfValueWith(SDValue(FRN, FRN->getNumValues()-1),
2037 InputGlue);
2038
2039 // If the node became dead and we haven't already seen it, delete it.
2040 if (FRN->use_empty() &&
2041 !std::count(NowDeadNodes.begin(), NowDeadNodes.end(), FRN))
2042 NowDeadNodes.push_back(FRN);
2043 }
2044 }
2045
2046 if (!NowDeadNodes.empty())
2047 CurDAG->RemoveDeadNodes(NowDeadNodes);
2048
2049 DEBUG(dbgs() << "ISEL: Match complete!\n");
2050 }
V7.0使用SelectionDAGISel::UpdateChains()替换了SelectionDAGISel::UpdateChainsAndGlue(),因为v7.0不需要支持OPC_MarkGlueResults类型的节点。但是,因为OPC_EmitMergeInputChains的存在,还需要支持公共链节点的替换。下面的容器ChainNodesMatched如果不为空,表明在当前的OPC_Scope中生成了公共链节点。 2431 void SelectionDAGISel::UpdateChains( 2432 SDNode *NodeToMatch, SDValue InputChain, 2433 SmallVectorImpl<SDNode *> &ChainNodesMatched, bool isMorphNodeTo) { 2434 SmallVector<SDNode*, 4> NowDeadNodes; 2435 2436 // Now that all the normal results are replaced, we replace the chain and 2437 // glue results if present. 2438 if (!ChainNodesMatched.empty()) { 2439 assert(InputChain.getNode() && 2440 "Matched input chains but didn't produce a chain"); 2441 // Loop over all of the nodes we matched that produced a chain result. 2442 // Replace all the chain results with the final chain we ended up with. 2443 for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) { 2444 SDNode *ChainNode = ChainNodesMatched[i]; 2445 // If ChainNode is null, it's because we replaced it on a previous 2446 // iteration and we cleared it out of the map. Just skip it. 2447 if (!ChainNode) 2448 continue; 2449 2450 assert(ChainNode->getOpcode() != ISD::DELETED_NODE && 2451 "Deleted node left in chain"); 2452 2453 // Don't replace the results of the root node if we're doing a 2454 // MorphNodeTo. 2455 if (ChainNode == NodeToMatch && isMorphNodeTo) 2456 continue; 2457 2458 SDValue ChainVal = SDValue(ChainNode, ChainNode->getNumValues()-1); 2459 if (ChainVal.getValueType() == MVT::Glue) 2460 ChainVal = ChainVal.getValue(ChainVal->getNumValues()-2); 2461 assert(ChainVal.getValueType() == MVT::Other && "Not a chain?"); 2462 SelectionDAG::DAGNodeDeletedListener NDL( 2463 *CurDAG, [&](SDNode *N, SDNode *E) { 2464 std::replace(ChainNodesMatched.begin(), ChainNodesMatched.end(), N, 2465 static_cast<SDNode *>(nullptr)); 2466 }); 2467 if (ChainNode->getOpcode() != ISD::TokenFactor) 2468 ReplaceUses(ChainVal, InputChain); 2469 2470 // If the node became dead and we haven't already seen it, delete it. 2471 if (ChainNode != NodeToMatch && ChainNode->use_empty() && 2472 !std::count(NowDeadNodes.begin(), NowDeadNodes.end(), ChainNode)) 2473 NowDeadNodes.push_back(ChainNode); 2474 } 2475 } 2476 2477 if (!NowDeadNodes.empty()) 2478 CurDAG->RemoveDeadNodes(NowDeadNodes); 2479 2480 LLVM_DEBUG(dbgs() << "ISEL: Match complete!\n"); 2481 } |
下面的OPC_MarkGlueResults是由MarkGlueResultsMatcher对象输出的,这些对象用于标记会使用标志寄存器的节点(当然是通过序号)。我们已经看到在UpdateChainsAndGlue()里这些节点会被目标节点的值所替换(v7.0不再支持)。
SelectionDAGISel::SelectCodeCommon(续)
3250 case OPC_MarkGlueResults: {
3251 unsigned NumNodes = MatcherTable[MatcherIndex++];
3252
3253 // Read and remember all the glue-result nodes.
3254 for (unsigned i = 0; i != NumNodes; ++i) {
3255 unsigned RecNo = MatcherTable[MatcherIndex++];
3256 if (RecNo & 128)
3257 RecNo = GetVBR(RecNo, MatcherTable, MatcherIndex);
3258
3259 assert(RecNo < RecordedNodes.size() && "Invalid MarkGlueResults");
3260 GlueResultNodesMatched.push_back(RecordedNodes[RecNo].first.getNode());
3261 }
3262 continue;
3263 }
3264
3265 case OPC_CompleteMatch: {
3266 // The match has been completed, and any new nodes (if any) have been
3267 // created. Patch up references to the matched dag to use the newly
3268 // created nodes.
3269 unsigned NumResults = MatcherTable[MatcherIndex++];
3270
3271 for (unsigned i = 0; i != NumResults; ++i) {
3272 unsigned ResSlot = MatcherTable[MatcherIndex++];
3273 if (ResSlot & 128)
3274 ResSlot = GetVBR(ResSlot, MatcherTable, MatcherIndex);
3275
3276 assert(ResSlot < RecordedNodes.size() && "Invalid CompleteMatch");
3277 SDValue Res = RecordedNodes[ResSlot].first;
3278
3279 assert(i < NodeToMatch->getNumValues() &&
3280 NodeToMatch->getValueType(i) != MVT::Other &&
3281 NodeToMatch->getValueType(i) != MVT::Glue &&
3282 "Invalid number of results to complete!");
3283 assert((NodeToMatch->getValueType(i) == Res.getValueType() ||
3284 NodeToMatch->getValueType(i) == MVT::iPTR ||
3285 Res.getValueType() == MVT::iPTR ||
3286 NodeToMatch->getValueType(i).getSizeInBits() ==
3287 Res.getValueType().getSizeInBits()) &&
3288 "invalid replacement");
3289 CurDAG->ReplaceAllUsesOfValueWith(SDValue(NodeToMatch, i), Res); <- v7.0删除
ReplaceUses(SDValue(NodeToMatch, i), Res); <- v7.0增加
3290 }
3291
3292 // If the root node defines glue, add it to the glue nodes to update list. <- v7.0删除
3293 if (NodeToMatch->getValueType(NodeToMatch->getNumValues()-1) == MVT::Glue)
3294 GlueResultNodesMatched.push_back(NodeToMatch);
3295
3296 // Update chain and glue uses.
3297 UpdateChainsAndGlue(NodeToMatch, InputChain, ChainNodesMatched,
3298 InputGlue, GlueResultNodesMatched, false);
// Update chain uses. <- v7.0增加
UpdateChains(NodeToMatch, InputChain, ChainNodesMatched, false);
// If the root node defines glue, we need to update it to the glue result.
// TODO: This never happens in our tests and I think it can be removed /
// replaced with an assert, but if we do it this the way the change is
// NFC.
if (NodeToMatch->getValueType(NodeToMatch->getNumValues() - 1) ==
MVT::Glue &&
InputGlue.getNode())
ReplaceUses(SDValue(NodeToMatch, NodeToMatch->getNumValues() - 1),
InputGlue);
3299
3300 assert(NodeToMatch->use_empty() &&
3301 "Didn't replace all uses of the node?");
CurDAG->RemoveDeadNode(NodeToMatch); ß v7.0增加
3302
3303 // FIXME: We just return here, which interacts correctly with SelectRoot
3304 // above. We should fix this to not return an SDNode* anymore.
3305 return nullptr;
3306 }
3307 }
3308
3309 // If the code reached this point, then the match failed. See if there is
3310 // another child to try in the current 'Scope', otherwise pop it until we
3311 // find a case to check.
3312 DEBUG(dbgs() << " Match failed at index " << CurrentOpcodeIndex << "\n");
3313 ++NumDAGIselRetries;
3314 while (1) {
3315 if (MatchScopes.empty()) {
3316 CannotYetSelect(NodeToMatch);
3317 return nullptr;
3318 }
3319
3320 // Restore the interpreter state back to the point where the scope was
3321 // formed.
3322 MatchScope &LastScope = MatchScopes.back();
3323 RecordedNodes.resize(LastScope.NumRecordedNodes);
3324 NodeStack.clear();
3325 NodeStack.append(LastScope.NodeStack.begin(), LastScope.NodeStack.end());
3326 N = NodeStack.back();
3327
3328 if (LastScope.NumMatchedMemRefs != MatchedMemRefs.size())
3329 MatchedMemRefs.resize(LastScope.NumMatchedMemRefs);
3330 MatcherIndex = LastScope.FailIndex;
3331
3332 DEBUG(dbgs() << " Continuing at " << MatcherIndex << "\n");
3333
3334 InputChain = LastScope.InputChain;
3335 InputGlue = LastScope.InputGlue;
3336 if (!LastScope.HasChainNodesMatched)
3337 ChainNodesMatched.clear();
3338 if (!LastScope.HasGlueResultNodesMatched) <- v7.0删除
3339 GlueResultNodesMatched.clear();
3340
3341 // Check to see what the offset is at the new MatcherIndex. If it is zero
3342 // we have reached the end of this scope, otherwise we have another child
3343 // in the current scope to try.
3344 unsigned NumToSkip = MatcherTable[MatcherIndex++];
3345 if (NumToSkip & 128)
3346 NumToSkip = GetVBR(NumToSkip, MatcherTable, MatcherIndex);
3347
3348 // If we have another child in this scope to match, update FailIndex and
3349 // try it.
3350 if (NumToSkip != 0) {
3351 LastScope.FailIndex = MatcherIndex+NumToSkip;
3350 break;
3351 }
3352
3353 // End of this scope, pop it and try the next child in the containing
3354 // scope.
3355 MatchScopes.pop_back();
3356 }
3357 }
3358 }
至于标记OPC_CompleteMatch,它与OPC_EmitNode配合表示匹配完成。在前面OPC_EmitNode已经生成了一个MachineSDNode实例,并将它chain与glue以外的结果保存在RecordedNodes(3169 ~ 3176行)。在3281行的循环取出这些结果来替换原来值。在3303行,如果匹配DAG的根节点会修改标志寄存器(glue),也要记录在GlueResultNodesMatched里,随后在UpdateChainsAndGlue()里得到替换(这次调用的isMorphNodeTo是false)。
3312行至函数结束,是出错处理。每次匹配出错都会进入到这里,前进到同一个Scope的下一个分支,或者上一层Scope的下一个分支(如果当前Scope已到末尾)。