[llvm] 65e80d6 - [Flang][OpenMP] Improve support for `if` clause on combined constructs

Sergio Afonso via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 4 02:43:45 PDT 2023


Author: Sergio Afonso
Date: 2023-08-04T10:43:12+01:00
New Revision: 65e80d6dfde052dc433077a03755120f42b5a626

URL: https://github.com/llvm/llvm-project/commit/65e80d6dfde052dc433077a03755120f42b5a626
DIFF: https://github.com/llvm/llvm-project/commit/65e80d6dfde052dc433077a03755120f42b5a626.diff

LOG: [Flang][OpenMP] Improve support for `if` clause on combined constructs

This patch adds support for matching multiple OpenMP `if` clauses to their
specified directive in a combined construct. It also enables this clause to be
attached by name to `simd` and `teams` directives, in addition to the others
that were already supported.

This patch on its own cannot yet be tested because there is currently no
lowering to MLIR support for any combined construct containing two or more
OpenMP directives that can have an `if` clause attached.

Depends on D155981.

Differential Revision: https://reviews.llvm.org/D156313

Added: 
    flang/test/Parser/OpenMP/if-clause-unparse.f90
    flang/test/Parser/OpenMP/if-clause.f90
    flang/test/Semantics/OpenMP/if-clause.f90

