[Mlir-commits] [mlir] 4b84223 - [MLIR][LLVMIR][DLTI] Pass to update #llvm.target's features per relevant backend (#154938)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Aug 26 15:12:38 PDT 2025


Author: Rolf Morel
Date: 2025-08-26T22:12:35Z
New Revision: 4b84223aad4fb5f277aa524b6ff518f4e1cd0df7

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

LOG: [MLIR][LLVMIR][DLTI] Pass to update #llvm.target's features per relevant backend (#154938)

Modifies `#llvm.target<..., features = $FEATURES>` so that `$FEATURES`
is now an `#llvm.target_features<[...]>` attribute (rather than a
`StringAttr`). This enables the attribute to respond to DLTI queries for
the different target features.

The pass updates the `$FEATURES` attribute of the target attr at name
`llvm.target` in accordance with the (Sub)Target's features that the
relevant LLVM backend knows about.

---

DEMO:
```mlir
module attributes {llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
                                              chip = "skylake"> } {
}
```
by way of `-llvm-target-to-target-features` turns into:
```mlir
module attributes {llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
                                              chip = "skylake", 
                                              features = <["+64bit", "+64bit-mode", "+adx", "+aes", "+allow-light-256-bit", "+avx", "+avx2", "+bmi", "+bmi2", "+clflushopt", "+cmov", "+crc32", "+cx16", "+cx8", "+ermsb", "+f16c", "+false-deps-popcnt", "+fast-15bytenop", "+fast-gather", "+fast-scalar-fsqrt", "+fast-shld-rotate", "+fast-variable-crosslane-shuffle", "+fast-variable-perlane-shuffle", "+fast-vector-fsqrt", "+fma", "+fsgsbase", "+fxsr", "+idivq-to-divl", "+invpcid", "+lzcnt", "+macrofusion", "+mmx", "+movbe", "+no-bypass-delay-blend", "+no-bypass-delay-mov", "+no-bypass-delay-shuffle", "+nopl", "+pclmul", "+popcnt", "+prfchw", "+rdrnd", "+rdseed", "+sahf", "+slow-3ops-lea", "+sse", "+sse2", "+sse3", "+sse4.1", "+sse4.2", "+ssse3", "+vzeroupper", "+x87", "+xsave", "+xsavec", "+xsaveopt", "+xsaves"]>>} {
}
```

Added: 
    mlir/include/mlir/Target/LLVMIR/Transforms/TargetUtils.h
    mlir/lib/Target/LLVMIR/Transforms/TargetToTargetFeatures.cpp
    mlir/lib/Target/LLVMIR/Transforms/TargetUtils.cpp
    mlir/test/Target/LLVMIR/target-to-data-layout-and-target-features.mlir
    mlir/test/Target/LLVMIR/target-to-data-layout-invalid.mlir
    mlir/test/Target/LLVMIR/target-to-data-layout-no-init.mlir
    mlir/test/Target/LLVMIR/target-to-target-features-dlti-query.mlir

Modified: 
    mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
    mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
    mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
    mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
    mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
    mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
    mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp

Removed: 
    mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir
    mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir
    mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir


################################################################################
diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 138dd7703a5e7..bfce904a18d4f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1246,7 +1246,8 @@ def LLVM_VScaleRangeAttr : LLVM_Attr<"VScaleRange", "vscale_range"> {
 // TargetFeaturesAttr
 //===----------------------------------------------------------------------===//
 
-def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
+def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features",
+                                        [DLTIQueryInterface]>
 {
   let summary = "LLVM target features attribute";
 
@@ -1299,6 +1300,9 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
     static constexpr StringLiteral getAttributeName() {
       return StringLiteral("target_features");
     }
+
+    /// Returns the attribute associated with the key.
+    FailureOr<Attribute> query(DataLayoutEntryKey key);
   }];
 
   let assemblyFormat = "`<` `[` (`]`) : ($features^ `]`)? `>`";
@@ -1306,7 +1310,7 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
 }
 
 //===----------------------------------------------------------------------===//
-// LLVM_TargetAttr
+// TargetAttr
 //===----------------------------------------------------------------------===//
 
 def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
