[Mlir-commits] [mlir] e739648 - [MLIR][SPIRVToLLVM] Conversion pattern for loop op
George Mitenkov
llvmlistbot at llvm.org
Wed Aug 5 00:36:26 PDT 2020
Author: George Mitenkov
Date: 2020-08-05T10:33:54+03:00
New Revision: e739648cfae21d2b564751ef0511fec9559305fa
URL: https://github.com/llvm/llvm-project/commit/e739648cfae21d2b564751ef0511fec9559305fa
DIFF: https://github.com/llvm/llvm-project/commit/e739648cfae21d2b564751ef0511fec9559305fa.diff
LOG: [MLIR][SPIRVToLLVM] Conversion pattern for loop op
This patch introduces a conversion of `spv.loop` to LLVM dialect.
Similarly to `spv.selection`, op's control attributes are not mapped
to LLVM yet and therefore the conversion fails if the loop control is
not `None`. Also, all blocks within the loop should be reachable in
order for conversion to succeed.
Reviewed By: mravishankar
Differential Revision: https://reviews.llvm.org/D84245
Added:
Modified:
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
mlir/test/Conversion/SPIRVToLLVM/control-flow-ops-to-llvm.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
index 45b9f4112151..0c326287e69e 100644
--- a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
+++ b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
@@ -718,6 +718,98 @@ class ReturnValuePattern : public SPIRVToLLVMConversion<spirv::ReturnValueOp> {
}
};
+/// Converts `spv.loop` to LLVM dialect. All blocks within selection should be
+/// reachable for conversion to succeed.
+/// The structure of the loop in LLVM dialect will be the following:
+///
+/// +------------------------------------+
+/// | <code before spv.loop> |
+/// | llvm.br ^header |
+/// +------------------------------------+
+/// |
+/// +----------------+ |
+/// | | |
+/// | V V
+/// | +------------------------------------+
+/// | | ^header: |
+/// | | <header code> |
+/// | | llvm.cond_br %cond, ^body, ^exit |
+/// | +------------------------------------+
+/// | |
+/// | |----------------------+
+/// | | |
+/// | V |
+/// | +------------------------------------+ |
+/// | | ^body: | |
+/// | | <body code> | |
+/// | | llvm.br ^continue | |
+/// | +------------------------------------+ |
+/// | | |
+/// | V |
+/// | +------------------------------------+ |
+/// | | ^continue: | |
+/// | | <continue code> | |
+/// | | llvm.br ^header | |
+/// | +------------------------------------+ |
+/// | | |
+/// +---------------+ +----------------------+
+/// |
+/// V
+/// +------------------------------------+
+/// | ^exit: |
+/// | llvm.br ^remaining |
+/// +------------------------------------+
+/// |
+/// V
+/// +------------------------------------+
+/// | ^remaining: |
+/// | <code after spv.loop> |
+/// +------------------------------------+
+///
+class LoopPattern : public SPIRVToLLVMConversion<spirv::LoopOp> {
+public:
+ using SPIRVToLLVMConversion<spirv::LoopOp>::SPIRVToLLVMConversion;
+
+ LogicalResult
+ matchAndRewrite(spirv::LoopOp loopOp, ArrayRef<Value> operands,
+ ConversionPatternRewriter &rewriter) const override {
+ // There is no support of loop control at the moment.
+ if (loopOp.loop_control() != spirv::LoopControl::None)
+ return failure();
+
+ Location loc = loopOp.getLoc();
+
+ // Split the current block after `spv.loop`. The remaing ops will be used in
+ // `endBlock`.
+ Block *currentBlock = rewriter.getBlock();
+ auto position = Block::iterator(loopOp);
+ Block *endBlock = rewriter.splitBlock(currentBlock, position);
+
+ // Remove entry block and create a branch in the current block going to the
+ // header block.
+ Block *entryBlock = loopOp.getEntryBlock();
+ assert(entryBlock->getOperations().size() == 1);
+ auto brOp = dyn_cast<spirv::BranchOp>(entryBlock->getOperations().front());
+ if (!brOp)
+ return failure();
+ Block *headerBlock = loopOp.getHeaderBlock();
+ rewriter.setInsertionPointToEnd(currentBlock);
+ rewriter.create<LLVM::BrOp>(loc, brOp.getBlockArguments(), headerBlock);
+ rewriter.eraseBlock(entryBlock);
+
+ // Branch from merge block to end block.
+ Block *mergeBlock = loopOp.getMergeBlock();
+ Operation *terminator = mergeBlock->getTerminator();
+ ValueRange terminatorOperands = terminator->getOperands();
+ rewriter.setInsertionPointToEnd(mergeBlock);
+ rewriter.create<LLVM::BrOp>(loc, terminatorOperands, endBlock);
+
+ rewriter.inlineRegionBefore(loopOp.body(), endBlock);
+ rewriter.replaceOp(loopOp, endBlock->getArguments());
+ return success();
+ }
+};
+
class MergePattern : public SPIRVToLLVMConversion<spirv::MergeOp> {
public:
using SPIRVToLLVMConversion<spirv::MergeOp>::SPIRVToLLVMConversion;
@@ -1109,7 +1201,7 @@ void mlir::populateSPIRVToLLVMConversionPatterns(
ConstantScalarAndVectorPattern,
// Control Flow ops
- BranchConversionPattern, BranchConditionalConversionPattern,
+ BranchConversionPattern, BranchConditionalConversionPattern, LoopPattern,
SelectionPattern, MergePattern,
// Function Call op
diff --git a/mlir/test/Conversion/SPIRVToLLVM/control-flow-ops-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/control-flow-ops-to-llvm.mlir
index 3c92040a17ed..6427ce47dc16 100644
--- a/mlir/test/Conversion/SPIRVToLLVM/control-flow-ops-to-llvm.mlir
+++ b/mlir/test/Conversion/SPIRVToLLVM/control-flow-ops-to-llvm.mlir
@@ -81,6 +81,45 @@ spv.module Logical GLSL450 {
// -----
+//===----------------------------------------------------------------------===//
+// spv.loop
+//===----------------------------------------------------------------------===//
+
+spv.module Logical GLSL450 {
+ // CHECK-LABEL: @infinite_loop
+ spv.func @infinite_loop(%count : i32) -> () "None" {
+ // CHECK: llvm.br ^[[BB1:.*]]
+ // CHECK: ^[[BB1]]:
+ // CHECK: %[[COND:.*]] = llvm.mlir.constant(true) : !llvm.i1
+ // CHECK: llvm.cond_br %[[COND]], ^[[BB2:.*]], ^[[BB4:.*]]
+ // CHECK: ^[[BB2]]:
+ // CHECK: llvm.br ^[[BB3:.*]]
+ // CHECK: ^[[BB3]]:
+ // CHECK: llvm.br ^[[BB1:.*]]
+ // CHECK: ^[[BB4]]:
+ // CHECK: llvm.br ^[[BB5:.*]]
+ // CHECK: ^[[BB5]]:
+ // CHECK: llvm.return
+ spv.loop {
+ spv.Branch ^header
+ ^header:
+ %cond = spv.constant true
+ spv.BranchConditional %cond, ^body, ^merge
+ ^body:
+ // Do nothing
+ spv.Branch ^continue
+ ^continue:
+ // Do nothing
+ spv.Branch ^header
+ ^merge:
+ spv._merge
+ }
+ spv.Return
+ }
+}
+
+// -----
+
//===----------------------------------------------------------------------===//
// spv.selection
//===----------------------------------------------------------------------===//
More information about the Mlir-commits
mailing list