Convert the CFG to an on-demand analysis - NFC.
authorDiego Novillo <dnovillo@google.com>
Mon, 27 Nov 2017 19:20:32 +0000 (14:20 -0500)
committerDiego Novillo <dnovillo@google.com>
Tue, 28 Nov 2017 18:25:41 +0000 (13:25 -0500)
This fixes some TODOs by moving the CFG into the IRContext as an
analysis.

source/opt/cfg.h
source/opt/ir_context.cpp
source/opt/ir_context.h
source/opt/pass.h

index 0a2054b74d21198dc8fe79e9258dc0f1a0353448..bfeaca7d4fbe1e6d137ab420014dcc637734bcc6 100644 (file)
@@ -40,9 +40,7 @@ class CFG {
   // |blk_id|.
   ir::BasicBlock* block(uint32_t blk_id) const { return id2block_.at(blk_id); }
 
-  // Return the pseudo entry and exit blocks. TODO(dnovillo): Remove when
-  // LocalSingleStoreElimPass::CalculateImmediateDominators() is moved into this
-  // class.
+  // Return the pseudo entry and exit blocks.
   const ir::BasicBlock* pseudo_entry_block() const {
     return &pseudo_entry_block_;
   }
@@ -91,10 +89,10 @@ class CFG {
       block2structured_succs_;
 
   // Extra block whose successors are all blocks with no predecessors
-  // in function. TODO(dnovillo): Needed?
+  // in function.
   ir::BasicBlock pseudo_entry_block_;
 
-  // Augmented CFG Exit Block. TODO(dnovillo): Needed?
+  // Augmented CFG Exit Block.
   ir::BasicBlock pseudo_exit_block_;
 
   // Map from block's label id to its predecessor blocks ids
index 3afdd6460d526224bbb8b8cc80a7cbd143c3f728..f516d0edb8860a34e53104e6e1fa8ecd3cf1864f 100644 (file)
@@ -31,6 +31,9 @@ void IRContext::BuildInvalidAnalyses(IRContext::Analysis set) {
   if (set & kAnalysisDecorations) {
     BuildDecorationManager();
   }
+  if (set & kAnalysisCFG) {
+    BuildCFG();
+  }
 }
 
 void IRContext::InvalidateAnalysesExceptFor(
@@ -52,6 +55,9 @@ void IRContext::InvalidateAnalyses(IRContext::Analysis analyses_to_invalidate) {
   if (analyses_to_invalidate & kAnalysisCombinators) {
     combinator_ops_.clear();
   }
+  if (analyses_to_invalidate & kAnalysisCFG) {
+    cfg_.reset(nullptr);
+  }
   valid_analyses_ = Analysis(valid_analyses_ & ~analyses_to_invalidate);
 }
 
index 12499be4da8c78b866270358faa4be3b7cccbc14..7e2a20f8d2f843330871b7d12280356de53693f1 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef SPIRV_TOOLS_IR_CONTEXT_H
 #define SPIRV_TOOLS_IR_CONTEXT_H
 
+#include "cfg.h"
 #include "decoration_manager.h"
 #include "def_use_manager.h"
 #include "module.h"
@@ -39,8 +40,7 @@ class IRContext {
   // 2. Make sure it gets invalidated or preserved by IRContext methods that add
   //    or remove IR elements (e.g., KillDef, KillInst, ReplaceAllUsesWith).
   //
-  // 3. Add handling code in BuildInvalidAnalyses and
-  //    InvalidateAnalysesExceptFor.
+  // 3. Add handling code in BuildInvalidAnalyses and InvalidateAnalyses
   enum Analysis {
     kAnalysisNone = 0 << 0,
     kAnalysisBegin = 1 << 0,
@@ -48,7 +48,8 @@ class IRContext {
     kAnalysisInstrToBlockMapping = 1 << 1,
     kAnalysisDecorations = 1 << 2,
     kAnalysisCombinators = 1 << 3,
-    kAnalysisEnd = 1 << 4
+    kAnalysisCFG = 1 << 4,
+    kAnalysisEnd = 1 << 5
   };
 
   friend inline Analysis operator|(Analysis lhs, Analysis rhs);
@@ -284,6 +285,14 @@ class IRContext {
     }
   }
 
+  // Returns a pointer to the CFG for all the functions in |module_|.
+  ir::CFG* cfg() {
+    if (!AreAnalysesValid(kAnalysisCFG)) {
+      BuildCFG();
+    }
+    return cfg_.get();
+  }
+
  private:
   // Builds the def-use manager from scratch, even if it was already valid.
   void BuildDefUseManager() {
@@ -309,6 +318,11 @@ class IRContext {
     valid_analyses_ = valid_analyses_ | kAnalysisDecorations;
   }
 
+  void BuildCFG() {
+    cfg_.reset(new ir::CFG(module()));
+    valid_analyses_ = valid_analyses_ | kAnalysisCFG;
+  }
+
   // Scans a module looking for it capabilities, and initializes combinator_ops_
   // accordingly.
   void InitializeCombinators();
@@ -344,6 +358,9 @@ class IRContext {
   // Opcodes of shader capability core executable instructions
   // without side-effect.
   std::unordered_map<uint32_t, std::unordered_set<uint32_t>> combinator_ops_;
+
+  // The CFG for all the functions in |module_|.
+  std::unique_ptr<ir::CFG> cfg_;
 };
 
 inline ir::IRContext::Analysis operator|(ir::IRContext::Analysis lhs,
index 73305e13598488df3aad532fbc4ca6a49f6cfab0..21c31f54c6433f42d5f8598f010444594f806891 100644 (file)
@@ -23,7 +23,6 @@
 #include <utility>
 
 #include "basic_block.h"
-#include "cfg.h"
 #include "def_use_manager.h"
 #include "ir_context.h"
 #include "module.h"
@@ -89,9 +88,8 @@ class Pass {
   // Returns a pointer to the current context for this pass.
   ir::IRContext* context() const { return context_; }
 
-  // Returns a pointer to the CFG for current module. TODO(dnovillo): This
-  // should belong in IRContext.
-  ir::CFG* cfg() const { return cfg_.get(); }
+  // Returns a pointer to the CFG for current module.
+  ir::CFG* cfg() const { return context()->cfg(); }
 
   // Add to |todo| all ids of functions called in |func|.
   void AddCalls(ir::Function* func, std::queue<uint32_t>* todo);
@@ -136,7 +134,6 @@ class Pass {
   virtual void InitializeProcessing(ir::IRContext* c) {
     context_ = c;
     next_id_ = context_->IdBound();
-    cfg_.reset(new ir::CFG(get_module()));
   }
 
   // Processes the given |module|. Returns Status::Failure if errors occur when
@@ -163,9 +160,6 @@ class Pass {
 
   // The context that this pass belongs to.
   ir::IRContext* context_;
-
-  // The CFG for all the functions in this module.
-  std::unique_ptr<ir::CFG> cfg_;
 };
 
 }  // namespace opt