@@ -1324,7 +1328,7 @@ def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
   }];
   let parameters = (ins "StringAttr":$triple,
                         "StringAttr":$chip,
-                        OptionalParameter<"StringAttr", "">:$features);
+                        OptionalParameter<"TargetFeaturesAttr", "">:$features);
 
   let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}];
 

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index 64600e86bedfb..60235bcb35561 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -560,8 +560,10 @@ def LLVM_TargetAttrInterface
       /*args=*/(ins)
     >,
     InterfaceMethod<
-      /*description=*/"Returns the target features as a string.",
-      /*retTy=*/"StringAttr",
+      /*description=*/"Returns the target features as a TargetFeaturesAttr.",
+      /*retTy=*/"Attribute", // NB: will be a LLVM::TargetFeaturesAttr, though
+                             // need to work around a cyclic dependency on
+                             // LLVMInterfaces.td and LLVMAttrDefs.td.
       /*methodName=*/"getFeatures",
       /*args=*/(ins)
     >

diff  --git a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
index 1e6419154108c..22e6fadfb37e9 100644
--- a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
+++ b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
@@ -12,7 +12,6 @@
 #include "mlir/Pass/Pass.h"
 
 namespace mlir {
-
 namespace LLVM {
 
 #define GEN_PASS_DECL

diff  --git a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
index 906f6e82efa50..c858e9f4c34cb 100644
--- a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
+++ b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
@@ -27,4 +27,20 @@ def LLVMTargetToDataLayout : Pass<"llvm-target-to-data-layout"> {
   ];
 }
 
+def LLVMTargetToTargetFeatures : Pass<"llvm-target-to-target-features"> {
+  let summary = "Update attached #llvm.target's features per the described target";
+  let description = [{
+    Obtain the TargetMachine specified by the attached #llvm.target's attributes
+    and obtain from it the full list of features of the selected target. Updates
+    the attached #llvm.target so that its features reflect the full list of
+    features.
+  }];
+  let options = [
+    Option<"initializeLLVMTargets", "initialize-llvm-targets", "bool",
+           /*default=*/"true",
+           "Whether to pre-load all available target machines, that LLVM is "
+           "configured to support, into the TargetRegistry.">
+  ];
+}
+
 #endif // MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES

diff  --git a/mlir/include/mlir/Target/LLVMIR/Transforms/TargetUtils.h b/mlir/include/mlir/Target/LLVMIR/Transforms/TargetUtils.h
new file mode 100644
index 0000000000000..2930733ee83d9
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/Transforms/TargetUtils.h
@@ -0,0 +1,35 @@
+//===- TargetUtils.h - Utils to obtain LLVM's TargetMachine and DataLayout ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVMIR_TRANSFORMS_TARGETUTILS_H
+#define MLIR_TARGET_LLVMIR_TRANSFORMS_TARGETUTILS_H
+
+#include "mlir/Dialect/LLVMIR/LLVMInterfaces.h"
+#include "llvm/Support/Threading.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace mlir {
+namespace LLVM {
+namespace detail {
+/// Idempotent helper to register/initialize all backends that LLVM has been
+/// configured to support. Only runs the first time it is called.
+void initializeBackendsOnce();
+
+/// Helper to obtain the TargetMachine specified by the properties of the
+/// TargetAttrInterface-implementing attribute.
+FailureOr<std::unique_ptr<llvm::TargetMachine>>
+getTargetMachine(mlir::LLVM::TargetAttrInterface attr);
+
+/// Helper to obtain the DataLayout of the target specified by the properties of
+/// the TargetAttrInterface-implementing attribute.
+FailureOr<llvm::DataLayout> getDataLayout(mlir::LLVM::TargetAttrInterface attr);
+} // namespace detail
+} // namespace LLVM
+} // namespace mlir
+
+#endif // MLIR_TARGET_LLVMIR_TRANSFORMS_TARGETUTILS_H

diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 634efcaea794e..9d7a23f028cb0 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -374,6 +374,43 @@ TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
       getAttributeName());
 }
 
