[llvm] [JumpThreading] Invalidate LVI after `combineMetadataForCSE`. (PR #65219)

via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 3 06:59:54 PDT 2023


https://github.com/DianQK updated https://github.com/llvm/llvm-project/pull/65219:

>From 543fd1854da4ee918c50e9ac87e49cf4df4534a9 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Sun, 3 Sep 2023 12:18:57 +0800
Subject: [PATCH 1/3] [JumpThreading][NFC] Pre-commit for invalid LVI.

---
 .../JumpThreading/invalidate-lvi.ll           | 53 +++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 llvm/test/Transforms/JumpThreading/invalidate-lvi.ll

diff --git a/llvm/test/Transforms/JumpThreading/invalidate-lvi.ll b/llvm/test/Transforms/JumpThreading/invalidate-lvi.ll
new file mode 100644
index 00000000000000..9c5cbfac62d9fb
--- /dev/null
+++ b/llvm/test/Transforms/JumpThreading/invalidate-lvi.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -S -passes=jump-threading < %s | FileCheck %s
+
+declare void @set_value(ptr)
+
+declare void @bar()
+
+define void @foo(i1 %0) {
+; CHECK-LABEL: define void @foo(
+; CHECK-SAME: i1 [[TMP0:%.*]]) {
+; CHECK-NEXT:  start:
+; CHECK-NEXT:    [[V:%.*]] = alloca i64, align 8
+; CHECK-NEXT:    call void @set_value(ptr [[V]])
+; CHECK-NEXT:    [[L1:%.*]] = load i64, ptr [[V]], align 8
+; CHECK-NEXT:    br i1 [[TMP0]], label [[BB0:%.*]], label [[BB4:%.*]]
+; CHECK:       bb0:
+; CHECK-NEXT:    [[C1:%.*]] = icmp eq i64 [[L1]], 0
+; CHECK-NEXT:    br i1 [[C1]], label [[BB1:%.*]], label [[BB4]]
+; CHECK:       bb1:
+; CHECK-NEXT:    store i64 0, ptr [[V]], align 8
+; CHECK-NEXT:    br label [[BB4]]
+; CHECK:       bb4:
+; CHECK-NEXT:    [[L2:%.*]] = phi i64 [ 0, [[BB1]] ], [ [[L1]], [[BB0]] ], [ [[L1]], [[START:%.*]] ]
+; CHECK-NEXT:    ret void
+;
+start:
+  %v = alloca i64, align 8
+  call void @set_value(ptr %v)
+  %l1 = load i64, ptr %v, align 8, !range !0
+  br i1 %0, label %bb0, label %bb2
+
+bb0:                                              ; preds = %start
+  %c1 = icmp eq i64 %l1, 0
+  br i1 %c1, label %bb1, label %bb2
+
+bb1:                                              ; preds = %bb0
+  store i64 0, ptr %v, align 8
+  br label %bb2
+
+bb2:                                              ; preds = %bb1, %bb0, %start
+  %l2 = load i64, ptr %v, align 8
+  %1 = icmp eq i64 %l2, 2
+  br i1 %1, label %bb3, label %bb4
+
+bb3:                                              ; preds = %bb2
+  call void @bar()
+  ret void
+
+bb4:                                              ; preds = %bb2
+  ret void
+}
+
+!0 = !{i64 0, i64 2}

>From a202e26749f48e891696eb4108b0bb0341bf28d1 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Sun, 3 Sep 2023 12:23:33 +0800
Subject: [PATCH 2/3] [JumpThreading] Invalidate LVI after
 `combineMetadataForCSE`.

---
 llvm/include/llvm/Analysis/LazyValueInfo.h    |  3 ++
 llvm/lib/Analysis/LazyValueInfo.cpp           | 35 +++++++++++++------
 llvm/lib/Transforms/Scalar/JumpThreading.cpp  |  2 ++
 .../JumpThreading/invalidate-lvi.ll           | 16 ++++++---
 4 files changed, 41 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/Analysis/LazyValueInfo.h b/llvm/include/llvm/Analysis/LazyValueInfo.h
index b109b7f7e65ae7..7b2bfdac75a8fa 100644
--- a/llvm/include/llvm/Analysis/LazyValueInfo.h
+++ b/llvm/include/llvm/Analysis/LazyValueInfo.h
@@ -115,6 +115,9 @@ class LazyValueInfo {
   /// PredBB to OldSucc to be from PredBB to NewSucc instead.
   void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc);
 
+  /// Remove information related to this value from the cache.
+  void forgetValue(Value *V);
+
   /// Inform the analysis cache that we have erased a block.
   void eraseBlock(BasicBlock *BB);
 
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 33651783cb1777..a4ca00db000ee4 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -245,6 +245,9 @@ namespace {
       ValueHandles.clear();
     }
 
+    /// Remove information related to this value from the cache.
+    void forgetValue(Value *V);
+
     /// Inform the cache that a given value has been deleted.
     void eraseValue(Value *V);
 
@@ -259,17 +262,20 @@ namespace {
   };
 }
 
-void LazyValueInfoCache::eraseValue(Value *V) {
-  for (auto &Pair : BlockCache) {
-    Pair.second->LatticeElements.erase(V);
-    Pair.second->OverDefined.erase(V);
-    if (Pair.second->NonNullPointers)
-      Pair.second->NonNullPointers->erase(V);
-  }
+void LazyValueInfoCache::forgetValue(Value *V) {
+    for (auto &Pair : BlockCache) {
+      Pair.second->LatticeElements.erase(V);
+      Pair.second->OverDefined.erase(V);
+      if (Pair.second->NonNullPointers)
+        Pair.second->NonNullPointers->erase(V);
+    }
+}
 
-  auto HandleIt = ValueHandles.find_as(V);
-  if (HandleIt != ValueHandles.end())
-    ValueHandles.erase(HandleIt);
+void LazyValueInfoCache::eraseValue(Value *V) {
+    forgetValue(V);
+    auto HandleIt = ValueHandles.find_as(V);
+    if (HandleIt != ValueHandles.end())
+      ValueHandles.erase(HandleIt);
 }
 
 void LVIValueHandle::deleted() {
@@ -465,6 +471,10 @@ class LazyValueInfoImpl {
     F.print(OS, &Writer);
   }
 
+  /// This is part of the update interface to remove information related to this
+  /// value from the cache.
+  void forgetValue(Value *V) { TheCache.forgetValue(V); }
+
   /// This is part of the update interface to inform the cache
   /// that a block has been deleted.
   void eraseBlock(BasicBlock *BB) {
@@ -1969,6 +1979,11 @@ void LazyValueInfo::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,
   }
 }
 
+void LazyValueInfo::forgetValue(Value *V) {
+  if (PImpl)
+    getImpl(PImpl, AC, nullptr).forgetValue(V);
+}
+
 void LazyValueInfo::eraseBlock(BasicBlock *BB) {
   if (PImpl) {
     getImpl(PImpl, AC, BB->getModule()).eraseBlock(BB);
diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index 180e6b4c823880..83d56b56fc801b 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -1269,6 +1269,7 @@ bool JumpThreadingPass::simplifyPartiallyRedundantLoad(LoadInst *LoadI) {
     if (IsLoadCSE) {
       LoadInst *NLoadI = cast<LoadInst>(AvailableVal);
       combineMetadataForCSE(NLoadI, LoadI, false);
+      LVI->forgetValue(NLoadI);
     };
 
     // If the returned value is the load itself, replace with poison. This can
@@ -1461,6 +1462,7 @@ bool JumpThreadingPass::simplifyPartiallyRedundantLoad(LoadInst *LoadI) {
 
   for (LoadInst *PredLoadI : CSELoads) {
     combineMetadataForCSE(PredLoadI, LoadI, true);
+    LVI->forgetValue(PredLoadI);
   }
 
   LoadI->replaceAllUsesWith(PN);
diff --git a/llvm/test/Transforms/JumpThreading/invalidate-lvi.ll b/llvm/test/Transforms/JumpThreading/invalidate-lvi.ll
index 9c5cbfac62d9fb..27191d6f54c2d8 100644
--- a/llvm/test/Transforms/JumpThreading/invalidate-lvi.ll
+++ b/llvm/test/Transforms/JumpThreading/invalidate-lvi.ll
@@ -12,15 +12,21 @@ define void @foo(i1 %0) {
 ; CHECK-NEXT:    [[V:%.*]] = alloca i64, align 8
 ; CHECK-NEXT:    call void @set_value(ptr [[V]])
 ; CHECK-NEXT:    [[L1:%.*]] = load i64, ptr [[V]], align 8
-; CHECK-NEXT:    br i1 [[TMP0]], label [[BB0:%.*]], label [[BB4:%.*]]
+; CHECK-NEXT:    br i1 [[TMP0]], label [[BB0:%.*]], label [[BB2:%.*]]
 ; CHECK:       bb0:
 ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i64 [[L1]], 0
-; CHECK-NEXT:    br i1 [[C1]], label [[BB1:%.*]], label [[BB4]]
-; CHECK:       bb1:
+; CHECK-NEXT:    br i1 [[C1]], label [[BB2_THREAD:%.*]], label [[BB2]]
+; CHECK:       bb2.thread:
 ; CHECK-NEXT:    store i64 0, ptr [[V]], align 8
-; CHECK-NEXT:    br label [[BB4]]
+; CHECK-NEXT:    br label [[BB4:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[L2:%.*]] = phi i64 [ [[L1]], [[BB0]] ], [ [[L1]], [[START:%.*]] ]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[L2]], 2
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB3:%.*]], label [[BB4]]
+; CHECK:       bb3:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    ret void
 ; CHECK:       bb4:
-; CHECK-NEXT:    [[L2:%.*]] = phi i64 [ 0, [[BB1]] ], [ [[L1]], [[BB0]] ], [ [[L1]], [[START:%.*]] ]
 ; CHECK-NEXT:    ret void
 ;
 start:

>From 394cfa5f000924e7070224ee9664fa3ab6f6c80a Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Sun, 3 Sep 2023 20:58:08 +0800
Subject: [PATCH 3/3] WIP

---
 llvm/include/llvm/Analysis/LazyValueInfo.h | 221 +++++++++++----------
 llvm/lib/Analysis/LazyValueInfo.cpp        |  98 ++++-----
 2 files changed, 161 insertions(+), 158 deletions(-)

diff --git a/llvm/include/llvm/Analysis/LazyValueInfo.h b/llvm/include/llvm/Analysis/LazyValueInfo.h
index 7b2bfdac75a8fa..f013a4a75d3d6a 100644
--- a/llvm/include/llvm/Analysis/LazyValueInfo.h
+++ b/llvm/include/llvm/Analysis/LazyValueInfo.h
@@ -26,117 +26,120 @@ namespace llvm {
   class Instruction;
   class TargetLibraryInfo;
   class Value;
-
-/// This pass computes, caches, and vends lazy value constraint information.
-class LazyValueInfo {
-  friend class LazyValueInfoWrapperPass;
-  AssumptionCache *AC = nullptr;
-  const DataLayout *DL = nullptr;
-  class TargetLibraryInfo *TLI = nullptr;
-  void *PImpl = nullptr;
-  LazyValueInfo(const LazyValueInfo&) = delete;
-  void operator=(const LazyValueInfo&) = delete;
-public:
-  ~LazyValueInfo();
-  LazyValueInfo() = default;
-  LazyValueInfo(AssumptionCache *AC_, const DataLayout *DL_,
-                TargetLibraryInfo *TLI_)
-      : AC(AC_), DL(DL_), TLI(TLI_) {}
-  LazyValueInfo(LazyValueInfo &&Arg)
-      : AC(Arg.AC), DL(Arg.DL), TLI(Arg.TLI), PImpl(Arg.PImpl) {
-    Arg.PImpl = nullptr;
-  }
-  LazyValueInfo &operator=(LazyValueInfo &&Arg) {
-    releaseMemory();
-    AC = Arg.AC;
-    DL = Arg.DL;
-    TLI = Arg.TLI;
-    PImpl = Arg.PImpl;
-    Arg.PImpl = nullptr;
-    return *this;
-  }
-
-  /// This is used to return true/false/dunno results.
-  enum Tristate {
-    Unknown = -1, False = 0, True = 1
+  class LazyValueInfoImpl;
+  /// This pass computes, caches, and vends lazy value constraint information.
+  class LazyValueInfo {
+    friend class LazyValueInfoWrapperPass;
+    AssumptionCache *AC = nullptr;
+    const DataLayout *DL = nullptr;
+    class TargetLibraryInfo *TLI = nullptr;
+    LazyValueInfoImpl *PImpl = nullptr;
+    LazyValueInfo(const LazyValueInfo &) = delete;
+    void operator=(const LazyValueInfo &) = delete;
+
+    LazyValueInfoImpl *getImpl();
+    LazyValueInfoImpl &getOrCreateImpl(const Module *M);
+
+  public:
+    ~LazyValueInfo();
+    LazyValueInfo() = default;
+    LazyValueInfo(AssumptionCache *AC_, const DataLayout *DL_,
+                  TargetLibraryInfo *TLI_)
+        : AC(AC_), DL(DL_), TLI(TLI_) {}
+    LazyValueInfo(LazyValueInfo &&Arg)
+        : AC(Arg.AC), DL(Arg.DL), TLI(Arg.TLI), PImpl(Arg.PImpl) {
+      Arg.PImpl = nullptr;
+    }
+    LazyValueInfo &operator=(LazyValueInfo &&Arg) {
+      releaseMemory();
+      AC = Arg.AC;
+      DL = Arg.DL;
+      TLI = Arg.TLI;
+      PImpl = Arg.PImpl;
+      Arg.PImpl = nullptr;
+      return *this;
+    }
+
+    /// This is used to return true/false/dunno results.
+    enum Tristate { Unknown = -1, False = 0, True = 1 };
+
+    // Public query interface.
+
+    /// Determine whether the specified value comparison with a constant is
+    /// known to be true or false on the specified CFG edge. Pred is a CmpInst
+    /// predicate.
+    Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
+                                BasicBlock *FromBB, BasicBlock *ToBB,
+                                Instruction *CxtI = nullptr);
+
+    /// Determine whether the specified value comparison with a constant is
+    /// known to be true or false at the specified instruction. \p Pred is a
+    /// CmpInst predicate. If \p UseBlockValue is true, the block value is also
+    /// taken into account.
+    Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C,
+                            Instruction *CxtI, bool UseBlockValue);
+
+    /// Determine whether the specified value comparison is known to be true
+    /// or false at the specified instruction. While this takes two Value's,
+    /// it still requires that one of them is a constant.
+    /// \p Pred is a CmpInst predicate.
+    /// If \p UseBlockValue is true, the block value is also taken into account.
+    Tristate getPredicateAt(unsigned Pred, Value *LHS, Value *RHS,
+                            Instruction *CxtI, bool UseBlockValue);
+
+    /// Determine whether the specified value is known to be a constant at the
+    /// specified instruction. Return null if not.
+    Constant *getConstant(Value *V, Instruction *CxtI);
+
+    /// Return the ConstantRange constraint that is known to hold for the
+    /// specified value at the specified instruction. This may only be called
+    /// on integer-typed Values.
+    ConstantRange getConstantRange(Value *V, Instruction *CxtI,
+                                   bool UndefAllowed = true);
+
+    /// Return the ConstantRange constraint that is known to hold for the value
+    /// at a specific use-site.
+    ConstantRange getConstantRangeAtUse(const Use &U, bool UndefAllowed = true);
+
+    /// Determine whether the specified value is known to be a
+    /// constant on the specified edge.  Return null if not.
+    Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
+                                Instruction *CxtI = nullptr);
+
+    /// Return the ConstantRage constraint that is known to hold for the
+    /// specified value on the specified edge. This may be only be called
+    /// on integer-typed Values.
+    ConstantRange getConstantRangeOnEdge(Value *V, BasicBlock *FromBB,
+                                         BasicBlock *ToBB,
+                                         Instruction *CxtI = nullptr);
+
+    /// Inform the analysis cache that we have threaded an edge from
+    /// PredBB to OldSucc to be from PredBB to NewSucc instead.
+    void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,
+                    BasicBlock *NewSucc);
+
+    /// Remove information related to this value from the cache.
+    void forgetValue(Value *V);
+
+    /// Inform the analysis cache that we have erased a block.
+    void eraseBlock(BasicBlock *BB);
+
+    /// Complete flush all previously computed values
+    void clear();
+
+    /// Print the \LazyValueInfo Analysis.
+    /// We pass in the DTree that is required for identifying which basic blocks
+    /// we can solve/print for, in the LVIPrinter.
+    void printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS);
+
+    // For old PM pass. Delete once LazyValueInfoWrapperPass is gone.
+    void releaseMemory();
+
+    /// Handle invalidation events in the new pass manager.
+    bool invalidate(Function &F, const PreservedAnalyses &PA,
+                    FunctionAnalysisManager::Invalidator &Inv);
   };
 
-  // Public query interface.
-
-  /// Determine whether the specified value comparison with a constant is known
-  /// to be true or false on the specified CFG edge.
-  /// Pred is a CmpInst predicate.
-  Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
-                              BasicBlock *FromBB, BasicBlock *ToBB,
-                              Instruction *CxtI = nullptr);
-
-  /// Determine whether the specified value comparison with a constant is known
-  /// to be true or false at the specified instruction.
-  /// \p Pred is a CmpInst predicate. If \p UseBlockValue is true, the block
-  /// value is also taken into account.
-  Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C,
-                          Instruction *CxtI, bool UseBlockValue);
-
-  /// Determine whether the specified value comparison is known to be true
-  /// or false at the specified instruction. While this takes two Value's,
-  /// it still requires that one of them is a constant.
-  /// \p Pred is a CmpInst predicate.
-  /// If \p UseBlockValue is true, the block value is also taken into account.
-  Tristate getPredicateAt(unsigned Pred, Value *LHS, Value *RHS,
-                          Instruction *CxtI, bool UseBlockValue);
-
-  /// Determine whether the specified value is known to be a constant at the
-  /// specified instruction. Return null if not.
-  Constant *getConstant(Value *V, Instruction *CxtI);
-
-  /// Return the ConstantRange constraint that is known to hold for the
-  /// specified value at the specified instruction. This may only be called
-  /// on integer-typed Values.
-  ConstantRange getConstantRange(Value *V, Instruction *CxtI,
-                                 bool UndefAllowed = true);
-
-  /// Return the ConstantRange constraint that is known to hold for the value
-  /// at a specific use-site.
-  ConstantRange getConstantRangeAtUse(const Use &U, bool UndefAllowed = true);
-
-  /// Determine whether the specified value is known to be a
-  /// constant on the specified edge.  Return null if not.
-  Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
-                              Instruction *CxtI = nullptr);
-
-  /// Return the ConstantRage constraint that is known to hold for the
-  /// specified value on the specified edge. This may be only be called
-  /// on integer-typed Values.
-  ConstantRange getConstantRangeOnEdge(Value *V, BasicBlock *FromBB,
-                                       BasicBlock *ToBB,
-                                       Instruction *CxtI = nullptr);
-
-  /// Inform the analysis cache that we have threaded an edge from
-  /// PredBB to OldSucc to be from PredBB to NewSucc instead.
-  void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc);
-
-  /// Remove information related to this value from the cache.
-  void forgetValue(Value *V);
-
-  /// Inform the analysis cache that we have erased a block.
-  void eraseBlock(BasicBlock *BB);
-
-  /// Complete flush all previously computed values
-  void clear(const Module *M);
-
-  /// Print the \LazyValueInfo Analysis.
-  /// We pass in the DTree that is required for identifying which basic blocks
-  /// we can solve/print for, in the LVIPrinter.
-  void printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS);
-
-  // For old PM pass. Delete once LazyValueInfoWrapperPass is gone.
-  void releaseMemory();
-
-  /// Handle invalidation events in the new pass manager.
-  bool invalidate(Function &F, const PreservedAnalyses &PA,
-                  FunctionAnalysisManager::Invalidator &Inv);
-};
-
 /// Analysis to compute lazy value information.
 class LazyValueAnalysis : public AnalysisInfoMixin<LazyValueAnalysis> {
 public:
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index a4ca00db000ee4..9249db623a4567 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -342,11 +342,10 @@ void LazyValueInfoCache::threadEdgeImpl(BasicBlock *OldSucc,
   }
 }
 
