summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2014-07-25 17:13:03 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2014-07-25 17:13:03 +0000
commit4b4d8ecde10a5be00a95bd7767ecd7519eef8dc2 (patch)
tree6a85c9ddb7df63c43faf2e7f900ee5c5199312f7 /llvm/lib/Transforms
parent29459ae83c8177c858f459a6392fdad37cbc1ef4 (diff)
downloadbcm5719-llvm-4b4d8ecde10a5be00a95bd7767ecd7519eef8dc2.tar.gz
bcm5719-llvm-4b4d8ecde10a5be00a95bd7767ecd7519eef8dc2.zip
Move -verify-use-list-order into llvm-uselistorder
Ugh. Turns out not even transformation passes link in how to read IR. I sincerely believe the buildbots will finally agree with my system after this though. (I don't really understand why all of this has been working on my system, but not on all the buildbots.) Create a new tool called llvm-uselistorder to use for verifying use-list order. For now, just dump everything from the (now defunct) -verify-use-list-order pass into the tool. This might be a better way to test use-list order anyway. Part of PR5680. llvm-svn: 213957
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/IPO/CMakeLists.txt1
-rw-r--r--llvm/lib/Transforms/IPO/IPO.cpp1
-rw-r--r--llvm/lib/Transforms/IPO/VerifyUseListOrder.cpp370
3 files changed, 0 insertions, 372 deletions
diff --git a/llvm/lib/Transforms/IPO/CMakeLists.txt b/llvm/lib/Transforms/IPO/CMakeLists.txt
index 070ecfdc143..90c1c33e6dc 100644
--- a/llvm/lib/Transforms/IPO/CMakeLists.txt
+++ b/llvm/lib/Transforms/IPO/CMakeLists.txt
@@ -20,7 +20,6 @@ add_llvm_library(LLVMipo
PruneEH.cpp
StripDeadPrototypes.cpp
StripSymbols.cpp
- VerifyUseListOrder.cpp
)
add_dependencies(LLVMipo intrinsics_gen)
diff --git a/llvm/lib/Transforms/IPO/IPO.cpp b/llvm/lib/Transforms/IPO/IPO.cpp
index 5dce2d6b407..b4d31d8d6fc 100644
--- a/llvm/lib/Transforms/IPO/IPO.cpp
+++ b/llvm/lib/Transforms/IPO/IPO.cpp
@@ -44,7 +44,6 @@ void llvm::initializeIPO(PassRegistry &Registry) {
initializeStripDebugDeclarePass(Registry);
initializeStripDeadDebugInfoPass(Registry);
initializeStripNonDebugSymbolsPass(Registry);
- initializeVerifyUseListOrderPass(Registry);
initializeBarrierNoopPass(Registry);
}
diff --git a/llvm/lib/Transforms/IPO/VerifyUseListOrder.cpp b/llvm/lib/Transforms/IPO/VerifyUseListOrder.cpp
deleted file mode 100644
index 16a88e3d9a1..00000000000
--- a/llvm/lib/Transforms/IPO/VerifyUseListOrder.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-//===- VerifyUseListOrder.cpp - Use List Order Verifier ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Pass to verify use-list order doesn't change after serialization.
-//
-// Despite it being a verifier, this pass *does* transform the module, since it
-// shuffles the use-list of every value.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Transforms/IPO.h"
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/AsmParser/Parser.h"
-#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
-#include "llvm/IR/UseListOrder.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SourceMgr.h"
-
-using namespace llvm;
-
-#define DEBUG_TYPE "use-list-order"
-
-namespace {
-
-struct TempFile {
- std::string Filename;
- FileRemover Remover;
- bool init(const std::string &Ext);
- bool writeBitcode(const Module &M) const;
- bool writeAssembly(const Module &M) const;
- std::unique_ptr<Module> readBitcode(LLVMContext &Context) const;
- std::unique_ptr<Module> readAssembly(LLVMContext &Context) const;
-};
-
-struct ValueMapping {
- DenseMap<const Value *, unsigned> IDs;
- std::vector<const Value *> Values;
-
- /// \brief Construct a value mapping for module.
- ///
- /// Creates mapping from every value in \c M to an ID. This mapping includes
- /// un-referencable values.
- ///
- /// Every \a Value that gets serialized in some way should be represented
- /// here. The order needs to be deterministic, but it's unnecessary to match
- /// the value-ids in the bitcode writer.
- ///
- /// All constants that are referenced by other values are included in the
- /// mapping, but others -- which wouldn't be serialized -- are not.
- ValueMapping(const Module &M);
-
- /// \brief Map a value.
- ///
- /// Maps a value. If it's a constant, maps all of its operands first.
- void map(const Value *V);
- unsigned lookup(const Value *V) const { return IDs.lookup(V); }
-};
-
-} // end namespace
-
-bool TempFile::init(const std::string &Ext) {
- SmallVector<char, 64> Vector;
- DEBUG(dbgs() << " - create-temp-file\n");
- if (auto EC = sys::fs::createTemporaryFile("use-list-order", Ext, Vector)) {
- (void)EC;
- DEBUG(dbgs() << "error: " << EC.message() << "\n");
- return true;
- }
- assert(!Vector.empty());
-
- Filename.assign(Vector.data(), Vector.data() + Vector.size());
- Remover.setFile(Filename);
- DEBUG(dbgs() << " - filename = " << Filename << "\n");
- return false;
-}
-
-bool TempFile::writeBitcode(const Module &M) const {
- DEBUG(dbgs() << " - write bitcode\n");
- std::string ErrorInfo;
- raw_fd_ostream OS(Filename.c_str(), ErrorInfo, sys::fs::F_None);
- if (!ErrorInfo.empty()) {
- DEBUG(dbgs() << "error: " << ErrorInfo << "\n");
- return true;
- }
-
- WriteBitcodeToFile(&M, OS);
- return false;
-}
-
-bool TempFile::writeAssembly(const Module &M) const {
- DEBUG(dbgs() << " - write assembly\n");
- std::string ErrorInfo;
- raw_fd_ostream OS(Filename.c_str(), ErrorInfo, sys::fs::F_Text);
- if (!ErrorInfo.empty()) {
- DEBUG(dbgs() << "error: " << ErrorInfo << "\n");
- return true;
- }
-
- OS << M;
- return false;
-}
-
-std::unique_ptr<Module> TempFile::readBitcode(LLVMContext &Context) const {
- DEBUG(dbgs() << " - read bitcode\n");
- ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOr =
- MemoryBuffer::getFile(Filename);
- if (!BufferOr) {
- DEBUG(dbgs() << "error: " << BufferOr.getError().message() << "\n");
- return nullptr;
- }
-
- std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOr.get());
- ErrorOr<Module *> ModuleOr = parseBitcodeFile(Buffer.release(), Context);
- if (!ModuleOr) {
- DEBUG(dbgs() << "error: " << ModuleOr.getError().message() << "\n");
- return nullptr;
- }
- return std::unique_ptr<Module>(ModuleOr.get());
-}
-
-std::unique_ptr<Module> TempFile::readAssembly(LLVMContext &Context) const {
- DEBUG(dbgs() << " - read assembly\n");
- SMDiagnostic Err;
- std::unique_ptr<Module> M(ParseAssemblyFile(Filename, Err, Context));
- if (!M.get())
- DEBUG(dbgs() << "error: "; Err.print("verify-use-list-order", dbgs()));
- return M;
-}
-
-ValueMapping::ValueMapping(const Module &M) {
- // Every value should be mapped, including things like void instructions and
- // basic blocks that are kept out of the ValueEnumerator.
- //
- // The current mapping order makes it easier to debug the tables. It happens
- // to be similar to the ID mapping when writing ValueEnumerator, but they
- // aren't (and needn't be) in sync.
-
- // Globals.
- for (const GlobalVariable &G : M.globals())
- map(&G);
- for (const GlobalAlias &A : M.aliases())
- map(&A);
- for (const Function &F : M)
- map(&F);
-
- // Constants used by globals.
- for (const GlobalVariable &G : M.globals())
- if (G.hasInitializer())
- map(G.getInitializer());
- for (const GlobalAlias &A : M.aliases())
- map(A.getAliasee());
- for (const Function &F : M)
- if (F.hasPrefixData())
- map(F.getPrefixData());
-
- // Function bodies.
- for (const Function &F : M) {
- for (const Argument &A : F.args())
- map(&A);
- for (const BasicBlock &BB : F)
- map(&BB);
- for (const BasicBlock &BB : F)
- for (const Instruction &I : BB)
- map(&I);
-
- // Constants used by instructions.
- for (const BasicBlock &BB : F)
- for (const Instruction &I : BB)
- for (const Value *Op : I.operands())
- if ((isa<Constant>(Op) && !isa<GlobalValue>(*Op)) ||
- isa<InlineAsm>(Op))
- map(Op);
- }
-}
-
-void ValueMapping::map(const Value *V) {
- if (IDs.lookup(V))
- return;
-
- if (auto *C = dyn_cast<Constant>(V))
- if (!isa<GlobalValue>(C))
- for (const Value *Op : C->operands())
- map(Op);
-
- Values.push_back(V);
- IDs[V] = Values.size();
-}
-
-#ifndef NDEBUG
-static void dumpMapping(const ValueMapping &VM) {
- dbgs() << "value-mapping (size = " << VM.Values.size() << "):\n";
- for (unsigned I = 0, E = VM.Values.size(); I != E; ++I) {
- dbgs() << " - id = " << I << ", value = ";
- VM.Values[I]->dump();
- }
-}
-
-static void debugValue(const ValueMapping &M, unsigned I, StringRef Desc) {
- const Value *V = M.Values[I];
- dbgs() << " - " << Desc << " value = ";
- V->dump();
- for (const Use &U : V->uses()) {
- dbgs() << " => use: op = " << U.getOperandNo()
- << ", user-id = " << M.IDs.lookup(U.getUser()) << ", user = ";
- U.getUser()->dump();
- }
-}
-
-static void debugUserMismatch(const ValueMapping &L, const ValueMapping &R,
- unsigned I) {
- dbgs() << " - fail: user mismatch: ID = " << I << "\n";
- debugValue(L, I, "LHS");
- debugValue(R, I, "RHS");
-
- dbgs() << "\nlhs-";
- dumpMapping(L);
- dbgs() << "\nrhs-";
- dumpMapping(R);
-}
-
-static void debugSizeMismatch(const ValueMapping &L, const ValueMapping &R) {
- dbgs() << " - fail: map size: " << L.Values.size()
- << " != " << R.Values.size() << "\n";
- dbgs() << "\nlhs-";
- dumpMapping(L);
- dbgs() << "\nrhs-";
- dumpMapping(R);
-}
-#endif
-
-static bool matches(const ValueMapping &LM, const ValueMapping &RM) {
- DEBUG(dbgs() << "compare value maps\n");
- if (LM.Values.size() != RM.Values.size()) {
- DEBUG(debugSizeMismatch(LM, RM));
- return false;
- }
-
- // This mapping doesn't include dangling constant users, since those don't
- // get serialized. However, checking if users are constant and calling
- // isConstantUsed() on every one is very expensive. Instead, just check if
- // the user is mapped.
- auto skipUnmappedUsers =
- [&](Value::const_use_iterator &U, Value::const_use_iterator E,
- const ValueMapping &M) {
- while (U != E && !M.lookup(U->getUser()))
- ++U;
- };
-
- // Iterate through all values, and check that both mappings have the same
- // users.
- for (unsigned I = 0, E = LM.Values.size(); I != E; ++I) {
- const Value *L = LM.Values[I];
- const Value *R = RM.Values[I];
- auto LU = L->use_begin(), LE = L->use_end();
- auto RU = R->use_begin(), RE = R->use_end();
- skipUnmappedUsers(LU, LE, LM);
- skipUnmappedUsers(RU, RE, RM);
-
- while (LU != LE) {
- if (RU == RE) {
- DEBUG(debugUserMismatch(LM, RM, I));
- return false;
- }
- if (LM.lookup(LU->getUser()) != RM.lookup(RU->getUser())) {
- DEBUG(debugUserMismatch(LM, RM, I));
- return false;
- }
- if (LU->getOperandNo() != RU->getOperandNo()) {
- DEBUG(debugUserMismatch(LM, RM, I));
- return false;
- }
- skipUnmappedUsers(++LU, LE, LM);
- skipUnmappedUsers(++RU, RE, RM);
- }
- if (RU != RE) {
- DEBUG(debugUserMismatch(LM, RM, I));
- return false;
- }
- }
-
- return true;
-}
-
-static bool verifyBitcodeUseListOrder(const Module &M) {
- DEBUG(dbgs() << "*** verify-use-list-order: bitcode ***\n");
- TempFile F;
- if (F.init("bc"))
- return false;
-
- if (F.writeBitcode(M))
- return false;
-
- LLVMContext Context;
- std::unique_ptr<Module> OtherM = F.readBitcode(Context);
- if (!OtherM)
- return false;
-
- return matches(ValueMapping(M), ValueMapping(*OtherM));
-}
-
-static bool verifyAssemblyUseListOrder(const Module &M) {
- DEBUG(dbgs() << "*** verify-use-list-order: assembly ***\n");
- TempFile F;
- if (F.init("ll"))
- return false;
-
- if (F.writeAssembly(M))
- return false;
-
- LLVMContext Context;
- std::unique_ptr<Module> OtherM = F.readAssembly(Context);
- if (!OtherM)
- return false;
-
- return matches(ValueMapping(M), ValueMapping(*OtherM));
-}
-
-namespace {
-class VerifyUseListOrder : public ModulePass {
-public:
- static char ID;
- VerifyUseListOrder();
- bool runOnModule(Module &M) override;
-};
-} // end anonymous namespace
-
-char VerifyUseListOrder::ID = 0;
-INITIALIZE_PASS(VerifyUseListOrder, "verify-use-list-order",
- "Verify Use List Order", false, false)
-VerifyUseListOrder::VerifyUseListOrder() : ModulePass(ID) {
- initializeVerifyUseListOrderPass(*PassRegistry::getPassRegistry());
-}
-
-bool VerifyUseListOrder::runOnModule(Module &M) {
- DEBUG(dbgs() << "*** verify-use-list-order ***\n");
- if (!shouldPreserveBitcodeUseListOrder()) {
- // Can't verify if order isn't preserved.
- DEBUG(dbgs() << "warning: cannot verify bitcode; "
- "try -preserve-bc-use-list-order\n");
- return false;
- }
-
- shuffleUseLists(M);
- if (!verifyBitcodeUseListOrder(M))
- report_fatal_error("bitcode use-list order changed");
-
- if (shouldPreserveBitcodeUseListOrder())
- if (!verifyAssemblyUseListOrder(M))
- report_fatal_error("assembly use-list order changed");
-
- return true;
-}
-
-ModulePass *llvm::createVerifyUseListOrderPass() {
- return new VerifyUseListOrder;
-}
OpenPOWER on IntegriCloud