Remove uses DCEInst and call ADCE
authorSteven Perron <stevenperron@google.com>
Thu, 22 Feb 2018 21:05:37 +0000 (16:05 -0500)
committerSteven Perron <31666470+s-perron@users.noreply.github.com>
Wed, 28 Feb 2018 02:06:08 +0000 (21:06 -0500)
The algorithm used in DCEInst to remove dead code is very slow.  It is
fine if you only want to remove a small number of instructions, but, if
you need to remove a large number of instructions, then the algorithm in
ADCE is much faster.

This PR removes the calls to DCEInst in the load-store removal passes
and adds a pass of ADCE afterwards.

A number of different iterations of the order of optimization, and I
believe this is the best I could find.

The results I have on 3 sets of shaders are:

Legalization:

Set 1: 5.39 -> 5.01
Set 2: 13.98 -> 8.38
Set 3: 98.00 -> 96.26

Performance passes:

Set 1: 6.90 -> 5.23
Set 2: 10.11 -> 6.62
Set 3: 253.69 -> 253.74

Size reduction passes:

Set 1: 7.16 -> 7.25
Set 2: 17.17 -> 16.81
Set 3: 112.06 -> 107.71

Note that the third set's compile time is large because of the large
number of basic blocks, not so much because of the number of
instructions.  That is why we don't see much gain there.

source/opt/local_single_block_elim_pass.cpp
source/opt/local_single_store_elim_pass.cpp
source/opt/local_single_store_elim_pass.h
source/opt/local_ssa_elim_pass.cpp
source/opt/local_ssa_elim_pass.h
source/opt/mem_pass.cpp
source/opt/mem_pass.h
source/opt/optimizer.cpp
test/opt/local_single_block_elim.cpp
test/opt/local_single_store_elim_test.cpp
test/opt/local_ssa_elim_test.cpp

