Skip to content

Commit

Permalink
Add the IRContext (part 1)
Browse files Browse the repository at this point in the history
This is the first part of adding the IRContext.  This class is meant to
hold the extra data that is build on top of the module that it
owns.

The first part will simply create the IRContext class and get it passed
to the passes in place of the module.  For now it does not have any
functionality of its own, but it acts more as a wrapper for the module.

The functions that I added to the IRContext are those that either
traverse the headers or add to them.  I did this because we may decide
to have other ways of dealing with these sections (for example adding a
type pool, or use the decoration manager).

I also added the function that add to the header because the IRContext
needs to know when an instruction is added to update other data
structures appropriately.

Note that there is still lots of work that needs to be done.  There are
still many places that change the module, and do not inform the context.
That will be the next step.
  • Loading branch information
s-perron committed Oct 31, 2017
1 parent d861cef commit 476cae6
Show file tree
Hide file tree
Showing 66 changed files with 604 additions and 246 deletions.
45 changes: 23 additions & 22 deletions source/link/linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ static spv_result_t MergeModules(
// TODO(pierremoreau): What should be the proper behaviour with built-in
// symbols?
static spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
const Module& linked_module,
const ir::IRContext& linked_context,
const DefUseManager& def_use_manager,
const DecorationManager& decoration_manager,
LinkageTable* linkings_to_do);
Expand Down Expand Up @@ -135,7 +135,7 @@ static spv_result_t CheckImportExportCompatibility(
static spv_result_t RemoveLinkageSpecificInstructions(
const MessageConsumer& consumer, bool create_executable,
const LinkageTable& linkings_to_do, DecorationManager* decoration_manager,
Module* linked_module);
ir::IRContext* linked_context);

