[flang-commits] [flang] [mlir] [MLIR][OpenMP] Improve assemblyFormat handling for clause-based ops (PR #108023)

Sergio Afonso via flang-commits flang-commits at lists.llvm.org
Tue Sep 10 06:18:47 PDT 2024


https://github.com/skatrak created https://github.com/llvm/llvm-project/pull/108023

This patch modifies the representation of `OpenMP_Clause` to allow definitions to incorporate both required and optional arguments while still allowing operations including them and overriding the `assemblyFormat` to take advantage of automatically-populated format strings.

The proposed approach is to split the `assemblyFormat` clause property into `reqAssemblyFormat` and `optAssemblyFormat`, and remove the `isRequired` template and associated `required` property. The `OpenMP_Op` class, in turn, populates the new `clausesReqAssemblyFormat` and `clausesOptAssemblyFormat` properties in addition to `clausesAssemblyFormat`. These properties can be used by clause-based OpenMP operation definitions to reconstruct parts of the clause-inherited format string in a more flexible way when overriding it.

Clause definitions are updated to follow this new approach and some operation definitions overriding the `assemblyFormat` are simplified by taking advantage of the improved flexibility, reducing code duplication. The `verify-openmp-ops` tablegen pass is updated for the new `OpenMP_Clause` representation.

Some MLIR and Flang unit tests had to be updated due to changes to the default printing order of clauses on updated operations.

>From 74d6885097a3dc4c93fd99d674c20ea7c7039901 Mon Sep 17 00:00:00 2001
From: Sergio Afonso <safonsof at amd.com>
Date: Tue, 10 Sep 2024 13:47:21 +0100
Subject: [PATCH] [MLIR][OpenMP] Improve assemblyFormat handling on
 clause-based representation

This patch modifies the representation of `OpenMP_Clauses` to allow them to
incorporate both required and optional arguments while still allowing
operations including them and overriding the `assemblyFormat` to take advantage
of automatically-populated format strings.

The proposed approach is to split the `assemblyFormat` clause property into
`reqAssemblyFormat` and `optAssemblyFormat`, and remove the `isRequired`
template and associated `required` property. The `OpenMP_Op` class, in turn,
populates the new `clausesReqAssemblyFormat` and `clausesOptAssemblyFormat`
properties in addition to `clausesAssemblyFormat`. These properties can be used
by clause-based OpenMP operation definitions to reconstruct parts of the
clause-inherited format string in a more flexible way when overriding it.

Clause definitions are updated to follow this new approach and some operation
definitions overriding the `assemblyFormat` are simplified by taking advantage
of the improved flexibility, reducing code duplication. The `verify-openmp-ops`
tablegen pass is updated for the new `OpenMP_Clause` representation.

Some MLIR and Flang unit tests had to be updated due to changes to the default
printing order of clauses on updated operations.
---
 flang/test/Lower/OpenMP/parallel.f90          |   6 +-
 flang/test/Lower/OpenMP/wsloop-chunks.f90     |   6 +-
 flang/test/Lower/OpenMP/wsloop-monotonic.f90  |   2 +-
 .../test/Lower/OpenMP/wsloop-nonmonotonic.f90 |   2 +-
 flang/test/Lower/OpenMP/wsloop-schedule.f90   |   2 +-
 flang/test/Lower/OpenMP/wsloop.f90            |   2 +-
 .../mlir/Dialect/OpenMP/OpenMPClauses.td      | 256 +++++++++---------
 .../mlir/Dialect/OpenMP/OpenMPOpBase.td       |  60 ++--
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td |  88 ++----
 .../OpenMPToLLVM/convert-to-llvmir.mlir       |   2 +-
 mlir/test/Dialect/OpenMP/ops.mlir             |  20 +-
 mlir/test/mlir-tblgen/openmp-ops-verify.td    |  19 +-
 mlir/test/mlir-tblgen/openmp-ops.td           |  61 ++++-
 mlir/tools/mlir-tblgen/OmpOpGen.cpp           |  35 ++-
 14 files changed, 278 insertions(+), 283 deletions(-)

diff --git a/flang/test/Lower/OpenMP/parallel.f90 b/flang/test/Lower/OpenMP/parallel.f90
index 07f4680f79ee27..4942d3a053433d 100644
--- a/flang/test/Lower/OpenMP/parallel.f90
+++ b/flang/test/Lower/OpenMP/parallel.f90
@@ -194,9 +194,9 @@ subroutine parallel_multiple_clauses(alpha, num_threads)
    !CHECK: omp.terminator
    !$omp end parallel
 
-   !CHECK: omp.parallel if({{.*}}) num_threads({{.*}} : i32) allocate(
-   !CHECK: %{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>
-   !CHECK: ) {
+   !CHECK: omp.parallel allocate(%{{.+}} : i64 -> %{{.+}}#1 : !fir.ref<i32>)
+   !CHECK: if({{.*}}) num_threads({{.*}} : i32)
+   !CHECK: private(@{{.+}} %{{.+}}#0 -> %{{.+}} : !fir.ref<i32>) {
    !$omp parallel num_threads(num_threads) if(alpha .le. 0) allocate(omp_high_bw_mem_alloc: alpha) private(alpha)
    !CHECK: fir.call
    call f3()
diff --git a/flang/test/Lower/OpenMP/wsloop-chunks.f90 b/flang/test/Lower/OpenMP/wsloop-chunks.f90
index 3d4e9bc505f281..cacb5b0d4b4a1e 100644
--- a/flang/test/Lower/OpenMP/wsloop-chunks.f90
+++ b/flang/test/Lower/OpenMP/wsloop-chunks.f90
@@ -20,7 +20,7 @@ program wsloop
 ! CHECK:         %[[VAL_3:.*]] = arith.constant 1 : i32
 ! CHECK:         %[[VAL_4:.*]] = arith.constant 9 : i32
 ! CHECK:         %[[VAL_5:.*]] = arith.constant 1 : i32
-! CHECK:         omp.wsloop schedule(static = %[[VAL_2]] : i32) nowait {
+! CHECK:         omp.wsloop nowait schedule(static = %[[VAL_2]] : i32) {
 ! CHECK-NEXT:      omp.loop_nest (%[[ARG0:.*]]) : i32 = (%[[VAL_3]]) to (%[[VAL_4]]) inclusive step (%[[VAL_5]]) {
 ! CHECK:             fir.store %[[ARG0]] to %[[STORE_IV:.*]]#1 : !fir.ref<i32>
 ! CHECK:             %[[LOAD_IV:.*]] = fir.load %[[STORE_IV]]#0 : !fir.ref<i32>
@@ -41,7 +41,7 @@ program wsloop
 ! CHECK:         %[[VAL_15:.*]] = arith.constant 1 : i32
 ! CHECK:         %[[VAL_16:.*]] = arith.constant 9 : i32
 ! CHECK:         %[[VAL_17:.*]] = arith.constant 1 : i32
-! CHECK:         omp.wsloop schedule(static = %[[VAL_14]] : i32) nowait {
+! CHECK:         omp.wsloop nowait schedule(static = %[[VAL_14]] : i32) {
 ! CHECK-NEXT:      omp.loop_nest (%[[ARG1:.*]]) : i32 = (%[[VAL_15]]) to (%[[VAL_16]]) inclusive step (%[[VAL_17]]) {
 ! CHECK:             fir.store %[[ARG1]] to %[[STORE_IV1:.*]]#1 : !fir.ref<i32>
 ! CHECK:             %[[VAL_24:.*]] = arith.constant 2 : i32
@@ -68,7 +68,7 @@ program wsloop
 ! CHECK:         %[[VAL_30:.*]] = arith.constant 1 : i32
 ! CHECK:         %[[VAL_31:.*]] = arith.constant 9 : i32
 ! CHECK:         %[[VAL_32:.*]] = arith.constant 1 : i32
-! CHECK:         omp.wsloop schedule(static = %[[VAL_29]] : i32) nowait {
+! CHECK:         omp.wsloop nowait schedule(static = %[[VAL_29]] : i32) {
 ! CHECK-NEXT:      omp.loop_nest (%[[ARG2:.*]]) : i32 = (%[[VAL_30]]) to (%[[VAL_31]]) inclusive step (%[[VAL_32]]) {
 ! CHECK:             fir.store %[[ARG2]] to %[[STORE_IV2:.*]]#1 : !fir.ref<i32>
 ! CHECK:             %[[VAL_39:.*]] = arith.constant 3 : i32
diff --git a/flang/test/Lower/OpenMP/wsloop-monotonic.f90 b/flang/test/Lower/OpenMP/wsloop-monotonic.f90
index 2a5cc2321c6444..ec1b216a8695fa 100644
--- a/flang/test/Lower/OpenMP/wsloop-monotonic.f90
+++ b/flang/test/Lower/OpenMP/wsloop-monotonic.f90
@@ -15,7 +15,7 @@ program wsloop_dynamic
 !CHECK:     %[[WS_LB:.*]] = arith.constant 1 : i32
 !CHECK:     %[[WS_UB:.*]] = arith.constant 9 : i32
 !CHECK:     %[[WS_STEP:.*]] = arith.constant 1 : i32
-!CHECK:     omp.wsloop schedule(dynamic, monotonic) nowait {
+!CHECK:     omp.wsloop nowait schedule(dynamic, monotonic) {
 !CHECK-NEXT:  omp.loop_nest (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]]) {
 !CHECK:         fir.store %[[I]] to %[[ALLOCA_IV:.*]]#1 : !fir.ref<i32>
 
diff --git a/flang/test/Lower/OpenMP/wsloop-nonmonotonic.f90 b/flang/test/Lower/OpenMP/wsloop-nonmonotonic.f90
index 1e71807ae5b1ab..e011a8de1e69ed 100644
--- a/flang/test/Lower/OpenMP/wsloop-nonmonotonic.f90
+++ b/flang/test/Lower/OpenMP/wsloop-nonmonotonic.f90
@@ -17,7 +17,7 @@ program wsloop_dynamic
 !CHECK:     %[[WS_LB:.*]] = arith.constant 1 : i32
 !CHECK:     %[[WS_UB:.*]] = arith.constant 9 : i32
 !CHECK:     %[[WS_STEP:.*]] = arith.constant 1 : i32
-!CHECK:     omp.wsloop schedule(dynamic, nonmonotonic) nowait {
+!CHECK:     omp.wsloop nowait schedule(dynamic, nonmonotonic) {
 !CHECK-NEXT:  omp.loop_nest (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]]) {
 !CHECK:         fir.store %[[I]] to %[[ALLOCA_IV]]#1 : !fir.ref<i32>
 
diff --git a/flang/test/Lower/OpenMP/wsloop-schedule.f90 b/flang/test/Lower/OpenMP/wsloop-schedule.f90
index 1df67474d65e3b..de0a2dae6b5874 100644
--- a/flang/test/Lower/OpenMP/wsloop-schedule.f90
+++ b/flang/test/Lower/OpenMP/wsloop-schedule.f90
@@ -14,7 +14,7 @@ program wsloop_dynamic
 !CHECK:      %[[WS_LB:.*]] = arith.constant 1 : i32
 !CHECK:      %[[WS_UB:.*]] = arith.constant 9 : i32
 !CHECK:      %[[WS_STEP:.*]] = arith.constant 1 : i32
-!CHECK:      omp.wsloop schedule(runtime, simd) nowait {
+!CHECK:      omp.wsloop nowait schedule(runtime, simd) {
 !CHECK-NEXT:   omp.loop_nest (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]]) {
 !CHECK:          fir.store %[[I]] to %[[STORE:.*]]#1 : !fir.ref<i32>
 
diff --git a/flang/test/Lower/OpenMP/wsloop.f90 b/flang/test/Lower/OpenMP/wsloop.f90
index 6536f5b83d2cbd..6566b3cbd6d4d9 100644
--- a/flang/test/Lower/OpenMP/wsloop.f90
+++ b/flang/test/Lower/OpenMP/wsloop.f90
@@ -64,7 +64,7 @@ subroutine loop_with_schedule_nowait
   ! CHECK:      %[[WS_LB:.*]] = arith.constant 1 : i32
   ! CHECK:      %[[WS_UB:.*]] = arith.constant 9 : i32
   ! CHECK:      %[[WS_STEP:.*]] = arith.constant 1 : i32
-  ! CHECK:      omp.wsloop schedule(runtime) nowait {
+  ! CHECK:      omp.wsloop nowait schedule(runtime) {
   ! CHECK-NEXT:   omp.loop_nest (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]]) {
   !$OMP DO SCHEDULE(runtime)
   do i=1, 9
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index e703c323edbc8a..c579ba6e751d2b 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -29,14 +29,14 @@ include "mlir/IR/SymbolInterfaces.td"
 class OpenMP_AlignedClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Variadic<OpenMP_PointerLikeType>:$aligned_vars,
     OptionalAttr<I64ArrayAttr>:$alignments
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `aligned` `(` custom<AlignedClause>($aligned_vars, type($aligned_vars),
                                         $alignments) `)`
   }];
@@ -57,8 +57,8 @@ def OpenMP_AlignedClause : OpenMP_AlignedClauseSkip<>;
 class OpenMP_AllocateClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Variadic<AnyType>:$allocate_vars,
     Variadic<AnyType>:$allocator_vars
@@ -69,7 +69,7 @@ class OpenMP_AllocateClauseSkip<
     unsigned getNumAllocatorsVars() { return getAllocatorVars().size(); }
   }];
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `allocate` `(`
       custom<AllocateAndAllocator>($allocate_vars, type($allocate_vars),
                                    $allocator_vars, type($allocator_vars)) `)`
@@ -91,13 +91,13 @@ def OpenMP_AllocateClause : OpenMP_AllocateClauseSkip<>;
 class OpenMP_CancelDirectiveNameClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/true, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     CancellationConstructTypeAttr:$cancel_directive
   );
 
-  let assemblyFormat = [{
+  let reqAssemblyFormat = [{
     `cancellation_construct_type` `(`
       custom<ClauseAttr>($cancel_directive) `)`
   }];
@@ -114,14 +114,14 @@ def OpenMP_CancelDirectiveNameClause : OpenMP_CancelDirectiveNameClauseSkip<>;
 class OpenMP_CopyprivateClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Variadic<OpenMP_PointerLikeType>:$copyprivate_vars,
     OptionalAttr<SymbolRefArrayAttr>:$copyprivate_syms
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `copyprivate` `(`
       custom<Copyprivate>($copyprivate_vars, type($copyprivate_vars),
                           $copyprivate_syms) `)`
@@ -143,8 +143,8 @@ def OpenMP_CopyprivateClause : OpenMP_CopyprivateClauseSkip<>;
 class OpenMP_CriticalNameClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/true, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let traits = [
     Symbol
   ];
@@ -153,7 +153,7 @@ class OpenMP_CriticalNameClauseSkip<
     SymbolNameAttr:$sym_name
   );
 
-  let assemblyFormat = "$sym_name";
+  let reqAssemblyFormat = "$sym_name";
 
   let description = [{
     The `sym_name` can be used in `omp.critical` constructs in the dialect.
@@ -169,14 +169,14 @@ def OpenMP_CriticalNameClause : OpenMP_CriticalNameClauseSkip<>;
 class OpenMP_DependClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     OptionalAttr<TaskDependArrayAttr>:$depend_kinds,
     Variadic<OpenMP_PointerLikeType>:$depend_vars
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `depend` `(`
       custom<DependVarList>($depend_vars, type($depend_vars), $depend_kinds) `)`
   }];
@@ -197,13 +197,13 @@ def OpenMP_DependClause : OpenMP_DependClauseSkip<>;
 class OpenMP_DeviceClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Optional<AnyInteger>:$device
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `device` `(` $device `:` type($device) `)`
   }];
 
@@ -222,14 +222,14 @@ def OpenMP_DeviceClause : OpenMP_DeviceClauseSkip<>;
 class OpenMP_DistScheduleClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     UnitAttr:$dist_schedule_static,
     Optional<IntLikeType>:$dist_schedule_chunk_size
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `dist_schedule_static` $dist_schedule_static
     | `dist_schedule_chunk_size` `(` $dist_schedule_chunk_size `:`
       type($dist_schedule_chunk_size) `)`
@@ -252,15 +252,15 @@ def OpenMP_DistScheduleClause : OpenMP_DistScheduleClauseSkip<>;
 class OpenMP_DoacrossClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/true, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     OptionalAttr<ClauseDependAttr>:$doacross_depend_type,
     ConfinedAttr<OptionalAttr<I64Attr>, [IntMinValue<0>]>:$doacross_num_loops,
     Variadic<AnyType>:$doacross_depend_vars
   );
 
-  let assemblyFormat = [{
+  let reqAssemblyFormat = [{
     ( `depend_type` `` $doacross_depend_type^ )?
     ( `depend_vec` `(` $doacross_depend_vars^ `:` type($doacross_depend_vars)
                    `)` )?
@@ -290,13 +290,13 @@ def OpenMP_DoacrossClause : OpenMP_DoacrossClauseSkip<>;
 class OpenMP_FilterClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Optional<IntLikeType>:$filtered_thread_id
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `filter` `(` $filtered_thread_id `:` type($filtered_thread_id) `)`
   }];
 
@@ -318,13 +318,13 @@ def OpenMP_FilterClause : OpenMP_FilterClauseSkip<>;
 class OpenMP_FinalClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Optional<I1>:$final
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `final` `(` $final `)`
   }];
 
@@ -346,13 +346,13 @@ def OpenMP_FinalClause : OpenMP_FinalClauseSkip<>;
 class OpenMP_GrainsizeClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Optional<IntLikeType>:$grainsize
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `grainsize` `(` $grainsize `:` type($grainsize) `)`
   }];
 
@@ -373,13 +373,13 @@ def OpenMP_GrainsizeClause : OpenMP_GrainsizeClauseSkip<>;
 class OpenMP_HasDeviceAddrClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Variadic<OpenMP_PointerLikeType>:$has_device_addr_vars
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `has_device_addr` `(` $has_device_addr_vars `:` type($has_device_addr_vars)
                       `)`
   }];
@@ -400,13 +400,13 @@ def OpenMP_HasDeviceAddrClause : OpenMP_HasDeviceAddrClauseSkip<>;
 class OpenMP_HintClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     DefaultValuedOptionalAttr<I64Attr, "0">:$hint
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `hint` `(` custom<SynchronizationHint>($hint) `)`
   }];
 
@@ -426,13 +426,13 @@ def OpenMP_HintClause : OpenMP_HintClauseSkip<>;
 class OpenMP_IfClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Optional<I1>:$if_expr
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `if` `(` $if_expr `)`
   }];
 
@@ -448,8 +448,8 @@ def OpenMP_IfClause : OpenMP_IfClauseSkip<>;
 class OpenMP_InReductionClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let traits = [
     ReductionClauseInterface
   ];
@@ -460,7 +460,7 @@ class OpenMP_InReductionClauseSkip<
     OptionalAttr<SymbolRefArrayAttr>:$in_reduction_syms
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `in_reduction` `(`
       custom<ReductionVarList>($in_reduction_vars, type($in_reduction_vars),
                                $in_reduction_byref, $in_reduction_syms) `)`
@@ -486,13 +486,13 @@ def OpenMP_InReductionClause : OpenMP_InReductionClauseSkip<>;
 class OpenMP_IsDevicePtrClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Variadic<OpenMP_PointerLikeType>:$is_device_ptr_vars
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `is_device_ptr` `(` $is_device_ptr_vars `:` type($is_device_ptr_vars) `)`
   }];
 
@@ -510,14 +510,14 @@ def OpenMP_IsDevicePtrClause : OpenMP_IsDevicePtrClauseSkip<>;
 class OpenMP_LinearClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Variadic<AnyType>:$linear_vars,
     Variadic<I32>:$linear_step_vars
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `linear` `(`
       custom<LinearClause>($linear_vars, type($linear_vars),
                            $linear_step_vars) `)`
@@ -540,8 +540,8 @@ def OpenMP_LinearClause : OpenMP_LinearClauseSkip<>;
 class OpenMP_LoopRelatedClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let traits = [
     AllTypesMatch<
       ["loop_lower_bounds", "loop_upper_bounds", "loop_steps"]>
@@ -572,8 +572,8 @@ def OpenMP_LoopRelatedClause : OpenMP_LoopRelatedClauseSkip<>;
 class OpenMP_MapClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let traits = [
     MapClauseOwningOpInterface
   ];
@@ -582,7 +582,7 @@ class OpenMP_MapClauseSkip<
     Variadic<OpenMP_PointerLikeType>:$map_vars
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `map_entries` `(` custom<MapEntries>($map_vars, type($map_vars)) `)`
   }];
 