index b872535..318eb35 100644 (file)
@@ -50,7 +50,6 @@ bool LocalSingleBlockLoadStoreElimPass::HasOnlySupportedRefs(uint32_t ptrId) {
 bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim(
     ir::Function* func) {
   // Perform local store/load and load/load elimination on each block
-  std::vector<ir::Instruction*> dead_instructions;
   bool modified = false;
   for (auto bi = func->begin(); bi != func->end(); ++bi) {
     var2store_.clear();
@@ -72,7 +71,6 @@ bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim(
             if (pinned_vars_.find(varId) == pinned_vars_.end()) {
               auto si = var2store_.find(varId);
               if (si != var2store_.end()) {
-                dead_instructions.push_back(si->second);
               }
             }
             var2store_[varId] = &*ii;
@@ -106,7 +104,6 @@ bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim(
             // replace load's result id and delete load
             context()->KillNamesAndDecorates(&*ii);
             context()->ReplaceAllUsesWith(ii->result_id(), replId);
-            dead_instructions.push_back(&*ii);
             modified = true;
           } else {
             if (ptrInst->opcode() == SpvOpVariable)
@@ -125,38 +122,6 @@ bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim(
           break;
       }
     }
-
-    while (!dead_instructions.empty()) {
-      ir::Instruction* inst = dead_instructions.back();
-      dead_instructions.pop_back();
-      DCEInst(inst, [&dead_instructions](ir::Instruction* other_inst) {
-        auto i = std::find(dead_instructions.begin(), dead_instructions.end(),
-                           other_inst);
-        if (i != dead_instructions.end()) {
-          dead_instructions.erase(i);
-        }
-      });
-    }
-
-    // Go back and delete useless stores in block
-    // TODO(greg-lunarg): Consider moving DCE into separate pass
-    std::vector<ir::Instruction*> dead_stores;
-    for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
-      if (ii->opcode() != SpvOpStore) continue;
-      if (IsLiveStore(&*ii)) continue;
-      dead_stores.push_back(&*ii);
-    }
-
-    while (!dead_stores.empty()) {
-      ir::Instruction* inst = dead_stores.back();
-      dead_stores.pop_back();
-      DCEInst(inst, [&dead_stores](ir::Instruction* other_inst) {
-        auto i = std::find(dead_stores.begin(), dead_stores.end(), other_inst);
-        if (i != dead_stores.end()) {
-          dead_stores.erase(i);
-        }
-      });
-    }
   }
   return modified;
 }
index 72f0396..46fd280 100644 (file)
@@ -184,7 +184,6 @@ bool LocalSingleStoreElimPass::SingleStoreProcess(ir::Function* func) {
   bool modified = false;
   for (auto bi = func->begin(); bi != func->end(); ++bi) {
     uint32_t instIdx = 0;
-    std::vector<ir::Instruction*> dead_instructions;
     for (auto ii = bi->begin(); ii != bi->end(); ++ii, ++instIdx) {
       if (ii->opcode() != SpvOpLoad) continue;
       uint32_t varId;
@@ -208,55 +207,6 @@ bool LocalSingleStoreElimPass::SingleStoreProcess(ir::Function* func) {
       // and add load to removal list
       context()->KillNamesAndDecorates(&*ii);
       context()->ReplaceAllUsesWith(ii->result_id(), replId);
-      dead_instructions.push_back(&*ii);
-      modified = true;
-    }
-
-    // Define the function that will update the data structures as instructions
-    // are deleted.
-    auto update_function = [&dead_instructions,
-                            this](ir::Instruction* other_inst) {
-      // Update dead_instructions.
-      auto i = std::find(dead_instructions.begin(), dead_instructions.end(),
-                         other_inst);
-      if (i != dead_instructions.end()) {
-        dead_instructions.erase(i);
-      }
-
-      // Update the variable-to-store map if any of its members is DCE'd.
-      uint32_t id;
-      if (other_inst->opcode() == SpvOpStore) GetPtr(other_inst, &id);
-      if (other_inst->opcode() == SpvOpVariable)
-        id = other_inst->result_id();
-      else
-        return;
-
-      auto store = ssa_var2store_.find(id);
-      if (store != ssa_var2store_.end()) {
-        ssa_var2store_.erase(store);
-      }
-    };
-
-    while (!dead_instructions.empty()) {
-      ir::Instruction* inst = dead_instructions.back();
-      dead_instructions.pop_back();
-      DCEInst(inst, update_function);
-    }
-  }
-  return modified;
-}
-
-bool LocalSingleStoreElimPass::SingleStoreDCE() {
-  bool modified = false;
-  std::unordered_set<ir::Instruction*> already_deleted;
-  for (auto v : ssa_var2store_) {
-    // check that it hasn't already been DCE'd
-    if (already_deleted.find(v.second) != already_deleted.end()) continue;
-    if (non_ssa_vars_.find(v.first) != non_ssa_vars_.end()) continue;
-    if (!IsLiveVar(v.first)) {
-      DCEInst(v.second, [&already_deleted](ir::Instruction* inst) {
-        already_deleted.insert(inst);
-      });
       modified = true;
     }
   }
@@ -268,7 +218,6 @@ bool LocalSingleStoreElimPass::LocalSingleStoreElim(ir::Function* func) {
   SingleStoreAnalyze(func);
   if (ssa_var2store_.empty()) return false;
   modified |= SingleStoreProcess(func);
-  modified |= SingleStoreDCE();
   return modified;
 }
 
index 80175f0..47b8004 100644 (file)
@@ -85,11 +85,6 @@ class LocalSingleStoreElimPass : public MemPass {
   // if any instructions are modified.
   bool SingleStoreProcess(ir::Function* func);
 
-  // Remove all stores to useless SSA variables. Remove useless
-  // access chains and variables as well. Assumes SingleStoreAnalyze
-  // and SingleStoreProcess has been run.
-  bool SingleStoreDCE();
-
   // Do "single-store" optimization of function variables defined only
   // with a single non-access-chain store in |func|. Replace all their
   // non-access-chain loads with the value that is stored and eliminate
index a1f6a17..3b220de 100644 (file)
 namespace spvtools {
 namespace opt {
 
-bool LocalMultiStoreElimPass::EliminateMultiStoreLocal(ir::Function* func) {
-  // Add Phi instructions to the function.
-  if (InsertPhiInstructions(func) == Status::SuccessWithoutChange) return false;
-
-  // Remove all target variable stores.
-  bool modified = false;
-  for (auto bi = func->begin(); bi != func->end(); ++bi) {
-    std::vector<ir::Instruction*> dead_instructions;
-    for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
-      if (ii->opcode() != SpvOpStore) continue;
-      uint32_t varId;
-      (void)GetPtr(&*ii, &varId);
-      if (!IsTargetVar(varId)) continue;
-      assert(!HasLoads(varId));
-      dead_instructions.push_back(&*ii);
-      modified = true;
-    }
-
-    while (!dead_instructions.empty()) {
-      ir::Instruction* inst = dead_instructions.back();
-      dead_instructions.pop_back();
-      DCEInst(inst, [&dead_instructions](ir::Instruction* other_inst) {
-        auto i = std::find(dead_instructions.begin(), dead_instructions.end(),
-                           other_inst);
-        if (i != dead_instructions.end()) {
-          dead_instructions.erase(i);
-        }
-      });
-    }
-  }
-
-  return modified;
-}
-
 void LocalMultiStoreElimPass::Initialize(ir::IRContext* c) {
   InitializeProcessing(c);
 
@@ -92,7 +58,7 @@ Pass::Status LocalMultiStoreElimPass::ProcessImpl() {
   if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
   // Process functions
   ProcessFunction pfn = [this](ir::Function* fp) {
-    return EliminateMultiStoreLocal(fp);
+    return InsertPhiInstructions(fp);
   };
   bool modified = ProcessEntryPointCallTree(pfn, get_module());
   return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
index 326f938..c3f70f6 100644 (file)
@@ -56,13 +56,6 @@ class LocalMultiStoreElimPass : public MemPass {
   // Return true if all extensions in this module are allowed by this pass.
   bool AllExtensionsSupported() const;
 
-  // Remove remaining loads and stores of function scope variables only
-  // referenced with non-access-chain loads and stores from function |func|.
-  // Insert Phi functions where necessary. Running LocalAccessChainRemoval,
-  // SingleBlockLocalElim and SingleStoreLocalElim beforehand will improve
-  // the runtime and effectiveness of this function.
-  bool EliminateMultiStoreLocal(ir::Function* func);
-
   void Initialize(ir::IRContext* c);
   Pass::Status ProcessImpl();
 
index 86b84a0..2102aa4 100644 (file)
@@ -326,8 +326,9 @@ uint32_t MemPass::GetCurrentValue(uint32_t var_id, uint32_t block_label) {
   return 0;
 }
 
-void MemPass::SSABlockInitLoopHeader(
+bool MemPass::SSABlockInitLoopHeader(
     std::list<ir::BasicBlock*>::iterator block_itr) {
+  bool modified = false;
   const uint32_t label = (*block_itr)->id();
 
   // Determine the back-edge label.
@@ -412,6 +413,7 @@ void MemPass::SSABlockInitLoopHeader(
     // use the variable id. We will patch this after visiting back
     // edge predecessor. For predecessors that do not define a value,
     // use undef.
+    modified = true;
     std::vector<ir::Operand> phi_in_operands;
     uint32_t typeId = GetPointeeTypeId(get_def_use_mgr()->GetDef(varId));
     for (uint32_t predLabel : cfg()->preds(label)) {
@@ -443,9 +445,11 @@ void MemPass::SSABlockInitLoopHeader(
     ++insertItr;
     block_defs_map_[label].insert({varId, phiId});
   }
+  return modified;
 }
 
-void MemPass::SSABlockInitMultiPred(ir::BasicBlock* block_ptr) {
+bool MemPass::SSABlockInitMultiPred(ir::BasicBlock* block_ptr) {
+  bool modified = false;
   const uint32_t label = block_ptr->id();
   // Collect all live variables and a default value for each across all
   // predecesors. Must be ordered map because phis are generated based on
@@ -483,6 +487,8 @@ void MemPass::SSABlockInitMultiPred(ir::BasicBlock* block_ptr) {
       continue;
     }
 
+    modified = true;
+
     // Val differs across predecessors. Add phi op to block and add its result
     // id to the map.
     std::vector<ir::Operand> phi_in_operands;
@@ -506,15 +512,16 @@ void MemPass::SSABlockInitMultiPred(ir::BasicBlock* block_ptr) {
     ++insertItr;
     block_defs_map_[label].insert({varId, phiId});
   }
+  return modified;
 }
 
-void MemPass::SSABlockInit(std::list<ir::BasicBlock*>::iterator block_itr) {
+bool MemPass::SSABlockInit(std::list<ir::BasicBlock*>::iterator block_itr) {
   const size_t numPreds = cfg()->preds((*block_itr)->id()).size();
-  if (numPreds == 0) return;
+  if (numPreds == 0) return false;
   if ((*block_itr)->IsLoopHeader())
-    SSABlockInitLoopHeader(block_itr);
+    return SSABlockInitLoopHeader(block_itr);
   else
-    SSABlockInitMultiPred(*block_itr);
+    return SSABlockInitMultiPred(*block_itr);
 }
 
 bool MemPass::IsTargetVar(uint32_t varId) {
@@ -576,13 +583,15 @@ void MemPass::PatchPhis(uint32_t header_id, uint32_t back_id) {
   }
 }
 
-Pass::Status MemPass::InsertPhiInstructions(ir::Function* func) {
+bool MemPass::InsertPhiInstructions(ir::Function* func) {
   // TODO(dnovillo) the current Phi placement mechanism assumes structured
   // control-flow. This should be generalized
   // (https://github.com/KhronosGroup/SPIRV-Tools/issues/893).
   assert(context()->get_feature_mgr()->HasCapability(SpvCapabilityShader) &&
          "This only works on structured control flow");
 
+  bool modified = false;
+
   // Initialize the data structures used to insert Phi instructions.
   InitSSARewrite(func);
 
@@ -599,7 +608,10 @@ Pass::Status MemPass::InsertPhiInstructions(ir::Function* func) {
     }
 
     // Process all stores and loads of targeted variables.
-    SSABlockInit(bi);
+    if (SSABlockInit(bi)) {
+      modified = true;
+    }
+
     ir::BasicBlock* bp = *bi;
     const uint32_t label = bp->id();
     ir::Instruction* inst = &*bp->begin();
@@ -627,6 +639,7 @@ Pass::Status MemPass::InsertPhiInstructions(ir::Function* func) {
           uint32_t varId;
           (void)GetPtr(inst, &varId);
           if (!IsTargetVar(varId)) break;
+          modified = true;
           uint32_t replId = GetCurrentValue(varId, label);
           // If the variable is not defined, use undef.
           if (replId == 0) {
@@ -660,7 +673,7 @@ Pass::Status MemPass::InsertPhiInstructions(ir::Function* func) {
     if (header != 0) PatchPhis(header, label);
   }
 
-  return Status::SuccessWithChange;
+  return modified;
 }
 
 // Remove all |phi| operands coming from unreachable blocks (i.e., blocks not in
index 5b90508..a52ac18 100644 (file)
@@ -122,8 +122,8 @@ class MemPass : public Pass {
 
   // Insert Phi instructions in the CFG of |func|.  This removes extra
   // load/store operations to local storage while preserving the SSA form of the
-  // code.
-  Pass::Status InsertPhiInstructions(ir::Function* func);
+  // code.  Returns true if the code was modified.
+  bool InsertPhiInstructions(ir::Function* func);
 
   // Cache of verified target vars
   std::unordered_set<uint32_t> seen_target_vars_;
@@ -158,7 +158,8 @@ class MemPass : public Pass {
   // Assumes all predecessors have been visited by EliminateLocalMultiStore
   // except the back edge. Use a dummy value in the phi for the back edge
   // until the back edge block is visited and patch the phi value then.
-  void SSABlockInitLoopHeader(std::list<ir::BasicBlock*>::iterator block_itr);
+  // Returns true if the code was modified.
+  bool SSABlockInitLoopHeader(std::list<ir::BasicBlock*>::iterator block_itr);
 
   // Initialize block_defs_map_ entry for multiple predecessor block
   // |block_ptr| by merging block_defs_map_ entries for all predecessors.
@@ -166,13 +167,15 @@ class MemPass : public Pass {
   // a phi function in the block and use that value id for the variable in
   // the new map. Assumes all predecessors have been visited by
   // EliminateLocalMultiStore.
-  void SSABlockInitMultiPred(ir::BasicBlock* block_ptr);
+  // Returns true if the code was modified.
+  bool SSABlockInitMultiPred(ir::BasicBlock* block_ptr);
 
   // Initialize the label2ssa_map entry for a block pointed to by |block_itr|.
   // Insert phi instructions into block when necessary. All predecessor
   // blocks must have been visited by EliminateLocalMultiStore except for
   // backedges.
-  void SSABlockInit(std::list<ir::BasicBlock*>::iterator block_itr);
+  // Returns true if the code was modified.
+  bool SSABlockInit(std::list<ir::BasicBlock*>::iterator block_itr);
 
   // Return true if variable is loaded in block with |label| or in any
   // succeeding block in structured order.
index c52e643..b897a77 100644 (file)
@@ -98,13 +98,16 @@ Optimizer& Optimizer::RegisterLegalizationPasses() {
           // Propagate the value stored to the loads in very simple cases.
           .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
           .RegisterPass(CreateLocalSingleStoreElimPass())
+          .RegisterPass(CreateAggressiveDCEPass())
           // Split up aggragates so they are easier to deal with.
           .RegisterPass(CreateScalarReplacementPass())
           // Remove loads and stores so everything is in intermediate values.
           // Takes care of copy propagation of non-members.
           .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
           .RegisterPass(CreateLocalSingleStoreElimPass())
+          .RegisterPass(CreateAggressiveDCEPass())
           .RegisterPass(CreateLocalMultiStoreElimPass())
+          .RegisterPass(CreateAggressiveDCEPass())
           // Propagate constants to get as many constant conditions on branches
           // as possible.
           .RegisterPass(CreateCCPPass())
@@ -128,11 +131,14 @@ Optimizer& Optimizer::RegisterPerformancePasses() {
       .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
       .RegisterPass(CreateLocalSingleStoreElimPass())
+      .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreateScalarReplacementPass())
       .RegisterPass(CreateLocalAccessChainConvertPass())
       .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
       .RegisterPass(CreateLocalSingleStoreElimPass())
+      .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreateLocalMultiStoreElimPass())
+      .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreateCCPPass())
       .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreateRedundancyEliminationPass())
@@ -160,9 +166,11 @@ Optimizer& Optimizer::RegisterSizePasses() {
       .RegisterPass(CreateLocalAccessChainConvertPass())
       .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
       .RegisterPass(CreateLocalSingleStoreElimPass())
+      .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreateInsertExtractElimPass())
       .RegisterPass(CreateDeadInsertElimPass())
       .RegisterPass(CreateLocalMultiStoreElimPass())
+      .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreateCCPPass())
       .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreateDeadBranchElimPass())
index 16e2459..8701035 100644 (file)
@@ -55,27 +55,6 @@ OpName %gl_FragColor "gl_FragColor"
 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
 )";
 
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %BaseColor "BaseColor"
-OpName %gl_FragColor "gl_FragColor"
-%void = OpTypeVoid
-%7 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
   const std::string before =
       R"(%main = OpFunction %void None %7
 %13 = OpLabel
@@ -91,14 +70,17 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %7
 %13 = OpLabel
+%v = OpVariable %_ptr_Function_v4float Function
 %14 = OpLoad %v4float %BaseColor
+OpStore %v %14
+%15 = OpLoad %v4float %v
 OpStore %gl_FragColor %14
 OpReturn
 OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalSingleBlockLoadStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs_before + before, predefs_before + after, true, true);
 }
 
 TEST_F(LocalSingleBlockLoadStoreElimTest, SimpleLoadLoadElim) {
@@ -192,6 +174,7 @@ OpBranch %29
 %31 = OpLoad %v4float %v
 %32 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_0
 OpStore %32 %31
+%33 = OpLoad %v4float %v
 %34 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_1
 OpStore %34 %31
 OpReturn
@@ -220,7 +203,7 @@ TEST_F(LocalSingleBlockLoadStoreElimTest,
   //     gl_FragColor = v/f;
   // }
 
-  const std::string predefs_before =
+  const std::string predefs =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -249,34 +232,6 @@ OpDecorate %Idx Flat
 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
 )";
 
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %Idx %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %Idx "Idx"
-OpName %gl_FragColor "gl_FragColor"
-OpDecorate %Idx Flat
-%void = OpTypeVoid
-%9 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Function_float = OpTypePointer Function %float
-%int = OpTypeInt 32 1
-%_ptr_Input_int = OpTypePointer Input %int
-%Idx = OpVariable %_ptr_Input_int Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
   const std::string before =
       R"(%main = OpFunction %void None %9
 %18 = OpLabel
@@ -301,11 +256,15 @@ OpFunctionEnd
       R"(%main = OpFunction %void None %9
 %18 = OpLabel
 %v = OpVariable %_ptr_Function_v4float Function
+%f = OpVariable %_ptr_Function_float Function
 %19 = OpLoad %v4float %BaseColor
 OpStore %v %19
 %20 = OpLoad %int %Idx
 %21 = OpAccessChain %_ptr_Function_float %v %20
 %22 = OpLoad %float %21
+OpStore %f %22
+%23 = OpLoad %v4float %v
+%24 = OpLoad %float %f
 %25 = OpCompositeConstruct %v4float %22 %22 %22 %22
 %26 = OpFDiv %v4float %19 %25
 OpStore %gl_FragColor %26
@@ -314,7 +273,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalSingleBlockLoadStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSingleBlockLoadStoreElimTest, NoElimIfInterveningAccessChainStore) {
@@ -446,7 +405,7 @@ TEST_F(LocalSingleBlockLoadStoreElimTest, ElimIfCopyObjectInFunction) {
   //   gl_FragData[1] = v2;
   // }
 
-  const std::string predefs_before =
+  const std::string predefs =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -477,35 +436,6 @@ OpName %v2 "v2"
 %int_1 = OpConstant %int 1
 )";
 
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %gl_FragData
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %BaseColor "BaseColor"
-OpName %gl_FragData "gl_FragData"
-%void = OpTypeVoid
-%8 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%uint = OpTypeInt 32 0
-%uint_32 = OpConstant %uint 32
-%_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32
-%_ptr_Output__arr_v4float_uint_32 = OpTypePointer Output %_arr_v4float_uint_32
-%gl_FragData = OpVariable %_ptr_Output__arr_v4float_uint_32 Output
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%float_0_5 = OpConstant %float 0.5
-%int_1 = OpConstant %int 1
-)";
-
   const std::string before =
       R"(%main = OpFunction %void None %8
 %22 = OpLabel
@@ -530,11 +460,18 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %8
 %22 = OpLabel
+%v1 = OpVariable %_ptr_Function_v4float Function
+%v2 = OpVariable %_ptr_Function_v4float Function
 %23 = OpLoad %v4float %BaseColor
+OpStore %v1 %23
+%24 = OpLoad %v4float %v1
 %25 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_0
 OpStore %25 %23
 %26 = OpLoad %v4float %BaseColor
 %27 = OpVectorTimesScalar %v4float %26 %float_0_5
+%28 = OpCopyObject %_ptr_Function_v4float %v2
+OpStore %28 %27
+%29 = OpLoad %v4float %28
 %30 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_1
 OpStore %30 %27
 OpReturn
@@ -542,14 +479,14 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalSingleBlockLoadStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSingleBlockLoadStoreElimTest, ElimOpaque) {
   // SPIR-V not representable in GLSL; not generatable from HLSL
   // at the moment
 
-  const std::string predefs_before =
+  const std::string predefs =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -565,7 +502,7 @@ OpName %outColor "outColor"
 OpName %sampler15 "sampler15"
 OpName %s0 "s0"
 OpName %texCoords "texCoords"
-OpName %param "param" 
+OpName %param "param"
 OpDecorate %sampler15 DescriptorSet 0
 %void = OpTypeVoid
 %12 = OpTypeFunction %void
@@ -590,48 +527,8 @@ OpDecorate %sampler15 DescriptorSet 0
 %texCoords = OpVariable %_ptr_Input_v2float Input
 )";
 
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %outColor %texCoords
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %S_t "S_t"
-OpMemberName %S_t 0 "v0"
-OpMemberName %S_t 1 "v1"
-OpMemberName %S_t 2 "smp"
-OpName %outColor "outColor"
-OpName %sampler15 "sampler15"
-OpName %s0 "s0"
-OpName %texCoords "texCoords"
-OpDecorate %sampler15 DescriptorSet 0
-%void = OpTypeVoid
-%10 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v2float = OpTypeVector %float 2
-%v4float = OpTypeVector %float 4
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%outColor = OpVariable %_ptr_Output_v4float Output
-%15 = OpTypeImage %float 2D 0 0 0 1 Unknown
-%16 = OpTypeSampledImage %15
-%S_t = OpTypeStruct %v2float %v2float %16
-%_ptr_Function_S_t = OpTypePointer Function %S_t
-%18 = OpTypeFunction %void %_ptr_Function_S_t
-%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
-%_ptr_Function_16 = OpTypePointer Function %16
-%sampler15 = OpVariable %_ptr_UniformConstant_16 UniformConstant
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%int_2 = OpConstant %int 2
-%_ptr_Function_v2float = OpTypePointer Function %v2float
-%_ptr_Input_v2float = OpTypePointer Input %v2float
-%texCoords = OpVariable %_ptr_Input_v2float Input
-)";
-
   const std::string before =
-      R"( %main = OpFunction %void None %12
+      R"(%main = OpFunction %void None %12
 %28 = OpLabel
 %s0 = OpVariable %_ptr_Function_S_t Function 
 %param = OpVariable %_ptr_Function_S_t Function
@@ -656,25 +553,33 @@ OpFunctionEnd
 )";
 
   const std::string after =
-      R"(%main = OpFunction %void None %10
-%26 = OpLabel
+      R"(%main = OpFunction %void None %12
+%28 = OpLabel
 %s0 = OpVariable %_ptr_Function_S_t Function
-%27 = OpLoad %v2float %texCoords
-%28 = OpLoad %S_t %s0
-%29 = OpCompositeInsert %S_t %27 %28 0
-%30 = OpLoad %16 %sampler15
-%32 = OpCompositeInsert %S_t %30 %29 2
-OpStore %s0 %32
-%35 = OpCompositeExtract %16 %32 2
-%37 = OpCompositeExtract %v2float %32 0
-%38 = OpImageSampleImplicitLod %v4float %35 %37
-OpStore %outColor %38
+%param = OpVariable %_ptr_Function_S_t Function
+%29 = OpLoad %v2float %texCoords
+%30 = OpLoad %S_t %s0
+%31 = OpCompositeInsert %S_t %29 %30 0
+OpStore %s0 %31
+%32 = OpLoad %18 %sampler15
+%33 = OpLoad %S_t %s0
+%34 = OpCompositeInsert %S_t %32 %31 2
+OpStore %s0 %34
+%35 = OpLoad %S_t %s0
+OpStore %param %34
+%36 = OpLoad %S_t %param
+%37 = OpCompositeExtract %18 %34 2
+%38 = OpLoad %S_t %param
+%39 = OpCompositeExtract %v2float %34 0
+%40 = OpImageSampleImplicitLod %v4float %37 %39
+OpStore %outColor %40
 OpReturn
 OpFunctionEnd
 )";
 
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<opt::LocalSingleBlockLoadStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSingleBlockLoadStoreElimTest, PositiveAndNegativeCallTree) {
@@ -701,7 +606,7 @@ TEST_F(LocalSingleBlockLoadStoreElimTest, PositiveAndNegativeCallTree) {
   //     gl_FragColor = bar(BaseColor);
   // }
 
-  const std::string predefs_before =
+  const std::string predefs =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -715,43 +620,6 @@ OpName %bar_vf4_ "bar(vf4;"
 OpName %v1_0 "v1"
 OpName %t "t"
 OpName %t_0 "t"
-OpName %gl_FragColor "gl_FragColor" 
-OpName %BaseColor "BaseColor"
-OpName %param "param" 
-%void = OpTypeVoid
-%13 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%17 = OpTypeFunction %v4float %_ptr_Function_v4float
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%main = OpFunction %void None %13
-%20 = OpLabel
-%param = OpVariable %_ptr_Function_v4float Function
-%21 = OpLoad %v4float %BaseColor
-OpStore %param %21
-%22 = OpFunctionCall %v4float %bar_vf4_ %param
-OpStore %gl_FragColor %22
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %foo_vf4_ "foo(vf4;"
-OpName %v1 "v1"
-OpName %bar_vf4_ "bar(vf4;"
-OpName %v1_0 "v1"
-OpName %t "t"
 OpName %gl_FragColor "gl_FragColor"
 OpName %BaseColor "BaseColor"
 OpName %param "param"
@@ -810,13 +678,16 @@ OpFunctionEnd
 %bar_vf4_ = OpFunction %v4float None %17
 %v1_0 = OpFunctionParameter %_ptr_Function_v4float
 %26 = OpLabel
+%t_0 = OpVariable %_ptr_Function_v4float Function
 %27 = OpLoad %v4float %v1_0
+OpStore %t_0 %27
+%28 = OpLoad %v4float %t_0
 OpReturnValue %27
 OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalSingleBlockLoadStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSingleBlockLoadStoreElimTest, PointerVariable) {
@@ -905,6 +776,9 @@ OpDecorate %7 Binding 0
 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
 %1 = OpFunction %void None %10
 %23 = OpLabel
+%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
+OpStore %24 %7
+%26 = OpLoad %_ptr_Uniform__struct_5 %24
 %27 = OpAccessChain %_ptr_Uniform_v4float %7 %int_0 %uint_0 %int_0
 %28 = OpLoad %v4float %27
 %29 = OpCopyObject %v4float %28
index 5d413c6..a7e0e90 100644 (file)
@@ -40,7 +40,7 @@ TEST_F(LocalSingleStoreElimTest, PositiveAndNegative) {
   //     gl_FragColor = v + f;
   // }
 
-  const std::string predefs_before =
+  const std::string predefs =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -69,34 +69,6 @@ OpName %gl_FragColor "gl_FragColor"
 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
 )";
 
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %BaseColor "BaseColor"
-OpName %f "f"
-OpName %fi "fi"
-OpName %gl_FragColor "gl_FragColor"
-%void = OpTypeVoid
-%9 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Function_float = OpTypePointer Function %float
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
   const std::string before =
       R"(%main = OpFunction %void None %9
 %19 = OpLabel
@@ -126,8 +98,10 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %9
 %19 = OpLabel
+%v = OpVariable %_ptr_Function_v4float Function
 %f = OpVariable %_ptr_Function_float Function
 %20 = OpLoad %v4float %BaseColor
+OpStore %v %20
 %21 = OpLoad %float %fi
 OpStore %f %21
 %22 = OpLoad %float %f
@@ -138,6 +112,7 @@ OpBranchConditional %23 %25 %24
 OpStore %f %float_0
 OpBranch %24
 %24 = OpLabel
+%26 = OpLoad %v4float %v
 %27 = OpLoad %float %f
 %28 = OpCompositeConstruct %v4float %27 %27 %27 %27
 %29 = OpFAdd %v4float %20 %28
@@ -147,7 +122,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalSingleStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSingleStoreElimTest, MultipleLoads) {
@@ -167,7 +142,7 @@ TEST_F(LocalSingleStoreElimTest, MultipleLoads) {
   //     gl_FragColor = v + f;
   // }
 
-  const std::string predefs_before =
+  const std::string predefs =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -196,34 +171,6 @@ OpName %gl_FragColor "gl_FragColor"
 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
 )";
 
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %r "r"
-OpName %gl_FragColor "gl_FragColor"
-%void = OpTypeVoid
-%9 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%float_1 = OpConstant %float 1
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
   const std::string before =
       R"(%main = OpFunction %void None %9
 %19 = OpLabel
@@ -255,16 +202,20 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %9
 %19 = OpLabel
+%v = OpVariable %_ptr_Function_v4float Function
 %r = OpVariable %_ptr_Function_v4float Function
 %20 = OpLoad %v4float %BaseColor
+OpStore %v %20
 %21 = OpLoad %float %fi
 %22 = OpFOrdLessThan %bool %21 %float_0
 OpSelectionMerge %23 None
 OpBranchConditional %22 %24 %25
 %24 = OpLabel
+%26 = OpLoad %v4float %v
 OpStore %r %20
 OpBranch %23
 %25 = OpLabel
+%27 = OpLoad %v4float %v
 %28 = OpCompositeConstruct %v4float %float_1 %float_1 %float_1 %float_1
 %29 = OpFSub %v4float %28 %20
 OpStore %r %29
@@ -277,7 +228,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalSingleStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSingleStoreElimTest, NoStoreElimWithInterveningAccessChainLoad) {
@@ -294,7 +245,7 @@ TEST_F(LocalSingleStoreElimTest, NoStoreElimWithInterveningAccessChainLoad) {
   //     gl_FragColor = v * f;
   // }
 
-  const std::string predefs_before =
+  const std::string predefs =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -320,31 +271,6 @@ OpName %gl_FragColor "gl_FragColor"
 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
 )";
 
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %gl_FragColor "gl_FragColor"
-%void = OpTypeVoid
-%8 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Function_float = OpTypePointer Function %float
-%uint = OpTypeInt 32 0
-%uint_3 = OpConstant %uint 3
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
   const std::string before =
       R"(%main = OpFunction %void None %8
 %17 = OpLabel
@@ -367,10 +293,14 @@ OpFunctionEnd
       R"(%main = OpFunction %void None %8
 %17 = OpLabel
 %v = OpVariable %_ptr_Function_v4float Function
+%f = OpVariable %_ptr_Function_float Function
 %18 = OpLoad %v4float %BaseColor
 OpStore %v %18
 %19 = OpAccessChain %_ptr_Function_float %v %uint_3
 %20 = OpLoad %float %19
+OpStore %f %20
+%21 = OpLoad %v4float %v
+%22 = OpLoad %float %f
 %23 = OpVectorTimesScalar %v4float %18 %20
 OpStore %gl_FragColor %23
 OpReturn
@@ -378,7 +308,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalSingleStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSingleStoreElimTest, NoReplaceOfDominatingPartialStore) {
@@ -453,7 +383,7 @@ TEST_F(LocalSingleStoreElimTest, ElimIfCopyObjectInFunction) {
   //     gl_FragColor = v + f;
   // }
 
-  const std::string predefs_before =
+  const std::string predefs =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -482,34 +412,6 @@ OpName %gl_FragColor "gl_FragColor"
 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
 )";
 
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %BaseColor "BaseColor"
-OpName %f "f"
-OpName %fi "fi"
-OpName %gl_FragColor "gl_FragColor"
-%void = OpTypeVoid
-%9 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Function_float = OpTypePointer Function %float
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
   const std::string before =
       R"(%main = OpFunction %void None %9
 %19 = OpLabel
@@ -540,8 +442,10 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %9
 %19 = OpLabel
+%v = OpVariable %_ptr_Function_v4float Function
 %f = OpVariable %_ptr_Function_float Function
 %20 = OpLoad %v4float %BaseColor
+OpStore %v %20
 %21 = OpLoad %float %fi
 OpStore %f %21
 %22 = OpLoad %float %f
@@ -552,6 +456,8 @@ OpBranchConditional %23 %25 %24
 OpStore %f %float_0
 OpBranch %24
 %24 = OpLabel
+%26 = OpCopyObject %_ptr_Function_v4float %v
+%27 = OpLoad %v4float %26
 %28 = OpLoad %float %f
 %29 = OpCompositeConstruct %v4float %28 %28 %28 %28
 %30 = OpFAdd %v4float %20 %29
@@ -561,7 +467,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalSingleStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSingleStoreElimTest, NoOptIfStoreNotDominating) {
@@ -657,7 +563,7 @@ TEST_F(LocalSingleStoreElimTest, OptInitializedVariableLikeStore) {
   //     gl_FragColor = vec4(f);
   // }
 
-  const std::string predefs_before =
+  const std::string predefs =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -678,26 +584,6 @@ OpDecorate %gl_FragColor Location 0
 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
 )";
 
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %gl_FragColor "gl_FragColor"
-OpDecorate %gl_FragColor Location 0
-%void = OpTypeVoid
-%6 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_ptr_Function_float = OpTypePointer Function %float
-%float_0 = OpConstant %float 0
-%v4float = OpTypeVector %float 4
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
   const std::string before =
       R"(%main = OpFunction %void None %6
 %12 = OpLabel
@@ -712,6 +598,8 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %6
 %12 = OpLabel
+%f = OpVariable %_ptr_Function_float Function %float_0
+%13 = OpLoad %float %f
 %14 = OpCompositeConstruct %v4float %float_0 %float_0 %float_0 %float_0
 OpStore %gl_FragColor %14
 OpReturn
@@ -719,90 +607,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalSingleStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
-}
-
-TEST_F(LocalSingleStoreElimTest, OptStoreOfNonCombinator) {
-  // Unused local store is removed but non-combinator operand remains
-
-  const std::string predefs_before =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %gl_GlobalInvocationID
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
-%void = OpTypeVoid
-%6 = OpTypeFunction %void
-%uint = OpTypeInt 32 0
-%v2uint = OpTypeVector %uint 2
-%_ptr_Function_uint = OpTypePointer Function %uint
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%_ptr_Input_v2uint = OpTypePointer Input %v2uint
-%164 = OpTypeImage %uint 2D 0 0 0 2 R32ui
-%_ptr_UniformConstant_164 = OpTypePointer UniformConstant %164
-%5661 = OpVariable %_ptr_UniformConstant_164 UniformConstant
-%gl_GlobalInvocationID = OpVariable %_ptr_Input_v2uint Input
-%4930 = OpVariable %_ptr_Uniform_uint Uniform
-%_ptr_Image_uint = OpTypePointer Image %uint
-%uint_0 = OpConstant %uint 0
-%uint_1 = OpConstant %uint 1
-)";
-
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %2 "main" %gl_GlobalInvocationID
-OpExecutionMode %2 OriginUpperLeft
-OpSource GLSL 140
-OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
-%void = OpTypeVoid
-%5 = OpTypeFunction %void
-%uint = OpTypeInt 32 0
-%v2uint = OpTypeVector %uint 2
-%_ptr_Function_uint = OpTypePointer Function %uint
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%_ptr_Input_v2uint = OpTypePointer Input %v2uint
-%11 = OpTypeImage %uint 2D 0 0 0 2 R32ui
-%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
-%13 = OpVariable %_ptr_UniformConstant_11 UniformConstant
-%gl_GlobalInvocationID = OpVariable %_ptr_Input_v2uint Input
-%14 = OpVariable %_ptr_Uniform_uint Uniform
-%_ptr_Image_uint = OpTypePointer Image %uint
-%uint_0 = OpConstant %uint 0
-%uint_1 = OpConstant %uint 1
-)";
-
-  const std::string before =
-      R"(%main = OpFunction %void None %6
-%12 = OpLabel
-%5297 = OpVariable %_ptr_Function_uint Function
-%4061 = OpLoad %164 %5661
-%16843 = OpLoad %v2uint %gl_GlobalInvocationID
-%24748 = OpLoad %uint %4930
-%15928 = OpImageTexelPointer %_ptr_Image_uint %4061 %16843 %uint_0
-%21946 = OpAtomicExchange %uint %15928 %uint_1 %uint_0 %24748
-OpStore %5297 %21946
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string after =
-      R"(%2 = OpFunction %void None %5
-%18 = OpLabel
-%20 = OpLoad %11 %13
-%21 = OpLoad %v2uint %gl_GlobalInvocationID
-%22 = OpLoad %uint %14
-%23 = OpImageTexelPointer %_ptr_Image_uint %20 %21 %uint_0
-%24 = OpAtomicExchange %uint %23 %uint_1 %uint_0 %22
-OpReturn
-OpFunctionEnd
-)";
-
-  SinglePassRunAndCheck<opt::LocalSingleStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSingleStoreElimTest, PointerVariable) {
@@ -891,6 +696,9 @@ OpDecorate %7 Binding 0
 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
 %1 = OpFunction %void None %10
 %23 = OpLabel
+%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
+OpStore %24 %7
+%26 = OpLoad %_ptr_Uniform__struct_5 %24
 %27 = OpAccessChain %_ptr_Uniform_v4float %7 %int_0 %uint_0 %int_0
 %28 = OpLoad %v4float %27
 %29 = OpCopyObject %v4float %28
index b6f282a..899318b 100644 (file)
@@ -44,24 +44,12 @@ OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %BC %fo
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 140
-)";
-
-  const std::string names_before =
-      R"(OpName %main "main"
+OpName %main "main"
 OpName %f "f"
 OpName %i "i"
 OpName %BC "BC"
 OpName %fo "fo"
-)";
-
-  const std::string names_after =
-      R"(OpName %main "main"
-OpName %BC "BC"
-OpName %fo "fo"
-)";
-
-  const std::string predefs2 =
-      R"(%void = OpTypeVoid
+%void = OpTypeVoid
 %8 = OpTypeFunction %void
 %float = OpTypeFloat 32
 %_ptr_Function_float = OpTypePointer Function %float
@@ -118,6 +106,10 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %8
 %22 = OpLabel
+%f = OpVariable %_ptr_Function_float Function
+%i = OpVariable %_ptr_Function_int Function
+OpStore %f %float_0
+OpStore %i %int_0
 OpBranch %23
 %23 = OpLabel
 %38 = OpPhi %float %float_0 %22 %34 %25
@@ -131,9 +123,11 @@ OpBranchConditional %28 %29 %24
 %32 = OpAccessChain %_ptr_Input_float %BC %39
 %33 = OpLoad %float %32
 %34 = OpFAdd %float %38 %33
+OpStore %f %34
 OpBranch %25
 %25 = OpLabel
 %36 = OpIAdd %int %39 %int_1
+OpStore %i %36
 OpBranch %23
 %24 = OpLabel
 OpStore %fo %38
@@ -142,8 +136,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs + names_before + predefs2 + before,
-      predefs + names_after + predefs2 + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSSAElimTest, ForLoopWithContinue) {
@@ -173,7 +166,7 @@ OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 140
 )";
 
-  const std::string names_before =
+  const std::string names =
       R"(OpName %main "main"
 OpName %f "f"
 OpName %i "i"
@@ -182,12 +175,6 @@ OpName %BC "BC"
 OpName %fo "fo"
 )";
 
-  const std::string names_after =
-      R"(OpName %main "main"
-OpName %BC "BC"
-OpName %fo "fo"
-)";
-
   const std::string predefs2 =
       R"(%void = OpTypeVoid
 %9 = OpTypeFunction %void