+FailureOr<Attribute> TargetFeaturesAttr::query(DataLayoutEntryKey key) {
+  auto stringKey = dyn_cast<StringAttr>(key);
+  if (!stringKey)
+    return failure();
+
+  if (contains(stringKey))
+    return UnitAttr::get(getContext());
+
+  if (contains((std::string("+") + stringKey.strref()).str()))
+    return BoolAttr::get(getContext(), true);
+
+  if (contains((std::string("-") + stringKey.strref()).str()))
+    return BoolAttr::get(getContext(), false);
+
+  return failure();
+}
+
+//===----------------------------------------------------------------------===//
+// TargetAttr
+//===----------------------------------------------------------------------===//
+
+FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
+  if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
+    if (stringAttrKey.getValue() == "triple")
+      return getTriple();
+    if (stringAttrKey.getValue() == "chip")
+      return getChip();
+    if (stringAttrKey.getValue() == "features" && getFeatures())
+      return getFeatures();
+  }
+  return failure();
+}
+
+//===----------------------------------------------------------------------===//
+// ModuleFlagAttr
+//===----------------------------------------------------------------------===//
+
 LogicalResult
 ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
                        LLVM::ModFlagBehavior flagBehavior, StringAttr key,
@@ -402,20 +439,3 @@ ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
                         "supported for unknown key '"
                      << key << "'";
 }
-
-//===----------------------------------------------------------------------===//
-// LLVM_TargetAttr
-//===----------------------------------------------------------------------===//
-
-FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
-  if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
-    if (stringAttrKey.getValue() == "triple")
-      return getTriple();
-    if (stringAttrKey.getValue() == "chip")
-      return getChip();
-    if (stringAttrKey.getValue() == "features" && getFeatures())
-      return getFeatures();
-  }
-
-  return failure();
-}

