[llvm] 62da359 - [SPIRV] Emitting DebugSource, DebugCompileUnit (#97558)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 22 20:27:39 PDT 2024
Author: bwlodarcz
Date: 2024-08-22T20:27:36-07:00
New Revision: 62da359ce7a7ae09e6afa96227eb556be54aabb1
URL: https://github.com/llvm/llvm-project/commit/62da359ce7a7ae09e6afa96227eb556be54aabb1
DIFF: https://github.com/llvm/llvm-project/commit/62da359ce7a7ae09e6afa96227eb556be54aabb1.diff
LOG: [SPIRV] Emitting DebugSource, DebugCompileUnit (#97558)
This commit introduces emission of DebugSource, DebugCompileUnit from
NonSemantic.Shader.DebugInfo.100 and required OpString with filename.
NonSemantic.Shader.DebugInfo.100 is divided, following DWARF into two
main concepts – emitting DIE and Line.
In DWARF .debug_abbriev and .debug_info sections are responsible for
emitting tree with information (DEIs) about e.g. types, compilation
unit. Corresponding to that in NonSemantic.Shader.DebugInfo.100 have
instructions like DebugSource, DebugCompileUnit etc. which preforms same
role in SPIR-V file. The difference is in fact that in SPIR-V there are
no sections but logical layout which forces order of the instruction
emission.
The NonSemantic.Shader.DebugInfo.100 requires for this type of global
information to be emitted after OpTypeXXX and OpConstantXXX
instructions.
One of the goals was to minimize changes and interaction with
SPIRVModuleAnalysis as possible which current commit achieves by
emitting it’s instructions directly into MachineFunction.
The possibility of duplicates are mitigated by guard inside pass which
emits the global information only once in one function.
By that method duplicates don’t have chance to be emitted.
>From that point, adding new debug global instructions should be
straightforward.
Added:
llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
llvm/test/CodeGen/SPIRV/debug-info/basic-global-di.ll
Modified:
llvm/docs/SPIRVUsage.rst
llvm/lib/Target/SPIRV/CMakeLists.txt
llvm/lib/Target/SPIRV/SPIRV.h
llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
Removed:
################################################################################
diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
index 70865b95cb3932..0f0b21fb237703 100644
--- a/llvm/docs/SPIRVUsage.rst
+++ b/llvm/docs/SPIRVUsage.rst
@@ -33,7 +33,11 @@ Static Compiler Commands
Command: `llc -O1 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_arbitrary_precision_integers input.ll -o output.spvt`
Description: Compiles an LLVM IL file to SPIR-V with (`-O1`) optimizations, targeting a 64-bit architecture. It enables the SPV_INTEL_arbitrary_precision_integers extension.
-3. **SPIR-V Binary Generation**
+3. **Compilation with experimental NonSemantic.Shader.DebugInfo.100 support**
+ Command: `llc --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info input.ll -o output.spvt`
+ Description: Compiles an LLVM IL file to SPIR-V with additional NonSemantic.Shader.DebugInfo.100 instructions. It enables the required SPV_KHR_non_semantic_info extension.
+
+4. **SPIR-V Binary Generation**
Command: `llc -O0 -mtriple=spirv64-unknown-unknown -filetype=obj input.ll -o output.spvt`
Description: Generates a SPIR-V object file (`output.spvt`) from an LLVM module, targeting a 64-bit SPIR-V architecture with no optimizations.
@@ -181,6 +185,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na
- Adds a new instruction that enables rotating values across invocations within a subgroup.
* - ``SPV_KHR_uniform_group_instructions``
- Allows support for additional group operations within uniform control flow.
+ * - ``SPV_KHR_non_semantic_info``
+ - Adds the ability to declare extended instruction sets that have no semantic impact and can be safely removed from a module.
To enable multiple extensions, list them separated by spaces. For example, to enable support for atomic operations on floating-point numbers and arbitrary precision integers, use:
diff --git a/llvm/lib/Target/SPIRV/CMakeLists.txt b/llvm/lib/Target/SPIRV/CMakeLists.txt
index 14647e92f5d088..5f8aea5fc8d84d 100644
--- a/llvm/lib/Target/SPIRV/CMakeLists.txt
+++ b/llvm/lib/Target/SPIRV/CMakeLists.txt
@@ -40,6 +40,7 @@ add_llvm_target(SPIRVCodeGen
SPIRVSubtarget.cpp
SPIRVTargetMachine.cpp
SPIRVUtils.cpp
+ SPIRVEmitNonSemanticDI.cpp
LINK_COMPONENTS
Analysis
diff --git a/llvm/lib/Target/SPIRV/SPIRV.h b/llvm/lib/Target/SPIRV/SPIRV.h
index e597a1dc8dc06c..6c35a467f53bef 100644
--- a/llvm/lib/Target/SPIRV/SPIRV.h
+++ b/llvm/lib/Target/SPIRV/SPIRV.h
@@ -26,6 +26,7 @@ FunctionPass *createSPIRVRegularizerPass();
FunctionPass *createSPIRVPreLegalizerPass();
FunctionPass *createSPIRVPostLegalizerPass();
ModulePass *createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM);
+MachineFunctionPass *createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM);
InstructionSelector *
createSPIRVInstructionSelector(const SPIRVTargetMachine &TM,
const SPIRVSubtarget &Subtarget,
@@ -36,6 +37,7 @@ void initializeSPIRVConvergenceRegionAnalysisWrapperPassPass(PassRegistry &);
void initializeSPIRVPreLegalizerPass(PassRegistry &);
void initializeSPIRVPostLegalizerPass(PassRegistry &);
void initializeSPIRVEmitIntrinsicsPass(PassRegistry &);
+void initializeSPIRVEmitNonSemanticDIPass(PassRegistry &);
} // namespace llvm
#endif // LLVM_LIB_TARGET_SPIRV_SPIRV_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
index 7fe8e11aaa4209..55b41627802096 100644
--- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
@@ -274,6 +274,8 @@ void SPIRVAsmPrinter::outputDebugSourceAndStrings(const Module &M) {
addStringImm(Str.first(), Inst);
outputMCInst(Inst);
}
+ // Output OpString.
+ outputModuleSection(SPIRV::MB_DebugStrings);
// Output OpSource.
MCInst Inst;
Inst.setOpcode(SPIRV::OpSource);
@@ -589,9 +591,11 @@ void SPIRVAsmPrinter::outputModuleSections() {
// the first section to allow use of: OpLine and OpNoLine debug information;
// non-semantic instructions with OpExtInst.
outputModuleSection(SPIRV::MB_TypeConstVars);
- // 10. All function declarations (functions without a body).
+ // 10. All global NonSemantic.Shader.DebugInfo.100 instructions.
+ outputModuleSection(SPIRV::MB_NonSemanticGlobalDI);
+ // 11. All function declarations (functions without a body).
outputExtFuncDecls();
- // 11. All function definitions (functions with a body).
+ // 12. All function definitions (functions with a body).
// This is done in regular function output.
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
index c7c244cfa89770..90a9ab1d33ced4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -68,7 +68,8 @@ static const std::map<std::string, SPIRV::Extension::Extension>
SPIRV::Extension::Extension::SPV_KHR_shader_clock},
{"SPV_KHR_cooperative_matrix",
SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix},
-};
+ {"SPV_KHR_non_semantic_info",
+ SPIRV::Extension::Extension::SPV_KHR_non_semantic_info}};
bool SPIRVExtensionsParser::parse(cl::Option &O, llvm::StringRef ArgName,
llvm::StringRef ArgValue,
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
new file mode 100644
index 00000000000000..cc506356e39043
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -0,0 +1,188 @@
+#include "MCTargetDesc/SPIRVBaseInfo.h"
+#include "MCTargetDesc/SPIRVMCTargetDesc.h"
+#include "SPIRVGlobalRegistry.h"
+#include "SPIRVRegisterInfo.h"
+#include "SPIRVTargetMachine.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Path.h"
+
+#define DEBUG_TYPE "spirv-nonsemantic-debug-info"
+
+namespace llvm {
+struct SPIRVEmitNonSemanticDI : public MachineFunctionPass {
+ static char ID;
+ SPIRVTargetMachine *TM;
+ SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM);
+ SPIRVEmitNonSemanticDI();
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+private:
+ bool IsGlobalDIEmitted = false;
+ bool emitGlobalDI(MachineFunction &MF);
+};
+
+void initializeSPIRVEmitNonSemanticDIPass(PassRegistry &);
+
+FunctionPass *createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM) {
+ return new SPIRVEmitNonSemanticDI(TM);
+}
+} // namespace llvm
+
+using namespace llvm;
+
+INITIALIZE_PASS(SPIRVEmitNonSemanticDI, DEBUG_TYPE,
+ "SPIRV NonSemantic.Shader.DebugInfo.100 emitter", false, false)
+
+char SPIRVEmitNonSemanticDI::ID = 0;
+
+SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM)
+ : MachineFunctionPass(ID), TM(TM) {
+ initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
+}
+
+SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI() : MachineFunctionPass(ID) {
+ initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
+}
+
+bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
+ // If this MachineFunction doesn't have any BB repeat procedure
+ // for the next
+ if (MF.begin() == MF.end()) {
+ IsGlobalDIEmitted = false;
+ return false;
+ }
+
+ // Required variables to get from metadata search
+ LLVMContext *Context;
+ SmallString<128> FilePath;
+ unsigned SourceLanguage = 0;
+ int64_t DwarfVersion = 0;
+ int64_t DebugInfoVersion = 0;
+
+ // Searching through the Module metadata to find nescessary
+ // information like DwarfVersion or SourceLanguage
+ {
+ const MachineModuleInfo &MMI =
+ getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
+ const Module *M = MMI.getModule();
+ Context = &M->getContext();
+ const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
+ if (!DbgCu)
+ return false;
+ for (const auto *Op : DbgCu->operands()) {
+ if (const auto *CompileUnit = dyn_cast<DICompileUnit>(Op)) {
+ DIFile *File = CompileUnit->getFile();
+ sys::path::append(FilePath, File->getDirectory(), File->getFilename());
+ SourceLanguage = CompileUnit->getSourceLanguage();
+ break;
+ }
+ }
+ const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");
+ for (const auto *Op : ModuleFlags->operands()) {
+ const MDOperand &MaybeStrOp = Op->getOperand(1);
+ if (MaybeStrOp.equalsStr("Dwarf Version"))
+ DwarfVersion =
+ cast<ConstantInt>(
+ cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
+ ->getSExtValue();
+ else if (MaybeStrOp.equalsStr("Debug Info Version"))
+ DebugInfoVersion =
+ cast<ConstantInt>(
+ cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
+ ->getSExtValue();
+ }
+ }
+ // NonSemantic.Shader.DebugInfo.100 global DI instruction emitting
+ {
+ // Required LLVM variables for emitting logic
+ const SPIRVInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo();
+ const SPIRVRegisterInfo *TRI = TM->getSubtargetImpl()->getRegisterInfo();
+ const RegisterBankInfo *RBI = TM->getSubtargetImpl()->getRegBankInfo();
+ SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+ MachineBasicBlock &MBB = *MF.begin();
+
+ // To correct placement of a OpLabel instruction during SPIRVAsmPrinter
+ // emission all new instructions needs to be placed after OpFunction
+ // and before first terminator
+ MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());
+
+ // Emit OpString with FilePath which is required by DebugSource
+ const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
+ MRI.setType(StrReg, LLT::scalar(32));
+ MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
+ MIB.addDef(StrReg);
+ addStringImm(FilePath, MIB);
+
+ const SPIRVType *VoidTy =
+ GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder);
+
+ // Emit DebugSource which is required by DebugCompilationUnit
+ const Register DebugSourceResIdReg =
+ MRI.createVirtualRegister(&SPIRV::IDRegClass);
+ MRI.setType(DebugSourceResIdReg, LLT::scalar(32));
+ MIB = MIRBuilder.buildInstr(SPIRV::OpExtInst)
+ .addDef(DebugSourceResIdReg)
+ .addUse(GR->getSPIRVTypeID(VoidTy))
+ .addImm(static_cast<int64_t>(
+ SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
+ .addImm(SPIRV::NonSemanticExtInst::DebugSource)
+ .addUse(StrReg);
+ MIB.constrainAllUses(*TII, *TRI, *RBI);
+ GR->assignSPIRVTypeToVReg(VoidTy, DebugSourceResIdReg, MF);
+
+ const SPIRVType *I32Ty =
+ GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder);
+
+ // Convert DwarfVersion, DebugInfo and SourceLanguage integers to OpConstant
+ // instructions required by DebugCompilationUnit
+ const Register DwarfVersionReg =
+ GR->buildConstantInt(DwarfVersion, MIRBuilder, I32Ty, false);
+ const Register DebugInfoVersionReg =
+ GR->buildConstantInt(DebugInfoVersion, MIRBuilder, I32Ty, false);
+ const Register SourceLanguageReg =
+ GR->buildConstantInt(SourceLanguage, MIRBuilder, I32Ty, false);
+
+ // Emit DebugCompilationUnit
+ const Register DebugCompUnitResIdReg =
+ MRI.createVirtualRegister(&SPIRV::IDRegClass);
+ MRI.setType(DebugCompUnitResIdReg, LLT::scalar(32));
+ MIB = MIRBuilder.buildInstr(SPIRV::OpExtInst)
+ .addDef(DebugCompUnitResIdReg)
+ .addUse(GR->getSPIRVTypeID(VoidTy))
+ .addImm(static_cast<int64_t>(
+ SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
+ .addImm(SPIRV::NonSemanticExtInst::DebugCompilationUnit)
+ .addUse(DebugInfoVersionReg)
+ .addUse(DwarfVersionReg)
+ .addUse(DebugSourceResIdReg)
+ .addUse(SourceLanguageReg);
+ MIB.constrainAllUses(*TII, *TRI, *RBI);
+ GR->assignSPIRVTypeToVReg(VoidTy, DebugCompUnitResIdReg, MF);
+ }
+ return true;
+}
+
+bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
+ bool Res = false;
+ // emitGlobalDI needs to be executed only once to avoid
+ // emitting duplicates
+ if (!IsGlobalDIEmitted) {
+ IsGlobalDIEmitted = true;
+ Res = emitGlobalDI(MF);
+ }
+ return Res;
+}
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index ac0aa682ea4beb..a2fcfc636e3684 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -21,7 +21,6 @@
#include "SPIRVSubtarget.h"
#include "SPIRVTargetMachine.h"
#include "SPIRVUtils.h"
-#include "TargetInfo/SPIRVTargetInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/TargetPassConfig.h"
@@ -427,7 +426,19 @@ void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) {
if (MAI.getSkipEmission(&MI))
continue;
const unsigned OpCode = MI.getOpcode();
- if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
+ if (OpCode == SPIRV::OpString) {
+ collectOtherInstr(MI, MAI, SPIRV::MB_DebugStrings, IS);
+ } else if (OpCode == SPIRV::OpExtInst) {
+ MachineOperand Ins = MI.getOperand(3);
+ namespace NS = SPIRV::NonSemanticExtInst;
+ static constexpr int64_t GlobalNonSemanticDITy[] = {
+ NS::DebugSource, NS::DebugCompilationUnit};
+ bool IsGlobalDI = false;
+ for (unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)
+ IsGlobalDI |= Ins.getImm() == GlobalNonSemanticDITy[Idx];
+ if (IsGlobalDI)
+ collectOtherInstr(MI, MAI, SPIRV::MB_NonSemanticGlobalDI, IS);
+ } else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
collectOtherInstr(MI, MAI, SPIRV::MB_DebugNames, IS);
} else if (OpCode == SPIRV::OpEntryPoint) {
collectOtherInstr(MI, MAI, SPIRV::MB_EntryPoints, IS);
@@ -899,6 +910,14 @@ void addInstrRequirements(const MachineInstr &MI,
Reqs.addCapability(SPIRV::Capability::Float16Buffer);
break;
}
+ case SPIRV::OpExtInst: {
+ if (MI.getOperand(2).getImm() ==
+ static_cast<int64_t>(
+ SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
+ Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
+ }
+ break;
+ }
case SPIRV::OpBitReverse:
case SPIRV::OpBitFieldInsert:
case SPIRV::OpBitFieldSExtract:
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
index 79226d6d93efb2..024728c347e8a8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
@@ -20,7 +20,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
namespace llvm {
class SPIRVSubtarget;
@@ -34,9 +33,11 @@ enum ModuleSectionType {
MB_EntryPoints, // All OpEntryPoint instructions (if any).
// MB_ExecutionModes, MB_DebugSourceAndStrings,
MB_DebugNames, // All OpName and OpMemberName intrs.
+ MB_DebugStrings, // All OpString intrs.
MB_DebugModuleProcessed, // All OpModuleProcessed instructions.
MB_Annotations, // OpDecorate, OpMemberDecorate etc.
MB_TypeConstVars, // OpTypeXXX, OpConstantXXX, and global OpVariables.
+ MB_NonSemanticGlobalDI, // OpExtInst with e.g. DebugSource, DebugTypeBasic.
MB_ExtFuncDecls, // OpFunction etc. to declare for external funcs.
NUM_MODULE_SECTIONS // Total number of sections requiring basic blocks.
};
diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
index 52fc6f33b4ef14..48a2ce89bad390 100644
--- a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
@@ -115,6 +115,7 @@ class SPIRVPassConfig : public TargetPassConfig {
void addOptimizedRegAlloc() override {}
void addPostRegAlloc() override;
+ void addPreEmitPass() override;
private:
const SPIRVTargetMachine &TM;
@@ -208,6 +209,17 @@ bool SPIRVPassConfig::addRegBankSelect() {
return false;
}
+static cl::opt<bool> SPVEnableNonSemanticDI(
+ "spv-emit-nonsemantic-debug-info",
+ cl::desc("Emit SPIR-V NonSemantic.Shader.DebugInfo.100 instructions"),
+ cl::Optional, cl::init(false));
+
+void SPIRVPassConfig::addPreEmitPass() {
+ if (SPVEnableNonSemanticDI) {
+ addPass(createSPIRVEmitNonSemanticDIPass(&getTM<SPIRVTargetMachine>()));
+ }
+}
+
namespace {
// A custom subclass of InstructionSelect, which is mostly the same except from
// not requiring RegBankSelect to occur previously.
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/basic-global-di.ll b/llvm/test/CodeGen/SPIRV/debug-info/basic-global-di.ll
new file mode 100644
index 00000000000000..336b7db324c3d4
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/basic-global-di.ll
@@ -0,0 +1,46 @@
+; RUN: llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info --print-after=spirv-nonsemantic-debug-info -O0 -mtriple=spirv64-unknown-unknown %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-MIR
+; RUN: llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s --check-prefix=CHECK-OPTION
+; RUN: %if spirv-tools %{ llc --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-MIR-DAG: [[type_void:%[0-9]+\:type]] = OpTypeVoid
+; CHECK-MIR-DAG: [[type_i64:%[0-9]+\:type\(s64\)]] = OpTypeInt 32, 0
+; CHECK-MIR-DAG: [[dwarf_version:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i64]], 5
+; CHECK-MIR-DAG: [[source_language:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i64]], 3
+; CHECK-MIR-DAG: [[debug_info_version:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i64]], 21
+; CHECK-MIR-DAG: [[filename_str:%[0-9]+\:id\(s32\)]] = OpString 1094795567, 1094795585, 792805697, 1111638594, 1111638594, 1128481583, 1128481603, 1697596227, 1886216568, 1663985004, 0
+; CHECK-MIR-DAG: [[debug_source:%[0-9]+\:id\(s32\)]] = OpExtInst [[type_void]], 3, 35, [[filename_str]]
+; CHECK-MIR-DAG: [[debug_compilation_unit:%[0-9]+\:id\(s32\)]] = OpExtInst [[type_void]], 3, 1, [[source_language]], [[dwarf_version]], [[debug_source]], [[debug_info_version]]
+
+; CHECK-SPIRV: [[ext_inst_non_semantic:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-SPIRV: [[filename_str:%[0-9]+]] = OpString "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC/example.c"
+; CHECK-SPIRV-DAG: [[type_void:%[0-9]+]] = OpTypeVoid
+; CHECK-SPIRV-DAG: [[type_i32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-SPIRV-DAG: [[dwarf_version:%[0-9]+]] = OpConstant [[type_i32]] 5
+; CHECK-SPIRV-DAG: [[debug_info_version:%[0-9]+]] = OpConstant [[type_i32]] 21
+; CHECK-SPIRV-DAG: [[source_language:%[0-9]+]] = OpConstant [[type_i32]] 3
+; CHECK-SPIRV: [[debug_source:%[0-9]+]] = OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugSource [[filename_str]]
+; CHECK-SPIRV: [[debug_compiation_unit:%[0-9]+]] = OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugCompilationUnit [[source_language]] [[dwarf_version]] [[debug_source]] [[debug_info_version]]
+
+; CHECK-OPTION-NOT: OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-OPTION-NOT: OpString "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC/example.c"
+
+define spir_func void @foo() {
+entry:
+ ret void
+}
+
+define spir_func void @bar() {
+entry:
+ ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_OpenCL, file: !1, producer: "clang version XX.X.XXXX (FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "example.c", directory: "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC", checksumkind: CSK_MD5, checksum: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
More information about the llvm-commits
mailing list