@@ -257,6 +244,11 @@ OpFunctionEnd
       R"(%46 = OpUndef %float
 %main = OpFunction %void None %9
 %23 = OpLabel
+%f = OpVariable %_ptr_Function_float Function
+%i = OpVariable %_ptr_Function_int Function
+%t = OpVariable %_ptr_Function_float Function
+OpStore %f %float_0
+OpStore %i %int_0
 OpBranch %24
 %24 = OpLabel
 %44 = OpPhi %float %float_0 %23 %48 %26
@@ -270,6 +262,7 @@ OpBranchConditional %29 %30 %25
 %30 = OpLabel
 %32 = OpAccessChain %_ptr_Input_float %BC %45
 %33 = OpLoad %float %32
+OpStore %t %33
 %35 = OpFOrdLessThan %bool %33 %float_0
 OpSelectionMerge %36 None
 OpBranchConditional %35 %37 %36
@@ -277,10 +270,12 @@ OpBranchConditional %35 %37 %36
 OpBranch %26
 %36 = OpLabel
 %40 = OpFAdd %float %44 %33
+OpStore %f %40
 OpBranch %26
 %26 = OpLabel
 %48 = OpPhi %float %44 %37 %40 %36
 %42 = OpIAdd %int %45 %int_1
+OpStore %i %42
 OpBranch %24
 %25 = OpLabel
 OpStore %fo %44
