Skip to content

Commit c7629b5

Browse files
committed
Verify loops bounds outside of core conversion.
1 parent 56bf019 commit c7629b5

6 files changed

Lines changed: 107 additions & 16 deletions

File tree

compiler/include/graphalg/GraphAlgPasses.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ def GraphAlgToCore : Pass<"graphalg-to-core", "::mlir::func::FuncOp"> {
3333
let summary = "Desugar GraphAlg IR into the Core operations";
3434
}
3535

36+
def GraphAlgVerifyLoopBounds : Pass<"graphalg-verify-loop-bounds", "::mlir::func::FuncOp"> {
37+
let summary = "Verifies that loops do not use dynamic ranges";
38+
39+
let description = [{
40+
ForOps can specify dynamic loop bounds that depend on arbitrary values
41+
in the program. This is useful during parsing, and it allows using
42+
parameters that will later be inlined as constants. GraphAlg Core,
43+
however, requires that loop bounds are either a constant integer value
44+
or the dimensions of a matrix. This pass enforces that requirement.
45+
}];
46+
}
47+
3648
def GraphAlgExplicateSparsity : Pass<"graphalg-explicate-sparsity", "mlir::func::FuncOp"> {
3749
let summary = "Makes explicit the sparsity of matrices";
3850
}

compiler/src/graphalg/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ add_library(GraphAlgPasses
4343
GraphAlgToCore.cpp
4444
GraphAlgToCorePipeline.cpp
4545
GraphAlgVerifyDimensions.cpp
46+
GraphAlgVerifyLoopBounds.cpp
4647
)
4748
add_dependencies(GraphAlgPasses MLIRGraphAlgPassesIncGen)
4849
target_link_libraries(

compiler/src/graphalg/GraphAlgToCore.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,6 @@ void GraphAlgToCore::runOnOperation() {
254254
target.addIllegalDialect<graphalg::GraphAlgDialect>();
255255
target.addDynamicallyLegalDialect<graphalg::GraphAlgDialect>(
256256
[](mlir::Operation *op) { return op->hasTrait<IsCore>(); });
257-
target.addDynamicallyLegalOp<ForOp>(
258-
[](ForOp op) { return !op.isDynamicRange(); });
259257

260258
mlir::RewritePatternSet patterns(&getContext());
261259
patterns.add(convertVecMatMul);
@@ -268,20 +266,6 @@ void GraphAlgToCore::runOnOperation() {
268266
patterns.add(convertTriu);
269267
patterns.add(convertLiteral);
270268

271-
// Conversion will give very unclear errors about dynamic range for loops, so
272-
// do our own analysis first.
273-
bool haveDynamicRangeLoops = false;
274-
getOperation()->walk([&](ForOp op) {
275-
if (op.isDynamicRange()) {
276-
op.emitOpError("loop bound must be a constant in GraphAlg Core");
277-
haveDynamicRangeLoops = true;
278-
}
279-
});
280-
281-
if (haveDynamicRangeLoops) {
282-
return signalPassFailure();
283-
}
284-
285269
if (mlir::failed(mlir::applyFullConversion(getOperation(), target,
286270
std::move(patterns)))) {
287271
signalPassFailure();
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <mlir/Dialect/Func/IR/FuncOps.h>
2+
#include <mlir/Pass/Pass.h>
3+
4+
#include "graphalg/GraphAlgOps.h"
5+
6+
namespace graphalg {
7+
8+
#define GEN_PASS_DEF_GRAPHALGVERIFYLOOPBOUNDS
9+
#include "graphalg/GraphAlgPasses.h.inc"
10+
11+
namespace {
12+
13+
class GraphAlgVerifyLoopBounds
14+
: public impl::GraphAlgVerifyLoopBoundsBase<GraphAlgVerifyLoopBounds> {
15+
using impl::GraphAlgVerifyLoopBoundsBase<
16+
GraphAlgVerifyLoopBounds>::GraphAlgVerifyLoopBoundsBase;
17+
18+
void runOnOperation() final;
19+
};
20+
21+
} // namespace
22+
23+
void GraphAlgVerifyLoopBounds::runOnOperation() {
24+
getOperation()->walk([&](ForOp op) {
25+
if (op.isDynamicRange()) {
26+
op.emitOpError("loop bound is not a constant or matrix dimension");
27+
signalPassFailure();
28+
}
29+
});
30+
}
31+
32+
} // namespace graphalg
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: graphalg-opt --graphalg-verify-loop-bounds --split-input-file --verify-diagnostics < %s
2+
#dim = #graphalg.dim<distinct[0]<>>
3+
4+
func.func @OkDim(%arg0: !graphalg.mat<#dim x 1 x i64>) -> !graphalg.mat<1 x 1 x i64> {
5+
%0 = graphalg.const_mat 0 : i64 -> <1 x 1 x i64>
6+
%1 = graphalg.for begin=0 iters=#dim init(%0) : !graphalg.mat<1 x 1 x i64> -> !graphalg.mat<1 x 1 x i64> body {
7+
^bb0(%arg1: !graphalg.mat<1 x 1 x i64>, %arg2: !graphalg.mat<1 x 1 x i64>):
8+
graphalg.yield %arg2 : !graphalg.mat<1 x 1 x i64>
9+
} until {
10+
}
11+
return %1 : !graphalg.mat<1 x 1 x i64>
12+
}
13+
14+
func.func @OkConst(%arg0: !graphalg.mat<#dim x 1 x i64>) -> !graphalg.mat<1 x 1 x i64> {
15+
%0 = graphalg.const_mat 0 : i64 -> <1 x 1 x i64>
16+
%1 = graphalg.for begin=0 iters=<42> init(%0) : !graphalg.mat<1 x 1 x i64> -> !graphalg.mat<1 x 1 x i64> body {
17+
^bb0(%arg1: !graphalg.mat<1 x 1 x i64>, %arg2: !graphalg.mat<1 x 1 x i64>):
18+
graphalg.yield %arg2 : !graphalg.mat<1 x 1 x i64>
19+
} until {
20+
}
21+
return %1 : !graphalg.mat<1 x 1 x i64>
22+
}
23+
24+
// -----
25+
#dim = #graphalg.dim<distinct[0]<>>
26+
27+
func.func @DynDim(%arg0 : !graphalg.mat<1 x 1 x i64>) -> !graphalg.mat<1 x 1 x i64> {
28+
%0 = graphalg.const_mat 0 : i64 -> <1 x 1 x i64>
29+
// expected-error@below{{'graphalg.for' op loop bound is not a constant or matrix dimension}}
30+
%1 = graphalg.for dyn_end=%arg0 begin=0 init(%0) : !graphalg.mat<1 x 1 x i64> -> !graphalg.mat<1 x 1 x i64> body {
31+
^bb0(%arg1: !graphalg.mat<1 x 1 x i64>, %arg2: !graphalg.mat<1 x 1 x i64>):
32+
graphalg.yield %arg2 : !graphalg.mat<1 x 1 x i64>
33+
} until {
34+
}
35+
return %1 : !graphalg.mat<1 x 1 x i64>
36+
}

playground/cpp/graphalg-playground.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "graphalg/GraphAlgAttr.h"
2626
#include "graphalg/GraphAlgDialect.h"
2727
#include "graphalg/GraphAlgPasses.h"
28+
#include "graphalg/GraphAlgSetConstArg.h"
2829
#include "graphalg/GraphAlgTypes.h"
2930
#include "graphalg/SemiringTypes.h"
3031
#include "graphalg/evaluate/Evaluator.h"
@@ -205,6 +206,31 @@ bool Playground::evaluate() {
205206
}
206207

207208
_argBuilders.clear();
209+
210+
// Inline constant arguments.
211+
llvm::SmallVector<mlir::TypedAttr> constArgs;
212+
for (auto arg : args) {
213+
graphalg::MatrixAttrReader reader(arg);
214+
if (reader.nRows() == 1 && reader.nCols() == 1) {
215+
constArgs.push_back(reader.at(0, 0));
216+
} else {
217+
// Not constant
218+
constArgs.push_back(mlir::TypedAttr());
219+
}
220+
}
221+
222+
if (mlir::failed(graphalg::setConstantArguments(_funcOp, constArgs))) {
223+
return false;
224+
}
225+
226+
// Verify that loop bounds are OK now.
227+
mlir::PassManager pm(&_ctx);
228+
pm.addPass(mlir::createCanonicalizerPass()); // To propagate constants
229+
pm.addPass(graphalg::createGraphAlgVerifyLoopBounds());
230+
if (mlir::failed(pm.run(_funcOp))) {
231+
return false;
232+
}
233+
208234
_result = graphalg::evaluate(_funcOp, args);
209235
if (!_result) {
210236
return false;

0 commit comments

Comments
 (0)