Remove Common Uniform Elimination Pass (#2731)
Remove Common Uniform Elimination Pass
Fixes #2520.
diff --git a/Android.mk b/Android.mk
index 075dc61..82d9776 100644
--- a/Android.mk
+++ b/Android.mk
@@ -84,7 +84,6 @@
source/opt/ccp_pass.cpp \
source/opt/code_sink.cpp \
source/opt/combine_access_chains.cpp \
- source/opt/common_uniform_elim_pass.cpp \
source/opt/compact_ids_pass.cpp \
source/opt/composite.cpp \
source/opt/const_folding_rules.cpp \
diff --git a/BUILD.gn b/BUILD.gn
index 8852584..70772b9 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -469,8 +469,6 @@
"source/opt/code_sink.h",
"source/opt/combine_access_chains.cpp",
"source/opt/combine_access_chains.h",
- "source/opt/common_uniform_elim_pass.cpp",
- "source/opt/common_uniform_elim_pass.h",
"source/opt/compact_ids_pass.cpp",
"source/opt/compact_ids_pass.h",
"source/opt/composite.cpp",
diff --git a/include/spirv-tools/optimizer.hpp b/include/spirv-tools/optimizer.hpp
index 1d8d6e0..4c668b4 100644
--- a/include/spirv-tools/optimizer.hpp
+++ b/include/spirv-tools/optimizer.hpp
@@ -492,20 +492,6 @@
// inserts created by that pass.
Optimizer::PassToken CreateDeadInsertElimPass();
-// Creates a pass to consolidate uniform references.
-// For each entry point function in the module, first change all constant index
-// access chain loads into equivalent composite extracts. Then consolidate
-// identical uniform loads into one uniform load. Finally, consolidate
-// identical uniform extracts into one uniform extract. This may require
-// moving a load or extract to a point which dominates all uses.
-//
-// This pass requires a module to have structured control flow ie shader
-// capability. It also requires logical addressing ie Addresses capability
-// is not enabled. It also currently does not support any extensions.
-//
-// This pass currently only optimizes loads with a single index.
-Optimizer::PassToken CreateCommonUniformElimPass();
-
// Create aggressive dead code elimination pass
// This pass eliminates unused code from the module. In addition,
// it detects and eliminates code which may have spurious uses but which do
diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt
index 4cd8001..3e1280e 100644
--- a/source/opt/CMakeLists.txt
+++ b/source/opt/CMakeLists.txt
@@ -22,7 +22,6 @@
cfg.h
code_sink.h
combine_access_chains.h
- common_uniform_elim_pass.h
compact_ids_pass.h
composite.h
const_folding_rules.h
@@ -123,7 +122,6 @@
cfg.cpp
code_sink.cpp
combine_access_chains.cpp
- common_uniform_elim_pass.cpp
compact_ids_pass.cpp
composite.cpp
const_folding_rules.cpp
diff --git a/source/opt/common_uniform_elim_pass.cpp b/source/opt/common_uniform_elim_pass.cpp
deleted file mode 100644
index 86889a6..0000000
--- a/source/opt/common_uniform_elim_pass.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-// Copyright (c) 2017 The Khronos Group Inc.
-// Copyright (c) 2017 Valve Corporation
-// Copyright (c) 2017 LunarG Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "source/opt/common_uniform_elim_pass.h"
-#include "source/cfa.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace opt {
-
-namespace {
-
-const uint32_t kAccessChainPtrIdInIdx = 0;
-const uint32_t kTypePointerStorageClassInIdx = 0;
-const uint32_t kTypePointerTypeIdInIdx = 1;
-const uint32_t kConstantValueInIdx = 0;
-const uint32_t kExtractCompositeIdInIdx = 0;
-const uint32_t kExtractIdx0InIdx = 1;
-const uint32_t kStorePtrIdInIdx = 0;
-const uint32_t kLoadPtrIdInIdx = 0;
-const uint32_t kCopyObjectOperandInIdx = 0;
-const uint32_t kTypeIntWidthInIdx = 0;
-
-} // anonymous namespace
-
-bool CommonUniformElimPass::IsNonPtrAccessChain(const SpvOp opcode) const {
- return opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain;
-}
-
-bool CommonUniformElimPass::IsSamplerOrImageType(
- const Instruction* typeInst) const {
- switch (typeInst->opcode()) {
- case SpvOpTypeSampler:
- case SpvOpTypeImage:
- case SpvOpTypeSampledImage:
- return true;
- default:
- break;
- }
- if (typeInst->opcode() != SpvOpTypeStruct) return false;
- // Return true if any member is a sampler or image
- return !typeInst->WhileEachInId([this](const uint32_t* tid) {
- const Instruction* compTypeInst = get_def_use_mgr()->GetDef(*tid);
- if (IsSamplerOrImageType(compTypeInst)) {
- return false;
- }
- return true;
- });
-}
-
-bool CommonUniformElimPass::IsSamplerOrImageVar(uint32_t varId) const {
- const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
- assert(varInst->opcode() == SpvOpVariable);
- const uint32_t varTypeId = varInst->type_id();
- const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
- const uint32_t varPteTypeId =
- varTypeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx);
- Instruction* varPteTypeInst = get_def_use_mgr()->GetDef(varPteTypeId);
- return IsSamplerOrImageType(varPteTypeInst);
-}
-
-Instruction* CommonUniformElimPass::GetPtr(Instruction* ip, uint32_t* objId) {
- const SpvOp op = ip->opcode();
- assert(op == SpvOpStore || op == SpvOpLoad);
- *objId = ip->GetSingleWordInOperand(op == SpvOpStore ? kStorePtrIdInIdx
- : kLoadPtrIdInIdx);
- Instruction* ptrInst = get_def_use_mgr()->GetDef(*objId);
- while (ptrInst->opcode() == SpvOpCopyObject) {
- *objId = ptrInst->GetSingleWordInOperand(kCopyObjectOperandInIdx);
- ptrInst = get_def_use_mgr()->GetDef(*objId);
- }
- Instruction* objInst = ptrInst;
- while (objInst->opcode() != SpvOpVariable &&
- objInst->opcode() != SpvOpFunctionParameter) {
- if (IsNonPtrAccessChain(objInst->opcode())) {
- *objId = objInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx);
- } else {
- assert(objInst->opcode() == SpvOpCopyObject);
- *objId = objInst->GetSingleWordInOperand(kCopyObjectOperandInIdx);
- }
- objInst = get_def_use_mgr()->GetDef(*objId);
- }
- return ptrInst;
-}
-
-bool CommonUniformElimPass::IsVolatileStruct(uint32_t type_id) {
- assert(get_def_use_mgr()->GetDef(type_id)->opcode() == SpvOpTypeStruct);
- return !get_decoration_mgr()->WhileEachDecoration(
- type_id, SpvDecorationVolatile, [](const Instruction&) { return false; });
-}
-
-bool CommonUniformElimPass::IsAccessChainToVolatileStructType(
- const Instruction& AccessChainInst) {
- assert(AccessChainInst.opcode() == SpvOpAccessChain);
-
- uint32_t ptr_id = AccessChainInst.GetSingleWordInOperand(0);
- const Instruction* ptr_inst = get_def_use_mgr()->GetDef(ptr_id);
- uint32_t pointee_type_id = GetPointeeTypeId(ptr_inst);
- const uint32_t num_operands = AccessChainInst.NumOperands();
-
- // walk the type tree:
- for (uint32_t idx = 3; idx < num_operands; ++idx) {
- Instruction* pointee_type = get_def_use_mgr()->GetDef(pointee_type_id);
-
- switch (pointee_type->opcode()) {
- case SpvOpTypeMatrix:
- case SpvOpTypeVector:
- case SpvOpTypeArray:
- case SpvOpTypeRuntimeArray:
- pointee_type_id = pointee_type->GetSingleWordOperand(1);
- break;
- case SpvOpTypeStruct:
- // check for volatile decorations:
- if (IsVolatileStruct(pointee_type_id)) return true;
-
- if (idx < num_operands - 1) {
- const uint32_t index_id = AccessChainInst.GetSingleWordOperand(idx);
- const Instruction* index_inst = get_def_use_mgr()->GetDef(index_id);
- uint32_t index_value = index_inst->GetSingleWordOperand(
- 2); // TODO: replace with GetUintValueFromConstant()
- pointee_type_id = pointee_type->GetSingleWordInOperand(index_value);
- }
- break;
- default:
- assert(false && "Unhandled pointee type.");
- }
- }
- return false;
-}
-
-bool CommonUniformElimPass::IsVolatileLoad(const Instruction& loadInst) {
- assert(loadInst.opcode() == SpvOpLoad);
- // Check if this Load instruction has Volatile Memory Access flag
- if (loadInst.NumOperands() == 4) {
- uint32_t memory_access_mask = loadInst.GetSingleWordOperand(3);
- if (memory_access_mask & SpvMemoryAccessVolatileMask) return true;
- }
- // If we load a struct directly (result type is struct),
- // check if the struct is decorated volatile
- uint32_t type_id = loadInst.type_id();
- if (get_def_use_mgr()->GetDef(type_id)->opcode() == SpvOpTypeStruct)
- return IsVolatileStruct(type_id);
- else
- return false;
-}
-
-bool CommonUniformElimPass::IsUniformVar(uint32_t varId) {
- const Instruction* varInst =
- get_def_use_mgr()->id_to_defs().find(varId)->second;
- if (varInst->opcode() != SpvOpVariable) return false;
- const uint32_t varTypeId = varInst->type_id();
- const Instruction* varTypeInst =
- get_def_use_mgr()->id_to_defs().find(varTypeId)->second;
- return varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) ==
- SpvStorageClassUniform ||
- varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) ==
- SpvStorageClassUniformConstant;
-}
-
-bool CommonUniformElimPass::HasUnsupportedDecorates(uint32_t id) const {
- return !get_def_use_mgr()->WhileEachUser(id, [this](Instruction* user) {
- if (IsNonTypeDecorate(user->opcode())) return false;
- return true;
- });
-}
-
-bool CommonUniformElimPass::HasOnlyNamesAndDecorates(uint32_t id) const {
- return get_def_use_mgr()->WhileEachUser(id, [this](Instruction* user) {
- SpvOp op = user->opcode();
- if (op != SpvOpName && !IsNonTypeDecorate(op)) return false;
- return true;
- });
-}
-
-void CommonUniformElimPass::DeleteIfUseless(Instruction* inst) {
- const uint32_t resId = inst->result_id();
- assert(resId != 0);
- if (HasOnlyNamesAndDecorates(resId)) {
- context()->KillInst(inst);
- }
-}
-
-Instruction* CommonUniformElimPass::ReplaceAndDeleteLoad(Instruction* loadInst,
- uint32_t replId,
- Instruction* ptrInst) {
- const uint32_t loadId = loadInst->result_id();
- context()->KillNamesAndDecorates(loadId);
- (void)context()->ReplaceAllUsesWith(loadId, replId);
- // remove load instruction
- Instruction* next_instruction = context()->KillInst(loadInst);
- // if access chain, see if it can be removed as well
- if (IsNonPtrAccessChain(ptrInst->opcode())) DeleteIfUseless(ptrInst);
- return next_instruction;
-}
-
-void CommonUniformElimPass::GenACLoadRepl(
- const Instruction* ptrInst,
- std::vector<std::unique_ptr<Instruction>>* newInsts, uint32_t* resultId) {
- // Build and append Load
- const uint32_t ldResultId = TakeNextId();
- const uint32_t varId =
- ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx);
- const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
- assert(varInst->opcode() == SpvOpVariable);
- const uint32_t varPteTypeId = GetPointeeTypeId(varInst);
- std::vector<Operand> load_in_operands;
- load_in_operands.push_back(Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID,
- std::initializer_list<uint32_t>{varId}));
- std::unique_ptr<Instruction> newLoad(new Instruction(
- context(), SpvOpLoad, varPteTypeId, ldResultId, load_in_operands));
- get_def_use_mgr()->AnalyzeInstDefUse(&*newLoad);
- newInsts->emplace_back(std::move(newLoad));
-
- // Build and append Extract
- const uint32_t extResultId = TakeNextId();
- const uint32_t ptrPteTypeId = GetPointeeTypeId(ptrInst);
- std::vector<Operand> ext_in_opnds;
- ext_in_opnds.push_back(Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID,
- std::initializer_list<uint32_t>{ldResultId}));
- uint32_t iidIdx = 0;
- ptrInst->ForEachInId([&iidIdx, &ext_in_opnds, this](const uint32_t* iid) {
- if (iidIdx > 0) {
- const Instruction* cInst = get_def_use_mgr()->GetDef(*iid);
- uint32_t val = cInst->GetSingleWordInOperand(kConstantValueInIdx);
- ext_in_opnds.push_back(
- Operand(spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
- std::initializer_list<uint32_t>{val}));
- }
- ++iidIdx;
- });
- std::unique_ptr<Instruction> newExt(
- new Instruction(context(), SpvOpCompositeExtract, ptrPteTypeId,
- extResultId, ext_in_opnds));
- get_def_use_mgr()->AnalyzeInstDefUse(&*newExt);
- newInsts->emplace_back(std::move(newExt));
- *resultId = extResultId;
-}
-
-bool CommonUniformElimPass::IsConstantIndexAccessChain(Instruction* acp) {
- uint32_t inIdx = 0;
- return acp->WhileEachInId([&inIdx, this](uint32_t* tid) {
- if (inIdx > 0) {
- Instruction* opInst = get_def_use_mgr()->GetDef(*tid);
- if (opInst->opcode() != SpvOpConstant) return false;
- }
- ++inIdx;
- return true;
- });
-}
-
-bool CommonUniformElimPass::UniformAccessChainConvert(Function* func) {
- bool modified = false;
- for (auto bi = func->begin(); bi != func->end(); ++bi) {
- for (Instruction* inst = &*bi->begin(); inst; inst = inst->NextNode()) {
- if (inst->opcode() != SpvOpLoad) continue;
- uint32_t varId;
- Instruction* ptrInst = GetPtr(inst, &varId);
- if (!IsNonPtrAccessChain(ptrInst->opcode())) continue;
- // Do not convert nested access chains
- if (ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx) != varId)
- continue;
- if (!IsUniformVar(varId)) continue;
- if (!IsConstantIndexAccessChain(ptrInst)) continue;
- if (HasUnsupportedDecorates(inst->result_id())) continue;
- if (HasUnsupportedDecorates(ptrInst->result_id())) continue;
- if (IsVolatileLoad(*inst)) continue;
- if (IsAccessChainToVolatileStructType(*ptrInst)) continue;
- std::vector<std::unique_ptr<Instruction>> newInsts;
- uint32_t replId;
- GenACLoadRepl(ptrInst, &newInsts, &replId);
- inst = ReplaceAndDeleteLoad(inst, replId, ptrInst);
- assert(inst->opcode() != SpvOpPhi);
- inst = inst->InsertBefore(std::move(newInsts));
- modified = true;
- }
- }
- return modified;
-}
-
-void CommonUniformElimPass::ComputeStructuredSuccessors(Function* func) {
- block2structured_succs_.clear();
- for (auto& blk : *func) {
- // If header, make merge block first successor.
- uint32_t mbid = blk.MergeBlockIdIfAny();
- if (mbid != 0) {
- block2structured_succs_[&blk].push_back(cfg()->block(mbid));
- uint32_t cbid = blk.ContinueBlockIdIfAny();
- if (cbid != 0) {
- block2structured_succs_[&blk].push_back(cfg()->block(mbid));
- }
- }
- // add true successors
- const auto& const_blk = blk;
- const_blk.ForEachSuccessorLabel([&blk, this](const uint32_t sbid) {
- block2structured_succs_[&blk].push_back(cfg()->block(sbid));
- });
- }
-}
-
-void CommonUniformElimPass::ComputeStructuredOrder(
- Function* func, std::list<BasicBlock*>* order) {
- // Compute structured successors and do DFS
- ComputeStructuredSuccessors(func);
- auto ignore_block = [](cbb_ptr) {};
- auto ignore_edge = [](cbb_ptr, cbb_ptr) {};
- auto get_structured_successors = [this](const BasicBlock* block) {
- return &(block2structured_succs_[block]);
- };
- // TODO(greg-lunarg): Get rid of const_cast by making moving const
- // out of the cfa.h prototypes and into the invoking code.
- auto post_order = [&](cbb_ptr b) {
- order->push_front(const_cast<BasicBlock*>(b));
- };
-
- order->clear();
- CFA<BasicBlock>::DepthFirstTraversal(&*func->begin(),
- get_structured_successors, ignore_block,
- post_order, ignore_edge);
-}
-
-bool CommonUniformElimPass::CommonUniformLoadElimination(Function* func) {
- // Process all blocks in structured order. This is just one way (the
- // simplest?) to keep track of the most recent block outside of control
- // flow, used to copy common instructions, guaranteed to dominate all
- // following load sites.
- std::list<BasicBlock*> structuredOrder;
- ComputeStructuredOrder(func, &structuredOrder);
- uniform2load_id_.clear();
- bool modified = false;
- // Find insertion point in first block to copy non-dominating loads.
- auto insertItr = func->begin()->begin();
- while (insertItr->opcode() == SpvOpVariable ||
- insertItr->opcode() == SpvOpNop)
- ++insertItr;
- // Update insertItr until it will not be removed. Without this code,
- // ReplaceAndDeleteLoad() can set |insertItr| as a dangling pointer.
- while (IsUniformLoadToBeRemoved(&*insertItr)) ++insertItr;
- uint32_t mergeBlockId = 0;
- for (auto bi = structuredOrder.begin(); bi != structuredOrder.end(); ++bi) {
- BasicBlock* bp = *bi;
- // Check if we are exiting outermost control construct. If so, remember
- // new load insertion point. Trying to keep register pressure down.
- if (mergeBlockId == bp->id()) {
- mergeBlockId = 0;
- insertItr = bp->begin();
- while (insertItr->opcode() == SpvOpPhi) {
- ++insertItr;
- }
-
- // Update insertItr until it will not be removed. Without this code,
- // ReplaceAndDeleteLoad() can set |insertItr| as a dangling pointer.
- while (IsUniformLoadToBeRemoved(&*insertItr)) ++insertItr;
- }
- for (Instruction* inst = &*bp->begin(); inst; inst = inst->NextNode()) {
- if (inst->opcode() != SpvOpLoad) continue;
- uint32_t varId;
- Instruction* ptrInst = GetPtr(inst, &varId);
- if (ptrInst->opcode() != SpvOpVariable) continue;
- if (!IsUniformVar(varId)) continue;
- if (IsSamplerOrImageVar(varId)) continue;
- if (HasUnsupportedDecorates(inst->result_id())) continue;
- if (IsVolatileLoad(*inst)) continue;
- uint32_t replId;
- const auto uItr = uniform2load_id_.find(varId);
- if (uItr != uniform2load_id_.end()) {
- replId = uItr->second;
- } else {
- if (mergeBlockId == 0) {
- // Load is in dominating block; just remember it
- uniform2load_id_[varId] = inst->result_id();
- continue;
- } else {
- // Copy load into most recent dominating block and remember it
- replId = TakeNextId();
- std::unique_ptr<Instruction> newLoad(new Instruction(
- context(), SpvOpLoad, inst->type_id(), replId,
- {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {varId}}}));
- get_def_use_mgr()->AnalyzeInstDefUse(&*newLoad);
- insertItr = insertItr.InsertBefore(std::move(newLoad));
- ++insertItr;
- uniform2load_id_[varId] = replId;
- }
- }
- inst = ReplaceAndDeleteLoad(inst, replId, ptrInst);
- modified = true;
- }
- // If we are outside of any control construct and entering one, remember
- // the id of the merge block
- if (mergeBlockId == 0) {
- mergeBlockId = bp->MergeBlockIdIfAny();
- }
- }
- return modified;
-}
-
-bool CommonUniformElimPass::CommonUniformLoadElimBlock(Function* func) {
- bool modified = false;
- for (auto& blk : *func) {
- uniform2load_id_.clear();
- for (Instruction* inst = &*blk.begin(); inst; inst = inst->NextNode()) {
- if (inst->opcode() != SpvOpLoad) continue;
- uint32_t varId;
- Instruction* ptrInst = GetPtr(inst, &varId);
- if (ptrInst->opcode() != SpvOpVariable) continue;
- if (!IsUniformVar(varId)) continue;
- if (!IsSamplerOrImageVar(varId)) continue;
- if (HasUnsupportedDecorates(inst->result_id())) continue;
- if (IsVolatileLoad(*inst)) continue;
- uint32_t replId;
- const auto uItr = uniform2load_id_.find(varId);
- if (uItr != uniform2load_id_.end()) {
- replId = uItr->second;
- } else {
- uniform2load_id_[varId] = inst->result_id();
- continue;
- }
- inst = ReplaceAndDeleteLoad(inst, replId, ptrInst);
- modified = true;
- }
- }
- return modified;
-}
-
-bool CommonUniformElimPass::CommonExtractElimination(Function* func) {
- // Find all composite ids with duplicate extracts.
- for (auto bi = func->begin(); bi != func->end(); ++bi) {
- for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
- if (ii->opcode() != SpvOpCompositeExtract) continue;
- // TODO(greg-lunarg): Support multiple indices
- if (ii->NumInOperands() > 2) continue;
- if (HasUnsupportedDecorates(ii->result_id())) continue;
- uint32_t compId = ii->GetSingleWordInOperand(kExtractCompositeIdInIdx);
- uint32_t idx = ii->GetSingleWordInOperand(kExtractIdx0InIdx);
- comp2idx2inst_[compId][idx].push_back(&*ii);
- }
- }
- // For all defs of ids with duplicate extracts, insert new extracts
- // after def, and replace and delete old extracts
- bool modified = false;
- for (auto bi = func->begin(); bi != func->end(); ++bi) {
- for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
- const auto cItr = comp2idx2inst_.find(ii->result_id());
- if (cItr == comp2idx2inst_.end()) continue;
- for (auto idxItr : cItr->second) {
- if (idxItr.second.size() < 2) continue;
- uint32_t replId = TakeNextId();
- std::unique_ptr<Instruction> newExtract(
- idxItr.second.front()->Clone(context()));
- newExtract->SetResultId(replId);
- get_def_use_mgr()->AnalyzeInstDefUse(&*newExtract);
- ++ii;
- ii = ii.InsertBefore(std::move(newExtract));
- for (auto instItr : idxItr.second) {
- uint32_t resId = instItr->result_id();
- context()->KillNamesAndDecorates(resId);
- (void)context()->ReplaceAllUsesWith(resId, replId);
- context()->KillInst(instItr);
- }
- modified = true;
- }
- }
- }
- return modified;
-}
-
-bool CommonUniformElimPass::EliminateCommonUniform(Function* func) {
- bool modified = false;
- modified |= UniformAccessChainConvert(func);
- modified |= CommonUniformLoadElimination(func);
- modified |= CommonExtractElimination(func);
-
- modified |= CommonUniformLoadElimBlock(func);
- return modified;
-}
-
-void CommonUniformElimPass::Initialize() {
- // Clear collections.
- comp2idx2inst_.clear();
-
- // Initialize extension whitelist
- InitExtensions();
-}
-
-bool CommonUniformElimPass::AllExtensionsSupported() const {
- // If any extension not in whitelist, return false
- for (auto& ei : get_module()->extensions()) {
- const char* extName =
- reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
- if (extensions_whitelist_.find(extName) == extensions_whitelist_.end())
- return false;
- }
- return true;
-}
-
-Pass::Status CommonUniformElimPass::ProcessImpl() {
- // Assumes all control flow structured.
- // TODO(greg-lunarg): Do SSA rewrite for non-structured control flow
- if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
- return Status::SuccessWithoutChange;
- // Assumes logical addressing only
- // TODO(greg-lunarg): Add support for physical addressing
- if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
- return Status::SuccessWithoutChange;
- if (context()->get_feature_mgr()->HasCapability(
- SpvCapabilityVariablePointersStorageBuffer))
- return Status::SuccessWithoutChange;
- // Do not process if any disallowed extensions are enabled
- if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
- // Do not process if module contains OpGroupDecorate. Additional
- // support required in KillNamesAndDecorates().
- // TODO(greg-lunarg): Add support for OpGroupDecorate
- for (auto& ai : get_module()->annotations())
- if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange;
- // If non-32-bit integer type in module, terminate processing
- // TODO(): Handle non-32-bit integer constants in access chains
- for (const Instruction& inst : get_module()->types_values())
- if (inst.opcode() == SpvOpTypeInt &&
- inst.GetSingleWordInOperand(kTypeIntWidthInIdx) != 32)
- return Status::SuccessWithoutChange;
- // Process entry point functions
- ProcessFunction pfn = [this](Function* fp) {
- return EliminateCommonUniform(fp);
- };
- bool modified = context()->ProcessEntryPointCallTree(pfn);
- return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
-}
-
-CommonUniformElimPass::CommonUniformElimPass() = default;
-
-Pass::Status CommonUniformElimPass::Process() {
- Initialize();
- return ProcessImpl();
-}
-
-void CommonUniformElimPass::InitExtensions() {
- extensions_whitelist_.clear();
- extensions_whitelist_.insert({
- "SPV_AMD_shader_explicit_vertex_parameter",
- "SPV_AMD_shader_trinary_minmax",
- "SPV_AMD_gcn_shader",
- "SPV_KHR_shader_ballot",
- "SPV_AMD_shader_ballot",
- "SPV_AMD_gpu_shader_half_float",
- "SPV_KHR_shader_draw_parameters",
- "SPV_KHR_subgroup_vote",
- "SPV_KHR_16bit_storage",
- "SPV_KHR_device_group",
- "SPV_KHR_multiview",
- "SPV_NVX_multiview_per_view_attributes",
- "SPV_NV_viewport_array2",
- "SPV_NV_stereo_view_rendering",
- "SPV_NV_sample_mask_override_coverage",
- "SPV_NV_geometry_shader_passthrough",
- "SPV_AMD_texture_gather_bias_lod",
- "SPV_KHR_storage_buffer_storage_class",
- // SPV_KHR_variable_pointers
- // Currently do not support extended pointer expressions
- "SPV_AMD_gpu_shader_int16",
- "SPV_KHR_post_depth_coverage",
- "SPV_KHR_shader_atomic_counter_ops",
- "SPV_EXT_shader_stencil_export",
- "SPV_EXT_shader_viewport_index_layer",
- "SPV_AMD_shader_image_load_store_lod",
- "SPV_AMD_shader_fragment_mask",
- "SPV_EXT_fragment_fully_covered",
- "SPV_AMD_gpu_shader_half_float_fetch",
- "SPV_GOOGLE_decorate_string",
- "SPV_GOOGLE_hlsl_functionality1",
- "SPV_GOOGLE_user_type",
- "SPV_NV_shader_subgroup_partitioned",
- "SPV_EXT_descriptor_indexing",
- "SPV_NV_fragment_shader_barycentric",
- "SPV_NV_compute_shader_derivatives",
- "SPV_NV_shader_image_footprint",
- "SPV_NV_shading_rate",
- "SPV_NV_mesh_shader",
- "SPV_NV_ray_tracing",
- "SPV_EXT_fragment_invocation_density",
- });
-}
-
-} // namespace opt
-} // namespace spvtools
diff --git a/source/opt/common_uniform_elim_pass.h b/source/opt/common_uniform_elim_pass.h
deleted file mode 100644
index e6ef69c..0000000
--- a/source/opt/common_uniform_elim_pass.h
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright (c) 2016 The Khronos Group Inc.
-// Copyright (c) 2016 Valve Corporation
-// Copyright (c) 2016 LunarG Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SOURCE_OPT_COMMON_UNIFORM_ELIM_PASS_H_
-#define SOURCE_OPT_COMMON_UNIFORM_ELIM_PASS_H_
-
-#include <algorithm>
-#include <list>
-#include <map>
-#include <memory>
-#include <queue>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-#include "source/opt/basic_block.h"
-#include "source/opt/decoration_manager.h"
-#include "source/opt/def_use_manager.h"
-#include "source/opt/ir_context.h"
-#include "source/opt/module.h"
-#include "source/opt/pass.h"
-
-namespace spvtools {
-namespace opt {
-
-// See optimizer.hpp for documentation.
-class CommonUniformElimPass : public Pass {
- using cbb_ptr = const BasicBlock*;
-
- public:
- using GetBlocksFunction =
- std::function<std::vector<BasicBlock*>*(const BasicBlock*)>;
-
- CommonUniformElimPass();
-
- const char* name() const override { return "eliminate-common-uniform"; }
- Status Process() override;
-
- private:
- // Returns true if |opcode| is a non-ptr access chain op
- bool IsNonPtrAccessChain(const SpvOp opcode) const;
-
- // Returns true if |typeInst| is a sampler or image type or a struct
- // containing one, recursively.
- bool IsSamplerOrImageType(const Instruction* typeInst) const;
-
- // Returns true if |varId| is a variable containing a sampler or image.
- bool IsSamplerOrImageVar(uint32_t varId) const;
-
- // Given a load or store pointed at by |ip|, return the top-most
- // non-CopyObj in its pointer operand. Also return the base pointer
- // in |objId|.
- Instruction* GetPtr(Instruction* ip, uint32_t* objId);
-
- // Return true if variable is uniform
- bool IsUniformVar(uint32_t varId);
-
- // Given the type id for a struct type, checks if the struct type
- // or any struct member is volatile decorated
- bool IsVolatileStruct(uint32_t type_id);
-
- // Given an OpAccessChain instruction, return true
- // if the accessed variable belongs to a volatile
- // decorated object or member of a struct type
- bool IsAccessChainToVolatileStructType(const Instruction& AccessChainInst);
-
- // Given an OpLoad instruction, return true if
- // OpLoad has a Volatile Memory Access flag or if
- // the resulting type is a volatile decorated struct
- bool IsVolatileLoad(const Instruction& loadInst);
-
- // Return true if any uses of |id| are decorate ops.
- bool HasUnsupportedDecorates(uint32_t id) const;
-
- // Return true if all uses of |id| are only name or decorate ops.
- bool HasOnlyNamesAndDecorates(uint32_t id) const;
-
- // Delete inst if it has no uses. Assumes inst has a resultId.
- void DeleteIfUseless(Instruction* inst);
-
- // Replace all instances of load's id with replId and delete load
- // and its access chain, if any
- Instruction* ReplaceAndDeleteLoad(Instruction* loadInst, uint32_t replId,
- Instruction* ptrInst);
-
- // For the (constant index) access chain ptrInst, create an
- // equivalent load and extract
- void GenACLoadRepl(const Instruction* ptrInst,
- std::vector<std::unique_ptr<Instruction>>* newInsts,
- uint32_t* resultId);
-
- // Return true if all indices are constant
- bool IsConstantIndexAccessChain(Instruction* acp);
-
- // Convert all uniform access chain loads into load/extract.
- bool UniformAccessChainConvert(Function* func);
-
- // Compute structured successors for function |func|.
- // A block's structured successors are the blocks it branches to
- // together with its declared merge block if it has one.
- // When order matters, the merge block always appears first.
- // This assures correct depth first search in the presence of early
- // returns and kills. If the successor vector contain duplicates
- // if the merge block, they are safely ignored by DFS.
- //
- // TODO(dnovillo): This pass computes structured successors slightly different
- // than the implementation in class Pass. Can this be re-factored?
- void ComputeStructuredSuccessors(Function* func);
-
- // Compute structured block order for |func| into |structuredOrder|. This
- // order has the property that dominators come before all blocks they
- // dominate and merge blocks come after all blocks that are in the control
- // constructs of their header.
- //
- // TODO(dnovillo): This pass computes structured order slightly different
- // than the implementation in class Pass. Can this be re-factored?
- void ComputeStructuredOrder(Function* func, std::list<BasicBlock*>* order);
-
- // Eliminate loads of uniform variables which have previously been loaded.
- // If first load is in control flow, move it to first block of function.
- // Most effective if preceded by UniformAccessChainRemoval().
- bool CommonUniformLoadElimination(Function* func);
-
- // Eliminate loads of uniform sampler and image variables which have
- // previously
- // been loaded in the same block for types whose loads cannot cross blocks.
- bool CommonUniformLoadElimBlock(Function* func);
-
- // Eliminate duplicated extracts of same id. Extract may be moved to same
- // block as the id definition. This is primarily intended for extracts
- // from uniform loads. Most effective if preceded by
- // CommonUniformLoadElimination().
- bool CommonExtractElimination(Function* func);
-
- // For function |func|, first change all uniform constant index
- // access chain loads into equivalent composite extracts. Then consolidate
- // identical uniform loads into one uniform load. Finally, consolidate
- // identical uniform extracts into one uniform extract. This may require
- // moving a load or extract to a point which dominates all uses.
- // Return true if func is modified.
- //
- // This pass requires the function to have structured control flow ie shader
- // capability. It also requires logical addressing ie Addresses capability
- // is not enabled. It also currently does not support any extensions.
- //
- // This function currently only optimizes loads with a single index.
- bool EliminateCommonUniform(Function* func);
-
- // Initialize extensions whitelist
- void InitExtensions();
-
- // Return true if all extensions in this module are allowed by this pass.
- bool AllExtensionsSupported() const;
-
- // Return true if |op| is a decorate for non-type instruction
- inline bool IsNonTypeDecorate(uint32_t op) const {
- return (op == SpvOpDecorate || op == SpvOpDecorateId);
- }
-
- // Return true if |inst| is an instruction that loads uniform variable and
- // can be replaced with other uniform load instruction.
- bool IsUniformLoadToBeRemoved(Instruction* inst) {
- if (inst->opcode() == SpvOpLoad) {
- uint32_t varId;
- Instruction* ptrInst = GetPtr(inst, &varId);
- if (ptrInst->opcode() == SpvOpVariable && IsUniformVar(varId) &&
- !IsSamplerOrImageVar(varId) &&
- !HasUnsupportedDecorates(inst->result_id()) && !IsVolatileLoad(*inst))
- return true;
- }
- return false;
- }
-
- void Initialize();
- Pass::Status ProcessImpl();
-
- // Map from uniform variable id to its common load id
- std::unordered_map<uint32_t, uint32_t> uniform2load_id_;
-
- // Map of extract composite ids to map of indices to insts
- // TODO(greg-lunarg): Consider std::vector.
- std::unordered_map<uint32_t,
- std::unordered_map<uint32_t, std::list<Instruction*>>>
- comp2idx2inst_;
-
- // Extensions supported by this pass.
- std::unordered_set<std::string> extensions_whitelist_;
-
- // Map from block to its structured successor blocks. See
- // ComputeStructuredSuccessors() for definition.
- std::unordered_map<const BasicBlock*, std::vector<BasicBlock*>>
- block2structured_succs_;
-};
-
-} // namespace opt
-} // namespace spvtools
-
-#endif // SOURCE_OPT_COMMON_UNIFORM_ELIM_PASS_H_
diff --git a/source/opt/optimizer.cpp b/source/opt/optimizer.cpp
index 6206f64..5c1e6ca 100644
--- a/source/opt/optimizer.cpp
+++ b/source/opt/optimizer.cpp
@@ -186,8 +186,6 @@
.RegisterPass(CreateDeadBranchElimPass())
.RegisterPass(CreateBlockMergePass())
.RegisterPass(CreateSimplificationPass());
- // Currently exposing driver bugs resulting in crashes (#946)
- // .RegisterPass(CreateCommonUniformElimPass())
}
Optimizer& Optimizer::RegisterSizePasses() {
@@ -215,8 +213,6 @@
.RegisterPass(CreateDeadInsertElimPass())
.RegisterPass(CreateRedundancyEliminationPass())
.RegisterPass(CreateCFGCleanupPass())
- // Currently exposing driver bugs resulting in crashes (#946)
- // .RegisterPass(CreateCommonUniformElimPass())
.RegisterPass(CreateAggressiveDCEPass());
}
@@ -340,8 +336,6 @@
RegisterPass(CreateEliminateDeadFunctionsPass());
} else if (pass_name == "eliminate-local-multi-store") {
RegisterPass(CreateLocalMultiStoreElimPass());
- } else if (pass_name == "eliminate-common-uniform") {
- RegisterPass(CreateCommonUniformElimPass());
} else if (pass_name == "eliminate-dead-const") {
RegisterPass(CreateEliminateDeadConstantPass());
} else if (pass_name == "eliminate-dead-inserts") {
@@ -713,11 +707,6 @@
MakeUnique<opt::ProcessLinesPass>(opt::kLinesEliminateDeadLines));
}
-Optimizer::PassToken CreateCommonUniformElimPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::CommonUniformElimPass>());
-}
-
Optimizer::PassToken CreateCompactIdsPass() {
return MakeUnique<Optimizer::PassToken::Impl>(
MakeUnique<opt::CompactIdsPass>());
diff --git a/source/opt/passes.h b/source/opt/passes.h
index b7a9cb0..0a348e4 100644
--- a/source/opt/passes.h
+++ b/source/opt/passes.h
@@ -23,7 +23,6 @@
#include "source/opt/cfg_cleanup_pass.h"
#include "source/opt/code_sink.h"
#include "source/opt/combine_access_chains.h"
-#include "source/opt/common_uniform_elim_pass.h"
#include "source/opt/compact_ids_pass.h"
#include "source/opt/copy_prop_arrays.h"
#include "source/opt/dead_branch_elim_pass.h"
diff --git a/test/opt/CMakeLists.txt b/test/opt/CMakeLists.txt
index ba29cf8..246c116 100644
--- a/test/opt/CMakeLists.txt
+++ b/test/opt/CMakeLists.txt
@@ -24,7 +24,6 @@
cfg_test.cpp
code_sink_test.cpp
combine_access_chains_test.cpp
- common_uniform_elim_test.cpp
compact_ids_test.cpp
constant_manager_test.cpp
copy_prop_array_test.cpp
diff --git a/test/opt/common_uniform_elim_test.cpp b/test/opt/common_uniform_elim_test.cpp
deleted file mode 100644
index 923f786..0000000
--- a/test/opt/common_uniform_elim_test.cpp
+++ /dev/null
@@ -1,1479 +0,0 @@
-// Copyright (c) 2017 Valve Corporation
-// Copyright (c) 2017 LunarG Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <string>
-
-#include "test/opt/pass_fixture.h"
-
-namespace spvtools {
-namespace opt {
-namespace {
-
-using CommonUniformElimTest = PassTest<::testing::Test>;
-
-TEST_F(CommonUniformElimTest, Basic1) {
- // Note: This test exemplifies the following:
- // - Common uniform (%_) load floated to nearest non-controlled block
- // - Common extract (g_F) floated to non-controlled block
- // - Non-common extract (g_F2) not floated, but common uniform load shared
- //
- // #version 140
- // in vec4 BaseColor;
- // in float fi;
- //
- // layout(std140) uniform U_t
- // {
- // float g_F;
- // float g_F2;
- // } ;
- //
- // void main()
- // {
- // vec4 v = BaseColor;
- // if (fi > 0) {
- // v = v * g_F;
- // }
- // else {
- // float f2 = g_F2 - g_F;
- // v = v * f2;
- // }
- // gl_FragColor = v;
- // }
-
- const std::string predefs =
- 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 %v "v"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %f2 "f2"
-OpName %gl_FragColor "gl_FragColor"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%11 = 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
-%U_t = OpTypeStruct %float %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Function_float = OpTypePointer Function %float
-%int_1 = OpConstant %int 1
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
- const std::string before =
- R"(%main = OpFunction %void None %11
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpLoad %float %fi
-%29 = OpFOrdGreaterThan %bool %28 %float_0
-OpSelectionMerge %30 None
-OpBranchConditional %29 %31 %32
-%31 = OpLabel
-%33 = OpLoad %v4float %v
-%34 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%35 = OpLoad %float %34
-%36 = OpVectorTimesScalar %v4float %33 %35
-OpStore %v %36
-OpBranch %30
-%32 = OpLabel
-%37 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%38 = OpLoad %float %37
-%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%40 = OpLoad %float %39
-%41 = OpFSub %float %38 %40
-OpStore %f2 %41
-%42 = OpLoad %v4float %v
-%43 = OpLoad %float %f2
-%44 = OpVectorTimesScalar %v4float %42 %43
-OpStore %v %44
-OpBranch %30
-%30 = OpLabel
-%45 = OpLoad %v4float %v
-OpStore %gl_FragColor %45
-OpReturn
-OpFunctionEnd
-)";
-
- const std::string after =
- R"(%main = OpFunction %void None %11
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%52 = OpLoad %U_t %_
-%53 = OpCompositeExtract %float %52 0
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpLoad %float %fi
-%29 = OpFOrdGreaterThan %bool %28 %float_0
-OpSelectionMerge %30 None
-OpBranchConditional %29 %31 %32
-%31 = OpLabel
-%33 = OpLoad %v4float %v
-%36 = OpVectorTimesScalar %v4float %33 %53
-OpStore %v %36
-OpBranch %30
-%32 = OpLabel
-%49 = OpCompositeExtract %float %52 1
-%41 = OpFSub %float %49 %53
-OpStore %f2 %41
-%42 = OpLoad %v4float %v
-%43 = OpLoad %float %f2
-%44 = OpVectorTimesScalar %v4float %42 %43
-OpStore %v %44
-OpBranch %30
-%30 = OpLabel
-%45 = OpLoad %v4float %v
-OpStore %gl_FragColor %45
-OpReturn
-OpFunctionEnd
-)";
-
- SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
- predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, Basic2) {
- // Note: This test exemplifies the following:
- // - Common uniform (%_) load floated to nearest non-controlled block
- // - Common extract (g_F) floated to non-controlled block
- // - Non-common extract (g_F2) not floated, but common uniform load shared
- //
- // #version 140
- // in vec4 BaseColor;
- // in float fi;
- // in float fi2;
- //
- // layout(std140) uniform U_t
- // {
- // float g_F;
- // float g_F2;
- // } ;
- //
- // void main()
- // {
- // float f = fi;
- // if (f < 0)
- // f = -f;
- // if (fi2 > 0) {
- // f = f * g_F;
- // }
- // else {
- // f = g_F2 - g_F;
- // }
- // gl_FragColor = f * BaseColor;
- // }
-
- const std::string predefs =
- R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %fi %fi2 %gl_FragColor %BaseColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %f "f"
-OpName %fi "fi"
-OpName %fi2 "fi2"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %gl_FragColor "gl_FragColor"
-OpName %BaseColor "BaseColor"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%11 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_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
-%fi2 = OpVariable %_ptr_Input_float Input
-%U_t = OpTypeStruct %float %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%int_1 = OpConstant %int 1
-%v4float = OpTypeVector %float 4
-%_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
-)";
-
- const std::string before =
- R"(%main = OpFunction %void None %11
-%25 = OpLabel
-%f = OpVariable %_ptr_Function_float Function
-%26 = OpLoad %float %fi
-OpStore %f %26
-%27 = OpLoad %float %f
-%28 = OpFOrdLessThan %bool %27 %float_0
-OpSelectionMerge %29 None
-OpBranchConditional %28 %30 %29
-%30 = OpLabel
-%31 = OpLoad %float %f
-%32 = OpFNegate %float %31
-OpStore %f %32
-OpBranch %29
-%29 = OpLabel
-%33 = OpLoad %float %fi2
-%34 = OpFOrdGreaterThan %bool %33 %float_0
-OpSelectionMerge %35 None
-OpBranchConditional %34 %36 %37
-%36 = OpLabel
-%38 = OpLoad %float %f
-%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%40 = OpLoad %float %39
-%41 = OpFMul %float %38 %40
-OpStore %f %41
-OpBranch %35
-%37 = OpLabel
-%42 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%43 = OpLoad %float %42
-%44 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%45 = OpLoad %float %44
-%46 = OpFSub %float %43 %45
-OpStore %f %46
-OpBranch %35
-%35 = OpLabel
-%47 = OpLoad %v4float %BaseColor
-%48 = OpLoad %float %f
-%49 = OpVectorTimesScalar %v4float %47 %48
-OpStore %gl_FragColor %49
-OpReturn
-OpFunctionEnd
-)";
-
- const std::string after =
- R"(%main = OpFunction %void None %11
-%25 = OpLabel
-%f = OpVariable %_ptr_Function_float Function
-%26 = OpLoad %float %fi
-OpStore %f %26
-%27 = OpLoad %float %f
-%28 = OpFOrdLessThan %bool %27 %float_0
-OpSelectionMerge %29 None
-OpBranchConditional %28 %30 %29
-%30 = OpLabel
-%31 = OpLoad %float %f
-%32 = OpFNegate %float %31
-OpStore %f %32
-OpBranch %29
-%29 = OpLabel
-%56 = OpLoad %U_t %_
-%57 = OpCompositeExtract %float %56 0
-%33 = OpLoad %float %fi2
-%34 = OpFOrdGreaterThan %bool %33 %float_0
-OpSelectionMerge %35 None
-OpBranchConditional %34 %36 %37
-%36 = OpLabel
-%38 = OpLoad %float %f
-%41 = OpFMul %float %38 %57
-OpStore %f %41
-OpBranch %35
-%37 = OpLabel
-%53 = OpCompositeExtract %float %56 1
-%46 = OpFSub %float %53 %57
-OpStore %f %46
-OpBranch %35
-%35 = OpLabel
-%47 = OpLoad %v4float %BaseColor
-%48 = OpLoad %float %f
-%49 = OpVectorTimesScalar %v4float %47 %48
-OpStore %gl_FragColor %49
-OpReturn
-OpFunctionEnd
-)";
-
- SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
- predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, Basic3) {
- // Note: This test exemplifies the following:
- // - Existing common uniform (%_) load kept in place and shared
- //
- // #version 140
- // in vec4 BaseColor;
- // in float fi;
- //
- // layout(std140) uniform U_t
- // {
- // bool g_B;
- // float g_F;
- // } ;
- //
- // void main()
- // {
- // vec4 v = BaseColor;
- // if (g_B)
- // v = v * g_F;
- // gl_FragColor = v;
- // }
-
- const std::string predefs =
- R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor %fi
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_B"
-OpMemberName %U_t 1 "g_F"
-OpName %_ ""
-OpName %gl_FragColor "gl_FragColor"
-OpName %fi "fi"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%10 = 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
-%U_t = OpTypeStruct %uint %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%bool = OpTypeBool
-%uint_0 = OpConstant %uint 0
-%int_1 = OpConstant %int 1
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-)";
-
- const std::string before =
- R"(%main = OpFunction %void None %10
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
-%29 = OpLoad %uint %28
-%30 = OpINotEqual %bool %29 %uint_0
-OpSelectionMerge %31 None
-OpBranchConditional %30 %32 %31
-%32 = OpLabel
-%33 = OpLoad %v4float %v
-%34 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%35 = OpLoad %float %34
-%36 = OpVectorTimesScalar %v4float %33 %35
-OpStore %v %36
-OpBranch %31
-%31 = OpLabel
-%37 = OpLoad %v4float %v
-OpStore %gl_FragColor %37
-OpReturn
-OpFunctionEnd
-)";
-
- const std::string after =
- R"(%main = OpFunction %void None %10
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%38 = OpLoad %U_t %_
-%39 = OpCompositeExtract %uint %38 0
-%30 = OpINotEqual %bool %39 %uint_0
-OpSelectionMerge %31 None
-OpBranchConditional %30 %32 %31
-%32 = OpLabel
-%33 = OpLoad %v4float %v
-%41 = OpCompositeExtract %float %38 1
-%36 = OpVectorTimesScalar %v4float %33 %41
-OpStore %v %36
-OpBranch %31
-%31 = OpLabel
-%37 = OpLoad %v4float %v
-OpStore %gl_FragColor %37
-OpReturn
-OpFunctionEnd
-)";
-
- SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
- predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, Loop) {
- // Note: This test exemplifies the following:
- // - Common extract (g_F) shared between two loops
- // #version 140
- // in vec4 BC;
- // in vec4 BC2;
- //
- // layout(std140) uniform U_t
- // {
- // float g_F;
- // } ;
- //
- // void main()
- // {
- // vec4 v = BC;
- // for (int i = 0; i < 4; i++)
- // v[i] = v[i] / g_F;
- // vec4 v2 = BC2;
- // for (int i = 0; i < 4; i++)
- // v2[i] = v2[i] * g_F;
- // gl_FragColor = v + v2;
- // }
-
- const std::string predefs =
- R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BC %BC2 %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BC "BC"
-OpName %i "i"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpName %_ ""
-OpName %v2 "v2"
-OpName %BC2 "BC2"
-OpName %i_0 "i"
-OpName %gl_FragColor "gl_FragColor"
-OpMemberDecorate %U_t 0 Offset 0
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%13 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BC = OpVariable %_ptr_Input_v4float Input
-%int = OpTypeInt 32 1
-%_ptr_Function_int = OpTypePointer Function %int
-%int_0 = OpConstant %int 0
-%int_4 = OpConstant %int 4
-%bool = OpTypeBool
-%_ptr_Function_float = OpTypePointer Function %float
-%U_t = OpTypeStruct %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%int_1 = OpConstant %int 1
-%BC2 = 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 %13
-%28 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%i = OpVariable %_ptr_Function_int Function
-%v2 = OpVariable %_ptr_Function_v4float Function
-%i_0 = OpVariable %_ptr_Function_int Function
-%29 = OpLoad %v4float %BC
-OpStore %v %29
-OpStore %i %int_0
-OpBranch %30
-%30 = OpLabel
-OpLoopMerge %31 %32 None
-OpBranch %33
-%33 = OpLabel
-%34 = OpLoad %int %i
-%35 = OpSLessThan %bool %34 %int_4
-OpBranchConditional %35 %36 %31
-%36 = OpLabel
-%37 = OpLoad %int %i
-%38 = OpLoad %int %i
-%39 = OpAccessChain %_ptr_Function_float %v %38
-%40 = OpLoad %float %39
-%41 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%42 = OpLoad %float %41
-%43 = OpFDiv %float %40 %42
-%44 = OpAccessChain %_ptr_Function_float %v %37
-OpStore %44 %43
-OpBranch %32
-%32 = OpLabel
-%45 = OpLoad %int %i
-%46 = OpIAdd %int %45 %int_1
-OpStore %i %46
-OpBranch %30
-%31 = OpLabel
-%47 = OpLoad %v4float %BC2
-OpStore %v2 %47
-OpStore %i_0 %int_0
-OpBranch %48
-%48 = OpLabel
-OpLoopMerge %49 %50 None
-OpBranch %51
-%51 = OpLabel
-%52 = OpLoad %int %i_0
-%53 = OpSLessThan %bool %52 %int_4
-OpBranchConditional %53 %54 %49
-%54 = OpLabel
-%55 = OpLoad %int %i_0
-%56 = OpLoad %int %i_0
-%57 = OpAccessChain %_ptr_Function_float %v2 %56
-%58 = OpLoad %float %57
-%59 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%60 = OpLoad %float %59
-%61 = OpFMul %float %58 %60
-%62 = OpAccessChain %_ptr_Function_float %v2 %55
-OpStore %62 %61
-OpBranch %50
-%50 = OpLabel
-%63 = OpLoad %int %i_0
-%64 = OpIAdd %int %63 %int_1
-OpStore %i_0 %64
-OpBranch %48
-%49 = OpLabel
-%65 = OpLoad %v4float %v
-%66 = OpLoad %v4float %v2
-%67 = OpFAdd %v4float %65 %66
-OpStore %gl_FragColor %67
-OpReturn
-OpFunctionEnd
-)";
-
- const std::string after =
- R"(%main = OpFunction %void None %13
-%28 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%i = OpVariable %_ptr_Function_int Function
-%v2 = OpVariable %_ptr_Function_v4float Function
-%i_0 = OpVariable %_ptr_Function_int Function
-%72 = OpLoad %U_t %_
-%73 = OpCompositeExtract %float %72 0
-%29 = OpLoad %v4float %BC
-OpStore %v %29
-OpStore %i %int_0
-OpBranch %30
-%30 = OpLabel
-OpLoopMerge %31 %32 None
-OpBranch %33
-%33 = OpLabel
-%34 = OpLoad %int %i
-%35 = OpSLessThan %bool %34 %int_4
-OpBranchConditional %35 %36 %31
-%36 = OpLabel
-%37 = OpLoad %int %i
-%38 = OpLoad %int %i
-%39 = OpAccessChain %_ptr_Function_float %v %38
-%40 = OpLoad %float %39
-%43 = OpFDiv %float %40 %73
-%44 = OpAccessChain %_ptr_Function_float %v %37
-OpStore %44 %43
-OpBranch %32
-%32 = OpLabel
-%45 = OpLoad %int %i
-%46 = OpIAdd %int %45 %int_1
-OpStore %i %46
-OpBranch %30
-%31 = OpLabel
-%47 = OpLoad %v4float %BC2
-OpStore %v2 %47
-OpStore %i_0 %int_0
-OpBranch %48
-%48 = OpLabel
-OpLoopMerge %49 %50 None
-OpBranch %51
-%51 = OpLabel
-%52 = OpLoad %int %i_0
-%53 = OpSLessThan %bool %52 %int_4
-OpBranchConditional %53 %54 %49
-%54 = OpLabel
-%55 = OpLoad %int %i_0
-%56 = OpLoad %int %i_0
-%57 = OpAccessChain %_ptr_Function_float %v2 %56
-%58 = OpLoad %float %57
-%61 = OpFMul %float %58 %73
-%62 = OpAccessChain %_ptr_Function_float %v2 %55
-OpStore %62 %61
-OpBranch %50
-%50 = OpLabel
-%63 = OpLoad %int %i_0
-%64 = OpIAdd %int %63 %int_1
-OpStore %i_0 %64
-OpBranch %48
-%49 = OpLabel
-%65 = OpLoad %v4float %v
-%66 = OpLoad %v4float %v2
-%67 = OpFAdd %v4float %65 %66
-OpStore %gl_FragColor %67
-OpReturn
-OpFunctionEnd
-)";
-
- SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
- predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, Volatile1) {
- // Note: This test exemplifies the following:
- // - Same test as Basic1 with the exception that
- // the Load of g_F in else-branch is volatile
- // - Common uniform (%_) load floated to nearest non-controlled block
- //
- // #version 140
- // in vec4 BaseColor;
- // in float fi;
- //
- // layout(std140) uniform U_t
- // {
- // float g_F;
- // float g_F2;
- // } ;
- //
- // void main()
- // {
- // vec4 v = BaseColor;
- // if (fi > 0) {
- // v = v * g_F;
- // }
- // else {
- // float f2 = g_F2 - g_F;
- // v = v * f2;
- // }
- // gl_FragColor = v;
- // }
-
- const std::string predefs =
- 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 %v "v"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %f2 "f2"
-OpName %gl_FragColor "gl_FragColor"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%11 = 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
-%U_t = OpTypeStruct %float %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Function_float = OpTypePointer Function %float
-%int_1 = OpConstant %int 1
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
- const std::string before =
- R"(%main = OpFunction %void None %11
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpLoad %float %fi
-%29 = OpFOrdGreaterThan %bool %28 %float_0
-OpSelectionMerge %30 None
-OpBranchConditional %29 %31 %32
-%31 = OpLabel
-%33 = OpLoad %v4float %v
-%34 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%35 = OpLoad %float %34
-%36 = OpVectorTimesScalar %v4float %33 %35
-OpStore %v %36
-OpBranch %30
-%32 = OpLabel
-%37 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%38 = OpLoad %float %37
-%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%40 = OpLoad %float %39 Volatile
-%41 = OpFSub %float %38 %40
-OpStore %f2 %41
-%42 = OpLoad %v4float %v
-%43 = OpLoad %float %f2
-%44 = OpVectorTimesScalar %v4float %42 %43
-OpStore %v %44
-OpBranch %30
-%30 = OpLabel
-%45 = OpLoad %v4float %v
-OpStore %gl_FragColor %45
-OpReturn
-OpFunctionEnd
-)";
-
- const std::string after =
- R"(%main = OpFunction %void None %11
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%50 = OpLoad %U_t %_
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpLoad %float %fi
-%29 = OpFOrdGreaterThan %bool %28 %float_0
-OpSelectionMerge %30 None
-OpBranchConditional %29 %31 %32
-%31 = OpLabel
-%33 = OpLoad %v4float %v
-%47 = OpCompositeExtract %float %50 0
-%36 = OpVectorTimesScalar %v4float %33 %47
-OpStore %v %36
-OpBranch %30
-%32 = OpLabel
-%49 = OpCompositeExtract %float %50 1
-%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%40 = OpLoad %float %39 Volatile
-%41 = OpFSub %float %49 %40
-OpStore %f2 %41
-%42 = OpLoad %v4float %v
-%43 = OpLoad %float %f2
-%44 = OpVectorTimesScalar %v4float %42 %43
-OpStore %v %44
-OpBranch %30
-%30 = OpLabel
-%45 = OpLoad %v4float %v
-OpStore %gl_FragColor %45
-OpReturn
-OpFunctionEnd
-)";
-
- SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
- predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, Volatile2) {
- // Note: This test exemplifies the following:
- // - Same test as Basic1 with the exception that
- // U_t is Volatile.
- // - No optimizations are applied
- //
- // #version 430
- // in vec4 BaseColor;
- // in float fi;
- //
- // layout(std430) volatile buffer U_t
- // {
- // float g_F;
- // float g_F2;
- // };
- //
- //
- // void main(void)
- // {
- // vec4 v = BaseColor;
- // if (fi > 0) {
- // v = v * g_F;
- // } else {
- // float f2 = g_F2 - g_F;
- // v = v * f2;
- // }
- // }
-
- const std::string text =
- R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %fi
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 430
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %f2 "f2"
-OpDecorate %BaseColor Location 0
-OpDecorate %fi Location 0
-OpMemberDecorate %U_t 0 Volatile
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Volatile
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t BufferBlock
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%3 = 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
-%U_t = OpTypeStruct %float %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Function_float = OpTypePointer Function %float
-%int_1 = OpConstant %int 1
-%main = OpFunction %void None %3
-%5 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%12 = OpLoad %v4float %BaseColor
-OpStore %v %12
-%15 = OpLoad %float %fi
-%18 = OpFOrdGreaterThan %bool %15 %float_0
-OpSelectionMerge %20 None
-OpBranchConditional %18 %19 %31
-%19 = OpLabel
-%21 = OpLoad %v4float %v
-%28 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%29 = OpLoad %float %28
-%30 = OpVectorTimesScalar %v4float %21 %29
-OpStore %v %30
-OpBranch %20
-%31 = OpLabel
-%35 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%36 = OpLoad %float %35
-%37 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%38 = OpLoad %float %37
-%39 = OpFSub %float %36 %38
-OpStore %f2 %39
-%40 = OpLoad %v4float %v
-%41 = OpLoad %float %f2
-%42 = OpVectorTimesScalar %v4float %40 %41
-OpStore %v %42
-OpBranch %20
-%20 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
- Pass::Status res = std::get<1>(
- SinglePassRunAndDisassemble<CommonUniformElimPass>(text, true, false));
- EXPECT_EQ(res, Pass::Status::SuccessWithoutChange);
-}
-
-TEST_F(CommonUniformElimTest, Volatile3) {
- // Note: This test exemplifies the following:
- // - Same test as Volatile2 with the exception that
- // the nested struct S is volatile
- // - No optimizations are applied
- //
- // #version 430
- // in vec4 BaseColor;
- // in float fi;
- //
- // struct S {
- // volatile float a;
- // };
- //
- // layout(std430) buffer U_t
- // {
- // S g_F;
- // S g_F2;
- // };
- //
- //
- // void main(void)
- // {
- // vec4 v = BaseColor;
- // if (fi > 0) {
- // v = v * g_F.a;
- // } else {
- // float f2 = g_F2.a - g_F.a;
- // v = v * f2;
- // }
- // }
-
- const std::string text =
- R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %fi
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 430
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %S "S"
-OpMemberName %S 0 "a"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %f2 "f2"
-OpDecorate %BaseColor Location 0
-OpDecorate %fi Location 0
-OpMemberDecorate %S 0 Offset 0
-OpMemberDecorate %S 0 Volatile
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t BufferBlock
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%3 = 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
-%S = OpTypeStruct %float
-%U_t = OpTypeStruct %S %S
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Function_float = OpTypePointer Function %float
-%int_1 = OpConstant %int 1
-%main = OpFunction %void None %3
-%5 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%12 = OpLoad %v4float %BaseColor
-OpStore %v %12
-%15 = OpLoad %float %fi
-%18 = OpFOrdGreaterThan %bool %15 %float_0
-OpSelectionMerge %20 None
-OpBranchConditional %18 %19 %32
-%19 = OpLabel
-%21 = OpLoad %v4float %v
-%29 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %int_0
-%30 = OpLoad %float %29
-%31 = OpVectorTimesScalar %v4float %21 %30
-OpStore %v %31
-OpBranch %20
-%32 = OpLabel
-%36 = OpAccessChain %_ptr_Uniform_float %_ %int_1 %int_0
-%37 = OpLoad %float %36
-%38 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %int_0
-%39 = OpLoad %float %38
-%40 = OpFSub %float %37 %39
-OpStore %f2 %40
-%41 = OpLoad %v4float %v
-%42 = OpLoad %float %f2
-%43 = OpVectorTimesScalar %v4float %41 %42
-OpStore %v %43
-OpBranch %20
-%20 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
- Pass::Status res = std::get<1>(
- SinglePassRunAndDisassemble<CommonUniformElimPass>(text, true, false));
- EXPECT_EQ(res, Pass::Status::SuccessWithoutChange);
-}
-
-TEST_F(CommonUniformElimTest, IteratorDanglingPointer) {
- // Note: This test exemplifies the following:
- // - Existing common uniform (%_) load kept in place and shared
- //
- // #version 140
- // in vec4 BaseColor;
- // in float fi;
- //
- // layout(std140) uniform U_t
- // {
- // bool g_B;
- // float g_F;
- // } ;
- //
- // uniform float alpha;
- // uniform bool alpha_B;
- //
- // void main()
- // {
- // vec4 v = BaseColor;
- // if (g_B) {
- // v = v * g_F;
- // if (alpha_B)
- // v = v * alpha;
- // else
- // v = v * fi;
- // }
- // gl_FragColor = v;
- // }
-
- const std::string predefs =
- R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor %fi
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_B"
-OpMemberName %U_t 1 "g_F"
-OpName %alpha "alpha"
-OpName %alpha_B "alpha_B"
-OpName %_ ""
-OpName %gl_FragColor "gl_FragColor"
-OpName %fi "fi"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%12 = 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
-%U_t = OpTypeStruct %uint %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%bool = OpTypeBool
-%uint_0 = OpConstant %uint 0
-%int_1 = OpConstant %int 1
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%alpha = OpVariable %_ptr_Uniform_float Uniform
-%alpha_B = OpVariable %_ptr_Uniform_uint Uniform
-)";
-
- const std::string before =
- R"(%main = OpFunction %void None %12
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
-%29 = OpLoad %uint %28
-%30 = OpINotEqual %bool %29 %uint_0
-OpSelectionMerge %31 None
-OpBranchConditional %30 %31 %32
-%32 = OpLabel
-%47 = OpLoad %v4float %v
-OpStore %gl_FragColor %47
-OpReturn
-%31 = OpLabel
-%33 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%34 = OpLoad %float %33
-%35 = OpLoad %v4float %v
-%36 = OpVectorTimesScalar %v4float %35 %34
-OpStore %v %36
-%37 = OpLoad %uint %alpha_B
-%38 = OpIEqual %bool %37 %uint_0
-OpSelectionMerge %43 None
-OpBranchConditional %38 %43 %39
-%39 = OpLabel
-%40 = OpLoad %float %alpha
-%41 = OpLoad %v4float %v
-%42 = OpVectorTimesScalar %v4float %41 %40
-OpStore %v %42
-OpBranch %50
-%50 = OpLabel
-%51 = OpLoad %v4float %v
-OpStore %gl_FragColor %51
-OpReturn
-%43 = OpLabel
-%44 = OpLoad %float %fi
-%45 = OpLoad %v4float %v
-%46 = OpVectorTimesScalar %v4float %45 %44
-OpStore %v %46
-OpBranch %60
-%60 = OpLabel
-%61 = OpLoad %v4float %v
-OpStore %gl_FragColor %61
-OpReturn
-OpFunctionEnd
-)";
-
- const std::string after =
- R"(%main = OpFunction %void None %12
-%28 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%29 = OpLoad %v4float %BaseColor
-OpStore %v %29
-%54 = OpLoad %U_t %_
-%55 = OpCompositeExtract %uint %54 0
-%32 = OpINotEqual %bool %55 %uint_0
-OpSelectionMerge %33 None
-OpBranchConditional %32 %33 %34
-%34 = OpLabel
-%35 = OpLoad %v4float %v
-OpStore %gl_FragColor %35
-OpReturn
-%33 = OpLabel
-%58 = OpLoad %float %alpha
-%57 = OpCompositeExtract %float %54 1
-%38 = OpLoad %v4float %v
-%39 = OpVectorTimesScalar %v4float %38 %57
-OpStore %v %39
-%40 = OpLoad %uint %alpha_B
-%41 = OpIEqual %bool %40 %uint_0
-OpSelectionMerge %42 None
-OpBranchConditional %41 %42 %43
-%43 = OpLabel
-%45 = OpLoad %v4float %v
-%46 = OpVectorTimesScalar %v4float %45 %58
-OpStore %v %46
-OpBranch %47
-%47 = OpLabel
-%48 = OpLoad %v4float %v
-OpStore %gl_FragColor %48
-OpReturn
-%42 = OpLabel
-%49 = OpLoad %float %fi
-%50 = OpLoad %v4float %v
-%51 = OpVectorTimesScalar %v4float %50 %49
-OpStore %v %51
-OpBranch %52
-%52 = OpLabel
-%53 = OpLoad %v4float %v
-OpStore %gl_FragColor %53
-OpReturn
-OpFunctionEnd
-)";
-
- SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
- predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, MixedConstantAndNonConstantIndexes) {
- const std::string text = R"(
-; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Uniform
-; CHECK: %501 = OpLabel
-; CHECK: [[ld:%\w+]] = OpLoad
-; CHECK-NOT: OpCompositeExtract {{%\w+}} {{%\w+}} 0 2 484
-; CHECK: OpAccessChain {{%\w+}} [[var]] %int_0 %int_2 [[ld]]
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "ringeffectLayer_px" %gl_FragCoord %178 %182
- OpExecutionMode %4 OriginUpperLeft
- OpSource HLSL 500
- OpDecorate %_arr_v4float_uint_10 ArrayStride 16
- OpMemberDecorate %_struct_20 0 Offset 0
- OpMemberDecorate %_struct_20 1 Offset 16
- OpMemberDecorate %_struct_20 2 Offset 32
- OpMemberDecorate %_struct_21 0 Offset 0
- OpDecorate %_struct_21 Block
- OpDecorate %23 DescriptorSet 0
- OpDecorate %gl_FragCoord BuiltIn FragCoord
- OpDecorate %178 Location 0
- OpDecorate %182 Location 0
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %float = OpTypeFloat 32
- %v4float = OpTypeVector %float 4
- %v2float = OpTypeVector %float 2
-%_ptr_Function_v2float = OpTypePointer Function %v2float
- %uint = OpTypeInt 32 0
- %uint_10 = OpConstant %uint 10
-%_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10
- %_struct_20 = OpTypeStruct %v4float %v4float %_arr_v4float_uint_10
- %_struct_21 = OpTypeStruct %_struct_20
-%_ptr_Uniform__struct_21 = OpTypePointer Uniform %_struct_21
- %23 = OpVariable %_ptr_Uniform__struct_21 Uniform
- %int = OpTypeInt 32 1
- %int_0 = OpConstant %int 0
-%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
-%_ptr_Uniform_float = OpTypePointer Uniform %float
- %uint_3 = OpConstant %uint 3
-%_ptr_Function_v4float = OpTypePointer Function %v4float
- %float_0 = OpConstant %float 0
- %43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
-%_ptr_Function_int = OpTypePointer Function %int
- %int_5 = OpConstant %int 5
- %bool = OpTypeBool
- %int_1 = OpConstant %int 1
- %int_2 = OpConstant %int 2
- %uint_5 = OpConstant %uint 5
-%_arr_v2float_uint_5 = OpTypeArray %v2float %uint_5
-%_ptr_Function__arr_v2float_uint_5 = OpTypePointer Function %_arr_v2float_uint_5
- %82 = OpTypeImage %float 2D 0 0 0 1 Unknown
-%_ptr_UniformConstant_82 = OpTypePointer UniformConstant %82
- %86 = OpTypeSampler
-%_ptr_UniformConstant_86 = OpTypePointer UniformConstant %86
- %90 = OpTypeSampledImage %82
- %v3float = OpTypeVector %float 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
- %178 = OpVariable %_ptr_Input_v4float Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
- %182 = OpVariable %_ptr_Output_v4float Output
- %4 = OpFunction %void None %3
- %5 = OpLabel
- %483 = OpVariable %_ptr_Function_v4float Function
- %484 = OpVariable %_ptr_Function_int Function
- %486 = OpVariable %_ptr_Function__arr_v2float_uint_5 Function
- %179 = OpLoad %v4float %178
- %493 = OpAccessChain %_ptr_Uniform_float %23 %int_0 %int_0 %uint_3
- %494 = OpLoad %float %493
- OpStore %483 %43
- OpStore %484 %int_0
- OpBranch %495
- %495 = OpLabel
- OpLoopMerge %496 %497 None
- OpBranch %498
- %498 = OpLabel
- %499 = OpLoad %int %484
- %500 = OpSLessThan %bool %499 %int_5
- OpBranchConditional %500 %501 %496
- %501 = OpLabel
- %504 = OpVectorShuffle %v2float %179 %179 0 1
- %505 = OpLoad %int %484
- %506 = OpAccessChain %_ptr_Uniform_v4float %23 %int_0 %int_2 %505
- %507 = OpLoad %v4float %506
- %508 = OpVectorShuffle %v2float %507 %507 0 1
- %509 = OpFAdd %v2float %504 %508
- %512 = OpAccessChain %_ptr_Uniform_v4float %23 %int_0 %int_1
- %513 = OpLoad %v4float %512
- %514 = OpVectorShuffle %v2float %513 %513 0 1
- %517 = OpVectorShuffle %v2float %513 %513 2 3
- %518 = OpExtInst %v2float %1 FClamp %509 %514 %517
- %519 = OpAccessChain %_ptr_Function_v2float %486 %505
- OpStore %519 %518
- OpBranch %497
- %497 = OpLabel
- %520 = OpLoad %int %484
- %521 = OpIAdd %int %520 %int_1
- OpStore %484 %521
- OpBranch %495
- %496 = OpLabel
- OpReturn
- OpFunctionEnd
-)";
-
- SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
- SinglePassRunAndMatch<CommonUniformElimPass>(text, true);
-}
-
-TEST_F(CommonUniformElimTest, LoadPlacedAfterPhi) {
- const std::string text = R"(
-; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Uniform
-; CHECK: OpSelectionMerge [[merge:%\w+]]
-; CHECK: [[merge]] = OpLabel
-; CHECK-NEXT: OpPhi
-; CHECK-NEXT: OpLoad {{%\w+}} [[var]]
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %2 "main"
- OpExecutionMode %2 OriginUpperLeft
- OpSource ESSL 310
- OpMemberDecorate %_struct_3 0 Offset 0
- OpDecorate %_struct_3 Block
- OpDecorate %4 DescriptorSet 0
- OpDecorate %4 Binding 0
- %void = OpTypeVoid
- %6 = OpTypeFunction %void
- %bool = OpTypeBool
- %false = OpConstantFalse %bool
- %uint = OpTypeInt 32 0
- %v2uint = OpTypeVector %uint 2
- %_struct_3 = OpTypeStruct %v2uint
-%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
- %4 = OpVariable %_ptr_Uniform__struct_3 Uniform
- %uint_0 = OpConstant %uint 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
- %uint_2 = OpConstant %uint 2
- %2 = OpFunction %void None %6
- %15 = OpLabel
- OpSelectionMerge %16 None
- OpBranchConditional %false %17 %16
- %17 = OpLabel
- OpBranch %16
- %16 = OpLabel
- %18 = OpPhi %bool %false %15 %false %17
- OpSelectionMerge %19 None
- OpBranchConditional %false %20 %21
- %20 = OpLabel
- %22 = OpAccessChain %_ptr_Uniform_uint %4 %uint_0 %uint_0
- %23 = OpLoad %uint %22
- OpBranch %19
- %21 = OpLabel
- OpBranch %19
- %19 = OpLabel
- OpReturn
- OpFunctionEnd
-)";
-
- SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
- SinglePassRunAndMatch<CommonUniformElimPass>(text, true);
-}
-
-TEST_F(CommonUniformElimTest, TestVariablePointer) {
- // Same test a basic1 except the variable pointers capability has been added.
- // This should stop the transformation from running.
- const std::string test =
- R"(OpCapability Shader
-OpCapability VariablePointers
-%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 %v "v"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %f2 "f2"
-OpName %gl_FragColor "gl_FragColor"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%11 = 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
-%U_t = OpTypeStruct %float %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Function_float = OpTypePointer Function %float
-%int_1 = OpConstant %int 1
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-%main = OpFunction %void None %11
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpLoad %float %fi
-%29 = OpFOrdGreaterThan %bool %28 %float_0
-OpSelectionMerge %30 None
-OpBranchConditional %29 %31 %32
-%31 = OpLabel
-%33 = OpLoad %v4float %v
-%34 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%35 = OpLoad %float %34
-%36 = OpVectorTimesScalar %v4float %33 %35
-OpStore %v %36
-OpBranch %30
-%32 = OpLabel
-%37 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%38 = OpLoad %float %37
-%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%40 = OpLoad %float %39
-%41 = OpFSub %float %38 %40
-OpStore %f2 %41
-%42 = OpLoad %v4float %v
-%43 = OpLoad %float %f2
-%44 = OpVectorTimesScalar %v4float %42 %43
-OpStore %v %44
-OpBranch %30
-%30 = OpLabel
-%45 = OpLoad %v4float %v
-OpStore %gl_FragColor %45
-OpReturn
-OpFunctionEnd
-)";
-
- SinglePassRunAndCheck<CommonUniformElimPass>(test, test, true, true);
-}
-
-// TODO(greg-lunarg): Add tests to verify handling of these cases:
-//
-// Disqualifying cases: extensions, decorations, non-logical addressing,
-// non-structured control flow
-// Others?
-
-} // namespace
-} // namespace opt
-} // namespace spvtools
diff --git a/test/opt/optimizer_test.cpp b/test/opt/optimizer_test.cpp
index b427804..ee6e949 100644
--- a/test/opt/optimizer_test.cpp
+++ b/test/opt/optimizer_test.cpp
@@ -163,7 +163,6 @@
"--eliminate-dead-branches",
"--eliminate-dead-functions",
"--eliminate-local-multi-store",
- "--eliminate-common-uniform",
"--eliminate-dead-const",
"--eliminate-dead-inserts",
"--eliminate-dead-variables",
diff --git a/test/tools/opt/flags.py b/test/tools/opt/flags.py
index ca873c7..07e4e3e 100644
--- a/test/tools/opt/flags.py
+++ b/test/tools/opt/flags.py
@@ -59,7 +59,7 @@
flags = [
'--ccp', '--cfg-cleanup', '--combine-access-chains', '--compact-ids',
'--convert-local-access-chains', '--copy-propagate-arrays',
- '--eliminate-common-uniform', '--eliminate-dead-branches',
+ '--eliminate-dead-branches',
'--eliminate-dead-code-aggressive', '--eliminate-dead-const',
'--eliminate-dead-functions', '--eliminate-dead-inserts',
'--eliminate-dead-variables', '--eliminate-insert-extract',
@@ -82,7 +82,6 @@
'compact-ids',
'convert-local-access-chains',
'copy-propagate-arrays',
- 'eliminate-common-uniform',
'eliminate-dead-branches',
'eliminate-dead-code-aggressive',
'eliminate-dead-const',
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index d29b8a0..a09b888 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -147,13 +147,6 @@
around known issues with some Vulkan drivers for initialize
variables.)");
printf(R"(
- --eliminate-common-uniform
- Perform load/load elimination for duplicate uniform values.
- Converts any constant index access chain uniform loads into
- its equivalent load and extract. Some loads will be moved
- to facilitate sharing. Performed only on entry point
- call tree functions.)");
- printf(R"(
--eliminate-dead-branches
Convert conditional branches with constant condition to the
indicated unconditional brranch. Delete all resulting dead