@@ -289,8 +284,8 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs + names_before + predefs2 + before,
-      predefs + names_after + predefs2 + after, true, true);
+      predefs + names + predefs2 + before, predefs + names + predefs2 + after,
+      true, true);
 }
 
 TEST_F(LocalSSAElimTest, ForLoopWithBreak) {
@@ -318,25 +313,13 @@ OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %BC %fo
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 140
-)";
-
-  const std::string names_before =
-      R"(OpName %main "main"
+OpName %main "main"
 OpName %f "f"
 OpName %i "i"
 OpName %t "t"
 OpName %BC "BC"
 OpName %fo "fo"
-)";
-
-  const std::string names_after =
-      R"(OpName %main "main"
-OpName %BC "BC"
-OpName %fo "fo"
-)";
-
-  const std::string predefs2 =
-      R"(%void = OpTypeVoid
+%void = OpTypeVoid
 %9 = OpTypeFunction %void
 %float = OpTypeFloat 32
 %_ptr_Function_float = OpTypePointer Function %float
@@ -405,6 +388,11 @@ OpFunctionEnd
       R"(%47 = OpUndef %float
 %main = OpFunction %void None %9
 %24 = OpLabel
+%f = OpVariable %_ptr_Function_float Function
+%i = OpVariable %_ptr_Function_int Function
+%t = OpVariable %_ptr_Function_float Function
+OpStore %f %float_0
+OpStore %i %int_0
 OpBranch %25
 %25 = OpLabel
 %45 = OpPhi %float %float_0 %24 %36 %27
