@@ -1475,6 +1475,74 @@ void FPPassManager::dumpPassStructure(unsigned Offset) {
1475
1475
}
1476
1476
}
1477
1477
1478
+ #ifdef EXPENSIVE_CHECKS
1479
+ namespace {
1480
+ namespace details {
1481
+
1482
+ // Basic hashing mechanism to detect structural change to the IR, used to verify
1483
+ // pass return status consistency with actual change. Loosely copied from
1484
+ // llvm/lib/Transforms/Utils/FunctionComparator.cpp
1485
+
1486
+ class StructuralHash {
1487
+ uint64_t Hash = 0x6acaa36bef8325c5ULL ;
1488
+
1489
+ void update (uint64_t V) { Hash = hashing::detail::hash_16_bytes (Hash, V); }
1490
+
1491
+ public:
1492
+ StructuralHash () = default ;
1493
+
1494
+ void update (Function &F) {
1495
+ if (F.empty ())
1496
+ return ;
1497
+
1498
+ update (F.isVarArg ());
1499
+ update (F.arg_size ());
1500
+
1501
+ SmallVector<const BasicBlock *, 8 > BBs;
1502
+ SmallPtrSet<const BasicBlock *, 16 > VisitedBBs;
1503
+
1504
+ BBs.push_back (&F.getEntryBlock ());
1505
+ VisitedBBs.insert (BBs[0 ]);
1506
+ while (!BBs.empty ()) {
1507
+ const BasicBlock *BB = BBs.pop_back_val ();
1508
+ update (45798 ); // Block header
1509
+ for (auto &Inst : *BB)
1510
+ update (Inst.getOpcode ());
1511
+
1512
+ const Instruction *Term = BB->getTerminator ();
1513
+ for (unsigned i = 0 , e = Term->getNumSuccessors (); i != e; ++i) {
1514
+ if (!VisitedBBs.insert (Term->getSuccessor (i)).second )
1515
+ continue ;
1516
+ BBs.push_back (Term->getSuccessor (i));
1517
+ }
1518
+ }
1519
+ }
1520
+
1521
+ void update (Module &M) {
1522
+ for (Function &F : M)
1523
+ update (F);
1524
+ }
1525
+
1526
+ uint64_t getHash () const { return Hash; }
1527
+ };
1528
+
1529
+ } // namespace details
1530
+
1531
+ uint64_t StructuralHash (Function &F) {
1532
+ details::StructuralHash H;
1533
+ H.update (F);
1534
+ return H.getHash ();
1535
+ }
1536
+
1537
+ uint64_t StructuralHash (Module &M) {
1538
+ details::StructuralHash H;
1539
+ H.update (M);
1540
+ return H.getHash ();
1541
+ }
1542
+
1543
+ } // end anonymous namespace
1544
+
1545
+ #endif
1478
1546
1479
1547
// / Execute all of the passes scheduled for execution by invoking
1480
1548
// / runOnFunction method. Keep track of whether any of the passes modifies
@@ -1513,7 +1581,16 @@ bool FPPassManager::runOnFunction(Function &F) {
1513
1581
{
1514
1582
PassManagerPrettyStackEntry X (FP, F);
1515
1583
TimeRegion PassTimer (getPassTimer (FP));
1584
+ #ifdef EXPENSIVE_CHECKS
1585
+ uint64_t RefHash = StructuralHash (F);
1586
+ #endif
1516
1587
LocalChanged |= FP->runOnFunction (F);
1588
+
1589
+ #ifdef EXPENSIVE_CHECKS
1590
+ assert ((LocalChanged || (RefHash == StructuralHash (F))) &&
1591
+ " Pass modifies its input and doesn't report it." );
1592
+ #endif
1593
+
1517
1594
if (EmitICRemark) {
1518
1595
unsigned NewSize = F.getInstructionCount ();
1519
1596
@@ -1614,7 +1691,17 @@ MPPassManager::runOnModule(Module &M) {
1614
1691
PassManagerPrettyStackEntry X (MP, M);
1615
1692
TimeRegion PassTimer (getPassTimer (MP));
1616
1693
1694
+ #ifdef EXPENSIVE_CHECKS
1695
+ uint64_t RefHash = StructuralHash (M);
1696
+ #endif
1697
+
1617
1698
LocalChanged |= MP->runOnModule (M);
1699
+
1700
+ #ifdef EXPENSIVE_CHECKS
1701
+ assert ((LocalChanged || (RefHash == StructuralHash (M))) &&
1702
+ " Pass modifies its input and doesn't report it." );
1703
+ #endif
1704
+
1618
1705
if (EmitICRemark) {
1619
1706
// Update the size of the module.
1620
1707
unsigned ModuleCount = M.getInstructionCount ();
0 commit comments