c796c389bec16dc3fec6aa131f239d0eab8ab8e7
[oota-llvm.git] / tools / verify-uselistorder / verify-uselistorder.cpp
1 //===- verify-uselistorder.cpp - The LLVM Modular Optimizer ---------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Verify that use-list order can be serialized correctly.  After reading the
11 // provided IR, this tool shuffles the use-lists and then writes and reads to a
12 // separate Module whose use-list orders are compared to the original.
13 //
14 // The shuffles are deterministic, but guarantee that use-lists will change.
15 // The algorithm per iteration is as follows:
16 //
17 //  1. Seed the random number generator.  The seed is different for each
18 //     shuffle.  Shuffle 0 uses default+0, shuffle 1 uses default+1, and so on.
19 //
20 //  2. Visit every Value in a deterministic order.
21 //
22 //  3. Assign a random number to each Use in the Value's use-list in order.
23 //
24 //  4. If the numbers are already in order, reassign numbers until they aren't.
25 //
26 //  5. Sort the use-list using Value::sortUseList(), which is a stable sort.
27 //
28 //===----------------------------------------------------------------------===//
29
30 #include "llvm/ADT/DenseMap.h"
31 #include "llvm/ADT/DenseSet.h"
32 #include "llvm/AsmParser/Parser.h"
33 #include "llvm/Bitcode/ReaderWriter.h"
34 #include "llvm/IR/LLVMContext.h"
35 #include "llvm/IR/Module.h"
36 #include "llvm/IR/UseListOrder.h"
37 #include "llvm/IR/Verifier.h"
38 #include "llvm/IRReader/IRReader.h"
39 #include "llvm/Support/CommandLine.h"
40 #include "llvm/Support/Debug.h"
41 #include "llvm/Support/ErrorHandling.h"
42 #include "llvm/Support/FileSystem.h"
43 #include "llvm/Support/FileUtilities.h"
44 #include "llvm/Support/ManagedStatic.h"
45 #include "llvm/Support/MemoryBuffer.h"
46 #include "llvm/Support/PrettyStackTrace.h"
47 #include "llvm/Support/Signals.h"
48 #include "llvm/Support/SourceMgr.h"
49 #include "llvm/Support/SystemUtils.h"
50 #include <random>
51 #include <vector>
52
53 using namespace llvm;
54
55 #define DEBUG_TYPE "use-list-order"
56
57 static cl::opt<std::string> InputFilename(cl::Positional,
58                                           cl::desc("<input bitcode file>"),
59                                           cl::init("-"),
60                                           cl::value_desc("filename"));
61
62 static cl::opt<bool> SaveTemps("save-temps", cl::desc("Save temp files"),
63                                cl::init(false));
64
65 static cl::opt<unsigned>
66     NumShuffles("num-shuffles",
67                 cl::desc("Number of times to shuffle and verify use-lists"),
68                 cl::init(1));
69
70 namespace {
71
72 struct TempFile {
73   std::string Filename;
74   FileRemover Remover;
75   bool init(const std::string &Ext);
76   bool writeBitcode(const Module &M) const;
77   bool writeAssembly(const Module &M) const;
78   std::unique_ptr<Module> readBitcode(LLVMContext &Context) const;
79   std::unique_ptr<Module> readAssembly(LLVMContext &Context) const;
80 };
81
82 struct ValueMapping {
83   DenseMap<const Value *, unsigned> IDs;
84   std::vector<const Value *> Values;
85
86   /// \brief Construct a value mapping for module.
87   ///
88   /// Creates mapping from every value in \c M to an ID.  This mapping includes
89   /// un-referencable values.
90   ///
91   /// Every \a Value that gets serialized in some way should be represented
92   /// here.  The order needs to be deterministic, but it's unnecessary to match
93   /// the value-ids in the bitcode writer.
94   ///
95   /// All constants that are referenced by other values are included in the
96   /// mapping, but others -- which wouldn't be serialized -- are not.
97   ValueMapping(const Module &M);
98
99   /// \brief Map a value.
100   ///
101   /// Maps a value.  If it's a constant, maps all of its operands first.
102   void map(const Value *V);
103   unsigned lookup(const Value *V) const { return IDs.lookup(V); }
104 };
105
106 } // end namespace
107
108 bool TempFile::init(const std::string &Ext) {
109   SmallVector<char, 64> Vector;
110   DEBUG(dbgs() << " - create-temp-file\n");
111   if (auto EC = sys::fs::createTemporaryFile("use-list-order", Ext, Vector)) {
112     (void)EC;
113     DEBUG(dbgs() << "error: " << EC.message() << "\n");
114     return true;
115   }
116   assert(!Vector.empty());
117
118   Filename.assign(Vector.data(), Vector.data() + Vector.size());
119   Remover.setFile(Filename, !SaveTemps);
120   DEBUG(dbgs() << " - filename = " << Filename << "\n");
121   return false;
122 }
123
124 bool TempFile::writeBitcode(const Module &M) const {
125   DEBUG(dbgs() << " - write bitcode\n");
126   std::error_code EC;
127   raw_fd_ostream OS(Filename, EC, sys::fs::F_None);
128   if (EC) {
129     DEBUG(dbgs() << "error: " << EC.message() << "\n");
130     return true;
131   }
132
133   WriteBitcodeToFile(&M, OS);
134   return false;
135 }
136
137 bool TempFile::writeAssembly(const Module &M) const {
138   DEBUG(dbgs() << " - write assembly\n");
139   std::error_code EC;
140   raw_fd_ostream OS(Filename, EC, sys::fs::F_Text);
141   if (EC) {
142     DEBUG(dbgs() << "error: " << EC.message() << "\n");
143     return true;
144   }
145
146   OS << M;
147   return false;
148 }
149
150 std::unique_ptr<Module> TempFile::readBitcode(LLVMContext &Context) const {
151   DEBUG(dbgs() << " - read bitcode\n");
152   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOr =
153       MemoryBuffer::getFile(Filename);
154   if (!BufferOr) {
155     DEBUG(dbgs() << "error: " << BufferOr.getError().message() << "\n");
156     return nullptr;
157   }
158
159   MemoryBuffer *Buffer = BufferOr.get().get();
160   ErrorOr<Module *> ModuleOr = parseBitcodeFile(Buffer, Context);
161   if (!ModuleOr) {
162     DEBUG(dbgs() << "error: " << ModuleOr.getError().message() << "\n");
163     return nullptr;
164   }
165   return std::unique_ptr<Module>(ModuleOr.get());
166 }
167
168 std::unique_ptr<Module> TempFile::readAssembly(LLVMContext &Context) const {
169   DEBUG(dbgs() << " - read assembly\n");
170   SMDiagnostic Err;
171   std::unique_ptr<Module> M = parseAssemblyFile(Filename, Err, Context);
172   if (!M.get())
173     DEBUG(dbgs() << "error: "; Err.print("verify-use-list-order", dbgs()));
174   return M;
175 }
176
177 ValueMapping::ValueMapping(const Module &M) {
178   // Every value should be mapped, including things like void instructions and
179   // basic blocks that are kept out of the ValueEnumerator.
180   //
181   // The current mapping order makes it easier to debug the tables.  It happens
182   // to be similar to the ID mapping when writing ValueEnumerator, but they
183   // aren't (and needn't be) in sync.
184
185   // Globals.
186   for (const GlobalVariable &G : M.globals())
187     map(&G);
188   for (const GlobalAlias &A : M.aliases())
189     map(&A);
190   for (const Function &F : M)
191     map(&F);
192
193   // Constants used by globals.
194   for (const GlobalVariable &G : M.globals())
195     if (G.hasInitializer())
196       map(G.getInitializer());
197   for (const GlobalAlias &A : M.aliases())
198     map(A.getAliasee());
199   for (const Function &F : M)
200     if (F.hasPrefixData())
201       map(F.getPrefixData());
202
203   // Function bodies.
204   for (const Function &F : M) {
205     for (const Argument &A : F.args())
206       map(&A);
207     for (const BasicBlock &BB : F)
208       map(&BB);
209     for (const BasicBlock &BB : F)
210       for (const Instruction &I : BB)
211         map(&I);
212
213     // Constants used by instructions.
214     for (const BasicBlock &BB : F)
215       for (const Instruction &I : BB)
216         for (const Value *Op : I.operands())
217           if ((isa<Constant>(Op) && !isa<GlobalValue>(*Op)) ||
218               isa<InlineAsm>(Op))
219             map(Op);
220   }
221 }
222
223 void ValueMapping::map(const Value *V) {
224   if (IDs.lookup(V))
225     return;
226
227   if (auto *C = dyn_cast<Constant>(V))
228     if (!isa<GlobalValue>(C))
229       for (const Value *Op : C->operands())
230         map(Op);
231
232   Values.push_back(V);
233   IDs[V] = Values.size();
234 }
235
236 #ifndef NDEBUG
237 static void dumpMapping(const ValueMapping &VM) {
238   dbgs() << "value-mapping (size = " << VM.Values.size() << "):\n";
239   for (unsigned I = 0, E = VM.Values.size(); I != E; ++I) {
240     dbgs() << " - id = " << I << ", value = ";
241     VM.Values[I]->dump();
242   }
243 }
244
245 static void debugValue(const ValueMapping &M, unsigned I, StringRef Desc) {
246   const Value *V = M.Values[I];
247   dbgs() << " - " << Desc << " value = ";
248   V->dump();
249   for (const Use &U : V->uses()) {
250     dbgs() << "   => use: op = " << U.getOperandNo()
251            << ", user-id = " << M.IDs.lookup(U.getUser()) << ", user = ";
252     U.getUser()->dump();
253   }
254 }
255
256 static void debugUserMismatch(const ValueMapping &L, const ValueMapping &R,
257                               unsigned I) {
258   dbgs() << " - fail: user mismatch: ID = " << I << "\n";
259   debugValue(L, I, "LHS");
260   debugValue(R, I, "RHS");
261
262   dbgs() << "\nlhs-";
263   dumpMapping(L);
264   dbgs() << "\nrhs-";
265   dumpMapping(R);
266 }
267
268 static void debugSizeMismatch(const ValueMapping &L, const ValueMapping &R) {
269   dbgs() << " - fail: map size: " << L.Values.size()
270          << " != " << R.Values.size() << "\n";
271   dbgs() << "\nlhs-";
272   dumpMapping(L);
273   dbgs() << "\nrhs-";
274   dumpMapping(R);
275 }
276 #endif
277
278 static bool matches(const ValueMapping &LM, const ValueMapping &RM) {
279   DEBUG(dbgs() << "compare value maps\n");
280   if (LM.Values.size() != RM.Values.size()) {
281     DEBUG(debugSizeMismatch(LM, RM));
282     return false;
283   }
284
285   // This mapping doesn't include dangling constant users, since those don't
286   // get serialized.  However, checking if users are constant and calling
287   // isConstantUsed() on every one is very expensive.  Instead, just check if
288   // the user is mapped.
289   auto skipUnmappedUsers =
290       [&](Value::const_use_iterator &U, Value::const_use_iterator E,
291           const ValueMapping &M) {
292     while (U != E && !M.lookup(U->getUser()))
293       ++U;
294   };
295
296   // Iterate through all values, and check that both mappings have the same
297   // users.
298   for (unsigned I = 0, E = LM.Values.size(); I != E; ++I) {
299     const Value *L = LM.Values[I];
300     const Value *R = RM.Values[I];
301     auto LU = L->use_begin(), LE = L->use_end();
302     auto RU = R->use_begin(), RE = R->use_end();
303     skipUnmappedUsers(LU, LE, LM);
304     skipUnmappedUsers(RU, RE, RM);
305
306     while (LU != LE) {
307       if (RU == RE) {
308         DEBUG(debugUserMismatch(LM, RM, I));
309         return false;
310       }
311       if (LM.lookup(LU->getUser()) != RM.lookup(RU->getUser())) {
312         DEBUG(debugUserMismatch(LM, RM, I));
313         return false;
314       }
315       if (LU->getOperandNo() != RU->getOperandNo()) {
316         DEBUG(debugUserMismatch(LM, RM, I));
317         return false;
318       }
319       skipUnmappedUsers(++LU, LE, LM);
320       skipUnmappedUsers(++RU, RE, RM);
321     }
322     if (RU != RE) {
323       DEBUG(debugUserMismatch(LM, RM, I));
324       return false;
325     }
326   }
327
328   return true;
329 }
330
331 static void verifyAfterRoundTrip(const Module &M,
332                                  std::unique_ptr<Module> OtherM) {
333   if (!OtherM)
334     report_fatal_error("parsing failed");
335   if (verifyModule(*OtherM, &errs()))
336     report_fatal_error("verification failed");
337   if (!matches(ValueMapping(M), ValueMapping(*OtherM)))
338     report_fatal_error("use-list order changed");
339 }
340 static void verifyBitcodeUseListOrder(const Module &M) {
341   errs() << "*** verify-use-list-order: bitcode ***\n";
342   TempFile F;
343   if (F.init("bc"))
344     report_fatal_error("failed to initialize bitcode file");
345
346   if (F.writeBitcode(M))
347     report_fatal_error("failed to write bitcode");
348
349   LLVMContext Context;
350   verifyAfterRoundTrip(M, F.readBitcode(Context));
351 }
352
353 static void verifyAssemblyUseListOrder(const Module &M) {
354   errs() << "*** verify-use-list-order: assembly ***\n";
355   TempFile F;
356   if (F.init("ll"))
357     report_fatal_error("failed to initialize assembly file");
358
359   if (F.writeAssembly(M))
360     report_fatal_error("failed to write assembly");
361
362   LLVMContext Context;
363   verifyAfterRoundTrip(M, F.readAssembly(Context));
364 }
365
366 static void verifyUseListOrder(const Module &M) {
367   verifyBitcodeUseListOrder(M);
368   verifyAssemblyUseListOrder(M);
369 }
370
371 static void shuffleValueUseLists(Value *V, std::minstd_rand0 &Gen,
372                                  DenseSet<Value *> &Seen) {
373   if (!Seen.insert(V).second)
374     return;
375
376   if (auto *C = dyn_cast<Constant>(V))
377     if (!isa<GlobalValue>(C))
378       for (Value *Op : C->operands())
379         shuffleValueUseLists(Op, Gen, Seen);
380
381   if (V->use_empty() || std::next(V->use_begin()) == V->use_end())
382     // Nothing to shuffle for 0 or 1 users.
383     return;
384
385   // Generate random numbers between 10 and 99, which will line up nicely in
386   // debug output.  We're not worried about collisons here.
387   DEBUG(dbgs() << "V = "; V->dump());
388   std::uniform_int_distribution<short> Dist(10, 99);
389   SmallDenseMap<const Use *, short, 16> Order;
390   auto compareUses =
391       [&Order](const Use &L, const Use &R) { return Order[&L] < Order[&R]; };
392   do {
393     for (const Use &U : V->uses()) {
394       auto I = Dist(Gen);
395       Order[&U] = I;
396       DEBUG(dbgs() << " - order: " << I << ", op = " << U.getOperandNo()
397                    << ", U = ";
398             U.getUser()->dump());
399     }
400   } while (std::is_sorted(V->use_begin(), V->use_end(), compareUses));
401
402   DEBUG(dbgs() << " => shuffle\n");
403   V->sortUseList(compareUses);
404
405   DEBUG({
406     for (const Use &U : V->uses()) {
407       dbgs() << " - order: " << Order.lookup(&U)
408              << ", op = " << U.getOperandNo() << ", U = ";
409       U.getUser()->dump();
410     }
411   });
412 }
413
414 static void reverseValueUseLists(Value *V, DenseSet<Value *> &Seen) {
415   if (!Seen.insert(V).second)
416     return;
417
418   if (auto *C = dyn_cast<Constant>(V))
419     if (!isa<GlobalValue>(C))
420       for (Value *Op : C->operands())
421         reverseValueUseLists(Op, Seen);
422
423   if (V->use_empty() || std::next(V->use_begin()) == V->use_end())
424     // Nothing to shuffle for 0 or 1 users.
425     return;
426
427   DEBUG({
428     dbgs() << "V = ";
429     V->dump();
430     for (const Use &U : V->uses()) {
431       dbgs() << " - order: op = " << U.getOperandNo() << ", U = ";
432       U.getUser()->dump();
433     }
434     dbgs() << " => reverse\n";
435   });
436
437   V->reverseUseList();
438
439   DEBUG({
440     for (const Use &U : V->uses()) {
441       dbgs() << " - order: op = " << U.getOperandNo() << ", U = ";
442       U.getUser()->dump();
443     }
444   });
445 }
446
447 template <class Changer>
448 static void changeUseLists(Module &M, Changer changeValueUseList) {
449   // Visit every value that would be serialized to an IR file.
450   //
451   // Globals.
452   for (GlobalVariable &G : M.globals())
453     changeValueUseList(&G);
454   for (GlobalAlias &A : M.aliases())
455     changeValueUseList(&A);
456   for (Function &F : M)
457     changeValueUseList(&F);
458
459   // Constants used by globals.
460   for (GlobalVariable &G : M.globals())
461     if (G.hasInitializer())
462       changeValueUseList(G.getInitializer());
463   for (GlobalAlias &A : M.aliases())
464     changeValueUseList(A.getAliasee());
465   for (Function &F : M)
466     if (F.hasPrefixData())
467       changeValueUseList(F.getPrefixData());
468
469   // Function bodies.
470   for (Function &F : M) {
471     for (Argument &A : F.args())
472       changeValueUseList(&A);
473     for (BasicBlock &BB : F)
474       changeValueUseList(&BB);
475     for (BasicBlock &BB : F)
476       for (Instruction &I : BB)
477         changeValueUseList(&I);
478
479     // Constants used by instructions.
480     for (BasicBlock &BB : F)
481       for (Instruction &I : BB)
482         for (Value *Op : I.operands())
483           if ((isa<Constant>(Op) && !isa<GlobalValue>(*Op)) ||
484               isa<InlineAsm>(Op))
485             changeValueUseList(Op);
486   }
487
488   if (verifyModule(M, &errs()))
489     report_fatal_error("verification failed");
490 }
491
492 static void shuffleUseLists(Module &M, unsigned SeedOffset) {
493   errs() << "*** shuffle-use-lists ***\n";
494   std::minstd_rand0 Gen(std::minstd_rand0::default_seed + SeedOffset);
495   DenseSet<Value *> Seen;
496   changeUseLists(M, [&](Value *V) { shuffleValueUseLists(V, Gen, Seen); });
497   DEBUG(dbgs() << "\n");
498 }
499
500 static void reverseUseLists(Module &M) {
501   errs() << "*** reverse-use-lists ***\n";
502   DenseSet<Value *> Seen;
503   changeUseLists(M, [&](Value *V) { reverseValueUseLists(V, Seen); });
504   DEBUG(dbgs() << "\n");
505 }
506
507 int main(int argc, char **argv) {
508   sys::PrintStackTraceOnErrorSignal();
509   llvm::PrettyStackTraceProgram X(argc, argv);
510
511   // Enable debug stream buffering.
512   EnableDebugBuffering = true;
513
514   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
515   LLVMContext &Context = getGlobalContext();
516
517   cl::ParseCommandLineOptions(argc, argv,
518                               "llvm tool to verify use-list order\n");
519
520   SMDiagnostic Err;
521
522   // Load the input module...
523   std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context);
524
525   if (!M.get()) {
526     Err.print(argv[0], errs());
527     return 1;
528   }
529   if (verifyModule(*M, &errs()))
530     report_fatal_error("verification failed");
531
532   errs() << "*** verify-use-list-order ***\n";
533   // Can't verify if order isn't preserved.
534   if (!shouldPreserveBitcodeUseListOrder()) {
535     errs() << "warning: forcing -preserve-bc-use-list-order\n";
536     setPreserveBitcodeUseListOrder(true);
537   }
538   if (!shouldPreserveAssemblyUseListOrder()) {
539     errs() << "warning: forcing -preserve-ll-use-list-order\n";
540     setPreserveAssemblyUseListOrder(true);
541   }
542
543   // Verify the use lists now and after reversing them.
544   verifyUseListOrder(*M);
545   reverseUseLists(*M);
546   verifyUseListOrder(*M);
547
548   for (unsigned I = 0, E = NumShuffles; I != E; ++I) {
549     errs() << "*** shuffle iteration: " << I + 1 << " of " << E << " ***\n";
550
551     // Shuffle with a different (deterministic) seed each time.
552     shuffleUseLists(*M, I);
553
554     // Verify again before and after reversing.
555     verifyUseListOrder(*M);
556     reverseUseLists(*M);
557     verifyUseListOrder(*M);
558   }
559
560   return 0;
561 }