Modified: 
    flang/include/flang/Parser/parse-tree.h
    flang/lib/Lower/OpenMP.cpp
    flang/lib/Parser/openmp-parsers.cpp
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/check-omp-structure.h
    llvm/include/llvm/Frontend/OpenMP/OMP.td

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 5ee7ecc61a4e2e..e70f5aeae117e6 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3462,8 +3462,8 @@ struct OmpDeviceTypeClause {
 // 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr)
 struct OmpIfClause {
   TUPLE_CLASS_BOILERPLATE(OmpIfClause);
-  ENUM_CLASS(DirectiveNameModifier, Parallel, Target, TargetEnterData,
-      TargetExitData, TargetData, TargetUpdate, Taskloop, Task)
+  ENUM_CLASS(DirectiveNameModifier, Parallel, Simd, Target, TargetData,
+      TargetEnterData, TargetExitData, TargetUpdate, Task, Taskloop, Teams)
   std::tuple<std::optional<DirectiveNameModifier>, ScalarLogicalExpr> t;
 };
 

diff  --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp
index 8dba0dbba10cab..2a04f3bb5be562 100644
--- a/flang/lib/Lower/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP.cpp
@@ -518,8 +518,10 @@ class ClauseProcessor {
   bool processCopyin() const;
   bool processDepend(llvm::SmallVectorImpl<mlir::Attribute> &dependTypeOperands,
                      llvm::SmallVectorImpl<mlir::Value> &dependOperands) const;
-  bool processIf(Fortran::lower::StatementContext &stmtCtx,
-                 mlir::Value &result) const;
+  bool
+  processIf(Fortran::lower::StatementContext &stmtCtx,
+            Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName,
+            mlir::Value &result) const;
   bool
   processLink(llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const;
   bool processMap(llvm::SmallVectorImpl<mlir::Value> &mapOperands,
@@ -1049,11 +1051,19 @@ genDependKindAttr(fir::FirOpBuilder &firOpBuilder,
                                               pbKind);
 }
 
-static mlir::Value
-getIfClauseOperand(Fortran::lower::AbstractConverter &converter,
-                   Fortran::lower::StatementContext &stmtCtx,
-                   const Fortran::parser::OmpClause::If *ifClause,
-                   mlir::Location clauseLocation) {
+static mlir::Value getIfClauseOperand(
+    Fortran::lower::AbstractConverter &converter,
+    Fortran::lower::StatementContext &stmtCtx,
+    const Fortran::parser::OmpClause::If *ifClause,
+    Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName,
+    mlir::Location clauseLocation) {
+  // Only consider the clause if it's intended for the given directive.
+  auto &directive = std::get<
+      std::optional<Fortran::parser::OmpIfClause::DirectiveNameModifier>>(
+      ifClause->v.t);
+  if (directive && directive.value() != directiveName)
+    return nullptr;
+
   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
   auto &expr = std::get<Fortran::parser::ScalarLogicalExpr>(ifClause->v.t);
   mlir::Value ifVal = fir::getBase(
@@ -1572,17 +1582,25 @@ bool ClauseProcessor::processDepend(
       });
 }
 
-bool ClauseProcessor::processIf(Fortran::lower::StatementContext &stmtCtx,
-                                mlir::Value &result) const {
-  return findRepeatableClause<ClauseTy::If>(
+bool ClauseProcessor::processIf(
+    Fortran::lower::StatementContext &stmtCtx,
+    Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName,
+    mlir::Value &result) const {
+  bool found = false;
+  findRepeatableClause<ClauseTy::If>(
       [&](const ClauseTy::If *ifClause,
           const Fortran::parser::CharBlock &source) {
         mlir::Location clauseLocation = converter.genLocation(source);
-        // TODO Consider DirectiveNameModifier of the `ifClause` to only search
-        // for an applicable 'if' clause.
-        result =
-            getIfClauseOperand(converter, stmtCtx, ifClause, clauseLocation);
+        mlir::Value operand = getIfClauseOperand(converter, stmtCtx, ifClause,
+                                                 directiveName, clauseLocation);
+        // Assume that, at most, a single 'if' clause will be applicable to the
+        // given directive.
+        if (operand) {
+          result = operand;
+          found = true;
+        }
       });
+  return found;
 }
 
 bool ClauseProcessor::processLink(
@@ -2109,8 +2127,30 @@ static void createTargetOp(Fortran::lower::AbstractConverter &converter,
   llvm::SmallVector<mlir::Location> useDeviceLocs;
   llvm::SmallVector<const Fortran::semantics::Symbol *> useDeviceSymbols;
 
+  Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName;
+  switch (directive) {
+  case llvm::omp::Directive::OMPD_target:
+    directiveName = Fortran::parser::OmpIfClause::DirectiveNameModifier::Target;
+    break;
+  case llvm::omp::Directive::OMPD_target_data:
+    directiveName =
+        Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetData;
+    break;
+  case llvm::omp::Directive::OMPD_target_enter_data:
+    directiveName =
+        Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetEnterData;
+    break;
+  case llvm::omp::Directive::OMPD_target_exit_data:
+    directiveName =
+        Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetExitData;
+    break;
+  default:
+    TODO(currentLocation, "OMPD_target directive unknown");
+    break;
+  }
+
   ClauseProcessor cp(converter, opClauseList);
-  cp.processIf(stmtCtx, ifClauseOperand);
+  cp.processIf(stmtCtx, directiveName, ifClauseOperand);
   cp.processDevice(stmtCtx, deviceOperand);
   cp.processThreadLimit(stmtCtx, threadLmtOperand);
   cp.processNowait(nowaitAttr);
@@ -2157,8 +2197,6 @@ static void createTargetOp(Fortran::lower::AbstractConverter &converter,
     firOpBuilder.create<mlir::omp::ExitDataOp>(currentLocation, ifClauseOperand,
                                                deviceOperand, nowaitAttr,
                                                mapOperands, mapTypesArrayAttr);
-  } else {
-    TODO(currentLocation, "OMPD_target directive unknown");
   }
 }
 
@@ -2256,7 +2294,9 @@ createCombinedParallelOp(Fortran::lower::AbstractConverter &converter,
   // 1. default
   // Note: rest of the clauses are handled when the inner operation is created
   ClauseProcessor cp(converter, opClauseList);
-  cp.processIf(stmtCtx, ifClauseOperand);
+  cp.processIf(stmtCtx,
+               Fortran::parser::OmpIfClause::DirectiveNameModifier::Parallel,
+               ifClauseOperand);
   cp.processNumThreads(stmtCtx, numThreadsClauseOperand);
   cp.processProcBind(procBindKindAttr);
 
@@ -2315,7 +2355,9 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
   cp.processCollapse(currentLocation, eval, lowerBound, upperBound, step, iv,
                      loopVarTypeSize);
   cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand);
-  cp.processIf(stmtCtx, ifClauseOperand);
+  cp.processIf(stmtCtx,
+               Fortran::parser::OmpIfClause::DirectiveNameModifier::Simd,
+               ifClauseOperand);
   cp.processReduction(currentLocation, reductionVars, reductionDeclSymbols);
   cp.processSimdlen(simdlenClauseOperand);
   cp.processSafelen(safelenClauseOperand);
@@ -2416,10 +2458,38 @@ genOMP(Fortran::lower::AbstractConverter &converter,
   llvm::SmallVector<mlir::Attribute> dependTypeOperands, reductionDeclSymbols;
   mlir::UnitAttr nowaitAttr, untiedAttr, mergeableAttr;
 
+  // Use placeholder value to avoid uninitialized `directiveName` compiler
+  // errors. The 'if clause' obtained won't be used for these directives.
+  Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName =
+      Fortran::parser::OmpIfClause::DirectiveNameModifier::Parallel;
+  switch (blockDirective.v) {
+  case llvm::omp::OMPD_parallel:
+    directiveName =
+        Fortran::parser::OmpIfClause::DirectiveNameModifier::Parallel;
+    break;
+  case llvm::omp::OMPD_task:
+    directiveName = Fortran::parser::OmpIfClause::DirectiveNameModifier::Task;
+    break;
+  // Target-related 'if' clauses handled by createTargetOp().
+  case llvm::omp::OMPD_target:
+  case llvm::omp::OMPD_target_data:
+  // These block directives do not accept an 'if' clause.
+  case llvm::omp::OMPD_master:
+  case llvm::omp::OMPD_single:
+  case llvm::omp::OMPD_ordered:
+  case llvm::omp::OMPD_taskgroup:
+    break;
+  default:
+    TODO(currentLocation,
+         "Unhandled block directive (" +
+             llvm::omp::getOpenMPDirectiveName(blockDirective.v) + ")");
+    break;
+  }
+
   const auto &opClauseList =
       std::get<Fortran::parser::OmpClauseList>(beginBlockDirective.t);
   ClauseProcessor cp(converter, opClauseList);
-  cp.processIf(stmtCtx, ifClauseOperand);
+  cp.processIf(stmtCtx, directiveName, ifClauseOperand);
   cp.processNumThreads(stmtCtx, numThreadsClauseOperand);
   cp.processProcBind(procBindKindAttr);
   cp.processAllocate(allocatorOperands, allocateOperands);
@@ -2524,8 +2594,6 @@ genOMP(Fortran::lower::AbstractConverter &converter,
   } else if (blockDirective.v == llvm::omp::OMPD_target_data) {
     createTargetOp(converter, opClauseList, blockDirective.v, currentLocation,
                    &eval);
-  } else {
-    TODO(currentLocation, "Unhandled block directive");
   }
 }
 

diff  --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 7baf96c1658c8b..6d1a3a04b481ef 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -115,6 +115,7 @@ TYPE_PARSER(construct<OmpDeviceTypeClause>(
 TYPE_PARSER(construct<OmpIfClause>(
     maybe(
         ("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) ||
+            "SIMD" >> pure(OmpIfClause::DirectiveNameModifier::Simd) ||
             "TARGET ENTER DATA" >>
                 pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) ||
             "TARGET EXIT DATA" >>
@@ -125,7 +126,8 @@ TYPE_PARSER(construct<OmpIfClause>(
                 pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) ||
             "TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) ||
             "TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task) ||
-            "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop)) /
+            "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) ||
+            "TEAMS" >> pure(OmpIfClause::DirectiveNameModifier::Teams)) /
         ":"),
     scalarLogicalExpr))
 

diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index fb67cb41953c73..0c838a968812f1 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2395,19 +2395,35 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
 void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
   CheckAllowed(llvm::omp::Clause::OMPC_if);
   using dirNameModifier = parser::OmpIfClause::DirectiveNameModifier;
+  // TODO Check that, when multiple 'if' clauses are applied to a combined
+  // construct, at most one of them applies to each directive.
+  // Need to define set here because llvm::omp::teamSet does not include target
+  // teams combined constructs.
+  OmpDirectiveSet teamSet{llvm::omp::Directive::OMPD_target_teams,
+      llvm::omp::Directive::OMPD_target_teams_distribute,
+      llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do,
+      llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd,
+      llvm::omp::Directive::OMPD_target_teams_distribute_simd,
+      llvm::omp::Directive::OMPD_teams,
+      llvm::omp::Directive::OMPD_teams_distribute,
+      llvm::omp::Directive::OMPD_teams_distribute_parallel_do,
+      llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd,
+      llvm::omp::Directive::OMPD_teams_distribute_simd};
   static std::unordered_map<dirNameModifier, OmpDirectiveSet>
       dirNameModifierMap{{dirNameModifier::Parallel, llvm::omp::parallelSet},
+          {dirNameModifier::Simd, llvm::omp::simdSet},
           {dirNameModifier::Target, llvm::omp::targetSet},
+          {dirNameModifier::TargetData,
+              {llvm::omp::Directive::OMPD_target_data}},
           {dirNameModifier::TargetEnterData,
               {llvm::omp::Directive::OMPD_target_enter_data}},
           {dirNameModifier::TargetExitData,
               {llvm::omp::Directive::OMPD_target_exit_data}},
-          {dirNameModifier::TargetData,
-              {llvm::omp::Directive::OMPD_target_data}},
           {dirNameModifier::TargetUpdate,
               {llvm::omp::Directive::OMPD_target_update}},
           {dirNameModifier::Task, {llvm::omp::Directive::OMPD_task}},
-          {dirNameModifier::Taskloop, llvm::omp::taskloopSet}};
+          {dirNameModifier::Taskloop, llvm::omp::taskloopSet},
+          {dirNameModifier::Teams, teamSet}};
   if (const auto &directiveName{
           std::get<std::optional<dirNameModifier>>(x.v.t)}) {
     auto search{dirNameModifierMap.find(*directiveName)};

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index d41d60755edbc1..3b5de101fe0793 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -66,22 +66,21 @@ static OmpDirectiveSet targetSet{Directive::OMPD_target,
     Directive::OMPD_target_parallel, Directive::OMPD_target_parallel_do,
     Directive::OMPD_target_parallel_do_simd, Directive::OMPD_target_simd,
     Directive::OMPD_target_teams, Directive::OMPD_target_teams_distribute,
+    Directive::OMPD_target_teams_distribute_parallel_do,
+    Directive::OMPD_target_teams_distribute_parallel_do_simd,
     Directive::OMPD_target_teams_distribute_simd};
 static OmpDirectiveSet simdSet{Directive::OMPD_distribute_parallel_do_simd,
-    Directive::OMPD_distribute_simd, Directive::OMPD_parallel_do_simd,
-    Directive::OMPD_do_simd, Directive::OMPD_simd,
-    Directive::OMPD_target_parallel_do_simd,
+    Directive::OMPD_distribute_simd, Directive::OMPD_do_simd,
+    Directive::OMPD_parallel_do_simd, Directive::OMPD_simd,
+    Directive::OMPD_target_parallel_do_simd, Directive::OMPD_target_simd,
     Directive::OMPD_target_teams_distribute_parallel_do_simd,
-    Directive::OMPD_target_teams_distribute_simd, Directive::OMPD_target_simd,
-    Directive::OMPD_taskloop_simd,
+    Directive::OMPD_target_teams_distribute_simd, Directive::OMPD_taskloop_simd,
     Directive::OMPD_teams_distribute_parallel_do_simd,
     Directive::OMPD_teams_distribute_simd};
 static OmpDirectiveSet teamSet{Directive::OMPD_teams,
     Directive::OMPD_teams_distribute,
     Directive::OMPD_teams_distribute_parallel_do,
     Directive::OMPD_teams_distribute_parallel_do_simd,
-    Directive::OMPD_teams_distribute_parallel_for,
-    Directive::OMPD_teams_distribute_parallel_for_simd,
     Directive::OMPD_teams_distribute_simd};
 static OmpDirectiveSet taskGeneratingSet{
     OmpDirectiveSet{Directive::OMPD_task} | taskloopSet};

diff  --git a/flang/test/Parser/OpenMP/if-clause-unparse.f90 b/flang/test/Parser/OpenMP/if-clause-unparse.f90
new file mode 100644
index 00000000000000..20f7b36e743e1a
--- /dev/null
+++ b/flang/test/Parser/OpenMP/if-clause-unparse.f90
@@ -0,0 +1,61 @@
+! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck %s
+! Check Unparsing of OpenMP IF clause
+
+program if_unparse
+  logical :: cond
+  integer :: i
+
+  ! CHECK: !$OMP TARGET UPDATE
+  ! CHECK-SAME: IF(cond)
+  !$omp target update if(cond)
+
+  ! CHECK: !$OMP TARGET UPDATE
+  ! CHECK-SAME: IF(TARGETUPDATE:cond)
+  !$omp target update if(target update: cond)
+  
+  ! CHECK: !$OMP TARGET UPDATE
+  ! CHECK-SAME: IF(TARGETUPDATE:cond)
+  !$omp target update if(targetupdate: cond)
+
+  ! CHECK: !$OMP TARGET ENTER DATA
+  ! CHECK-SAME: IF(TARGETENTERDATA:cond)
+  !$omp target enter data map(to: i) if(target enter data: cond)
+
+  ! CHECK: !$OMP TARGET EXIT DATA
+  ! CHECK-SAME: IF(TARGETEXITDATA:cond)
+  !$omp target exit data map(from: i) if(target exit data: cond)
+
+  ! CHECK: !$OMP TARGET DATA
+  ! CHECK-SAME: IF(TARGETDATA:cond)
+  !$omp target data map(tofrom: i) if(target data: cond)
+  !$omp end target data
+
+  ! CHECK: !$OMP TARGET
+  ! CHECK-SAME: IF(TARGET:cond)
+  !$omp target if(target: cond)
+  !$omp end target
+
+  ! CHECK: !$OMP TEAMS
+  ! CHECK-SAME: IF(TEAMS:cond)
+  !$omp teams if(teams: cond)
+  !$omp end teams
+
+  ! CHECK: !$OMP PARALLEL DO SIMD
+  ! CHECK-SAME: IF(PARALLEL:i<10) IF(SIMD:.FALSE.)
+  !$omp parallel do simd if(parallel: i < 10) if(simd: .false.)
+  do i = 1, 10
+  end do
+  !$omp end parallel do simd
+
+  ! CHECK: !$OMP TASK
+  ! CHECK-SAME: IF(TASK:cond)
+  !$omp task if(task: cond)
+  !$omp end task
+
+  ! CHECK: !$OMP TASKLOOP
+  ! CHECK-SAME: IF(TASKLOOP:cond)
+  !$omp taskloop if(taskloop: cond)
+  do i = 1, 10
+  end do
+  !$omp end taskloop
+end program if_unparse

diff  --git a/flang/test/Parser/OpenMP/if-clause.f90 b/flang/test/Parser/OpenMP/if-clause.f90
new file mode 100644
index 00000000000000..ca62f6969eee1c
--- /dev/null
+++ b/flang/test/Parser/OpenMP/if-clause.f90
@@ -0,0 +1,61 @@
+! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck %s
+
+program openmp_parse_if
+  logical :: cond
+  integer :: i
+
+  ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
+  ! CHECK-NEXT: OmpClause -> If -> OmpIfClause
+  ! CHECK-NOT: DirectiveNameModifier
+  !$omp target update if(cond)
+
+  ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
+  ! CHECK-NEXT: OmpClause -> If -> OmpIfClause
+  ! CHECK-NEXT: DirectiveNameModifier = TargetUpdate
+  !$omp target update if(target update: cond)
+
+  ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target enter data
+  ! CHECK: OmpClause -> If -> OmpIfClause
+  ! CHECK-NEXT: DirectiveNameModifier = TargetEnterData
+  !$omp target enter data map(to: i) if(target enter data: cond)
+
+  ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target exit data
+  ! CHECK: OmpClause -> If -> OmpIfClause
+  ! CHECK-NEXT: DirectiveNameModifier = TargetExitData
+  !$omp target exit data map(from: i) if(target exit data: cond)
+
+  ! CHECK: OmpBlockDirective -> llvm::omp::Directive = target data
+  ! CHECK: OmpClause -> If -> OmpIfClause
+  ! CHECK-NEXT: DirectiveNameModifier = TargetData
+  !$omp target data map(tofrom: i) if(target data: cond)
+  !$omp end target data
+
+  ! CHECK: OmpLoopDirective -> llvm::omp::Directive = target teams distribute parallel do simd
+  ! CHECK: OmpClause -> If -> OmpIfClause
+  ! CHECK-NEXT: DirectiveNameModifier = Target
+  ! CHECK: OmpClause -> If -> OmpIfClause
+  ! CHECK-NEXT: DirectiveNameModifier = Teams
+  ! CHECK: OmpClause -> If -> OmpIfClause
+  ! CHECK-NEXT: DirectiveNameModifier = Parallel
+  ! CHECK: OmpClause -> If -> OmpIfClause
+  ! CHECK-NEXT: DirectiveNameModifier = Simd
+  !$omp target teams distribute parallel do simd if(target: cond) &
+  !$omp&    if(teams: cond) if(parallel: cond) if(simd: cond)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute parallel do simd
+
+  ! CHECK: OmpBlockDirective -> llvm::omp::Directive = task
+  ! CHECK-NEXT: OmpClause -> If -> OmpIfClause
+  ! CHECK-NEXT: DirectiveNameModifier = Task
+  !$omp task if(task: cond)
+  !$omp end task
+
+  ! CHECK: OmpLoopDirective -> llvm::omp::Directive = taskloop
+  ! CHECK-NEXT: OmpClause -> If -> OmpIfClause
+  ! CHECK-NEXT: DirectiveNameModifier = Taskloop
+  !$omp taskloop if(taskloop: cond)
+  do i = 1, 10
+  end do
+  !$omp end taskloop
+end program openmp_parse_if

diff  --git a/flang/test/Semantics/OpenMP/if-clause.f90 b/flang/test/Semantics/OpenMP/if-clause.f90
new file mode 100644
index 00000000000000..dc9aa5ef7f1d15
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/if-clause.f90
@@ -0,0 +1,624 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp
+! Check OpenMP 'if' clause validity for all directives that can have it
+
+program main
+  integer :: i
+
+  ! ----------------------------------------------------------------------------
+  ! DISTRIBUTE PARALLEL DO
+  ! ----------------------------------------------------------------------------
+  !$omp teams
+  !$omp distribute parallel do if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end distribute parallel do
+
+  !$omp distribute parallel do if(parallel: .true.)
+  do i = 1, 10
+  end do
+  !$omp end distribute parallel do
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp distribute parallel do if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end distribute parallel do
+
+  !ERROR: At most one IF clause can appear on the DISTRIBUTE PARALLEL DO directive
+  !$omp distribute parallel do if(.true.) if(parallel: .false.)
+  do i = 1, 10
+  end do
+  !$omp end distribute parallel do
+  !$omp end teams
+
+  ! ----------------------------------------------------------------------------
+  ! DISTRIBUTE PARALLEL DO SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp teams
+  !$omp distribute parallel do simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end distribute parallel do simd
+
+  !$omp distribute parallel do simd if(parallel: .true.) if(simd: .false.)
+  do i = 1, 10
+  end do
+  !$omp end distribute parallel do simd
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp distribute parallel do simd if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end distribute parallel do simd
+  !$omp end teams
+
+  ! ----------------------------------------------------------------------------
+  ! DISTRIBUTE SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp teams
+  !$omp distribute simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end distribute simd
+
+  !$omp distribute simd if(simd: .true.)
+  do i = 1, 10
+  end do
+  !$omp end distribute simd
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp distribute simd if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end distribute simd
+
+  !ERROR: At most one IF clause can appear on the DISTRIBUTE SIMD directive
+  !$omp distribute simd if(.true.) if(simd: .false.)
+  do i = 1, 10
+  end do
+  !$omp end distribute simd
+  !$omp end teams
+
+  ! ----------------------------------------------------------------------------
+  ! DO SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp do simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end do simd
+
+  !$omp do simd if(simd: .true.)
+  do i = 1, 10
+  end do
+  !$omp end do simd
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp do simd if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end do simd
+
+  !ERROR: At most one IF clause can appear on the DO SIMD directive
+  !$omp do simd if(.true.) if(simd: .false.)
+  do i = 1, 10
+  end do
+  !$omp end do simd
+
+  ! ----------------------------------------------------------------------------
+  ! PARALLEL
+  ! ----------------------------------------------------------------------------
+  !$omp parallel if(.true.)
+  !$omp end parallel
+
+  !$omp parallel if(parallel: .true.)
+  !$omp end parallel
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp parallel if(target: .true.)
+  !$omp end parallel
+
+  !ERROR: At most one IF clause can appear on the PARALLEL directive
+  !$omp parallel if(.true.) if(parallel: .false.)
+  !$omp end parallel
+
+  ! ----------------------------------------------------------------------------
+  ! PARALLEL DO
+  ! ----------------------------------------------------------------------------
+  !$omp parallel do if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end parallel do
+
+  !$omp parallel do if(parallel: .true.)
+  do i = 1, 10
+  end do
+  !$omp end parallel do
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp parallel do if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end parallel do
+
+  !ERROR: At most one IF clause can appear on the PARALLEL DO directive
+  !$omp parallel do if(.true.) if(parallel: .false.)
+  do i = 1, 10
+  end do
+  !$omp end parallel do
+
+  ! ----------------------------------------------------------------------------
+  ! PARALLEL DO SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp parallel do simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end parallel do simd
+
+  !$omp parallel do simd if(parallel: .true.) if(simd: .false.)
+  do i = 1, 10
+  end do
+  !$omp end parallel do simd
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp parallel do simd if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end parallel do simd
+
+  ! ----------------------------------------------------------------------------
+  ! PARALLEL SECTIONS
+  ! ----------------------------------------------------------------------------
+  !$omp parallel sections if(.true.)
+  !$omp end parallel sections
+
+  !$omp parallel sections if(parallel: .true.)
+  !$omp end parallel sections
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp parallel sections if(target: .true.)
+  !$omp end parallel sections
+
+  !ERROR: At most one IF clause can appear on the PARALLEL SECTIONS directive
+  !$omp parallel sections if(.true.) if(parallel: .false.)
+  !$omp end parallel sections
+
+  ! ----------------------------------------------------------------------------
+  ! PARALLEL WORKSHARE
+  ! ----------------------------------------------------------------------------
+  !$omp parallel workshare if(.true.)
+  !$omp end parallel workshare
+
+  !$omp parallel workshare if(parallel: .true.)
+  !$omp end parallel workshare
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp parallel workshare if(target: .true.)
+  !$omp end parallel workshare
+
+  !ERROR: At most one IF clause can appear on the PARALLEL WORKSHARE directive
+  !$omp parallel workshare if(.true.) if(parallel: .false.)
+  !$omp end parallel workshare
+
+  ! ----------------------------------------------------------------------------
+  ! SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end simd
+
+  !$omp simd if(simd: .true.)
+  do i = 1, 10
+  end do
+  !$omp end simd
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp simd if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end simd
+
+  !ERROR: At most one IF clause can appear on the SIMD directive
+  !$omp simd if(.true.) if(simd: .false.)
+  do i = 1, 10
+  end do
+  !$omp end simd
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET
+  ! ----------------------------------------------------------------------------
+  !$omp target if(.true.)
+  !$omp end target
+
+  !$omp target if(target: .true.)
+  !$omp end target
+
+  !ERROR: Unmatched directive name modifier PARALLEL on the IF clause
+  !$omp target if(parallel: .true.)
+  !$omp end target
+
+  !ERROR: At most one IF clause can appear on the TARGET directive
+  !$omp target if(.true.) if(target: .false.)
+  !$omp end target
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET DATA
+  ! ----------------------------------------------------------------------------
+  !$omp target data map(tofrom: i) if(.true.)
+  !$omp end target data
+
+  !$omp target data map(tofrom: i) if(target data: .true.)
+  !$omp end target data
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp target data map(tofrom: i) if(target: .true.)
+  !$omp end target data
+
+  !ERROR: At most one IF clause can appear on the TARGET DATA directive
+  !$omp target data map(tofrom: i) if(.true.) if(target data: .false.)
+  !$omp end target data
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET ENTER DATA
+  ! ----------------------------------------------------------------------------
+  !$omp target enter data map(to: i) if(.true.)
+
+  !$omp target enter data map(to: i) if(target enter data: .true.)
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp target enter data map(to: i) if(target: .true.)
+
+  !ERROR: At most one IF clause can appear on the TARGET ENTER DATA directive
+  !$omp target enter data map(to: i) if(.true.) if(target enter data: .false.)
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET EXIT DATA
+  ! ----------------------------------------------------------------------------
+  !$omp target exit data map(from: i) if(.true.)
+
+  !$omp target exit data map(from: i) if(target exit data: .true.)
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp target exit data map(from: i) if(target: .true.)
+  
+  !ERROR: At most one IF clause can appear on the TARGET EXIT DATA directive
+  !$omp target exit data map(from: i) if(.true.) if(target exit data: .false.)
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET PARALLEL
+  ! ----------------------------------------------------------------------------
+  !$omp target parallel if(.true.)
+  !$omp end target parallel
+
+  !$omp target parallel if(target: .true.) if(parallel: .false.)
+  !$omp end target parallel
+
+  !ERROR: Unmatched directive name modifier SIMD on the IF clause
+  !$omp target parallel if(simd: .true.)
+  !$omp end target parallel
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET PARALLEL DO
+  ! ----------------------------------------------------------------------------
+  !$omp target parallel do if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end target parallel do
+
+  !$omp target parallel do if(target: .true.) if(parallel: .false.)
+  do i = 1, 10
+  end do
+  !$omp end target parallel do
+
+  !ERROR: Unmatched directive name modifier SIMD on the IF clause
+  !$omp target parallel do if(simd: .true.)
+  do i = 1, 10
+  end do
+  !$omp end target parallel do
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET PARALLEL DO SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp target parallel do simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end target parallel do simd
+
+  !$omp target parallel do simd if(target: .true.) if(parallel: .false.) &
+  !$omp&                        if(simd: .true.)
+  do i = 1, 10
+  end do
+  !$omp end target parallel do simd
+
+  !ERROR: Unmatched directive name modifier TEAMS on the IF clause
+  !$omp target parallel do simd if(teams: .true.)
+  do i = 1, 10
+  end do
+  !$omp end target parallel do simd
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp target simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end target simd
+
+  !$omp target simd if(target: .true.) if(simd: .false.)
+  do i = 1, 10
+  end do
+  !$omp end target simd
+
+  !ERROR: Unmatched directive name modifier PARALLEL on the IF clause
+  !$omp target simd if(parallel: .true.)
+  do i = 1, 10
+  end do
+  !$omp end target simd
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET TEAMS
+  ! ----------------------------------------------------------------------------
+  !$omp target teams if(.true.)
+  !$omp end target teams
+
+  !$omp target teams if(target: .true.) if(teams: .false.)
+  !$omp end target teams
+
+  !ERROR: Unmatched directive name modifier PARALLEL on the IF clause
+  !$omp target teams if(parallel: .true.)
+  !$omp end target teams
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET TEAMS DISTRIBUTE
+  ! ----------------------------------------------------------------------------
+  !$omp target teams distribute if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute
+
+  !$omp target teams distribute if(target: .true.) if(teams: .false.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute
+
+  !ERROR: Unmatched directive name modifier PARALLEL on the IF clause
+  !$omp target teams distribute if(parallel: .true.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET TEAMS DISTRIBUTE PARALLEL DO
+  ! ----------------------------------------------------------------------------
+  !$omp target teams distribute parallel do if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute parallel do
+
+  !$omp target teams distribute parallel do &
+  !$omp&   if(target: .true.) if(teams: .false.) if(parallel: .true.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute parallel do
+
+  !ERROR: Unmatched directive name modifier SIMD on the IF clause
+  !$omp target teams distribute parallel do if(simd: .true.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute parallel do
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp target teams distribute parallel do simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute parallel do simd
+
+  !$omp target teams distribute parallel do simd &
+  !$omp&   if(target: .true.) if(teams: .false.) if(parallel: .true.) &
+  !$omp&   if(simd: .false.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute parallel do simd
+
+  !ERROR: Unmatched directive name modifier TASK on the IF clause
+  !$omp target teams distribute parallel do simd if(task: .true.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute parallel do simd
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET TEAMS DISTRIBUTE SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp target teams distribute simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute simd
+
+  !$omp target teams distribute simd &
+  !$omp&   if(target: .true.) if(teams: .false.) if(simd: .true.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute simd
+
+  !ERROR: Unmatched directive name modifier PARALLEL on the IF clause
+  !$omp target teams distribute simd if(parallel: .true.)
+  do i = 1, 10
+  end do
+  !$omp end target teams distribute simd
+
+  ! ----------------------------------------------------------------------------
+  ! TARGET UPDATE
+  ! ----------------------------------------------------------------------------
+  !$omp target update if(.true.)
+  
+  !$omp target update if(target update: .true.)
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp target update if(target: .true.)
+
+  !ERROR: At most one IF clause can appear on the TARGET UPDATE directive
+  !$omp target update if(.true.) if(target update: .false.)
+
+  ! ----------------------------------------------------------------------------
+  ! TASK
+  ! ----------------------------------------------------------------------------
+  !$omp task if(.true.)
+  !$omp end task
+
+  !$omp task if(task: .true.)
+  !$omp end task
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp task if(target: .true.)
+  !$omp end task
+
+  !ERROR: At most one IF clause can appear on the TASK directive
+  !$omp task if(.true.) if(task: .false.)
+  !$omp end task
+
+  ! ----------------------------------------------------------------------------
+  ! TASKLOOP
+  ! ----------------------------------------------------------------------------
+  !$omp taskloop if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end taskloop
+
+  !$omp taskloop if(taskloop: .true.)
+  do i = 1, 10
+  end do
+  !$omp end taskloop
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp taskloop if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end taskloop
+
+  !ERROR: At most one IF clause can appear on the TASKLOOP directive
+  !$omp taskloop if(.true.) if(taskloop: .false.)
+  do i = 1, 10
+  end do
+  !$omp end taskloop
+
+  ! ----------------------------------------------------------------------------
+  ! TASKLOOP SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp taskloop simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end taskloop simd
+
+  !$omp taskloop simd if(taskloop: .true.) if(simd: .false.)
+  do i = 1, 10
+  end do
+  !$omp end taskloop simd
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp taskloop simd if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end taskloop simd
+
+  ! ----------------------------------------------------------------------------
+  ! TEAMS
+  ! ----------------------------------------------------------------------------
+  !$omp teams if(.true.)
+  !$omp end teams
+
+  !$omp teams if(teams: .true.)
+  !$omp end teams
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp teams if(target: .true.)
+  !$omp end teams
+
+  !ERROR: At most one IF clause can appear on the TEAMS directive
+  !$omp teams if(.true.) if(teams: .false.)
+  !$omp end teams
+
+  ! ----------------------------------------------------------------------------
+  ! TEAMS DISTRIBUTE
+  ! ----------------------------------------------------------------------------
+  !$omp teams distribute if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute
+
+  !$omp teams distribute if(teams: .true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp teams distribute if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute
+
+  !ERROR: At most one IF clause can appear on the TEAMS DISTRIBUTE directive
+  !$omp teams distribute if(.true.) if(teams: .true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute
+
+  ! ----------------------------------------------------------------------------
+  ! TEAMS DISTRIBUTE PARALLEL DO
+  ! ----------------------------------------------------------------------------
+  !$omp teams distribute parallel do if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute parallel do
+
+  !$omp teams distribute parallel do if(teams: .true.) if(parallel: .false.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute parallel do
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp teams distribute parallel do if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute parallel do
+
+  ! ----------------------------------------------------------------------------
+  ! TEAMS DISTRIBUTE PARALLEL DO SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp teams distribute parallel do simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute parallel do simd
+
+  !$omp teams distribute parallel do simd &
+  !$omp&   if(teams: .true.) if(parallel: .true.) if(simd: .true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute parallel do simd
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp teams distribute parallel do simd if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute parallel do simd
+
+  ! ----------------------------------------------------------------------------
+  ! TEAMS DISTRIBUTE SIMD
+  ! ----------------------------------------------------------------------------
+  !$omp teams distribute simd if(.true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute simd
+
+  !$omp teams distribute simd if(teams: .true.) if(simd: .true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute simd
+
+  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !$omp teams distribute simd if(target: .true.)
+  do i = 1, 10
+  end do
+  !$omp end teams distribute simd
+end program main

diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index f7a980476bac0c..6c9f6a5edb01c1 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -640,7 +640,6 @@ def OMP_Atomic : Directive<"atomic"> {
 }
 def OMP_Target : Directive<"target"> {
   let allowedClauses = [
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Map>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_Depend>,
@@ -654,6 +653,7 @@ def OMP_Target : Directive<"target"> {
     VersionedClause<OMPC_OMPX_Attribute>,
   ];
   let allowedOnceClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Device>,
     VersionedClause<OMPC_ThreadLimit, 51>,
     VersionedClause<OMPC_DefaultMap>,
@@ -672,12 +672,13 @@ def OMP_Teams : Directive<"teams"> {
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Default>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NumTeams>,
     VersionedClause<OMPC_ThreadLimit>
   ];
 }
 def OMP_Cancel : Directive<"cancel"> {
-  let allowedClauses = [
+  let allowedOnceClauses = [
     VersionedClause<OMPC_If>
   ];
 }
@@ -740,6 +741,7 @@ def OMP_TargetExitData : Directive<"target exit data"> {
 }
 def OMP_TargetParallel : Directive<"target parallel"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Map>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_Depend>,
@@ -757,7 +759,6 @@ def OMP_TargetParallel : Directive<"target parallel"> {
   let allowedOnceClauses = [
     VersionedClause<OMPC_DefaultMap>,
     VersionedClause<OMPC_Device>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_ProcBind>,
     VersionedClause<OMPC_OMPX_DynCGroupMem>,
@@ -796,6 +797,7 @@ def OMP_TargetParallelFor : Directive<"target parallel for"> {
 }
 def OMP_TargetParallelDo : Directive<"target parallel do"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Map>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_FirstPrivate>,
@@ -812,7 +814,6 @@ def OMP_TargetParallelDo : Directive<"target parallel do"> {
     VersionedClause<OMPC_Copyin>
   ];
   let allowedOnceClauses = [
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_ProcBind>,
     VersionedClause<OMPC_Device>,
@@ -905,6 +906,7 @@ def OMP_ParallelForSimd : Directive<"parallel for simd"> {
 }
 def OMP_ParallelDoSimd : Directive<"parallel do simd"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_FirstPrivate>,
@@ -918,7 +920,6 @@ def OMP_ParallelDoSimd : Directive<"parallel do simd"> {
     VersionedClause<OMPC_NonTemporal>,
   ];
   let allowedOnceClauses = [
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_ProcBind>,
     VersionedClause<OMPC_Schedule>,
@@ -962,7 +963,6 @@ def OMP_ParallelMasked : Directive<"parallel masked"> {
 }
 def OMP_ParallelSections : Directive<"parallel sections"> {
   let allowedClauses = [
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_ProcBind>,
     VersionedClause<OMPC_Private>,
@@ -975,6 +975,7 @@ def OMP_ParallelSections : Directive<"parallel sections"> {
     VersionedClause<OMPC_OMPX_Attribute>,
   ];
   let allowedOnceClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NumThreads>
   ];
 }
@@ -1008,6 +1009,7 @@ def OMP_DoSimd : Directive<"do simd"> {
     VersionedClause<OMPC_Reduction>
   ];
   let allowedOnceClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Schedule>,
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Ordered>,
@@ -1065,6 +1067,7 @@ def OMP_TaskLoop : Directive<"taskloop"> {
 }
 def OMP_TaskLoopSimd : Directive<"taskloop simd"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Aligned>,
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Default>,
@@ -1081,7 +1084,6 @@ def OMP_TaskLoopSimd : Directive<"taskloop simd"> {
     VersionedClause<OMPC_Untied>
   ];
   let allowedOnceClauses = [
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_SafeLen>,
     VersionedClause<OMPC_SimdLen>,
@@ -1312,6 +1314,7 @@ def OMP_TargetParallelDoSimd : Directive<"target parallel do simd"> {
 }
 def OMP_TargetSimd : Directive<"target simd"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Aligned>,
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Depend>,
@@ -1333,7 +1336,6 @@ def OMP_TargetSimd : Directive<"target simd"> {
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_SafeLen>,
     VersionedClause<OMPC_SimdLen>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_ProcBind>,
     VersionedClause<OMPC_Device>,
@@ -1358,9 +1360,13 @@ def OMP_TeamsDistribute : Directive<"teams distribute"> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_OMPX_Attribute>,
   ];
+  let allowedOnceClauses = [
+    VersionedClause<OMPC_If>
+  ];
 }
 def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If, 50>,
     VersionedClause<OMPC_Aligned>,
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_FirstPrivate>,
@@ -1376,7 +1382,6 @@ def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> {
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_DistSchedule>,
-    VersionedClause<OMPC_If, 50>,
     VersionedClause<OMPC_NumTeams>,
     VersionedClause<OMPC_SafeLen>,
     VersionedClause<OMPC_SimdLen>,
@@ -1415,6 +1420,7 @@ def OMP_TeamsDistributeParallelForSimd :
 def OMP_TeamsDistributeParallelDoSimd :
     Directive<"teams distribute parallel do simd"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_FirstPrivate>,
     VersionedClause<OMPC_LastPrivate>,
@@ -1436,7 +1442,6 @@ def OMP_TeamsDistributeParallelDoSimd :
     VersionedClause<OMPC_Schedule>,
     VersionedClause<OMPC_SafeLen>,
     VersionedClause<OMPC_SimdLen>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Order, 50>
   ];
 }
@@ -1466,6 +1471,7 @@ def OMP_TeamsDistributeParallelFor :
 def OMP_TeamsDistributeParallelDo :
     Directive<"teams distribute parallel do"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_FirstPrivate>,
     VersionedClause<OMPC_LastPrivate>,
@@ -1482,7 +1488,6 @@ let allowedOnceClauses = [
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_DistSchedule>,
     VersionedClause<OMPC_Ordered>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_ProcBind>,
     VersionedClause<OMPC_Schedule>,
@@ -1652,6 +1657,7 @@ def OMP_TargetTeamsDistributeParallelForSimd :
 def OMP_TargetTeamsDistributeParallelDoSimd :
     Directive<"target teams distribute parallel do simd"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Map>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_Depend>,
@@ -1670,7 +1676,6 @@ def OMP_TargetTeamsDistributeParallelDoSimd :
     VersionedClause<OMPC_NonTemporal>
   ];
   let allowedOnceClauses = [
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Device>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_DefaultMap>,
@@ -2070,6 +2075,7 @@ def OMP_teams_loop : Directive<"teams loop"> {
 }
 def OMP_target_teams_loop : Directive<"target teams loop"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Depend>,
     VersionedClause<OMPC_DefaultMap>,
@@ -2089,7 +2095,6 @@ def OMP_target_teams_loop : Directive<"target teams loop"> {
     VersionedClause<OMPC_Bind, 50>,
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Default>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_NumTeams>,
     VersionedClause<OMPC_Order>,
@@ -2120,6 +2125,7 @@ def OMP_parallel_loop : Directive<"parallel loop"> {
 }
 def OMP_target_parallel_loop : Directive<"target parallel loop"> {
   let allowedClauses = [
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_Depend>,
@@ -2140,7 +2146,6 @@ def OMP_target_parallel_loop : Directive<"target parallel loop"> {
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_DefaultMap>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_Order>,


        


More information about the llvm-commits mailing list