mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-27 13:57:52 +00:00
[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:
parent
f7f9f94b2e
commit
29812a6195
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
}];
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user