verify-uselistorder.cpp 18 KB

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