Skip to content

Commit 38aa6f6

Browse files
ulysseBcopybara-github
authored andcommitted
Fold re-materialization into loop unification pass.
Generalizes loop normalization pass so that it also performs rematerialization. Remove the former re-materialization pass. In the process, also: * Update `MappingExpr::GetRangeParameters` to take the domain as a list of value accesses (= value + mapping) instead of having values and mappings in two different arguments. This is to match how the loop-nest domain is exposed by LoopFusionAnalysis. * Change the code in many places to use llvm::SmallVector default size. This avoids mismatch when passing vectors between functions. PiperOrigin-RevId: 361104418
1 parent 1c61f0d commit 38aa6f6

15 files changed

+309
-935
lines changed

sair_attributes.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,13 @@ mlir::AffineExpr MappingDimExpr::AsAffineExpr() const {
136136
}
137137

138138
RangeParameters MappingDimExpr::GetRangeParameters(
139-
mlir::Location loc, mlir::ValueRange domain, DomainShapeAttr shape,
139+
mlir::Location loc, llvm::ArrayRef<ValueAccess> domain,
140140
MappingAttr inverse_mapping, mlir::OpBuilder &builder,
141141
MapArguments &map_arguments) const {
142-
auto range_op = mlir::cast<RangeOp>(domain[dimension()].getDefiningOp());
143-
auto mapping = shape.Dimension(dimension())
144-
.dependency_mapping()
145-
.ResizeUseDomain(map_arguments.Indices().size());
142+
const ValueAccess &dim_access = domain[dimension()];
143+
auto range_op = mlir::cast<RangeOp>(dim_access.value.getDefiningOp());
144+
auto mapping =
145+
dim_access.mapping.ResizeUseDomain(map_arguments.Indices().size());
146146
assert(mapping.IsFullySpecified());
147147
return {
148148
.begin = map_arguments.AddArgument(range_op.LowerBound().Map(mapping)),
@@ -358,12 +358,12 @@ MappingExpr MappingStripeExpr::Canonicalize() const {
358358
}
359359

360360
RangeParameters MappingStripeExpr::GetRangeParameters(
361-
mlir::Location loc, mlir::ValueRange domain, DomainShapeAttr shape,
361+
mlir::Location loc, llvm::ArrayRef<ValueAccess> domain,
362362
MappingAttr inverse_mapping, mlir::OpBuilder &builder,
363363
MapArguments &map_arguments) const {
364364
// Compute range parameters for the operand.
365365
RangeParameters operand_parameters = operand().GetRangeParameters(
366-
loc, domain, shape, inverse_mapping, builder, map_arguments);
366+
loc, domain, inverse_mapping, builder, map_arguments);
367367
int step = this->step() * operand_parameters.step;
368368

369369
// If the stripe covers the entire operand range, no additional computation is
@@ -664,11 +664,11 @@ MappingExpr MappingUnStripeExpr::Canonicalize() const {
664664
}
665665

666666
RangeParameters MappingUnStripeExpr::GetRangeParameters(
667-
mlir::Location loc, mlir::ValueRange domain, DomainShapeAttr shape,
667+
mlir::Location loc, llvm::ArrayRef<ValueAccess> domain,
668668
MappingAttr inverse_mapping, mlir::OpBuilder &builder,
669669
MapArguments &map_arguments) const {
670670
RangeParameters inner_parameters = operands()[0].GetRangeParameters(
671-
loc, domain, shape, inverse_mapping, builder, map_arguments);
671+
loc, domain, inverse_mapping, builder, map_arguments);
672672
inner_parameters.step = 1;
673673
return inner_parameters;
674674
}

sair_attributes.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,7 @@ class MappingDimExpr
376376
MappingExpr Canonicalize() const { return *this; }
377377

378378
RangeParameters GetRangeParameters(mlir::Location loc,
379-
mlir::ValueRange domain,
380-
DomainShapeAttr shape,
379+
llvm::ArrayRef<ValueAccess> domain,
381380
MappingAttr inverse_mapping,
382381
mlir::OpBuilder &builder,
383382
MapArguments &map_arguments) const;
@@ -441,8 +440,7 @@ class MappingNoneExpr
441440
MappingExpr Canonicalize() const { return *this; }
442441

443442
RangeParameters GetRangeParameters(mlir::Location loc,
444-
mlir::ValueRange domain,
445-
DomainShapeAttr shape,
443+
llvm::ArrayRef<ValueAccess> domain,
446444
MappingAttr inverse_mapping,
447445
mlir::OpBuilder &builder,
448446
MapArguments &map_arguments) const {
@@ -508,8 +506,7 @@ class MappingStripeExpr
508506
MappingExpr Canonicalize() const;
509507

510508
RangeParameters GetRangeParameters(mlir::Location loc,
511-
mlir::ValueRange domain,
512-
DomainShapeAttr shape,
509+
llvm::ArrayRef<ValueAccess> domain,
513510
MappingAttr inverse_mapping,
514511
mlir::OpBuilder &builder,
515512
MapArguments &map_arguments) const;
@@ -568,8 +565,7 @@ class MappingUnStripeExpr
568565
MappingExpr Canonicalize() const;
569566

570567
RangeParameters GetRangeParameters(mlir::Location loc,
571-
mlir::ValueRange domain,
572-
DomainShapeAttr shape,
568+
llvm::ArrayRef<ValueAccess> domain,
573569
MappingAttr inverse_mapping,
574570
mlir::OpBuilder &builder,
575571
MapArguments &map_arguments) const;

sair_base.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ def MappingExpr : AttrInterface<"MappingExpr"> {
142142
After returning, builder insertion point is after newly added
143143
instructions.}],
144144
"RangeParameters", "GetRangeParameters",
145-
(ins "mlir::Location":$loc, "mlir::ValueRange":$domain,
146-
"DomainShapeAttr":$shape, "MappingAttr":$inverse_mapping,
147-
"mlir::OpBuilder&":$builder, "MapArguments&":$map_arguments)
145+
(ins "mlir::Location":$loc, "llvm::ArrayRef<ValueAccess>":$domain,
146+
"MappingAttr":$inverse_mapping, "mlir::OpBuilder&":$builder,
147+
"MapArguments&":$map_arguments)
148148
>
149149
];
150150
}
@@ -352,7 +352,7 @@ def SairOpInterface : OpInterface<"SairOp"> {
352352
[{Creates a copy of the operation with a new domain. May steal the body of
353353
the current operation but does not erase it.}],
354354
"SairOp", "ReCreateWithNewDomain", (ins
355-
"llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>>":$new_domains,
355+
"llvm::ArrayRef<llvm::SmallVector<mlir::Value>>":$new_domains,
356356
"DomainShapeAttr":$new_shape,
357357
"MappingAttr":$new_to_old_mapping,
358358
"mlir::OpBuilder &":$builder

sair_ops.cc

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,7 @@ DomainShapeAttr SairFreeOp::shape() {
16561656
// array containing the composition of `lhs` with each element of `rhs_array`.
16571657
static mlir::ArrayAttr ComposeMappings(MappingAttr lhs,
16581658
mlir::ArrayAttr rhs_array) {
1659-
llvm::SmallVector<mlir::Attribute, 4> new_mappings;
1659+
llvm::SmallVector<mlir::Attribute> new_mappings;
16601660
new_mappings.reserve(rhs_array.size());
16611661
for (mlir::Attribute rhs : rhs_array.getValue()) {
16621662
new_mappings.push_back(lhs.Compose(rhs.cast<MappingAttr>()).Canonicalize());
@@ -1670,7 +1670,7 @@ static mlir::ArrayAttr ComposeLoopNest(MappingAttr new_to_old_mapping,
16701670
if (old_loop_nest == nullptr) return nullptr;
16711671
mlir::MLIRContext *context = old_loop_nest.getContext();
16721672

1673-
llvm::SmallVector<mlir::Attribute, 4> new_loop_nest;
1673+
llvm::SmallVector<mlir::Attribute> new_loop_nest;
16741674
new_loop_nest.reserve(old_loop_nest.size());
16751675
for (mlir::Attribute attr : old_loop_nest.getValue()) {
16761676
LoopAttr loop = attr.cast<LoopAttr>();
@@ -1683,31 +1683,31 @@ static mlir::ArrayAttr ComposeLoopNest(MappingAttr new_to_old_mapping,
16831683
}
16841684

16851685
SairOp SairDynRangeOp::ReCreateWithNewDomain(
1686-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1686+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
16871687
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
16881688
mlir::OpBuilder &builder) {
16891689
llvm_unreachable(
16901690
"not called by NormalizeLoops because the op defines a dimension");
16911691
}
16921692

16931693
SairOp SairStaticRangeOp::ReCreateWithNewDomain(
1694-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1694+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
16951695
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
16961696
mlir::OpBuilder &builder) {
16971697
llvm_unreachable(
16981698
"not called by NormalizeLoops because the op defines a dimension");
16991699
}
17001700

17011701
SairOp SairPlaceholderOp::ReCreateWithNewDomain(
1702-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1702+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
17031703
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
17041704
mlir::OpBuilder &builder) {
17051705
llvm_unreachable(
17061706
"not called by NormalizeLoops because the op defines a dimension");
17071707
}
17081708

17091709
SairOp SairCopyOp::ReCreateWithNewDomain(
1710-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1710+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
17111711
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
17121712
mlir::OpBuilder &builder) {
17131713
assert(new_domains.size() == 1);
@@ -1726,7 +1726,7 @@ SairOp SairCopyOp::ReCreateWithNewDomain(
17261726
}
17271727

17281728
SairOp SairFromScalarOp::ReCreateWithNewDomain(
1729-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1729+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
17301730
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
17311731
mlir::OpBuilder &builder) {
17321732
llvm_unreachable(
@@ -1738,7 +1738,7 @@ namespace {
17381738
// value would be preserved if an op is created with the given new domains.
17391739
template <typename OpTy>
17401740
void CheckMemRefDomainPreserved(
1741-
OpTy op, llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1741+
OpTy op, llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
17421742
MappingAttr new_to_old_mapping) {
17431743
assert(new_domains.size() == 2);
17441744
// Assert that memref domain is left untouched.
@@ -1757,24 +1757,14 @@ void CheckMemRefDomainPreserved(
17571757
} // end namespace
17581758

17591759
SairOp SairFromMemRefOp::ReCreateWithNewDomain(
1760-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1760+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
17611761
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
17621762
mlir::OpBuilder &builder) {
1763-
CheckMemRefDomainPreserved(*this, new_domains, new_to_old_mapping);
1764-
1765-
mlir::ArrayAttr new_mappings =
1766-
ComposeMappings(new_to_old_mapping, mapping_array());
1767-
auto return_type =
1768-
ValueType::get(new_shape, getType().cast<ValueType>().ElementType());
1769-
auto new_op = builder.create<SairFromMemRefOp>(
1770-
getLoc(), return_type, new_domains[0], new_domains[1], new_mappings,
1771-
memref(), access_mapAttr());
1772-
ForwardAttributes(getOperation(), new_op.getOperation());
1773-
return llvm::cast<SairOp>(new_op.getOperation());
1763+
llvm_unreachable("must be erased before calling loop normalization");
17741764
}
17751765

17761766
SairOp SairLoadFromMemRefOp::ReCreateWithNewDomain(
1777-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1767+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
17781768
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
17791769
mlir::OpBuilder &builder) {
17801770
CheckMemRefDomainPreserved(*this, new_domains, new_to_old_mapping);
@@ -1794,22 +1784,14 @@ SairOp SairLoadFromMemRefOp::ReCreateWithNewDomain(
17941784
}
17951785

17961786
SairOp SairToMemRefOp::ReCreateWithNewDomain(
1797-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1787+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
17981788
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
17991789
mlir::OpBuilder &builder) {
1800-
CheckMemRefDomainPreserved(*this, new_domains, new_to_old_mapping);
1801-
1802-
mlir::ArrayAttr new_mappings =
1803-
ComposeMappings(new_to_old_mapping, mapping_array());
1804-
auto new_op = builder.create<SairToMemRefOp>(
1805-
getLoc(), new_domains[0], new_domains[1], new_mappings, memref(), value(),
1806-
shape(), access_mapAttr());
1807-
ForwardAttributes(getOperation(), new_op.getOperation());
1808-
return llvm::cast<SairOp>(new_op.getOperation());
1790+
llvm_unreachable("must be erased before calling loop normalization");
18091791
}
18101792

18111793
SairOp SairStoreToMemRefOp::ReCreateWithNewDomain(
1812-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1794+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
18131795
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
18141796
mlir::OpBuilder &builder) {
18151797
CheckMemRefDomainPreserved(*this, new_domains, new_to_old_mapping);
@@ -1850,7 +1832,7 @@ static void MoveMapBody(mlir::Location loc, mlir::Block &old_body,
18501832
}
18511833

18521834
SairOp SairMapOp::ReCreateWithNewDomain(
1853-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1835+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
18541836
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
18551837
mlir::OpBuilder &builder) {
18561838
assert(new_domains.size() == 1);
@@ -1874,7 +1856,7 @@ SairOp SairMapOp::ReCreateWithNewDomain(
18741856
}
18751857

18761858
SairOp SairMapReduceOp::ReCreateWithNewDomain(
1877-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1859+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
18781860
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
18791861
mlir::OpBuilder &builder) {
18801862
assert(new_domains.size() == 2);
@@ -1909,7 +1891,7 @@ SairOp SairMapReduceOp::ReCreateWithNewDomain(
19091891
}
19101892

19111893
SairOp SairProjLastOp::ReCreateWithNewDomain(
1912-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1894+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
19131895
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
19141896
mlir::OpBuilder &builder) {
19151897
assert(new_domains.size() == 2);
@@ -1927,7 +1909,7 @@ SairOp SairProjLastOp::ReCreateWithNewDomain(
19271909
}
19281910

19291911
SairOp SairProjAnyOp::ReCreateWithNewDomain(
1930-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1912+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
19311913
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
19321914
mlir::OpBuilder &builder) {
19331915
assert(new_domains.size() == 2);
@@ -1945,7 +1927,7 @@ SairOp SairProjAnyOp::ReCreateWithNewDomain(
19451927
}
19461928

19471929
SairOp SairFbyOp::ReCreateWithNewDomain(
1948-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1930+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
19491931
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
19501932
mlir::OpBuilder &builder) {
19511933
assert(new_domains.size() == 2);
@@ -1962,15 +1944,15 @@ SairOp SairFbyOp::ReCreateWithNewDomain(
19621944
}
19631945

19641946
SairOp SairExitOp::ReCreateWithNewDomain(
1965-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1947+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
19661948
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
19671949
mlir::OpBuilder &builder) {
19681950
llvm_unreachable(
19691951
"not called by NormalizeLoops because sair.exit has a 0D domain");
19701952
}
19711953

19721954
SairOp SairAllocOp::ReCreateWithNewDomain(
1973-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1955+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
19741956
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
19751957
mlir::OpBuilder &builder) {
19761958
assert(new_domains.size() == 1);
@@ -1988,7 +1970,7 @@ SairOp SairAllocOp::ReCreateWithNewDomain(
19881970
}
19891971

19901972
SairOp SairFreeOp::ReCreateWithNewDomain(
1991-
llvm::ArrayRef<llvm::SmallVector<mlir::Value, 4>> new_domains,
1973+
llvm::ArrayRef<llvm::SmallVector<mlir::Value>> new_domains,
19921974
DomainShapeAttr new_shape, MappingAttr new_to_old_mapping,
19931975
mlir::OpBuilder &builder) {
19941976
assert(new_domains.size() == 1);

test/normalize_loops.mlir

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// RUN: sair-opt %s -sair-normalize-loops -cse -mlir-print-local-scope | FileCheck %s
2+
// RUN: sair-opt %s -sair-normalize-loops -cse -mlir-print-op-generic | FileCheck %s --check-prefix=GENERIC
3+
24

35
// CHECK-LABEL: @identity
46
func @identity(%arg0: index, %arg1: f32) {
@@ -102,34 +104,6 @@ func @unstripe(%arg0: f32) {
102104
return
103105
}
104106

105-
// CHECK-LABEL: @from_to_memref
106-
func @from_to_memref(%arg0: index) {
107-
sair.program {
108-
// CHECK: %[[SIZE:.*]] = sair.from_scalar
109-
%size = sair.from_scalar %arg0 : !sair.value<(), index>
110-
// CHECK: %[[D0:.*]] = sair.static_range 4
111-
%0 = sair.static_range 4 : !sair.range
112-
// CHECK: %[[D1:.*]] = sair.dyn_range %{{.*}}
113-
// CHECK: %[[D2:.*]] = sair.dyn_range %{{.*}}
114-
%1 = sair.dyn_range %size : !sair.range
115-
// CHECK: %[[MEMREF:.*]] = sair.alloc[d0:%[[D0]]] %[[SIZE]]
116-
%memref = sair.alloc[d0:%0] %size {
117-
loop_nest = [{name = "A", iter = #sair.mapping_expr<d0>}]
118-
} : !sair.value<d0:range, memref<?xf32>>
119-
// CHECK: %[[V0:.*]] = sair.from_memref[d0:%[[D0]]] %[[MEMREF]](d0) memref[d1:%[[D1]]]
120-
%2 = sair.from_memref[d0:%0] %memref(d0) memref[d1:%1]
121-
: #sair.shape<d0:range x d1:range>, memref<?xf32>
122-
// CHECK: sair.to_memref[d0:%[[D0]]] %[[MEMREF]](d0) memref[d1:%[[D2]]] %[[V0]](d0, d1)
123-
sair.to_memref[d0:%0] %memref(d0) memref[d1:%1] %2(d0, d1)
124-
: #sair.shape<d0:range x d1:range>, memref<?xf32>
125-
sair.free[d0:%0] %memref(d0) {
126-
loop_nest = [{name = "A", iter = #sair.mapping_expr<d0>}]
127-
} : !sair.value<d0:range, memref<?xf32>>
128-
sair.exit
129-
}
130-
return
131-
}
132-
133107
// CHECK-LABEL: @load_store_memref
134108
func @load_store_memref(%arg0: index) {
135109
sair.program {
@@ -188,3 +162,44 @@ func @load_store_memref(%arg0: index) {
188162
}
189163
return
190164
}
165+
// In the generic form, the function (symbol) name is an attribute and is
166+
// printed after the body region.
167+
// GENERIC-LABEL: sym_name = "load_store_memref"
168+
169+
// CHECK-LABEL: @remat
170+
func @remat(%arg0: f32) {
171+
sair.program {
172+
// CHECK: %[[INIT:.*]] = sair.from_scalar
173+
// GENERIC: %[[INIT:.*]] = "sair.from_scalar"
174+
%0 = sair.from_scalar %arg0 : !sair.value<(), f32>
175+
// CHECK: %[[RANGE:.*]] = sair.static_range
176+
// GENERIC: %[[RANGE:.*]] = "sair.static_range"
177+
%1 = sair.static_range 8 : !sair.range
178+
// CHECK: %[[RESULT:.*]] = sair.copy[d0:%[[RANGE]]] %[[INIT]]
179+
// CHECK: loop_nest = [{iter = #sair.mapping_expr<d0>, name = "A"}]
180+
// CHECK: !sair.value<d0:range, f32>
181+
//
182+
// CHECK: %[[P0:.*]] = sair.placeholder : !sair.range
183+
// CHECK: %[[VALUE:.*]] = sair.proj_any of[d0:%[[P0]]] %[[RESULT]](d0)
184+
// CHECK: #sair.shape<d0:range>
185+
//
186+
// Ensure that the mapping has the expected use domain, and that the
187+
// resulting value has the right type.
188+
// GENERIC: "sair.copy"(%[[RANGE]], %[[INIT]])
189+
// GENERIC-SAME: mapping_array = [#sair.mapping<1>]
190+
// GENERIC-SAME: (!sair.range, !sair.value<(), f32>) -> !sair.value<d0:range, f32>
191+
%2 = sair.copy %0 {
192+
loop_nest = [{name = "A", iter = #sair.mapping_expr<none>}]
193+
} : !sair.value<(), f32>
194+
// CHECK: sair.copy[d0:%[[RANGE]]] %[[VALUE]]
195+
%3 = sair.copy[d0:%1] %2 {
196+
loop_nest = [{name = "A", iter = #sair.mapping_expr<d0>}]
197+
} : !sair.value<d0:range, f32>
198+
%4 = sair.proj_last of[d0:%1] %3(d0) : #sair.shape<d0:range>, f32
199+
sair.exit %4 : f32
200+
} : f32
201+
return
202+
}
203+
// In the generic form, the function (symbol) name is an attribute and is
204+
// printed after the body region.
205+
// GENERIC-LABEL: sym_name = "remat"

0 commit comments

Comments
 (0)