diff options
-rw-r--r-- | llvm/include/llvm/Analysis/MemorySSA.h | 1 | ||||
-rw-r--r-- | llvm/lib/Analysis/MemorySSA.cpp | 42 | ||||
-rw-r--r-- | llvm/lib/Analysis/MemorySSAUpdater.cpp | 2 | ||||
-rw-r--r-- | llvm/test/Analysis/MemorySSA/unreachable.ll | 31 |
4 files changed, 75 insertions, 1 deletions
diff --git a/llvm/include/llvm/Analysis/MemorySSA.h b/llvm/include/llvm/Analysis/MemorySSA.h index 282290b899b..e89bf26a723 100644 --- a/llvm/include/llvm/Analysis/MemorySSA.h +++ b/llvm/include/llvm/Analysis/MemorySSA.h @@ -793,6 +793,7 @@ protected: friend class MemorySSAPrinterLegacyPass; friend class MemorySSAUpdater; + void verifyPrevDefInPhis(Function &F) const; void verifyDefUses(Function &F) const; void verifyDomination(Function &F) const; void verifyOrdering(Function &F) const; diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp index 5df56ddd8e3..ed4b6456232 100644 --- a/llvm/lib/Analysis/MemorySSA.cpp +++ b/llvm/lib/Analysis/MemorySSA.cpp @@ -49,6 +49,7 @@ #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> +#include <cstdlib> #include <iterator> #include <memory> #include <utility> @@ -1852,6 +1853,7 @@ void MemorySSA::verifyMemorySSA() const { verifyDomination(F); verifyOrdering(F); verifyDominationNumbers(F); + verifyPrevDefInPhis(F); // Previously, the verification used to also verify that the clobberingAccess // cached by MemorySSA is the same as the clobberingAccess found at a later // query to AA. This does not hold true in general due to the current fragility @@ -1864,6 +1866,46 @@ void MemorySSA::verifyMemorySSA() const { // example, see test4 added in D51960. } +void MemorySSA::verifyPrevDefInPhis(Function &F) const { +#ifndef NDEBUG + for (const BasicBlock &BB : F) { + if (MemoryPhi *Phi = getMemoryAccess(&BB)) { + for (unsigned I = 0, E = Phi->getNumIncomingValues(); I != E; ++I) { + auto *Pred = Phi->getIncomingBlock(I); + auto *IncAcc = Phi->getIncomingValue(I); + // If Pred has no unreachable predecessors, get last def looking at + // IDoms. If, while walkings IDoms, any of these has an unreachable + // predecessor, then the expected incoming def is LoE. + if (auto *DTNode = DT->getNode(Pred)) { + while (DTNode) { + if (auto *DefList = getBlockDefs(DTNode->getBlock())) { + auto *LastAcc = &*(--DefList->end()); + assert(LastAcc == IncAcc && + "Incorrect incoming access into phi."); + break; + } + DTNode = DTNode->getIDom(); + } + assert((DTNode || IncAcc == getLiveOnEntryDef()) && + "Expected LoE inc"); + } else if (auto *DefList = getBlockDefs(Pred)) { + // If Pred has unreachable predecessors, but has at least a Def, the + // incoming access can be the last Def in Pred, or it could have been + // optimized to LoE. + auto *LastAcc = &*(--DefList->end()); + assert((LastAcc == IncAcc || IncAcc == getLiveOnEntryDef()) && + "Incorrect incoming access into phi."); + } else { + // If Pred has unreachable predecessors and no Defs, incoming access + // should be LoE. + assert(IncAcc == getLiveOnEntryDef() && "Expected LoE inc"); + } + } + } + } +#endif +} + /// Verify that all of the blocks we believe to have valid domination numbers /// actually have valid domination numbers. void MemorySSA::verifyDominationNumbers(const Function &F) const { diff --git a/llvm/lib/Analysis/MemorySSAUpdater.cpp b/llvm/lib/Analysis/MemorySSAUpdater.cpp index 42bbe7483b2..7fea41a8a53 100644 --- a/llvm/lib/Analysis/MemorySSAUpdater.cpp +++ b/llvm/lib/Analysis/MemorySSAUpdater.cpp @@ -1074,7 +1074,7 @@ void MemorySSAUpdater::moveTo(MemoryUseOrDef *What, BasicBlock *BB, // Now reinsert it into the IR and do whatever fixups needed. if (auto *MD = dyn_cast<MemoryDef>(What)) - insertDef(MD); + insertDef(MD, true); else insertUse(cast<MemoryUse>(What)); diff --git a/llvm/test/Analysis/MemorySSA/unreachable.ll b/llvm/test/Analysis/MemorySSA/unreachable.ll new file mode 100644 index 00000000000..6a936435373 --- /dev/null +++ b/llvm/test/Analysis/MemorySSA/unreachable.ll @@ -0,0 +1,31 @@ +; RUN: opt -licm -enable-mssa-loop-dependency -verify-memoryssa %s -S | FileCheck %s +; REQUIRES: asserts +; Ensure verification doesn't fail with unreachable blocks. + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-grtev4-linux-gnu" + +declare dso_local void @f() + +; CHECK-LABEL: @foo +define dso_local void @foo() { +entry: + br i1 undef, label %if.then, label %if.end + +if.then: ; preds = %entry + br label %try.cont + +if.end: ; preds = %entry +; 1 = MemoryDef(liveOnEntry) + call void @f() + br label %try.cont + +catch: ; No predecessors! +; 2 = MemoryDef(liveOnEntry) + call void @f() + br label %try.cont + +try.cont: ; preds = %if.end, %catch, %if.then +; 3 = MemoryPhi({if.then,liveOnEntry},{if.end,1},{catch,liveOnEntry}) + ret void +} |