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();
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;
// 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)
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;
}
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;
// 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;
}
}
SingleStoreAnalyze(func);
if (ssa_var2store_.empty()) return false;
modified |= SingleStoreProcess(func);
- modified |= SingleStoreDCE();
return modified;
}
// 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
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);
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;
// 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();
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.
// 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)) {
++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
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;
++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) {
}
}
-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);
}
// 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();
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) {
if (header != 0) PatchPhis(header, label);
}
- return Status::SuccessWithChange;
+ return modified;
}
// Remove all |phi| operands coming from unreachable blocks (i.e., blocks not in
// 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_;
// 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.
// 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.
// 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())
.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())
.RegisterPass(CreateLocalAccessChainConvertPass())
.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
.RegisterPass(CreateLocalSingleStoreElimPass())
+ .RegisterPass(CreateAggressiveDCEPass())
.RegisterPass(CreateInsertExtractElimPass())
.RegisterPass(CreateDeadInsertElimPass())
.RegisterPass(CreateLocalMultiStoreElimPass())
+ .RegisterPass(CreateAggressiveDCEPass())
.RegisterPass(CreateCCPPass())
.RegisterPass(CreateAggressiveDCEPass())
.RegisterPass(CreateDeadBranchElimPass())
%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
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) {
%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
// gl_FragColor = v/f;
// }
- const std::string predefs_before =
+ const std::string predefs =
R"(OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
%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
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
)";
SinglePassRunAndCheck<opt::LocalSingleBlockLoadStoreElimPass>(
- predefs_before + before, predefs_after + after, true, true);
+ predefs + before, predefs + after, true, true);
}
TEST_F(LocalSingleBlockLoadStoreElimTest, NoElimIfInterveningAccessChainStore) {
// gl_FragData[1] = v2;
// }
- const std::string predefs_before =
+ const std::string predefs =
R"(OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
%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
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
)";
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
OpName %sampler15 "sampler15"
OpName %s0 "s0"
OpName %texCoords "texCoords"
-OpName %param "param"
+OpName %param "param"
OpDecorate %sampler15 DescriptorSet 0
%void = OpTypeVoid
%12 = OpTypeFunction %void
%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
)";
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) {
// gl_FragColor = bar(BaseColor);
// }
- const std::string predefs_before =
+ const std::string predefs =
R"(OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
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"
%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) {
%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
// gl_FragColor = v + f;
// }
- const std::string predefs_before =
+ const std::string predefs =
R"(OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
%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
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
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
)";
SinglePassRunAndCheck<opt::LocalSingleStoreElimPass>(
- predefs_before + before, predefs_after + after, true, true);
+ predefs + before, predefs + after, true, true);
}
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
%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
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
)";
SinglePassRunAndCheck<opt::LocalSingleStoreElimPass>(
- predefs_before + before, predefs_after + after, true, true);
+ predefs + before, predefs + after, true, true);
}
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
%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
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
)";
SinglePassRunAndCheck<opt::LocalSingleStoreElimPass>(
- predefs_before + before, predefs_after + after, true, true);
+ predefs + before, predefs + after, true, true);
}
TEST_F(LocalSingleStoreElimTest, NoReplaceOfDominatingPartialStore) {
// gl_FragColor = v + f;
// }
- const std::string predefs_before =
+ const std::string predefs =
R"(OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
%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
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
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
)";
SinglePassRunAndCheck<opt::LocalSingleStoreElimPass>(
- predefs_before + before, predefs_after + after, true, true);
+ predefs + before, predefs + after, true, true);
}
TEST_F(LocalSingleStoreElimTest, NoOptIfStoreNotDominating) {
// gl_FragColor = vec4(f);
// }
- const std::string predefs_before =
+ const std::string predefs =
R"(OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
%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
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
)";
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) {
%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
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
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
%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
)";
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) {
OpSource GLSL 140
)";
- const std::string names_before =
+ const std::string names =
R"(OpName %main "main"
OpName %f "f"
OpName %i "i"
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
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
%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
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
)";
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) {
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
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
%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
)";
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) {
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"
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
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
%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
)";
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) {
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
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
%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
OpBranch %27
%27 = OpLabel
%43 = OpIAdd %int %46 %int_1
+OpStore %i %43
OpBranch %25
%26 = OpLabel
%49 = OpPhi %float %45 %28 %37 %41
)";
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) {
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
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
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) {
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
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
)";
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) {
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
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
)";
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) {
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
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
)";
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) {
// oColor = v;
// }
- const std::string predefs_before =
+ const std::string predefs =
R"(OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
%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
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
%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
)";
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) {
%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