@@ -419,15 +407,18 @@ OpBranchConditional %30 %31 %26
 %34 = OpAccessChain %_ptr_Input_float %BC %46
 %35 = OpLoad %float %34
 %36 = OpFAdd %float %45 %35
+OpStore %t %36
 %38 = OpFOrdGreaterThan %bool %36 %float_1
 OpSelectionMerge %39 None
 OpBranchConditional %38 %40 %39
 %40 = OpLabel
 OpBranch %26
 %39 = OpLabel
+OpStore %f %36
 OpBranch %27
 %27 = OpLabel
 %43 = OpIAdd %int %46 %int_1
+OpStore %i %43
 OpBranch %25
 %26 = OpLabel
 %49 = OpPhi %float %48 %28 %36 %40
@@ -437,8 +428,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs + names_before + predefs2 + before,
-      predefs + names_after + predefs2 + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSSAElimTest, SwapProblem) {
@@ -467,10 +457,7 @@ OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %fe %fo
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 140
-)";
-
-  const std::string names_before =
-      R"(OpName %main "main"
+OpName %main "main"
 OpName %f1 "f1"
 OpName %f2 "f2"
 OpName %ie "ie"
@@ -478,16 +465,7 @@ OpName %fe "fe"
 OpName %i "i"
 OpName %t "t"
 OpName %fo "fo"
