Pass::Status CommonUniformElimPass::ProcessImpl() { // Assumes all control flow structured. // TODO(greg-lunarg): Do SSA rewrite for non-structured control flow if (!module_->HasCapability(SpvCapabilityShader)) return Status::SuccessWithoutChange; // Assumes logical addressing only // TODO(greg-lunarg): Add support for physical addressing if (module_->HasCapability(SpvCapabilityAddresses)) 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 : 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 ir::Instruction& inst : module_->types_values()) if (inst.opcode() == SpvOpTypeInt && inst.GetSingleWordInOperand(kTypeIntWidthInIdx) != 32) return Status::SuccessWithoutChange; // Process entry point functions ProcessFunction pfn = [this](ir::Function* fp) { return EliminateCommonUniform(fp); }; bool modified = ProcessEntryPointCallTree(pfn, module_); FinalizeNextId(module_); return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; }
Pass::Status LocalAccessChainConvertPass::ProcessImpl() { // If non-32-bit integer type in module, terminate processing // TODO(): Handle non-32-bit integer constants in access chains for (const ir::Instruction& inst : module_->types_values()) if (inst.opcode() == SpvOpTypeInt && inst.GetSingleWordInOperand(kTypeIntWidthInIdx) != 32) 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 : module_->annotations()) if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange; // Do not process if any disallowed extensions are enabled if (!AllExtensionsSupported()) return Status::SuccessWithoutChange; // Collect all named and decorated ids FindNamedOrDecoratedIds(); // Process all entry point functions. ProcessFunction pfn = [this](ir::Function* fp) { return ConvertLocalAccessChains(fp); }; bool modified = ProcessEntryPointCallTree(pfn, module_); FinalizeNextId(module_); return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; }
Pass::Status AggressiveDCEPass::ProcessImpl() { // Current functionality assumes shader capability // TODO(greg-lunarg): Handle additional capabilities if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader)) return Status::SuccessWithoutChange; // Current functionality assumes relaxed logical addressing (see // instruction.h) // TODO(greg-lunarg): Handle non-logical addressing if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses)) return Status::SuccessWithoutChange; // The variable pointer extension is no longer needed to use the capability, // so we have to look for the capability. if (context()->get_feature_mgr()->HasCapability( SpvCapabilityVariablePointersStorageBuffer)) return Status::SuccessWithoutChange; // If any extensions in the module are not explicitly supported, // return unmodified. if (!AllExtensionsSupported()) return Status::SuccessWithoutChange; // If the decoration manager is kept live then the context will try to keep it // up to date. ADCE deals with group decorations by changing the operands in // |OpGroupDecorate| instruction directly without informing the decoration // manager. This can put it in an invalid state which will cause an error // when the context tries to update it. To avoid this problem invalidate // the decoration manager upfront. context()->InvalidateAnalyses(IRContext::Analysis::kAnalysisDecorations); // Eliminate Dead functions. bool modified = EliminateDeadFunctions(); InitializeModuleScopeLiveInstructions(); // Process all entry point functions. ProcessFunction pfn = [this](Function* fp) { return AggressiveDCE(fp); }; modified |= context()->ProcessEntryPointCallTree(pfn); // Process module-level instructions. Now that all live instructions have // been marked, it is safe to remove dead global values. modified |= ProcessGlobalValues(); // Kill all dead instructions. for (auto inst : to_kill_) { context()->KillInst(inst); } // Cleanup all CFG including all unreachable blocks. ProcessFunction cleanup = [this](Function* f) { return CFGCleanup(f); }; modified |= context()->ProcessEntryPointCallTree(cleanup); return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; }
Pass::Status LocalSingleBlockLoadStoreElimPass::ProcessImpl() { // Assumes relaxed logical addressing only (see instruction.h). if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses)) 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 any extensions in the module are not explicitly supported, // return unmodified. if (!AllExtensionsSupported()) return Status::SuccessWithoutChange; // Process all entry point functions ProcessFunction pfn = [this](Function* fp) { return LocalSingleBlockLoadStoreElim(fp); }; bool modified = context()->ProcessEntryPointCallTree(pfn); return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; }