Merge branch 'topo' into loopgen-after-readable-order
This commit is contained in:
@@ -53,12 +53,15 @@
|
||||
#include "spirv.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace spv {
|
||||
|
||||
class Block;
|
||||
class Function;
|
||||
class Module;
|
||||
|
||||
@@ -75,8 +78,8 @@ const MemorySemanticsMask MemorySemanticsAllMemory = (MemorySemanticsMask)0x3FF;
|
||||
|
||||
class Instruction {
|
||||
public:
|
||||
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode) { }
|
||||
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode) { }
|
||||
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { }
|
||||
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { }
|
||||
virtual ~Instruction() {}
|
||||
void addIdOperand(Id id) { operands.push_back(id); }
|
||||
void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); }
|
||||
@@ -107,6 +110,8 @@ public:
|
||||
addImmediateOperand(word);
|
||||
}
|
||||
}
|
||||
void setBlock(Block* b) { block = b; }
|
||||
Block* getBlock() const { return block; }
|
||||
Op getOpCode() const { return opCode; }
|
||||
int getNumOperands() const { return (int)operands.size(); }
|
||||
Id getResultId() const { return resultId; }
|
||||
@@ -145,6 +150,7 @@ protected:
|
||||
Op opCode;
|
||||
std::vector<Id> operands;
|
||||
std::string originalString; // could be optimized away; convenience for getting string operand
|
||||
Block* block;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -156,18 +162,31 @@ public:
|
||||
Block(Id id, Function& parent);
|
||||
virtual ~Block()
|
||||
{
|
||||
// TODO: free instructions
|
||||
}
|
||||
|
||||
|
||||
Id getId() { return instructions.front()->getResultId(); }
|
||||
|
||||
Function& getParent() const { return parent; }
|
||||
void addInstruction(Instruction* inst);
|
||||
void addPredecessor(Block* pred) { predecessors.push_back(pred); }
|
||||
void addLocalVariable(Instruction* inst) { localVariables.push_back(inst); }
|
||||
int getNumPredecessors() const { return (int)predecessors.size(); }
|
||||
void addInstruction(std::unique_ptr<Instruction> inst);
|
||||
void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);}
|
||||
void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
|
||||
const std::vector<Block*>& getPredecessors() const { return predecessors; }
|
||||
const std::vector<Block*>& getSuccessors() const { return successors; }
|
||||
void setUnreachable() { unreachable = true; }
|
||||
bool isUnreachable() const { return unreachable; }
|
||||
// Returns the block's merge instruction, if one exists (otherwise null).
|
||||
const Instruction* getMergeInstruction() const {
|
||||
if (instructions.size() < 2) return nullptr;
|
||||
const Instruction* nextToLast = (instructions.cend() - 2)->get();
|
||||
switch (nextToLast->getOpCode()) {
|
||||
case OpSelectionMerge:
|
||||
case OpLoopMerge:
|
||||
return nextToLast;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool isTerminated() const
|
||||
{
|
||||
@@ -206,9 +225,9 @@ protected:
|
||||
// To enforce keeping parent and ownership in sync:
|
||||
friend Function;
|
||||
|
||||
std::vector<Instruction*> instructions;
|
||||
std::vector<Block*> predecessors;
|
||||
std::vector<Instruction*> localVariables;
|
||||
std::vector<std::unique_ptr<Instruction> > instructions;
|
||||
std::vector<Block*> predecessors, successors;
|
||||
std::vector<std::unique_ptr<Instruction> > localVariables;
|
||||
Function& parent;
|
||||
|
||||
// track whether this block is known to be uncreachable (not necessarily
|
||||
@@ -217,6 +236,11 @@ protected:
|
||||
bool unreachable;
|
||||
};
|
||||
|
||||
// Traverses the control-flow graph rooted at root in an order suited for
|
||||
// readable code generation. Invokes callback at every node in the traversal
|
||||
// order.
|
||||
void inReadableOrder(Block* root, std::function<void(Block*)> callback);
|
||||
|
||||
//
|
||||
// SPIR-V IR Function.
|
||||
//
|
||||
@@ -247,7 +271,7 @@ public:
|
||||
Module& getParent() const { return parent; }
|
||||
Block* getEntryBlock() const { return blocks.front(); }
|
||||
Block* getLastBlock() const { return blocks.back(); }
|
||||
void addLocalVariable(Instruction* inst);
|
||||
void addLocalVariable(std::unique_ptr<Instruction> inst);
|
||||
Id getReturnType() const { return functionInstruction.getTypeId(); }
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
@@ -259,8 +283,7 @@ public:
|
||||
parameterInstructions[p]->dump(out);
|
||||
|
||||
// Blocks
|
||||
for (int b = 0; b < (int)blocks.size(); ++b)
|
||||
blocks[b]->dump(out);
|
||||
inReadableOrder(blocks[0], [&out](const Block* b) { b->dump(out); });
|
||||
Instruction end(0, 0, OpFunctionEnd);
|
||||
end.dump(out);
|
||||
}
|
||||
@@ -348,22 +371,27 @@ __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParam
|
||||
}
|
||||
}
|
||||
|
||||
__inline void Function::addLocalVariable(Instruction* inst)
|
||||
__inline void Function::addLocalVariable(std::unique_ptr<Instruction> inst)
|
||||
{
|
||||
blocks[0]->addLocalVariable(inst);
|
||||
parent.mapInstruction(inst);
|
||||
Instruction* raw_instruction = inst.get();
|
||||
blocks[0]->addLocalVariable(std::move(inst));
|
||||
parent.mapInstruction(raw_instruction);
|
||||
}
|
||||
|
||||
__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false)
|
||||
{
|
||||
instructions.push_back(new Instruction(id, NoType, OpLabel));
|
||||
instructions.push_back(std::unique_ptr<Instruction>(new Instruction(id, NoType, OpLabel)));
|
||||
instructions.back()->setBlock(this);
|
||||
parent.getParent().mapInstruction(instructions.back().get());
|
||||
}
|
||||
|
||||
__inline void Block::addInstruction(Instruction* inst)
|
||||
__inline void Block::addInstruction(std::unique_ptr<Instruction> inst)
|
||||
{
|
||||
instructions.push_back(inst);
|
||||
if (inst->getResultId())
|
||||
parent.getParent().mapInstruction(inst);
|
||||
Instruction* raw_instruction = inst.get();
|
||||
instructions.push_back(std::move(inst));
|
||||
raw_instruction->setBlock(this);
|
||||
if (raw_instruction->getResultId())
|
||||
parent.getParent().mapInstruction(raw_instruction);
|
||||
}
|
||||
|
||||
}; // end spv namespace
|
||||
|
||||
Reference in New Issue
Block a user