-)";
-
-  const std::string names_after =
-      R"(OpName %main "main"
-OpName %fe "fe"
-OpName %fo "fo"
-)";
-
-  const std::string predefs2 =
-      R"(%void = OpTypeVoid
+%void = OpTypeVoid
 %11 = OpTypeFunction %void
 %float = OpTypeFloat 32
 %_ptr_Function_float = OpTypePointer Function %float
@@ -551,8 +529,17 @@ OpFunctionEnd
       R"(%43 = OpUndef %float
 %main = OpFunction %void None %11
 %23 = OpLabel
+%f1 = OpVariable %_ptr_Function_float Function
+%f2 = OpVariable %_ptr_Function_float Function
+%ie = OpVariable %_ptr_Function_int Function
+%i = OpVariable %_ptr_Function_int Function
+%t = OpVariable %_ptr_Function_float Function
+OpStore %f1 %float_0
+OpStore %f2 %float_1
 %24 = OpLoad %float %fe
 %25 = OpConvertFToS %int %24
+OpStore %ie %25
+OpStore %i %int_0
 OpBranch %26
 %26 = OpLabel
 %40 = OpPhi %float %float_0 %23 %41 %28
@@ -565,9 +552,13 @@ OpBranch %29
 %32 = OpSLessThan %bool %42 %25
 OpBranchConditional %32 %33 %27
 %33 = OpLabel