@@ -601,13 +601,13 @@ def OpenMP_MapClause : OpenMP_MapClauseSkip<>;
 class OpenMP_MemoryOrderClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     OptionalAttr<MemoryOrderKindAttr>:$memory_order
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `memory_order` `(` custom<ClauseAttr>($memory_order) `)`
   }];
 
@@ -626,13 +626,13 @@ def OpenMP_MemoryOrderClause : OpenMP_MemoryOrderClauseSkip<>;
 class OpenMP_MergeableClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     UnitAttr:$mergeable
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `mergeable` $mergeable
   }];
 
@@ -651,13 +651,13 @@ def OpenMP_MergeableClause : OpenMP_MergeableClauseSkip<>;
 class OpenMP_NogroupClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     UnitAttr:$nogroup
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `nogroup` $nogroup
   }];
 
@@ -679,13 +679,13 @@ def OpenMP_NogroupClause : OpenMP_NogroupClauseSkip<>;
 class OpenMP_NontemporalClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Variadic<OpenMP_PointerLikeType>:$nontemporal_vars
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `nontemporal` `(`  $nontemporal_vars `:` type($nontemporal_vars) `)`
   }];
 
@@ -704,13 +704,13 @@ def OpenMP_NontemporalClause : OpenMP_NontemporalClauseSkip<>;
 class OpenMP_NowaitClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     UnitAttr:$nowait
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `nowait` $nowait
   }];
 
