From 03f9197d62dddfb70e70acb5563518f589d29251 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Mon, 16 Sep 2013 16:43:19 +0000 Subject: TableGen: give asm match classes deterministic order. TableGen was sorting the entries in some of its internal data structures by pointer. This order filtered through to the final matching table and affected the diagnostics produced on bad assembly occasionally. It also turns out STL algorithms are ridiculously easy to misuse on containers with custom order methods. (No bugs before, or now that I know of, but plenty in the middle). This should fix the sanitizer bot, which ends up with weird pointers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190793 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/AsmMatcherEmitter.cpp | 69 ++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 23 deletions(-) (limited to 'utils') diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 0974b943f1..ff04d63d00 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -125,6 +125,13 @@ namespace { class AsmMatcherInfo; struct SubtargetFeatureInfo; +// Register sets are used as keys in some second-order sets TableGen creates +// when generating its data structures. This means that the order of two +// RegisterSets can be seen in the outputted AsmMatcher tables occasionally, and +// can even affect compiler output (at least seen in diagnostics produced when +// all matches fail). So we use a type that sorts them consistently. +typedef std::set RegisterSet; + class AsmMatcherEmitter { RecordKeeper &Records; public: @@ -185,7 +192,7 @@ struct ClassInfo { std::string ParserMethod; /// For register classes, the records for all the registers in this class. - std::set Registers; + RegisterSet Registers; /// For custom match classes, he diagnostic kind for when the predicate fails. std::string DiagnosticType; @@ -213,11 +220,11 @@ public: if (!isRegisterClass() || !RHS.isRegisterClass()) return false; - std::set Tmp; - std::insert_iterator< std::set > II(Tmp, Tmp.begin()); + RegisterSet Tmp; + std::insert_iterator II(Tmp, Tmp.begin()); std::set_intersection(Registers.begin(), Registers.end(), RHS.Registers.begin(), RHS.Registers.end(), - II); + II, LessRecordByID()); return !Tmp.empty(); } @@ -1057,6 +1064,18 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) { PrintFatalError(Rec->getLoc(), "operand has no match class!"); } +struct LessRegisterSet { + bool operator() (const RegisterSet &LHS, const RegisterSet & RHS) { + // std::set defines its own compariso "operator<", but it + // performs a lexicographical comparison by T's innate comparison + // for some reason. We don't want non-deterministic pointer + // comparisons so use this instead. + return std::lexicographical_compare(LHS.begin(), LHS.end(), + RHS.begin(), RHS.end(), + LessRecordByID()); + } +}; + void AsmMatcherInfo:: buildRegisterClasses(SmallPtrSet &SingletonRegisters) { const std::vector &Registers = @@ -1064,33 +1083,35 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { ArrayRef RegClassList = Target.getRegBank().getRegClasses(); + typedef std::set RegisterSetSet; + // The register sets used for matching. - std::set< std::set > RegisterSets; + RegisterSetSet RegisterSets; // Gather the defined sets. for (ArrayRef::const_iterator it = - RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) - RegisterSets.insert(std::set( + RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) + RegisterSets.insert(RegisterSet( (*it)->getOrder().begin(), (*it)->getOrder().end())); // Add any required singleton sets. for (SmallPtrSet::iterator it = SingletonRegisters.begin(), ie = SingletonRegisters.end(); it != ie; ++it) { Record *Rec = *it; - RegisterSets.insert(std::set(&Rec, &Rec + 1)); + RegisterSets.insert(RegisterSet(&Rec, &Rec + 1)); } // Introduce derived sets where necessary (when a register does not determine // a unique register set class), and build the mapping of registers to the set // they should classify to. - std::map > RegisterMap; + std::map RegisterMap; for (std::vector::const_iterator it = Registers.begin(), ie = Registers.end(); it != ie; ++it) { const CodeGenRegister &CGR = **it; // Compute the intersection of all sets containing this register. - std::set ContainingSet; + RegisterSet ContainingSet; - for (std::set< std::set >::iterator it = RegisterSets.begin(), + for (RegisterSetSet::iterator it = RegisterSets.begin(), ie = RegisterSets.end(); it != ie; ++it) { if (!it->count(CGR.TheDef)) continue; @@ -1100,11 +1121,12 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { continue; } - std::set Tmp; + RegisterSet Tmp; std::swap(Tmp, ContainingSet); - std::insert_iterator< std::set > II(ContainingSet, - ContainingSet.begin()); - std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II); + std::insert_iterator II(ContainingSet, + ContainingSet.begin()); + std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II, + LessRecordByID()); } if (!ContainingSet.empty()) { @@ -1114,9 +1136,9 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { } // Construct the register classes. - std::map, ClassInfo*> RegisterSetClasses; + std::map RegisterSetClasses; unsigned Index = 0; - for (std::set< std::set >::iterator it = RegisterSets.begin(), + for (RegisterSetSet::iterator it = RegisterSets.begin(), ie = RegisterSets.end(); it != ie; ++it, ++Index) { ClassInfo *CI = new ClassInfo(); CI->Kind = ClassInfo::RegisterClass0 + Index; @@ -1134,13 +1156,14 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { // Find the superclasses; we could compute only the subgroup lattice edges, // but there isn't really a point. - for (std::set< std::set >::iterator it = RegisterSets.begin(), + for (RegisterSetSet::iterator it = RegisterSets.begin(), ie = RegisterSets.end(); it != ie; ++it) { ClassInfo *CI = RegisterSetClasses[*it]; - for (std::set< std::set >::iterator it2 = RegisterSets.begin(), + for (RegisterSetSet::iterator it2 = RegisterSets.begin(), ie2 = RegisterSets.end(); it2 != ie2; ++it2) if (*it != *it2 && - std::includes(it2->begin(), it2->end(), it->begin(), it->end())) + std::includes(it2->begin(), it2->end(), it->begin(), it->end(), + LessRecordByID())) CI->SuperClasses.push_back(RegisterSetClasses[*it2]); } @@ -1152,8 +1175,8 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { Record *Def = RC.getDef(); if (!Def) continue; - ClassInfo *CI = RegisterSetClasses[std::set(RC.getOrder().begin(), - RC.getOrder().end())]; + ClassInfo *CI = RegisterSetClasses[RegisterSet(RC.getOrder().begin(), + RC.getOrder().end())]; if (CI->ValueName.empty()) { CI->ClassName = RC.getName(); CI->Name = "MCK_" + RC.getName(); @@ -1165,7 +1188,7 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { } // Populate the map for individual registers. - for (std::map >::iterator it = RegisterMap.begin(), + for (std::map::iterator it = RegisterMap.begin(), ie = RegisterMap.end(); it != ie; ++it) RegisterClasses[it->first] = RegisterSetClasses[it->second]; -- cgit v1.2.3