diff  --git a/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
index a0232601c5f9c..044da1c442049 100644
--- a/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
@@ -1,5 +1,7 @@
 add_mlir_dialect_library(MLIRTargetLLVMIRTransforms
   TargetToDataLayout.cpp
+  TargetToTargetFeatures.cpp
+  TargetUtils.cpp
 
   DEPENDS
   MLIRTargetLLVMIRTransformsIncGen

diff  --git a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
index d41d441812039..c0f9ceb6313d0 100644
--- a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
+++ b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
@@ -5,21 +5,14 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+
 #include "mlir/Target/LLVMIR/Transforms/Passes.h"
+#include "mlir/Target/LLVMIR/Transforms/TargetUtils.h"
 
 #include "mlir/Dialect/DLTI/DLTI.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/Target/LLVMIR/Import.h"
 
-#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/TargetSelect.h"
-#include "llvm/Target/TargetMachine.h"
-
-#define DEBUG_TYPE "mlir-llvm-target-to-data-layout"
-#define DBGS() (llvm::dbgs() << '[' << DEBUG_TYPE << "] ")
-#define LDBG(X) LLVM_DEBUG(DBGS() << X << "\n")
-
 namespace mlir {
 namespace LLVM {
 #define GEN_PASS_DEF_LLVMTARGETTODATALAYOUT
@@ -29,35 +22,6 @@ namespace LLVM {
 
 using namespace mlir;
 
-static FailureOr<std::unique_ptr<llvm::TargetMachine>>
-getTargetMachine(LLVM::TargetAttrInterface attr) {
-  StringRef triple = attr.getTriple();
-  StringRef chipAKAcpu = attr.getChip();
-  StringRef features = attr.getFeatures() ? attr.getFeatures().getValue() : "";
-
-  std::string error;
-  const llvm::Target *target =
-      llvm::TargetRegistry::lookupTarget(triple, error);
-  if (!target || !error.empty()) {
-    LDBG("Looking up target '" << triple << "' failed: " << error << "\n");
-    return failure();
-  }
-
-  return std::unique_ptr<llvm::TargetMachine>(target->createTargetMachine(
-      llvm::Triple(triple), chipAKAcpu, features, {}, {}));
-}
-
-static FailureOr<llvm::DataLayout>
-getDataLayout(LLVM::TargetAttrInterface attr) {
-  FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
-      getTargetMachine(attr);
-  if (failed(targetMachine)) {
-    LDBG("Failed to retrieve the target machine for data layout.\n");
-    return failure();
-  }
-  return (targetMachine.value())->createDataLayout();
-}
-
 struct TargetToDataLayoutPass
     : public LLVM::impl::LLVMTargetToDataLayoutBase<TargetToDataLayoutPass> {
   using LLVM::impl::LLVMTargetToDataLayoutBase<
@@ -66,15 +30,8 @@ struct TargetToDataLayoutPass
   void runOnOperation() override {
     Operation *op = getOperation();
 
-    if (initializeLLVMTargets) {
-      static llvm::once_flag initializeBackendsOnce;
-      llvm::call_once(initializeBackendsOnce, []() {
-        // Ensure that the targets, that LLVM has been configured to support,
-        // are loaded into the TargetRegistry.
-        llvm::InitializeAllTargets();
-        llvm::InitializeAllTargetMCs();
-      });
-    }
+    if (initializeLLVMTargets)
+      LLVM::detail::initializeBackendsOnce();
 
     auto targetAttr = op->getAttrOfType<LLVM::TargetAttrInterface>(
         LLVM::LLVMDialect::getTargetAttrName());
@@ -85,7 +42,8 @@ struct TargetToDataLayoutPass
       return signalPassFailure();
     }
 
-    FailureOr<llvm::DataLayout> dataLayout = getDataLayout(targetAttr);
+    FailureOr<llvm::DataLayout> dataLayout =
+        LLVM::detail::getDataLayout(targetAttr);
     if (failed(dataLayout)) {
       op->emitError() << "failed to obtain llvm::DataLayout for " << targetAttr;
       return signalPassFailure();

diff  --git a/mlir/lib/Target/LLVMIR/Transforms/TargetToTargetFeatures.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetToTargetFeatures.cpp
new file mode 100644
index 0000000000000..4a1ca46af0f2a
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Transforms/TargetToTargetFeatures.cpp
@@ -0,0 +1,78 @@
+//===- TargetToTargetFeatures.cpp - extract features from TargetMachine ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Target/LLVMIR/Transforms/Passes.h"
+#include "mlir/Target/LLVMIR/Transforms/TargetUtils.h"
+
+#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Target/LLVMIR/Import.h"
+
+#include "llvm/MC/MCSubtargetInfo.h"
+
+namespace mlir {
+namespace LLVM {
+#define GEN_PASS_DEF_LLVMTARGETTOTARGETFEATURES
+#include "mlir/Target/LLVMIR/Transforms/Passes.h.inc"
+} // namespace LLVM
+} // namespace mlir
+
+using namespace mlir;
+
+struct TargetToTargetFeaturesPass
+    : public LLVM::impl::LLVMTargetToTargetFeaturesBase<
+          TargetToTargetFeaturesPass> {
+  using LLVM::impl::LLVMTargetToTargetFeaturesBase<
+      TargetToTargetFeaturesPass>::LLVMTargetToTargetFeaturesBase;
+
+  void runOnOperation() override {
+    Operation *op = getOperation();
+
+    if (initializeLLVMTargets)
+      LLVM::detail::initializeBackendsOnce();
+
+    auto targetAttr = op->getAttrOfType<LLVM::TargetAttr>(
+        LLVM::LLVMDialect::getTargetAttrName());
+    if (!targetAttr) {
+      op->emitError() << "no LLVM::TargetAttr attribute at key \""
+                      << LLVM::LLVMDialect::getTargetAttrName() << "\"";
+      return signalPassFailure();
+    }
+
+    FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
+        LLVM::detail::getTargetMachine(targetAttr);
+    if (failed(targetMachine)) {
+      op->emitError() << "failed to obtain llvm::TargetMachine for "
+                      << targetAttr;
+      return signalPassFailure();
+    }
+
+    llvm::MCSubtargetInfo const *subTargetInfo =
+        (*targetMachine)->getMCSubtargetInfo();
+
+    const std::vector<llvm::SubtargetFeatureKV> enabledFeatures =
+        subTargetInfo->getEnabledProcessorFeatures();
+
+    auto plussedFeatures = llvm::to_vector(
+        llvm::map_range(enabledFeatures, [](llvm::SubtargetFeatureKV feature) {
+          return std::string("+") + feature.Key;
+        }));
+
+    auto plussedFeaturesRefs = llvm::to_vector(llvm::map_range(
+        plussedFeatures, [](auto &it) { return StringRef(it.c_str()); }));
+
+    auto fullTargetFeaturesAttr =
+        LLVM::TargetFeaturesAttr::get(&getContext(), plussedFeaturesRefs);
+
+    auto updatedTargetAttr =
+        LLVM::TargetAttr::get(&getContext(), targetAttr.getTriple(),
+                              targetAttr.getChip(), fullTargetFeaturesAttr);
+
+    op->setAttr(LLVM::LLVMDialect::getTargetAttrName(), updatedTargetAttr);
+  }
+};

diff  --git a/mlir/lib/Target/LLVMIR/Transforms/TargetUtils.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetUtils.cpp
new file mode 100644
index 0000000000000..f1d36228bef1f
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Transforms/TargetUtils.cpp
@@ -0,0 +1,71 @@
+//===- TargetUtils.cpp - utils for obtaining generic target backend info --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Target/LLVMIR/Transforms/Passes.h"
+
+#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Target/LLVMIR/Import.h"
+
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/DebugLog.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+
+#define DEBUG_TYPE "mlir-llvm-target-utils"
+
+namespace mlir {
+namespace LLVM {
+namespace detail {
+void initializeBackendsOnce() {
+  static const auto initOnce = [] {
+    // Ensure that the targets, that LLVM has been configured to support,
+    // are loaded into the TargetRegistry.
+    llvm::InitializeAllTargets();
+    llvm::InitializeAllTargetMCs();
+    return true;
+  }();
+  (void)initOnce; // Dummy usage.
+}
+
+FailureOr<std::unique_ptr<llvm::TargetMachine>>
+getTargetMachine(mlir::LLVM::TargetAttrInterface attr) {
+  StringRef triple = attr.getTriple();
+  StringRef chipAKAcpu = attr.getChip();
+  // NB: `TargetAttrInterface::getFeatures()` is coarsely typed to work around
+  // cyclic dependency issue in tablegen files.
+  auto featuresAttr =
+      llvm::cast_if_present<LLVM::TargetFeaturesAttr>(attr.getFeatures());
+  std::string features = featuresAttr ? featuresAttr.getFeaturesString() : "";
+
+  std::string error;
+  const llvm::Target *target =
+      llvm::TargetRegistry::lookupTarget(triple, error);
+  if (!target || !error.empty()) {
+    LDBG() << "Looking up target '" << triple << "' failed: " << error << "\n";
+    return failure();
+  }
+
+  return std::unique_ptr<llvm::TargetMachine>(target->createTargetMachine(
+      llvm::Triple(triple), chipAKAcpu, features, {}, {}));
+}
+
+FailureOr<llvm::DataLayout>
+getDataLayout(mlir::LLVM::TargetAttrInterface attr) {
+  FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
+      getTargetMachine(attr);
+  if (failed(targetMachine)) {
+    LDBG() << "Failed to retrieve the target machine for data layout.\n";
+    return failure();
+  }
+  return (targetMachine.value())->createDataLayout();
+}
+
+} // namespace detail
+} // namespace LLVM
+} // namespace mlir

diff  --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir b/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir
deleted file mode 100644
index 45bfd6a465d7c..0000000000000
--- a/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir
+++ /dev/null
@@ -1,75 +0,0 @@
-// REQUIRES: target=x86{{.*}}
-// RUN: mlir-opt -llvm-target-to-data-layout -split-input-file %s | FileCheck %s
-
-// CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
-// CHECK-SAME:   "dlti.endianness" = "little"
-// CHECK-SAME: llvm.target = #llvm.target<
-// CHECK-SAME:   triple = "x86_64-unknown-linux"
-// CHECK-SAME:   chip = ""
-// CHECK-NOT:    features =
-
-module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
-                                               chip = ""> } {
-}
-
-// -----
-
-// CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
-// CHECK-SAME:   "dlti.endianness" = "little"
-// CHECK-SAME: llvm.target = #llvm.target<
-// CHECK-SAME:   triple = "x86_64-unknown-linux"
-// CHECK-SAME:   chip = ""
-// CHECK-SAME:   features = "+mmx,+sse"
-
-module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
-                                               chip = "",
-                                               features = "+mmx,+sse"> } {
-}
-
-// -----
-
-// CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
-// CHECK-SAME:   "dlti.endianness" = "little"
-// CHECK-SAME: llvm.target = #llvm.target<
-// CHECK-SAME:   triple = "x86_64-unknown-linux"
-// CHECK-SAME:   chip = "skylake"
-// CHECK-NOT:    features =
-
-module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
-                                               chip = "skylake"> } {
-}
-
-// -----
-
-// CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
-// CHECK-SAME:   "dlti.endianness" = "little"
-// CHECK-SAME: llvm.target = #llvm.target<
-// CHECK-SAME:   triple = "x86_64-unknown-linux"
-// CHECK-SAME:   chip = "skylake"
-// CHECK-SAME:   features = "+mmx,+sse">
-
-module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
-                                               chip = "skylake",
-                                               features = "+mmx,+sse"> } {
-}
-
-// -----
-
-// CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
-// CHECK-SAME:   "dlti.endianness" = "little"
-// CHECK-SAME:   index = 32
-// CHECK-SAME: llvm.target = #llvm.target<
-// CHECK-SAME:   triple = "x86_64-unknown-linux"
-// CHECK-SAME:   chip = "skylake"
-// CHECK-SAME:   features = "+mmx,+sse"
-
-module attributes { dlti.dl_spec = #dlti.dl_spec<index = 32>,
-                    llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
-                                               chip = "skylake",
-                                               features = "+mmx,+sse"> } {
-}

diff  --git a/mlir/test/Target/LLVMIR/target-to-data-layout-and-target-features.mlir b/mlir/test/Target/LLVMIR/target-to-data-layout-and-target-features.mlir
new file mode 100644
index 0000000000000..b6b2976860541
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/target-to-data-layout-and-target-features.mlir
@@ -0,0 +1,137 @@
+// REQUIRES: target=x86{{.*}}
+
+// RUN: mlir-opt -llvm-target-to-data-layout -split-input-file %s | FileCheck --check-prefix=DATA-LAYOUT %s
+// RUN: mlir-opt -llvm-target-to-target-features -split-input-file %s | FileCheck --check-prefix=TARGET-FEATURES %s
+
+// DATA-LAYOUT: module attributes
+// DATA-LAYOUT-SAME: dlti.dl_spec = #dlti.dl_spec
+// DATA-LAYOUT-SAME:   "dlti.endianness" = "little"
+// DATA-LAYOUT-SAME: llvm.target = #llvm.target<
+// DATA-LAYOUT-SAME:   triple = "x86_64-unknown-linux"
+// DATA-LAYOUT-SAME:   chip = ""
+// DATA-LAYOUT-NOT:    features =
+
+// TARGET-FEATURES: module attributes
+// TARGET-FEATURES-NOT:  dlti.dl_spec
+// TARGET-FEATURES-SAME: llvm.target = #llvm.target<
+// TARGET-FEATURES-SAME:   triple = "x86_64-unknown-linux"
+// TARGET-FEATURES-SAME:   chip = ""
+// TARGET-FEATURES-SAME:   features = <[
+// TARGET-FEATURES-SAME:     +64bit
+// TARGET-FEATURES-NOT:      +avx
+// TARGET-FEATURES-SAME:     +sse
+// TARGET-FEATURES-NOT:      +mmx
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = ""> } {
+}
+
+// -----
+
+// DATA-LAYOUT: module attributes
+// DATA-LAYOUT-SAME: dlti.dl_spec = #dlti.dl_spec
+// DATA-LAYOUT-SAME:   "dlti.endianness" = "little"
+// DATA-LAYOUT-SAME: llvm.target = #llvm.target<
+// DATA-LAYOUT-SAME:   triple = "x86_64-unknown-linux"
+// DATA-LAYOUT-SAME:   chip = ""
+// DATA-LAYOUT-SAME:   features = <["+mmx", "+sse"]>
+
+// TARGET-FEATURES: module attributes
+// TARGET-FEATURES-NOT:  dlti.dl_spec
+// TARGET-FEATURES-SAME: llvm.target = #llvm.target<
+// TARGET-FEATURES-SAME:   triple = "x86_64-unknown-linux"
+// TARGET-FEATURES-SAME:   chip = ""
+// TARGET-FEATURES-SAME:   features = <[
+// TARGET-FEATURES-SAME:     +64bit
+// TARGET-FEATURES-NOT:      +avx
+// TARGET-FEATURES-SAME:     +mmx
+// TARGET-FEATURES-SAME:     +sse
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "",
+                                               features = <["+mmx", "+sse"]>> } {
+}
+
+// -----
+
+// DATA-LAYOUT: module attributes
+// DATA-LAYOUT-SAME: dlti.dl_spec = #dlti.dl_spec
+// DATA-LAYOUT-SAME:   "dlti.endianness" = "little"
+// DATA-LAYOUT-SAME: llvm.target = #llvm.target<
+// DATA-LAYOUT-SAME:   triple = "x86_64-unknown-linux"
+// DATA-LAYOUT-SAME:   chip = "skylake"
+// DATA-LAYOUT-NOT:    features =
+
+// TARGET-FEATURES: module attributes
+// TARGET-FEATURES-NOT:  dlti.dl_spec
+// TARGET-FEATURES-SAME: llvm.target = #llvm.target<
+// TARGET-FEATURES-SAME:   triple = "x86_64-unknown-linux"
+// TARGET-FEATURES-SAME:   chip = "skylake"
+// TARGET-FEATURES-SAME:   features = <[
+// TARGET-FEATURES-SAME:     +64bit
+// TARGET-FEATURES-SAME:     +avx
+// TARGET-FEATURES-SAME:     +avx2
+// TARGET-FEATURES-NOT:      +avx512f
+// TARGET-FEATURES-SAME:     +mmx
+// TARGET-FEATURES-SAME:     +sse
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "skylake"> } {
+}
+
+// -----
+
+// DATA-LAYOUT: module attributes
+// DATA-LAYOUT-SAME: dlti.dl_spec = #dlti.dl_spec
+// DATA-LAYOUT-SAME:   "dlti.endianness" = "little"
+// DATA-LAYOUT-SAME: llvm.target = #llvm.target<
+// DATA-LAYOUT-SAME:   triple = "x86_64-unknown-linux"
+// DATA-LAYOUT-SAME:   chip = "skylake"
+// DATA-LAYOUT-SAME:   features = <["-sse", "-avx"]>
+
+// TARGET-FEATURES: module attributes
+// TARGET-FEATURES-NOT:  dlti.dl_spec
+// TARGET-FEATURES-SAME: llvm.target = #llvm.target<
+// TARGET-FEATURES-SAME:   triple = "x86_64-unknown-linux"
+// TARGET-FEATURES-SAME:   chip = "skylake"
+// TARGET-FEATURES-SAME:   features = <[
+// TARGET-FEATURES-SAME:     +64bit
+// TARGET-FEATURES-NOT:      +avx
+// TARGET-FEATURES-NOT:      +avx2
+// TARGET-FEATURES-SAME:     +mmx
+// TARGET-FEATURES-NOT:      +sse
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "skylake",
+                                               features = <["-sse", "-avx"]>> } {
+}
+
+// -----
+
+// DATA-LAYOUT: module attributes
+// DATA-LAYOUT-SAME: dlti.dl_spec = #dlti.dl_spec
+// DATA-LAYOUT-SAME:   "dlti.endianness" = "little"
+// DATA-LAYOUT-SAME:   index = 32
+// DATA-LAYOUT-SAME: llvm.target = #llvm.target<
+// DATA-LAYOUT-SAME:   triple = "x86_64-unknown-linux"
+// DATA-LAYOUT-SAME:   chip = "skylake"
+// DATA-LAYOUT-SAME:   features = <["-mmx", "+avx512f"]>
+
+// TARGET-FEATURES: module attributes
+// TARGET-FEATURES-SAME: #dlti.dl_spec<index = 32 : i64>
+// TARGET-FEATURES-SAME: llvm.target = #llvm.target<
+// TARGET-FEATURES-SAME:   triple = "x86_64-unknown-linux"
+// TARGET-FEATURES-SAME:   chip = "skylake"
+// TARGET-FEATURES-SAME:   features = <[
+// TARGET-FEATURES-SAME:     +64bit
+// TARGET-FEATURES-SAME:     +avx
+// TARGET-FEATURES-SAME:     +avx2
+// TARGET-FEATURES-SAME:     +avx512f
+// TARGET-FEATURES-NOT:      +mmx
+// TARGET-FEATURES-SAME:     +sse
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<index = 32>,
+                    llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "skylake",
+                                               features = <["-mmx", "+avx512f"]>> } {
+}

