Skip to content
Open
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
13 changes: 13 additions & 0 deletions flang/lib/Lower/OpenMP/ClauseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,19 @@ bool ClauseProcessor::processNumTasks(
return false;
}

bool ClauseProcessor::processSizes(StatementContext &stmtCtx,
mlir::omp::SizesClauseOps &result) const {
if (auto *clause = findUniqueClause<omp::clause::Sizes>()) {
result.sizes.reserve(clause->v.size());
for (const ExprTy &vv : clause->v)
result.sizes.push_back(fir::getBase(converter.genExprValue(vv, stmtCtx)));

return true;
}

return false;
}

bool ClauseProcessor::processNumTeams(
lower::StatementContext &stmtCtx,
mlir::omp::NumTeamsClauseOps &result) const {
Expand Down
2 changes: 2 additions & 0 deletions flang/lib/Lower/OpenMP/ClauseProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class ClauseProcessor {
mlir::omp::LoopRelatedClauseOps &loopResult,
mlir::omp::CollapseClauseOps &collapseResult,
llvm::SmallVectorImpl<const semantics::Symbol *> &iv) const;
bool processSizes(StatementContext &stmtCtx,
mlir::omp::SizesClauseOps &result) const;
bool processDevice(lower::StatementContext &stmtCtx,
mlir::omp::DeviceClauseOps &result) const;
bool processDeviceType(mlir::omp::DeviceTypeClauseOps &result) const;
Expand Down
360 changes: 236 additions & 124 deletions flang/lib/Lower/OpenMP/OpenMP.cpp

Large diffs are not rendered by default.

24 changes: 20 additions & 4 deletions flang/lib/Lower/OpenMP/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,6 @@ int64_t collectLoopRelatedInfo(
mlir::omp::LoopRelatedClauseOps &result,
llvm::SmallVectorImpl<const semantics::Symbol *> &iv) {
int64_t numCollapse = 1;
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();

// Collect the loops to collapse.
lower::pft::Evaluation *doConstructEval = &eval.getFirstNestedEvaluation();
Expand All @@ -667,6 +666,25 @@ int64_t collectLoopRelatedInfo(
numCollapse = collapseValue;
}

collectLoopRelatedInfo(converter, currentLocation, eval, numCollapse, result,
iv);
return numCollapse;
}

void collectLoopRelatedInfo(
lower::AbstractConverter &converter, mlir::Location currentLocation,
lower::pft::Evaluation &eval, int64_t numCollapse,
mlir::omp::LoopRelatedClauseOps &result,
llvm::SmallVectorImpl<const semantics::Symbol *> &iv) {

fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();

// Collect the loops to collapse.
lower::pft::Evaluation *doConstructEval = &eval.getFirstNestedEvaluation();
if (doConstructEval->getIf<parser::DoConstruct>()->IsDoConcurrent()) {
TODO(currentLocation, "Do Concurrent in Worksharing loop construct");
}

// Collect sizes from tile directive if present.
std::int64_t sizesLengthValue = 0l;
if (auto *ompCons{eval.getIf<parser::OpenMPConstruct>()}) {
Expand All @@ -676,7 +694,7 @@ int64_t collectLoopRelatedInfo(
});
}

collapseValue = std::max(collapseValue, sizesLengthValue);
std::int64_t collapseValue = std::max(numCollapse, sizesLengthValue);
std::size_t loopVarTypeSize = 0;
do {
lower::pft::Evaluation *doLoop =
Expand Down Expand Up @@ -709,8 +727,6 @@ int64_t collectLoopRelatedInfo(
} while (collapseValue > 0);

convertLoopBounds(converter, currentLocation, result, loopVarTypeSize);

return numCollapse;
}

} // namespace omp
Expand Down
7 changes: 7 additions & 0 deletions flang/lib/Lower/OpenMP/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ int64_t collectLoopRelatedInfo(
mlir::omp::LoopRelatedClauseOps &result,
llvm::SmallVectorImpl<const semantics::Symbol *> &iv);

