[Mlir-commits] [mlir] 76cf140 - [MLIR] Added llvm.fence

Alex Zinenko llvmlistbot at llvm.org
Tue Mar 17 09:53:45 PDT 2020


Author: Sagar Jain
Date: 2020-03-17T17:53:37+01:00
New Revision: 76cf14035be346ad7f8f9fef334fbc03fc11bd33

URL: https://github.com/llvm/llvm-project/commit/76cf14035be346ad7f8f9fef334fbc03fc11bd33
DIFF: https://github.com/llvm/llvm-project/commit/76cf14035be346ad7f8f9fef334fbc03fc11bd33.diff

LOG: [MLIR] Added llvm.fence

This patch adds llvm.fence. I tried not to change the syntax much.

syntax:

LLVM IR
`fence [syncscope("<target-scope>")] <ordering>`

MLIR LLVM Dialect

`llvm.fence [syncscope("<target-scope>")] <ordering>`

example:
LLVM IR: `fence syncscope("agent") seq_cst`
MLIR: `llvm.fence syncscope("agent") seq_cst`

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

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
    mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
    mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
    mlir/test/Dialect/LLVMIR/invalid.mlir
    mlir/test/Dialect/LLVMIR/roundtrip.mlir
    mlir/test/Target/import.ll
    mlir/test/Target/llvmir.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index c702ed8d2fca..c495dfd7c903 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -943,4 +943,16 @@ def LLVM_AssumeOp : LLVM_Op<"intr.assume", []>,
   }];
 }
 
+def LLVM_FenceOp : LLVM_ZeroResultOp<"fence", []>,
+                   Arguments<(ins AtomicOrdering:$ordering,
+                    StrAttr:$syncscope)> {
+  let llvmBuilder = [{
+    llvm::LLVMContext &llvmContext = builder.getContext();
+    builder.CreateFence(getLLVMAtomicOrdering($ordering),
+      llvmContext.getOrInsertSyncScopeID($syncscope));
+  }];
+  let parser = [{ return parseFenceOp(parser, result); }];
+  let printer = [{ printFenceOp(p, *this); }];
+  let verifier = "return ::verify(*this);";
+}
 #endif // LLVMIR_OPS

diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 7a15d579127d..2a2e6699fee5 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -1567,6 +1567,47 @@ static LogicalResult verify(AtomicCmpXchgOp op) {
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// Printer, parser and verifier for LLVM::FenceOp.
+//===----------------------------------------------------------------------===//
+
+// <operation> ::= `llvm.fence` (`syncscope(`strAttr`)`)? keyword
+// attribute-dict?
+static ParseResult parseFenceOp(OpAsmParser &parser, OperationState &result) {
+  StringAttr sScope;
+  StringRef syncscopeKeyword = "syncscope";
+  if (!failed(parser.parseOptionalKeyword(syncscopeKeyword))) {
+    if (parser.parseLParen() ||
+        parser.parseAttribute(sScope, syncscopeKeyword, result.attributes) ||
+        parser.parseRParen())
+      return failure();
+  } else {
+    result.addAttribute(syncscopeKeyword,
+                        parser.getBuilder().getStringAttr(""));
+  }
+  if (parseAtomicOrdering(parser, result, "ordering") ||
+      parser.parseOptionalAttrDict(result.attributes))
+    return failure();
+  return success();
+}
+
+static void printFenceOp(OpAsmPrinter &p, FenceOp &op) {
+  StringRef syncscopeKeyword = "syncscope";
+  p << op.getOperationName() << ' ';
+  if (!op.getAttr(syncscopeKeyword).cast<StringAttr>().getValue().empty())
+    p << "syncscope(" << op.getAttr(syncscopeKeyword) << ") ";
+  p << stringifyAtomicOrdering(op.ordering());
+}
+
+static LogicalResult verify(FenceOp &op) {
+  if (op.ordering() == AtomicOrdering::not_atomic ||
+      op.ordering() == AtomicOrdering::unordered ||
+      op.ordering() == AtomicOrdering::monotonic)
+    return op.emitOpError("can be given only acquire, release, acq_rel, "
+                          "and seq_cst orderings");
+  return success();
+}
+
 //===----------------------------------------------------------------------===//
 // LLVMDialect initialization, type parsing, and registration.
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
index 6a774acdf6bf..86351bd689ad 100644
--- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
+++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
@@ -485,8 +485,7 @@ static const DenseMap<unsigned, StringRef> opcMap = {
     INST(Or, Or), INST(Xor, XOr), INST(Alloca, Alloca), INST(Load, Load),
     INST(Store, Store),
     // Getelementptr is handled specially.
-    INST(Ret, Return),
-    // FIXME: fence
+    INST(Ret, Return), INST(Fence, Fence),
     // FIXME: atomiccmpxchg
     // FIXME: atomicrmw
     INST(Trunc, Trunc), INST(ZExt, ZExt), INST(SExt, SExt),
@@ -539,6 +538,26 @@ static ICmpPredicate getICmpPredicate(llvm::CmpInst::Predicate p) {
   llvm_unreachable("incorrect comparison predicate");
 }
 
+static AtomicOrdering getLLVMAtomicOrdering(llvm::AtomicOrdering ordering) {
+  switch (ordering) {
+  case llvm::AtomicOrdering::NotAtomic:
+    return LLVM::AtomicOrdering::not_atomic;
+  case llvm::AtomicOrdering::Unordered:
+    return LLVM::AtomicOrdering::unordered;
+  case llvm::AtomicOrdering::Monotonic:
+    return LLVM::AtomicOrdering::monotonic;
+  case llvm::AtomicOrdering::Acquire:
+    return LLVM::AtomicOrdering::acquire;
+  case llvm::AtomicOrdering::Release:
+    return LLVM::AtomicOrdering::release;
+  case llvm::AtomicOrdering::AcquireRelease:
+    return LLVM::AtomicOrdering::acq_rel;
+  case llvm::AtomicOrdering::SequentiallyConsistent:
+    return LLVM::AtomicOrdering::seq_cst;
+  }
+  llvm_unreachable("incorrect atomic ordering");
+}
+
 // `br` branches to `target`. Return the branch arguments to `br`, in the
 // same order of the PHIs in `target`.
 LogicalResult
@@ -743,6 +762,23 @@ LogicalResult Importer::processInstruction(llvm::Instruction *inst) {
       v = op->getResult(0);
     return success();
   }
+  case llvm::Instruction::Fence: {
+    StringRef syncscope;
+    SmallVector<StringRef, 4> ssNs;
+    llvm::LLVMContext &llvmContext = dialect->getLLVMContext();
+    llvm::FenceInst *fence = cast<llvm::FenceInst>(inst);
+    llvmContext.getSyncScopeNames(ssNs);
+    int fenceSyncScopeID = fence->getSyncScopeID();
+    for (unsigned i = 0, e = ssNs.size(); i != e; i++) {
+      if (fenceSyncScopeID == llvmContext.getOrInsertSyncScopeID(ssNs[i])) {
+        syncscope = ssNs[i];
+        break;
+      }
+    }
+    b.create<FenceOp>(loc, getLLVMAtomicOrdering(fence->getOrdering()),
+                      syncscope);
+    return success();
+  }
   case llvm::Instruction::GetElementPtr: {
     // FIXME: Support inbounds GEPs.
     llvm::GetElementPtrInst *gep = cast<llvm::GetElementPtrInst>(inst);

diff  --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir
index eaee62ef8324..03de594083dd 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -561,3 +561,10 @@ llvm.func @caller(%arg0: !llvm.i32) -> !llvm.i32 {
   %2 = llvm.landingpad : !llvm<"{ i8*, i32 }">
   llvm.return %0 : !llvm.i32
 }
+
+// -----
+
+func @invalid_ordering_in_fence() {
+  // expected-error @+1 {{can be given only acquire, release, acq_rel, and seq_cst orderings}}
+  llvm.fence syncscope("agent") monotonic
+}

diff  --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index 8a8de4cf6f21..32fe4c496523 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -292,4 +292,15 @@ func @useFreezeOp(%arg0: !llvm.i32) {
   // CHECK:  = llvm.freeze %[[x]] : !llvm.i8
   %2 = llvm.freeze %1 : !llvm.i8
   return
+}
+
+// CHECK-LABEL: @useFenceInst
+func @useFenceInst() {
+  // CHECK:  syncscope("agent") seq_cst 
+  llvm.fence syncscope("agent") seq_cst
+  // CHECK:  seq_cst 
+  llvm.fence syncscope("") seq_cst
+  // CHECK:  release
+  llvm.fence release
+  return
 }
\ No newline at end of file

diff  --git a/mlir/test/Target/import.ll b/mlir/test/Target/import.ll
index 5e38b6b2fe7d..0394309093f2 100644
--- a/mlir/test/Target/import.ll
+++ b/mlir/test/Target/import.ll
@@ -307,4 +307,15 @@ define i32 @useFreezeOp(i32 %x) {
   %3 = freeze i8 %2
   %poison = add nsw i1 0, undef
   ret i32 0
+}
+
+;CHECK-LABEL: @useFenceInst
+define i32 @useFenceInst() {
+  ;CHECK: llvm.fence syncscope("agent") seq_cst
+  fence syncscope("agent") seq_cst
+  ;CHECK: llvm.fence release
+  fence release
+  ;CHECK: llvm.fence seq_cst
+  fence syncscope("") seq_cst
+  ret i32 0
 }
\ No newline at end of file

diff  --git a/mlir/test/Target/llvmir.mlir b/mlir/test/Target/llvmir.mlir
index 7f202b39a471..43cc7d804dae 100644
--- a/mlir/test/Target/llvmir.mlir
+++ b/mlir/test/Target/llvmir.mlir
@@ -1190,3 +1190,14 @@ llvm.func @boolConstArg() -> !llvm.i1 {
   %2 = llvm.and %0, %1 : !llvm.i1
   llvm.return %2 : !llvm.i1
 }
+
+// CHECK-LABEL: @callFenceInst
+llvm.func @callFenceInst() {
+  // CHECK: fence syncscope("agent") release
+  llvm.fence syncscope("agent") release
+  // CHECK: fence release
+  llvm.fence release
+  // CHECK: fence release
+  llvm.fence syncscope("") release
+  llvm.return
+}
\ No newline at end of file


        


More information about the Mlir-commits mailing list