[llvm] [UniformityAnalysis] Add CallbackVH to keep UniformValues consistent on value deletion (PR #187658)

Pankaj Dwivedi via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 13 07:34:45 PDT 2026


https://github.com/PankajDwivedi-25 updated https://github.com/llvm/llvm-project/pull/187658

>From 14bbeb4621d51633071a3c77fbd0690679c06220 Mon Sep 17 00:00:00 2001
From: padivedi <padivedi at amd.com>
Date: Thu, 9 Apr 2026 12:01:46 +0530
Subject: [PATCH 1/4] add callBackVH sdupport in uniformity

---
 llvm/include/llvm/ADT/GenericUniformityImpl.h | 14 ++++++
 llvm/include/llvm/ADT/GenericUniformityInfo.h |  1 +
 llvm/lib/Analysis/UniformityAnalysis.cpp      | 45 +++++++++++++++++++
 .../lib/CodeGen/MachineUniformityAnalysis.cpp |  4 ++
 .../Target/AMDGPU/UniformityAnalysisTest.cpp  | 43 ++++++++++++++++++
 5 files changed, 107 insertions(+)

diff --git a/llvm/include/llvm/ADT/GenericUniformityImpl.h b/llvm/include/llvm/ADT/GenericUniformityImpl.h
index d5859981ce1a7..d439571b7bc4c 100644
--- a/llvm/include/llvm/ADT/GenericUniformityImpl.h
+++ b/llvm/include/llvm/ADT/GenericUniformityImpl.h
@@ -57,6 +57,12 @@
 
 namespace llvm {
 
+/// Interface for keeping UniformValues in sync when IR values are deleted.
+/// IR specialization installs a concrete CallbackVH-based implementation.
+struct UniformValueCallbackManager {
+  virtual ~UniformValueCallbackManager() = default;
+};
+
 // Forward decl from llvm/CodeGen/MachineInstr.h
 class MachineInstr;
 
@@ -376,6 +382,10 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
   /// Divergence is seeded by calls to \p markDivergent.
   void compute();
 
+  /// \brief Register callbacks (e.g., CallbackVH for IR) to keep
+  /// UniformValues in sync when values are deleted after analysis.
+  void registerCallbacks();
+
   /// \brief Whether \p Val will always return a uniform value regardless of its
   /// operands
   bool isAlwaysUniform(const InstructionT &Instr) const;
@@ -447,6 +457,10 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
   // values not in this set are conservatively treated as divergent.
   DenseSet<ConstValueRefT> UniformValues;
 
+  // For IR: callbacks to remove from UniformValues on value deletion,
+  // avoiding stale pointers when addresses are reused.
+  std::unique_ptr<UniformValueCallbackManager> UniformValueCallbacks;
+
   // Internal worklist for divergence propagation.
   std::vector<const InstructionT *> Worklist;
 
diff --git a/llvm/include/llvm/ADT/GenericUniformityInfo.h b/llvm/include/llvm/ADT/GenericUniformityInfo.h
index a504335ec078e..7dff3d84d92cf 100644
--- a/llvm/include/llvm/ADT/GenericUniformityInfo.h
+++ b/llvm/include/llvm/ADT/GenericUniformityInfo.h
@@ -52,6 +52,7 @@ template <typename ContextT> class GenericUniformityInfo {
   void compute() {
     DA->initialize();
     DA->compute();
+    DA->registerCallbacks();
   }
 
   /// The GPU kernel this analysis result is for
diff --git a/llvm/lib/Analysis/UniformityAnalysis.cpp b/llvm/lib/Analysis/UniformityAnalysis.cpp
index 41519bcd09baa..b3d56737d2ad8 100644
--- a/llvm/lib/Analysis/UniformityAnalysis.cpp
+++ b/llvm/lib/Analysis/UniformityAnalysis.cpp
@@ -14,10 +14,46 @@
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instructions.h"
+#include "llvm/IR/ValueHandle.h"
 #include "llvm/InitializePasses.h"
 
 using namespace llvm;
 
+namespace {
+
+/// CallbackVH that removes the value from UniformValues on deletion.
+/// Prevents stale pointers when a deleted value's address is reused.
+class UniformValueHandle : public CallbackVH {
+  DenseSet<const Value *> &UniformSet;
+
+public:
+  UniformValueHandle(Value *V, DenseSet<const Value *> &S)
+      : CallbackVH(V), UniformSet(S) {}
+  virtual ~UniformValueHandle() = default;
+
+  void deleted() override {
+    UniformSet.erase(getValPtr());
+    CallbackVH::deleted();
+  }
+};
+
+/// IR implementation: registers CallbackVH for each uniform value.
+class IRUniformValueCallbackManager : public UniformValueCallbackManager {
+  DenseSet<const Value *> &UniformSet;
+  std::vector<std::unique_ptr<UniformValueHandle>> Handles;
+
+public:
+  explicit IRUniformValueCallbackManager(DenseSet<const Value *> &S)
+      : UniformSet(S) {}
+
+  void registerValue(const Value *V) {
+    Handles.push_back(std::make_unique<UniformValueHandle>(
+        const_cast<Value *>(V), UniformSet));
+  }
+};
+
+} // namespace
+
 template <>
 bool llvm::GenericUniformityAnalysisImpl<SSAContext>::hasDivergentDefs(
     const Instruction &I) const {
@@ -107,6 +143,15 @@ template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() {
     pushUsers(Arg);
 }
 
+template <>
+void llvm::GenericUniformityAnalysisImpl<SSAContext>::registerCallbacks() {
+  IRUniformValueCallbackManager *Manager =
+      new IRUniformValueCallbackManager(UniformValues);
+  for (const Value *V : UniformValues)
+    Manager->registerValue(V);
+  UniformValueCallbacks.reset(Manager);
+}
+
 template <>
 bool llvm::GenericUniformityAnalysisImpl<SSAContext>::usesValueFromCycle(
     const Instruction &I, const Cycle &DefCycle) const {
diff --git a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
index aa85b95a96d09..5467e88c41745 100644
--- a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
+++ b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
@@ -84,6 +84,10 @@ void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
   }
 }
 
+template <>
+void llvm::GenericUniformityAnalysisImpl<
+    MachineSSAContext>::registerCallbacks() {}
+
 template <>
 void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
     Register Reg) {
diff --git a/llvm/unittests/Target/AMDGPU/UniformityAnalysisTest.cpp b/llvm/unittests/Target/AMDGPU/UniformityAnalysisTest.cpp
index ae44d3ef6cbf2..7ad54af38f443 100644
--- a/llvm/unittests/Target/AMDGPU/UniformityAnalysisTest.cpp
+++ b/llvm/unittests/Target/AMDGPU/UniformityAnalysisTest.cpp
@@ -93,3 +93,46 @@ TEST(UniformityAnalysis, NewValueIsConservativelyDivergent) {
   EXPECT_TRUE(UI.isDivergent(NewInst))
       << "New instruction created after analysis must be reported divergent";
 }
+
+TEST(UniformityAnalysis, DeletionCallbackMakesNewInstDivergent) {
+  // Delete a uniform instruction. CallbackVH::deleted() removes it from
+  // UniformValues during eraseFromParent(). A newly created instruction is
+  // not in UniformValues and must be conservatively reported as divergent.
+  LLVMInitializeAMDGPUTargetInfo();
+  LLVMInitializeAMDGPUTarget();
+  LLVMInitializeAMDGPUTargetMC();
+
+  StringRef ModuleString = R"(
+  target triple = "amdgcn-unknown-amdhsa"
+  define amdgpu_kernel void @test(i32 inreg %a, i32 inreg %b) {
+    %add = add i32 %a, %b
+    ret void
+  }
+  )";
+  LLVMContext Context;
+  SMDiagnostic Err;
+  std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, Context);
+  ASSERT_TRUE(M) << Err.getMessage();
+
+  Function *F = M->getFunction("test");
+  ASSERT_TRUE(F);
+
+  std::unique_ptr<TargetMachine> TM =
+      createAMDGPUTargetMachine("amdgcn-amd-", "gfx1010", "+wavefrontsize32");
+  ASSERT_TRUE(TM);
+  TargetTransformInfo TTI = TM->getTargetTransformInfo(*F);
+
+  UniformityInfo UI = computeUniformity(&TTI, F);
+
+  Instruction *AddInst = &*F->getEntryBlock().begin();
+  ASSERT_TRUE(isa<BinaryOperator>(AddInst));
+  EXPECT_FALSE(UI.isDivergent(AddInst)) << "%add should be uniform";
+
+  AddInst->eraseFromParent();
+
+  IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
+  Value *NewInst = Builder.CreateAdd(F->getArg(0), F->getArg(1), "new_add");
+
+  EXPECT_TRUE(UI.isDivergent(NewInst))
+      << "New instruction after deletion must be reported divergent";
+}

>From c30110b31c99ed0b2509a121f2e8e2701db5bd76 Mon Sep 17 00:00:00 2001
From: Pankaj Dwivedi <pankajkumar.divedi at amd.com>
Date: Thu, 9 Apr 2026 19:29:17 +0530
Subject: [PATCH 2/4] Update UniformityAnalysis.cpp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Juan Manuel Martinez CaamaƱo <jmartinezcaamao at gmail.com>
---
 llvm/lib/Analysis/UniformityAnalysis.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Analysis/UniformityAnalysis.cpp b/llvm/lib/Analysis/UniformityAnalysis.cpp
index b3d56737d2ad8..1ccad01192737 100644
--- a/llvm/lib/Analysis/UniformityAnalysis.cpp
+++ b/llvm/lib/Analysis/UniformityAnalysis.cpp
@@ -145,11 +145,11 @@ template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() {
 
 template <>
 void llvm::GenericUniformityAnalysisImpl<SSAContext>::registerCallbacks() {
-  IRUniformValueCallbackManager *Manager =
-      new IRUniformValueCallbackManager(UniformValues);
+  std::unique_ptr<IRUniformValueCallbackManager> Manager =
+      std::make_unique<IRUniformValueCallbackManager>(UniformValues);
   for (const Value *V : UniformValues)
     Manager->registerValue(V);
-  UniformValueCallbacks.reset(Manager);
+  UniformValueCallbacks = std::move(Manager);
 }
 
 template <>

>From b8f3fbc23bf30228afa62245ac496541f15b95a4 Mon Sep 17 00:00:00 2001
From: padivedi <padivedi at amd.com>
Date: Mon, 13 Apr 2026 20:00:12 +0530
Subject: [PATCH 3/4] replace callbackVH with assertingVH

---
 llvm/include/llvm/ADT/GenericSSAContext.h     |  5 +++
 llvm/include/llvm/ADT/GenericUniformityImpl.h | 24 +++++-----
 llvm/include/llvm/ADT/GenericUniformityInfo.h |  5 ++-
 llvm/include/llvm/CodeGen/MachineSSAContext.h |  1 +
 llvm/include/llvm/IR/SSAContext.h             |  2 +
 llvm/lib/Analysis/UniformityAnalysis.cpp      | 45 -------------------
 .../lib/CodeGen/MachineUniformityAnalysis.cpp |  4 --
 .../Target/AMDGPU/UniformityAnalysisTest.cpp  |  9 ++--
 8 files changed, 27 insertions(+), 68 deletions(-)

diff --git a/llvm/include/llvm/ADT/GenericSSAContext.h b/llvm/include/llvm/ADT/GenericSSAContext.h
index 36d0e2e8f70cd..db1a44f79633d 100644
--- a/llvm/include/llvm/ADT/GenericSSAContext.h
+++ b/llvm/include/llvm/ADT/GenericSSAContext.h
@@ -63,6 +63,11 @@ template <typename _FunctionT> class GenericSSAContext {
   // instruction.
   using UseT = typename SSATraits::UseT;
 
+  // The key type for the DenseSet tracking uniform values. For IR this is
+  // AssertingVH<const Value> to catch forgotten eraseValue() calls in debug
+  // builds; for MIR it is Register.
+  using UniformSetKeyT = typename SSATraits::UniformSetKeyT;
+
   // A BlockT is a sequence of InstructionT, and forms a node of the CFG. It
   // has global methods predecessors() and successors() that return
   // the list of incoming CFG edges and outgoing CFG edges
diff --git a/llvm/include/llvm/ADT/GenericUniformityImpl.h b/llvm/include/llvm/ADT/GenericUniformityImpl.h
index d439571b7bc4c..1877c7a4b33c8 100644
--- a/llvm/include/llvm/ADT/GenericUniformityImpl.h
+++ b/llvm/include/llvm/ADT/GenericUniformityImpl.h
@@ -57,12 +57,6 @@
 
 namespace llvm {
 
-/// Interface for keeping UniformValues in sync when IR values are deleted.
-/// IR specialization installs a concrete CallbackVH-based implementation.
-struct UniformValueCallbackManager {
-  virtual ~UniformValueCallbackManager() = default;
-};
-
 // Forward decl from llvm/CodeGen/MachineInstr.h
 class MachineInstr;
 
@@ -382,9 +376,9 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
   /// Divergence is seeded by calls to \p markDivergent.
   void compute();
 
-  /// \brief Register callbacks (e.g., CallbackVH for IR) to keep
-  /// UniformValues in sync when values are deleted after analysis.
-  void registerCallbacks();
+  /// \brief Remove \p V from UniformValues. Must be called before deleting
+  /// a value that was present during analysis to prevent stale pointers.
+  void eraseValue(ConstValueRefT V) { UniformValues.erase(V); }
 
   /// \brief Whether \p Val will always return a uniform value regardless of its
   /// operands
@@ -455,11 +449,7 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
   // Values known to be uniform. Populated in initialize() with all values,
   // then values are removed as divergence is propagated. After analysis,
   // values not in this set are conservatively treated as divergent.
-  DenseSet<ConstValueRefT> UniformValues;
-
-  // For IR: callbacks to remove from UniformValues on value deletion,
-  // avoiding stale pointers when addresses are reused.
-  std::unique_ptr<UniformValueCallbackManager> UniformValueCallbacks;
+  DenseSet<typename ContextT::UniformSetKeyT> UniformValues;
 
   // Internal worklist for divergence propagation.
   std::vector<const InstructionT *> Worklist;
@@ -1325,6 +1315,12 @@ bool GenericUniformityInfo<ContextT>::hasDivergentTerminator(const BlockT &B) {
   return DA && DA->hasDivergentTerminator(B);
 }
 
+template <typename ContextT>
+void GenericUniformityInfo<ContextT>::eraseValue(ConstValueRefT V) {
+  if (DA)
+    DA->eraseValue(V);
+}
+
 /// \brief T helper function for printing.
 template <typename ContextT>
 void GenericUniformityInfo<ContextT>::print(raw_ostream &out) const {
diff --git a/llvm/include/llvm/ADT/GenericUniformityInfo.h b/llvm/include/llvm/ADT/GenericUniformityInfo.h
index 7dff3d84d92cf..63782651e7b9d 100644
--- a/llvm/include/llvm/ADT/GenericUniformityInfo.h
+++ b/llvm/include/llvm/ADT/GenericUniformityInfo.h
@@ -52,7 +52,6 @@ template <typename ContextT> class GenericUniformityInfo {
   void compute() {
     DA->initialize();
     DA->compute();
-    DA->registerCallbacks();
   }
 
   /// The GPU kernel this analysis result is for
@@ -77,6 +76,10 @@ template <typename ContextT> class GenericUniformityInfo {
 
   bool hasDivergentTerminator(const BlockT &B);
 
+  /// \brief Remove \p V from the analysis. Must be called before deleting
+  /// a value that was present during analysis to prevent stale pointers.
+  void eraseValue(ConstValueRefT V);
+
   void print(raw_ostream &Out) const;
 
   iterator_range<TemporalDivergenceTuple *> getTemporalDivergenceList() const;
diff --git a/llvm/include/llvm/CodeGen/MachineSSAContext.h b/llvm/include/llvm/CodeGen/MachineSSAContext.h
index 0e4304f69380f..697b94f83a1c7 100644
--- a/llvm/include/llvm/CodeGen/MachineSSAContext.h
+++ b/llvm/include/llvm/CodeGen/MachineSSAContext.h
@@ -33,6 +33,7 @@ template <> struct GenericSSATraits<MachineFunction> {
   using ValueRefT = Register;
   using ConstValueRefT = Register;
   using UseT = MachineOperand;
+  using UniformSetKeyT = Register;
 };
 
 using MachineSSAContext = GenericSSAContext<MachineFunction>;
diff --git a/llvm/include/llvm/IR/SSAContext.h b/llvm/include/llvm/IR/SSAContext.h
index d0da5e222a8e6..15755c8b287c4 100644
--- a/llvm/include/llvm/IR/SSAContext.h
+++ b/llvm/include/llvm/IR/SSAContext.h
@@ -17,6 +17,7 @@
 
 #include "llvm/ADT/GenericSSAContext.h"
 #include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/ValueHandle.h"
 
 namespace llvm {
 class BasicBlock;
@@ -35,6 +36,7 @@ template <> struct GenericSSATraits<Function> {
   using ValueRefT = Value *;
   using ConstValueRefT = const Value *;
   using UseT = Use;
+  using UniformSetKeyT = AssertingVH<const Value>;
 };
 
 using SSAContext = GenericSSAContext<Function>;
diff --git a/llvm/lib/Analysis/UniformityAnalysis.cpp b/llvm/lib/Analysis/UniformityAnalysis.cpp
index 1ccad01192737..41519bcd09baa 100644
--- a/llvm/lib/Analysis/UniformityAnalysis.cpp
+++ b/llvm/lib/Analysis/UniformityAnalysis.cpp
@@ -14,46 +14,10 @@
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instructions.h"
-#include "llvm/IR/ValueHandle.h"
 #include "llvm/InitializePasses.h"
 
 using namespace llvm;
 
-namespace {
-
-/// CallbackVH that removes the value from UniformValues on deletion.
-/// Prevents stale pointers when a deleted value's address is reused.
-class UniformValueHandle : public CallbackVH {
-  DenseSet<const Value *> &UniformSet;
-
-public:
-  UniformValueHandle(Value *V, DenseSet<const Value *> &S)
-      : CallbackVH(V), UniformSet(S) {}
-  virtual ~UniformValueHandle() = default;
-
-  void deleted() override {
-    UniformSet.erase(getValPtr());
-    CallbackVH::deleted();
-  }
-};
-
-/// IR implementation: registers CallbackVH for each uniform value.
-class IRUniformValueCallbackManager : public UniformValueCallbackManager {
-  DenseSet<const Value *> &UniformSet;
-  std::vector<std::unique_ptr<UniformValueHandle>> Handles;
-
-public:
-  explicit IRUniformValueCallbackManager(DenseSet<const Value *> &S)
-      : UniformSet(S) {}
-
-  void registerValue(const Value *V) {
-    Handles.push_back(std::make_unique<UniformValueHandle>(
-        const_cast<Value *>(V), UniformSet));
-  }
-};
-
-} // namespace
-
 template <>
 bool llvm::GenericUniformityAnalysisImpl<SSAContext>::hasDivergentDefs(
     const Instruction &I) const {
@@ -143,15 +107,6 @@ template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() {
     pushUsers(Arg);
 }
 
-template <>
-void llvm::GenericUniformityAnalysisImpl<SSAContext>::registerCallbacks() {
-  std::unique_ptr<IRUniformValueCallbackManager> Manager =
-      std::make_unique<IRUniformValueCallbackManager>(UniformValues);
-  for (const Value *V : UniformValues)
-    Manager->registerValue(V);
-  UniformValueCallbacks = std::move(Manager);
-}
-
 template <>
 bool llvm::GenericUniformityAnalysisImpl<SSAContext>::usesValueFromCycle(
     const Instruction &I, const Cycle &DefCycle) const {
diff --git a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
index 5467e88c41745..aa85b95a96d09 100644
--- a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
+++ b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
@@ -84,10 +84,6 @@ void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
   }
 }
 
-template <>
-void llvm::GenericUniformityAnalysisImpl<
-    MachineSSAContext>::registerCallbacks() {}
-
 template <>
 void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
     Register Reg) {
diff --git a/llvm/unittests/Target/AMDGPU/UniformityAnalysisTest.cpp b/llvm/unittests/Target/AMDGPU/UniformityAnalysisTest.cpp
index 7ad54af38f443..ed55062769525 100644
--- a/llvm/unittests/Target/AMDGPU/UniformityAnalysisTest.cpp
+++ b/llvm/unittests/Target/AMDGPU/UniformityAnalysisTest.cpp
@@ -94,10 +94,10 @@ TEST(UniformityAnalysis, NewValueIsConservativelyDivergent) {
       << "New instruction created after analysis must be reported divergent";
 }
 
-TEST(UniformityAnalysis, DeletionCallbackMakesNewInstDivergent) {
-  // Delete a uniform instruction. CallbackVH::deleted() removes it from
-  // UniformValues during eraseFromParent(). A newly created instruction is
-  // not in UniformValues and must be conservatively reported as divergent.
+TEST(UniformityAnalysis, EraseValueBeforeDeletion) {
+  // Passes must call eraseValue() before deleting a value that was present
+  // during analysis. After deletion, a newly created instruction is not in
+  // UniformValues and must be conservatively reported as divergent.
   LLVMInitializeAMDGPUTargetInfo();
   LLVMInitializeAMDGPUTarget();
   LLVMInitializeAMDGPUTargetMC();
@@ -128,6 +128,7 @@ TEST(UniformityAnalysis, DeletionCallbackMakesNewInstDivergent) {
   ASSERT_TRUE(isa<BinaryOperator>(AddInst));
   EXPECT_FALSE(UI.isDivergent(AddInst)) << "%add should be uniform";
 
+  UI.eraseValue(AddInst);
   AddInst->eraseFromParent();
 
   IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());

>From 6b9547f6a9e06d01c466c0b473e0a18c47ae24e1 Mon Sep 17 00:00:00 2001
From: padivedi <padivedi at amd.com>
Date: Mon, 13 Apr 2026 20:04:00 +0530
Subject: [PATCH 4/4] update the affcted files which use uniformity and
 eraseFromParent

---
 .../AMDGPU/AMDGPUAnnotateUniformValues.cpp    |  7 +++-
 .../Target/AMDGPU/AMDGPUAtomicOptimizer.cpp   | 14 ++++---
 .../Target/AMDGPU/AMDGPUCodeGenPrepare.cpp    | 25 +++++++-----
 .../AMDGPU/AMDGPULateCodeGenPrepare.cpp       | 10 +++--
 .../AMDGPU/AMDGPURewriteUndefForPHI.cpp       |  8 +++-
 .../AMDGPU/AMDGPUUniformIntrinsicCombine.cpp  | 29 +++++++-------
 .../AMDGPU/AMDGPUUnifyDivergentExitNodes.cpp  | 39 ++++++++++++-------
 .../Target/AMDGPU/SIAnnotateControlFlow.cpp   |  8 +++-
 llvm/lib/Transforms/Scalar/StructurizeCFG.cpp | 21 +++++++---
 9 files changed, 105 insertions(+), 56 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp
index 77b042c8e7076..82be576131fa3 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp
@@ -92,8 +92,11 @@ AMDGPUAnnotateUniformValuesPass::run(Function &F,
   AMDGPUAnnotateUniformValues Impl(UI, MSSA, AA, F);
   Impl.visit(F);
 
-  if (!Impl.changed())
-    return PreservedAnalyses::all();
+  if (!Impl.changed()) {
+    PreservedAnalyses PA = PreservedAnalyses::all();
+    PA.abandon<UniformityInfoAnalysis>();
+    return PA;
+  }
 
   PreservedAnalyses PA = PreservedAnalyses::none();
   // TODO: Should preserve nearly everything
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp
index b4d51522e28af..9f1111459575c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp
@@ -68,7 +68,7 @@ class AMDGPUAtomicOptimizerImpl
 private:
   Function &F;
   SmallVector<ReplacementInfo, 8> ToReplace;
-  const UniformityInfo &UA;
+  UniformityInfo &UA;
   const DataLayout &DL;
   DomTreeUpdater &DTU;
   const GCNSubtarget &ST;
@@ -92,7 +92,7 @@ class AMDGPUAtomicOptimizerImpl
 public:
   AMDGPUAtomicOptimizerImpl() = delete;
 
-  AMDGPUAtomicOptimizerImpl(Function &F, const UniformityInfo &UA,
+  AMDGPUAtomicOptimizerImpl(Function &F, UniformityInfo &UA,
                             DomTreeUpdater &DTU, const GCNSubtarget &ST,
                             ScanOptions ScanImpl)
       : F(F), UA(UA), DL(F.getDataLayout()), DTU(DTU), ST(ST),
@@ -116,7 +116,7 @@ bool AMDGPUAtomicOptimizer::runOnFunction(Function &F) {
     return false;
   }
 
-  const UniformityInfo &UA =
+  UniformityInfo &UA =
       getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
 
   DominatorTreeWrapperPass *DTW =
@@ -133,7 +133,7 @@ bool AMDGPUAtomicOptimizer::runOnFunction(Function &F) {
 
 PreservedAnalyses AMDGPUAtomicOptimizerPass::run(Function &F,
                                                  FunctionAnalysisManager &AM) {
-  const auto &UA = AM.getResult<UniformityInfoAnalysis>(F);
+  UniformityInfo &UA = AM.getResult<UniformityInfoAnalysis>(F);
 
   DomTreeUpdater DTU(&AM.getResult<DominatorTreeAnalysis>(F),
                      DomTreeUpdater::UpdateStrategy::Lazy);
@@ -142,7 +142,9 @@ PreservedAnalyses AMDGPUAtomicOptimizerPass::run(Function &F,
   bool IsChanged = AMDGPUAtomicOptimizerImpl(F, UA, DTU, ST, ScanImpl).run();
 
   if (!IsChanged) {
-    return PreservedAnalyses::all();
+    PreservedAnalyses PA = PreservedAnalyses::all();
+    PA.abandon<UniformityInfoAnalysis>();
+    return PA;
   }
 
   PreservedAnalyses PA;
@@ -972,7 +974,7 @@ void AMDGPUAtomicOptimizerImpl::optimizeAtomic(Instruction &I,
     }
   }
 
-  // And delete the original.
+  UA.eraseValue(&I);
   I.eraseFromParent();
 }
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
index d049df810c476..1962629d22687 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
@@ -101,7 +101,7 @@ class AMDGPUCodeGenPrepareImpl
   const GCNSubtarget &ST;
   const AMDGPUTargetMachine &TM;
   const TargetLibraryInfo *TLI;
-  const UniformityInfo &UA;
+  UniformityInfo &UA;
   const DataLayout &DL;
   SimplifyQuery SQ;
   const bool HasFP32DenormalFlush;
@@ -114,7 +114,7 @@ class AMDGPUCodeGenPrepareImpl
 
   AMDGPUCodeGenPrepareImpl(Function &F, const AMDGPUTargetMachine &TM,
                            const TargetLibraryInfo *TLI, AssumptionCache *AC,
-                           const DominatorTree *DT, const UniformityInfo &UA)
+                           const DominatorTree *DT, UniformityInfo &UA)
       : F(F), ST(TM.getSubtarget<GCNSubtarget>(F)), TM(TM), TLI(TLI), UA(UA),
         DL(F.getDataLayout()), SQ(DL, TLI, DT, AC),
         HasFP32DenormalFlush(SIModeRegisterDefaults(F, ST).FP32Denormals ==
@@ -301,8 +301,9 @@ bool AMDGPUCodeGenPrepareImpl::run() {
   }
 
   while (!DeadVals.empty()) {
-    if (auto *I = dyn_cast_or_null<Instruction>(DeadVals.pop_back_val()))
-      RecursivelyDeleteTriviallyDeadInstructions(I, TLI);
+    if (Instruction *I = dyn_cast_or_null<Instruction>(DeadVals.pop_back_val()))
+      RecursivelyDeleteTriviallyDeadInstructions(
+          I, TLI, nullptr, [&](Value *V) { UA.eraseValue(V); });
   }
 
   return MadeChange;
@@ -1371,7 +1372,7 @@ Value *AMDGPUCodeGenPrepareImpl::shrinkDivRem64(IRBuilder<> &Builder,
 
 void AMDGPUCodeGenPrepareImpl::expandDivRem64(BinaryOperator &I) const {
   Instruction::BinaryOps Opc = I.getOpcode();
-  // Do the general expansion.
+  UA.eraseValue(&I);
   if (Opc == Instruction::UDiv || Opc == Instruction::SDiv) {
     expandDivisionUpTo64Bits(&I);
     return;
@@ -2272,7 +2273,7 @@ bool AMDGPUCodeGenPrepare::runOnFunction(Function &F) {
       &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
   auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
   const DominatorTree *DT = DTWP ? &DTWP->getDomTree() : nullptr;
-  const UniformityInfo &UA =
+  UniformityInfo &UA =
       getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
   return AMDGPUCodeGenPrepareImpl(F, TM, TLI, AC, DT, UA).run();
 }
@@ -2283,10 +2284,13 @@ PreservedAnalyses AMDGPUCodeGenPreparePass::run(Function &F,
   const TargetLibraryInfo *TLI = &FAM.getResult<TargetLibraryAnalysis>(F);
   AssumptionCache *AC = &FAM.getResult<AssumptionAnalysis>(F);
   const DominatorTree *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F);
-  const UniformityInfo &UA = FAM.getResult<UniformityInfoAnalysis>(F);
+  UniformityInfo &UA = FAM.getResult<UniformityInfoAnalysis>(F);
   AMDGPUCodeGenPrepareImpl Impl(F, ATM, TLI, AC, DT, UA);
-  if (!Impl.run())
-    return PreservedAnalyses::all();
+  if (!Impl.run()) {
+    PreservedAnalyses PA = PreservedAnalyses::all();
+    PA.abandon<UniformityInfoAnalysis>();
+    return PA;
+  }
   PreservedAnalyses PA = PreservedAnalyses::none();
   if (!Impl.FlowChanged)
     PA.preserveSet<CFGAnalyses>();
@@ -2312,6 +2316,7 @@ CallInst *AMDGPUCodeGenPrepareImpl::createWorkitemIdX(IRBuilder<> &B) const {
 void AMDGPUCodeGenPrepareImpl::replaceWithWorkitemIdX(Instruction &I) const {
   IRBuilder<> B(&I);
   CallInst *Tid = createWorkitemIdX(B);
+  UA.eraseValue(&I);
   BasicBlock::iterator BI(&I);
   ReplaceInstWithValue(BI, Tid);
 }
@@ -2323,6 +2328,7 @@ void AMDGPUCodeGenPrepareImpl::replaceWithMaskedWorkitemIdX(
   CallInst *Tid = createWorkitemIdX(B);
   Constant *Mask = ConstantInt::get(Tid->getType(), WaveSize - 1);
   Value *AndInst = B.CreateAnd(Tid, Mask);
+  UA.eraseValue(&I);
   BasicBlock::iterator BI(&I);
   ReplaceInstWithValue(BI, AndInst);
 }
@@ -2384,6 +2390,7 @@ bool AMDGPUCodeGenPrepareImpl::visitMbcntHi(IntrinsicInst &I) const {
       // Replace mbcnt.hi(mask, val) with val only when work group size matches
       // wave size (single wave per work group).
       if (*MaybeX == Wave) {
+        UA.eraseValue(&I);
         BasicBlock::iterator BI(&I);
         ReplaceInstWithValue(BI, I.getArgOperand(1));
         return true;
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULateCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPULateCodeGenPrepare.cpp
index 63e265612cbf7..f80493f0c576b 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULateCodeGenPrepare.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULateCodeGenPrepare.cpp
@@ -225,7 +225,8 @@ bool AMDGPULateCodeGenPrepare::run() {
       Changed |= LRO.optimizeLiveType(&I, DeadInsts);
     }
 
-  RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts);
+  RecursivelyDeleteTriviallyDeadInstructionsPermissive(
+      DeadInsts, nullptr, nullptr, [&](Value *V) { UA.eraseValue(V); });
   return Changed;
 }
 
@@ -559,8 +560,11 @@ AMDGPULateCodeGenPreparePass::run(Function &F, FunctionAnalysisManager &FAM) {
 
   bool Changed = AMDGPULateCodeGenPrepare(F, ST, &AC, UI).run();
 
-  if (!Changed)
-    return PreservedAnalyses::all();
+  if (!Changed) {
+    PreservedAnalyses PA = PreservedAnalyses::all();
+    PA.abandon<UniformityInfoAnalysis>();
+    return PA;
+  }
   PreservedAnalyses PA = PreservedAnalyses::none();
   PA.preserveSet<CFGAnalyses>();
   return PA;
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURewriteUndefForPHI.cpp b/llvm/lib/Target/AMDGPU/AMDGPURewriteUndefForPHI.cpp
index 1c135f09080e1..81111e95cf21c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURewriteUndefForPHI.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURewriteUndefForPHI.cpp
@@ -161,8 +161,10 @@ bool rewritePHIs(Function &F, UniformityInfo &UA, DominatorTree *DT) {
     }
   }
 
-  for (auto *PHI : ToBeDeleted)
+  for (PHINode *PHI : ToBeDeleted) {
+    UA.eraseValue(PHI);
     PHI->eraseFromParent();
+  }
 
   return Changed;
 }
@@ -185,7 +187,9 @@ AMDGPURewriteUndefForPHIPass::run(Function &F, FunctionAnalysisManager &AM) {
     return PA;
   }
 
-  return PreservedAnalyses::all();
+  PreservedAnalyses PA = PreservedAnalyses::all();
+  PA.abandon<UniformityInfoAnalysis>();
+  return PA;
 }
 
 FunctionPass *llvm::createAMDGPURewriteUndefForPHILegacyPass() {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUUniformIntrinsicCombine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUUniformIntrinsicCombine.cpp
index 864d877fe9ac0..536fbd1abf27b 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUUniformIntrinsicCombine.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUUniformIntrinsicCombine.cpp
@@ -44,7 +44,7 @@ using namespace llvm::PatternMatch;
 /// Wrapper for querying uniformity info that first checks locally tracked
 /// instructions.
 static bool
-isDivergentUseWithNew(const Use &U, const UniformityInfo &UI,
+isDivergentUseWithNew(const Use &U, UniformityInfo &UI,
                       const ValueMap<const Value *, bool> &Tracker) {
   Value *V = U.get();
   if (auto It = Tracker.find(V); It != Tracker.end())
@@ -53,8 +53,7 @@ isDivergentUseWithNew(const Use &U, const UniformityInfo &UI,
 }
 
 /// Optimizes uniform intrinsics calls if their operand can be proven uniform.
-static bool optimizeUniformIntrinsic(IntrinsicInst &II,
-                                     const UniformityInfo &UI,
+static bool optimizeUniformIntrinsic(IntrinsicInst &II, UniformityInfo &UI,
                                      ValueMap<const Value *, bool> &Tracker) {
   llvm::Intrinsic::ID IID = II.getIntrinsicID();
   /// We deliberately do not simplify readfirstlane with a uniform argument, so
@@ -68,6 +67,7 @@ static bool optimizeUniformIntrinsic(IntrinsicInst &II,
       return false;
     LLVM_DEBUG(dbgs() << "Replacing " << II << " with " << *Src << '\n');
     II.replaceAllUsesWith(Src);
+    UI.eraseValue(&II);
     II.eraseFromParent();
     return true;
   }
@@ -102,9 +102,10 @@ static bool optimizeUniformIntrinsic(IntrinsicInst &II,
         }
       }
     }
-    // Erase the intrinsic if it has no remaining uses.
-    if (II.use_empty())
+    if (II.use_empty()) {
+      UI.eraseValue(&II);
       II.eraseFromParent();
+    }
     return Changed;
   }
   case Intrinsic::amdgcn_wave_shuffle: {
@@ -114,6 +115,7 @@ static bool optimizeUniformIntrinsic(IntrinsicInst &II,
     // Like with readlane, if Value is uniform then just propagate it
     if (!isDivergentUseWithNew(Val, UI, Tracker)) {
       II.replaceAllUsesWith(Val);
+      UI.eraseValue(&II);
       II.eraseFromParent();
       return true;
     }
@@ -136,7 +138,7 @@ static bool optimizeUniformIntrinsic(IntrinsicInst &II,
 }
 
 /// Iterates over intrinsic calls in the Function to optimize.
-static bool runUniformIntrinsicCombine(Function &F, const UniformityInfo &UI) {
+static bool runUniformIntrinsicCombine(Function &F, UniformityInfo &UI) {
   bool IsChanged = false;
   ValueMap<const Value *, bool> Tracker;
 
@@ -152,13 +154,14 @@ static bool runUniformIntrinsicCombine(Function &F, const UniformityInfo &UI) {
 PreservedAnalyses
 AMDGPUUniformIntrinsicCombinePass::run(Function &F,
                                        FunctionAnalysisManager &AM) {
-  const auto &UI = AM.getResult<UniformityInfoAnalysis>(F);
-  if (!runUniformIntrinsicCombine(F, UI))
-    return PreservedAnalyses::all();
+  UniformityInfo &UI = AM.getResult<UniformityInfoAnalysis>(F);
+  if (!runUniformIntrinsicCombine(F, UI)) {
+    PreservedAnalyses PA = PreservedAnalyses::all();
+    PA.abandon<UniformityInfoAnalysis>();
+    return PA;
+  }
 
-  PreservedAnalyses PA;
-  PA.preserve<UniformityInfoAnalysis>();
-  return PA;
+  return PreservedAnalyses::none();
 }
 
 namespace {
@@ -184,7 +187,7 @@ char &llvm::AMDGPUUniformIntrinsicCombineLegacyPassID =
 bool AMDGPUUniformIntrinsicCombineLegacy::runOnFunction(Function &F) {
   if (skipFunction(F))
     return false;
-  const UniformityInfo &UI =
+  UniformityInfo &UI =
       getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
   return runUniformIntrinsicCombine(F, UI);
 }
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUUnifyDivergentExitNodes.cpp b/llvm/lib/Target/AMDGPU/AMDGPUUnifyDivergentExitNodes.cpp
index b772cf0bd87b2..3d5815a77d104 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUUnifyDivergentExitNodes.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUUnifyDivergentExitNodes.cpp
@@ -66,9 +66,9 @@ class AMDGPUUnifyDivergentExitNodesImpl {
   // We can preserve non-critical-edgeness when we unify function exit nodes
   BasicBlock *unifyReturnBlockSet(Function &F, DomTreeUpdater &DTU,
                                   ArrayRef<BasicBlock *> ReturningBlocks,
-                                  StringRef Name);
+                                  UniformityInfo &UA, StringRef Name);
   bool run(Function &F, DominatorTree *DT, const PostDominatorTree &PDT,
-           const UniformityInfo &UA);
+           UniformityInfo &UA);
 };
 
 class AMDGPUUnifyDivergentExitNodes : public FunctionPass {
@@ -135,7 +135,7 @@ static bool isUniformlyReached(const UniformityInfo &UA, BasicBlock &BB) {
 
 BasicBlock *AMDGPUUnifyDivergentExitNodesImpl::unifyReturnBlockSet(
     Function &F, DomTreeUpdater &DTU, ArrayRef<BasicBlock *> ReturningBlocks,
-    StringRef Name) {
+    UniformityInfo &UA, StringRef Name) {
   // Otherwise, we need to insert a new basic block into the function, add a PHI
   // nodes (if the function returns values), and convert all of the return
   // instructions into unconditional branches.
@@ -163,6 +163,7 @@ BasicBlock *AMDGPUUnifyDivergentExitNodesImpl::unifyReturnBlockSet(
       PN->addIncoming(BB->getTerminator()->getOperand(0), BB);
 
     // Remove and delete the return inst.
+    UA.eraseValue(BB->getTerminator());
     BB->getTerminator()->eraseFromParent();
     UncondBrInst::Create(NewRetBlock, BB);
     Updates.emplace_back(DominatorTree::Insert, BB, NewRetBlock);
@@ -172,8 +173,14 @@ BasicBlock *AMDGPUUnifyDivergentExitNodesImpl::unifyReturnBlockSet(
     DTU.applyUpdates(Updates);
   Updates.clear();
 
+  // simplifyCFG may delete instructions from blocks beyond the ones being
+  // simplified, so pre-erase all values from the uniformity set. The analysis
+  // is stale after this pass anyway.
+  for (BasicBlock &BB : F)
+    for (Instruction &I : BB)
+      UA.eraseValue(&I);
+
   for (BasicBlock *BB : ReturningBlocks) {
-    // Cleanup possible branch to unconditional branch to the return.
     simplifyCFG(BB, *TTI, RequireAndPreserveDomTree ? &DTU : nullptr,
                 SimplifyCFGOptions().bonusInstThreshold(2));
   }
@@ -223,7 +230,7 @@ static void handleNBranch(Function &F, BasicBlock *BB, Instruction *BI,
 
 bool AMDGPUUnifyDivergentExitNodesImpl::run(Function &F, DominatorTree *DT,
                                             const PostDominatorTree &PDT,
-                                            const UniformityInfo &UA) {
+                                            UniformityInfo &UA) {
   if (PDT.root_size() == 0 ||
       (PDT.root_size() == 1 && !isa<UncondBrInst, CondBrInst, CallBrInst>(
                                    PDT.getRoot()->getTerminator())))
@@ -265,7 +272,8 @@ bool AMDGPUUnifyDivergentExitNodesImpl::run(Function &F, DominatorTree *DT,
         DummyReturnBB = createDummyReturnBlock(F, ReturningBlocks);
 
       BasicBlock *LoopHeaderBB = BI->getSuccessor();
-      BI->eraseFromParent(); // Delete the unconditional branch.
+      UA.eraseValue(BI);
+      BI->eraseFromParent();
       // Add a new conditional branch with a dummy edge to the return block.
       CondBrInst::Create(ConstantInt::getTrue(F.getContext()), LoopHeaderBB,
                          DummyReturnBB, BB);
@@ -294,7 +302,7 @@ bool AMDGPUUnifyDivergentExitNodesImpl::run(Function &F, DominatorTree *DT,
 
       Updates.reserve(Updates.size() + UnreachableBlocks.size());
       for (BasicBlock *BB : UnreachableBlocks) {
-        // Remove and delete the unreachable inst.
+        UA.eraseValue(BB->getTerminator());
         BB->getTerminator()->eraseFromParent();
         UncondBrInst::Create(UnreachableBlock, BB);
         Updates.emplace_back(DominatorTree::Insert, BB, UnreachableBlock);
@@ -308,7 +316,7 @@ bool AMDGPUUnifyDivergentExitNodesImpl::run(Function &F, DominatorTree *DT,
 
       Type *RetTy = F.getReturnType();
       Value *RetVal = RetTy->isVoidTy() ? nullptr : PoisonValue::get(RetTy);
-      // Remove and delete the unreachable inst.
+      UA.eraseValue(UnreachableBlock->getTerminator());
       UnreachableBlock->getTerminator()->eraseFromParent();
 
       Function *UnreachableIntrin = Intrinsic::getOrInsertDeclaration(
@@ -340,7 +348,7 @@ bool AMDGPUUnifyDivergentExitNodesImpl::run(Function &F, DominatorTree *DT,
   if (ReturningBlocks.size() == 1)
     return Changed; // Already has a single return block
 
-  unifyReturnBlockSet(F, DTU, ReturningBlocks, "UnifiedReturnBlock");
+  unifyReturnBlockSet(F, DTU, ReturningBlocks, UA, "UnifiedReturnBlock");
   return true;
 }
 
@@ -350,7 +358,8 @@ bool AMDGPUUnifyDivergentExitNodes::runOnFunction(Function &F) {
     DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
   const auto &PDT =
       getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
-  const auto &UA = getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
+  UniformityInfo &UA =
+      getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
   const auto *TranformInfo =
       &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
   return AMDGPUUnifyDivergentExitNodesImpl(TranformInfo).run(F, DT, PDT, UA);
@@ -364,9 +373,11 @@ AMDGPUUnifyDivergentExitNodesPass::run(Function &F,
     DT = &AM.getResult<DominatorTreeAnalysis>(F);
 
   const auto &PDT = AM.getResult<PostDominatorTreeAnalysis>(F);
-  const auto &UA = AM.getResult<UniformityInfoAnalysis>(F);
+  UniformityInfo &UA = AM.getResult<UniformityInfoAnalysis>(F);
   const auto *TransformInfo = &AM.getResult<TargetIRAnalysis>(F);
-  return AMDGPUUnifyDivergentExitNodesImpl(TransformInfo).run(F, DT, PDT, UA)
-             ? PreservedAnalyses::none()
-             : PreservedAnalyses::all();
+  if (AMDGPUUnifyDivergentExitNodesImpl(TransformInfo).run(F, DT, PDT, UA))
+    return PreservedAnalyses::none();
+  PreservedAnalyses PA = PreservedAnalyses::all();
+  PA.abandon<UniformityInfoAnalysis>();
+  return PA;
 }
diff --git a/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp b/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp
index 54ec4a51a4ab3..8233f9095fe07 100644
--- a/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp
+++ b/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp
@@ -176,6 +176,7 @@ bool SIAnnotateControlFlow::hasKill(const BasicBlock *BB) {
 
 // Erase "Phi" if it is not used any more. Return true if any change was made.
 bool SIAnnotateControlFlow::eraseIfUnused(PHINode *Phi) {
+  UA->eraseValue(Phi);
   bool Changed = RecursivelyDeleteDeadPHINode(Phi);
   if (Changed)
     LLVM_DEBUG(dbgs() << "Erased unused condition phi\n");
@@ -398,8 +399,11 @@ PreservedAnalyses SIAnnotateControlFlowPass::run(Function &F,
   SIAnnotateControlFlow Impl(F, ST, DT, LI, UI);
 
   bool Changed = Impl.run();
-  if (!Changed)
-    return PreservedAnalyses::all();
+  if (!Changed) {
+    PreservedAnalyses PA = PreservedAnalyses::all();
+    PA.abandon<UniformityInfoAnalysis>();
+    return PA;
+  }
 
   // TODO: Is LoopInfo preserved?
   PreservedAnalyses PA = PreservedAnalyses::none();
diff --git a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
index 04ece92b74375..9957cce3a1deb 100644
--- a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
+++ b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
@@ -724,8 +724,11 @@ void StructurizeCFG::simplifyConditions() {
       }
     }
   }
-  for (auto *I : InstToErase)
+  for (auto *I : InstToErase) {
+    if (UA)
+      UA->eraseValue(I);
     I->eraseFromParent();
+  }
 }
 
 /// Remove all PHI values coming from "From" into "To" and remember
@@ -1011,9 +1014,11 @@ void StructurizeCFG::simplifyAffectedPhis() {
     // to achieve better register pressure.
     Q.CanUseUndef = false;
     for (WeakVH VH : AffectedPhis) {
-      if (auto Phi = dyn_cast_or_null<PHINode>(VH)) {
-        if (auto NewValue = simplifyInstruction(Phi, Q)) {
+      if (PHINode *Phi = dyn_cast_or_null<PHINode>(VH)) {
+        if (Value *NewValue = simplifyInstruction(Phi, Q)) {
           Phi->replaceAllUsesWith(NewValue);
+          if (UA)
+            UA->eraseValue(Phi);
           Phi->eraseFromParent();
           Changed = true;
         }
@@ -1032,6 +1037,8 @@ DebugLoc StructurizeCFG::killTerminator(BasicBlock *BB) {
     delPhiValues(BB, Succ);
 
   DebugLoc DL = Term->getDebugLoc();
+  if (UA)
+    UA->eraseValue(Term);
   Term->eraseFromParent();
   return DL;
 }
@@ -1490,8 +1497,12 @@ PreservedAnalyses StructurizeCFGPass::run(Function &F,
 
     Changed |= SCFG.run(R, DT, TTI);
   }
-  if (!Changed)
-    return PreservedAnalyses::all();
+  if (!Changed) {
+    PreservedAnalyses PA = PreservedAnalyses::all();
+    if (SkipUniformRegions)
+      PA.abandon<UniformityInfoAnalysis>();
+    return PA;
+  }
   PreservedAnalyses PA;
   PA.preserve<DominatorTreeAnalysis>();
   return PA;



More information about the llvm-commits mailing list