diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-08-05 17:49:48 +0000 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-08-05 17:49:48 +0000 |
commit | 5a511b59c5571097e9cec617873168f55a8f2e0c (patch) | |
tree | 08755bde5a2c4060314b11d5580280dfa13d0ffa /llvm/lib/Bitcode | |
parent | 00c9b6461f65380deed20676147083a6e8c66c3e (diff) | |
download | bcm5719-llvm-5a511b59c5571097e9cec617873168f55a8f2e0c.tar.gz bcm5719-llvm-5a511b59c5571097e9cec617873168f55a8f2e0c.zip |
BitcodeReader: Fix non-determinism in use-list order
`BasicBlockFwdRefs` (and `BlockAddrFwdRefs` before it) was being emptied
in a non-deterministic order. When predicting use-list order I've
worked around this another way, but even when parsing lazily (and we
can't recreate use-list order) use-lists should be deterministic.
Make them so by using a side-queue of functions with forward-referenced
blocks that gets visited in order.
llvm-svn: 214899
Diffstat (limited to 'llvm/lib/Bitcode')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.h | 2 |
2 files changed, 15 insertions, 3 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 85dde397916..79085248770 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -38,9 +38,14 @@ std::error_code BitcodeReader::materializeForwardReferencedFunctions() { // Prevent recursion. WillMaterializeAllForwardRefs = true; - while (!BasicBlockFwdRefs.empty()) { - Function *F = BasicBlockFwdRefs.begin()->first; + while (!BasicBlockFwdRefQueue.empty()) { + Function *F = BasicBlockFwdRefQueue.front(); + BasicBlockFwdRefQueue.pop_front(); assert(F && "Expected valid function"); + if (!BasicBlockFwdRefs.count(F)) + // Already materialized. + continue; + // Check for a function that isn't materializable to prevent an infinite // loop. When parsing a blockaddress stored in a global variable, there // isn't a trivial way to check if a function will have a body without a @@ -52,6 +57,7 @@ std::error_code BitcodeReader::materializeForwardReferencedFunctions() { if (std::error_code EC = Materialize(F)) return EC; } + assert(BasicBlockFwdRefs.empty() && "Function missing from queue"); // Reset state. WillMaterializeAllForwardRefs = false; @@ -72,6 +78,7 @@ void BitcodeReader::FreeState() { MDKindMap.clear(); assert(BasicBlockFwdRefs.empty() && "Unresolved blockaddress fwd references"); + BasicBlockFwdRefQueue.clear(); } //===----------------------------------------------------------------------===// @@ -1629,7 +1636,10 @@ std::error_code BitcodeReader::ParseConstants() { // Otherwise insert a placeholder and remember it so it can be inserted // when the function is parsed. BB = BasicBlock::Create(Context); - BasicBlockFwdRefs[Fn].emplace_back(BBID, BB); + auto &FwdBBs = BasicBlockFwdRefs[Fn]; + if (FwdBBs.empty()) + BasicBlockFwdRefQueue.push_back(Fn); + FwdBBs.emplace_back(BBID, BB); } V = BlockAddress::get(Fn, BB); break; diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.h b/llvm/lib/Bitcode/Reader/BitcodeReader.h index a25ab37a4e3..0b3c1c17c49 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.h +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.h @@ -22,6 +22,7 @@ #include "llvm/IR/OperandTraits.h" #include "llvm/IR/Type.h" #include "llvm/IR/ValueHandle.h" +#include <deque> #include <system_error> #include <vector> @@ -183,6 +184,7 @@ class BitcodeReader : public GVMaterializer { /// inserted lazily into functions when they're loaded. typedef std::pair<unsigned, BasicBlock *> BasicBlockRefTy; DenseMap<Function *, std::vector<BasicBlockRefTy>> BasicBlockFwdRefs; + std::deque<Function *> BasicBlockFwdRefQueue; /// UseRelativeIDs - Indicates that we are using a new encoding for /// instruction operands where most operands in the current |