[Mlir-commits] [mlir] [mlir][openacc] Update acc.loop to be a proper loop like operation (PR #67355)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Sep 25 10:45:01 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-openacc
<details>
<summary>Changes</summary>
The initial design of the `acc.loop` was to be an operation that encapsulates a loop like operation. This was an early design and we now want to change it so the `acc.loop` operation becomes a real loop-like operation by implementing the LoopLikeInterface.
Differential Revision: https://reviews.llvm.org/D159229
This patch is just moved from Phabricator to github
---
Patch is 39.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/67355.diff
6 Files Affected:
- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACC.h (+1)
- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td (+44-32)
- (modified) mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp (+74-4)
- (modified) mlir/test/Dialect/OpenACC/canonicalize.mlir (+6-4)
- (modified) mlir/test/Dialect/OpenACC/invalid.mlir (+50-38)
- (modified) mlir/test/Dialect/OpenACC/ops.mlir (+125-153)
``````````diff
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACC.h b/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
index ca5876fba674599..7c8abdfe5f3549d 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
@@ -25,6 +25,7 @@
#include "mlir/Dialect/OpenACC/OpenACCTypeInterfaces.h.inc"
#include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
+#include "mlir/Interfaces/LoopLikeInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#define GET_TYPEDEF_CLASSES
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index ce1b4e29cd51b9b..82d10c39f7bee5b 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -14,6 +14,7 @@
#define OPENACC_OPS
include "mlir/Interfaces/ControlFlowInterfaces.td"
+include "mlir/Interfaces/LoopLikeInterface.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/IR/BuiltinTypes.td"
include "mlir/IR/EnumAttr.td"
@@ -1136,46 +1137,53 @@ def OpenACC_HostDataOp : OpenACC_Op<"host_data", [AttrSizedOperandSegments]> {
//===----------------------------------------------------------------------===//
def OpenACC_LoopOp : OpenACC_Op<"loop",
- [AttrSizedOperandSegments, RecursiveMemoryEffects]> {
+ [AttrSizedOperandSegments, RecursiveMemoryEffects,
+ DeclareOpInterfaceMethods<LoopLikeOpInterface>]> {
let summary = "loop construct";
let description = [{
- The "acc.loop" operation represents the OpenACC loop construct.
+ The "acc.loop" operation represents the OpenACC loop construct. The lower
+ and upper bounds specify a half-open range: the range includes the lower
+ bound but does not include the upper bound. If the `inclusive` attribute is
+ set then the upper bound is included.
Example:
```mlir
- acc.loop gang vector {
- scf.for %arg3 = %c0 to %c10 step %c1 {
- scf.for %arg4 = %c0 to %c10 step %c1 {
- scf.for %arg5 = %c0 to %c10 step %c1 {
- // ... body
- }
- }
- }
+ acc.loop gang() vector() (%arg3 : index, %arg4 : index, %arg5 : index) =
+ (%c0, %c0, %c0 : index, index, index) to
+ (%c10, %c10, %c10 : index, index, index) step
+ (%c1, %c1, %c1 : index, index, index) {
+ // Loop body
acc.yield
} attributes { collapse = 3 }
```
}];
- let arguments = (ins OptionalAttr<I64Attr>:$collapse,
- Optional<IntOrIndex>:$gangNum,
- Optional<IntOrIndex>:$gangDim,
- Optional<IntOrIndex>:$gangStatic,
- Optional<IntOrIndex>:$workerNum,
- Optional<IntOrIndex>:$vectorLength,
- UnitAttr:$seq,
- UnitAttr:$independent,
- UnitAttr:$auto_,
- UnitAttr:$hasGang,
- UnitAttr:$hasWorker,
- UnitAttr:$hasVector,
- Variadic<IntOrIndex>:$tileOperands,
- Variadic<OpenACC_PointerLikeTypeInterface>:$privateOperands,
- OptionalAttr<SymbolRefArrayAttr>:$privatizations,
- Variadic<AnyType>:$reductionOperands,
- OptionalAttr<SymbolRefArrayAttr>:$reductionRecipes,
- Variadic<OpenACC_PointerLikeTypeInterface>:$cacheOperands);
+ let arguments = (ins
+ Variadic<IntOrIndex>:$lowerbound,
+ Variadic<IntOrIndex>:$upperbound,
+ Variadic<IntOrIndex>:$step,
+ OptionalAttr<DenseBoolArrayAttr>:$inclusiveUpperbound,
+ OptionalAttr<I64Attr>:$collapse,
+ Optional<IntOrIndex>:$gangNum,
+ Optional<IntOrIndex>:$gangDim,
+ Optional<IntOrIndex>:$gangStatic,
+ Optional<IntOrIndex>:$workerNum,
+ Optional<IntOrIndex>:$vectorLength,
+ UnitAttr:$seq,
+ UnitAttr:$independent,
+ UnitAttr:$auto_,
+ UnitAttr:$hasGang,
+ UnitAttr:$hasWorker,
+ UnitAttr:$hasVector,
+ Variadic<IntOrIndex>:$tileOperands,
+ Variadic<OpenACC_PointerLikeTypeInterface>:$privateOperands,
+ OptionalAttr<SymbolRefArrayAttr>:$privatizations,
+ Variadic<AnyType>:$reductionOperands,
+ OptionalAttr<SymbolRefArrayAttr>:$reductionRecipes,
+ Variadic<OpenACC_PointerLikeTypeInterface>:$cacheOperands
+ );
let results = (outs Variadic<AnyType>:$results);
@@ -1191,9 +1199,12 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
let hasCustomAssemblyFormat = 1;
let assemblyFormat = [{
oilist(
- `gang` `` custom<GangClause>($gangNum, type($gangNum), $gangDim, type($gangDim), $gangStatic, type($gangStatic), $hasGang)
- | `worker` `` custom<WorkerClause>($workerNum, type($workerNum), $hasWorker)
- | `vector` `` custom<VectorClause>($vectorLength, type($vectorLength), $hasVector)
+ `gang` `` custom<GangClause>($gangNum, type($gangNum), $gangDim,
+ type($gangDim), $gangStatic, type($gangStatic), $hasGang)
+ | `worker` ``
+ custom<WorkerClause>($workerNum, type($workerNum), $hasWorker)
+ | `vector` ``
+ custom<VectorClause>($vectorLength, type($vectorLength), $hasVector)
| `private` `(` custom<SymOperandList>(
$privateOperands, type($privateOperands), $privatizations)
`)`
@@ -1203,7 +1214,8 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
`)`
| `cache` `(` $cacheOperands `:` type($cacheOperands) `)`
)
- $region
+ custom<LoopControl>($region, $lowerbound, type($lowerbound), $upperbound,
+ type($upperbound), $step, type($step))
( `(` type($results)^ `)` )?
attr-dict-with-keyword
}];
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index b30215663fbcec9..91e83e1ffa28b79 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -737,6 +737,9 @@ static ParseResult parseGangClause(
// optional gang operands
if (succeeded(parser.parseOptionalLParen())) {
+ // Allow empty parenthesis.
+ if (succeeded(parser.parseOptionalRParen()))
+ return success();
while (true) {
bool newValue = false;
bool needValue = false;
@@ -783,8 +786,8 @@ static ParseResult parseGangClause(
void printGangClause(OpAsmPrinter &p, Operation *op, Value gangNum,
Type gangNumType, Value gangDim, Type gangDimType,
Value gangStatic, Type gangStaticType, UnitAttr hasGang) {
+ p << "(";
if (gangNum || gangStatic || gangDim) {
- p << "(";
if (gangNum) {
p << LoopOp::getGangNumKeyword() << "=" << gangNum << " : "
<< gangNumType;
@@ -800,8 +803,8 @@ void printGangClause(OpAsmPrinter &p, Operation *op, Value gangNum,
if (gangStatic)
p << LoopOp::getGangStaticKeyword() << "=" << gangStatic << " : "
<< gangStaticType;
- p << ")";
}
+ p << ")";
}
static ParseResult
@@ -810,6 +813,9 @@ parseWorkerClause(OpAsmParser &parser,
Type &workerNumType, UnitAttr &hasWorker) {
hasWorker = UnitAttr::get(parser.getBuilder().getContext());
if (succeeded(parser.parseOptionalLParen())) {
+ // Allow empty parenthesis.
+ if (succeeded(parser.parseOptionalRParen()))
+ return success();
workerNum = OpAsmParser::UnresolvedOperand{};
if (parser.parseOperand(*workerNum) ||
parser.parseColonType(workerNumType) || parser.parseRParen())
@@ -820,8 +826,10 @@ parseWorkerClause(OpAsmParser &parser,
void printWorkerClause(OpAsmPrinter &p, Operation *op, Value workerNum,
Type workerNumType, UnitAttr hasWorker) {
+ p << "(";
if (workerNum)
- p << "(" << workerNum << " : " << workerNumType << ")";
+ p << workerNum << " : " << workerNumType;
+ p << ")";
}
static ParseResult
@@ -830,6 +838,9 @@ parseVectorClause(OpAsmParser &parser,
Type &vectorLengthType, UnitAttr &hasVector) {
hasVector = UnitAttr::get(parser.getBuilder().getContext());
if (succeeded(parser.parseOptionalLParen())) {
+ // Allow empty parenthesis.
+ if (succeeded(parser.parseOptionalRParen()))
+ return success();
vectorLength = OpAsmParser::UnresolvedOperand{};
if (parser.parseOperand(*vectorLength) ||
parser.parseColonType(vectorLengthType) || parser.parseRParen())
@@ -840,11 +851,18 @@ parseVectorClause(OpAsmParser &parser,
void printVectorClause(OpAsmPrinter &p, Operation *op, Value vectorLength,
Type vectorLengthType, UnitAttr hasVector) {
+ p << "(";
if (vectorLength)
- p << "(" << vectorLength << " : " << vectorLengthType << ")";
+ p << vectorLength << " : " << vectorLengthType;
+ p << ")";
}
LogicalResult acc::LoopOp::verify() {
+ if (!getUpperbound().empty() &&
+ (getUpperbound().size() != getInclusiveUpperbound()->size()))
+ return emitError() << "inclusiveUpperbound size is expected to be the same"
+ << " as upperbound size";
+
// auto, independent and seq attribute are mutually exclusive.
if ((getAuto_() && (getIndependent() || getSeq())) ||
(getIndependent() && getSeq())) {
@@ -875,6 +893,58 @@ LogicalResult acc::LoopOp::verify() {
return success();
}
+llvm::SmallVector<mlir::Region *> acc::LoopOp::getLoopRegions() {
+ return {&getRegion()};
+}
+
+/// loop-control ::= `(` ssa-id-and-type-list `)` `=` `(` ssa-id-and-type-list
+/// `)` `to` `(` ssa-id-and-type-list `)` `step` `(` ssa-id-and-type-list `)`
+ParseResult
+parseLoopControl(OpAsmParser &parser, Region ®ion,
+ SmallVectorImpl<OpAsmParser::UnresolvedOperand> &lowerbound,
+ SmallVectorImpl<Type> &lowerboundType,
+ SmallVectorImpl<OpAsmParser::UnresolvedOperand> &upperbound,
+ SmallVectorImpl<Type> &upperboundType,
+ SmallVectorImpl<OpAsmParser::UnresolvedOperand> &step,
+ SmallVectorImpl<Type> &stepType) {
+
+ SmallVector<OpAsmParser::Argument> inductionVars;
+ if (succeeded(parser.parseOptionalLParen())) {
+ if (parser.parseArgumentList(inductionVars, OpAsmParser::Delimiter::None,
+ /*allowType=*/true) ||
+ parser.parseRParen() || parser.parseEqual() || parser.parseLParen() ||
+ parser.parseOperandList(lowerbound, inductionVars.size(),
+ OpAsmParser::Delimiter::None) ||
+ parser.parseColonTypeList(lowerboundType) || parser.parseRParen() ||
+ parser.parseKeyword("to") || parser.parseLParen() ||
+ parser.parseOperandList(upperbound, inductionVars.size(),
+ OpAsmParser::Delimiter::None) ||
+ parser.parseColonTypeList(upperboundType) || parser.parseRParen() ||
+ parser.parseKeyword("step") || parser.parseLParen() ||
+ parser.parseOperandList(step, inductionVars.size(),
+ OpAsmParser::Delimiter::None) ||
+ parser.parseColonTypeList(stepType) || parser.parseRParen())
+ return failure();
+ }
+ return parser.parseRegion(region, inductionVars);
+}
+
+void printLoopControl(OpAsmPrinter &p, Operation *op, Region ®ion,
+ ValueRange lowerbound, TypeRange lowerboundType,
+ ValueRange upperbound, TypeRange upperboundType,
+ ValueRange steps, TypeRange stepType) {
+ ValueRange regionArgs = region.front().getArguments();
+ if (!regionArgs.empty()) {
+ p << "(";
+ llvm::interleaveComma(regionArgs, p,
+ [&p](Value v) { p << v << " : " << v.getType(); });
+ p << ") = (" << lowerbound << " : " << lowerboundType << ") to ("
+ << upperbound << " : " << upperboundType << ") "
+ << " step (" << steps << " : " << stepType << ") ";
+ }
+ p.printRegion(region, /*printEntryBlockArgs=*/false);
+}
+
//===----------------------------------------------------------------------===//
// DataOp
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/OpenACC/canonicalize.mlir b/mlir/test/Dialect/OpenACC/canonicalize.mlir
index 6173ab6699c6c58..4522ffb252a62e3 100644
--- a/mlir/test/Dialect/OpenACC/canonicalize.mlir
+++ b/mlir/test/Dialect/OpenACC/canonicalize.mlir
@@ -110,14 +110,16 @@ func.func @testupdateop(%a: memref<f32>, %ifCond: i1) -> () {
func.func @testhostdataop(%a: memref<f32>, %ifCond: i1) -> () {
%0 = acc.use_device varPtr(%a : memref<f32>) -> memref<f32>
+ %1 = arith.constant 1 : i32
+ %2 = arith.constant 10 : i32
%false = arith.constant false
acc.host_data dataOperands(%0 : memref<f32>) if(%false) {
- acc.loop {
+ acc.loop (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
acc.yield
- }
- acc.loop {
+ } attributes { inclusiveUpperbound = array<i1: true> }
+ acc.loop (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
acc.yield
- }
+ } attributes { inclusiveUpperbound = array<i1: true> }
acc.terminator
}
return
diff --git a/mlir/test/Dialect/OpenACC/invalid.mlir b/mlir/test/Dialect/OpenACC/invalid.mlir
index 46c1bb51f0e4c07..c3bddd0c6256f09 100644
--- a/mlir/test/Dialect/OpenACC/invalid.mlir
+++ b/mlir/test/Dialect/OpenACC/invalid.mlir
@@ -1,71 +1,81 @@
// RUN: mlir-opt -split-input-file -verify-diagnostics %s
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
// expected-error at +1 {{gang, worker or vector cannot appear with the seq attr}}
-acc.loop gang {
+acc.loop gang() (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
"test.openacc_dummy_op"() : () -> ()
acc.yield
-} attributes {seq}
+} attributes {seq, inclusiveUpperbound = array<i1: true>}
// -----
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
// expected-error at +1 {{gang, worker or vector cannot appear with the seq attr}}
-acc.loop worker {
+acc.loop worker() (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
"test.openacc_dummy_op"() : () -> ()
acc.yield
-} attributes {seq}
+} attributes {seq, inclusiveUpperbound = array<i1: true>}
// -----
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
// expected-error at +1 {{gang, worker or vector cannot appear with the seq attr}}
-acc.loop vector {
+acc.loop vector() (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
"test.openacc_dummy_op"() : () -> ()
acc.yield
-} attributes {seq}
+} attributes {seq, inclusiveUpperbound = array<i1: true>}
// -----
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
// expected-error at +1 {{gang, worker or vector cannot appear with the seq attr}}
-acc.loop gang worker {
+acc.loop gang() worker() (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
"test.openacc_dummy_op"() : () -> ()
acc.yield
-} attributes {seq}
+} attributes {seq, inclusiveUpperbound = array<i1: true>}
// -----
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
// expected-error at +1 {{gang, worker or vector cannot appear with the seq attr}}
-acc.loop gang vector {
+acc.loop gang() vector() (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
"test.openacc_dummy_op"() : () -> ()
acc.yield
-} attributes {seq}
+} attributes {seq, inclusiveUpperbound = array<i1: true>}
// -----
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
// expected-error at +1 {{gang, worker or vector cannot appear with the seq attr}}
-acc.loop worker vector {
+acc.loop worker() vector() (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
"test.openacc_dummy_op"() : () -> ()
acc.yield
-} attributes {seq}
+} attributes {seq, inclusiveUpperbound = array<i1: true>}
// -----
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
// expected-error at +1 {{gang, worker or vector cannot appear with the seq attr}}
-acc.loop gang worker vector {
+acc.loop gang() worker() vector() (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
"test.openacc_dummy_op"() : () -> ()
acc.yield
-} attributes {seq}
-
-// -----
-
-// expected-error at +1 {{expected non-empty body.}}
-acc.loop {
-}
+} attributes {seq, inclusiveUpperbound = array<i1: true>}
// -----
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
// expected-error at +1 {{only one of "auto", "independent", "seq" can be present at the same time}}
-acc.loop {
+acc.loop (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
acc.yield
-} attributes {auto_, seq}
+} attributes {auto_, seq, inclusiveUpperbound = array<i1: true>}
// -----
@@ -133,11 +143,13 @@ acc.parallel {
// -----
-acc.loop {
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
+acc.loop (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32){
// expected-error at +1 {{'acc.init' op cannot be nested in a compute operation}}
acc.init
acc.yield
-}
+} attributes {inclusiveUpperbound = array<i1: true>}
// -----
@@ -149,21 +161,25 @@ acc.parallel {
// -----
-acc.loop {
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
+acc.loop (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
// expected-error at +1 {{'acc.shutdown' op cannot be nested in a compute operation}}
acc.shutdown
acc.yield
-}
+} attributes {inclusiveUpperbound = array<i1: true>}
// -----
-acc.loop {
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
+acc.loop (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
"test.openacc_dummy_op"() ({
// expected-error at +1 {{'acc.shutdown' op cannot be nested in a compute operation}}
acc.shutdown
}) : () -> ()
acc.yield
-}
+} attributes {inclusiveUpperbound = array<i1: true>}
// -----
@@ -395,8 +411,10 @@ acc.firstprivate.recipe @privatization_i32 : i32 init {
// -----
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
// expected-error at +1 {{expected ')'}}
-acc.loop gang(static=%i64Value: i64, num=%i64Value: i64 {
+acc.loop gang(static=%i64Value: i64, num=%i64Value: i64 (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
"test.openacc_dummy_op"() : () -> ()
acc.yield
}
@@ -464,8 +482,10 @@ acc.reduction.recipe @reduction_i64 : i64 reduction_operator<add> init {
// -----
+%1 = arith.constant 1 : i32
+%2 = arith.constant 10 : i32
// expected-error at +1 {{new value expected after comma}}
-acc.loop gang(static=%i64Value: i64, ) {
+acc.loop gang(static=%i64Value: i64, ) (%iv : i32) = (%1 : i32) to (%2 : i32) step (%1 : i32) {
"test.openacc_dummy_op"() : () -> ()
acc.yield
}
@@ -481,14 +501,6 @@ func.func @fct1(%0 : !llvm.ptr<i32>) -> () {
// -----
-// expected-error at +1 {{expect at least one of num, dim or static values}}
-acc.loop gang() {
- "test.openacc_dummy_op"() : () -> ()
- acc.yield
-}
-
-// -----
-
%i64value = arith.constant 1 : i64
// expected-error at +1 {{num_gangs expects a maximum of 3 values}}
acc.parallel num_gangs(%i64value, %i64value, %i64value, %i64value : i64, i64, i64, i64) {
diff --git a/mlir/test/Dialect/OpenACC/ops.mlir b/mlir/test/Dialect/OpenACC/ops.mlir
index d1950b1fb3f2916..78a95a4ecbb4c63 100644
--- a/mlir/test/Dialect/OpenACC/ops.mlir
+++ b/mlir/test/Dialect/OpenACC/ops.mlir
@@ -11,52 +11,40 @@ func.func @compute1(%A: memref<10x10xf32>, %B: memref<10x10xf32>, %C: memref<10x
%async = arith.constant 1 : i64
acc.parallel async(%async: i64) {
- acc.loop gang vector {
- scf.for %arg3 = %c0 to %c10 step %c1 {
- scf.for %arg4 = %c0 to %c10 step %c1 {
- scf.for %arg5 = %c0 to %c10 step %c1 {
- %a = memref.load %A[%arg3, %arg5] : memref<10x10xf32>
- %b = memref.load %B[%arg5, %arg4] : memref<10x10xf32>
- %cij = memref.load %C[%arg3, %arg4] : memref<10x10xf32>
- %p = arith.mulf %a, %b : f32
- %co = arith.addf %cij, %p : f32
- memref.store %co, %C[%arg3, %arg4] : memref<10x10xf32>
- }
- }
- }
+ acc.loop gang() vector() (%arg3 : index, %arg4 : index, %arg5 : index) = (%c0, %c0, %c0 : index, index, index) to (%c10, %c10, %c10 : index, index, index) step (%c1, %c1, %c1 : index, index, index) {
+ %a = memref.load %A[%arg3, %arg5] : memref<10x10xf32>
+ %b = memref.load %B[%arg5, %arg4] : memref<10x10xf32>
+ %cij = memref.load %C[%arg3, %arg4] : memref<10x10xf32>
+ %p = arith.mulf %a, %b : f32
+ %co = arith.addf %cij, %p : f32
+ memref.store %co, %C[%arg3, %arg4] : memref<10x10xf32>
acc.yield
- } attributes { collapse = 3 }
+ } attributes { collapse = 3, inclusiveUpperbound = array<i1: true, true, true> }
acc.yield
}
return %C : memref<10x10xf32>
}
-// CHECK-LABEL: func @compute1(
+// CHECK-LABE...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/67355
More information about the Mlir-commits
mailing list