Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions mlir/tools/mlir-pet/Lib/islNodeBuilder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,38 @@ void IslNodeBuilder::createFor(isl::ast_node forNode) {

void IslNodeBuilder::createUser(isl::ast_node userNode) {
auto expression = userNode.user_get_expr();
if (isl_ast_expr_get_type(expression.get()) != isl_ast_expr_op)
llvm_unreachable("expect isl_ast_expr_op");
if (isl_ast_expr_get_op_type(expression.get()) != isl_ast_op_call)
llvm_unreachable("expect operation of type call");
/* if (isl_ast_expr_get_type(expression.get()) != isl_ast_expr_op)
llvm_unreachable("expect isl_ast_expr_op");
if (isl_ast_expr_get_op_type(expression.get()) != isl_ast_op_call)
llvm_unreachable("expect operation of type call");*/
auto stmtExpression = expression.get_op_arg(0);

auto n_args = isl_ast_expr_op_get_n_arg(expression.get());

// is there a Minusop in arguments?
LoopTable tempTable = MLIRBuilder_.getLoopTable();
// check in all AST args
for (int i = n_args - 1; i > 0; i--) {
auto arg = expression.get_op_arg(i);
// TODO check if it is a minusOP
if (isl_ast_expr_get_type(arg.get()) == isl_ast_expr_op) {

// modify the index variable:
// find key
std::string key;
// the -1 compensates for the offset in islAST args (0 is the Stmt ID)
if (failed(MLIRBuilder_.getLoopTable().getIdAtPos(i - 1, key))) {
llvm_unreachable("cannot find key");
return;
}
// calculate new opposite Value to be used within the loop
auto val = MLIRBuilder_.createAstOp(arg, i - 1);

// insert the value into Looptable
MLIRBuilder_.getLoopTable().update(key, val);
}
}

auto stmtId = stmtExpression.get_id();
auto stmt = islAst_.getScop().getStmt(stmtId);
if (!stmt)
Expand All @@ -178,6 +205,8 @@ void IslNodeBuilder::createUser(isl::ast_node userNode) {
MLIRBuilder_.dump();
llvm_unreachable("cannot generate statement");
}
// restore loop table
MLIRBuilder_.getLoopTable() = tempTable;
}

void IslNodeBuilder::createBlock(isl::ast_node blockNode) {
Expand Down
41 changes: 41 additions & 0 deletions mlir/tools/mlir-pet/Lib/mlirCodegen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ Value MLIRCodegen::createOp(__isl_take pet_expr *expr, Type t) {
case pet_op_lt:
case pet_op_gt:
case pet_op_minus:
return builder_.create<NegFOp>(location, lhs);
case pet_op_pre_inc:
case pet_op_pre_dec:
case pet_op_address_of:
Expand Down Expand Up @@ -881,6 +882,38 @@ Value MLIRCodegen::createExpr(__isl_keep pet_expr *expr, Type t) {
return nullptr;
}

Value MLIRCodegen::createAstOp(__isl_take isl::noexceptions::ast_expr expr,
int pos) {
auto loc = builder_.getUnknownLoc();
if (isl_ast_expr_get_op_type(expr.get()) == isl_ast_expr_op_minus) {

Value val;
// get the corresponding index variable

SmallVector<Value, 4> vals = SmallVector<Value, 4>();
for (int i = 0; i <= pos; i++) {
loopTable_.getValueAtPos(i, val);
vals.push_back(val);
}
// construct a map d0,d1 -> -d1 for minusOP
SmallVector<AffineExpr, 4> result = SmallVector<AffineExpr, 4>();

for (int i = 0; i < pos; i++) {

result.push_back(builder_.getAffineDimExpr(i));
}
result.push_back(-builder_.getAffineDimExpr(pos));

auto ubMap = AffineMap::get(pos + 1, 0, -builder_.getAffineDimExpr(pos));

// return the ApplyOp value
return builder_.create<AffineApplyOp>(loc, ubMap, vals);

} else {
llvm_unreachable("AST-op type not handled");
return nullptr;
}
}
LogicalResult MLIRCodegen::createStmt(__isl_keep pet_expr *expr) {
LLVM_DEBUG(dbgs() << __func__ << "\n");
auto Value = createExpr(expr);
Expand Down Expand Up @@ -1104,6 +1137,14 @@ LogicalResult LoopTable::getValueAtPos(size_t pos, Value &value) const {
return success();
}

LogicalResult LoopTable::update(std::string key, Value &value) {
if (failed(find(key)))
return failure();
symbolTable_[key] = value;

return success();
}

LogicalResult LoopTable::getIdAtPos(size_t pos, std::string &valueId) const {
if (pos > size())
return failure();
Expand Down
9 changes: 6 additions & 3 deletions mlir/tools/mlir-pet/Lib/mlirCodegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,11 @@ class SymbolTable {
void dump() const;

private:
// the symbol table maps a loop value to the loop id.
std::map<std::string, mlir::Value> symbolTable_;

protected:
// dump helper.
void dumpImpl() const;
// the symbol table maps a loop value to the loop id.
std::map<std::string, mlir::Value> symbolTable_;

public:
decltype(symbolTable_.begin()) begin() { return symbolTable_.begin(); }
Expand All @@ -73,6 +72,8 @@ class LoopTable : public SymbolTable {
// i.e., i mapped with c0.
void insertMapping(std::string idPet, std::string idIsl);

mlir::LogicalResult update(std::string key, mlir::Value &value);

// dump the current state.
void dump() const;

Expand Down Expand Up @@ -108,6 +109,8 @@ class MLIRCodegen {
mlir::AffineExpr ubExpr, std::string ub,
int step);

mlir::Value createAstOp(__isl_take isl::noexceptions::ast_expr expr, int pos);

// return a reference to loop table.
LoopTable &getLoopTable();

Expand Down
21 changes: 21 additions & 0 deletions mlir/tools/mlir-pet/Test/Inputs/negLoop.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
float A[1000][1000];
float a;
int main() {
#pragma scop
a = 0.0;
// for(int i = 0; i < 10; i++){
for (int i = 200; i > 100; i--) {
for (int k = 200; k > 100; k--) {
// for (int k = 101; k <= 200; k++){
a = a + 5.0;
A[k][i] = 2.0f;
}
for (int k = 101; k <= 200; k++) {
a = a + 5.0;
A[i][k] = 2.0f;
}
}

#pragma endscop
return a;
}
47 changes: 47 additions & 0 deletions mlir/tools/mlir-pet/Test/negLoop.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// RUN: mlir-pet %S/Inputs/negLoop.c | FileCheck %s
// CHECK:#map0 = affine_map<(d0) -> (d0)>
// CHECK:#map1 = affine_map<(d0, d1) -> (-d1)>
// CHECK:#map2 = affine_map<(d0) -> (-d0)>
// CHECK:#map3 = affine_map<(d0, d1) -> (d0, d1)>
// CHECK:#map4 = affine_map<() -> (-200)>
// CHECK:#map5 = affine_map<() -> (-99)>
// CHECK:#map6 = affine_map<() -> (101)>
// CHECK:#map7 = affine_map<() -> (201)>


// CHECK:module {
// CHECK: func @scop_entry(%arg0: memref<100x100xf32>, %arg1: memref<1xf32>) {
// CHECK: %cst = constant 0.000000e+00 : f32
// CHECK: %c0 = constant 0 : index
// CHECK: affine.store %cst, %arg1[%c0] : memref<1xf32>
// CHECK: affine.for %arg2 = -200 to -99 {
// CHECK: affine.for %arg3 = -200 to -99 {
// CHECK: %0 = affine.apply #map1(%arg2, %arg3)
// CHECK: %1 = affine.apply #map2(%arg2)
// CHECK: %c0_0 = constant 0 : index
// CHECK: %2 = affine.load %arg1[%c0_0] : memref<1xf32>
// CHECK: %cst_1 = constant 5.000000e+00 : f32
// CHECK: %3 = addf %2, %cst_1 : f32
// CHECK: %c0_2 = constant 0 : index
// CHECK: affine.store %3, %arg1[%c0_2] : memref<1xf32>
// CHECK: %4 = affine.apply #map1(%arg2, %arg3)
// CHECK: %5 = affine.apply #map2(%arg2)
// CHECK: %cst_3 = constant 2.000000e+00 : f32
// CHECK: affine.store %cst_3, %arg0[%4, %5] : memref<100x100xf32>
// CHECK: }
// CHECK: affine.for %arg3 = 101 to 201 {
// CHECK: %0 = affine.apply #map2(%arg2)
// CHECK: %c0_0 = constant 0 : index
// CHECK: %1 = affine.load %arg1[%c0_0] : memref<1xf32>
// CHECK: %cst_1 = constant 5.000000e+00 : f32
// CHECK: %2 = addf %1, %cst_1 : f32
// CHECK: %c0_2 = constant 0 : index
// CHECK: affine.store %2, %arg1[%c0_2] : memref<1xf32>
// CHECK: %3 = affine.apply #map2(%arg2)
// CHECK: %cst_3 = constant 2.000000e+00 : f32
// CHECK: affine.store %cst_3, %arg0[%3, %arg3] : memref<100x100xf32>
// CHECK: }
// CHECK: }
// CHECK: return
// CHECK: }
// CHECK:}
36 changes: 18 additions & 18 deletions mlir/tools/mlir-pet/Test/syrk.mlir
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
// RUN: mlir-pet %S/Inputs/syrk.c | FileCheck %s
// CHECK: #map0 = affine_map<(d0) -> (d0)>
// CHECK: #map1 = affine_map<(d0, d1) -> (d0, d1)>
// CHECK: #map2 = affine_map<() -> (0)>
// CHECK: #map3 = affine_map<(d0) -> (d0 + 1)>
// CHECK: #map4 = affine_map<() -> (1200)>
// CHECK: #map5 = affine_map<() -> (2000)>
// CHECK:#map0 = affine_map<(d0, d1) -> (d0, d1)>
// CHECK:#map1 = affine_map<(d0) -> (d0)>
// CHECK:#map2 = affine_map<() -> (0)>
// CHECK:#map3 = affine_map<(d0) -> (d0 + 1)>
// CHECK:#map4 = affine_map<() -> (1200)>
// CHECK:#map5 = affine_map<() -> (2000)>

// CHECK: module {
// CHECK:module {
// CHECK: func @scop_entry(%arg0: memref<2000x1200xf32>, %arg1: memref<2000x2000xf32>, %arg2: memref<1xf32>, %arg3: memref<1xf32>) {
// CHECK: affine.for %arg4 = 0 to 2000 {
// CHECK: affine.for %arg5 = 0 to #map3(%arg4) {
// CHECK: %0 = affine.load %arg1[%arg4, %arg5] : memref<2000x2000xf32>
// CHECK: %c0 = constant 0 : index
// CHECK: %0 = affine.load %arg3[%c0] : memref<1xf32>
// CHECK: %1 = affine.load %arg1[%arg4, %arg5] : memref<2000x2000xf32>
// CHECK: %2 = mulf %0, %1 : f32
// CHECK: %1 = affine.load %arg3[%c0] : memref<1xf32>
// CHECK: %2 = mulf %1, %0 : f32
// CHECK: affine.store %2, %arg1[%arg4, %arg5] : memref<2000x2000xf32>
// CHECK: }
// CHECK: affine.for %arg5 = 0 to 1200 {
// CHECK: affine.for %arg6 = 0 to #map3(%arg4) {
// CHECK: %0 = affine.load %arg1[%arg4, %arg6] : memref<2000x2000xf32>
// CHECK: %c0 = constant 0 : index
// CHECK: %0 = affine.load %arg2[%c0] : memref<1xf32>
// CHECK: %1 = affine.load %arg0[%arg4, %arg5] : memref<2000x1200xf32>
// CHECK: %2 = mulf %0, %1 : f32
// CHECK: %3 = affine.load %arg0[%arg6, %arg5] : memref<2000x1200xf32>
// CHECK: %4 = mulf %2, %3 : f32
// CHECK: %5 = affine.load %arg1[%arg4, %arg6] : memref<2000x2000xf32>
// CHECK: %6 = addf %4, %5 : f32
// CHECK: %1 = affine.load %arg2[%c0] : memref<1xf32>
// CHECK: %2 = affine.load %arg0[%arg4, %arg5] : memref<2000x1200xf32>
// CHECK: %3 = mulf %1, %2 : f32
// CHECK: %4 = affine.load %arg0[%arg6, %arg5] : memref<2000x1200xf32>
// CHECK: %5 = mulf %3, %4 : f32
// CHECK: %6 = addf %5, %0 : f32
// CHECK: affine.store %6, %arg1[%arg4, %arg6] : memref<2000x2000xf32>
// CHECK: }
// CHECK: }
// CHECK: }
// CHECK: return
// CHECK: }
// CHECK: }
// CHECK:}
50 changes: 26 additions & 24 deletions mlir/tools/mlir-pet/Test/trisolv.mlir
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
// RUN: mlir-pet %S/Inputs/trisolv.c | FileCheck %s
// CHECK: #map0 = affine_map<(d0) -> (d0)>
// CHECK: #map1 = affine_map<(d0, d1) -> (d0, d1)>
// CHECK: #map2 = affine_map<() -> (0)>
// CHECK: #map3 = affine_map<() -> (2000)>
// CHECK: module {
// CHECK: func @scop_entry(%arg0: memref<2000x2000xf32>, %arg1: memref<2000xf32>, %arg2: memref<2000xf32>) {
// CHECK: affine.for %arg3 = 0 to 2000 {
// CHECK: %0 = affine.load %arg1[%arg3] : memref<2000xf32>
// CHECK: affine.store %0, %arg2[%arg3] : memref<2000xf32>
// CHECK: affine.for %arg4 = 0 to #map0(%arg3) {
// CHECK: %4 = affine.load %arg0[%arg3, %arg4] : memref<2000x2000xf32>
// CHECK: %5 = affine.load %arg2[%arg4] : memref<2000xf32>
// CHECK: %6 = mulf %4, %5 : f32
// CHECK: %7 = affine.load %arg2[%arg3] : memref<2000xf32>
// CHECK: %8 = subf %7, %6 : f32
// CHECK: affine.store %8, %arg2[%arg3] : memref<2000xf32>
// CHECK: }
// CHECK: %1 = affine.load %arg0[%arg3, %arg3] : memref<2000x2000xf32>
// CHECK: %2 = affine.load %arg2[%arg3] : memref<2000xf32>
// CHECK: %3 = divf %2, %1 : f32
// CHECK: affine.store %3, %arg2[%arg3] : memref<2000xf32>
// CHECK: }
// CHECK: return
// CHECK: }
// CHECK:#map0 = affine_map<(d0) -> (d0)>
// CHECK:#map1 = affine_map<(d0, d1) -> (d0, d1)>
// CHECK:#map2 = affine_map<() -> (0)>
// CHECK:#map3 = affine_map<() -> (2000)>

// CHECK:module {
// CHECK: func @scop_entry(%arg0: memref<2000x2000xf32>, %arg1: memref<2000xf32>, %arg2: memref<2000xf32>) {
// CHECK: affine.for %arg3 = 0 to 2000 {
// CHECK: %0 = affine.load %arg1[%arg3] : memref<2000xf32>
// CHECK: affine.store %0, %arg2[%arg3] : memref<2000xf32>
// CHECK: affine.for %arg4 = 0 to #map0(%arg3) {
// CHECK: %4 = affine.load %arg2[%arg3] : memref<2000xf32>
// CHECK: %5 = affine.load %arg0[%arg3, %arg4] : memref<2000x2000xf32>
// CHECK: %6 = affine.load %arg2[%arg4] : memref<2000xf32>
// CHECK: %7 = mulf %5, %6 : f32
// CHECK: %8 = subf %4, %7 : f32
// CHECK: affine.store %8, %arg2[%arg3] : memref<2000xf32>
// CHECK: }
// CHECK: %1 = affine.load %arg2[%arg3] : memref<2000xf32>
// CHECK: %2 = affine.load %arg0[%arg3, %arg3] : memref<2000x2000xf32>
// CHECK: %3 = divf %1, %2 : f32
// CHECK: affine.store %3, %arg2[%arg3] : memref<2000xf32>
// CHECK: }
// CHECK: return
// CHECK: }
// CHECK:}