[Mlir-commits] [mlir] 00d4814 - [mlir] Generalize intrinsic builders in the LLVM dialect definition

Alex Zinenko llvmlistbot at llvm.org
Tue Feb 25 02:59:22 PST 2020


Author: Alex Zinenko
Date: 2020-02-25T11:59:04+01:00
New Revision: 00d4814f499fd09f8cf326c1c1a219175268b970

URL: https://github.com/llvm/llvm-project/commit/00d4814f499fd09f8cf326c1c1a219175268b970
DIFF: https://github.com/llvm/llvm-project/commit/00d4814f499fd09f8cf326c1c1a219175268b970.diff

LOG: [mlir] Generalize intrinsic builders in the LLVM dialect definition

All LLVM IR intrinsics are constructed in a similar way. The ODS definition of
the LLVM dialect in MLIR also lists multiple intrinsics, many of which
reproduce the same (or similar enough) code stanza to translate the MLIR
operation into the LLVM IR intrinsic. Provide a single base class containing
parameterizable code to build LLVM IR intrinsics given their name and the lists
of overloadable operands and results. Use this class to remove (almost)
duplicate translations for intrinsics defined in LLVMOps.td.

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

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
    mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
index 840b4396134e..cfae60bc6952 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
@@ -75,9 +75,7 @@ class LLVM_OpBase<Dialect dialect, string mnemonic, list<OpTrait> traits = []> :
 class LLVM_Op<string mnemonic, list<OpTrait> traits = []> :
     LLVM_OpBase<LLVM_Dialect, mnemonic, traits>;
 
-// Base class for LLVM intrinsics operation. It is the same as an LLVM_Op
-// but the operation has a ".intr." element in the prefix becoming
-// "llvm.intr.*".
+// Compatibility class for LLVM intrinsic operations.
 class LLVM_IntrOp<string mnemonic, list<OpTrait> traits = []> :
     LLVM_Op<"intr."#mnemonic, traits>;
 
@@ -115,42 +113,96 @@ class LLVM_EnumAttr<string name, string llvmName, string description,
   string llvmClassName = llvmName;
 }
 
-// LLVM vector reduction over a single vector.
-class LLVM_VectorReduction<string mnem> :
-  LLVM_IntrOp<"experimental.vector.reduce." # mnem, []>,
-  Arguments<(ins LLVM_Type)>, Results<(outs LLVM_Type:$res)> {
-    let llvmBuilder = [{
-      llvm::Module *module = builder.GetInsertBlock()->getModule();
-      llvm::Function *fn = llvm::Intrinsic::getDeclaration(
-        module,
-        llvm::Intrinsic::experimental_vector_reduce_}] #
-        !subst(".","_", mnem) # [{, {
-          opInst.getOperand(0).getType().cast<LLVM::LLVMType>()
-          .getUnderlyingType(),
-        });
-      auto operands = lookupValues(opInst.getOperands());
-      $res = builder.CreateCall(fn, operands);
-    }];
+// For every value in the list, substitutes the value in the place of "$0" in
+// "pattern" and stores the list of strings as "lst".
+class ListIntSubst<string pattern, list<int> values> {
+  list<string> lst = !foreach(x, values,
+                              !subst("$0", !cast<string>(x), pattern));
 }
 
-// LLVM vector reduction over a single vector, with an initial value.
-class LLVM_VectorReductionV2<string mnem> :
-  LLVM_IntrOp<"experimental.vector.reduce.v2." # mnem, []>,
-  Arguments<(ins LLVM_Type, LLVM_Type)>, Results<(outs LLVM_Type:$res)> {
-    let llvmBuilder = [{
-      llvm::Module *module = builder.GetInsertBlock()->getModule();
-      llvm::Function *fn = llvm::Intrinsic::getDeclaration(
+// Patterns with code obtaining the LLVM IR type of the given operand or result
+// of operation. "$0" is expected to be replaced by the position of the operand
+// or result in the operation.
+def LLVM_IntrPatterns {
+  string operand =
+    [{opInst.getOperand($0).getType()
+      .cast<LLVM::LLVMType>().getUnderlyingType()}];
+  string result =
+    [{opInst.getResult($0).getType()
+      .cast<LLVM::LLVMType>().getUnderlyingType()}];
+}
+
+
+// Base class for LLVM intrinsics operation. It is similar to LLVM_Op, but
+// provides the "llvmBuilder" field for constructing the intrinsic. The builder
+// relies on the contents on "overloadedResults" and "overloadedOperands" lists
+// that contain the positions of intrinsic results and operands that are
+// overloadable in the LLVM sense, that is their types must be passed in during
+// the construction of the intrinsic declaration to 
diff erentiate between
+// 
diff erently-typed versions of the intrinsic. "opName" contains the name of
+// the operation to be associated with the intrinsic and "enumName" contains the
+// name of the intrinsic as appears in `llvm::Intrinsic` enum; one usually wants
+// these to be related.
+class LLVM_IntrOpBase<Dialect dialect, string opName, string enumName,
+                      list<int> overloadedResults, list<int> overloadedOperands,
+                      list<OpTrait> traits, bit hasResult>
+    : LLVM_OpBase<dialect, opName, traits>,
+      Results<!if(hasResult, (outs LLVM_Type:$res), (outs))> {
+  let llvmBuilder = [{
+    llvm::Module *module = builder.GetInsertBlock()->getModule();
+    llvm::Function *fn = llvm::Intrinsic::getDeclaration(
         module,
-        llvm::Intrinsic::experimental_vector_reduce_v2_}] #
-        !subst(".","_", mnem) # [{, {
-          opInst.getResult(0).getType().cast<LLVM::LLVMType>()
-          .getUnderlyingType(),
-          opInst.getOperand(1).getType().cast<LLVM::LLVMType>()
-          .getUnderlyingType(),
+        llvm::Intrinsic::}] # enumName # [{,
+        { }] # StrJoin<!listconcat(
+            ListIntSubst<LLVM_IntrPatterns.result, overloadedResults>.lst,
+            ListIntSubst<LLVM_IntrPatterns.operand,
+                         overloadedOperands>.lst)>.result # [{
         });
