[Mlir-commits] [mlir] 0dc91bf - [mlir][spirv] Handle debuginfo for control flow ops.
Denis Khalikov
llvmlistbot at llvm.org
Sat May 16 05:37:18 PDT 2020
Author: Denis Khalikov
Date: 2020-05-16T15:36:14+03:00
New Revision: 0dc91bfd11e6cced0c46c1a25cc96edea0d8fc22
URL: https://github.com/llvm/llvm-project/commit/0dc91bfd11e6cced0c46c1a25cc96edea0d8fc22
DIFF: https://github.com/llvm/llvm-project/commit/0dc91bfd11e6cced0c46c1a25cc96edea0d8fc22.diff
LOG: [mlir][spirv] Handle debuginfo for control flow ops.
Summary:
Handle debuginfo for control flow operations: spv.Selection,
spv.Loop, spv.BranchOp, spv.BranchConditional.
Differential Revision: https://reviews.llvm.org/D79931
Added:
Modified:
mlir/lib/Dialect/SPIRV/Serialization/Deserializer.cpp
mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp
mlir/test/Dialect/SPIRV/Serialization/debug.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Dialect/SPIRV/Serialization/Deserializer.cpp b/mlir/lib/Dialect/SPIRV/Serialization/Deserializer.cpp
index 490367e71ef1..a45780ba63a0 100644
--- a/mlir/lib/Dialect/SPIRV/Serialization/Deserializer.cpp
+++ b/mlir/lib/Dialect/SPIRV/Serialization/Deserializer.cpp
@@ -62,10 +62,12 @@ namespace {
struct BlockMergeInfo {
Block *mergeBlock;
Block *continueBlock; // nullptr for spv.selection
+ Location loc;
- BlockMergeInfo() : mergeBlock(nullptr), continueBlock(nullptr) {}
- BlockMergeInfo(Block *m, Block *c = nullptr)
- : mergeBlock(m), continueBlock(c) {}
+ BlockMergeInfo(Location location)
+ : mergeBlock(nullptr), continueBlock(nullptr), loc(location) {}
+ BlockMergeInfo(Location location, Block *m, Block *c = nullptr)
+ : mergeBlock(m), continueBlock(c), loc(location) {}
};
/// A struct for containing OpLine instruction information.
@@ -1539,7 +1541,11 @@ LogicalResult Deserializer::processBranch(ArrayRef<uint32_t> operands) {
}
auto *target = getOrCreateBlock(operands[0]);
- opBuilder.create<spirv::BranchOp>(unknownLoc, target);
+ auto loc = createFileLineColLoc(opBuilder);
+ // The preceding instruction for the OpBranch instruction could be an
+ // OpLoopMerge or an OpSelectionMerge instruction, in this case they will have
+ // the same OpLine information.
+ opBuilder.create<spirv::BranchOp>(loc, target);
clearDebugLine();
return success();
@@ -1566,9 +1572,12 @@ Deserializer::processBranchConditional(ArrayRef<uint32_t> operands) {
if (operands.size() == 5) {
weights = std::make_pair(operands[3], operands[4]);
}
-
+ // The preceding instruction for the OpBranchConditional instruction could be
+ // an OpSelectionMerge instruction, in this case they will have the same
+ // OpLine information.
+ auto loc = createFileLineColLoc(opBuilder);
opBuilder.create<spirv::BranchConditionalOp>(
- unknownLoc, condition, trueBlock,
+ loc, condition, trueBlock,
/*trueArguments=*/ArrayRef<Value>(), falseBlock,
/*falseArguments=*/ArrayRef<Value>(), weights);
@@ -1616,8 +1625,9 @@ LogicalResult Deserializer::processSelectionMerge(ArrayRef<uint32_t> operands) {
}
auto *mergeBlock = getOrCreateBlock(operands[0]);
+ auto loc = createFileLineColLoc(opBuilder);
- if (!blockMergeInfo.try_emplace(curBlock, mergeBlock).second) {
+ if (!blockMergeInfo.try_emplace(curBlock, loc, mergeBlock).second) {
return emitError(
unknownLoc,
"a block cannot have more than one OpSelectionMerge instruction");
@@ -1643,8 +1653,10 @@ LogicalResult Deserializer::processLoopMerge(ArrayRef<uint32_t> operands) {
auto *mergeBlock = getOrCreateBlock(operands[0]);
auto *continueBlock = getOrCreateBlock(operands[1]);
+ auto loc = createFileLineColLoc(opBuilder);
- if (!blockMergeInfo.try_emplace(curBlock, mergeBlock, continueBlock).second) {
+ if (!blockMergeInfo.try_emplace(curBlock, loc, mergeBlock, continueBlock)
+ .second) {
return emitError(
unknownLoc,
"a block cannot have more than one OpLoopMerge instruction");
@@ -1832,7 +1844,6 @@ LogicalResult ControlFlowStructurizer::structurizeImpl() {
LLVM_DEBUG(llvm::dbgs()
<< "[cf] block " << block << " is a function entry block\n");
}
-
for (auto &op : *block)
newBlock->push_back(op.clone(mapper));
}
@@ -1913,10 +1924,12 @@ LogicalResult ControlFlowStructurizer::structurizeImpl() {
if (Block *mappedTo = mapper.lookupOrNull(newMerge))
newMerge = mappedTo;
+ // Keep original location for nested selection/loop ops.
+ Location loc = it->second.loc;
// The iterator should be erased before adding a new entry into
// blockMergeInfo to avoid iterator invalidation.
blockMergeInfo.erase(it);
- blockMergeInfo.try_emplace(newHeader, newMerge, newContinue);
+ blockMergeInfo.try_emplace(newHeader, loc, newMerge, newContinue);
}
// The structured selection/loop's entry block does not have arguments.
@@ -2017,13 +2030,12 @@ LogicalResult Deserializer::structurizeControlFlow() {
<< "[cf] continue block " << continueBlock << ":\n");
LLVM_DEBUG(continueBlock->print(llvm::dbgs()));
}
-
// Erase this case before calling into structurizer, who will update
// blockMergeInfo.
blockMergeInfo.erase(blockMergeInfo.begin());
- if (failed(ControlFlowStructurizer::structurize(unknownLoc, blockMergeInfo,
- headerBlock, mergeBlock,
- continueBlock)))
+ if (failed(ControlFlowStructurizer::structurize(mergeInfo.loc,
+ blockMergeInfo, headerBlock,
+ mergeBlock, continueBlock)))
return failure();
}
diff --git a/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp b/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp
index a2e8d3368125..2b500ddbf985 100644
--- a/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp
+++ b/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp
@@ -391,6 +391,12 @@ class Serializer {
/// A flag which indicates if the debuginfo should be emitted.
bool emitDebugInfo = false;
+ /// A flag which indicates if the last processed instruction was a merge
+ /// instruction.
+ /// According to SPIR-V spec: "If a branch merge instruction is used, the last
+ /// OpLine in the block must be before its merge instruction".
+ bool lastProcessedWasMergeInst = false;
+
/// The <id> of the OpString instruction, which specifies a file name, for
/// use by other debug instructions.
uint32_t fileID = 0;
@@ -1518,11 +1524,14 @@ LogicalResult Serializer::processSelectionOp(spirv::SelectionOp selectionOp) {
auto *headerBlock = selectionOp.getHeaderBlock();
auto *mergeBlock = selectionOp.getMergeBlock();
auto mergeID = getBlockID(mergeBlock);
+ auto loc = selectionOp.getLoc();
// Emit the selection header block, which dominates all other blocks, first.
// We need to emit an OpSelectionMerge instruction before the selection header
// block's terminator.
auto emitSelectionMerge = [&]() {
+ emitDebugLine(functionBody, loc);
+ lastProcessedWasMergeInst = true;
// TODO(antiagainst): properly support selection control here
encodeInstructionInto(
functionBody, spirv::Opcode::OpSelectionMerge,
@@ -1567,6 +1576,7 @@ LogicalResult Serializer::processLoopOp(spirv::LoopOp loopOp) {
auto headerID = getBlockID(headerBlock);
auto continueID = getBlockID(continueBlock);
auto mergeID = getBlockID(mergeBlock);
+ auto loc = loopOp.getLoc();
// This LoopOp is in some MLIR block with preceding and following ops. In the
// binary format, it should reside in separate SPIR-V blocks from its
@@ -1583,6 +1593,8 @@ LogicalResult Serializer::processLoopOp(spirv::LoopOp loopOp) {
// need to emit an OpLoopMerge instruction before the loop header block's
// terminator.
auto emitLoopMerge = [&]() {
+ emitDebugLine(functionBody, loc);
+ lastProcessedWasMergeInst = true;
// TODO(antiagainst): properly support loop control here
encodeInstructionInto(
functionBody, spirv::Opcode::OpLoopMerge,
@@ -1622,11 +1634,13 @@ LogicalResult Serializer::processBranchConditionalOp(
arguments.push_back(val.cast<IntegerAttr>().getInt());
}
+ emitDebugLine(functionBody, condBranchOp.getLoc());
return encodeInstructionInto(functionBody, spirv::Opcode::OpBranchConditional,
arguments);
}
LogicalResult Serializer::processBranchOp(spirv::BranchOp branchOp) {
+ emitDebugLine(functionBody, branchOp.getLoc());
return encodeInstructionInto(functionBody, spirv::Opcode::OpBranch,
{getOrCreateBlockID(branchOp.getTarget())});
}
@@ -1873,6 +1887,11 @@ LogicalResult Serializer::emitDebugLine(SmallVectorImpl<uint32_t> &binary,
if (!emitDebugInfo)
return success();
+ if (lastProcessedWasMergeInst) {
+ lastProcessedWasMergeInst = false;
+ return success();
+ }
+
auto fileLoc = loc.dyn_cast<FileLineColLoc>();
if (fileLoc)
encodeInstructionInto(binary, spirv::Opcode::OpLine,
diff --git a/mlir/test/Dialect/SPIRV/Serialization/debug.mlir b/mlir/test/Dialect/SPIRV/Serialization/debug.mlir
index fe7c365a037b..aa9653da4f2e 100644
--- a/mlir/test/Dialect/SPIRV/Serialization/debug.mlir
+++ b/mlir/test/Dialect/SPIRV/Serialization/debug.mlir
@@ -66,4 +66,81 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
// CHECK: loc({{".*debug.mlir"}}:67:5)
spv.Return
}
+
+ spv.func @loop(%count : i32) -> () "None" {
+ %zero = spv.constant 0: i32
+ %one = spv.constant 1: i32
+ %ivar = spv.Variable init(%zero) : !spv.ptr<i32, Function>
+ %jvar = spv.Variable init(%zero) : !spv.ptr<i32, Function>
+ spv.loop {
+ // CHECK: loc({{".*debug.mlir"}}:75:5)
+ spv.Branch ^header
+ ^header:
+ %ival0 = spv.Load "Function" %ivar : i32
+ %icmp = spv.SLessThan %ival0, %count : i32
+ // CHECK: loc({{".*debug.mlir"}}:75:5)
+ spv.BranchConditional %icmp, ^body, ^merge
+ ^body:
+ spv.Store "Function" %jvar, %zero : i32
+ spv.loop {
+ // CHECK: loc({{".*debug.mlir"}}:85:7)
+ spv.Branch ^header
+ ^header:
+ %jval0 = spv.Load "Function" %jvar : i32
+ %jcmp = spv.SLessThan %jval0, %count : i32
+ // CHECK: loc({{".*debug.mlir"}}:85:7)
+ spv.BranchConditional %jcmp, ^body, ^merge
+ ^body:
+ // CHECK: loc({{".*debug.mlir"}}:95:9)
+ spv.Branch ^continue
+ ^continue:
+ %jval1 = spv.Load "Function" %jvar : i32
+ %add = spv.IAdd %jval1, %one : i32
+ spv.Store "Function" %jvar, %add : i32
+ // CHECK: loc({{".*debug.mlir"}}:101:9)
+ spv.Branch ^header
+ ^merge:
+ // CHECK: loc({{".*debug.mlir"}}:85:7)
+ spv._merge
+ // CHECK: loc({{".*debug.mlir"}}:85:7)
+ }
+ // CHECK: loc({{".*debug.mlir"}}:108:7)
+ spv.Branch ^continue
+ ^continue:
+ %ival1 = spv.Load "Function" %ivar : i32
+ %add = spv.IAdd %ival1, %one : i32
+ spv.Store "Function" %ivar, %add : i32
+ // CHECK: loc({{".*debug.mlir"}}:114:7)
+ spv.Branch ^header
+ ^merge:
+ // CHECK: loc({{".*debug.mlir"}}:75:5)
+ spv._merge
+ // CHECK: loc({{".*debug.mlir"}}:75:5)
+ }
+ spv.Return
+ }
+
+ spv.func @selection(%cond: i1) -> () "None" {
+ %zero = spv.constant 0: i32
+ %one = spv.constant 1: i32
+ %two = spv.constant 2: i32
+ %var = spv.Variable init(%zero) : !spv.ptr<i32, Function>
+ spv.selection {
+ // CHECK: loc({{".*debug.mlir"}}:128:5)
+ spv.BranchConditional %cond [5, 10], ^then, ^else
+ ^then:
+ spv.Store "Function" %var, %one : i32
+ // CHECK: loc({{".*debug.mlir"}}:134:7)
+ spv.Branch ^merge
+ ^else:
+ spv.Store "Function" %var, %two : i32
+ // CHECK: loc({{".*debug.mlir"}}:138:7)
+ spv.Branch ^merge
+ ^merge:
+ // CHECK: loc({{".*debug.mlir"}}:128:5)
+ spv._merge
+ // CHECK: loc({{".*debug.mlir"}}:128:5)
+ }
+ spv.Return
+ }
}
More information about the Mlir-commits
mailing list