+OpStore %t %40
+OpStore %f1 %41
+OpStore %f2 %40
 OpBranch %28
 %28 = OpLabel
 %38 = OpIAdd %int %42 %int_1
+OpStore %i %38
 OpBranch %26
 %27 = OpLabel
 OpStore %fo %40
@@ -576,8 +567,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs + names_before + predefs2 + before,
-      predefs + names_after + predefs2 + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSSAElimTest, LostCopyProblem) {
@@ -606,25 +596,13 @@ OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %BC %fo
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 140
-)";
-
-  const std::string names_before =
-      R"(OpName %main "main"
+OpName %main "main"
 OpName %f "f"
 OpName %i "i"
 OpName %t "t"
 OpName %BC "BC"
 OpName %fo "fo"
-)";
-
-  const std::string names_after =
-      R"(OpName %main "main"
-OpName %BC "BC"
-OpName %fo "fo"
-)";
-
-  const std::string predefs2 =
-      R"(%void = OpTypeVoid
+%void = OpTypeVoid
 %9 = OpTypeFunction %void
 %float = OpTypeFloat 32
 %_ptr_Function_float = OpTypePointer Function %float
@@ -693,6 +671,11 @@ OpFunctionEnd
       R"(%47 = OpUndef %float
 %main = OpFunction %void None %9
 %24 = OpLabel
+%f = OpVariable %_ptr_Function_float Function
+%i = OpVariable %_ptr_Function_int Function
+%t = OpVariable %_ptr_Function_float Function
+OpStore %f %float_0
+OpStore %i %int_0
 OpBranch %25
 %25 = OpLabel
 %45 = OpPhi %float %float_0 %24 %37 %27
@@ -704,9 +687,11 @@ OpBranch %28
 %30 = OpSLessThan %bool %46 %int_4
 OpBranchConditional %30 %31 %26
 %31 = OpLabel
+OpStore %t %45
 %35 = OpAccessChain %_ptr_Input_float %BC %46
 %36 = OpLoad %float %35
 %37 = OpFAdd %float %45 %36
+OpStore %f %37
 %39 = OpFOrdGreaterThan %bool %37 %float_1
 OpSelectionMerge %40 None
 OpBranchConditional %39 %41 %40
@@ -716,6 +701,7 @@ OpBranch %26
 OpBranch %27
 %27 = OpLabel
 %43 = OpIAdd %int %46 %int_1
+OpStore %i %43
 OpBranch %25
 %26 = OpLabel
 %49 = OpPhi %float %45 %28 %37 %41
@@ -726,8 +712,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs + names_before + predefs2 + before,
-      predefs + names_after + predefs2 + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSSAElimTest, IfThenElse) {
@@ -753,25 +738,12 @@ OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %f %BaseColor %gl_FragColor
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 140
-)";
-
-  const std::string names_before =
-      R"(OpName %main "main"
+OpName %main "main"
 OpName %f "f"
 OpName %v "v"
 OpName %BaseColor "BaseColor"
 OpName %gl_FragColor "gl_FragColor"
-)";
-
-  const std::string names_after =
-      R"(OpName %main "main"
-OpName %f "f"
-OpName %BaseColor "BaseColor"
-OpName %gl_FragColor "gl_FragColor"
-)";
-
-  const std::string predefs2 =
-      R"(%void = OpTypeVoid
+%void = OpTypeVoid
 %8 = OpTypeFunction %void
 %float = OpTypeFloat 32
 %_ptr_Input_float = OpTypePointer Input %float
@@ -817,117 +789,6 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %8
 %20 = OpLabel
-%21 = OpLoad %float %f
-%22 = OpFOrdGreaterThanEqual %bool %21 %float_0
-OpSelectionMerge %23 None
-OpBranchConditional %22 %24 %25
-%24 = OpLabel
-%26 = OpLoad %v4float %BaseColor
-%27 = OpVectorTimesScalar %v4float %26 %float_0_5
-OpBranch %23
-%25 = OpLabel
-%28 = OpLoad %v4float %BaseColor
-%29 = OpFAdd %v4float %28 %18
-OpBranch %23
-%23 = OpLabel
-%31 = OpPhi %v4float %27 %24 %29 %25
-OpStore %gl_FragColor %31
-OpReturn
-OpFunctionEnd
-)";
-
-  SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs + names_before + predefs2 + before,
-      predefs + names_after + predefs2 + after, true, true);
-}
-
-TEST_F(LocalSSAElimTest, DecoratedVar) {
-  // SPIR-V hand edited to decorate v
-  // #version 450
-  //
-  // layout (location=0) in vec4 BaseColor;
-  // layout (location=1) in float f;
-  // layout (location=0) out vec4 OutColor;
-  //
-  // void main()
-  // {
-  //     vec4 v;
-  //     if (f >= 0)
-  //       v = BaseColor * 0.5;
-  //     else
-  //       v = BaseColor + vec4(0.1,0.1,0.1,0.1);
-  //     OutColor = v;
-  // }
-
-  const std::string predefs_before =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %f %BaseColor %OutColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 450
-OpName %main "main"
-OpName %f "f"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %OutColor "OutColor"
-OpDecorate %v RelaxedPrecision
-OpDecorate %f Location 1
-OpDecorate %BaseColor Location 0
-OpDecorate %OutColor Location 0
-%void = OpTypeVoid
-%8 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_ptr_Input_float = OpTypePointer Input %float
-%f = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%float_0_5 = OpConstant %float 0.5
-%float_0_1 = OpConstant %float 0.1
-%18 = OpConstantComposite %v4float %float_0_1 %float_0_1 %float_0_1 %float_0_1
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%OutColor = OpVariable %_ptr_Output_v4float Output
-)";
-
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %f %BaseColor %OutColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 450
-OpName %main "main"
-OpName %f "f"
-OpName %BaseColor "BaseColor"
-OpName %OutColor "OutColor"
-OpDecorate %f Location 1
-OpDecorate %BaseColor Location 0
-OpDecorate %OutColor Location 0
-%void = OpTypeVoid
-%8 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_ptr_Input_float = OpTypePointer Input %float
-%f = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%float_0_5 = OpConstant %float 0.5
-%float_0_1 = OpConstant %float 0.1
-%18 = OpConstantComposite %v4float %float_0_1 %float_0_1 %float_0_1 %float_0_1
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%OutColor = OpVariable %_ptr_Output_v4float Output
-)";
-
-  const std::string before =
-      R"(%main = OpFunction %void None %8
-%20 = OpLabel
 %v = OpVariable %_ptr_Function_v4float Function
 %21 = OpLoad %float %f
 %22 = OpFOrdGreaterThanEqual %bool %21 %float_0
@@ -944,36 +805,14 @@ OpBranch %23
 OpStore %v %29
 OpBranch %23
 %23 = OpLabel
-%30 = OpLoad %v4float %v
-OpStore %OutColor %30
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string after =
-      R"(%main = OpFunction %void None %8
-%20 = OpLabel
-%21 = OpLoad %float %f
-%22 = OpFOrdGreaterThanEqual %bool %21 %float_0
-OpSelectionMerge %23 None
-OpBranchConditional %22 %24 %25
-%24 = OpLabel
-%26 = OpLoad %v4float %BaseColor
-%27 = OpVectorTimesScalar %v4float %26 %float_0_5
-OpBranch %23
-%25 = OpLabel
-%28 = OpLoad %v4float %BaseColor
-%29 = OpFAdd %v4float %28 %18
-OpBranch %23
-%23 = OpLabel
 %31 = OpPhi %v4float %27 %24 %29 %25
-OpStore %OutColor %31
+OpStore %gl_FragColor %31
 OpReturn
 OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs_before + before, predefs_after + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSSAElimTest, IfThen) {
@@ -997,25 +836,12 @@ OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 140
-)";
-
-  const std::string names_before =
-      R"(OpName %main "main"
+OpName %main "main"
 OpName %v "v"
 OpName %BaseColor "BaseColor"
 OpName %f "f"
 OpName %gl_FragColor "gl_FragColor"