-      auto operands = lookupValues(opInst.getOperands());
-      $res = builder.CreateCall(fn, operands);
-    }];
+    auto operands = lookupValues(opInst.getOperands());
+    }] # !if(hasResult, "$res = ", "") # [{builder.CreateCall(fn, operands);
+  }];
 }
 
+// Base class for LLVM intrinsic operations returning no results. Places the
+// intrinsic into the LLVM dialect and prefixes its name with "intr.".
+//
+// Sample use: derive an entry from this class and populate the fields.
+//
+//    def LLVM_Name : LLVM_ZeroResultIntrOp<"name", [0], [NoSideEffect]>,
+//                    Arguments<(ins LLVM_Type, LLVM_Type)>;
+//
+// The mnemonic will be prefixed with "llvm.intr.", where the "llvm." part comes
+// from the LLVM dialect. The overloadedOperands list contains the indices of
+// the operands the type of which will be passed in the LLVM IR intrinsic
+// builder. In the example above, the Op has two arguments, but only the first
+// one (as indicated by `[0]`) is necessary to resolve the overloaded intrinsic.
+// The Op has no results.
+class LLVM_ZeroResultIntrOp<string mnem, list<int> overloadedOperands = [],
+                            list<OpTrait> traits = []>
+    : LLVM_IntrOpBase<LLVM_Dialect, "intr." # mnem, !subst(".", "_", mnem),
+                      [], overloadedOperands, traits, 0>;
+
+// Base class for LLVM intrinsic operations returning one result. Places the
+// intrinsic into the LLVM dialect and prefixes its name with "intr.". This is
+// similar to LLVM_ZeroResultIntrOp but allows one to define Ops returning one
+// result, called "res". Additionally, the overloadedResults list should contain
+// "0" if the result must be used to resolve overloaded intrinsics, or remain
+// empty otherwise.
+class LLVM_OneResultIntrOp<string mnem, list<int> overloadedResults = [],
+                           list<int> overloadedOperands = [],
+                           list<OpTrait> traits = []>
+    : LLVM_IntrOpBase<LLVM_Dialect, "intr." # mnem, !subst(".", "_", mnem),
+                      overloadedResults, overloadedOperands, traits, 1>;
+
+// LLVM vector reduction over a single vector.
+class LLVM_VectorReduction<string mnem>
+    : LLVM_OneResultIntrOp<"experimental.vector.reduce." # mnem, [], [0], []>,
+      Arguments<(ins LLVM_Type)>;
+
+// LLVM vector reduction over a single vector, with an initial value.
+class LLVM_VectorReductionV2<string mnem>
+    : LLVM_OneResultIntrOp<"experimental.vector.reduce.v2." # mnem,
+                           [0], [1], []>,
+      Arguments<(ins LLVM_Type, LLVM_Type)>;
+
 #endif  // LLVMIR_OP_BASE

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 5be06a8bfe72..a4d74bf70cbe 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -692,84 +692,34 @@ def LLVM_ConstantOp
 // "intr." to avoid potential name clashes.
 
 class LLVM_UnaryIntrinsicOp<string func, list<OpTrait> traits = []> :
-    LLVM_OneResultOp<"intr." # func,
+    LLVM_OneResultIntrOp<func, [], [0],
            !listconcat([NoSideEffect, SameOperandsAndResultType], traits)>,
-    Arguments<(ins LLVM_Type:$in)>,
-    LLVM_Builder<"$res = builder.CreateCall(llvm::Intrinsic::getDeclaration("
-      "builder.GetInsertBlock()->getModule(), llvm::Intrinsic::" # func # ","
-      "{$in->getType()}), {$in});"> {
-}
+    Arguments<(ins LLVM_Type:$in)>;
 
 class LLVM_BinarySameArgsIntrinsicOp<string func, list<OpTrait> traits = []> :
-    LLVM_OneResultOp<"intr." # func,
+    LLVM_OneResultIntrOp<func, [], [0],
            !listconcat([NoSideEffect, SameOperandsAndResultType], traits)>,