@@ -730,13 +730,13 @@ def OpenMP_NowaitClause : OpenMP_NowaitClauseSkip<>;
 class OpenMP_NumTasksClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Optional<IntLikeType>:$num_tasks
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `num_tasks` `(` $num_tasks `:` type($num_tasks) `)`
   }];
 
@@ -756,14 +756,14 @@ def OpenMP_NumTasksClause : OpenMP_NumTasksClauseSkip<>;
 class OpenMP_NumTeamsClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Optional<AnyInteger>:$num_teams_lower,
     Optional<AnyInteger>:$num_teams_upper
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `num_teams` `(` ( $num_teams_lower^ `:` type($num_teams_lower) )? `to`
                       $num_teams_upper `:` type($num_teams_upper) `)`
   }];
@@ -787,13 +787,13 @@ def OpenMP_NumTeamsClause : OpenMP_NumTeamsClauseSkip<>;
 class OpenMP_NumThreadsClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Optional<IntLikeType>:$num_threads
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `num_threads` `(` $num_threads `:` type($num_threads) `)`
   }];
 
@@ -812,14 +812,14 @@ def OpenMP_NumThreadsClause : OpenMP_NumThreadsClauseSkip<>;
 class OpenMP_OrderClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     OptionalAttr<OrderKindAttr>:$order,
     OptionalAttr<OrderModifierAttr>:$order_mod
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `order` `(` custom<OrderClause>($order, $order_mod) `)`
   }];
 
