[Mlir-commits] [mlir] 7a79c6a - [mlir][OpenMP] OpenMP Synchronization Hints stored as IntegerAttr

Kiran Chandramohan llvmlistbot at llvm.org
Tue Oct 12 04:01:41 PDT 2021


Author: Shraiysh Vaishay
Date: 2021-10-12T11:01:19Z
New Revision: 7a79c6afea93d1237bea2317bea624947ce8a4a5

URL: https://github.com/llvm/llvm-project/commit/7a79c6afea93d1237bea2317bea624947ce8a4a5
DIFF: https://github.com/llvm/llvm-project/commit/7a79c6afea93d1237bea2317bea624947ce8a4a5.diff

LOG: [mlir][OpenMP] OpenMP Synchronization Hints stored as IntegerAttr

`hint-expression` is an IntegerAttr, because it can be a combination of multiple values from the enum `omp_sync_hint_t` (Section 2.17.12 of OpenMP 5.0)

Reviewed By: ftynse, kiranchandramohan

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

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
    mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
    mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
    mlir/test/Dialect/OpenMP/invalid.mlir
    mlir/test/Dialect/OpenMP/ops.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 73ee9df406c9a..ac6243ab57c7f 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -369,21 +369,6 @@ def CriticalDeclareOp : OpenMP_Op<"critical.declare", [Symbol]> {
 }
 
 
