spirv::Deserializer::Deserializer(ArrayRef<uint32_t> binary,
MLIRContext *context)
: binary(binary), context(context), unknownLoc(UnknownLoc::get(context)),
- module(createModuleOp()), opBuilder(module->getRegion()) {}
+ module(createModuleOp()), opBuilder(module->getRegion())
+#ifndef NDEBUG
+ ,
+ logger(llvm::dbgs())
+#endif
+{
+}
LogicalResult spirv::Deserializer::deserialize() {
- LLVM_DEBUG(llvm::dbgs() << "+++ starting deserialization +++\n");
+ LLVM_DEBUG({
+ logger.resetIndent();
+ logger.startLine()
+ << "//+++---------- start deserialization ----------+++//\n";
+ });
if (failed(processHeader()))
return failure();
attachVCETriple();
- LLVM_DEBUG(llvm::dbgs() << "+++ completed deserialization +++\n");
+ LLVM_DEBUG(logger.startLine()
+ << "//+++-------- completed deserialization --------+++//\n");
return success();
}
<< operands[0];
}
- if (funcMap.count(operands[1])) {
+ uint32_t fnID = operands[1];
+ if (funcMap.count(fnID)) {
return emitError(unknownLoc, "duplicate function definition/declaration");
}
<< functionType << " and return type " << resultType << " specified";
}
- std::string fnName = getFunctionSymbol(operands[1]);
+ std::string fnName = getFunctionSymbol(fnID);
auto funcOp = opBuilder.create<spirv::FuncOp>(
unknownLoc, fnName, functionType, fnControl.getValue());
- curFunction = funcMap[operands[1]] = funcOp;
- LLVM_DEBUG(llvm::dbgs() << "-- start function " << fnName << " (type = "
- << fnType << ", id = " << operands[1] << ") --\n");
+ curFunction = funcMap[fnID] = funcOp;
auto *entryBlock = funcOp.addEntryBlock();
- LLVM_DEBUG(llvm::dbgs() << "[block] created entry block " << entryBlock
- << "\n");
+ LLVM_DEBUG({
+ logger.startLine()
+ << "//===-------------------------------------------===//\n";
+ logger.startLine() << "[fn] name: " << fnName << "\n";
+ logger.startLine() << "[fn] type: " << fnType << "\n";
+ logger.startLine() << "[fn] ID: " << fnID << "\n";
+ logger.startLine() << "[fn] entry block: " << entryBlock << "\n";
+ logger.indent();
+ });
// Parse the op argument instructions
if (functionType.getNumInputs()) {
<< argDefinedType << " at argument " << i;
}
if (getValue(operands[1])) {
- return emitError(unknownLoc, "duplicate definition of result <id> '")
+ return emitError(unknownLoc, "duplicate definition of result <id> ")
<< operands[1];
}
auto argValue = funcOp.getArgument(i);
return failure();
}
if (opcode == spirv::Opcode::OpFunctionEnd) {
- LLVM_DEBUG(llvm::dbgs()
- << "-- completed function '" << fnName << "' (type = " << fnType
- << ", id = " << operands[1] << ") --\n");
return processFunctionEnd(instOperands);
}
if (opcode != spirv::Opcode::OpLabel) {
return failure();
}
- LLVM_DEBUG(llvm::dbgs() << "-- completed function '" << fnName << "' (type = "
- << fnType << ", id = " << operands[1] << ") --\n");
return processFunctionEnd(instOperands);
}
curBlock = nullptr;
curFunction = llvm::None;
+ LLVM_DEBUG({
+ logger.unindent();
+ logger.startLine()
+ << "//===-------------------------------------------===//\n";
+ });
return success();
}
Block *spirv::Deserializer::getOrCreateBlock(uint32_t id) {
if (auto *block = getBlock(id)) {
- LLVM_DEBUG(llvm::dbgs() << "[block] got exiting block for id = " << id
- << " @ " << block << "\n");
+ LLVM_DEBUG(logger.startLine() << "[block] got exiting block for id = " << id
+ << " @ " << block << "\n");
return block;
}
// spv.mlir.selection or spv.mlir.loop or function). Create it into the
// function for now and sort out the proper place later.
auto *block = curFunction->addBlock();
- LLVM_DEBUG(llvm::dbgs() << "[block] created block for id = " << id << " @ "
- << block << "\n");
+ LLVM_DEBUG(logger.startLine() << "[block] created block for id = " << id
+ << " @ " << block << "\n");
return blockMap[id] = block;
}
auto labelID = operands[0];
// We may have forward declared this block.
auto *block = getOrCreateBlock(labelID);
- LLVM_DEBUG(llvm::dbgs() << "[block] populating block " << block << "\n");
+ LLVM_DEBUG(logger.startLine()
+ << "[block] populating block " << block << "\n");
// If we have seen this block, make sure it was just a forward declaration.
assert(block->empty() && "re-deserialize the same block!");
Type blockArgType = getType(operands[0]);
BlockArgument blockArg = curBlock->addArgument(blockArgType);
valueMap[operands[1]] = blockArg;
- LLVM_DEBUG(llvm::dbgs() << "[phi] created block argument " << blockArg
- << " id = " << operands[1] << " of type "
- << blockArgType << '\n');
+ LLVM_DEBUG(logger.startLine()
+ << "[phi] created block argument " << blockArg
+ << " id = " << operands[1] << " of type " << blockArgType << "\n");
// For each (value, predecessor) pair, insert the value to the predecessor's
// blockPhiInfo entry so later we can fix the block argument there.
Block *predecessor = getOrCreateBlock(operands[i + 1]);
std::pair<Block *, Block *> predecessorTargetPair{predecessor, curBlock};
blockPhiInfo[predecessorTargetPair].push_back(value);
- LLVM_DEBUG(llvm::dbgs() << "[phi] predecessor @ " << predecessor
- << " with arg id = " << value << '\n');
+ LLVM_DEBUG(logger.startLine() << "[phi] predecessor @ " << predecessor
+ << " with arg id = " << value << "\n");
}
return success();
/// spv.mlir.selection/spv.mlir.loop op.
class ControlFlowStructurizer {
public:
+#ifndef NDEBUG
+ ControlFlowStructurizer(Location loc, uint32_t control,
+ spirv::BlockMergeInfoMap &mergeInfo, Block *header,
+ Block *merge, Block *cont,
+ llvm::ScopedPrinter &logger)
+ : location(loc), control(control), blockMergeInfo(mergeInfo),
+ headerBlock(header), mergeBlock(merge), continueBlock(cont),
+ logger(logger) {}
+#else
+ ControlFlowStructurizer(Location loc, uint32_t control,
+ spirv::BlockMergeInfoMap &mergeInfo, Block *header,
+ Block *merge, Block *cont)
+ : location(loc), control(control), blockMergeInfo(mergeInfo),
+ headerBlock(header), mergeBlock(merge), continueBlock(cont) {}
+#endif
+
/// Structurizes the loop at the given `headerBlock`.
///
/// This method will create an spv.mlir.loop op in the `mergeBlock` and move
/// branches to the `headerBlock` will be redirected to the `mergeBlock`. This
/// method will also update `mergeInfo` by remapping all blocks inside to the
/// newly cloned ones inside structured control flow op's regions.
- static LogicalResult structurize(Location loc, uint32_t control,
- spirv::BlockMergeInfoMap &mergeInfo,
- Block *headerBlock, Block *mergeBlock,
- Block *continueBlock) {
- return ControlFlowStructurizer(loc, control, mergeInfo, headerBlock,
- mergeBlock, continueBlock)
- .structurizeImpl();
- }
+ LogicalResult structurize();
private:
- ControlFlowStructurizer(Location loc, uint32_t control,
- spirv::BlockMergeInfoMap &mergeInfo, Block *header,
- Block *merge, Block *cont)
- : location(loc), control(control), blockMergeInfo(mergeInfo),
- headerBlock(header), mergeBlock(merge), continueBlock(cont) {}
-
/// Creates a new spv.mlir.selection op at the beginning of the `mergeBlock`.
spirv::SelectionOp createSelectionOp(uint32_t selectionControl);
/// Collects all blocks reachable from `headerBlock` except `mergeBlock`.
void collectBlocksInConstruct();
- LogicalResult structurizeImpl();
-
Location location;
uint32_t control;
Block *continueBlock; // nullptr for spv.mlir.selection
SetVector<Block *> constructBlocks;
+
+#ifndef NDEBUG
+ /// A logger used to emit information during the deserialzation process.
+ llvm::ScopedPrinter &logger;
+#endif
};
} // namespace
}
}
-LogicalResult ControlFlowStructurizer::structurizeImpl() {
+LogicalResult ControlFlowStructurizer::structurize() {
Operation *op = nullptr;
bool isLoop = continueBlock != nullptr;
if (isLoop) {
// SelectionOp/LoopOp's region.
auto *newBlock = builder.createBlock(&body.back());
mapper.map(block, newBlock);
- LLVM_DEBUG(llvm::dbgs() << "[cf] cloned block " << newBlock
- << " from block " << block << "\n");
+ LLVM_DEBUG(logger.startLine() << "[cf] cloned block " << newBlock
+ << " from block " << block << "\n");
if (!isFnEntryBlock(block)) {
for (BlockArgument blockArg : block->getArguments()) {
auto newArg = newBlock->addArgument(blockArg.getType());
mapper.map(blockArg, newArg);
- LLVM_DEBUG(llvm::dbgs() << "[cf] remapped block argument " << blockArg
- << " to " << newArg << '\n');
+ LLVM_DEBUG(logger.startLine() << "[cf] remapped block argument "
+ << blockArg << " to " << newArg << "\n");
}
} else {
- LLVM_DEBUG(llvm::dbgs()
+ LLVM_DEBUG(logger.startLine()
<< "[cf] block " << block << " is a function entry block\n");
}
// SelectionOp/LoopOp resides right now.
headerBlock->replaceAllUsesWith(mergeBlock);
- LLVM_DEBUG(llvm::dbgs() << "[cf] after cloning and fixing references:\n");
- LLVM_DEBUG(llvm::dbgs() << *headerBlock->getParentOp());
- LLVM_DEBUG(llvm::dbgs() << "\n");
+ LLVM_DEBUG({
+ logger.startLine() << "[cf] after cloning and fixing references:\n";
+ headerBlock->getParentOp()->print(logger.getOStream());
+ logger.startLine() << "\n";
+ });
if (isLoop) {
if (!mergeBlock->args_empty()) {
// All the blocks cloned into the SelectionOp/LoopOp's region can now be
// cleaned up.
- LLVM_DEBUG(llvm::dbgs() << "[cf] cleaning up blocks after clone\n");
+ LLVM_DEBUG(logger.startLine() << "[cf] cleaning up blocks after clone\n");
// First we need to drop all operands' references inside all blocks. This is
// needed because we can have blocks referencing SSA values from one another.
for (auto *block : constructBlocks)
// flow, we cannot just simply erase it because it may contain arguments
// matching the function signature and used by the cloned blocks.
if (isFnEntryBlock(block)) {
- LLVM_DEBUG(llvm::dbgs() << "[cf] changing entry block " << block
- << " to only contain a spv.Branch op\n");
+ LLVM_DEBUG(logger.startLine() << "[cf] changing entry block " << block
+ << " to only contain a spv.Branch op\n");
// Still keep the function entry block for the potential block arguments,
// but replace all ops inside with a branch to the merge block.
block->clear();
builder.setInsertionPointToEnd(block);
builder.create<spirv::BranchOp>(location, mergeBlock);
} else {
- LLVM_DEBUG(llvm::dbgs() << "[cf] erasing block " << block << "\n");
+ LLVM_DEBUG(logger.startLine() << "[cf] erasing block " << block << "\n");
block->erase();
}
}
- LLVM_DEBUG(
- llvm::dbgs() << "[cf] after structurizing construct with header block "
- << headerBlock << ":\n"
- << *op << '\n');
+ LLVM_DEBUG(logger.startLine()
+ << "[cf] after structurizing construct with header block "
+ << headerBlock << ":\n"
+ << *op << "\n");
return success();
}
LogicalResult spirv::Deserializer::wireUpBlockArgument() {
- LLVM_DEBUG(llvm::dbgs() << "[phi] start wiring up block arguments\n");
+ LLVM_DEBUG({
+ logger.startLine()
+ << "//----- [phi] start wiring up block arguments -----//\n";
+ logger.indent();
+ });
OpBuilder::InsertionGuard guard(opBuilder);
Block *block = info.first.first;
Block *target = info.first.second;
const BlockPhiInfo &phiInfo = info.second;
- LLVM_DEBUG(llvm::dbgs() << "[phi] block " << block << "\n");
- LLVM_DEBUG(llvm::dbgs() << "[phi] before creating block argument:\n");
- LLVM_DEBUG(block->getParentOp()->print(llvm::dbgs()));
- LLVM_DEBUG(llvm::dbgs() << '\n');
+ LLVM_DEBUG({
+ logger.startLine() << "[phi] block " << block << "\n";
+ logger.startLine() << "[phi] before creating block argument:\n";
+ block->getParentOp()->print(logger.getOStream());
+ logger.startLine() << "\n";
+ });
// Set insertion point to before this block's terminator early because we
// may materialize ops via getValue() call.
for (uint32_t valueId : phiInfo) {
if (Value value = getValue(valueId)) {
blockArgs.push_back(value);
- LLVM_DEBUG(llvm::dbgs() << "[phi] block argument " << value
- << " id = " << valueId << '\n');
+ LLVM_DEBUG(logger.startLine() << "[phi] block argument " << value
+ << " id = " << valueId << "\n");
} else {
return emitError(unknownLoc, "OpPhi references undefined value!");
}
return emitError(unknownLoc, "unimplemented terminator for Phi creation");
}
- LLVM_DEBUG(llvm::dbgs() << "[phi] after creating block argument:\n");
- LLVM_DEBUG(block->getParentOp()->print(llvm::dbgs()));
- LLVM_DEBUG(llvm::dbgs() << '\n');
+ LLVM_DEBUG({
+ logger.startLine() << "[phi] after creating block argument:\n";
+ block->getParentOp()->print(logger.getOStream());
+ logger.startLine() << "\n";
+ });
}
blockPhiInfo.clear();
- LLVM_DEBUG(llvm::dbgs() << "[phi] completed wiring up block arguments\n");
+ LLVM_DEBUG({
+ logger.unindent();
+ logger.startLine()
+ << "//--- [phi] completed wiring up block arguments ---//\n";
+ });
return success();
}
LogicalResult spirv::Deserializer::structurizeControlFlow() {
- LLVM_DEBUG(llvm::dbgs() << "[cf] start structurizing control flow\n");
+ LLVM_DEBUG({
+ logger.startLine()
+ << "//----- [cf] start structurizing control flow -----//\n";
+ logger.indent();
+ });
while (!blockMergeInfo.empty()) {
Block *headerBlock = blockMergeInfo.begin()->first;
BlockMergeInfo mergeInfo = blockMergeInfo.begin()->second;
- LLVM_DEBUG(llvm::dbgs() << "[cf] header block " << headerBlock << ":\n");
- LLVM_DEBUG(headerBlock->print(llvm::dbgs()));
+ LLVM_DEBUG({
+ logger.startLine() << "[cf] header block " << headerBlock << ":\n";
+ headerBlock->print(logger.getOStream());
+ logger.startLine() << "\n";
+ });
auto *mergeBlock = mergeInfo.mergeBlock;
assert(mergeBlock && "merge block cannot be nullptr");
if (!mergeBlock->args_empty())
return emitError(unknownLoc, "OpPhi in loop merge block unimplemented");
- LLVM_DEBUG(llvm::dbgs() << "[cf] merge block " << mergeBlock << ":\n");
- LLVM_DEBUG(mergeBlock->print(llvm::dbgs()));
+ LLVM_DEBUG({
+ logger.startLine() << "[cf] merge block " << mergeBlock << ":\n";
+ mergeBlock->print(logger.getOStream());
+ logger.startLine() << "\n";
+ });
auto *continueBlock = mergeInfo.continueBlock;
- if (continueBlock) {
- LLVM_DEBUG(llvm::dbgs()
- << "[cf] continue block " << continueBlock << ":\n");
- LLVM_DEBUG(continueBlock->print(llvm::dbgs()));
- }
+ LLVM_DEBUG(if (continueBlock) {
+ logger.startLine() << "[cf] continue block " << continueBlock << ":\n";
+ continueBlock->print(logger.getOStream());
+ logger.startLine() << "\n";
+ });
// Erase this case before calling into structurizer, who will update
// blockMergeInfo.
blockMergeInfo.erase(blockMergeInfo.begin());
- if (failed(ControlFlowStructurizer::structurize(
- mergeInfo.loc, mergeInfo.control, blockMergeInfo, headerBlock,
- mergeBlock, continueBlock)))
+ ControlFlowStructurizer structurizer(mergeInfo.loc, mergeInfo.control,
+ blockMergeInfo, headerBlock,
+ mergeBlock, continueBlock
+#ifndef NDEBUG
+ ,
+ logger
+#endif
+ );
+ if (failed(structurizer.structurize()))
return failure();
}
- LLVM_DEBUG(llvm::dbgs() << "[cf] completed structurizing control flow\n");
+ LLVM_DEBUG({
+ logger.unindent();
+ logger.startLine()
+ << "//--- [cf] completed structurizing control flow ---//\n";
+ });
return success();
}
if (fileName.empty())
fileName = "<unknown>";
return FileLineColLoc::get(opBuilder.getStringAttr(fileName), debugLine->line,
- debugLine->col);
+ debugLine->column);
}
LogicalResult
// OpNoLine instruction."
if (operands.size() != 3)
return emitError(unknownLoc, "OpLine must have 3 operands");
- debugLine = DebugLine(operands[0], operands[1], operands[2]);
+ debugLine = DebugLine{operands[0], operands[1], operands[2]};
return success();
}