mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 02:26:07 +00:00

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.
143 lines
6.3 KiB
TableGen
143 lines
6.3 KiB
TableGen
// Tablegen tests for the verification of clause-based OpenMP dialect operation
|
|
// definitions.
|
|
|
|
// Run tablegen to generate OmpCommon.td in temp directory first.
|
|
// RUN: mkdir -p %t/mlir/Dialect/OpenMP
|
|
// RUN: mlir-tblgen --gen-directive-decl --directives-dialect=OpenMP \
|
|
// RUN: %S/../../../llvm/include/llvm/Frontend/OpenMP/OMP.td \
|
|
// RUN: -I %S/../../../llvm/include > %t/mlir/Dialect/OpenMP/OmpCommon.td
|
|
|
|
// RUN: not mlir-tblgen -verify-openmp-ops -I %S/../../include -I %t %s 2>&1 | FileCheck %s
|
|
|
|
include "mlir/Dialect/OpenMP/OpenMPOpBase.td"
|
|
|
|
|
|
def OpenMP_SimpleClause : OpenMP_Clause<
|
|
/*traits=*/false, /*arguments=*/false, /*assemblyFormat=*/false,
|
|
/*description=*/false, /*extraClassDeclaration=*/false> {
|
|
let arguments = (ins I32:$val1);
|
|
let reqAssemblyFormat = "`val1` `(` $val1 `)`";
|
|
let description = "Simple clause description.";
|
|
let extraClassDeclaration = "void simpleClauseExtraClassDecl();";
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Verify errors / warnings for overriding each field.
|
|
// -----------------------------------------------------------------------------
|
|
|
|
def 1OverrideArgsOp : OpenMP_Op<"op", clauses=[OpenMP_SimpleClause]> {
|
|
let description = "Description of operation." # clausesDescription;
|
|
dag arguments = (ins I32:$myval);
|
|
}
|
|
// CHECK: warning: 'Simple' clause-defined argument 'I32:$val1' not present in operation.
|
|
// CHECK-SAME: Consider `dag arguments = !con(clausesArgs, ...)` or explicitly skipping this field.
|
|
// CHECK-NEXT: def 1OverrideArgsOp
|
|
|
|
def 2OverrideAssemblyFormatOp : OpenMP_Op<"op", clauses=[OpenMP_SimpleClause]> {
|
|
let description = "Description of operation." # clausesDescription;
|
|
string assemblyFormat = "`alt_repr` `(` $val1 `)`";
|
|
}
|
|
// 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]> {
|
|
let description = "Description of operation.";
|
|
}
|
|
// CHECK: error: 'Simple' clause-defined `description` not present in operation.
|
|
// CHECK-SAME: Consider concatenating `clausesDescription` or explicitly skipping this field.
|
|
// CHECK-NEXT: def 3OverrideDescriptionOp
|
|
|
|
def 4OverrideExtraClassDeclarationOp : OpenMP_Op<"op", clauses=[OpenMP_SimpleClause]> {
|
|
let description = "Description of operation." # clausesDescription;
|
|
string extraClassDeclaration = "";
|
|
}
|
|
// CHECK: warning: 'Simple' clause-defined `extraClassDeclaration` not present in operation.
|
|
// CHECK-SAME: Consider concatenating `clausesExtraClassDeclaration` or explicitly skipping this field.
|
|
// CHECK-NEXT: def 4OverrideExtraClassDeclarationOp
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Verify that reporting is correct when OpenMP_Clause is inherited indirectly.
|
|
// -----------------------------------------------------------------------------
|
|
|
|
class OpenMP_IndirectClauseSkip<
|
|
bit traits = false, bit arguments = false, bit assemblyFormat = false,
|
|
bit description = false, bit extraClassDeclaration = false
|
|
> : OpenMP_Clause<traits, arguments, assemblyFormat, description,
|
|
extraClassDeclaration> {
|
|
let arguments = (ins I32:$val2);
|
|
let reqAssemblyFormat = "`val2` `(` $val2 `)`";
|
|
let description = "Indirectly-inherited clause description.";
|
|
let extraClassDeclaration = "void indirectClauseExtraClassDecl();";
|
|
}
|
|
|
|
def IndirectClause : OpenMP_IndirectClauseSkip<>;
|
|
|
|
def 5IndirectClauseOp : OpenMP_Op<"op", clauses=[IndirectClause]> {
|
|
let description = "Description of operation." # clausesDescription;
|
|
dag arguments = (ins I32:$myval);
|
|
}
|
|
// CHECK: warning: 'Indirect' clause-defined argument 'I32:$val2' not present in operation.
|
|
// CHECK-NEXT: def 5IndirectClauseOp
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Verify that multiple clauses are taken into account.
|
|
// -----------------------------------------------------------------------------
|
|
|
|
def 6MultiClauseOp : OpenMP_Op<"op", clauses=[OpenMP_SimpleClause, IndirectClause]> {
|
|
let description = "Description of operation." # clausesDescription;
|
|
let arguments = (ins I32:$val1);
|
|
let assemblyFormat = "`val2` `(` $val2 `)`";
|
|
}
|
|
// 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
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Verify that reporting is correct when clause definitions have other
|
|
// superclasses in addition to OpenMP_Clause.
|
|
// -----------------------------------------------------------------------------
|
|
|
|
class Placeholder {}
|
|
def MultiSuperClassClause : Placeholder, OpenMP_IndirectClauseSkip<>;
|
|
|
|
def 7MultiSuperClassClauseOp : OpenMP_Op<"op", clauses=[IndirectClause]> {
|
|
let description = "Description of operation." # clausesDescription;
|
|
dag arguments = (ins I32:$myval);
|
|
}
|
|
// CHECK: warning: 'Indirect' clause-defined argument 'I32:$val2' not present in operation.
|
|
// CHECK-NEXT: def 7MultiSuperClassClauseOp
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Verify that no errors are produced if the field being overriden is also
|
|
// skipped for the clause.
|
|
// -----------------------------------------------------------------------------
|
|
|
|
def SkipArgsOp : OpenMP_Op<"op",
|
|
clauses=[OpenMP_IndirectClauseSkip<arguments=true>]> {
|
|
let description = "Description of operation." # clausesDescription;
|
|
dag arguments = (ins I32:$myval);
|
|
}
|
|
def SkipAssemblyFormatOp : OpenMP_Op<"op",
|
|
clauses=[OpenMP_IndirectClauseSkip<assemblyFormat=true>]> {
|
|
let description = "Description of operation." # clausesDescription;
|
|
string assemblyFormat = "`alt_repr` `(` $val1 `)`";
|
|
}
|
|
def SkipDescriptionOp : OpenMP_Op<"op",
|
|
clauses=[OpenMP_IndirectClauseSkip<description=true>]> {
|
|
let description = "Description of operation.";
|
|
}
|
|
def SkipExtraClassDeclarationOp : OpenMP_Op<"op",
|
|
clauses=[OpenMP_IndirectClauseSkip<extraClassDeclaration=true>]> {
|
|
let description = "Description of operation." # clausesDescription;
|
|
string extraClassDeclaration = "";
|
|
}
|
|
// CHECK-NOT: error:
|
|
// CHECK-NOT: warning:
|