@@ -839,13 +839,13 @@ def OpenMP_OrderClause : OpenMP_OrderClauseSkip<>;
 class OpenMP_OrderedClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     ConfinedAttr<OptionalAttr<I64Attr>, [IntMinValue<0>]>:$ordered
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `ordered` `(` $ordered `)`
   }];
 
@@ -865,13 +865,13 @@ def OpenMP_OrderedClause : OpenMP_OrderedClauseSkip<>;
 class OpenMP_ParallelizationLevelClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     UnitAttr:$par_level_simd
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `par_level_simd` $par_level_simd
   }];
 
@@ -891,13 +891,13 @@ def OpenMP_ParallelizationLevelClause : OpenMP_ParallelizationLevelClauseSkip<>;
 class OpenMP_PriorityClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Optional<AnyInteger>:$priority
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `priority` `(` $priority `:` type($priority) `)`
   }];
 
@@ -921,14 +921,14 @@ def OpenMP_PriorityClause : OpenMP_PriorityClauseSkip<>;
 class OpenMP_PrivateClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Variadic<AnyType>:$private_vars,
     OptionalAttr<SymbolRefArrayAttr>:$private_syms
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `private` `(`
       custom<PrivateList>($private_vars, type($private_vars), $private_syms) `)`
   }];
@@ -945,13 +945,13 @@ def OpenMP_PrivateClause : OpenMP_PrivateClauseSkip<>;
 class OpenMP_ProcBindClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     OptionalAttr<ProcBindKindAttr>:$proc_bind_kind
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `proc_bind` `(` custom<ClauseAttr>($proc_bind_kind) `)`
   }];
 
@@ -970,8 +970,8 @@ def OpenMP_ProcBindClause : OpenMP_ProcBindClauseSkip<>;
 class OpenMP_ReductionClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let traits = [
     ReductionClauseInterface
   ];
@@ -982,7 +982,7 @@ class OpenMP_ReductionClauseSkip<
     OptionalAttr<SymbolRefArrayAttr>:$reduction_syms
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `reduction` `(`
       custom<ReductionVarList>($reduction_vars, type($reduction_vars),
                                $reduction_byref, $reduction_syms) `)`
@@ -1018,13 +1018,13 @@ def OpenMP_ReductionClause : OpenMP_ReductionClauseSkip<>;
 class OpenMP_SafelenClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     ConfinedAttr<OptionalAttr<I64Attr>, [IntPositive]>:$safelen
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `safelen` `(` $safelen  `)`
   }];
 
@@ -1044,8 +1044,8 @@ def OpenMP_SafelenClause : OpenMP_SafelenClauseSkip<>;
 class OpenMP_ScheduleClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     OptionalAttr<ScheduleKindAttr>:$schedule_kind,
     Optional<AnyType>:$schedule_chunk,
@@ -1053,7 +1053,7 @@ class OpenMP_ScheduleClauseSkip<
     UnitAttr:$schedule_simd
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `schedule` `(`
       custom<ScheduleClause>($schedule_kind, $schedule_mod, $schedule_simd,
                              $schedule_chunk, type($schedule_chunk)) `)`
@@ -1076,13 +1076,13 @@ def OpenMP_ScheduleClause : OpenMP_ScheduleClauseSkip<>;
 class OpenMP_SimdlenClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     ConfinedAttr<OptionalAttr<I64Attr>, [IntPositive]>:$simdlen
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `simdlen` `(` $simdlen  `)`
   }];
 
@@ -1101,8 +1101,8 @@ def OpenMP_SimdlenClause : OpenMP_SimdlenClauseSkip<>;
 class OpenMP_TaskReductionClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let traits = [
     ReductionClauseInterface
   ];
@@ -1113,7 +1113,7 @@ class OpenMP_TaskReductionClauseSkip<
     OptionalAttr<SymbolRefArrayAttr>:$task_reduction_syms
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `task_reduction` `(`
       custom<ReductionVarList>($task_reduction_vars, type($task_reduction_vars),
                                $task_reduction_byref, $task_reduction_syms) `)`
@@ -1149,13 +1149,13 @@ def OpenMP_TaskReductionClause : OpenMP_TaskReductionClauseSkip<>;
 class OpenMP_ThreadLimitClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Optional<AnyInteger>:$thread_limit
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `thread_limit` `(` $thread_limit `:` type($thread_limit) `)`
   }];
 
@@ -1173,13 +1173,13 @@ def OpenMP_ThreadLimitClause : OpenMP_ThreadLimitClauseSkip<>;
 class OpenMP_UntiedClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     UnitAttr:$untied
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `untied` $untied
   }];
 
@@ -1200,13 +1200,13 @@ def OpenMP_UntiedClause : OpenMP_UntiedClauseSkip<>;
 class OpenMP_UseDeviceAddrClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Variadic<OpenMP_PointerLikeType>:$use_device_addr_vars
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `use_device_addr` `(` $use_device_addr_vars `:` type($use_device_addr_vars) `)`
   }];
 
