X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fverify-uselistorder%2Fverify-uselistorder.cpp;h=76d3e04266f0614ec4ddbb8ce233b85f6872d3db;hb=7838818ad7bc483260188b139606f6751e96c5d4;hp=429daa13b98f0340d5a6172115b57f0269ddebff;hpb=b2b0ad4c75ce683da6f92de378c1c3422fc938a9;p=oota-llvm.git diff --git a/tools/verify-uselistorder/verify-uselistorder.cpp b/tools/verify-uselistorder/verify-uselistorder.cpp index 429daa13b98..76d3e04266f 100644 --- a/tools/verify-uselistorder/verify-uselistorder.cpp +++ b/tools/verify-uselistorder/verify-uselistorder.cpp @@ -34,6 +34,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/UseListOrder.h" +#include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -64,7 +65,7 @@ static cl::opt SaveTemps("save-temps", cl::desc("Save temp files"), static cl::opt NumShuffles("num-shuffles", cl::desc("Number of times to shuffle and verify use-lists"), - cl::init(5)); + cl::init(1)); namespace { @@ -167,7 +168,7 @@ std::unique_ptr TempFile::readBitcode(LLVMContext &Context) const { std::unique_ptr TempFile::readAssembly(LLVMContext &Context) const { DEBUG(dbgs() << " - read assembly\n"); SMDiagnostic Err; - std::unique_ptr M(ParseAssemblyFile(Filename, Err, Context)); + std::unique_ptr M = parseAssemblyFile(Filename, Err, Context); if (!M.get()) DEBUG(dbgs() << "error: "; Err.print("verify-use-list-order", dbgs())); return M; @@ -327,47 +328,44 @@ static bool matches(const ValueMapping &LM, const ValueMapping &RM) { return true; } -static bool verifyBitcodeUseListOrder(const Module &M) { - DEBUG(dbgs() << "*** verify-use-list-order: bitcode ***\n"); +static void verifyAfterRoundTrip(const Module &M, + std::unique_ptr OtherM) { + if (!OtherM) + report_fatal_error("parsing failed"); + if (verifyModule(*OtherM, &errs())) + report_fatal_error("verification failed"); + if (!matches(ValueMapping(M), ValueMapping(*OtherM))) + report_fatal_error("use-list order changed"); +} +static void verifyBitcodeUseListOrder(const Module &M) { + errs() << "*** verify-use-list-order: bitcode ***\n"; TempFile F; if (F.init("bc")) - return false; + report_fatal_error("failed to initialize bitcode file"); if (F.writeBitcode(M)) - return false; + report_fatal_error("failed to write bitcode"); LLVMContext Context; - std::unique_ptr OtherM = F.readBitcode(Context); - if (!OtherM) - return false; - - return matches(ValueMapping(M), ValueMapping(*OtherM)); + verifyAfterRoundTrip(M, F.readBitcode(Context)); } -static bool verifyAssemblyUseListOrder(const Module &M) { - DEBUG(dbgs() << "*** verify-use-list-order: assembly ***\n"); +static void verifyAssemblyUseListOrder(const Module &M) { + errs() << "*** verify-use-list-order: assembly ***\n"; TempFile F; if (F.init("ll")) - return false; + report_fatal_error("failed to initialize assembly file"); if (F.writeAssembly(M)) - return false; + report_fatal_error("failed to write assembly"); LLVMContext Context; - std::unique_ptr OtherM = F.readAssembly(Context); - if (!OtherM) - return false; - - return matches(ValueMapping(M), ValueMapping(*OtherM)); + verifyAfterRoundTrip(M, F.readAssembly(Context)); } static void verifyUseListOrder(const Module &M) { - if (!verifyBitcodeUseListOrder(M)) - report_fatal_error("bitcode use-list order changed"); - - if (shouldPreserveAssemblyUseListOrder()) - if (!verifyAssemblyUseListOrder(M)) - report_fatal_error("assembly use-list order changed"); + verifyBitcodeUseListOrder(M); + verifyAssemblyUseListOrder(M); } static void shuffleValueUseLists(Value *V, std::minstd_rand0 &Gen, @@ -413,43 +411,70 @@ static void shuffleValueUseLists(Value *V, std::minstd_rand0 &Gen, }); } -/// Shuffle all use-lists in a module. -void shuffleUseLists(Module &M, unsigned SeedOffset) { - DEBUG(dbgs() << "*** shuffle-use-lists ***\n"); - std::minstd_rand0 Gen(std::minstd_rand0::default_seed + SeedOffset); - DenseSet Seen; +static void reverseValueUseLists(Value *V, DenseSet &Seen) { + if (!Seen.insert(V).second) + return; - // Shuffle the use-list of each value that would be serialized to an IR file - // (bitcode or assembly). - auto shuffle = [&](Value *V) { shuffleValueUseLists(V, Gen, Seen); }; + if (auto *C = dyn_cast(V)) + if (!isa(C)) + for (Value *Op : C->operands()) + reverseValueUseLists(Op, Seen); + if (V->use_empty() || std::next(V->use_begin()) == V->use_end()) + // Nothing to shuffle for 0 or 1 users. + return; + + DEBUG({ + dbgs() << "V = "; + V->dump(); + for (const Use &U : V->uses()) { + dbgs() << " - order: op = " << U.getOperandNo() << ", U = "; + U.getUser()->dump(); + } + dbgs() << " => reverse\n"; + }); + + V->reverseUseList(); + + DEBUG({ + for (const Use &U : V->uses()) { + dbgs() << " - order: op = " << U.getOperandNo() << ", U = "; + U.getUser()->dump(); + } + }); +} + +template +static void changeUseLists(Module &M, Changer changeValueUseList) { + // Visit every value that would be serialized to an IR file. + // // Globals. for (GlobalVariable &G : M.globals()) - shuffle(&G); + changeValueUseList(&G); for (GlobalAlias &A : M.aliases()) - shuffle(&A); + changeValueUseList(&A); for (Function &F : M) - shuffle(&F); + changeValueUseList(&F); // Constants used by globals. for (GlobalVariable &G : M.globals()) if (G.hasInitializer()) - shuffle(G.getInitializer()); + changeValueUseList(G.getInitializer()); for (GlobalAlias &A : M.aliases()) - shuffle(A.getAliasee()); + changeValueUseList(A.getAliasee()); for (Function &F : M) if (F.hasPrefixData()) - shuffle(F.getPrefixData()); + changeValueUseList(F.getPrefixData()); // Function bodies. for (Function &F : M) { for (Argument &A : F.args()) - shuffle(&A); + changeValueUseList(&A); for (BasicBlock &BB : F) - shuffle(&BB); + changeValueUseList(&BB); for (BasicBlock &BB : F) for (Instruction &I : BB) - shuffle(&I); + changeValueUseList(&I); // Constants used by instructions. for (BasicBlock &BB : F) @@ -457,9 +482,25 @@ void shuffleUseLists(Module &M, unsigned SeedOffset) { for (Value *Op : I.operands()) if ((isa(Op) && !isa(*Op)) || isa(Op)) - shuffle(Op); + changeValueUseList(Op); } + if (verifyModule(M, &errs())) + report_fatal_error("verification failed"); +} + +static void shuffleUseLists(Module &M, unsigned SeedOffset) { + errs() << "*** shuffle-use-lists ***\n"; + std::minstd_rand0 Gen(std::minstd_rand0::default_seed + SeedOffset); + DenseSet Seen; + changeUseLists(M, [&](Value *V) { shuffleValueUseLists(V, Gen, Seen); }); + DEBUG(dbgs() << "\n"); +} + +static void reverseUseLists(Module &M) { + errs() << "*** reverse-use-lists ***\n"; + DenseSet Seen; + changeUseLists(M, [&](Value *V) { reverseValueUseLists(V, Seen); }); DEBUG(dbgs() << "\n"); } @@ -486,21 +527,34 @@ int main(int argc, char **argv) { Err.print(argv[0], errs()); return 1; } + if (verifyModule(*M, &errs())) + report_fatal_error("verification failed"); - DEBUG(dbgs() << "*** verify-use-list-order ***\n"); + errs() << "*** verify-use-list-order ***\n"; + // Can't verify if order isn't preserved. if (!shouldPreserveBitcodeUseListOrder()) { - // Can't verify if order isn't preserved. - DEBUG(dbgs() << "warning: cannot verify bitcode; " - "try -preserve-bc-use-list-order\n"); - return 0; + errs() << "warning: forcing -preserve-bc-use-list-order\n"; + setPreserveBitcodeUseListOrder(true); + } + if (!shouldPreserveAssemblyUseListOrder()) { + errs() << "warning: forcing -preserve-ll-use-list-order\n"; + setPreserveAssemblyUseListOrder(true); } + // Verify the use lists now and after reversing them. + verifyUseListOrder(*M); + reverseUseLists(*M); + verifyUseListOrder(*M); + for (unsigned I = 0, E = NumShuffles; I != E; ++I) { - DEBUG(dbgs() << "*** iteration: " << I << " ***\n"); + errs() << "*** shuffle iteration: " << I + 1 << " of " << E << " ***\n"; - // Shuffle with a different seed each time so that use-lists that aren't - // modified the first time are likely to be modified the next time. + // Shuffle with a different (deterministic) seed each time. shuffleUseLists(*M, I); + + // Verify again before and after reversing. + verifyUseListOrder(*M); + reverseUseLists(*M); verifyUseListOrder(*M); }