-    Arguments<(ins LLVM_Type:$a, LLVM_Type:$b)>,
-    LLVM_Builder<"$res = builder.CreateCall(llvm::Intrinsic::getDeclaration("
-      "builder.GetInsertBlock()->getModule(), llvm::Intrinsic::" # func # ","
-      "{$a->getType()}), {$a, $b});"> {
-}
+    Arguments<(ins LLVM_Type:$a, LLVM_Type:$b)>;
 
 class LLVM_TernarySameArgsIntrinsicOp<string func, list<OpTrait> traits = []> :
-    LLVM_OneResultOp<"intr." # func,
+    LLVM_OneResultIntrOp<func, [], [0],
            !listconcat([NoSideEffect, SameOperandsAndResultType], traits)>,
-    Arguments<(ins LLVM_Type:$a, LLVM_Type:$b, LLVM_Type:$c)>,
-    LLVM_Builder<"$res = builder.CreateCall(llvm::Intrinsic::getDeclaration("
-      "builder.GetInsertBlock()->getModule(), llvm::Intrinsic::" # func # ","
-      "{$a->getType()}), {$a, $b, $c});"> {
-}
+    Arguments<(ins LLVM_Type:$a, LLVM_Type:$b, LLVM_Type:$c)>;
 
+def LLVM_CopySignOp : LLVM_BinarySameArgsIntrinsicOp<"copysign">;
+def LLVM_CosOp : LLVM_UnaryIntrinsicOp<"cos">;
 def LLVM_ExpOp : LLVM_UnaryIntrinsicOp<"exp">;
 def LLVM_FAbsOp : LLVM_UnaryIntrinsicOp<"fabs">;
 def LLVM_FCeilOp : LLVM_UnaryIntrinsicOp<"ceil">;
-def LLVM_CosOp : LLVM_UnaryIntrinsicOp<"cos">;
-def LLVM_CopySignOp : LLVM_BinarySameArgsIntrinsicOp<"copysign">;
 def LLVM_FMAOp : LLVM_TernarySameArgsIntrinsicOp<"fma">;
 def LLVM_FMulAddOp : LLVM_TernarySameArgsIntrinsicOp<"fmuladd">;
-def LLVM_SqrtOp : LLVM_UnaryIntrinsicOp<"sqrt">;
-
-def LLVM_LogOp : LLVM_Op<"intr.log", [NoSideEffect]>,
-                   Arguments<(ins LLVM_Type:$in)>,
-                   Results<(outs LLVM_Type:$res)> {
-  let llvmBuilder = [{
-    llvm::Module *module = builder.GetInsertBlock()->getModule();
-    llvm::Function *fn = llvm::Intrinsic::getDeclaration(
-        module, llvm::Intrinsic::log, {$in->getType()});
-    $res = builder.CreateCall(fn, {$in});
-  }];
-}
-
-def LLVM_Log10Op : LLVM_Op<"intr.log10", [NoSideEffect]>,
-                   Arguments<(ins LLVM_Type:$in)>,
-                   Results<(outs LLVM_Type:$res)> {
-  let llvmBuilder = [{
-    llvm::Module *module = builder.GetInsertBlock()->getModule();
-    llvm::Function *fn = llvm::Intrinsic::getDeclaration(
-        module, llvm::Intrinsic::log10, {$in->getType()});
-    $res = builder.CreateCall(fn, {$in});
-  }];
-}
-
-def LLVM_Log2Op : LLVM_Op<"intr.log2", [NoSideEffect]>,
-                   Arguments<(ins LLVM_Type:$in)>,
-                   Results<(outs LLVM_Type:$res)> {
-  let llvmBuilder = [{
-    llvm::Module *module = builder.GetInsertBlock()->getModule();
-    llvm::Function *fn = llvm::Intrinsic::getDeclaration(
-        module, llvm::Intrinsic::log2, {$in->getType()});
-    $res = builder.CreateCall(fn, {$in});
-  }];
-}
-
-def LLVM_Prefetch : LLVM_ZeroResultOp<"intr.prefetch">,
+def LLVM_Log10Op : LLVM_UnaryIntrinsicOp<"log10">;
+def LLVM_Log2Op : LLVM_UnaryIntrinsicOp<"log2">;
+def LLVM_LogOp : LLVM_UnaryIntrinsicOp<"log">;
+def LLVM_Prefetch : LLVM_ZeroResultIntrOp<"prefetch", [0]>,
                     Arguments<(ins LLVM_Type:$addr, LLVM_Type:$rw,
-                    LLVM_Type:$hint, LLVM_Type:$cache)> {
-  let llvmBuilder = [{
-    llvm::Module *module = builder.GetInsertBlock()->getModule();
-    llvm::Function *fn = llvm::Intrinsic::getDeclaration(
-        module, llvm::Intrinsic::prefetch, $addr->getType());
-    builder.CreateCall(fn, {$addr, $rw, $hint, $cache});
-  }];
-}
+                               LLVM_Type:$hint, LLVM_Type:$cache)>;
+def LLVM_SqrtOp : LLVM_UnaryIntrinsicOp<"sqrt">;
 
 //
 // Vector Reductions.


        


More information about the Mlir-commits mailing list