void MapTableEmitter::emitMapFuncBody(raw_ostream &OS, unsigned TableSize) { ListInit *ColFields = InstrMapDesc.getColFields(); const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols(); // Emit binary search algorithm to locate instructions in the // relation table. If found, return opcode value from the appropriate column // of the table. emitBinSearch(OS, TableSize); if (ValueCols.size() > 1) { for (unsigned i = 0, e = ValueCols.size(); i < e; i++) { ListInit *ColumnI = ValueCols[i]; for (unsigned j = 0, ColSize = ColumnI->size(); j < ColSize; ++j) { std::string ColName = ColFields->getElement(j)->getAsUnquotedString(); OS << " if (in" << ColName; OS << " == "; OS << ColName << "_" << ColumnI->getElement(j)->getAsUnquotedString(); if (j < ColumnI->size() - 1) OS << " && "; else OS << ")\n"; } OS << " return " << InstrMapDesc.getName(); OS << "Table[mid]["<<i+1<<"];\n"; } OS << " return -1;"; } else OS << " return " << InstrMapDesc.getName() << "Table[mid][1];\n"; OS <<"}\n\n"; }
static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { std::vector<Record*> InstrMapVec; InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); std::map<std::string, std::vector<Init*> > ColFieldValueMap; // Iterate over all InstrMapping records and create a map between column // fields and their possible values across all records. for (unsigned i = 0, e = InstrMapVec.size(); i < e; i++) { Record *CurMap = InstrMapVec[i]; ListInit *ColFields; ColFields = CurMap->getValueAsListInit("ColFields"); ListInit *List = CurMap->getValueAsListInit("ValueCols"); std::vector<ListInit*> ValueCols; unsigned ListSize = List->size(); for (unsigned j = 0; j < ListSize; j++) { ListInit *ListJ = dyn_cast<ListInit>(List->getElement(j)); if (ListJ->size() != ColFields->size()) PrintFatalError("Record `" + CurMap->getName() + "', field " "`ValueCols' entries don't match with the entries in 'ColFields' !"); ValueCols.push_back(ListJ); } for (unsigned j = 0, endCF = ColFields->size(); j < endCF; j++) { for (unsigned k = 0; k < ListSize; k++){ std::string ColName = ColFields->getElement(j)->getAsUnquotedString(); ColFieldValueMap[ColName].push_back((ValueCols[k])->getElement(j)); } } } for (std::map<std::string, std::vector<Init*> >::iterator II = ColFieldValueMap.begin(), IE = ColFieldValueMap.end(); II != IE; II++) { std::vector<Init*> FieldValues = (*II).second; // Delete duplicate entries from ColFieldValueMap for (unsigned i = 0; i < FieldValues.size() - 1; i++) { Init *CurVal = FieldValues[i]; for (unsigned j = i+1; j < FieldValues.size(); j++) { if (CurVal == FieldValues[j]) { FieldValues.erase(FieldValues.begin()+j); } } } // Emit enumerated values for the column fields. OS << "enum " << (*II).first << " {\n"; for (unsigned i = 0, endFV = FieldValues.size(); i < endFV; i++) { OS << "\t" << (*II).first << "_" << FieldValues[i]->getAsUnquotedString(); if (i != endFV - 1) OS << ",\n"; else OS << "\n};\n\n"; } } }
Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr, ListInit *CurValueCol) { ListInit *RowFields = InstrMapDesc.getRowFields(); std::vector<Init*> KeyValue; // Construct KeyValue using KeyInstr's values for RowFields. for (Init *RowField : RowFields->getValues()) { Init *KeyInstrVal = KeyInstr->getValue(RowField)->getValue(); KeyValue.push_back(KeyInstrVal); } // Get all the instructions that share the same KeyValue as the KeyInstr // in RowInstrMap. We search through these instructions to find a match // for the current column, i.e., the instruction which has the same values // as CurValueCol for all the fields in ColFields. const std::vector<Record*> &RelatedInstrVec = RowInstrMap[KeyValue]; ListInit *ColFields = InstrMapDesc.getColFields(); Record *MatchInstr = nullptr; for (unsigned i = 0, e = RelatedInstrVec.size(); i < e; i++) { bool MatchFound = true; Record *CurInstr = RelatedInstrVec[i]; for (unsigned j = 0, endCF = ColFields->size(); (j < endCF) && MatchFound; j++) { Init *ColFieldJ = ColFields->getElement(j); Init *CurInstrInit = CurInstr->getValue(ColFieldJ)->getValue(); std::string CurInstrVal = CurInstrInit->getAsUnquotedString(); Init *ColFieldJVallue = CurValueCol->getElement(j); MatchFound = (CurInstrVal == ColFieldJVallue->getAsUnquotedString()); } if (MatchFound) { if (MatchInstr) { // Already had a match // Error if multiple matches are found for a column. std::string KeyValueStr; for (Init *Value : KeyValue) { if (!KeyValueStr.empty()) KeyValueStr += ", "; KeyValueStr += Value->getAsString(); } PrintFatalError("Multiple matches found for `" + KeyInstr->getName() + "', for the relation `" + InstrMapDesc.getName() + "', row fields [" + KeyValueStr + "], column `" + CurValueCol->getAsString() + "'"); } MatchInstr = CurInstr; } } return MatchInstr; }
bool MapTableEmitter::isKeyColInstr(Record* CurInstr) { ListInit *ColFields = InstrMapDesc.getColFields(); ListInit *KeyCol = InstrMapDesc.getKeyCol(); // Check if the instruction is a KeyCol instruction. bool MatchFound = true; for (unsigned j = 0, endCF = ColFields->size(); (j < endCF) && MatchFound; j++) { RecordVal *ColFieldName = CurInstr->getValue(ColFields->getElement(j)); std::string CurInstrVal = ColFieldName->getValue()->getAsUnquotedString(); std::string KeyColValue = KeyCol->getElement(j)->getAsUnquotedString(); MatchFound = (CurInstrVal == KeyColValue); } return MatchFound; }
CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { TheDef = R; std::string DefName = R->getName(); ModRef = ReadWriteMem; isOverloaded = false; isCommutative = false; canThrow = false; isNoReturn = false; isNoDuplicate = false; isConvergent = false; if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!"); EnumName = std::string(DefName.begin()+4, DefName.end()); if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field. GCCBuiltinName = R->getValueAsString("GCCBuiltinName"); if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field. MSBuiltinName = R->getValueAsString("MSBuiltinName"); TargetPrefix = R->getValueAsString("TargetPrefix"); Name = R->getValueAsString("LLVMName"); if (Name == "") { // If an explicit name isn't specified, derive one from the DefName. Name = "llvm."; for (unsigned i = 0, e = EnumName.size(); i != e; ++i) Name += (EnumName[i] == '_') ? '.' : EnumName[i]; } else { // Verify it starts with "llvm.". if (Name.size() <= 5 || std::string(Name.begin(), Name.begin() + 5) != "llvm.") PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"); } // If TargetPrefix is specified, make sure that Name starts with // "llvm.<targetprefix>.". if (!TargetPrefix.empty()) { if (Name.size() < 6+TargetPrefix.size() || std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size()) != (TargetPrefix + ".")) PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." + TargetPrefix + ".'!"); } // Parse the list of return types. std::vector<MVT::SimpleValueType> OverloadedVTs; ListInit *TypeList = R->getValueAsListInit("RetTypes"); for (unsigned i = 0, e = TypeList->size(); i != e; ++i) { Record *TyEl = TypeList->getElementAsRecord(i); assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); MVT::SimpleValueType VT; if (TyEl->isSubClassOf("LLVMMatchType")) { unsigned MatchTy = TyEl->getValueAsInt("Number"); assert(MatchTy < OverloadedVTs.size() && "Invalid matching number!"); VT = OverloadedVTs[MatchTy]; // It only makes sense to use the extended and truncated vector element // variants with iAny types; otherwise, if the intrinsic is not // overloaded, all the types can be specified directly. assert(((!TyEl->isSubClassOf("LLVMExtendedType") && !TyEl->isSubClassOf("LLVMTruncatedType")) || VT == MVT::iAny || VT == MVT::vAny) && "Expected iAny or vAny type"); } else { VT = getValueType(TyEl->getValueAsDef("VT")); } if (MVT(VT).isOverloaded()) { OverloadedVTs.push_back(VT); isOverloaded = true; } // Reject invalid types. if (VT == MVT::isVoid) PrintFatalError("Intrinsic '" + DefName + " has void in result type list!"); IS.RetVTs.push_back(VT); IS.RetTypeDefs.push_back(TyEl); } // Parse the list of parameter types. TypeList = R->getValueAsListInit("ParamTypes"); for (unsigned i = 0, e = TypeList->size(); i != e; ++i) { Record *TyEl = TypeList->getElementAsRecord(i); assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); MVT::SimpleValueType VT; if (TyEl->isSubClassOf("LLVMMatchType")) { unsigned MatchTy = TyEl->getValueAsInt("Number"); assert(MatchTy < OverloadedVTs.size() && "Invalid matching number!"); VT = OverloadedVTs[MatchTy]; // It only makes sense to use the extended and truncated vector element // variants with iAny types; otherwise, if the intrinsic is not // overloaded, all the types can be specified directly. assert(((!TyEl->isSubClassOf("LLVMExtendedType") && !TyEl->isSubClassOf("LLVMTruncatedType") && !TyEl->isSubClassOf("LLVMVectorSameWidth")) || VT == MVT::iAny || VT == MVT::vAny) && "Expected iAny or vAny type"); } else VT = getValueType(TyEl->getValueAsDef("VT")); if (MVT(VT).isOverloaded()) { OverloadedVTs.push_back(VT); isOverloaded = true; } // Reject invalid types. if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) PrintFatalError("Intrinsic '" + DefName + " has void in result type list!"); IS.ParamVTs.push_back(VT); IS.ParamTypeDefs.push_back(TyEl); } // Parse the intrinsic properties. ListInit *PropList = R->getValueAsListInit("IntrProperties"); for (unsigned i = 0, e = PropList->size(); i != e; ++i) { Record *Property = PropList->getElementAsRecord(i); assert(Property->isSubClassOf("IntrinsicProperty") && "Expected a property!"); if (Property->getName() == "IntrNoMem") ModRef = NoMem; else if (Property->getName() == "IntrReadMem") ModRef = ModRefBehavior(ModRef & ~MR_Mod); else if (Property->getName() == "IntrWriteMem") ModRef = ModRefBehavior(ModRef & ~MR_Ref); else if (Property->getName() == "IntrArgMemOnly") ModRef = ModRefBehavior(ModRef & ~MR_Anywhere); else if (Property->getName() == "Commutative") isCommutative = true; else if (Property->getName() == "Throws") canThrow = true; else if (Property->getName() == "IntrNoDuplicate") isNoDuplicate = true; else if (Property->getName() == "IntrConvergent") isConvergent = true; else if (Property->getName() == "IntrNoReturn") isNoReturn = true; else if (Property->isSubClassOf("NoCapture")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); } else if (Property->isSubClassOf("Returned")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, Returned)); } else if (Property->isSubClassOf("ReadOnly")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadOnly)); } else if (Property->isSubClassOf("WriteOnly")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, WriteOnly)); } else if (Property->isSubClassOf("ReadNone")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone)); } else llvm_unreachable("Unknown property!"); } // Sort the argument attributes for later benefit. std::sort(ArgumentAttributes.begin(), ArgumentAttributes.end()); }
// Calculate all subregindices for Reg. Loopy subregs cause infinite recursion. RegisterMaps::SubRegMap &RegisterMaps::inferSubRegIndices(Record *Reg) { SubRegMap &SRM = SubReg[Reg]; if (!SRM.empty()) return SRM; std::vector<Record*> SubRegs = Reg->getValueAsListOfDefs("SubRegs"); std::vector<Record*> Indices = Reg->getValueAsListOfDefs("SubRegIndices"); if (SubRegs.size() != Indices.size()) throw "Register " + Reg->getName() + " SubRegIndices doesn't match SubRegs"; // First insert the direct subregs and make sure they are fully indexed. for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) { if (!SRM.insert(std::make_pair(Indices[i], SubRegs[i])).second) throw "SubRegIndex " + Indices[i]->getName() + " appears twice in Register " + Reg->getName(); inferSubRegIndices(SubRegs[i]); } // Keep track of inherited subregs and how they can be reached. // Register -> (SubRegIndex, SubRegIndex) typedef std::map<Record*, std::pair<Record*,Record*>, LessRecord> OrphanMap; OrphanMap Orphans; // Clone inherited subregs. Here the order is important - earlier subregs take // precedence. for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) { SubRegMap &M = SubReg[SubRegs[i]]; for (SubRegMap::iterator si = M.begin(), se = M.end(); si != se; ++si) if (!SRM.insert(*si).second) Orphans[si->second] = std::make_pair(Indices[i], si->first); } // Finally process the composites. ListInit *Comps = Reg->getValueAsListInit("CompositeIndices"); for (unsigned i = 0, e = Comps->size(); i != e; ++i) { DagInit *Pat = dynamic_cast<DagInit*>(Comps->getElement(i)); if (!Pat) throw "Invalid dag '" + Comps->getElement(i)->getAsString() + "' in CompositeIndices"; DefInit *BaseIdxInit = dynamic_cast<DefInit*>(Pat->getOperator()); if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex")) throw "Invalid SubClassIndex in " + Pat->getAsString(); // Resolve list of subreg indices into R2. Record *R2 = Reg; for (DagInit::const_arg_iterator di = Pat->arg_begin(), de = Pat->arg_end(); di != de; ++di) { DefInit *IdxInit = dynamic_cast<DefInit*>(*di); if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex")) throw "Invalid SubClassIndex in " + Pat->getAsString(); SubRegMap::const_iterator ni = SubReg[R2].find(IdxInit->getDef()); if (ni == SubReg[R2].end()) throw "Composite " + Pat->getAsString() + " refers to bad index in " + R2->getName(); R2 = ni->second; } // Insert composite index. Allow overriding inherited indices etc. SRM[BaseIdxInit->getDef()] = R2; // R2 is now directly addressable, no longer an orphan. Orphans.erase(R2); } // Now, Orphans contains the inherited subregisters without a direct index. if (!Orphans.empty()) { errs() << "Error: Register " << getQualifiedName(Reg) << " inherited subregisters without an index:\n"; for (OrphanMap::iterator i = Orphans.begin(), e = Orphans.end(); i != e; ++i) { errs() << " " << getQualifiedName(i->first) << " = " << i->second.first->getName() << ", " << i->second.second->getName() << "\n"; } abort(); } return SRM; }
const CodeGenRegister::SubRegMap & CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { // Only compute this map once. if (SubRegsComplete) return SubRegs; SubRegsComplete = true; std::vector<Record*> SubList = TheDef->getValueAsListOfDefs("SubRegs"); std::vector<Record*> Indices = TheDef->getValueAsListOfDefs("SubRegIndices"); if (SubList.size() != Indices.size()) throw TGError(TheDef->getLoc(), "Register " + getName() + " SubRegIndices doesn't match SubRegs"); // First insert the direct subregs and make sure they are fully indexed. for (unsigned i = 0, e = SubList.size(); i != e; ++i) { CodeGenRegister *SR = RegBank.getReg(SubList[i]); if (!SubRegs.insert(std::make_pair(Indices[i], SR)).second) throw TGError(TheDef->getLoc(), "SubRegIndex " + Indices[i]->getName() + " appears twice in Register " + getName()); } // Keep track of inherited subregs and how they can be reached. SmallVector<Orphan, 8> Orphans; // Clone inherited subregs and place duplicate entries on Orphans. // Here the order is important - earlier subregs take precedence. for (unsigned i = 0, e = SubList.size(); i != e; ++i) { CodeGenRegister *SR = RegBank.getReg(SubList[i]); const SubRegMap &Map = SR->getSubRegs(RegBank); // Add this as a super-register of SR now all sub-registers are in the list. // This creates a topological ordering, the exact order depends on the // order getSubRegs is called on all registers. SR->SuperRegs.push_back(this); for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE; ++SI) { if (!SubRegs.insert(*SI).second) Orphans.push_back(Orphan(SI->second, Indices[i], SI->first)); // Noop sub-register indexes are possible, so avoid duplicates. if (SI->second != SR) SI->second->SuperRegs.push_back(this); } } // Process the composites. ListInit *Comps = TheDef->getValueAsListInit("CompositeIndices"); for (unsigned i = 0, e = Comps->size(); i != e; ++i) { DagInit *Pat = dynamic_cast<DagInit*>(Comps->getElement(i)); if (!Pat) throw TGError(TheDef->getLoc(), "Invalid dag '" + Comps->getElement(i)->getAsString() + "' in CompositeIndices"); DefInit *BaseIdxInit = dynamic_cast<DefInit*>(Pat->getOperator()); if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex")) throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " + Pat->getAsString()); // Resolve list of subreg indices into R2. CodeGenRegister *R2 = this; for (DagInit::const_arg_iterator di = Pat->arg_begin(), de = Pat->arg_end(); di != de; ++di) { DefInit *IdxInit = dynamic_cast<DefInit*>(*di); if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex")) throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " + Pat->getAsString()); const SubRegMap &R2Subs = R2->getSubRegs(RegBank); SubRegMap::const_iterator ni = R2Subs.find(IdxInit->getDef()); if (ni == R2Subs.end()) throw TGError(TheDef->getLoc(), "Composite " + Pat->getAsString() + " refers to bad index in " + R2->getName()); R2 = ni->second; } // Insert composite index. Allow overriding inherited indices etc. SubRegs[BaseIdxInit->getDef()] = R2; // R2 is no longer an orphan. for (unsigned j = 0, je = Orphans.size(); j != je; ++j) if (Orphans[j].SubReg == R2) Orphans[j].SubReg = 0; } // Now Orphans contains the inherited subregisters without a direct index. // Create inferred indexes for all missing entries. for (unsigned i = 0, e = Orphans.size(); i != e; ++i) { Orphan &O = Orphans[i]; if (!O.SubReg) continue; SubRegs[RegBank.getCompositeSubRegIndex(O.First, O.Second, true)] = O.SubReg; } return SubRegs; }
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) : TheDef(R), Name(R->getName()), EnumValue(-1) { // Rename anonymous register classes. if (R->getName().size() > 9 && R->getName()[9] == '.') { static unsigned AnonCounter = 0; R->setName("AnonRegClass_"+utostr(AnonCounter++)); } std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes"); for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { Record *Type = TypeList[i]; if (!Type->isSubClassOf("ValueType")) throw "RegTypes list member '" + Type->getName() + "' does not derive from the ValueType class!"; VTs.push_back(getValueType(Type)); } assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); // Allocation order 0 is the full set. AltOrders provides others. const SetTheory::RecVec *Elements = RegBank.getSets().expand(R); ListInit *AltOrders = R->getValueAsListInit("AltOrders"); Orders.resize(1 + AltOrders->size()); // Default allocation order always contains all registers. for (unsigned i = 0, e = Elements->size(); i != e; ++i) { Orders[0].push_back((*Elements)[i]); Members.insert(RegBank.getReg((*Elements)[i])); } // Alternative allocation orders may be subsets. SetTheory::RecSet Order; for (unsigned i = 0, e = AltOrders->size(); i != e; ++i) { RegBank.getSets().evaluate(AltOrders->getElement(i), Order); Orders[1 + i].append(Order.begin(), Order.end()); // Verify that all altorder members are regclass members. while (!Order.empty()) { CodeGenRegister *Reg = RegBank.getReg(Order.back()); Order.pop_back(); if (!contains(Reg)) throw TGError(R->getLoc(), " AltOrder register " + Reg->getName() + " is not a class member"); } } // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags. ListInit *SRC = R->getValueAsListInit("SubRegClasses"); for (ListInit::const_iterator i = SRC->begin(), e = SRC->end(); i != e; ++i) { DagInit *DAG = dynamic_cast<DagInit*>(*i); if (!DAG) throw "SubRegClasses must contain DAGs"; DefInit *DAGOp = dynamic_cast<DefInit*>(DAG->getOperator()); Record *RCRec; if (!DAGOp || !(RCRec = DAGOp->getDef())->isSubClassOf("RegisterClass")) throw "Operator '" + DAG->getOperator()->getAsString() + "' in SubRegClasses is not a RegisterClass"; // Iterate over args, all SubRegIndex instances. for (DagInit::const_arg_iterator ai = DAG->arg_begin(), ae = DAG->arg_end(); ai != ae; ++ai) { DefInit *Idx = dynamic_cast<DefInit*>(*ai); Record *IdxRec; if (!Idx || !(IdxRec = Idx->getDef())->isSubClassOf("SubRegIndex")) throw "Argument '" + (*ai)->getAsString() + "' in SubRegClasses is not a SubRegIndex"; if (!SubRegClasses.insert(std::make_pair(IdxRec, RCRec)).second) throw "SubRegIndex '" + IdxRec->getName() + "' mentioned twice"; } } // Allow targets to override the size in bits of the RegisterClass. unsigned Size = R->getValueAsInt("Size"); Namespace = R->getValueAsString("Namespace"); SpillSize = Size ? Size : EVT(VTs[0]).getSizeInBits(); SpillAlignment = R->getValueAsInt("Alignment"); CopyCost = R->getValueAsInt("CopyCost"); Allocatable = R->getValueAsBit("isAllocatable"); AltOrderSelect = R->getValueAsCode("AltOrderSelect"); }
const CodeGenRegister::SubRegMap & CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { // Only compute this map once. if (SubRegsComplete) return SubRegs; SubRegsComplete = true; std::vector<Record*> SubList = TheDef->getValueAsListOfDefs("SubRegs"); std::vector<Record*> IdxList = TheDef->getValueAsListOfDefs("SubRegIndices"); if (SubList.size() != IdxList.size()) throw TGError(TheDef->getLoc(), "Register " + getName() + " SubRegIndices doesn't match SubRegs"); // First insert the direct subregs and make sure they are fully indexed. SmallVector<CodeGenSubRegIndex*, 8> Indices; for (unsigned i = 0, e = SubList.size(); i != e; ++i) { CodeGenRegister *SR = RegBank.getReg(SubList[i]); CodeGenSubRegIndex *Idx = RegBank.getSubRegIdx(IdxList[i]); Indices.push_back(Idx); if (!SubRegs.insert(std::make_pair(Idx, SR)).second) throw TGError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() + " appears twice in Register " + getName()); } // Keep track of inherited subregs and how they can be reached. SmallPtrSet<CodeGenRegister*, 8> Orphans; // Clone inherited subregs and place duplicate entries in Orphans. // Here the order is important - earlier subregs take precedence. for (unsigned i = 0, e = SubList.size(); i != e; ++i) { CodeGenRegister *SR = RegBank.getReg(SubList[i]); const SubRegMap &Map = SR->getSubRegs(RegBank); // Add this as a super-register of SR now all sub-registers are in the list. // This creates a topological ordering, the exact order depends on the // order getSubRegs is called on all registers. SR->SuperRegs.push_back(this); for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE; ++SI) { if (!SubRegs.insert(*SI).second) Orphans.insert(SI->second); // Noop sub-register indexes are possible, so avoid duplicates. if (SI->second != SR) SI->second->SuperRegs.push_back(this); } } // Expand any composed subreg indices. // If dsub_2 has ComposedOf = [qsub_1, dsub_0], and this register has a // qsub_1 subreg, add a dsub_2 subreg. Keep growing Indices and process // expanded subreg indices recursively. for (unsigned i = 0; i != Indices.size(); ++i) { CodeGenSubRegIndex *Idx = Indices[i]; const CodeGenSubRegIndex::CompMap &Comps = Idx->getComposites(); CodeGenRegister *SR = SubRegs[Idx]; const SubRegMap &Map = SR->getSubRegs(RegBank); // Look at the possible compositions of Idx. // They may not all be supported by SR. for (CodeGenSubRegIndex::CompMap::const_iterator I = Comps.begin(), E = Comps.end(); I != E; ++I) { SubRegMap::const_iterator SRI = Map.find(I->first); if (SRI == Map.end()) continue; // Idx + I->first doesn't exist in SR. // Add I->second as a name for the subreg SRI->second, assuming it is // orphaned, and the name isn't already used for something else. if (SubRegs.count(I->second) || !Orphans.erase(SRI->second)) continue; // We found a new name for the orphaned sub-register. SubRegs.insert(std::make_pair(I->second, SRI->second)); Indices.push_back(I->second); } } // Process the composites. ListInit *Comps = TheDef->getValueAsListInit("CompositeIndices"); for (unsigned i = 0, e = Comps->size(); i != e; ++i) { DagInit *Pat = dynamic_cast<DagInit*>(Comps->getElement(i)); if (!Pat) throw TGError(TheDef->getLoc(), "Invalid dag '" + Comps->getElement(i)->getAsString() + "' in CompositeIndices"); DefInit *BaseIdxInit = dynamic_cast<DefInit*>(Pat->getOperator()); if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex")) throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " + Pat->getAsString()); CodeGenSubRegIndex *BaseIdx = RegBank.getSubRegIdx(BaseIdxInit->getDef()); // Resolve list of subreg indices into R2. CodeGenRegister *R2 = this; for (DagInit::const_arg_iterator di = Pat->arg_begin(), de = Pat->arg_end(); di != de; ++di) { DefInit *IdxInit = dynamic_cast<DefInit*>(*di); if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex")) throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " + Pat->getAsString()); CodeGenSubRegIndex *Idx = RegBank.getSubRegIdx(IdxInit->getDef()); const SubRegMap &R2Subs = R2->getSubRegs(RegBank); SubRegMap::const_iterator ni = R2Subs.find(Idx); if (ni == R2Subs.end()) throw TGError(TheDef->getLoc(), "Composite " + Pat->getAsString() + " refers to bad index in " + R2->getName()); R2 = ni->second; } // Insert composite index. Allow overriding inherited indices etc. SubRegs[BaseIdx] = R2; // R2 is no longer an orphan. Orphans.erase(R2); } // Now Orphans contains the inherited subregisters without a direct index. // Create inferred indexes for all missing entries. // Work backwards in the Indices vector in order to compose subregs bottom-up. // Consider this subreg sequence: // // qsub_1 -> dsub_0 -> ssub_0 // // The qsub_1 -> dsub_0 composition becomes dsub_2, so the ssub_0 register // can be reached in two different ways: // // qsub_1 -> ssub_0 // dsub_2 -> ssub_0 // // We pick the latter composition because another register may have [dsub_0, // dsub_1, dsub_2] subregs without neccessarily having a qsub_1 subreg. The // dsub_2 -> ssub_0 composition can be shared. while (!Indices.empty() && !Orphans.empty()) { CodeGenSubRegIndex *Idx = Indices.pop_back_val(); CodeGenRegister *SR = SubRegs[Idx]; const SubRegMap &Map = SR->getSubRegs(RegBank); for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE; ++SI) if (Orphans.erase(SI->second)) SubRegs[RegBank.getCompositeSubRegIndex(Idx, SI->first)] = SI->second; } // Initialize RegUnitList. A register with no subregisters creates its own // unit. Otherwise, it inherits all its subregister's units. Because // getSubRegs is called recursively, this processes the register hierarchy in // postorder. // // TODO: We currently assume all register units correspond to a named "leaf" // register. We should also unify register units for ad-hoc register // aliases. This can be done by iteratively merging units for aliasing // registers using a worklist. assert(RegUnits.empty() && "Should only initialize RegUnits once"); if (SubRegs.empty()) { RegUnits.push_back(RegBank.newRegUnit()); } else { for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end(); I != E; ++I) { // Strangely a register may have itself as a subreg (self-cycle) e.g. XMM. CodeGenRegister *SR = I->second; if (SR == this) { if (RegUnits.empty()) RegUnits.push_back(RegBank.newRegUnit()); continue; } // Merge the subregister's units into this register's RegUnits. mergeRegUnits(RegUnits, SR->RegUnits); } } return SubRegs; }