@@ -1225,13 +1225,13 @@ def OpenMP_UseDeviceAddrClause : OpenMP_UseDeviceAddrClauseSkip<>;
 class OpenMP_UseDevicePtrClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins
     Variadic<OpenMP_PointerLikeType>:$use_device_ptr_vars
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `use_device_ptr` `(` $use_device_ptr_vars `:` type($use_device_ptr_vars) `)`
   }];
 
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td
index 83e23599b37f6f..8a7e1b3461cce4 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td
@@ -59,18 +59,12 @@ def OpenMP_MapBoundsType : OpenMP_Type<"MapBounds", "map_bounds_ty"> {
 // Optionally, operation traits and extra class declarations might be attached
 // to clauses, which will be forwarded to all operations that include them.
 //
-// Each clause must specify whether it's required or optional. This impacts how
-// the `assemblyFormat` for operations including it get generated.
-//
 // An `OpenMP_Op` can inhibit the inheritance of `traits`, `arguments`,
-// `assemblyFormat`, `description` and `extraClassDeclaration` fields from any
-// given `OpenMP_Clause` by setting to 1 the corresponding "skip" template
-// argument bit.
-class OpenMP_Clause<bit isRequired, bit skipTraits, bit skipArguments,
-                    bit skipAssemblyFormat, bit skipDescription,
-                    bit skipExtraClassDeclaration> {
-  bit required = isRequired;
-
+// `{opt,req}assemblyFormat`, `description` and `extraClassDeclaration` fields
+// from any given `OpenMP_Clause` by setting to 1 the corresponding "skip"
+// template argument bit.
+class OpenMP_Clause<bit skipTraits, bit skipArguments, bit skipAssemblyFormat,
+                    bit skipDescription, bit skipExtraClassDeclaration> {
   bit ignoreTraits = skipTraits;
   list<Trait> traits = [];
 
@@ -78,7 +72,8 @@ class OpenMP_Clause<bit isRequired, bit skipTraits, bit skipArguments,
   dag arguments;
 
   bit ignoreAsmFormat = skipAssemblyFormat;
-  string assemblyFormat = "";
+  string reqAssemblyFormat = "";
+  string optAssemblyFormat = "";
 
   bit ignoreDesc = skipDescription;
   string description = "";
@@ -98,15 +93,16 @@ class OpenMP_Clause<bit isRequired, bit skipTraits, bit skipArguments,
 //     are saved to a `clausesArgs` field to allow overriding the arguments
 //     field in the definition of the operation and still being able to include
 //     those inherited from clauses.
-//   - `assemblyFormat`: It is a concatenation of the `assemblyFormat` of
-//     all required clauses followed by an `oilist()` containing the
-//     `assemblyFormat` of all optional clauses. The format string is completed
-//     with $region (if `singleRegion = true`) followed by attr-dict. This field
-//     remains uninitialized if no non-empty `assemblyFormat` strings are
-//     inherited from clauses. The `clausesAssemblyFormat` field holds
-//     all the format except for "$region attr-dict", so that an operation
-//     overriding `assemblyFormat` can still benefit from the auto-generated
-//     format for its clauses.
+//   - `assemblyFormat`: It is a concatenation of the `reqAssemblyFormat`
+//     followed by an `oilist()` containing the `optAssemblyFormat` of all
+//     clauses. The format string is completed with $region (if `singleRegion =
+//     true`) followed by `attr-dict`. This field remains uninitialized if no
+//     non-empty `{req,opt}AssemblyFormat` strings are inherited from clauses.
+//     The `clausesAssemblyFormat` field holds all the format string except for
+//     "$region attr-dict", and the `clauses{Req,Opt}AssemblyFormat` fields
+//     hold the required and optional parts of the format string separately, so
+//     that an operation overriding `assemblyFormat` can still benefit from the
+//     auto-generated format for its clauses.
 //   - `description`: This is still required to be defined by the operation.
 //     However, a `clausesDescription` field is provided containing a
 //     concatenation of descriptions of all clauses, to be appended to the
@@ -153,31 +149,29 @@ class OpenMP_Op<string mnemonic, list<Trait> traits = [],
   // characters.
 
   // Required clauses.
-  defvar reqClauses = !filter(clause, clauses, clause.required);
   defvar asmFormatFilteredReqClauses =
-    !filter(clause, reqClauses, !not(!or(clause.ignoreAsmFormat,
-                                     !empty(clause.assemblyFormat))));
+    !filter(clause, clauses, !not(!or(clause.ignoreAsmFormat,
+                                     !empty(clause.reqAssemblyFormat))));
 
   defvar asmFormatReqClauseStrings =
-    !foreach(clause, asmFormatFilteredReqClauses, clause.assemblyFormat);
+    !foreach(clause, asmFormatFilteredReqClauses, clause.reqAssemblyFormat);
 
-  defvar asmFormatReqClauseBody = !interleave(asmFormatReqClauseStrings, " ");
+  string clausesReqAssemblyFormat = !interleave(asmFormatReqClauseStrings, " ");
 
   // Optional clauses.
-  defvar optClauses = !filter(clause, clauses, !not(clause.required));
   defvar asmFormatFilteredOptClauses =
-    !filter(clause, optClauses, !not(!or(clause.ignoreAsmFormat,
-                                     !empty(clause.assemblyFormat))));
+    !filter(clause, clauses, !not(!or(clause.ignoreAsmFormat,
+                                     !empty(clause.optAssemblyFormat))));
 
   defvar asmFormatOptClauseStrings =
-    !foreach(clause, asmFormatFilteredOptClauses, clause.assemblyFormat);
+    !foreach(clause, asmFormatFilteredOptClauses, clause.optAssemblyFormat);
 
-  defvar asmFormatOptClauseBody = !interleave(asmFormatOptClauseStrings, "|");
+  string clausesOptAssemblyFormat = !interleave(asmFormatOptClauseStrings, "|");
 
   string clausesAssemblyFormat =
-    !if(!empty(asmFormatReqClauseStrings), "", asmFormatReqClauseBody # " ") #
+    !if(!empty(asmFormatReqClauseStrings), "", clausesReqAssemblyFormat # " ") #
     !if(!empty(asmFormatOptClauseStrings), "",
-        "oilist(" # asmFormatOptClauseBody # ")");
+        "oilist(" # clausesOptAssemblyFormat # ")");
 
   // Put together descriptions of all clauses into a single string.
   defvar descFilteredClauses =
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 1aa4e771cd4dea..9d2123a2e9bf52 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -132,11 +132,8 @@ def ParallelOp : OpenMP_Op<"parallel", traits = [
     DeclareOpInterfaceMethods<OutlineableOpenMPOpInterface>,
     RecursiveMemoryEffects
   ], clauses = [
-    OpenMP_AllocateClauseSkip<assemblyFormat = true>,
-    OpenMP_IfClauseSkip<assemblyFormat = true>,
-    OpenMP_NumThreadsClauseSkip<assemblyFormat = true>,
-    OpenMP_PrivateClauseSkip<assemblyFormat = true>,
-    OpenMP_ProcBindClauseSkip<assemblyFormat = true>,
+    OpenMP_AllocateClause, OpenMP_IfClause, OpenMP_NumThreadsClause,
+    OpenMP_PrivateClauseSkip<assemblyFormat = true>, OpenMP_ProcBindClause,
     OpenMP_ReductionClauseSkip<assemblyFormat = true>
   ], singleRegion = true> {
   let summary = "parallel construct";
@@ -158,20 +155,12 @@ def ParallelOp : OpenMP_Op<"parallel", traits = [
   // and parsing of the parallel region is not intermingled with printing and
   // parsing of reduction and private clauses. `assemblyFormat` should also be
   // no longer skipped for clauses added to this operation at that time.
-  let assemblyFormat = [{
-    oilist(
-          `if` `(` $if_expr `)`
-          | `num_threads` `(` $num_threads `:` type($num_threads) `)`
-          | `allocate` `(`
-              custom<AllocateAndAllocator>(
-                $allocate_vars, type($allocate_vars),
-                $allocator_vars, type($allocator_vars)
-              ) `)`
-          | `proc_bind` `(` custom<ClauseAttr>($proc_bind_kind) `)`
-    ) custom<ParallelRegion>($region, $reduction_vars, type($reduction_vars),
-                             $reduction_byref, $reduction_syms, $private_vars,
-                             type($private_vars), $private_syms) attr-dict
-  }];
+  let assemblyFormat =
+    clausesReqAssemblyFormat # " oilist(" # clausesOptAssemblyFormat # ")" # [{
+      custom<ParallelRegion>($region, $reduction_vars, type($reduction_vars),
+                            $reduction_byref, $reduction_syms, $private_vars,
+                            type($private_vars), $private_syms) attr-dict
+    }];
 
   let hasVerifier = 1;
 }
@@ -361,14 +350,9 @@ def WsloopOp : OpenMP_Op<"wsloop", traits = [
     DeclareOpInterfaceMethods<LoopWrapperInterface>,
     RecursiveMemoryEffects, SingleBlock
   ], clauses = [
-    OpenMP_AllocateClauseSkip<assemblyFormat = true>,
-    OpenMP_LinearClauseSkip<assemblyFormat = true>,
-    OpenMP_NowaitClauseSkip<assemblyFormat = true>,
-    OpenMP_OrderClauseSkip<assemblyFormat = true>,
-    OpenMP_OrderedClauseSkip<assemblyFormat = true>,
-    OpenMP_PrivateClauseSkip<assemblyFormat = true>,
-    OpenMP_ReductionClauseSkip<assemblyFormat = true>,
-    OpenMP_ScheduleClauseSkip<assemblyFormat = true>
+    OpenMP_AllocateClause, OpenMP_LinearClause, OpenMP_NowaitClause,
+    OpenMP_OrderClause, OpenMP_OrderedClause, OpenMP_PrivateClause,
+    OpenMP_ReductionClauseSkip<assemblyFormat = true>, OpenMP_ScheduleClause
   ], singleRegion = true> {
   let summary = "worksharing-loop construct";
   let description = [{
@@ -404,27 +388,11 @@ def WsloopOp : OpenMP_Op<"wsloop", traits = [
   // and parsing of the workshare loop region is not intermingled with printing
   // and parsing of reduction clauses. `assemblyFormat` should also be no longer
   // skipped for clauses added to this operation at that time.
-  let assemblyFormat = [{
-    oilist(`linear` `(`
-              custom<LinearClause>($linear_vars, type($linear_vars),
-                                   $linear_step_vars) `)`
-          |`schedule` `(`
-              custom<ScheduleClause>(
-                $schedule_kind, $schedule_mod, $schedule_simd,
-                $schedule_chunk, type($schedule_chunk)) `)`
-          |`nowait` $nowait
-          |`ordered` `(` $ordered `)`
-          |`order` `(` custom<OrderClause>($order, $order_mod) `)`
-          |`allocate` `(`
-                custom<AllocateAndAllocator>(
-                  $allocate_vars, type($allocate_vars), $allocator_vars,
-                  type($allocator_vars)) `)`
-          |`private` `(`
-                custom<PrivateList>(
-                  $private_vars, type($private_vars), $private_syms) `)`
-    ) custom<Wsloop>($region, $reduction_vars, type($reduction_vars),
-                     $reduction_byref, $reduction_syms) attr-dict
-  }];
+  let assemblyFormat =
+    clausesReqAssemblyFormat # " oilist(" # clausesOptAssemblyFormat # ")" # [{
+      custom<Wsloop>($region, $reduction_vars, type($reduction_vars),
+                    $reduction_byref, $reduction_syms) attr-dict
+    }];
 
   let hasVerifier = 1;
 }
@@ -1249,12 +1217,8 @@ def AtomicReadOp : OpenMP_Op<"atomic.read", traits = [
                             TypeAttr:$element_type), clausesArgs);
 
   // Override clause-based assemblyFormat.
-  let assemblyFormat = [{
-    $v `=` $x
-    oilist( `memory_order` `(` custom<ClauseAttr>($memory_order) `)`
-          | `hint` `(` custom<SynchronizationHint>($hint) `)`)
-    `:` type($x) `,` $element_type attr-dict
-  }];
+  let assemblyFormat = "$v `=` $x" # clausesReqAssemblyFormat # " oilist(" #
+    clausesOptAssemblyFormat # ") `:` type($x) `,` $element_type attr-dict";
 
   let extraClassDeclaration = [{
     /// The number of variable operands.
@@ -1293,13 +1257,8 @@ def AtomicWriteOp : OpenMP_Op<"atomic.write", traits = [
                             AnyType:$expr), clausesArgs);
 
   // Override clause-based assemblyFormat.
-  let assemblyFormat = [{
-    $x `=` $expr
-    oilist( `hint` `(` custom<SynchronizationHint>($hint) `)`
-          | `memory_order` `(` custom<ClauseAttr>($memory_order) `)`)
-    `:` type($x) `,` type($expr)
-    attr-dict
-  }];
+  let assemblyFormat = "$x `=` $expr" # clausesReqAssemblyFormat # " oilist(" #
+    clausesOptAssemblyFormat # ") `:` type($x) `,` type($expr) attr-dict";
 
   let extraClassDeclaration = [{
     /// The number of variable operands.
@@ -1357,11 +1316,8 @@ def AtomicUpdateOp : OpenMP_Op<"atomic.update", traits = [
   let regions = (region SizedRegion<1>:$region);
 
   // Override clause-based assemblyFormat.
-  let assemblyFormat = [{
-    oilist( `memory_order` `(` custom<ClauseAttr>($memory_order) `)`
-          | `hint` `(` custom<SynchronizationHint>($hint) `)`)
-    $x `:` type($x) $region attr-dict
-  }];
+  let assemblyFormat = clausesAssemblyFormat #
+    "$x `:` type($x) $region attr-dict";
 
   let extraClassDeclaration = [{
     /// The number of variable operands.
diff --git a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
index 5afdbaa2a56af3..97e5b578017ead 100644
--- a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
+++ b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
@@ -118,7 +118,7 @@ func.func @atomic_write(%a: !llvm.ptr) -> () {
 
 // CHECK-LABEL: @atomic_read
 // CHECK: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr)
-// CHECK: omp.atomic.read %[[ARG1]] = %[[ARG0]] memory_order(acquire) hint(contended) : !llvm.ptr
+// CHECK: omp.atomic.read %[[ARG1]] = %[[ARG0]] hint(contended) memory_order(acquire) : !llvm.ptr
 func.func @atomic_read(%a: !llvm.ptr, %b: !llvm.ptr) -> () {
   omp.atomic.read %b = %a memory_order(acquire) hint(contended) : !llvm.ptr, i32
   return
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index dce5b3950def49..e7d3e67ca7e05b 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -66,11 +66,11 @@ func.func @omp_terminator() -> () {
 }
 
 func.func @omp_parallel(%data_var : memref<i32>, %if_cond : i1, %num_threads : i32, %idx : index) -> () {
-  // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32) allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
+  // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) if(%{{.*}}) num_threads(%{{.*}} : i32)
   "omp.parallel" (%data_var, %data_var, %if_cond, %num_threads) ({
 
   // test without if condition
-  // CHECK: omp.parallel num_threads(%{{.*}} : i32) allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
+  // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) num_threads(%{{.*}} : i32)
     "omp.parallel"(%data_var, %data_var, %num_threads) ({
       omp.terminator
     }) {operandSegmentSizes = array<i32: 1,1,0,1,0,0>} : (memref<i32>, memref<i32>, i32) -> ()
@@ -79,7 +79,7 @@ func.func @omp_parallel(%data_var : memref<i32>, %if_cond : i1, %num_threads : i
     omp.barrier
 
   // test without num_threads
-  // CHECK: omp.parallel if(%{{.*}}) allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
+  // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) if(%{{.*}})
     "omp.parallel"(%data_var, %data_var, %if_cond) ({
       omp.terminator
     }) {operandSegmentSizes = array<i32: 1,1,1,0,0,0>} : (memref<i32>, memref<i32>, i1) -> ()
@@ -428,7 +428,7 @@ func.func @omp_wsloop(%lb : index, %ub : index, %step : index, %data_var : memre
   }) {operandSegmentSizes = array<i32: 0,0,2,2,0,0,0>, schedule_kind = #omp<schedulekind static>} :
     (memref<i32>, memref<i32>, i32, i32) -> ()
 
-  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(dynamic = %{{.*}}) ordered(2) {
+  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(dynamic = %{{.*}}) {
   // CHECK-NEXT: omp.loop_nest
   "omp.wsloop" (%data_var, %linear_var, %chunk_var) ({
     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
@@ -438,7 +438,7 @@ func.func @omp_wsloop(%lb : index, %ub : index, %step : index, %data_var : memre
   }) {operandSegmentSizes = array<i32: 0,0,1,1,0,0,1>, schedule_kind = #omp<schedulekind dynamic>, ordered = 2} :
     (memref<i32>, i32, i32) -> ()
 
-  // CHECK: omp.wsloop schedule(auto) nowait {
+  // CHECK: omp.wsloop nowait schedule(auto) {
   // CHECK-NEXT: omp.loop_nest
   "omp.wsloop" () ({
     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
@@ -485,7 +485,7 @@ func.func @omp_wsloop_pretty(%lb : index, %ub : index, %step : index, %data_var
     omp.terminator
   }
 
-  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static = %{{.*}} : i32) ordered(2) {
+  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(static = %{{.*}} : i32) {
   // CHECK-NEXT: omp.loop_nest
   omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(static = %chunk_var : i32) {
     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
@@ -494,7 +494,7 @@ func.func @omp_wsloop_pretty(%lb : index, %ub : index, %step : index, %data_var
     omp.terminator
   }
 
-  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(dynamic = %{{.*}} : i32, nonmonotonic) ordered(2) {
+  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(dynamic = %{{.*}} : i32, nonmonotonic) {
   // CHECK-NEXT: omp.loop_nest
   omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(dynamic = %chunk_var : i32, nonmonotonic) {
     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step)  {
@@ -503,7 +503,7 @@ func.func @omp_wsloop_pretty(%lb : index, %ub : index, %step : index, %data_var
     omp.terminator
   }
 
-  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(dynamic = %{{.*}} : i16, monotonic) ordered(2) {
+  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(dynamic = %{{.*}} : i16, monotonic) {
   // CHECK-NEXT: omp.loop_nest
   omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(dynamic = %chunk_var2 : i16, monotonic) {
     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
@@ -1358,7 +1358,7 @@ func.func @omp_atomic_read(%v: memref<i32>, %x: memref<i32>) {
   omp.atomic.read %v = %x memory_order(relaxed) : memref<i32>, i32
   // CHECK: omp.atomic.read %[[v]] = %[[x]] hint(contended, nonspeculative) : memref<i32>, i32
   omp.atomic.read %v = %x hint(nonspeculative, contended) : memref<i32>, i32
-  // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) hint(contended, speculative) : memref<i32>, i32
+  // CHECK: omp.atomic.read %[[v]] = %[[x]] hint(contended, speculative) memory_order(seq_cst) : memref<i32>, i32
   omp.atomic.read %v = %x hint(speculative, contended) memory_order(seq_cst) : memref<i32>, i32
   // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) : memref<i32>, i32
   omp.atomic.read %v = %x hint(none) memory_order(seq_cst) : memref<i32>, i32
@@ -1575,7 +1575,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : i32, %xBool : memref<i1>,
     omp.yield(%newval : i32)
   }
 
-  // CHECK: omp.atomic.update memory_order(seq_cst) hint(uncontended, speculative) %[[X]] : memref<i32>
+  // CHECK: omp.atomic.update hint(uncontended, speculative) memory_order(seq_cst) %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
diff --git a/mlir/test/mlir-tblgen/openmp-ops-verify.td b/mlir/test/mlir-tblgen/openmp-ops-verify.td
index 7fc962b4eaa4d9..dc8bc4bdbe2e78 100644
--- a/mlir/test/mlir-tblgen/openmp-ops-verify.td
+++ b/mlir/test/mlir-tblgen/openmp-ops-verify.td
@@ -13,11 +13,10 @@ include "mlir/Dialect/OpenMP/OpenMPOpBase.td"
 
 
 def OpenMP_SimpleClause : OpenMP_Clause<
-    /*isRequired=*/true, /*traits=*/false, /*arguments=*/false,
-    /*assemblyFormat=*/false, /*description=*/false,
-    /*extraClassDeclaration=*/false> {
+    /*traits=*/false, /*arguments=*/false, /*assemblyFormat=*/false,
+    /*description=*/false, /*extraClassDeclaration=*/false> {
   let arguments = (ins I32:$val1);
-  let assemblyFormat = "`val1` `(` $val1 `)`";
+  let reqAssemblyFormat = "`val1` `(` $val1 `)`";
   let description = "Simple clause description.";
   let extraClassDeclaration = "void simpleClauseExtraClassDecl();";
 }
@@ -39,8 +38,8 @@ def 2OverrideAssemblyFormatOp : OpenMP_Op<"op", clauses=[OpenMP_SimpleClause]> {
   let description = "Description of operation." # clausesDescription;
   string assemblyFormat = "`alt_repr` `(` $val1 `)`";
 }
-// CHECK: warning: 'Simple' clause-defined `assemblyFormat` not present in operation.
-// CHECK-SAME: Consider concatenating `clausesAssemblyFormat` or explicitly skipping this field.
+// CHECK: warning: 'Simple' clause-defined `reqAssemblyFormat` not present in operation.
+// CHECK-SAME: Consider concatenating `clauses[{Req,Opt}]AssemblyFormat` or explicitly skipping this field.
 // CHECK-NEXT: def 2OverrideAssemblyFormatOp
 
 def 3OverrideDescriptionOp : OpenMP_Op<"op", clauses=[OpenMP_SimpleClause]> {
@@ -66,10 +65,10 @@ def 4OverrideExtraClassDeclarationOp : OpenMP_Op<"op", clauses=[OpenMP_SimpleCla
 class OpenMP_IndirectClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/true, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let arguments = (ins I32:$val2);
-  let assemblyFormat = "`val2` `(` $val2 `)`";
+  let reqAssemblyFormat = "`val2` `(` $val2 `)`";
   let description = "Indirectly-inherited clause description.";
   let extraClassDeclaration = "void indirectClauseExtraClassDecl();";
 }
@@ -93,7 +92,7 @@ def 6MultiClauseOp : OpenMP_Op<"op", clauses=[OpenMP_SimpleClause, IndirectClaus
   let arguments = (ins I32:$val1);
   let assemblyFormat = "`val2` `(` $val2 `)`";
 }
-// CHECK: warning: 'Simple' clause-defined `assemblyFormat` not present in operation.
+// CHECK: warning: 'Simple' clause-defined `reqAssemblyFormat` not present in operation.
 // CHECK-NEXT: def 6MultiClauseOp
 // CHECK: warning: 'Indirect' clause-defined argument 'I32:$val2' not present in operation.
 // CHECK-NEXT: def 6MultiClauseOp
diff --git a/mlir/test/mlir-tblgen/openmp-ops.td b/mlir/test/mlir-tblgen/openmp-ops.td
index 83f267cb4ed088..5da8957b51f444 100644
--- a/mlir/test/mlir-tblgen/openmp-ops.td
+++ b/mlir/test/mlir-tblgen/openmp-ops.td
@@ -25,8 +25,8 @@ def TraitThree : NativeOpTrait<"TraitThree">;
 class OptClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let traits = [
     TraitOne
   ];
@@ -35,7 +35,7 @@ class OptClauseSkip<
     Optional<AnyInteger>:$opt_simple_val
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `optsimple` `(` $opt_simple_val `:` type($opt_simple_val) `)`
   }];
 
@@ -51,9 +51,8 @@ class OptClauseSkip<
 def OptClause : OptClauseSkip<>;
 
 def OptClauseTwo : OpenMP_Clause<
-    /*isRequired=*/false, /*skipTraits=*/false, /*skipArguments=*/false,
-    /*skipAssemblyFormat=*/false, /*skipDescription=*/false,
-    /*skipExtraClassDeclaration=*/false> {
+    /*skipTraits=*/false, /*skipArguments=*/false, /*skipAssemblyFormat=*/false,
+    /*skipDescription=*/false, /*skipExtraClassDeclaration=*/false> {
   let traits = [
     TraitOne, TraitTwo
   ];
@@ -62,7 +61,7 @@ def OptClauseTwo : OpenMP_Clause<
     Optional<AnyInteger>:$opt_two_val
   );
 
-  let assemblyFormat = [{
+  let optAssemblyFormat = [{
     `opt_two` `(` $opt_two_val `:` type($opt_two_val) `)`
   }];
 
@@ -78,8 +77,8 @@ def OptClauseTwo : OpenMP_Clause<
 class ReqClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
-  > : OpenMP_Clause</*isRequired=*/true, traits, arguments, assemblyFormat,
-                    description, extraClassDeclaration> {
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
   let traits = [
     TraitTwo
   ];
@@ -88,7 +87,7 @@ class ReqClauseSkip<
     AnyInteger:$req_simple_val
   );
 
-  let assemblyFormat = [{
+  let reqAssemblyFormat = [{
     `reqsimple` `(` $req_simple_val `:` type($req_simple_val) `)`
   }];
 
@@ -104,9 +103,8 @@ class ReqClauseSkip<
 def ReqClause : ReqClauseSkip<>;
 
 def ReqClauseTwo : OpenMP_Clause<
-    /*isRequired=*/true, /*skipTraits=*/false, /*skipArguments=*/false,
-    /*skipAssemblyFormat=*/false, /*skipDescription=*/false,
-    /*skipExtraClassDeclaration=*/false> {
+    /*skipTraits=*/false, /*skipArguments=*/false, /*skipAssemblyFormat=*/false,
+    /*skipDescription=*/false, /*skipExtraClassDeclaration=*/false> {
   let traits = [
     TraitTwo, TraitThree
   ];
@@ -115,7 +113,7 @@ def ReqClauseTwo : OpenMP_Clause<
     AnyInteger:$req_two_val
   );
 
-  let assemblyFormat = [{
+  let reqAssemblyFormat = [{
     `req_two` `(` $req_two_val `:` type($req_two_val) `)`
   }];
 
@@ -130,6 +128,41 @@ def ReqClauseTwo : OpenMP_Clause<
 
 // Clause-based operation definitions.
 
+def OpAddArguments : OpenMP_Op<"op_add_arguments",
+    traits=[AttrSizedOperandSegments], clauses=[ReqClause, OptClause]> {
+  let summary = "operation with clauses - arguments added";
+  let description = [{
+    Description of operation with clauses - arguments added.
+  }] # clausesDescription;
+  let arguments = !con(clausesArgs, (ins Optional<AnyInteger>:$opt_added,
+                                         AnyInteger:$req_added));
+  let assemblyFormat = clausesReqAssemblyFormat #
+    "`req_added` `(` $req_added `:` type($req_added) `)` oilist(" #
+    clausesOptAssemblyFormat #
+    "|`opt_added` `(` $opt_added `:` type($opt_added) `)`) attr-dict";
+}
+
+// DECL-LABEL: class OpAddArguments : public ::mlir::Op<
+// DECL: getReqSimpleVal() {
+// DECL: getOptSimpleVal() {
+// DECL: void reqClauseExtraClassDecl();
+// DECL: void optClauseExtraClassDecl();
+
+// DOC-LABEL: omp::OpAddArguments
+// DOC: _Operation with clauses - arguments added_
+// DOC: operation ::= `omp.op_add_arguments`
+// DOC: `reqsimple` `(` $req_simple_val `:` type($req_simple_val) `)`
+// DOC: `req_added` `(` $req_added `:` type($req_added) `)`
+// DOC: oilist(
+// DOC: `optsimple` `(` $opt_simple_val `:` type($opt_simple_val) `)`
+// DOC: |`opt_added` `(` $opt_added `:` type($opt_added) `)`
+// DOC-NOT: $region
+// DOC: attr-dict
+// DOC: Description of operation with clauses - arguments added.
+// DOC: Required clause description.
+// DOC: Optional clause description.
+// DOC: Traits: `AttrSizedOperandSegments`, `TraitOne`, `TraitTwo`
+
 def OpOptClause : OpenMP_Op<"op_with_opt",
     traits=[TraitThree], clauses=[OptClause]> {
   let summary = "operation with optional clause";
diff --git a/mlir/tools/mlir-tblgen/OmpOpGen.cpp b/mlir/tools/mlir-tblgen/OmpOpGen.cpp
index 15458212637888..7642db3862a803 100644
--- a/mlir/tools/mlir-tblgen/OmpOpGen.cpp
+++ b/mlir/tools/mlir-tblgen/OmpOpGen.cpp
@@ -80,13 +80,17 @@ static bool verifyArgument(DagInit *arguments, StringRef argName,
       });
 }
 
-/// Check that the given string record value, identified by its name \c value,
+/// Check that the given string record value, identified by its \c opValueName,
 /// is either undefined or empty in both the given operation and clause record
 /// or its contents for the clause record are contained in the operation record.
-static bool verifyStringValue(StringRef value, const Record *op,
-                              const Record *clause) {
-  auto opValue = op->getValueAsOptionalString(value);
-  auto clauseValue = clause->getValueAsOptionalString(value);
+/// Passing a non-empty \c clauseValueName enables checking values named
+/// differently in the operation and clause records.
+static bool verifyStringValue(const Record *op, const Record *clause,
+                              StringRef opValueName,
+                              StringRef clauseValueName = {}) {
+  auto opValue = op->getValueAsOptionalString(opValueName);
+  auto clauseValue = clause->getValueAsOptionalString(
+      clauseValueName.empty() ? opValueName : clauseValueName);
 
   bool opHasValue = opValue && !opValue->trim().empty();
   bool clauseHasValue = clauseValue && !clauseValue->trim().empty();
@@ -122,16 +126,25 @@ static void verifyClause(const Record *op, const Record *clause) {
   }
 
   if (!clause->getValueAsBit("ignoreAsmFormat") &&
-      !verifyStringValue("assemblyFormat", op, clause))
+      !verifyStringValue(op, clause, "assemblyFormat", "reqAssemblyFormat"))
     PrintWarning(
         op->getLoc(),
         "'" + clauseClassName +
-            "' clause-defined `assemblyFormat` not present in operation. "
-            "Consider concatenating `clausesAssemblyFormat` or explicitly "
-            "skipping this field.");
+            "' clause-defined `reqAssemblyFormat` not present in operation. "
+            "Consider concatenating `clauses[{Req,Opt}]AssemblyFormat` or "
+            "explicitly skipping this field.");
+
+  if (!clause->getValueAsBit("ignoreAsmFormat") &&
+      !verifyStringValue(op, clause, "assemblyFormat", "optAssemblyFormat"))
+    PrintWarning(
+        op->getLoc(),
+        "'" + clauseClassName +
+            "' clause-defined `optAssemblyFormat` not present in operation. "
+            "Consider concatenating `clauses[{Req,Opt}]AssemblyFormat` or "
+            "explicitly skipping this field.");
 
   if (!clause->getValueAsBit("ignoreDesc") &&
-      !verifyStringValue("description", op, clause))
+      !verifyStringValue(op, clause, "description"))
     PrintError(op->getLoc(),
                "'" + clauseClassName +
                    "' clause-defined `description` not present in operation. "
@@ -139,7 +152,7 @@ static void verifyClause(const Record *op, const Record *clause) {
                    "skipping this field.");
 
   if (!clause->getValueAsBit("ignoreExtraDecl") &&
-      !verifyStringValue("extraClassDeclaration", op, clause))
+      !verifyStringValue(op, clause, "extraClassDeclaration"))
     PrintWarning(
         op->getLoc(),
         "'" + clauseClassName +



More information about the flang-commits mailing list