OSDN Git Service

Subzero: Control whether deleted instructions are retained.
authorJim Stichnoth <stichnot@chromium.org>
Mon, 14 Mar 2016 15:37:52 +0000 (08:37 -0700)
committerJim Stichnoth <stichnot@chromium.org>
Mon, 14 Mar 2016 15:37:52 +0000 (08:37 -0700)
Normally, deleted instructions are preserved in the Cfg, and printed as part of dump output.  This helps debugging by partially explaining the provenance of new instructions that originated from the deleted instructions.

However, these instructions slow down iteration over the instruction list, and checking their deleted status may pollute the cache.

As such, in a non-DUMP enabled build, we repurpose the renumberInstructions() pass to also unlink deleted instructions as needed.

A flag is provided to override this behavior, in case we have to debug a situation where a bug only manifests in a DUMP build and not a non-DUMP build, or vice versa.

BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4360
R=eholk@chromium.org, jpp@chromium.org

Review URL: https://codereview.chromium.org/1790063003 .

src/IceCfg.h
src/IceCfgNode.cpp
src/IceClFlags.cpp
src/IceClFlags.h
src/IceDefs.h

index d3aabe9..88178fd 100644 (file)
@@ -185,6 +185,14 @@ public:
   /// predecessor and successor edges, in the form of CfgNode::InEdges[] and
   /// CfgNode::OutEdges[].
   void computeInOutEdges();
+  /// Renumber the non-deleted instructions in the Cfg.  This needs to be done
+  /// in preparation for live range analysis.  The instruction numbers in a
+  /// block must be monotonically increasing.  The range of instruction numbers
+  /// in a block, from lowest to highest, must not overlap with the range of any
+  /// other block.
+  ///
+  /// Also, if the configuration specifies to do so, remove/unlink all deleted
+  /// instructions from the Cfg, to speed up later passes over the instructions.
   void renumberInstructions();
   void placePhiLoads();
   void placePhiStores();
index 0729585..212f742 100644 (file)
@@ -52,16 +52,25 @@ void CfgNode::appendInst(Inst *Instr) {
   }
 }
 
-// Renumbers the non-deleted instructions in the node. This needs to be done in
-// preparation for live range analysis. The instruction numbers in a block must
-// be monotonically increasing. The range of instruction numbers in a block,
-// from lowest to highest, must not overlap with the range of any other block.
+namespace {
+template <typename List> void removeDeletedAndRenumber(List *L, Cfg *Func) {
+  const bool DoDelete =
+      BuildDefs::minimal() || !GlobalContext::getFlags().getKeepDeletedInsts();
+  auto I = L->begin(), E = L->end(), Next = I;
+  for (++Next; I != E; I = Next++) {
+    if (DoDelete && I->isDeleted()) {
+      L->erase(I);
+    } else {
+      I->renumber(Func);
+    }
+  }
+}
+} // end of anonymous namespace
+
 void CfgNode::renumberInstructions() {
   InstNumberT FirstNumber = Func->getNextInstNumber();
-  for (Inst &I : Phis)
-    I.renumber(Func);
-  for (Inst &I : Insts)
-    I.renumber(Func);
+  removeDeletedAndRenumber(&Phis, Func);
+  removeDeletedAndRenumber(&Insts, Func);
   InstCountEstimate = Func->getNextInstNumber() - FirstNumber;
 }
 
index e21413c..b944ec0 100644 (file)
@@ -136,6 +136,14 @@ cl::opt<bool>
     FunctionSections("ffunction-sections",
                      cl::desc("Emit functions into separate sections"));
 
+/// Retain deleted instructions in the Cfg.  Defaults to true in DUMP-enabled
+/// build, and false in a non-DUMP build, but is ignored in a MINIMAL build.
+/// This flag allows overriding the default primarily for debugging.
+cl::opt<bool>
+    KeepDeletedInsts("keep-deleted-insts",
+                     cl::desc("Retain deleted instructions in the Cfg"),
+                     cl::init(Ice::BuildDefs::dump()));
+
 /// Mock bounds checking on loads/stores.
 cl::opt<bool> MockBoundsCheck("mock-bounds-check",
                               cl::desc("Mock bounds checking on loads/stores"));
@@ -475,6 +483,7 @@ void ClFlags::resetClFlags(ClFlags &OutFlags) {
   OutFlags.ForceMemIntrinOpt = false;
   OutFlags.FunctionSections = false;
   OutFlags.GenerateUnitTestMessages = false;
+  OutFlags.KeepDeletedInsts = Ice::BuildDefs::dump();
   OutFlags.MockBoundsCheck = false;
   OutFlags.PhiEdgeSplit = false;
   OutFlags.RandomNopInsertion = false;
@@ -544,6 +553,7 @@ void ClFlags::getParsedClFlags(ClFlags &OutFlags) {
   OutFlags.setFunctionSections(::FunctionSections);
   OutFlags.setNumTranslationThreads(::NumThreads);
   OutFlags.setOptLevel(::OLevel);
+  OutFlags.setKeepDeletedInsts(::KeepDeletedInsts);
   OutFlags.setMockBoundsCheck(::MockBoundsCheck);
   OutFlags.setPhiEdgeSplit(::EnablePhiEdgeSplit);
   OutFlags.setRandomSeed(::RandomSeed);
index d10c8c4..971ad9d 100644 (file)
@@ -164,6 +164,11 @@ public:
     GenerateUnitTestMessages = NewValue;
   }
 
+  /// Get the value of ClFlags::KeepDeletedInsts
+  bool getKeepDeletedInsts() const { return KeepDeletedInsts; }
+  /// Set ClFlags::KeepDeletedInsts to a new value
+  void setKeepDeletedInsts(bool NewValue) { KeepDeletedInsts = NewValue; }
+
   /// Get the value of ClFlags::MockBoundsCheck
   bool getMockBoundsCheck() const { return MockBoundsCheck; }
   /// Set ClFlags::MockBoundsCheck to a new value
@@ -437,6 +442,8 @@ private:
   bool FunctionSections;
   /// Initialized to false; not set by the command line.
   bool GenerateUnitTestMessages;
+  /// see anonymous_namespace{IceClFlags.cpp}::KeepDeletedInsts
+  bool KeepDeletedInsts;
   /// see anonymous_namespace{IceClFlags.cpp}::MockBoundsCheck
   bool MockBoundsCheck;
   /// see anonymous_namespace{IceClFlags.cpp}::EnablePhiEdgeSplit
index d9c0c23..2b19b3f 100644 (file)
@@ -222,7 +222,7 @@ enum VerboseItem {
   IceV_ConstPoolStats = 1 << 23,
   IceV_All = ~IceV_None,
   IceV_Most =
-      IceV_All & ~IceV_LinearScan & ~IceV_GlobalInit & IceV_ConstPoolStats
+      IceV_All & ~IceV_LinearScan & ~IceV_GlobalInit & ~IceV_ConstPoolStats
 };
 using VerboseMask = uint32_t;