-// TODO: Autogenerate this from OMP.td in llvm/include/Frontend
-def omp_sync_hint_none: I32EnumAttrCase<"none", 0>;
-def omp_sync_hint_uncontended: I32EnumAttrCase<"uncontended", 1>;
-def omp_sync_hint_contended: I32EnumAttrCase<"contended", 2>;
-def omp_sync_hint_nonspeculative: I32EnumAttrCase<"nonspeculative", 3>;
-def omp_sync_hint_speculative: I32EnumAttrCase<"speculative", 4>;
-
-def SyncHintKind: I32EnumAttr<"SyncHintKind", "OpenMP Sync Hint Kind",
-    [omp_sync_hint_none, omp_sync_hint_uncontended, omp_sync_hint_contended,
-     omp_sync_hint_nonspeculative, omp_sync_hint_speculative]> {
-  let cppNamespace = "::mlir::omp";
-  let stringToSymbolFnName = "ConvertToEnum";
-  let symbolToStringFnName = "ConvertToString";
-}
-
 def CriticalOp : OpenMP_Op<"critical"> {
   let summary = "critical construct";
   let description = [{
@@ -392,12 +377,12 @@ def CriticalOp : OpenMP_Op<"critical"> {
   }];
 
   let arguments = (ins OptionalAttr<FlatSymbolRefAttr>:$name,
-                       OptionalAttr<SyncHintKind>:$hint);
+                       DefaultValuedAttr<I64Attr, "0">:$hint);
 
   let regions = (region AnyRegion:$region);
 
   let assemblyFormat = [{
-    (`(` $name^ `)`)? (`hint` `(` $hint^ `)`)? $region attr-dict
+    (`(` $name^ `)`)? custom<SynchronizationHint>($hint) $region attr-dict
   }];
 
   let verifier = "return ::verifyCriticalOp(*this);";

diff  --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 35754f19adb47..32faac397eb16 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -959,11 +959,109 @@ static LogicalResult verifyWsLoopOp(WsLoopOp op) {
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// Parser, printer and verifier for Synchronization Hint (2.17.12)
+//===----------------------------------------------------------------------===//
+
+/// Parses a Synchronization Hint clause. The value of hint is an integer
+/// which is a combination of 
diff erent hints from `omp_sync_hint_t`.
+///
+/// hint-clause = `hint` `(` hint-value `)`
+static ParseResult parseSynchronizationHint(OpAsmParser &parser,
+                                            IntegerAttr &hintAttr) {
+  if (failed(parser.parseOptionalKeyword("hint"))) {
+    hintAttr = IntegerAttr::get(parser.getBuilder().getI64Type(), 0);
+    return success();
+  }
+
+  if (failed(parser.parseLParen()))
+    return failure();
+  StringRef hintKeyword;
+  int64_t hint = 0;
+  do {
+    if (failed(parser.parseKeyword(&hintKeyword)))
+      return failure();
+    if (hintKeyword == "uncontended")
+      hint |= 1;
+    else if (hintKeyword == "contended")
+      hint |= 2;
+    else if (hintKeyword == "nonspeculative")
+      hint |= 4;
+    else if (hintKeyword == "speculative")
+      hint |= 8;
+    else
+      return parser.emitError(parser.getCurrentLocation())
+             << hintKeyword << " is not a valid hint";
+  } while (succeeded(parser.parseOptionalComma()));
+  if (failed(parser.parseRParen()))
+    return failure();
+  hintAttr = IntegerAttr::get(parser.getBuilder().getI64Type(), hint);
+  return success();
+}
+
+/// Prints a Synchronization Hint clause
+static void printSynchronizationHint(OpAsmPrinter &p, Operation *op,
+                                     IntegerAttr hintAttr) {
+  int64_t hint = hintAttr.getInt();
+
+  if (hint == 0)
+    return;
+
+  // Helper function to get n-th bit from the right end of `value`
+  auto bitn = [](int value, int n) -> bool { return value & (1 << n); };
+
+  bool uncontended = bitn(hint, 0);
+  bool contended = bitn(hint, 1);
+  bool nonspeculative = bitn(hint, 2);
+  bool speculative = bitn(hint, 3);
+
+  SmallVector<StringRef> hints;
+  if (uncontended)
+    hints.push_back("uncontended");
+  if (contended)
+    hints.push_back("contended");
+  if (nonspeculative)
+    hints.push_back("nonspeculative");
+  if (speculative)
+    hints.push_back("speculative");
+
+  p << "hint(";
+  llvm::interleaveComma(hints, p);
+  p << ")";
+}
+
+/// Verifies a synchronization hint clause
+static LogicalResult verifySynchronizationHint(Operation *op, int32_t hint) {
+
+  // Helper function to get n-th bit from the right end of `value`
+  auto bitn = [](int value, int n) -> bool { return value & (1 << n); };
+
+  bool uncontended = bitn(hint, 0);
+  bool contended = bitn(hint, 1);
+  bool nonspeculative = bitn(hint, 2);
+  bool speculative = bitn(hint, 3);
+
+  if (uncontended && contended)
+    return op->emitOpError() << "the hints omp_sync_hint_uncontended and "
+                                "omp_sync_hint_contended cannot be combined";
+  if (nonspeculative && speculative)
+    return op->emitOpError() << "the hints omp_sync_hint_nonspeculative and "
+                                "omp_sync_hint_speculative cannot be combined.";
+  return success();
+}
+
+//===----------------------------------------------------------------------===//
+// Verifier for critical construct (2.17.1)
+//===----------------------------------------------------------------------===//
+
 static LogicalResult verifyCriticalOp(CriticalOp op) {
-  if (!op.name().hasValue() && op.hint().hasValue() &&
-      (op.hint().getValue() != SyncHintKind::none))
+
+  if (failed(verifySynchronizationHint(op, op.hint()))) {
+    return failure();
+  }
+  if (!op.name().hasValue() && (op.hint() != 0))
     return op.emitOpError() << "must specify a name unless the effect is as if "
-                               "hint(none) is specified";
+                               "no hint is specified";
 
   if (op.nameAttr()) {
     auto symbolRef = op.nameAttr().cast<SymbolRefAttr>();

diff  --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 3bd02a7efb5bf..f91c02cf9956b 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -300,14 +300,8 @@ convertOmpCritical(Operation &opInst, llvm::IRBuilderBase &builder,
   llvm::OpenMPIRBuilder::LocationDescription ompLoc(
       builder.saveIP(), builder.getCurrentDebugLocation());
   llvm::LLVMContext &llvmContext = moduleTranslation.getLLVMContext();
-  llvm::Constant *hint = nullptr;
-  if (criticalOp.hint().hasValue()) {
-    hint =
-        llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext),
-                               static_cast<int>(criticalOp.hint().getValue()));
-  } else {
-    hint = llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext), 0);
-  }
+  llvm::Constant *hint = llvm::ConstantInt::get(
+      llvm::Type::getInt32Ty(llvmContext), static_cast<int>(criticalOp.hint()));
   builder.restoreIP(moduleTranslation.getOpenMPBuilder()->createCritical(
       ompLoc, bodyGenCB, finiCB, criticalOp.name().getValueOr(""), hint));
   return success();

diff  --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 86f6012dd26bd..20f8d124d0d3b 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -297,7 +297,7 @@ func @foo(%lb : index, %ub : index, %step : index, %mem : memref<1xf32>) {
 // -----
 
 func @omp_critical1() -> () {
-  // expected-error @below {{must specify a name unless the effect is as if hint(none) is specified}}
+  // expected-error @below {{must specify a name unless the effect is as if no hint is specified}}
   omp.critical hint(nonspeculative) {
     omp.terminator
   }
@@ -313,3 +313,35 @@ func @omp_critical2() -> () {
   }
   return
 }
+
+// -----
+
+omp.critical.declare @mutex
+func @omp_critical() -> () {
+  // expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
+  omp.critical(@mutex) hint(uncontended, contended) {
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+omp.critical.declare @mutex
+func @omp_critical() -> () {
+  // expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined}}
+  omp.critical(@mutex) hint(nonspeculative, speculative) {
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+omp.critical.declare @mutex
+func @omp_critica() -> () {
+  // expected-error @below {{invalid_hint is not a valid hint}}
+  omp.critical(@mutex) hint(invalid_hint) {
+    omp.terminator
+  }
+}

diff  --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 58f0d984d7845..b59ceef29a626 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -375,12 +375,42 @@ omp.critical.declare @mutex
 
 // CHECK-LABEL: omp_critical
 func @omp_critical() -> () {
+  // CHECK: omp.critical
   omp.critical {
     omp.terminator
   }
 
+  // CHECK: omp.critical(@{{.*}}) hint(uncontended)
+  omp.critical(@mutex) hint(uncontended) {
+    omp.terminator
+  }
+  // CHECK: omp.critical(@{{.*}}) hint(contended)
+  omp.critical(@mutex) hint(contended) {
+    omp.terminator
+  }
+  // CHECK: omp.critical(@{{.*}}) hint(nonspeculative)
   omp.critical(@mutex) hint(nonspeculative) {
     omp.terminator
   }
+  // CHECK: omp.critical(@{{.*}}) hint(uncontended, nonspeculative)
+  omp.critical(@mutex) hint(uncontended, nonspeculative) {
+    omp.terminator
+  }
+  // CHECK: omp.critical(@{{.*}}) hint(contended, nonspeculative)
+  omp.critical(@mutex) hint(nonspeculative, contended) {
+    omp.terminator
+  }
+  // CHECK: omp.critical(@{{.*}}) hint(speculative)
+  omp.critical(@mutex) hint(speculative) {
+    omp.terminator
+  }
+  // CHECK: omp.critical(@{{.*}}) hint(uncontended, speculative)
+  omp.critical(@mutex) hint(uncontended, speculative) {
+    omp.terminator
+  }
+  // CHECK: omp.critical(@{{.*}}) hint(contended, speculative)
+  omp.critical(@mutex) hint(speculative, contended) {
+    omp.terminator
+  }
   return
 }


        


More information about the Mlir-commits mailing list