void collectLoopRelatedInfo(
lower::AbstractConverter &converter, mlir::Location currentLocation,
lower::pft::Evaluation &eval, std::int64_t collapseValue,
// const omp::List<omp::Clause> &clauses,
mlir::omp::LoopRelatedClauseOps &result,
llvm::SmallVectorImpl<const semantics::Symbol *> &iv);

void collectTileSizesFromOpenMPConstruct(
const parser::OpenMPConstruct *ompCons,
llvm::SmallVectorImpl<int64_t> &tileSizes,
Expand Down
7 changes: 4 additions & 3 deletions flang/lib/Semantics/check-directive-structure.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,8 @@ class DirectiveStructureChecker : public virtual BaseChecker {
const C &clause, const parser::ScalarIntConstantExpr &i);

void RequiresPositiveParameter(const C &clause,
const parser::ScalarIntExpr &i, llvm::StringRef paramName = "parameter");
const parser::ScalarIntExpr &i, llvm::StringRef paramName = "parameter",
bool allowZero = true);

void OptionalConstantPositiveParameter(
const C &clause, const std::optional<parser::ScalarIntConstantExpr> &o);
Expand Down Expand Up @@ -657,9 +658,9 @@ void DirectiveStructureChecker<D, C, PC, ClauseEnumSize>::SayNotMatching(
template <typename D, typename C, typename PC, std::size_t ClauseEnumSize>
void DirectiveStructureChecker<D, C, PC,
ClauseEnumSize>::RequiresPositiveParameter(const C &clause,
const parser::ScalarIntExpr &i, llvm::StringRef paramName) {
const parser::ScalarIntExpr &i, llvm::StringRef paramName, bool allowZero) {
if (const auto v{GetIntValue(i)}) {
if (*v < 0) {
if (*v < (allowZero ? 0 : 1)) {
context_.Say(GetContext().clauseSource,
"The %s of the %s clause must be "
"a positive integer expression"_err_en_US,
Expand Down
8 changes: 7 additions & 1 deletion flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2749,6 +2749,13 @@ void OmpStructureChecker::Enter(const parser::OmpClause &x) {
}
}

void OmpStructureChecker::Enter(const parser::OmpClause::Sizes &c) {
CheckAllowedClause(llvm::omp::Clause::OMPC_sizes);
for (const parser::Cosubscript &v : c.v)
RequiresPositiveParameter(llvm::omp::Clause::OMPC_sizes, v,
/*paramName=*/"parameter", /*allowZero=*/false);
}

// Following clauses do not have a separate node in parse-tree.h.
CHECK_SIMPLE_CLAUSE(Absent, OMPC_absent)
CHECK_SIMPLE_CLAUSE(Affinity, OMPC_affinity)
Expand Down Expand Up @@ -2790,7 +2797,6 @@ CHECK_SIMPLE_CLAUSE(Notinbranch, OMPC_notinbranch)
CHECK_SIMPLE_CLAUSE(Partial, OMPC_partial)
CHECK_SIMPLE_CLAUSE(ProcBind, OMPC_proc_bind)
CHECK_SIMPLE_CLAUSE(Simd, OMPC_simd)
CHECK_SIMPLE_CLAUSE(Sizes, OMPC_sizes)
CHECK_SIMPLE_CLAUSE(Permutation, OMPC_permutation)
CHECK_SIMPLE_CLAUSE(Uniform, OMPC_uniform)
CHECK_SIMPLE_CLAUSE(Unknown, OMPC_unknown)
Expand Down
16 changes: 12 additions & 4 deletions flang/lib/Semantics/resolve-directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2388,10 +2388,18 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
void OmpAttributeVisitor::CheckAssocLoopLevel(
std::int64_t level, const parser::OmpClause *clause) {
if (clause && level != 0) {
context_.Say(clause->source,
"The value of the parameter in the COLLAPSE or ORDERED clause must"
" not be larger than the number of nested loops"
" following the construct."_err_en_US);
switch (clause->Id()) {
case llvm::omp::OMPC_sizes:
context_.Say(clause->source,
"The SIZES clause has more entries than there are nested canonical loops."_err_en_US);
break;
default:
context_.Say(clause->source,
"The value of the parameter in the COLLAPSE or ORDERED clause must"
" not be larger than the number of nested loops"
" following the construct."_err_en_US);
break;
}
}
}

Expand Down
58 changes: 58 additions & 0 deletions flang/test/Lower/OpenMP/tile01.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s | FileCheck %s


subroutine omp_tile01(lb, ub, inc)
integer res, i, lb, ub, inc

!$omp tile sizes(4)
do i = lb, ub, inc
res = i
end do
!$omp end tile

end subroutine omp_tile01


! CHECK: func.func @_QPomp_tile01(
! CHECK: %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "lb"},
! CHECK: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "ub"},
! CHECK: %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "inc"}) {
! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_tile01Ei"}
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_tile01Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile01Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile01Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_tile01Eres"}
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFomp_tile01Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile01Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_8:.*]] = arith.constant 4 : i32
! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_12:.*]] = arith.constant 0 : i32
! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_14:.*]] = arith.cmpi slt, %[[VAL_11]], %[[VAL_12]] : i32
! CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_12]], %[[VAL_11]] : i32
! CHECK: %[[VAL_16:.*]] = arith.select %[[VAL_14]], %[[VAL_15]], %[[VAL_11]] : i32
! CHECK: %[[VAL_17:.*]] = arith.select %[[VAL_14]], %[[VAL_10]], %[[VAL_9]] : i32
! CHECK: %[[VAL_18:.*]] = arith.select %[[VAL_14]], %[[VAL_9]], %[[VAL_10]] : i32
! CHECK: %[[VAL_19:.*]] = arith.subi %[[VAL_18]], %[[VAL_17]] overflow<nuw> : i32
! CHECK: %[[VAL_20:.*]] = arith.divui %[[VAL_19]], %[[VAL_16]] : i32
! CHECK: %[[VAL_21:.*]] = arith.addi %[[VAL_20]], %[[VAL_13]] overflow<nuw> : i32
! CHECK: %[[VAL_22:.*]] = arith.cmpi slt, %[[VAL_18]], %[[VAL_17]] : i32
! CHECK: %[[VAL_23:.*]] = arith.select %[[VAL_22]], %[[VAL_12]], %[[VAL_21]] : i32
! CHECK: %[[VAL_24:.*]] = omp.new_cli
! CHECK: omp.canonical_loop(%[[VAL_24]]) %[[VAL_25:.*]] : i32 in range(%[[VAL_23]]) {
! CHECK: %[[VAL_26:.*]] = arith.muli %[[VAL_25]], %[[VAL_11]] : i32
! CHECK: %[[VAL_27:.*]] = arith.addi %[[VAL_9]], %[[VAL_26]] : i32
! CHECK: hlfir.assign %[[VAL_27]] to %[[VAL_2]]#0 : i32, !fir.ref<i32>
! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32>
! CHECK: hlfir.assign %[[VAL_28]] to %[[VAL_6]]#0 : i32, !fir.ref<i32>
! CHECK: omp.terminator
! CHECK: }
! CHECK: %[[VAL_29:.*]] = omp.new_cli
! CHECK: %[[VAL_30:.*]] = omp.new_cli
! CHECK: omp.tile (%[[VAL_29]], %[[VAL_30]]) <- (%[[VAL_24]]) sizes(%[[VAL_8]] : i32)
! CHECK: return
! CHECK: }