-
+namespace llvm {
 namespace {
 /// An assembly annotator class to print LazyValueCache information in
 /// comments.
-class LazyValueInfoImpl;
 class LazyValueInfoAnnotatedWriter : public AssemblyAnnotationWriter {
   LazyValueInfoImpl *LVIImpl;
   // While analyzing which blocks we can solve values for, we need the dominator
@@ -363,8 +362,7 @@ class LazyValueInfoAnnotatedWriter : public AssemblyAnnotationWriter {
   void emitInstructionAnnot(const Instruction *I,
                             formatted_raw_ostream &OS) override;
 };
-}
-namespace {
+} // namespace
 // The actual implementation of the lazy analysis and update.  Note that the
 // inheritance from LazyValueInfoCache is intended to be temporary while
 // splitting the code and then transitioning to a has-a relationship.
@@ -489,8 +487,7 @@ class LazyValueInfoImpl {
                     Function *GuardDecl)
       : AC(AC), DL(DL), GuardDecl(GuardDecl) {}
 };
-} // end anonymous namespace
-
+} // namespace llvm
 
 void LazyValueInfoImpl::solve() {
   SmallVector<std::pair<BasicBlock *, Value *>, 8> StartingStack(
@@ -1552,25 +1549,12 @@ void LazyValueInfoImpl::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,
 //                            LazyValueInfo Impl
 //===----------------------------------------------------------------------===//
 
-/// This lazily constructs the LazyValueInfoImpl.
-static LazyValueInfoImpl &getImpl(void *&PImpl, AssumptionCache *AC,
-                                  const Module *M) {
-  if (!PImpl) {
-    assert(M && "getCache() called with a null Module");
-    const DataLayout &DL = M->getDataLayout();
-    Function *GuardDecl = M->getFunction(
-        Intrinsic::getName(Intrinsic::experimental_guard));
-    PImpl = new LazyValueInfoImpl(AC, DL, GuardDecl);
-  }
-  return *static_cast<LazyValueInfoImpl*>(PImpl);
-}
-
 bool LazyValueInfoWrapperPass::runOnFunction(Function &F) {
   Info.AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
   Info.TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
 
-  if (Info.PImpl)
-    getImpl(Info.PImpl, Info.AC, F.getParent()).clear();
+  if (auto *Impl = Info.getImpl())
+    Impl->clear();
 
   // Fully lazy.
   return false;
@@ -1584,12 +1568,32 @@ void LazyValueInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
 
 LazyValueInfo &LazyValueInfoWrapperPass::getLVI() { return Info; }
 
+/// This lazily constructs the LazyValueInfoImpl.
+LazyValueInfoImpl &LazyValueInfo::getOrCreateImpl(const Module *M) {
+  if (!PImpl) {
+    assert(M && "getCache() called with a null Module");
+    const DataLayout &DL = M->getDataLayout();
+    Function *GuardDecl =
+        M->getFunction(Intrinsic::getName(Intrinsic::experimental_guard));
+    PImpl = new LazyValueInfoImpl(AC, DL, GuardDecl);
+  }
+  return *static_cast<LazyValueInfoImpl *>(PImpl);
+}
+
+LazyValueInfoImpl *LazyValueInfo::getImpl() {
+  if (!PImpl) {
+    assert(false && "PImpl uninitialized");
+    return nullptr;
+  }
+  return static_cast<LazyValueInfoImpl *>(PImpl);
+}
+
 LazyValueInfo::~LazyValueInfo() { releaseMemory(); }
 
 void LazyValueInfo::releaseMemory() {
   // If the cache was allocated, free it.
-  if (PImpl) {
-    delete &getImpl(PImpl, AC, nullptr);
+  if (auto *Impl = getImpl()) {
+    delete &*Impl;
     PImpl = nullptr;
   }
 }
@@ -1636,7 +1640,7 @@ Constant *LazyValueInfo::getConstant(Value *V, Instruction *CxtI) {
 
   BasicBlock *BB = CxtI->getParent();
   ValueLatticeElement Result =
-      getImpl(PImpl, AC, BB->getModule()).getValueInBlock(V, BB, CxtI);
+      getOrCreateImpl(BB->getModule()).getValueInBlock(V, BB, CxtI);
 
   if (Result.isConstant())
     return Result.getConstant();
@@ -1654,7 +1658,7 @@ ConstantRange LazyValueInfo::getConstantRange(Value *V, Instruction *CxtI,
   unsigned Width = V->getType()->getIntegerBitWidth();
   BasicBlock *BB = CxtI->getParent();
   ValueLatticeElement Result =
-      getImpl(PImpl, AC, BB->getModule()).getValueInBlock(V, BB, CxtI);
+      getOrCreateImpl(BB->getModule()).getValueInBlock(V, BB, CxtI);
   if (Result.isUnknown())
     return ConstantRange::getEmpty(Width);
   if (Result.isConstantRange(UndefAllowed))
@@ -1720,7 +1724,7 @@ Constant *LazyValueInfo::getConstantOnEdge(Value *V, BasicBlock *FromBB,
                                            Instruction *CxtI) {
   Module *M = FromBB->getModule();
   ValueLatticeElement Result =
-      getImpl(PImpl, AC, M).getValueOnEdge(V, FromBB, ToBB, CxtI);
+      getOrCreateImpl(M).getValueOnEdge(V, FromBB, ToBB, CxtI);
 
   if (Result.isConstant())
     return Result.getConstant();
@@ -1739,7 +1743,7 @@ ConstantRange LazyValueInfo::getConstantRangeOnEdge(Value *V,
   unsigned Width = V->getType()->getIntegerBitWidth();
   Module *M = FromBB->getModule();
   ValueLatticeElement Result =
-      getImpl(PImpl, AC, M).getValueOnEdge(V, FromBB, ToBB, CxtI);
+      getOrCreateImpl(M).getValueOnEdge(V, FromBB, ToBB, CxtI);
 
   if (Result.isUnknown())
     return ConstantRange::getEmpty(Width);
@@ -1825,7 +1829,7 @@ LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
                                   Instruction *CxtI) {
   Module *M = FromBB->getModule();
   ValueLatticeElement Result =
-      getImpl(PImpl, AC, M).getValueOnEdge(V, FromBB, ToBB, CxtI);
+      getOrCreateImpl(M).getValueOnEdge(V, FromBB, ToBB, CxtI);
 
   return getPredicateResult(Pred, C, Result, M->getDataLayout(), TLI);
 }
@@ -1847,9 +1851,10 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
       return LazyValueInfo::True;
   }
 
-  ValueLatticeElement Result = UseBlockValue
-      ? getImpl(PImpl, AC, M).getValueInBlock(V, CxtI->getParent(), CxtI)
-      : getImpl(PImpl, AC, M).getValueAt(V, CxtI);
+  auto &Impl = getOrCreateImpl(M);
+  ValueLatticeElement Result =
+      UseBlockValue ? Impl.getValueInBlock(V, CxtI->getParent(), CxtI)
+                    : Impl.getValueAt(V, CxtI);
   Tristate Ret = getPredicateResult(Pred, C, Result, DL, TLI);
   if (Ret != Unknown)
     return Ret;
@@ -1953,12 +1958,12 @@ LazyValueInfo::Tristate LazyValueInfo::getPredicateAt(unsigned P, Value *LHS,
   if (UseBlockValue) {
     Module *M = CxtI->getModule();
     ValueLatticeElement L =
-        getImpl(PImpl, AC, M).getValueInBlock(LHS, CxtI->getParent(), CxtI);
+        getOrCreateImpl(M).getValueInBlock(LHS, CxtI->getParent(), CxtI);
     if (L.isOverdefined())
       return LazyValueInfo::Unknown;
 
     ValueLatticeElement R =
-        getImpl(PImpl, AC, M).getValueInBlock(RHS, CxtI->getParent(), CxtI);
+        getOrCreateImpl(M).getValueInBlock(RHS, CxtI->getParent(), CxtI);
     Type *Ty = CmpInst::makeCmpResultType(LHS->getType());
     if (Constant *Res = L.getCompare((CmpInst::Predicate)P, Ty, R,
                                      M->getDataLayout())) {
@@ -1973,33 +1978,28 @@ LazyValueInfo::Tristate LazyValueInfo::getPredicateAt(unsigned P, Value *LHS,
 
 void LazyValueInfo::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,
                                BasicBlock *NewSucc) {
-  if (PImpl) {
-    getImpl(PImpl, AC, PredBB->getModule())
-        .threadEdge(PredBB, OldSucc, NewSucc);
-  }
+  if (auto *Impl = getImpl())
+    Impl->threadEdge(PredBB, OldSucc, NewSucc);
 }
 
 void LazyValueInfo::forgetValue(Value *V) {
-  if (PImpl)
-    getImpl(PImpl, AC, nullptr).forgetValue(V);
+  if (auto *Impl = getImpl())
+    getImpl()->forgetValue(V);
 }
 
 void LazyValueInfo::eraseBlock(BasicBlock *BB) {
-  if (PImpl) {
-    getImpl(PImpl, AC, BB->getModule()).eraseBlock(BB);
-  }
+  if (auto *Impl = getImpl())
+    getImpl()->eraseBlock(BB);
 }
 
-void LazyValueInfo::clear(const Module *M) {
-  if (PImpl) {
-    getImpl(PImpl, AC, M).clear();
-  }
+void LazyValueInfo::clear() {
+  if (auto *Impl = getImpl())
+    getImpl()->clear();
 }
 
 void LazyValueInfo::printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS) {
-  if (PImpl) {
-    getImpl(PImpl, AC, F.getParent()).printLVI(F, DTree, OS);
-  }
+  if (auto *Impl = getImpl())
+    getImpl()->printLVI(F, DTree, OS);
 }
 
 // Print the LVI for the function arguments at the start of each basic block.



More information about the llvm-commits mailing list