Skip to content

Commit 1d31691

Browse files
committed
verify-uselistorder: Reverse use-lists at every verification
Updated `verify-uselistorder` to more than double the number of use-list orders it checks. - Every time it verifies an order, it then reverses the order and verifies again. - It now verifies the initial order, before running any shuffles. Changed the default to `-num-shuffles=1`, since this is already four checks, and after r214584 shuffling is guaranteed to make a new order. This is part of PR5680. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214596 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 4277019 commit 1d31691

File tree

1 file changed

+69
-21
lines changed

1 file changed

+69
-21
lines changed

tools/verify-uselistorder/verify-uselistorder.cpp

+69-21
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static cl::opt<bool> SaveTemps("save-temps", cl::desc("Save temp files"),
6464
static cl::opt<unsigned>
6565
NumShuffles("num-shuffles",
6666
cl::desc("Number of times to shuffle and verify use-lists"),
67-
cl::init(5));
67+
cl::init(1));
6868

6969
namespace {
7070

@@ -413,53 +413,93 @@ static void shuffleValueUseLists(Value *V, std::minstd_rand0 &Gen,
413413
});
414414
}
415415

416-
/// Shuffle all use-lists in a module.
417-
static void shuffleUseLists(Module &M, unsigned SeedOffset) {
418-
DEBUG(dbgs() << "*** shuffle-use-lists ***\n");
419-
std::minstd_rand0 Gen(std::minstd_rand0::default_seed + SeedOffset);
420-
DenseSet<Value *> Seen;
416+
static void reverseValueUseLists(Value *V, DenseSet<Value *> &Seen) {
417+
if (!Seen.insert(V).second)
418+
return;
419+
420+
if (auto *C = dyn_cast<Constant>(V))
421+
if (!isa<GlobalValue>(C))
422+
for (Value *Op : C->operands())
423+
reverseValueUseLists(Op, Seen);
424+
425+
if (V->use_empty() || std::next(V->use_begin()) == V->use_end())
426+
// Nothing to shuffle for 0 or 1 users.
427+
return;
428+
429+
DEBUG({
430+
dbgs() << "V = ";
431+
V->dump();
432+
for (const Use &U : V->uses()) {
433+
dbgs() << " - order: op = " << U.getOperandNo() << ", U = ";
434+
U.getUser()->dump();
435+
}
436+
dbgs() << " => reverse\n";
437+
});
421438

422-
// Shuffle the use-list of each value that would be serialized to an IR file
423-
// (bitcode or assembly).
424-
auto shuffle = [&](Value *V) { shuffleValueUseLists(V, Gen, Seen); };
439+
V->reverseUseList();
425440

441+
DEBUG({
442+
for (const Use &U : V->uses()) {
443+
dbgs() << " - order: op = " << U.getOperandNo() << ", U = ";
444+
U.getUser()->dump();
445+
}
446+
});
447+
}
448+
449+
template <class Changer>
450+
static void changeUseLists(Module &M, Changer changeValueUseList) {
451+
// Visit every value that would be serialized to an IR file.
452+
//
426453
// Globals.
427454
for (GlobalVariable &G : M.globals())
428-
shuffle(&G);
455+
changeValueUseList(&G);
429456
for (GlobalAlias &A : M.aliases())
430-
shuffle(&A);
457+
changeValueUseList(&A);
431458
for (Function &F : M)
432-
shuffle(&F);
459+
changeValueUseList(&F);
433460

434461
// Constants used by globals.
435462
for (GlobalVariable &G : M.globals())
436463
if (G.hasInitializer())
437-
shuffle(G.getInitializer());
464+
changeValueUseList(G.getInitializer());
438465
for (GlobalAlias &A : M.aliases())
439-
shuffle(A.getAliasee());
466+
changeValueUseList(A.getAliasee());
440467
for (Function &F : M)
441468
if (F.hasPrefixData())
442-
shuffle(F.getPrefixData());
469+
changeValueUseList(F.getPrefixData());
443470

444471
// Function bodies.
445472
for (Function &F : M) {
446473
for (Argument &A : F.args())
447-
shuffle(&A);
474+
changeValueUseList(&A);
448475
for (BasicBlock &BB : F)
449-
shuffle(&BB);
476+
changeValueUseList(&BB);
450477
for (BasicBlock &BB : F)
451478
for (Instruction &I : BB)
452-
shuffle(&I);
479+
changeValueUseList(&I);
453480

454481
// Constants used by instructions.
455482
for (BasicBlock &BB : F)
456483
for (Instruction &I : BB)
457484
for (Value *Op : I.operands())
458485
if ((isa<Constant>(Op) && !isa<GlobalValue>(*Op)) ||
459486
isa<InlineAsm>(Op))
460-
shuffle(Op);
487+
changeValueUseList(Op);
461488
}
489+
}
490+
491+
static void shuffleUseLists(Module &M, unsigned SeedOffset) {
492+
DEBUG(dbgs() << "*** shuffle-use-lists ***\n");
493+
std::minstd_rand0 Gen(std::minstd_rand0::default_seed + SeedOffset);
494+
DenseSet<Value *> Seen;
495+
changeUseLists(M, [&](Value *V) { shuffleValueUseLists(V, Gen, Seen); });
496+
DEBUG(dbgs() << "\n");
497+
}
462498

499+
static void reverseUseLists(Module &M) {
500+
DEBUG(dbgs() << "*** reverse-use-lists ***\n");
501+
DenseSet<Value *> Seen;
502+
changeUseLists(M, [&](Value *V) { reverseValueUseLists(V, Seen); });
463503
DEBUG(dbgs() << "\n");
464504
}
465505

@@ -495,12 +535,20 @@ int main(int argc, char **argv) {
495535
return 0;
496536
}
497537

538+
// Verify the use lists now and after reversing them.
539+
verifyUseListOrder(*M);
540+
reverseUseLists(*M);
541+
verifyUseListOrder(*M);
542+
498543
for (unsigned I = 0, E = NumShuffles; I != E; ++I) {
499544
DEBUG(dbgs() << "*** iteration: " << I << " ***\n");
500545

501-
// Shuffle with a different seed each time so that use-lists that aren't
502-
// modified the first time are likely to be modified the next time.
546+
// Shuffle with a different (deterministic) seed each time.
503547
shuffleUseLists(*M, I);
548+
549+
// Verify again before and after reversing.
550+
verifyUseListOrder(*M);
551+
reverseUseLists(*M);
504552
verifyUseListOrder(*M);
505553
}
506554

0 commit comments

Comments
 (0)