88 changes: 88 additions & 0 deletions flang/test/Lower/OpenMP/tile02.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s | FileCheck %s


subroutine omp_tile02(lb, ub, inc)
integer res, i, lb, ub, inc

!$omp tile sizes(3,7)
do i = lb, ub, inc
do j = lb, ub, inc
res = i + j
end do
end do
!$omp end tile

end subroutine omp_tile02


! CHECK: func.func @_QPomp_tile02(
! CHECK: %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "lb"},
! CHECK: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "ub"},
! CHECK: %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "inc"}) {
! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_tile02Ei"}
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_tile02Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile02Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFomp_tile02Ej"}
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFomp_tile02Ej"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile02Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_tile02Eres"}
! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFomp_tile02Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile02Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_10:.*]] = arith.constant 3 : i32
! CHECK: %[[VAL_11:.*]] = arith.constant 7 : i32
! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_15:.*]] = arith.constant 0 : i32
! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_17:.*]] = arith.cmpi slt, %[[VAL_14]], %[[VAL_15]] : i32
! CHECK: %[[VAL_18:.*]] = arith.subi %[[VAL_15]], %[[VAL_14]] : i32
! CHECK: %[[VAL_19:.*]] = arith.select %[[VAL_17]], %[[VAL_18]], %[[VAL_14]] : i32
! CHECK: %[[VAL_20:.*]] = arith.select %[[VAL_17]], %[[VAL_13]], %[[VAL_12]] : i32
! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_17]], %[[VAL_12]], %[[VAL_13]] : i32
! CHECK: %[[VAL_22:.*]] = arith.subi %[[VAL_21]], %[[VAL_20]] overflow<nuw> : i32
! CHECK: %[[VAL_23:.*]] = arith.divui %[[VAL_22]], %[[VAL_19]] : i32
! CHECK: %[[VAL_24:.*]] = arith.addi %[[VAL_23]], %[[VAL_16]] overflow<nuw> : i32
! CHECK: %[[VAL_25:.*]] = arith.cmpi slt, %[[VAL_21]], %[[VAL_20]] : i32
! CHECK: %[[VAL_26:.*]] = arith.select %[[VAL_25]], %[[VAL_15]], %[[VAL_24]] : i32
! CHECK: %[[VAL_27:.*]] = omp.new_cli
! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_31:.*]] = arith.constant 0 : i32
! CHECK: %[[VAL_32:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_33:.*]] = arith.cmpi slt, %[[VAL_30]], %[[VAL_31]] : i32
! CHECK: %[[VAL_34:.*]] = arith.subi %[[VAL_31]], %[[VAL_30]] : i32
! CHECK: %[[VAL_35:.*]] = arith.select %[[VAL_33]], %[[VAL_34]], %[[VAL_30]] : i32
! CHECK: %[[VAL_36:.*]] = arith.select %[[VAL_33]], %[[VAL_29]], %[[VAL_28]] : i32
! CHECK: %[[VAL_37:.*]] = arith.select %[[VAL_33]], %[[VAL_28]], %[[VAL_29]] : i32
! CHECK: %[[VAL_38:.*]] = arith.subi %[[VAL_37]], %[[VAL_36]] overflow<nuw> : i32
! CHECK: %[[VAL_39:.*]] = arith.divui %[[VAL_38]], %[[VAL_35]] : i32
! CHECK: %[[VAL_40:.*]] = arith.addi %[[VAL_39]], %[[VAL_32]] overflow<nuw> : i32
! CHECK: %[[VAL_41:.*]] = arith.cmpi slt, %[[VAL_37]], %[[VAL_36]] : i32
! CHECK: %[[VAL_42:.*]] = arith.select %[[VAL_41]], %[[VAL_31]], %[[VAL_40]] : i32
! CHECK: %[[VAL_43:.*]] = omp.new_cli
! CHECK: omp.canonical_loop(%[[VAL_27]]) %[[VAL_44:.*]] : i32 in range(%[[VAL_26]]) {
! CHECK: omp.canonical_loop(%[[VAL_43]]) %[[VAL_45:.*]] : i32 in range(%[[VAL_42]]) {
! CHECK: %[[VAL_46:.*]] = arith.muli %[[VAL_44]], %[[VAL_14]] : i32
! CHECK: %[[VAL_47:.*]] = arith.addi %[[VAL_12]], %[[VAL_46]] : i32
! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_2]]#0 : i32, !fir.ref<i32>
! CHECK: %[[VAL_48:.*]] = arith.muli %[[VAL_45]], %[[VAL_30]] : i32
! CHECK: %[[VAL_49:.*]] = arith.addi %[[VAL_28]], %[[VAL_48]] : i32
! CHECK: hlfir.assign %[[VAL_49]] to %[[VAL_5]]#0 : i32, !fir.ref<i32>
! CHECK: %[[VAL_50:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_51:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_52:.*]] = arith.addi %[[VAL_50]], %[[VAL_51]] : i32
! CHECK: hlfir.assign %[[VAL_52]] to %[[VAL_8]]#0 : i32, !fir.ref<i32>
! CHECK: omp.terminator
! CHECK: }
! CHECK: omp.terminator
! CHECK: }
! CHECK: %[[VAL_53:.*]] = omp.new_cli
! CHECK: %[[VAL_54:.*]] = omp.new_cli
! CHECK: %[[VAL_55:.*]] = omp.new_cli
! CHECK: %[[VAL_56:.*]] = omp.new_cli
! CHECK: omp.tile (%[[VAL_53]], %[[VAL_55]], %[[VAL_54]], %[[VAL_56]]) <- (%[[VAL_27]], %[[VAL_43]]) sizes(%[[VAL_10]], %[[VAL_11]] : i32, i32)
! CHECK: return
! CHECK: }
5 changes: 3 additions & 2 deletions flang/test/Parser/OpenMP/loop-transformation-construct02.f90
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ subroutine loop_transformation_construct

