diff --git a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp --- a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp @@ -357,7 +357,7 @@ // This map keeps track of all the new definitions for an instruction. This // information is needed when restoring SSA form after cloning blocks. -typedef DenseMap> DefMap; +typedef MapVector> DefMap; inline raw_ostream &operator<<(raw_ostream &OS, const PathType &Path) { OS << "< "; @@ -1126,6 +1126,9 @@ /// Add new value mappings to the DefMap to keep track of all new definitions /// for a particular instruction. These will be used while updating SSA form. void updateDefMap(DefMap &NewDefs, ValueToValueMapTy &VMap) { + std::vector> NewDefsVector; + NewDefsVector.reserve(VMap.size()); + for (auto Entry : VMap) { Instruction *Inst = dyn_cast(const_cast(Entry.first)); @@ -1138,11 +1141,20 @@ if (!Cloned) continue; - if (NewDefs.find(Inst) == NewDefs.end()) - NewDefs[Inst] = {Cloned}; - else - NewDefs[Inst].push_back(Cloned); + NewDefsVector.push_back({Inst, Cloned}); } + + // Sort the defs to get deterministic insertion order into NewDefs. + sort(NewDefsVector, [](const auto &KV1, const auto &KV2) { + auto [Instr1, Cloned1] = KV1; + auto [Instr2, Cloned2] = KV2; + if (Instr1 == Instr2) + return Cloned1->comesBefore(Cloned2); + return Instr1->comesBefore(Instr2); + }); + + for (const auto &[Inst, Cloned] : NewDefsVector) + NewDefs[Inst].push_back(Cloned); } /// Update the last branch of a particular cloned path to point to the correct