Fix non-determinism in DAGISel emitter.

- This manifested as non-determinism in the .inc output in rare cases (when two
   distinct patterns ended up being equivalent, which is rather rare). That
   meant the pattern matching was non-deterministic, which could eventually mean
   the code generator selected different instructions based on the arch.

 - It's probably worth making the DAGISel ensure a total ordering (or force the
   user to), but the simple fix here is to totally order the Record* maps based
   on a unique ID.

 - PR4672, PR4711.

Yay:
--
ddunbar@giles:~$ cat ~/llvm.obj.64/lib/Target/*/*.inc | shasum
d1099ff34b21459a5a3e7021c225c080e6017ece  -
ddunbar@giles:~$ cat ~/llvm.obj.ppc/lib/Target/*/*.inc | shasum
d1099ff34b21459a5a3e7021c225c080e6017ece  -
--

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79846 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Daniel Dunbar 2009-08-23 09:47:37 +00:00
parent ae60324d46
commit 6f5cc82686
4 changed files with 23 additions and 7 deletions

View File

@ -100,6 +100,9 @@ bool isExtVectorInVTs(const std::vector<unsigned char> &EVTs) {
} // end namespace EEVT. } // end namespace EEVT.
} // end namespace llvm. } // end namespace llvm.
bool RecordPtrCmp::operator()(const Record *LHS, const Record *RHS) const {
return LHS->getID() < RHS->getID();
}
/// Dependent variable map for CodeGenDAGPattern variant generation /// Dependent variable map for CodeGenDAGPattern variant generation
typedef std::map<std::string, int> DepVarMap; typedef std::map<std::string, int> DepVarMap;

View File

@ -462,6 +462,10 @@ struct PatternToMatch {
std::string getPredicateCheck() const; std::string getPredicateCheck() const;
}; };
// Deterministic comparison of Record*.
struct RecordPtrCmp {
bool operator()(const Record *LHS, const Record *RHS) const;
};
class CodeGenDAGPatterns { class CodeGenDAGPatterns {
RecordKeeper &Records; RecordKeeper &Records;
@ -469,12 +473,12 @@ class CodeGenDAGPatterns {
std::vector<CodeGenIntrinsic> Intrinsics; std::vector<CodeGenIntrinsic> Intrinsics;
std::vector<CodeGenIntrinsic> TgtIntrinsics; std::vector<CodeGenIntrinsic> TgtIntrinsics;
std::map<Record*, SDNodeInfo> SDNodes; std::map<Record*, SDNodeInfo, RecordPtrCmp> SDNodes;
std::map<Record*, std::pair<Record*, std::string> > SDNodeXForms; std::map<Record*, std::pair<Record*, std::string>, RecordPtrCmp> SDNodeXForms;
std::map<Record*, ComplexPattern> ComplexPatterns; std::map<Record*, ComplexPattern, RecordPtrCmp> ComplexPatterns;
std::map<Record*, TreePattern*> PatternFragments; std::map<Record*, TreePattern*, RecordPtrCmp> PatternFragments;
std::map<Record*, DAGDefaultOperand> DefaultOperands; std::map<Record*, DAGDefaultOperand, RecordPtrCmp> DefaultOperands;
std::map<Record*, DAGInstruction> Instructions; std::map<Record*, DAGInstruction, RecordPtrCmp> Instructions;
// Specific SDNode definitions: // Specific SDNode definitions:
Record *intrinsic_void_sdnode; Record *intrinsic_void_sdnode;

View File

@ -1319,6 +1319,8 @@ void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
if (PrintSem) OS << ";\n"; if (PrintSem) OS << ";\n";
} }
unsigned Record::LastID = 0;
void Record::setName(const std::string &Name) { void Record::setName(const std::string &Name) {
if (Records.getDef(getName()) == this) { if (Records.getDef(getName()) == this) {
Records.removeDef(getName()); Records.removeDef(getName());

View File

@ -1220,6 +1220,10 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
} }
class Record { class Record {
static unsigned LastID;
// Unique record ID.
unsigned ID;
std::string Name; std::string Name;
SMLoc Loc; SMLoc Loc;
std::vector<std::string> TemplateArgs; std::vector<std::string> TemplateArgs;
@ -1227,9 +1231,12 @@ class Record {
std::vector<Record*> SuperClasses; std::vector<Record*> SuperClasses;
public: public:
explicit Record(const std::string &N, SMLoc loc) : Name(N), Loc(loc) {} explicit Record(const std::string &N, SMLoc loc) :
ID(LastID++), Name(N), Loc(loc) {}
~Record() {} ~Record() {}
unsigned getID() const { return ID; }
const std::string &getName() const { return Name; } const std::string &getName() const { return Name; }
void setName(const std::string &Name); // Also updates RecordKeeper. void setName(const std::string &Name); // Also updates RecordKeeper.