// Structs for holding the data members for SpvLinker.
struct Linker::Impl {
Expand Down Expand Up @@ -224,13 +224,14 @@ spv_result_t Linker::Link(const uint32_t* const* binaries,
libspirv::AssemblyGrammar grammar(impl_->context);
res = MergeModules(consumer, modules, grammar, linked_module.get());
if (res != SPV_SUCCESS) return res;
ir::IRContext linked_context(std::move(linked_module));

DefUseManager def_use_manager(consumer, linked_module.get());
DefUseManager def_use_manager(consumer, linked_context.module());

// Phase 4: Find the import/export pairs
LinkageTable linkings_to_do;
DecorationManager decoration_manager(linked_module.get());
res = GetImportExportPairs(consumer, *linked_module, def_use_manager,
DecorationManager decoration_manager(linked_context.module());
res = GetImportExportPairs(consumer, linked_context, def_use_manager,
decoration_manager, &linkings_to_do);
if (res != SPV_SUCCESS) return res;

Expand All @@ -243,30 +244,30 @@ spv_result_t Linker::Link(const uint32_t* const* binaries,
PassManager manager;
manager.SetMessageConsumer(consumer);
manager.AddPass<RemoveDuplicatesPass>();
opt::Pass::Status pass_res = manager.Run(linked_module.get());
opt::Pass::Status pass_res = manager.Run(&linked_context);
if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;

// Phase 7: Remove linkage specific instructions, such as import/export
// attributes, linkage capability, etc. if applicable
res = RemoveLinkageSpecificInstructions(consumer, !options.GetCreateLibrary(),
linkings_to_do, &decoration_manager,
linked_module.get());
&linked_context);
if (res != SPV_SUCCESS) return res;

// Phase 8: Rematch import variables/functions to export variables/functions
// TODO(pierremoreau): Keep the previous DefUseManager up-to-date
DefUseManager def_use_manager2(consumer, linked_module.get());
DefUseManager def_use_manager2(consumer, linked_context.module());
for (const auto& linking_entry : linkings_to_do)
def_use_manager2.ReplaceAllUsesWith(linking_entry.imported_symbol.id,
linking_entry.exported_symbol.id);

// Phase 9: Compact the IDs used in the module
manager.AddPass<opt::CompactIdsPass>();
pass_res = manager.Run(linked_module.get());
pass_res = manager.Run(&linked_context);
if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;

// Phase 10: Output the module
linked_module->ToBinary(&linked_binary, true);
linked_context.module()->ToBinary(&linked_binary, true);

return SPV_SUCCESS;
}
Expand Down Expand Up @@ -476,7 +477,7 @@ static spv_result_t MergeModules(
}

static spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
const Module& linked_module,
const ir::IRContext& linked_context,
const DefUseManager& def_use_manager,
const DecorationManager& decoration_manager,
LinkageTable* linkings_to_do) {
Expand All @@ -491,7 +492,7 @@ static spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
std::unordered_map<std::string, std::vector<LinkageSymbolInfo>> exports;

// Figure out the imports and exports
for (const auto& decoration : linked_module.annotations()) {
for (const auto& decoration : linked_context.annotations()) {
if (decoration.opcode() != SpvOpDecorate ||
decoration.GetSingleWordInOperand(1u) != SpvDecorationLinkageAttributes)
continue;
Expand Down Expand Up @@ -532,8 +533,8 @@ static spv_result_t GetImportExportPairs(const MessageConsumer& consumer,

// range-based for loop calls begin()/end(), but never cbegin()/cend(),
// which will not work here.
for (auto func_iter = linked_module.cbegin();
func_iter != linked_module.cend(); ++func_iter) {
for (auto func_iter = linked_context.module()->cbegin();
func_iter != linked_context.module()->cend(); ++func_iter) {
if (func_iter->result_id() != id) continue;
func_iter->ForEachParam([&symbol_info](const Instruction* inst) {
symbol_info.parameter_ids.push_back(inst->result_id());
Expand Down Expand Up @@ -628,7 +629,7 @@ static spv_result_t CheckImportExportCompatibility(
static spv_result_t RemoveLinkageSpecificInstructions(
const MessageConsumer& consumer, bool create_executable,
const LinkageTable& linkings_to_do, DecorationManager* decoration_manager,
Module* linked_module) {
ir::IRContext* linked_context) {
spv_position_t position = {};

if (decoration_manager == nullptr)
Expand All @@ -638,7 +639,7 @@ static spv_result_t RemoveLinkageSpecificInstructions(
"should "
"not "
"be empty.";
if (linked_module == nullptr)
if (linked_context == nullptr)
return libspirv::DiagnosticStream(position, consumer,
SPV_ERROR_INVALID_DATA)
<< "|linked_module| of RemoveLinkageSpecificInstructions should not "
Expand Down Expand Up @@ -670,8 +671,8 @@ static spv_result_t RemoveLinkageSpecificInstructions(

// Remove prototypes of imported functions
for (const auto& linking_entry : linkings_to_do) {
for (auto func_iter = linked_module->begin();
func_iter != linked_module->end();) {
for (auto func_iter = linked_context->module()->begin();
func_iter != linked_context->module()->end();) {
if (func_iter->result_id() == linking_entry.imported_symbol.id)
func_iter = func_iter.Erase();
else
Expand All @@ -681,12 +682,12 @@ static spv_result_t RemoveLinkageSpecificInstructions(

// Remove declarations of imported variables
for (const auto& linking_entry : linkings_to_do) {
for (auto& inst : linked_module->types_values())
for (auto& inst : linked_context->types_values())
if (inst.result_id() == linking_entry.imported_symbol.id) inst.ToNop();
}

// Remove import linkage attributes
for (auto& inst : linked_module->annotations())
for (auto& inst : linked_context->annotations())
if (inst.opcode() == SpvOpDecorate &&
inst.GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
inst.GetSingleWordOperand(3u) == SpvLinkageTypeImport)
Expand All @@ -695,13 +696,13 @@ static spv_result_t RemoveLinkageSpecificInstructions(
// Remove export linkage attributes and Linkage capability if making an
// executable
if (create_executable) {
for (auto& inst : linked_module->annotations())
for (auto& inst : linked_context->annotations())
if (inst.opcode() == SpvOpDecorate &&
inst.GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
inst.GetSingleWordOperand(3u) == SpvLinkageTypeExport)
inst.ToNop();

for (auto& inst : linked_module->capabilities())
for (auto& inst : linked_context->capabilities())
if (inst.GetSingleWordInOperand(0u) == SpvCapabilityLinkage) {
inst.ToNop();
// The RemoveDuplicatesPass did remove duplicated capabilities, so we
Expand Down
5 changes: 4 additions & 1 deletion source/opt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ add_library(SPIRV-Tools-opt
insert_extract_elim.h
instruction.h
ir_loader.h
ir_context.h
local_access_chain_convert_pass.h
local_single_block_elim_pass.h
local_single_store_elim_pass.h
Expand Down Expand Up @@ -80,6 +81,7 @@ add_library(SPIRV-Tools-opt
insert_extract_elim.cpp
instruction.cpp
ir_loader.cpp
ir_context.cpp
local_access_chain_convert_pass.cpp
local_single_block_elim_pass.cpp
local_single_store_elim_pass.cpp
Expand All @@ -97,7 +99,8 @@ add_library(SPIRV-Tools-opt
types.cpp
type_manager.cpp
unify_const_pass.cpp
instruction_list.cpp)
instruction_list.cpp
)

spvtools_default_compile_options(SPIRV-Tools-opt)
target_include_directories(SPIRV-Tools-opt
Expand Down
10 changes: 5 additions & 5 deletions source/opt/aggressive_dead_code_elim_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,9 +395,9 @@ bool AggressiveDCEPass::AggressiveDCE(ir::Function* func) {
return modified;
}

void AggressiveDCEPass::Initialize(ir::Module* module) {
InitializeProcessing(module);
InitializeCFGCleanup(module);
void AggressiveDCEPass::Initialize(ir::IRContext* c) {
InitializeProcessing(c);
InitializeCFGCleanup(c);

// Clear collections
worklist_ = std::queue<ir::Instruction*>{};
Expand Down Expand Up @@ -436,8 +436,8 @@ Pass::Status AggressiveDCEPass::ProcessImpl() {

AggressiveDCEPass::AggressiveDCEPass() {}

Pass::Status AggressiveDCEPass::Process(ir::Module* module) {
Initialize(module);
Pass::Status AggressiveDCEPass::Process(ir::IRContext* c) {
Initialize(c);
return ProcessImpl();
}

Expand Down
4 changes: 2 additions & 2 deletions source/opt/aggressive_dead_code_elim_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class AggressiveDCEPass : public MemPass {

AggressiveDCEPass();
const char* name() const override { return "eliminate-dead-code-aggressive"; }
Status Process(ir::Module*) override;
Status Process(ir::IRContext* c) override;

private:
// Return true if |varId| is variable of |storageClass|.
Expand Down Expand Up @@ -127,7 +127,7 @@ class AggressiveDCEPass : public MemPass {
// TODO(): Remove useless control constructs.
bool AggressiveDCE(ir::Function* func);

void Initialize(ir::Module* module);
void Initialize(ir::IRContext* c);
Pass::Status ProcessImpl();

// True if current function has a call instruction contained in it
Expand Down
9 changes: 5 additions & 4 deletions source/opt/block_merge_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "block_merge_pass.h"

#include "iterator.h"
#include "ir_context.h"

namespace spvtools {
namespace opt {
Expand Down Expand Up @@ -94,8 +95,8 @@ bool BlockMergePass::MergeBlocks(ir::Function* func) {
return modified;
}

void BlockMergePass::Initialize(ir::Module* module) {
InitializeProcessing(module);
void BlockMergePass::Initialize(ir::IRContext* c) {
InitializeProcessing(c);

// Initialize extension whitelist
InitExtensions();
Expand Down Expand Up @@ -126,8 +127,8 @@ Pass::Status BlockMergePass::ProcessImpl() {

BlockMergePass::BlockMergePass() {}

Pass::Status BlockMergePass::Process(ir::Module* module) {
Initialize(module);
Pass::Status BlockMergePass::Process(ir::IRContext* c) {
Initialize(c);
return ProcessImpl();
}

Expand Down
5 changes: 3 additions & 2 deletions source/opt/block_merge_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "def_use_manager.h"
#include "module.h"
#include "pass.h"
#include "ir_context.h"

namespace spvtools {
namespace opt {
Expand All @@ -37,7 +38,7 @@ class BlockMergePass : public Pass {
public:
BlockMergePass();
const char* name() const override { return "merge-blocks"; }
Status Process(ir::Module*) override;
Status Process(ir::IRContext*) override;

private:
// Return true if |labId| has multiple refs. Do not count OpName.
Expand All @@ -56,7 +57,7 @@ class BlockMergePass : public Pass {
// Return true if all extensions in this module are allowed by this pass.
bool AllExtensionsSupported() const;

void Initialize(ir::Module* module);
void Initialize(ir::IRContext* c);
Pass::Status ProcessImpl();

// Extensions supported by this pass.
Expand Down
12 changes: 6 additions & 6 deletions source/opt/cfg_cleanup_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@
namespace spvtools {
namespace opt {

void CFGCleanupPass::Initialize(ir::Module* module) {
InitializeProcessing(module);
InitializeCFGCleanup(module);
void CFGCleanupPass::Initialize(ir::IRContext* c) {
InitializeProcessing(c);
InitializeCFGCleanup(c);
}

Pass::Status CFGCleanupPass::Process(ir::Module* module) {
Initialize(module);
Pass::Status CFGCleanupPass::Process(ir::IRContext* c) {
Initialize(c);

// Process all entry point functions.
ProcessFunction pfn = [this](ir::Function* fp) { return CFGCleanup(fp); };
bool modified = ProcessReachableCallTree(pfn, module);
bool modified = ProcessReachableCallTree(pfn, context());
return modified ? Pass::Status::SuccessWithChange
: Pass::Status::SuccessWithoutChange;
}
Expand Down
4 changes: 2 additions & 2 deletions source/opt/cfg_cleanup_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ class CFGCleanupPass : public MemPass {
public:
CFGCleanupPass() = default;
const char* name() const override { return "cfg-cleanup"; }
Status Process(ir::Module*) override;
Status Process(ir::IRContext* c) override;

private:
// Initialize the pass.
void Initialize(ir::Module* module);
void Initialize(ir::IRContext* c);
};

} // namespace opt
Expand Down
9 changes: 5 additions & 4 deletions source/opt/common_uniform_elim_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "common_uniform_elim_pass.h"
#include "cfa.h"
#include "ir_context.h"

namespace spvtools {
namespace opt {
Expand Down Expand Up @@ -542,8 +543,8 @@ bool CommonUniformElimPass::EliminateCommonUniform(ir::Function* func) {
return modified;
}

void CommonUniformElimPass::Initialize(ir::Module* module) {
InitializeProcessing(module);
void CommonUniformElimPass::Initialize(ir::IRContext* c) {
InitializeProcessing(c);

// Clear collections.
comp2idx2inst_.clear();
Expand Down Expand Up @@ -598,8 +599,8 @@ Pass::Status CommonUniformElimPass::ProcessImpl() {

CommonUniformElimPass::CommonUniformElimPass() {}

Pass::Status CommonUniformElimPass::Process(ir::Module* module) {
Initialize(module);
Pass::Status CommonUniformElimPass::Process(ir::IRContext* c) {
Initialize(c);
return ProcessImpl();
}

Expand Down
5 changes: 3 additions & 2 deletions source/opt/common_uniform_elim_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "module.h"
#include "basic_block.h"
#include "pass.h"
#include "ir_context.h"

namespace spvtools {
namespace opt {
Expand All @@ -43,7 +44,7 @@ class CommonUniformElimPass : public Pass {

CommonUniformElimPass();
const char* name() const override { return "eliminate-common-uniform"; }
Status Process(ir::Module*) override;
Status Process(ir::IRContext*) override;

private:
// Returns true if |opcode| is a non-ptr access chain op
Expand Down Expand Up @@ -173,7 +174,7 @@ class CommonUniformElimPass : public Pass {
return (op == SpvOpDecorate || op == SpvOpDecorateId);
}

void Initialize(ir::Module* module);
void Initialize(ir::IRContext* c);
Pass::Status ProcessImpl();

// Decorations for the module we are processing
Expand Down
Loading

0 comments on commit 476cae6

Please sign in to comment.