[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