-)";
-
-  const std::string names_after =
-      R"(OpName %main "main"
-OpName %BaseColor "BaseColor"
-OpName %f "f"
-OpName %gl_FragColor "gl_FragColor"
-)";
-
-  const std::string predefs2 =
-      R"(%void = OpTypeVoid
+%void = OpTypeVoid
 %8 = OpTypeFunction %void
 %float = OpTypeFloat 32
 %v4float = OpTypeVector %float 4
@@ -1056,13 +882,16 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %8
 %18 = OpLabel
+%v = OpVariable %_ptr_Function_v4float Function
 %19 = OpLoad %v4float %BaseColor
+OpStore %v %19
 %20 = OpLoad %float %f
 %21 = OpFOrdLessThanEqual %bool %20 %float_0
 OpSelectionMerge %22 None
 OpBranchConditional %21 %23 %22
 %23 = OpLabel
 %25 = OpVectorTimesScalar %v4float %19 %float_0_5
+OpStore %v %25
 OpBranch %22
 %22 = OpLabel
 %27 = OpPhi %v4float %19 %18 %25 %23
@@ -1072,8 +901,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs + names_before + predefs2 + before,
-      predefs + names_after + predefs2 + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSSAElimTest, Switch) {
@@ -1109,26 +937,13 @@ OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 140
-)";
-
-  const std::string names_before =
-      R"(OpName %main "main"
+OpName %main "main"
 OpName %v "v"
 OpName %BaseColor "BaseColor"
 OpName %i "i"
 OpName %f "f"
 OpName %gl_FragColor "gl_FragColor"
-)";
-
-  const std::string names_after =
-      R"(OpName %main "main"
-OpName %BaseColor "BaseColor"
-OpName %f "f"
-OpName %gl_FragColor "gl_FragColor"
-)";
-
-  const std::string predefs2 =
-      R"(%void = OpTypeVoid
+%void = OpTypeVoid
 %9 = OpTypeFunction %void
 %float = OpTypeFloat 32
 %v4float = OpTypeVector %float 4
@@ -1186,21 +1001,28 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %9
 %21 = OpLabel
+%v = OpVariable %_ptr_Function_v4float Function
+%i = OpVariable %_ptr_Function_int Function
 %22 = OpLoad %v4float %BaseColor
+OpStore %v %22
 %23 = OpLoad %float %f
 %24 = OpConvertFToS %int %23
+OpStore %i %24
 OpSelectionMerge %26 None
 OpSwitch %24 %27 0 %28 1 %29 2 %30
 %27 = OpLabel
 OpBranch %26
 %28 = OpLabel
 %32 = OpVectorTimesScalar %v4float %22 %float_0_1
+OpStore %v %32
 OpBranch %26
 %29 = OpLabel
 %34 = OpVectorTimesScalar %v4float %22 %float_0_3
+OpStore %v %34
 OpBranch %26
 %30 = OpLabel
 %36 = OpVectorTimesScalar %v4float %22 %float_0_7
+OpStore %v %36
 OpBranch %26
 %26 = OpLabel
 %38 = OpPhi %v4float %22 %27 %32 %28 %34 %29 %36 %30
@@ -1210,8 +1032,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs + names_before + predefs2 + before,
-      predefs + names_after + predefs2 + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSSAElimTest, SwitchWithFallThrough) {
@@ -1246,26 +1067,13 @@ OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 140
-)";
-
-  const std::string names_before =
-      R"(OpName %main "main"
+OpName %main "main"
 OpName %v "v"
 OpName %BaseColor "BaseColor"
 OpName %i "i"
 OpName %f "f"
 OpName %gl_FragColor "gl_FragColor"
-)";
-
-  const std::string names_after =
-      R"(OpName %main "main"
-OpName %BaseColor "BaseColor"
-OpName %f "f"
-OpName %gl_FragColor "gl_FragColor"
-)";
-
-  const std::string predefs2 =
-      R"(%void = OpTypeVoid
+%void = OpTypeVoid
 %9 = OpTypeFunction %void
 %float = OpTypeFloat 32
 %v4float = OpTypeVector %float 4
@@ -1323,23 +1131,30 @@ OpFunctionEnd
   const std::string after =
       R"(%main = OpFunction %void None %9
 %20 = OpLabel
+%v = OpVariable %_ptr_Function_v4float Function
+%i = OpVariable %_ptr_Function_int Function
 %21 = OpLoad %v4float %BaseColor
+OpStore %v %21
 %22 = OpLoad %float %f
 %23 = OpConvertFToS %int %22
+OpStore %i %23
 OpSelectionMerge %25 None
 OpSwitch %23 %26 0 %27 1 %28 2 %29
 %26 = OpLabel
 OpBranch %25
 %27 = OpLabel
 %31 = OpVectorTimesScalar %v4float %21 %float_0_1
+OpStore %v %31
 OpBranch %25
 %28 = OpLabel
 %33 = OpCompositeConstruct %v4float %float_0_1 %float_0_1 %float_0_1 %float_0_1
 %34 = OpFAdd %v4float %21 %33
+OpStore %v %34
 OpBranch %29
 %29 = OpLabel
 %38 = OpPhi %v4float %21 %20 %34 %28
 %36 = OpVectorTimesScalar %v4float %38 %float_0_7
+OpStore %v %36
 OpBranch %25
 %25 = OpLabel
 %39 = OpPhi %v4float %21 %26 %31 %27 %36 %29
@@ -1349,8 +1164,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs + names_before + predefs2 + before,
-      predefs + names_after + predefs2 + after, true, true);
+      predefs + before, predefs + after, true, true);
 }
 
 TEST_F(LocalSSAElimTest, DontPatchPhiInLoopHeaderThatIsNotAVar) {
@@ -1401,7 +1215,7 @@ TEST_F(LocalSSAElimTest, OptInitializedVariableLikeStore) {
   //     oColor = v;
   // }
 
-  const std::string predefs_before =
+  const std::string predefs =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -1435,39 +1249,6 @@ OpDecorate %oColor Location 0
 %oColor = OpVariable %_ptr_Output_v4float Output
 )";
 
-  const std::string predefs_after =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %fi %iColor %oColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 450
-OpName %main "main"
-OpName %fi "fi"
-OpName %iColor "iColor"
-OpName %oColor "oColor"
-OpDecorate %fi Location 1
-OpDecorate %iColor Location 0
-OpDecorate %oColor Location 0
-%void = OpTypeVoid
-%8 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%float_0 = OpConstant %float 0
-%13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%bool = OpTypeBool
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%iColor = OpVariable %_ptr_Input_v4float Input
-%uint = OpTypeInt 32 0
-%uint_0 = OpConstant %uint 0
-%_ptr_Function_float = OpTypePointer Function %float
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%oColor = OpVariable %_ptr_Output_v4float Output
-)";
-
   const std::string func_before =
       R"(%main = OpFunction %void None %8
 %21 = OpLabel
@@ -1493,6 +1274,7 @@ OpFunctionEnd
   const std::string func_after =
       R"(%main = OpFunction %void None %8
 %21 = OpLabel
+%v = OpVariable %_ptr_Function_v4float Function %13
 %22 = OpLoad %float %fi
 %23 = OpFOrdLessThan %bool %22 %float_0
 OpSelectionMerge %24 None
@@ -1501,6 +1283,7 @@ OpBranchConditional %23 %25 %24
 %26 = OpAccessChain %_ptr_Input_float %iColor %uint_0
 %27 = OpLoad %float %26
 %29 = OpCompositeInsert %v4float %27 %13 0
+OpStore %v %29
 OpBranch %24
 %24 = OpLabel
 %31 = OpPhi %v4float %13 %21 %29 %25
@@ -1510,7 +1293,7 @@ OpFunctionEnd
 )";
 
   SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
-      predefs_before + func_before, predefs_after + func_after, true, true);
+      predefs + func_before, predefs + func_after, true, true);
 }
 
 TEST_F(LocalSSAElimTest, PointerVariable) {
@@ -1599,6 +1382,8 @@ OpDecorate %7 Binding 0
 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
 %1 = OpFunction %void None %10
 %23 = OpLabel
+%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
+OpStore %24 %7
 %27 = OpAccessChain %_ptr_Uniform_v4float %7 %int_0 %uint_0 %int_0
 %28 = OpLoad %v4float %27
 %29 = OpCopyObject %v4float %28