Skip to content

Commit

Permalink
[MLIR][OpenMP] Add support for safelen clause
Browse files Browse the repository at this point in the history
This supports translation from MLIR to LLVM IR using OMPIRBuilder for
OpenMP safelen clause in SIMD construct.

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D132245
  • Loading branch information
psoni2628 committed Aug 24, 2022
1 parent 4fce38c commit b8055c5
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 2 deletions.
2 changes: 1 addition & 1 deletion flang/lib/Lower/OpenMP.cpp
Expand Up @@ -1150,7 +1150,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
TypeRange resultType;
auto SimdLoopOp = firOpBuilder.create<mlir::omp::SimdLoopOp>(
currentLocation, resultType, lowerBound, upperBound, step,
ifClauseOperand, simdlenClauseOperand,
ifClauseOperand, simdlenClauseOperand, nullptr,
/*inclusive=*/firOpBuilder.getUnitAttr());
createBodyOfOp<omp::SimdLoopOp>(SimdLoopOp, converter, currentLocation,
eval, &loopOpClauseList, iv);
Expand Down
6 changes: 6 additions & 0 deletions mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
Expand Up @@ -421,6 +421,10 @@ def SimdLoopOp : OpenMP_Op<"simdloop", [AttrSizedOperandSegments,

When a simdlen clause is present, the preferred number of iterations to be
executed concurrently is the value provided to the simdlen clause.

The safelen clause specifies that no two concurrent iterations within a
SIMD chunk can have a distance in the logical iteration space that is
greater than or equal to the value given in the clause.
```
omp.simdloop <clauses>
for (%i1, %i2) : index = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) {
Expand All @@ -436,13 +440,15 @@ def SimdLoopOp : OpenMP_Op<"simdloop", [AttrSizedOperandSegments,
Variadic<IntLikeType>:$step,
Optional<I1>:$if_expr,
ConfinedAttr<OptionalAttr<I64Attr>, [IntPositive]>:$simdlen,
ConfinedAttr<OptionalAttr<I64Attr>, [IntPositive]>:$safelen,
UnitAttr:$inclusive
);

let regions = (region AnyRegion:$region);
let assemblyFormat = [{
oilist(`if` `(` $if_expr `)`
|`simdlen` `(` $simdlen `)`
|`safelen` `(` $safelen `)`
) `for` custom<LoopControl>($region, $lowerBound, $upperBound, $step,
type($step), $inclusive) attr-dict
}];
Expand Down
7 changes: 7 additions & 0 deletions mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
Expand Up @@ -578,6 +578,13 @@ LogicalResult SimdLoopOp::verify() {
if (this->lowerBound().empty()) {
return emitOpError() << "empty lowerbound for simd loop operation";
}
if (this->simdlen().has_value() && this->safelen().has_value() &&
this->simdlen().value() > this->safelen().value()) {
return emitOpError()
<< "simdlen clause and safelen clause are both present, but the "
"simdlen value is not less than or equal to safelen value";
}

return success();
}

Expand Down
Expand Up @@ -970,10 +970,14 @@ convertOmpSimdLoop(Operation &opInst, llvm::IRBuilderBase &builder,
if (llvm::Optional<uint64_t> simdlenVar = loop.simdlen())
simdlen = builder.getInt64(simdlenVar.value());

llvm::ConstantInt *safelen = nullptr;
if (llvm::Optional<uint64_t> safelenVar = loop.safelen())
safelen = builder.getInt64(safelenVar.value());

ompBuilder->applySimd(
loopInfo,
loop.if_expr() ? moduleTranslation.lookupValue(loop.if_expr()) : nullptr,
simdlen, nullptr);
simdlen, safelen);

builder.restoreIP(afterIP);
return success();
Expand Down
20 changes: 20 additions & 0 deletions mlir/test/Dialect/OpenMP/invalid.mlir
Expand Up @@ -215,6 +215,26 @@ func.func @omp_simdloop_pretty_simdlen(%lb : index, %ub : index, %step : index)

// -----

func.func @omp_simdloop_pretty_safelen(%lb : index, %ub : index, %step : index) -> () {
// expected-error @below {{op attribute 'safelen' failed to satisfy constraint: 64-bit signless integer attribute whose value is positive}}
omp.simdloop safelen(0) for (%iv): index = (%lb) to (%ub) step (%step) {
omp.yield
}
return
}

// -----

func.func @omp_simdloop_pretty_simdlen_safelen(%lb : index, %ub : index, %step : index) -> () {
// expected-error @below {{'omp.simdloop' op simdlen clause and safelen clause are both present, but the simdlen value is not less than or equal to safelen value}}
omp.simdloop simdlen(2) safelen(1) for (%iv): index = (%lb) to (%ub) step (%step) {
omp.yield
}
return
}

// -----

// expected-error @below {{op expects initializer region with one argument of the reduction type}}
omp.reduction.declare @add_f32 : f64
init {
Expand Down
9 changes: 9 additions & 0 deletions mlir/test/Dialect/OpenMP/ops.mlir
Expand Up @@ -366,6 +366,15 @@ func.func @omp_simdloop_pretty_simdlen(%lb : index, %ub : index, %step : index)
return
}

// CHECK-LABEL: omp_simdloop_pretty_safelen
func.func @omp_simdloop_pretty_safelen(%lb : index, %ub : index, %step : index) -> () {
// CHECK: omp.simdloop safelen(2) for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
omp.simdloop safelen(2) for (%iv): index = (%lb) to (%ub) step (%step) {
omp.yield
}
return
}

// CHECK-LABEL: omp_simdloop_pretty_multiple
func.func @omp_simdloop_pretty_multiple(%lb1 : index, %ub1 : index, %step1 : index, %lb2 : index, %ub2 : index, %step2 : index) -> () {
// CHECK: omp.simdloop for (%{{.*}}, %{{.*}}) : index = (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}})
Expand Down
34 changes: 34 additions & 0 deletions mlir/test/Target/LLVMIR/openmp-llvm.mlir
Expand Up @@ -765,6 +765,40 @@ llvm.func @simdloop_simple_multiple_simdlen(%lb1 : i64, %ub1 : i64, %step1 : i64

// -----

// CHECK-LABEL: @simdloop_simple_multiple_safelen
llvm.func @simdloop_simple_multiple_safelen(%lb1 : i64, %ub1 : i64, %step1 : i64, %lb2 : i64, %ub2 : i64, %step2 : i64, %arg0: !llvm.ptr<f32>, %arg1: !llvm.ptr<f32>) {
omp.simdloop safelen(2) for (%iv1, %iv2) : i64 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) {
%3 = llvm.mlir.constant(2.000000e+00 : f32) : f32
%4 = llvm.getelementptr %arg0[%iv1] : (!llvm.ptr<f32>, i64) -> !llvm.ptr<f32>
%5 = llvm.getelementptr %arg1[%iv2] : (!llvm.ptr<f32>, i64) -> !llvm.ptr<f32>
llvm.store %3, %4 : !llvm.ptr<f32>
llvm.store %3, %5 : !llvm.ptr<f32>
omp.yield
}
llvm.return
}
// CHECK: llvm.loop.vectorize.enable
// CHECK-NEXT: llvm.loop.vectorize.width{{.*}}i64 2

// -----

// CHECK-LABEL: @simdloop_simple_multiple_simdlen_safelen
llvm.func @simdloop_simple_multiple_simdlen_safelen(%lb1 : i64, %ub1 : i64, %step1 : i64, %lb2 : i64, %ub2 : i64, %step2 : i64, %arg0: !llvm.ptr<f32>, %arg1: !llvm.ptr<f32>) {
omp.simdloop simdlen(1) safelen(2) for (%iv1, %iv2) : i64 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) {
%3 = llvm.mlir.constant(2.000000e+00 : f32) : f32
%4 = llvm.getelementptr %arg0[%iv1] : (!llvm.ptr<f32>, i64) -> !llvm.ptr<f32>
%5 = llvm.getelementptr %arg1[%iv2] : (!llvm.ptr<f32>, i64) -> !llvm.ptr<f32>
llvm.store %3, %4 : !llvm.ptr<f32>
llvm.store %3, %5 : !llvm.ptr<f32>
omp.yield
}
llvm.return
}
// CHECK: llvm.loop.vectorize.enable
// CHECK-NEXT: llvm.loop.vectorize.width{{.*}}i64 1

// -----

// CHECK-LABEL: @simdloop_if
llvm.func @simdloop_if(%arg0: !llvm.ptr<i32> {fir.bindc_name = "n"}, %arg1: !llvm.ptr<i32> {fir.bindc_name = "threshold"}) {
%0 = llvm.mlir.constant(1 : i64) : i64
Expand Down

0 comments on commit b8055c5

Please sign in to comment.