!$omp do
!$omp unroll
!$omp tile
!$omp tile sizes(2)
do i = 1, I
y(i) = y(i) * 5
end do
Expand All @@ -34,7 +34,8 @@ subroutine loop_transformation_construct
!CHECK-PARSE-NEXT: | | | | OpenMPLoopConstruct
!CHECK-PARSE-NEXT: | | | | | OmpBeginLoopDirective
!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = tile
!CHECK-PARSE-NEXT: | | | | | | OmpClauseList ->
!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4'
!CHECK-PARSE-NEXT: | | | | | | | LiteralConstant -> IntLiteralConstant = '2'
!CHECK-PARSE-NEXT: | | | | | | Flags = None
!CHECK-PARSE-NEXT: | | | | | DoConstruct
!CHECK-PARSE-NEXT: | | | | | | NonLabelDoStmt
Expand Down
32 changes: 32 additions & 0 deletions flang/test/Parser/OpenMP/tile-fail.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
! RUN: split-file %s %t
! RUN: not %flang_fc1 -fsyntax-only -fopenmp %t/stray_end1.f90 2>&1 | FileCheck %t/stray_end1.f90
! RUN: not %flang_fc1 -fsyntax-only -fopenmp %t/stray_end2.f90 2>&1 | FileCheck %t/stray_end2.f90
! RUN: not %flang_fc1 -fsyntax-only -fopenmp %t/stray_begin.f90 2>&1 | FileCheck %t/stray_begin.f90