diff  --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir b/mlir/test/Target/LLVMIR/target-to-data-layout-invalid.mlir
similarity index 100%
rename from mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir
rename to mlir/test/Target/LLVMIR/target-to-data-layout-invalid.mlir

diff  --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir b/mlir/test/Target/LLVMIR/target-to-data-layout-no-init.mlir
similarity index 100%
rename from mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir
rename to mlir/test/Target/LLVMIR/target-to-data-layout-no-init.mlir

diff  --git a/mlir/test/Target/LLVMIR/target-to-target-features-dlti-query.mlir b/mlir/test/Target/LLVMIR/target-to-target-features-dlti-query.mlir
new file mode 100644
index 0000000000000..9a1f49b0bca80
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/target-to-target-features-dlti-query.mlir
@@ -0,0 +1,75 @@
+// REQUIRES: target=x86{{.*}}
+
+// RUN: mlir-opt -transform-interpreter -split-input-file %s --verify-diagnostics
+
+// Check that processor features, like AVX, are appropriated derived and queryable.
+
+// expected-remark @+2 {{attr associated to ["features", "+avx"] = unit}}
+// expected-remark @below {{attr associated to ["features", "avx"] = true}}
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "skylake">,
+                    test.dl_spec = #dlti.dl_spec<index = 32> } {
+  func.func private @f()
+}
+
+module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%arg: !transform.any_op) {
+    %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op
+    %module = transform.get_parent_op %funcs : (!transform.any_op) -> !transform.any_op
+    %mod = transform.apply_registered_pass "llvm-target-to-target-features" to %module : (!transform.any_op) -> !transform.any_op
+    %plus_avx = transform.dlti.query ["features", "+avx"] at %mod : (!transform.any_op) -> !transform.any_param
+    transform.debug.emit_param_as_remark %plus_avx, "attr associated to [\"features\", \"+avx\"] =" at %mod : !transform.any_param, !transform.any_op
+    %avx = transform.dlti.query ["features", "avx"] at %mod : (!transform.any_op) -> !transform.any_param
+    transform.debug.emit_param_as_remark %avx, "attr associated to [\"features\", \"avx\"] =" at %mod : !transform.any_param, !transform.any_op
+    transform.yield
+  }
+}
+
+// -----
+
+// Check that newer processor features, like AMX, are appropriated derived and queryable.
+
+// expected-remark @+2 {{attr associated to ["features", "+amx-bf16"] = unit}}
+// expected-remark @below {{attr associated to ["features", "amx-bf16"] = true}}
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "sapphirerapids">,
+                    test.dl_spec = #dlti.dl_spec<index = 32> } {
+  func.func private @f()
+}
+
+module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%arg: !transform.any_op) {
+    %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op
+    %module = transform.get_parent_op %funcs : (!transform.any_op) -> !transform.any_op
+    %mod = transform.apply_registered_pass "llvm-target-to-target-features" to %module : (!transform.any_op) -> !transform.any_op
+    %plus_avx = transform.dlti.query ["features", "+amx-bf16"] at %mod : (!transform.any_op) -> !transform.any_param
+    transform.debug.emit_param_as_remark %plus_avx, "attr associated to [\"features\", \"+amx-bf16\"] =" at %mod : !transform.any_param, !transform.any_op
+    %avx = transform.dlti.query ["features", "amx-bf16"] at %mod : (!transform.any_op) -> !transform.any_param
+    transform.debug.emit_param_as_remark %avx, "attr associated to [\"features\", \"amx-bf16\"] =" at %mod : !transform.any_param, !transform.any_op
+    transform.yield
+  }
+}
+
+// -----
+
+// Check that features that a processor does not have, AMX in this case,
+// aren't derived and hence that querying for them will fail.
+
+// expected-error @+2 {{target op of failed DLTI query}}
+// expected-note @below {{key "+amx-bf16" has no DLTI-mapping per attr: #llvm.target_features}}
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "skylake">,
+                    test.dl_spec = #dlti.dl_spec<index = 32> } {
+  func.func private @f()
+}
+
+module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%arg: !transform.any_op) {
+    %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op
+    %module = transform.get_parent_op %funcs : (!transform.any_op) -> !transform.any_op
+    %mod = transform.apply_registered_pass "llvm-target-to-target-features" to %module : (!transform.any_op) -> !transform.any_op
+    // expected-error @below {{'transform.dlti.query' op failed to apply}}
+    %param = transform.dlti.query ["features", "+amx-bf16"] at %mod : (!transform.any_op) -> !transform.any_param
+    transform.yield
+  }
+}


        


More information about the Mlir-commits mailing list