[MLIR][SPIRV] Rename spv.loop to spv.mlir.loop.

To unify the naming scheme across all ops in the SPIR-V dialect,
we are moving from spv.camelCase to spv.CamelCase everywhere.

Reviewed By: antiagainst

Differential Revision: https://reviews.llvm.org/D97918
This commit is contained in:
KareemErgawy-TomTom 2021-03-05 15:35:35 -05:00 committed by Lei Zhang
parent f7f9f94b2e
commit 29812a6195
18 changed files with 96 additions and 95 deletions

View File

@ -525,7 +525,7 @@ control flow construct. With this approach, it's easier to discover all blocks
belonging to a structured control flow construct. It is also more idiomatic to
MLIR system.
We introduce a `spv.selection` and `spv.loop` op for structured selections and
We introduce a `spv.selection` and `spv.mlir.loop` op for structured selections and
loops, respectively. The merge targets are the next ops following them. Inside
their regions, a special terminator, `spv.mlir.merge` is introduced for branching to
the merge target.
@ -608,7 +608,7 @@ func @selection(%cond: i1) -> () {
### Loop
`spv.loop` defines a loop construct. It contains one region. The region should
`spv.mlir.loop` defines a loop construct. It contains one region. The region should
contain at least four blocks: one entry block, one loop header block, one loop
continue block, one merge block.
@ -673,7 +673,7 @@ func @loop(%count : i32) -> () {
%one = spv.Constant 1: i32
%var = spv.Variable init(%zero) : !spv.ptr<i32, Function>
spv.loop {
spv.mlir.loop {
spv.Branch ^header
^header:
@ -969,7 +969,7 @@ the representational differences between SPIR-V dialect and binary format:
* Attributes on ops, if not part of the op's binary encoding, are emitted as
`OpDecorate*` instructions in the SPIR-V binary module section for
decorations.
* `spv.selection`s and `spv.loop`s are emitted as basic blocks with `Op*Merge`
* `spv.selection`s and `spv.mlir.loop`s are emitted as basic blocks with `Op*Merge`
instructions in the header block as required by the binary format.
* Block arguments are materialized as `OpPhi` instructions at the beginning of
the corresponding blocks.
@ -991,7 +991,7 @@ Similarly, a few transformations are performed during deserialization:
`spv.mlir.referenceof` op to turn the symbol of the corresponding
`spv.SpecConstant` into an SSA value.
* `OpPhi` instructions are converted to block arguments.
* Structured control flow are placed inside `spv.selection` and `spv.loop`.
* Structured control flow are placed inside `spv.selection` and `spv.mlir.loop`.
## Conversions

View File

@ -663,9 +663,9 @@ the conditional branch.
spv.FunctionCall @bar(%0) : (i32) -> () => llvm.call @bar(%0) : (f32) -> ()
```
### `spv.selection` and `spv.loop`
### `spv.selection` and `spv.mlir.loop`
Control flow within `spv.selection` and `spv.loop` is lowered directly to LLVM
Control flow within `spv.selection` and `spv.mlir.loop` is lowered directly to LLVM
via branch ops. The conversion can only be applied to selection or loop with all
blocks being reachable. Moreover, selection and loop control attributes (such as
`Flatten` or `Unroll`) are not supported at the moment.
@ -694,7 +694,7 @@ spv.selection {
```mlir
// Conversion of loop
%cond = spv.Constant true %cond = llvm.mlir.constant(true) : i1
spv.loop {
spv.mlir.loop {
spv.Branch ^header llvm.br ^header
^header: ^header:

View File

@ -249,7 +249,7 @@ def SPV_FunctionCallOp : SPV_Op<"FunctionCall", [
// -----
def SPV_LoopOp : SPV_Op<"loop", [InFunctionScope]> {
def SPV_LoopOp : SPV_Op<"mlir.loop", [InFunctionScope]> {
let summary = "Define a structured loop.";
let description = [{
@ -263,12 +263,12 @@ def SPV_LoopOp : SPV_Op<"loop", [InFunctionScope]> {
Instead of having a `spv.LoopMerge` op to directly model loop merge
instruction for indicating the merge and continue target, we use regions
to delimit the boundary of the loop: the merge target is the next op
following the `spv.loop` op and the continue target is the block that
has a back-edge pointing to the entry block inside the `spv.loop`'s region.
following the `spv.mlir.loop` op and the continue target is the block that
has a back-edge pointing to the entry block inside the `spv.mlir.loop`'s region.
This way it's easier to discover all blocks belonging to a construct and
it plays nicer with the MLIR system.
The `spv.loop` region should contain at least four blocks: one entry block,
The `spv.mlir.loop` region should contain at least four blocks: one entry block,
one loop header block, one loop continue block, one loop merge block.
The entry block should be the first block and it should jump to the loop
header block, which is the second block. The loop merge block should be the
@ -317,10 +317,10 @@ def SPV_MergeOp : SPV_Op<"mlir.merge", [NoSideEffect, Terminator]> {
let summary = "A special terminator for merging a structured selection/loop.";
let description = [{
We use `spv.selection`/`spv.loop` for modelling structured selection/loop.
We use `spv.selection`/`spv.mlir.loop` for modelling structured selection/loop.
This op is a terminator used inside their regions to mean jumping to the
merge point, which is the next op following the `spv.selection` or
`spv.loop` op. This op does not have a corresponding instruction in the
`spv.mlir.loop` op. This op does not have a corresponding instruction in the
SPIR-V binary format; it's solely for structural purpose.
}];

View File

@ -26,7 +26,7 @@ using namespace mlir;
namespace mlir {
struct ScfToSPIRVContextImpl {
// Map between the spirv region control flow operation (spv.loop or
// Map between the spirv region control flow operation (spv.mlir.loop or
// spv.selection) to the VariableOp created to store the region results. The
// order of the VariableOp matches the order of the results.
DenseMap<Operation *, SmallVector<spirv::VariableOp, 8>> outputVars;
@ -111,8 +111,8 @@ public:
/// Helper function to replaces SCF op outputs with SPIR-V variable loads.
/// We create VariableOp to handle the results value of the control flow region.
/// spv.loop/spv.selection currently don't yield value. Right after the loop
/// we load the value from the allocation and use it as the SCF op result.
/// spv.mlir.loop/spv.selection currently don't yield value. Right after the
/// loop we load the value from the allocation and use it as the SCF op result.
template <typename ScfOp, typename OpTy>
static void replaceSCFOutputValue(ScfOp scfOp, OpTy newOp,
ConversionPatternRewriter &rewriter,

View File

@ -981,12 +981,12 @@ public:
}
};
/// 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:
/// Converts `spv.mlir.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> |
/// | <code before spv.mlir.loop> |
/// | llvm.br ^header |
/// +------------------------------------+
/// |
@ -1026,7 +1026,7 @@ public:
/// V
/// +------------------------------------+
/// | ^remaining: |
/// | <code after spv.loop> |
/// | <code after spv.mlir.loop> |
/// +------------------------------------+
///
class LoopPattern : public SPIRVToLLVMConversion<spirv::LoopOp> {
@ -1042,8 +1042,8 @@ public:
Location loc = loopOp.getLoc();
// Split the current block after `spv.loop`. The remaining ops will be used
// in `endBlock`.
// Split the current block after `spv.mlir.loop`. The remaining ops will be
// used in `endBlock`.
Block *currentBlock = rewriter.getBlock();
auto position = Block::iterator(loopOp);
Block *endBlock = rewriter.splitBlock(currentBlock, position);

View File

@ -61,7 +61,7 @@ struct SPIRVInlinerInterface : public DialectInlinerInterface {
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
BlockAndValueMapping &) const final {
// Return true here when inlining into spv.func, spv.selection, and
// spv.loop operations.
// spv.mlir.loop operations.
auto *op = dest->getParentOp();
return isa<spirv::FuncOp, spirv::SelectionOp, spirv::LoopOp>(op);
}

View File

@ -2297,7 +2297,7 @@ static LogicalResult verify(spirv::LoadOp loadOp) {
}
//===----------------------------------------------------------------------===//
// spv.loop
// spv.mlir.loop
//===----------------------------------------------------------------------===//
void spirv::LoopOp::build(OpBuilder &builder, OperationState &state) {
@ -2463,12 +2463,12 @@ static LogicalResult verify(spirv::MergeOp mergeOp) {
auto *parentOp = mergeOp->getParentOp();
if (!parentOp || !isa<spirv::SelectionOp, spirv::LoopOp>(parentOp))
return mergeOp.emitOpError(
"expected parent op to be 'spv.selection' or 'spv.loop'");
"expected parent op to be 'spv.selection' or 'spv.mlir.loop'");
Block &parentLastBlock = mergeOp->getParentRegion()->back();
if (mergeOp.getOperation() != parentLastBlock.getTerminator())
return mergeOp.emitOpError(
"can only be used in the last block of 'spv.selection' or 'spv.loop'");
return mergeOp.emitOpError("can only be used in the last block of "
"'spv.selection' or 'spv.mlir.loop'");
return success();
}

View File

@ -470,7 +470,7 @@ spirv::Deserializer::processFunctionEnd(ArrayRef<uint32_t> operands) {
}
// Wire up block arguments from OpPhi instructions.
// Put all structured control flow in spv.selection/spv.loop ops.
// Put all structured control flow in spv.selection/spv.mlir.loop ops.
if (failed(wireUpBlockArgument()) || failed(structurizeControlFlow())) {
return failure();
}
@ -1414,7 +1414,7 @@ Block *spirv::Deserializer::getOrCreateBlock(uint32_t id) {
}
// We don't know where this block will be placed finally (in a spv.selection
// or spv.loop or function). Create it into the function for now and sort
// 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 << " @ "
@ -1584,16 +1584,16 @@ LogicalResult spirv::Deserializer::processPhi(ArrayRef<uint32_t> operands) {
namespace {
/// A class for putting all blocks in a structured selection/loop in a
/// spv.selection/spv.loop op.
/// spv.selection/spv.mlir.loop op.
class ControlFlowStructurizer {
public:
/// Structurizes the loop at the given `headerBlock`.
///
/// This method will create an spv.loop op in the `mergeBlock` and move all
/// blocks in the structured loop into the spv.loop's region. All 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.
/// This method will create an spv.mlir.loop op in the `mergeBlock` and move
/// all blocks in the structured loop into the spv.mlir.loop's region. All
/// 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,
@ -1613,7 +1613,7 @@ private:
/// Creates a new spv.selection op at the beginning of the `mergeBlock`.
spirv::SelectionOp createSelectionOp(uint32_t selectionControl);
/// Creates a new spv.loop op at the beginning of the `mergeBlock`.
/// Creates a new spv.mlir.loop op at the beginning of the `mergeBlock`.
spirv::LoopOp createLoopOp(uint32_t loopControl);
/// Collects all blocks reachable from `headerBlock` except `mergeBlock`.

View File

@ -45,7 +45,7 @@ namespace spirv {
/// A struct for containing a header block's merge and continue targets.
///
/// This struct is used to track original structured control flow info from
/// SPIR-V blob. This info will be used to create spv.selection/spv.loop
/// SPIR-V blob. This info will be used to create spv.selection/spv.mlir.loop
/// later.
struct BlockMergeInfo {
Block *mergeBlock;
@ -346,9 +346,9 @@ private:
// In SPIR-V, structured control flow is explicitly declared using merge
// instructions (OpSelectionMerge and OpLoopMerge). In the SPIR-V dialect,
// we use spv.selection and spv.loop to group structured control flow.
// we use spv.selection and spv.mlir.loop to group structured control flow.
// The deserializer need to turn structured control flow marked with merge
// instructions into using spv.selection/spv.loop ops.
// instructions into using spv.selection/spv.mlir.loop ops.
//
// Because structured control flow can nest and the basic block order have
// flexibility, we cannot isolate a structured selection/loop without
@ -360,11 +360,12 @@ private:
// target blocks.
// 2. For each selection/loop header block, recursively get all basic blocks
// reachable (except the merge block) and put them in a newly created
// spv.selection/spv.loop's region. Structured control flow guarantees
// spv.selection/spv.mlir.loop's region. Structured control flow guarantees
// that we enter and exit in structured ways and the construct is nestable.
// 3. Put the new spv.selection/spv.loop op at the beginning of the old merge
// 3. Put the new spv.selection/spv.mlir.loop op at the beginning of the old
// merge
// block and redirect all branches to the old header block to the old
// merge block (which contains the spv.selection/spv.loop op now).
// merge block (which contains the spv.selection/spv.mlir.loop op now).
/// For OpPhi instructions, we use block arguments to represent them. OpPhi
/// encodes a list of (value, predecessor) pairs. At the time of handling the
@ -410,7 +411,7 @@ private:
LogicalResult wireUpBlockArgument();
/// Extracts blocks belonging to a structured selection/loop into a
/// spv.selection/spv.loop op. This method iterates until all blocks
/// spv.selection/spv.mlir.loop op. This method iterates until all blocks
/// declared as selection/loop headers are handled.
LogicalResult structurizeControlFlow();

View File

@ -42,8 +42,8 @@ static Block *getStructuredControlFlowOpMergeBlock(Operation *op) {
/// that should be used as the parent block for SPIR-V OpPhi instructions
/// corresponding to the block arguments.
static Block *getPhiIncomingBlock(Block *block) {
// If the predecessor block in question is the entry block for a spv.loop,
// we jump to this spv.loop from its enclosing block.
// If the predecessor block in question is the entry block for a
// spv.mlir.loop, we jump to this spv.mlir.loop from its enclosing block.
if (block->isEntryBlock()) {
if (auto loopOp = dyn_cast<spirv::LoopOp>(block->getParentOp())) {
// Then the incoming parent block for OpPhi should be the merge block of
@ -966,8 +966,8 @@ LogicalResult Serializer::emitPhiForBlockArguments(Block *block) {
// structure. It does not directly map to the incoming parent block for the
// OpPhi instructions at SPIR-V binary level. This is because structured
// control flow ops are serialized to multiple SPIR-V blocks. If there is a
// spv.selection/spv.loop op in the MLIR predecessor block, the branch op
// jumping to the OpPhi's block then resides in the previous structured
// spv.selection/spv.mlir.loop op in the MLIR predecessor block, the branch
// op jumping to the OpPhi's block then resides in the previous structured
// control flow op's merge block.
predecessor = getPhiIncomingBlock(predecessor);
if (auto branchOp = dyn_cast<spirv::BranchOp>(terminator)) {

View File

@ -12,7 +12,7 @@ func @loop_kernel(%arg2 : memref<10xf32>, %arg3 : memref<10xf32>) {
%ub = constant 42 : index
// CHECK: %[[STEP:.*]] = spv.Constant 2 : i32
%step = constant 2 : index
// CHECK: spv.loop {
// CHECK: spv.mlir.loop {
// CHECK-NEXT: spv.Branch ^[[HEADER:.*]](%[[LB]] : i32)
// CHECK: ^[[HEADER]](%[[INDVAR:.*]]: i32):
// CHECK: %[[CMP:.*]] = spv.SLessThan %[[INDVAR]], %[[UB]] : i32
@ -56,7 +56,7 @@ func @loop_yield(%arg2 : memref<10xf32>, %arg3 : memref<10xf32>) {
%s1 = constant 1.0 : f32
// CHECK: %[[VAR1:.*]] = spv.Variable : !spv.ptr<f32, Function>
// CHECK: %[[VAR2:.*]] = spv.Variable : !spv.ptr<f32, Function>
// CHECK: spv.loop {
// CHECK: spv.mlir.loop {
// CHECK: spv.Branch ^[[HEADER:.*]](%[[LB]], %[[INITVAR1]], %[[INITVAR2]] : i32, f32, f32)
// CHECK: ^[[HEADER]](%[[INDVAR:.*]]: i32, %[[CARRIED1:.*]]: f32, %[[CARRIED2:.*]]: f32):
// CHECK: %[[CMP:.*]] = spv.SLessThan %[[INDVAR]], %[[UB]] : i32

View File

@ -82,7 +82,7 @@ spv.module Logical GLSL450 {
// -----
//===----------------------------------------------------------------------===//
// spv.loop
// spv.mlir.loop
//===----------------------------------------------------------------------===//
spv.module Logical GLSL450 {
@ -100,7 +100,7 @@ spv.module Logical GLSL450 {
// CHECK: llvm.br ^[[BB5:.*]]
// CHECK: ^[[BB5]]:
// CHECK: llvm.return
spv.loop {
spv.mlir.loop {
spv.Branch ^header
^header:
%cond = spv.Constant true

View File

@ -263,7 +263,7 @@ spv.module Logical GLSL450 {
// -----
//===----------------------------------------------------------------------===//
// spv.loop
// spv.mlir.loop
//===----------------------------------------------------------------------===//
// for (int i = 0; i < count; ++i) {}
@ -272,8 +272,8 @@ func @loop(%count : i32) -> () {
%one = spv.Constant 1: i32
%var = spv.Variable init(%zero) : !spv.ptr<i32, Function>
// CHECK: spv.loop {
spv.loop {
// CHECK: spv.mlir.loop {
spv.mlir.loop {
// CHECK-NEXT: spv.Branch ^bb1
spv.Branch ^header
@ -309,8 +309,8 @@ func @loop(%count : i32) -> () {
// CHECK-LABEL: @empty_region
func @empty_region() -> () {
// CHECK: spv.loop
spv.loop {
// CHECK: spv.mlir.loop
spv.mlir.loop {
}
return
}
@ -319,8 +319,8 @@ func @empty_region() -> () {
// CHECK-LABEL: @loop_with_control
func @loop_with_control() -> () {
// CHECK: spv.loop control(Unroll)
spv.loop control(Unroll) {
// CHECK: spv.mlir.loop control(Unroll)
spv.mlir.loop control(Unroll) {
}
return
}
@ -329,7 +329,7 @@ func @loop_with_control() -> () {
func @wrong_merge_block() -> () {
// expected-error @+1 {{last block must be the merge block with only one 'spv.mlir.merge' op}}
spv.loop {
spv.mlir.loop {
spv.Return
}
return
@ -339,7 +339,7 @@ func @wrong_merge_block() -> () {
func @missing_entry_block() -> () {
// expected-error @+1 {{must have an entry block branching to the loop header block}}
spv.loop {
spv.mlir.loop {
spv.mlir.merge
}
return
@ -349,7 +349,7 @@ func @missing_entry_block() -> () {
func @missing_header_block() -> () {
// expected-error @+1 {{must have a loop header block branched from the entry block}}
spv.loop {
spv.mlir.loop {
^entry:
spv.Branch ^merge
^merge:
@ -362,7 +362,7 @@ func @missing_header_block() -> () {
func @entry_should_branch_to_header() -> () {
// expected-error @+1 {{entry block must only have one 'spv.Branch' op to the second block}}
spv.loop {
spv.mlir.loop {
^entry:
spv.Branch ^merge
^header:
@ -377,7 +377,7 @@ func @entry_should_branch_to_header() -> () {
func @missing_continue_block() -> () {
// expected-error @+1 {{requires a loop continue block branching to the loop header block}}
spv.loop {
spv.mlir.loop {
^entry:
spv.Branch ^header
^header:
@ -392,7 +392,7 @@ func @missing_continue_block() -> () {
func @continue_should_branch_to_header() -> () {
// expected-error @+1 {{second to last block must be the loop continue block that branches to the loop header block}}
spv.loop {
spv.mlir.loop {
^entry:
spv.Branch ^header
^header:
@ -409,7 +409,7 @@ func @continue_should_branch_to_header() -> () {
func @only_entry_and_continue_branch_to_header() -> () {
// expected-error @+1 {{can only have the entry and loop continue block branching to the loop header block}}
spv.loop {
spv.mlir.loop {
^entry:
spv.Branch ^header
^header:
@ -431,7 +431,7 @@ func @only_entry_and_continue_branch_to_header() -> () {
//===----------------------------------------------------------------------===//
func @merge() -> () {
// expected-error @+1 {{expected parent op to be 'spv.selection' or 'spv.loop'}}
// expected-error @+1 {{expected parent op to be 'spv.selection' or 'spv.mlir.loop'}}
spv.mlir.merge
}
@ -447,7 +447,7 @@ func @only_allowed_in_last_block(%cond : i1) -> () {
^then:
spv.Store "Function" %var, %one : i32
// expected-error @+1 {{can only be used in the last block of 'spv.selection' or 'spv.loop'}}
// expected-error @+1 {{can only be used in the last block of 'spv.selection' or 'spv.mlir.loop'}}
spv.mlir.merge
^merge:
@ -461,12 +461,12 @@ func @only_allowed_in_last_block(%cond : i1) -> () {
func @only_allowed_in_last_block() -> () {
%true = spv.Constant true
spv.loop {
spv.mlir.loop {
spv.Branch ^header
^header:
spv.BranchConditional %true, ^body, ^merge
^body:
// expected-error @+1 {{can only be used in the last block of 'spv.selection' or 'spv.loop'}}
// expected-error @+1 {{can only be used in the last block of 'spv.selection' or 'spv.mlir.loop'}}
spv.mlir.merge
^continue:
spv.Branch ^header
@ -497,7 +497,7 @@ func @in_selection(%cond : i1) -> () {
// CHECK-LABEL: func @in_loop
func @in_loop(%cond : i1) -> () {
spv.loop {
spv.mlir.loop {
spv.Branch ^header
^header:
spv.BranchConditional %cond, ^body, ^merge
@ -582,7 +582,7 @@ func @in_selection(%cond : i1) -> (i32) {
// CHECK-LABEL: func @in_loop
func @in_loop(%cond : i1) -> (i32) {
spv.loop {
spv.mlir.loop {
spv.Branch ^header
^header:
spv.BranchConditional %cond, ^body, ^merge

View File

@ -121,7 +121,7 @@ spv.module Logical GLSL450 {
spv.module Logical GLSL450 {
spv.func @callee(%cond : i1) -> () "None" {
spv.loop {
spv.mlir.loop {
spv.Branch ^header
^header:
spv.BranchConditional %cond, ^body, ^merge
@ -148,7 +148,7 @@ spv.module Logical GLSL450 {
spv.module Logical GLSL450 {
spv.func @callee(%cond : i1) -> () "None" {
spv.loop {
spv.mlir.loop {
spv.Branch ^header
^header:
spv.BranchConditional %cond, ^body, ^merge
@ -166,7 +166,7 @@ spv.module Logical GLSL450 {
spv.func @calling_loop_no_ret_func() "None" {
// CHECK-NEXT: %[[TRUE:.*]] = spv.Constant true
%0 = spv.Constant true
// CHECK-NEXT: spv.loop
// CHECK-NEXT: spv.mlir.loop
// CHECK-NEXT: spv.Branch ^bb1
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: spv.BranchConditional %[[TRUE]], ^bb2, ^bb4

View File

@ -72,7 +72,7 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
%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 {
spv.mlir.loop {
// CHECK: loc({{".*debug.mlir"}}:75:5)
spv.Branch ^header
^header:
@ -82,7 +82,7 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
spv.BranchConditional %icmp, ^body, ^merge
^body:
spv.Store "Function" %jvar, %zero : i32
spv.loop {
spv.mlir.loop {
// CHECK: loc({{".*debug.mlir"}}:85:7)
spv.Branch ^header
^header:

View File

@ -26,7 +26,7 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
spv.func @f_loop_with_function_call(%count : i32) -> () "None" {
%zero = spv.Constant 0: i32
%var = spv.Variable init(%zero) : !spv.ptr<i32, Function>
spv.loop {
spv.mlir.loop {
spv.Branch ^header
^header:
%val0 = spv.Load "Function" %var : i32

View File

@ -11,8 +11,8 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
// CHECK: spv.Branch ^bb1
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: spv.loop
spv.loop {
// CHECK-NEXT: spv.mlir.loop
spv.mlir.loop {
// CHECK-NEXT: spv.Branch ^bb1
spv.Branch ^header
@ -73,8 +73,8 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
%8 = spv.Constant 2 : i32
// CHECK: spv.Branch ^bb1(%{{.*}} : i32)
// CHECK-NEXT: ^bb1(%[[OUTARG:.*]]: i32):
// CHECK-NEXT: spv.loop {
spv.loop {
// CHECK-NEXT: spv.mlir.loop {
spv.mlir.loop {
// CHECK-NEXT: spv.Branch ^bb1(%[[OUTARG]] : i32)
spv.Branch ^header(%6 : i32)
// CHECK-NEXT: ^bb1(%[[HEADARG:.*]]: i32):
@ -119,8 +119,8 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
// CHECK: spv.Branch ^bb1
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: spv.loop control(Unroll)
spv.loop control(Unroll) {
// CHECK-NEXT: spv.mlir.loop control(Unroll)
spv.mlir.loop control(Unroll) {
// CHECK-NEXT: spv.Branch ^bb1
spv.Branch ^header
@ -140,8 +140,8 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
spv.Store "Function" %jvar, %zero : i32
// CHECK-NEXT: spv.Branch ^bb3
// CHECK-NEXT: ^bb3:
// CHECK-NEXT: spv.loop control(DontUnroll)
spv.loop control(DontUnroll) {
// CHECK-NEXT: spv.mlir.loop control(DontUnroll)
spv.mlir.loop control(DontUnroll) {
// CHECK-NEXT: spv.Branch ^bb1
spv.Branch ^header

View File

@ -182,8 +182,8 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
// CHECK: spv.Branch ^[[FN_BB:.*]](%{{.*}} : i32)
// CHECK: ^[[FN_BB]](%[[FN_BB_ARG:.*]]: i32):
// CHECK: spv.loop {
spv.loop {
// CHECK: spv.mlir.loop {
spv.mlir.loop {
// CHECK: spv.Branch ^bb1(%[[FN_BB_ARG]] : i32)
spv.Branch ^bb1(%30 : i32)
// CHECK: ^[[LP1_HDR:.*]](%[[LP1_HDR_ARG:.*]]: i32):
@ -200,8 +200,8 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
%35 = spv.IMul %20, %5 : i32
// CHECK: spv.Branch ^[[LP1_CNT:.*]](%[[MUL]] : i32)
// CHECK: ^[[LP1_CNT]](%[[LP1_CNT_ARG:.*]]: i32):
// CHECK: spv.loop {
spv.loop {
// CHECK: spv.mlir.loop {
spv.mlir.loop {
// CHECK: spv.Branch ^[[LP2_HDR:.*]](%[[LP1_CNT_ARG]] : i32)
spv.Branch ^bb1(%34 : i32)
// CHECK: ^[[LP2_HDR]](%[[LP2_HDR_ARG:.*]]: i32):
@ -251,8 +251,8 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
// CHECK: spv.Constant 43
// CHECK-NEXT: spv.Branch ^[[BB1:.+]](%{{.+}} : i32)
// CHECK-NEXT: ^[[BB1]](%{{.+}}: i32):
// CHECK-NEXT: spv.loop
spv.loop { // loop 1
// CHECK-NEXT: spv.mlir.loop
spv.mlir.loop { // loop 1
spv.Branch ^bb1(%val1 : i32)
^bb1(%loop1_bb_arg: i32):
%loop1_lt = spv.SLessThan %loop1_bb_arg, %cst4 : i32
@ -267,8 +267,8 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
// CHECK: spv.Constant 44
// CHECK-NEXT: spv.Branch ^[[BB2:.+]](%{{.+}} : i32)
// CHECK-NEXT: ^[[BB2]](%{{.+}}: i32):
// CHECK-NEXT: spv.loop
spv.loop { // loop 2
// CHECK-NEXT: spv.mlir.loop
spv.mlir.loop { // loop 2
spv.Branch ^bb1(%val2 : i32)
^bb1(%loop2_bb_arg: i32):
%loop2_lt = spv.SLessThan %loop2_bb_arg, %cst4 : i32