[llvm] [DXIL][Analysis] Collect Function properties in Metadata Analysis (PR #105728)

S. Bharadwaj Yadavalli via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 27 15:12:53 PDT 2024


https://github.com/bharadwajy updated https://github.com/llvm/llvm-project/pull/105728

>From 04400db2d84e46adea7e1bc12755fb74a62c228c Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Wed, 21 Aug 2024 15:35:17 -0400
Subject: [PATCH 1/3] [DXIL][Analysis] Infrastructure to collect Function
 properties in Metadata Analysis - Add a map of function-function properties
 to the metadata information. - Add a structure to represent various function
 properties. Currently   numthreads property of a compute shader entry
 function is represented.

---
 .../llvm/Analysis/DXILMetadataAnalysis.h      |  7 ++-
 llvm/lib/Analysis/DXILMetadataAnalysis.cpp    | 50 +++++++++++++++++++
 .../CodeGen/DirectX/Metadata/dxilVer-1.8.ll   |  2 +
 .../Metadata/shaderModel-cs-val-ver-0.0.ll    |  4 +-
 .../DirectX/Metadata/shaderModel-cs.ll        |  2 +
 5 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h b/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h
index 0515139c01aee6..6195ac08b0e99c 100644
--- a/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h
+++ b/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_ANALYSIS_DXILMETADATA_H
 #define LLVM_ANALYSIS_DXILMETADATA_H
 
+#include "llvm/IR/Function.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/VersionTuple.h"
@@ -19,12 +20,16 @@ namespace llvm {
 
 namespace dxil {
 
+struct FunctionProperties {
+  unsigned NumThreads[3];
+};
+
 struct ModuleMetadataInfo {
   VersionTuple DXILVersion{};
   VersionTuple ShaderModelVersion{};
   Triple::EnvironmentType ShaderStage = Triple::UnknownEnvironment;
   VersionTuple ValidatorVersion{};
-
+  std::unordered_map<Function *, FunctionProperties> FunctionPropertyMap{};
   void print(raw_ostream &OS) const;
 };
 
diff --git a/llvm/lib/Analysis/DXILMetadataAnalysis.cpp b/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
index 192e151565370d..39bd750d69649b 100644
--- a/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
+++ b/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
@@ -8,11 +8,16 @@
 
 #include "llvm/Analysis/DXILMetadataAnalysis.h"
 #include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
 #include "llvm/InitializePasses.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <memory>
+#include <utility>
 
 #define DEBUG_TYPE "dxil-metadata-analysis"
 
@@ -33,6 +38,37 @@ static ModuleMetadataInfo collectMetadataInfo(Module &M) {
     MMDAI.ValidatorVersion =
         VersionTuple(MajorMD->getZExtValue(), MinorMD->getZExtValue());
   }
+
+  if (MMDAI.ShaderStage == Triple::EnvironmentType::Compute) {
+    // For all HLSL Shader functions
+    for (auto &F : M.functions()) {
+      if (!F.hasFnAttribute("hlsl.shader"))
+        continue;
+
+      // Get numthreads attribute value
+      StringRef NumThreadsStr =
+          F.getFnAttribute("hlsl.numthreads").getValueAsString();
+      SmallVector<StringRef> NumThreadsVec;
+      NumThreadsStr.split(NumThreadsVec, ',');
+      if (NumThreadsVec.size() != 3) {
+        report_fatal_error(Twine(F.getName()) +
+                               ": Invalid numthreads specified",
+                           /* gen_crash_diag */ false);
+      }
+      FunctionProperties EFP;
+      auto Zip =
+          llvm::zip(NumThreadsVec, MutableArrayRef<unsigned>(EFP.NumThreads));
+      for (auto It : Zip) {
+        StringRef Str = std::get<0>(It);
+        APInt V;
+        assert(!Str.getAsInteger(10, V) &&
+               "Failed to parse numthreads components as integer values");
+        unsigned &Num = std::get<1>(It);
+        Num = V.getLimitedValue();
+      }
+      MMDAI.FunctionPropertyMap.emplace(std::make_pair(std::addressof(F), EFP));
+    }
+  }
   return MMDAI;
 }
 
@@ -42,6 +78,20 @@ void ModuleMetadataInfo::print(raw_ostream &OS) const {
   OS << "Shader Stage : " << Triple::getEnvironmentTypeName(ShaderStage)
      << "\n";
   OS << "Validator Version : " << ValidatorVersion.getAsString() << "\n";
+  for (auto MapItem : FunctionPropertyMap) {
+    MapItem.first->getReturnType()->print(OS, false, true);
+    OS << " " << MapItem.first->getName() << "(";
+    FunctionType *FT = MapItem.first->getFunctionType();
+    for (unsigned I = 0, Sz = FT->getNumParams(); I < Sz; ++I) {
+      if (I)
+        OS << ",";
+      FT->getParamType(I)->print(OS);
+    }
+    OS << ")\n";
+    OS << "  NumThreads: " << MapItem.second.NumThreads[0] << ","
+       << MapItem.second.NumThreads[1] << "," << MapItem.second.NumThreads[2]
+       << "\n";
+  }
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll
index 53edcde24b189f..d429b6534e4253 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll
@@ -9,6 +9,8 @@ target triple = "dxil-pc-shadermodel6.8-compute"
 ; ANALYSIS-NEXT: DXIL Version : 1.8
 ; ANALYSIS-NEXT: Shader Stage : compute
 ; ANALYSIS-NEXT: Validator Version : 0
+; ANALYSIS-NEXT: void entry()
+; ANALYSIS-NEXT: NumThreads: 1,2,1
 ; ANALYSIS-EMPTY:
 
 define void @entry() #0 {
diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs-val-ver-0.0.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs-val-ver-0.0.ll
index c9ea6c94e36519..b7e6d2fd3cf432 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs-val-ver-0.0.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs-val-ver-0.0.ll
@@ -19,5 +19,7 @@ attributes #0 = { noinline nounwind "exp-shader"="cs" "hlsl.numthreads"="1,2,1"
 ; ANALYSIS: Shader Model Version : 6.6
 ; ANALYSIS-NEXT: DXIL Version : 1.6
 ; ANALYSIS-NEXT: Shader Stage : compute
-; ANALYSIS-NEXT: Validator Version : 0
+; ANALYSIS-NEXT: Validator Version : 0.0
+; ANALYSIS-NEXT: void entry()
+; ANALYSIS-NEXT:   NumThreads: 1,2,1
 ; ANALYSIS-EMPTY:
diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs.ll
index f5e524562ac1e0..77b52ee3478abe 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs.ll
@@ -11,6 +11,8 @@ target triple = "dxil-pc-shadermodel6.6-compute"
 ; ANALYSIS-NEXT: DXIL Version : 1.6
 ; ANALYSIS-NEXT: Shader Stage : compute
 ; ANALYSIS-NEXT: Validator Version : 0
+; ANALYSIS-NEXT: void entry()
+; ANALYSIS-NEXT:   NumThreads: 1,2,1
 ; ANALYSIS-EMPTY:
 
 define void @entry() #0 {

>From 92ffbbb63c1d5599cf7b696c270c49654270ed09 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Tue, 27 Aug 2024 17:58:58 -0400
Subject: [PATCH 2/3] Improvements to entry function information collected in
 Metadata Analysis Pass - Record shader kind specified for entry function from
 hlsl.shader attribute - Record all entry functions irrespective of the target
 shader profile being compute - Update expected output of tests accordingly

---
 .../llvm/Analysis/DXILMetadataAnalysis.h      |  2 +
 llvm/lib/Analysis/DXILMetadataAnalysis.cpp    | 45 ++++++++++---------
 .../CodeGen/DirectX/Metadata/dxilVer-1.0.ll   |  2 +
 .../DirectX/Metadata/shaderModel-as.ll        |  2 +
 .../DirectX/Metadata/shaderModel-gs.ll        |  2 +
 .../DirectX/Metadata/shaderModel-hs.ll        |  2 +
 .../DirectX/Metadata/shaderModel-ms.ll        |  2 +
 .../DirectX/Metadata/shaderModel-ps.ll        |  2 +
 .../DirectX/Metadata/shaderModel-vs.ll        |  2 +
 9 files changed, 41 insertions(+), 20 deletions(-)

diff --git a/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h b/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h
index 6195ac08b0e99c..2277f0153f7fca 100644
--- a/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h
+++ b/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h
@@ -21,6 +21,8 @@ namespace llvm {
 namespace dxil {
 
 struct FunctionProperties {
+  // Specific target shader stage may be specified for entry functions
+  Triple::EnvironmentType ShaderStage = Triple::UnknownEnvironment;
   unsigned NumThreads[3];
 };
 
diff --git a/llvm/lib/Analysis/DXILMetadataAnalysis.cpp b/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
index 39bd750d69649b..9d8fa2fa482e3a 100644
--- a/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
+++ b/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
@@ -39,36 +39,41 @@ static ModuleMetadataInfo collectMetadataInfo(Module &M) {
         VersionTuple(MajorMD->getZExtValue(), MinorMD->getZExtValue());
   }
 
-  if (MMDAI.ShaderStage == Triple::EnvironmentType::Compute) {
     // For all HLSL Shader functions
     for (auto &F : M.functions()) {
       if (!F.hasFnAttribute("hlsl.shader"))
         continue;
 
-      // Get numthreads attribute value
+      FunctionProperties EFP{};
+      // Get "hlsl.shader" attribute
+      Attribute EntryAttr = F.getFnAttribute("hlsl.shader");
+      StringRef EntryProfile = EntryAttr.getValueAsString();
+      Triple T("", "", "", EntryProfile);
+      EFP.ShaderStage = T.getEnvironment();
+      // Get numthreads attribute value, if one exists
       StringRef NumThreadsStr =
           F.getFnAttribute("hlsl.numthreads").getValueAsString();
-      SmallVector<StringRef> NumThreadsVec;
-      NumThreadsStr.split(NumThreadsVec, ',');
-      if (NumThreadsVec.size() != 3) {
-        report_fatal_error(Twine(F.getName()) +
-                               ": Invalid numthreads specified",
-                           /* gen_crash_diag */ false);
-      }
-      FunctionProperties EFP;
-      auto Zip =
-          llvm::zip(NumThreadsVec, MutableArrayRef<unsigned>(EFP.NumThreads));
-      for (auto It : Zip) {
-        StringRef Str = std::get<0>(It);
-        APInt V;
-        assert(!Str.getAsInteger(10, V) &&
-               "Failed to parse numthreads components as integer values");
-        unsigned &Num = std::get<1>(It);
-        Num = V.getLimitedValue();
+      if (!NumThreadsStr.empty()) {
+        SmallVector<StringRef> NumThreadsVec;
+        NumThreadsStr.split(NumThreadsVec, ',');
+        if (NumThreadsVec.size() != 3) {
+          report_fatal_error(Twine(F.getName()) +
+                                 ": Invalid numthreads specified",
+                             /* gen_crash_diag */ false);
+        }
+        auto Zip =
+            llvm::zip(NumThreadsVec, MutableArrayRef<unsigned>(EFP.NumThreads));
+        for (auto It : Zip) {
+          StringRef Str = std::get<0>(It);
+          APInt V;
+          assert(!Str.getAsInteger(10, V) &&
+                 "Failed to parse numthreads components as integer values");
+          unsigned &Num = std::get<1>(It);
+          Num = V.getLimitedValue();
+        }
       }
       MMDAI.FunctionPropertyMap.emplace(std::make_pair(std::addressof(F), EFP));
     }
-  }
   return MMDAI;
 }
 
diff --git a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll
index 30797945e8e56c..fc076d675e994a 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll
@@ -9,6 +9,8 @@ target triple = "dxil-pc-shadermodel6.0-vertex"
 ; ANALYSIS-NEXT: DXIL Version : 1.0
 ; ANALYSIS-NEXT: Shader Stage : vertex
 ; ANALYSIS-NEXT: Validator Version : 0
+; ANALYSIS-NEXT: void entry()
+; ANALYSIS-NEXT: 0,0,0
 ; ANALYSIS-EMPTY:
 
 define void @entry() #0 {
diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-as.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-as.ll
index 49c820e14e36b4..618079af215396 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-as.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-as.ll
@@ -9,6 +9,8 @@ target triple = "dxil-pc-shadermodel6-amplification"
 ; ANALYSIS-NEXT: DXIL Version : 1.0
 ; ANALYSIS-NEXT: Shader Stage : amplification
 ; ANALYSIS-NEXT: Validator Version : 0
+; ANALYSIS-NEXT: void entry()
+; ANALYSIS-NEXT: 0,0,0
 ; ANALYSIS-EMPTY:
 
 define void @entry() #0 {
diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-gs.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-gs.ll
index fb58312e2c9310..22df8350ed4ad0 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-gs.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-gs.ll
@@ -9,6 +9,8 @@ target triple = "dxil-pc-shadermodel6.6-geometry"
 ; ANALYSIS-NEXT: DXIL Version : 1.6
 ; ANALYSIS-NEXT: Shader Stage : geometry
 ; ANALYSIS-NEXT: Validator Version : 0
+; ANALYSIS-NEXT: void entry()
+; ANALYSIS-NEXT: 0,0,0
 ; ANALYSIS-EMPTY:
 
 define void @entry() #0 {
diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-hs.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-hs.ll
index b12de400698fe1..5237094931b51a 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-hs.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-hs.ll
@@ -9,6 +9,8 @@ target triple = "dxil-pc-shadermodel6.6-hull"
 ; ANALYSIS-NEXT: DXIL Version : 1.6
 ; ANALYSIS-NEXT: Shader Stage : hull
 ; ANALYSIS-NEXT: Validator Version : 0
+; ANALYSIS-NEXT: void entry()
+; ANALYSIS-NEXT: 0,0,0
 ; ANALYSIS-EMPTY:
 
 define void @entry() #0 {
diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ms.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ms.ll
index e22dbbcebf5849..d8f4cc578227cc 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ms.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ms.ll
@@ -9,6 +9,8 @@ target triple = "dxil-pc-shadermodel6.6-mesh"
 ; ANALYSIS-NEXT: DXIL Version : 1.6
 ; ANALYSIS-NEXT: Shader Stage : mesh
 ; ANALYSIS-NEXT: Validator Version : 0
+; ANALYSIS-NEXT: void entry()
+; ANALYSIS-NEXT: 0,0,0
 ; ANALYSIS-EMPTY:
 
 define void @entry() #0 {
diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ps.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ps.ll
index eb784d71517bba..20ec0b01df6d4c 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ps.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ps.ll
@@ -9,6 +9,8 @@ target triple = "dxil-pc-shadermodel5.0-pixel"
 ; ANALYSIS-NEXT: DXIL Version : 1.0
 ; ANALYSIS-NEXT: Shader Stage : pixel
 ; ANALYSIS-NEXT: Validator Version : 0
+; ANALYSIS-NEXT: void entry()
+; ANALYSIS-NEXT: 0,0,0
 ; ANALYSIS-EMPTY:
 
 define void @entry() #0 {
diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-vs.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-vs.ll
index ac52b5004eb906..e4f32775e28cbb 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-vs.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-vs.ll
@@ -9,6 +9,8 @@ target triple = "dxil-pc-shadermodel-vertex"
 ; ANALYSIS-NEXT: DXIL Version : 1.0
 ; ANALYSIS-NEXT: Shader Stage : vertex
 ; ANALYSIS-NEXT: Validator Version : 0
+; ANALYSIS-NEXT: void entry()
+; ANALYSIS-NEXT: 0,0,0
 ; ANALYSIS-EMPTY:
 
 define void @entry() #0 {

>From c067683a47d66117ac321813e365433b38d941a0 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Tue, 27 Aug 2024 18:11:29 -0400
Subject: [PATCH 3/3] clang-format

---
 llvm/lib/Analysis/DXILMetadataAnalysis.cpp | 66 +++++++++++-----------
 1 file changed, 33 insertions(+), 33 deletions(-)

diff --git a/llvm/lib/Analysis/DXILMetadataAnalysis.cpp b/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
index 9d8fa2fa482e3a..7577097f751275 100644
--- a/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
+++ b/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
@@ -39,41 +39,41 @@ static ModuleMetadataInfo collectMetadataInfo(Module &M) {
         VersionTuple(MajorMD->getZExtValue(), MinorMD->getZExtValue());
   }
 
-    // For all HLSL Shader functions
-    for (auto &F : M.functions()) {
-      if (!F.hasFnAttribute("hlsl.shader"))
-        continue;
-
-      FunctionProperties EFP{};
-      // Get "hlsl.shader" attribute
-      Attribute EntryAttr = F.getFnAttribute("hlsl.shader");
-      StringRef EntryProfile = EntryAttr.getValueAsString();
-      Triple T("", "", "", EntryProfile);
-      EFP.ShaderStage = T.getEnvironment();
-      // Get numthreads attribute value, if one exists
-      StringRef NumThreadsStr =
-          F.getFnAttribute("hlsl.numthreads").getValueAsString();
-      if (!NumThreadsStr.empty()) {
-        SmallVector<StringRef> NumThreadsVec;
-        NumThreadsStr.split(NumThreadsVec, ',');
-        if (NumThreadsVec.size() != 3) {
-          report_fatal_error(Twine(F.getName()) +
-                                 ": Invalid numthreads specified",
-                             /* gen_crash_diag */ false);
-        }
-        auto Zip =
-            llvm::zip(NumThreadsVec, MutableArrayRef<unsigned>(EFP.NumThreads));
-        for (auto It : Zip) {
-          StringRef Str = std::get<0>(It);
-          APInt V;
-          assert(!Str.getAsInteger(10, V) &&
-                 "Failed to parse numthreads components as integer values");
-          unsigned &Num = std::get<1>(It);
-          Num = V.getLimitedValue();
-        }
+  // For all HLSL Shader functions
+  for (auto &F : M.functions()) {
+    if (!F.hasFnAttribute("hlsl.shader"))
+      continue;
+
+    FunctionProperties EFP{};
+    // Get "hlsl.shader" attribute
+    Attribute EntryAttr = F.getFnAttribute("hlsl.shader");
+    StringRef EntryProfile = EntryAttr.getValueAsString();
+    Triple T("", "", "", EntryProfile);
+    EFP.ShaderStage = T.getEnvironment();
+    // Get numthreads attribute value, if one exists
+    StringRef NumThreadsStr =
+        F.getFnAttribute("hlsl.numthreads").getValueAsString();
+    if (!NumThreadsStr.empty()) {
+      SmallVector<StringRef> NumThreadsVec;
+      NumThreadsStr.split(NumThreadsVec, ',');
+      if (NumThreadsVec.size() != 3) {
+        report_fatal_error(Twine(F.getName()) +
+                               ": Invalid numthreads specified",
+                           /* gen_crash_diag */ false);
+      }
+      auto Zip =
+          llvm::zip(NumThreadsVec, MutableArrayRef<unsigned>(EFP.NumThreads));
+      for (auto It : Zip) {
+        StringRef Str = std::get<0>(It);
+        APInt V;
+        assert(!Str.getAsInteger(10, V) &&
+               "Failed to parse numthreads components as integer values");
+        unsigned &Num = std::get<1>(It);
+        Num = V.getLimitedValue();
       }
-      MMDAI.FunctionPropertyMap.emplace(std::make_pair(std::addressof(F), EFP));
     }
+    MMDAI.FunctionPropertyMap.emplace(std::make_pair(std::addressof(F), EFP));
+  }
   return MMDAI;
 }
 



More information about the llvm-commits mailing list