[llvm] [DXIL][ShaderFlags] Add analysis for WaveOps flag (PR #118140)

Finn Plummer via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 22 15:12:32 PST 2025


https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/118140

>From 77b5bf1aa75dbe414916c0b06cb3af67bcf0d73b Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 22 Jan 2025 23:07:12 +0000
Subject: [PATCH 1/3] [NFC] Create emitBoolTable common function

- We want to emit a table of bools that denotes which
attributes/properties are set, so move it a common function
---
 llvm/utils/TableGen/DXILEmitter.cpp | 43 +++++++++++++++++------------
 1 file changed, 25 insertions(+), 18 deletions(-)

diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp
index 70f2aa65226401..223462538c0fd2 100644
--- a/llvm/utils/TableGen/DXILEmitter.cpp
+++ b/llvm/utils/TableGen/DXILEmitter.cpp
@@ -372,16 +372,31 @@ static void emitDXILAttributes(const RecordKeeper &Records, raw_ostream &OS) {
   OS << "#endif\n\n";
 }
 
-// Helper function to determine if the given Attr is defined in the vector
-// Attrs, by comparing the names
-static bool attrIsDefined(std::vector<const Record *> Attrs,
-                          const Record *Attr) {
-  for (auto CurAttr : Attrs)
-    if (CurAttr->getName() == Attr->getName())
+// Helper function to determine if Recs contains Rec
+static bool containsRec(ArrayRef<const Record *> Recs, const Record *Rec) {
+  for (auto CurRec : Recs)
+    if (CurRec->getName() == Rec->getName())
       return true;
   return false;
 }
 
+// Iterate through AllRecords and output 'true' if there is a Rec with the same name in
+// CurRecords, output all others as 'false' to create a boolean table.
+// Eg)
+// In:
+//   CurRecords->getName() = {"Cat"}
+//   DefinedRecords->getName() = {"Dog", "Cat", "Cow"}
+// Out:
+//   false, true, false
+static void emitBoolTable(ArrayRef<const Record *> CurRecords, ArrayRef<const Record *> AllRecords, raw_ostream &OS) {
+  for (const Record *Rec : AllRecords) {
+    std::string HasRec = ", false";
+    if (containsRec(CurRecords, Rec))
+      HasRec = ", true";
+    OS << HasRec;
+  }
+}
+
 /// Emit a table of bools denoting a DXIL op's function attributes
 static void emitDXILOpAttributes(const RecordKeeper &Records,
                                  ArrayRef<DXILOperationDesc> Ops,
@@ -393,6 +408,7 @@ static void emitDXILOpAttributes(const RecordKeeper &Records,
   //
   //     OpName, VersionMajor, VersionMinor, FnAttr1, FnAttr2, ...
   // Eg)    Abs,            1,            0,    true,   false, ...
+  auto DefinedAttrs = Records.getAllDerivedDefinitions("DXILAttribute");
   OS << "#ifdef DXIL_OP_ATTRIBUTES\n";
   for (const auto &Op : Ops) {
     for (const auto *Rec : Op.AttrRecs) {
@@ -402,18 +418,9 @@ static void emitDXILOpAttributes(const RecordKeeper &Records,
           Rec->getValueAsDef("dxil_version")->getValueAsInt("Minor");
       OS << "DXIL_OP_ATTRIBUTES(dxil::OpCode::" << Op.OpName << ", ";
       OS << std::to_string(Major) << ", " << std::to_string(Minor);
-      // These Attrs are the ones set for above DXIL version
-      auto Attrs = Rec->getValueAsListOfDefs("fn_attrs");
-      // We will then iteratre through all possible attributes and mark the
-      // present ones as 'true' and all the others as 'false' to create the
-      // boolean table, eg) true, false, false, false
-      for (const Record *Attr :
-           Records.getAllDerivedDefinitions("DXILAttribute")) {
-        std::string HasAttr = ", false";
-        if (attrIsDefined(Attrs, Attr))
-          HasAttr = ", true";
-        OS << HasAttr;
-      }
+      // These Attrs are the ones set for on an op with the above DXIL version
+      auto OpAttrs = Rec->getValueAsListOfDefs("fn_attrs");
+      emitBoolTable(OpAttrs, DefinedAttrs, OS);
       OS << ")\n";
     }
   }

>From dc27c2d2c92743fdde43bf7e9c1c8668a7d2ff70 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 22 Jan 2025 23:11:24 +0000
Subject: [PATCH 2/3] [DirectX][ShaderFlags] Add analysis for `WaveOps` flag

- Add emitDXILOpProperties to build boolean tables of which ops hold
which properties into `DXILEmitter.cpp`
- Check each call instruction to see if it invokes an intrinsic that is
marked as IsWave, and set the WaveOps flag if this is true for any
intrinsics. Done in DXILShaderFlags.cpp
---
 llvm/lib/Target/DirectX/DXILShaderFlags.cpp | 22 +++++++++++++++++++++
 llvm/utils/TableGen/DXILEmitter.cpp         | 16 +++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index 6a15bac153d857..e4632643e5577b 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -11,6 +11,7 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "DXILConstants.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
 #include "llvm/ADT/SCCIterator.h"
@@ -30,6 +31,25 @@
 using namespace llvm;
 using namespace llvm::dxil;
 
+static dxil::Properties getOpCodeProperties(dxil::OpCode OpCode) {
+  dxil::Properties Props;
+  switch (OpCode) {
+#define DXIL_OP_PROPERTIES(OpCode, ...) \
+  case OpCode: Props = dxil::Properties{__VA_ARGS__}; break;
+#include "DXILOperation.inc"
+  }
+  return Props;
+}
+
+static bool checkWaveOps(Intrinsic::ID IID) {
+  switch (IID) {
+#define DXIL_OP_INTRINSIC(OpCode, IntrinsicID, ...) \
+  case IntrinsicID: return getOpCodeProperties(OpCode).IsWave;
+#include "DXILOperation.inc"
+  }
+  return false;
+}
+
 /// Update the shader flags mask based on the given instruction.
 /// \param CSF Shader flags mask to update.
 /// \param I Instruction to check.
@@ -92,6 +112,8 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
 
     // TODO: Set DX11_1_DoubleExtensions if I is a call to DXIL intrinsic
     // DXIL::Opcode::Fma https://github.com/llvm/llvm-project/issues/114554
+
+    CSF.WaveOps |= checkWaveOps(CI->getIntrinsicID());
   }
 }
 
diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp
index 223462538c0fd2..6e94821a30be8c 100644
--- a/llvm/utils/TableGen/DXILEmitter.cpp
+++ b/llvm/utils/TableGen/DXILEmitter.cpp
@@ -437,6 +437,21 @@ static void emitDXILProperties(const RecordKeeper &Records, raw_ostream &OS) {
   OS << "#endif\n\n";
 }
 
+/// Emit a table of bools denoting a DXIL op's properties
+static void emitDXILOpProperties(const RecordKeeper &Records,
+                                 ArrayRef<DXILOperationDesc> Ops,
+                                 raw_ostream &OS) {
+  auto DefinedProps = Records.getAllDerivedDefinitions("DXILProperty");
+  OS << "#ifdef DXIL_OP_PROPERTIES\n";
+  for (const auto &Op : Ops) {
+    OS << "DXIL_OP_PROPERTIES(dxil::OpCode::" << Op.OpName;
+    emitBoolTable(Op.PropRecs, DefinedProps, OS);
+    OS << ")\n";
+  }
+  OS << "#undef DXIL_OP_PROPERTIES\n";
+  OS << "#endif\n\n";
+}
+
 /// Emit a list of DXIL op function types
 static void emitDXILOpFunctionTypes(ArrayRef<DXILOperationDesc> Ops,
                                     raw_ostream &OS) {
@@ -641,6 +656,7 @@ static void emitDxilOperation(const RecordKeeper &Records, raw_ostream &OS) {
   emitDXILAttributes(Records, OS);
   emitDXILOpAttributes(Records, DXILOps, OS);
   emitDXILProperties(Records, OS);
+  emitDXILOpProperties(Records, DXILOps, OS);
   emitDXILOpFunctionTypes(DXILOps, OS);
   emitDXILIntrinsicArgSelectTypes(Records, OS);
   emitDXILIntrinsicMap(DXILOps, OS);

>From 898854ef4474057d66fe424bcda9eefce492d296 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 22 Jan 2025 23:11:53 +0000
Subject: [PATCH 3/3] add template test case for checking if the shader flags
 are set

---
 llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll

diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll
new file mode 100644
index 00000000000000..9567698fdc5efd
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll
@@ -0,0 +1,15 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+;
+; CHECK: ; Shader Flags Value: 0x00080000
+; CHECK: ; Note: shader requires additional functionality:
+; CHECK-NEXT: ;       Wave level operations
+; CHECK-NEXT: ; Note: extra DXIL module flags:
+; CHECK-NEXT: {{^;$}}
+
+target triple = "dxil-pc-shadermodel6.7-library"
+
+define noundef half @wave_rla_half(half noundef %expr, i32 noundef %idx) {
+entry:
+  %ret = call half @llvm.dx.wave.readlane.f16(half %expr, i32 %idx)
+  ret half %ret
+}



More information about the llvm-commits mailing list