!--- stray_end1.f90
! Parser error

subroutine stray_end1
!CHECK: error: expected OpenMP construct
!$omp end tile
end subroutine


!--- stray_end2.f90
! Semantic error

subroutine stray_end2
print *
!CHECK: error: The END TILE directive must follow the DO loop associated with the loop construct
!$omp end tile
end subroutine


!--- stray_begin.f90

subroutine stray_begin
!CHECK: error: A DO loop must follow the TILE directive
!$omp tile sizes(2)
end subroutine

15 changes: 10 additions & 5 deletions flang/test/Parser/OpenMP/tile.f90
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s
! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=51 %s | FileCheck --ignore-case %s
! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=51 %s | FileCheck --check-prefix="PARSE-TREE" %s

subroutine openmp_tiles(x)

integer, intent(inout)::x

!CHECK: !$omp tile
!$omp tile
!CHECK: !$omp tile sizes(2_4)
!$omp tile sizes(2)
!CHECK: do
do x = 1, 100
call F1()
Expand All @@ -17,7 +17,12 @@ subroutine openmp_tiles(x)

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE: OmpBeginLoopDirective
!PARSE-TREE: OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4'
!PARSE-TREE: LiteralConstant -> IntLiteralConstant = '2'
!PARSE-TREE: Flags = None
!PARSE-TREE: DoConstruct
!PARSE-TREE: EndDoStmt
!PARSE-TREE: OmpEndLoopDirective
!PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = tile

END subroutine openmp_tiles

Loading