[Mlir-commits] [mlir] fc41777 - [mlir][spirv] De-template serialization

Lei Zhang llvmlistbot at llvm.org
Wed Dec 23 11:59:43 PST 2020


Author: Lei Zhang
Date: 2020-12-23T14:54:26-05:00
New Revision: fc41777702aae1cb88512a6aa45382736766fadf

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

LOG: [mlir][spirv] De-template serialization

Previously for each op we generate a separate serialization
method for it. Those serialization methods duplicate the logic
of parsing operands/results/attributes and such.

This commit creates a generic method and let suitable op-specific
serialization method to call into it.

wc -l SPIRVSerialization.inc: before 8304; after: 5597 (So -2707)

Reviewed By: hanchung, ThomasRaoux

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

Added: 
    

Modified: 
    mlir/lib/Target/SPIRV/Serialization.cpp
    mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Target/SPIRV/Serialization.cpp b/mlir/lib/Target/SPIRV/Serialization.cpp
index db00f5ecf899..c530cccd4232 100644
--- a/mlir/lib/Target/SPIRV/Serialization.cpp
+++ b/mlir/lib/Target/SPIRV/Serialization.cpp
@@ -364,15 +364,23 @@ class Serializer {
   /// Main dispatch method for serializing an operation.
   LogicalResult processOperation(Operation *op);
 
-  /// Method to dispatch to the serialization function for an operation in
-  /// SPIR-V dialect that is a mirror of an instruction in the SPIR-V spec.
-  /// This is auto-generated from ODS. Dispatch is handled for all operations
-  /// in SPIR-V dialect that have hasOpcode == 1.
+  /// Serializes an operation `op` as core instruction with `opcode` if
+  /// `extInstSet` is empty. Otherwise serializes it as an extended instruction
+  /// with `opcode` from `extInstSet`.
+  /// This method is a generic one for dispatching any SPIR-V ops that has no
+  /// variadic operands and attributes in TableGen definitions.
+  LogicalResult processOpWithoutGrammarAttr(Operation *op, StringRef extInstSet,
+                                            uint32_t opcode);
+
+  /// Dispatches to the serialization function for an operation in SPIR-V
+  /// dialect that is a mirror of an instruction in the SPIR-V spec. This is
+  /// auto-generated from ODS. Dispatch is handled for all operations in SPIR-V
+  /// dialect that have hasOpcode == 1.
   LogicalResult dispatchToAutogenSerialization(Operation *op);
 
-  /// Method to serialize an operation in the SPIR-V dialect that is a mirror of
-  /// an instruction in the SPIR-V spec. This is auto generated if hasOpcode ==
-  /// 1 and autogenSerialization == 1 in ODS.
+  /// Serializes an operation in the SPIR-V dialect that is a mirror of an
+  /// instruction in the SPIR-V spec. This is auto generated if hasOpcode == 1
+  /// and autogenSerialization == 1 in ODS.
   template <typename OpTy>
   LogicalResult processOp(OpTy op) {
     return op.emitError("unsupported op serialization");
@@ -1930,6 +1938,46 @@ LogicalResult Serializer::processOperation(Operation *opInst) {
           [&](Operation *op) { return dispatchToAutogenSerialization(op); });
 }
 
+LogicalResult Serializer::processOpWithoutGrammarAttr(Operation *op,
+                                                      StringRef extInstSet,
+                                                      uint32_t opcode) {
+  SmallVector<uint32_t, 4> operands;
+  Location loc = op->getLoc();
+
+  uint32_t resultID = 0;
+  if (op->getNumResults() != 0) {
+    uint32_t resultTypeID = 0;
+    if (failed(processType(loc, op->getResult(0).getType(), resultTypeID)))
+      return failure();
+    operands.push_back(resultTypeID);
+
+    resultID = getNextID();
+    operands.push_back(resultID);
+    valueIDMap[op->getResult(0)] = resultID;
+  };
+
+  for (Value operand : op->getOperands())
+    operands.push_back(getValueID(operand));
+
+  emitDebugLine(functionBody, loc);
+
+  if (extInstSet.empty()) {
+    encodeInstructionInto(functionBody, static_cast<spirv::Opcode>(opcode),
+                          operands);
+  } else {
+    encodeExtensionInstruction(op, extInstSet, opcode, operands);
+  }
+
+  if (op->getNumResults() != 0) {
+    for (auto attr : op->getAttrs()) {
+      if (failed(processDecoration(loc, resultID, attr)))
+        return failure();
+    }
+  }
+
+  return success();
+}
+
 namespace {
 template <>
 LogicalResult

diff  --git a/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp b/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
index ab520114e7f5..74fe1e0fdb08 100644
--- a/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
+++ b/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
@@ -647,8 +647,7 @@ static void emitDecorationSerialization(const Operator &op, StringRef tabs,
     // All non-argument attributes translated into OpDecorate instruction
     os << tabs << formatv("for (auto attr : {0}->getAttrs()) {{\n", opVar);
     os << tabs
-       << formatv("  if (llvm::any_of({0}, [&](StringRef elided)", elidedAttrs);
-    os << " {return attr.first == elided;})) {\n";
+       << formatv("  if (llvm::is_contained({0}, attr.first)) {{", elidedAttrs);
     os << tabs << "    continue;\n";
     os << tabs << "  }\n";
     os << tabs
@@ -666,14 +665,35 @@ static void emitSerializationFunction(const Record *attrClass,
                                       const Record *record, const Operator &op,
                                       raw_ostream &os) {
   // If the record has 'autogenSerialization' set to 0, nothing to do
-  if (!record->getValueAsBit("autogenSerialization")) {
+  if (!record->getValueAsBit("autogenSerialization"))
     return;
-  }
+
   StringRef opVar("op"), operands("operands"), elidedAttrs("elidedAttrs"),
       resultID("resultID");
+
   os << formatv(
       "template <> LogicalResult\nSerializer::processOp<{0}>({0} {1}) {{\n",
       op.getQualCppClassName(), opVar);
+
+  // Special case for ops without attributes in TableGen definitions
+  if (op.getNumAttributes() == 0 && op.getNumVariableLengthOperands() == 0) {
+    std::string extInstSet;
+    std::string opcode;
+    if (record->isSubClassOf("SPV_ExtInstOp")) {
+      extInstSet =
+          formatv("\"{0}\"", record->getValueAsString("extendedInstSetName"));
+      opcode = std::to_string(record->getValueAsInt("extendedInstOpcode"));
+    } else {
+      extInstSet = "\"\"";
+      opcode = formatv("static_cast<uint32_t>(spirv::Opcode::{0})",
+                       record->getValueAsString("spirvOpName"));
+    }
+
+    os << formatv("  return processOpWithoutGrammarAttr({0}, {1}, {2});\n}\n\n",
+                  opVar, extInstSet, opcode);
+    return;
+  }
+
   os << formatv("  SmallVector<uint32_t, 4> {0};\n", operands);
   os << formatv("  SmallVector<StringRef, 2> {0};\n", elidedAttrs);
 


        


More information about the Mlir-commits mailing list