[llvm] [SPIRV] Emit NonSemantic DebugValue (PR #224158)
Diego Novillo via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 22 06:35:39 PDT 2026
================
@@ -585,6 +724,157 @@ MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
return Reg;
}
+// Whether declaring \p BT's SPIR-V type would require a capability. The type
+// width determines the requirement: Int16, Int64, Float16 and Float64 in
+// SPIRVModuleAnalysis::collectReqs(). A boolean and a 32-bit scalar are free.
+static bool scalarTypeNeedsCapability(const DIBasicType *BT) {
+ if (isBooleanType(BT))
+ return false;
+ unsigned Width = BT->getSizeInBits();
+ return Width != 32;
+}
+
+MCRegister SPIRVNonSemanticDebugHandler::findOrEmitScalarType(
+ const DIBasicType *BT, SPIRV::ModuleAnalysisInfo &MAI) {
+ bool IsBool = isBooleanType(BT);
+ bool IsFloat = BT->getEncoding() == dwarf::DW_ATE_float;
+ unsigned Opcode = IsBool ? SPIRV::OpTypeBool
+ : IsFloat ? SPIRV::OpTypeFloat
+ : SPIRV::OpTypeInt;
+ // Two DIBasicTypes can describe one SPIR-V type, and OpTypeBool has no
+ // width, so the key is the opcode and the width rather than the node.
+ int64_t Width = IsBool ? 0 : BT->getSizeInBits();
+
+ // OpTypeInt 32 0 is already owned by getOrEmitOpTypeInt32Reg(), which every
+ // line and column constant needs. Declaring a second one is a duplicate type
+ // declaration, which the validator rejects.
+ if (Opcode == SPIRV::OpTypeInt && Width == 32)
+ return getOrEmitOpTypeInt32Reg(MAI);
+
+ auto [CacheIt, Inserted] =
+ ScalarTypeCache.try_emplace({Opcode, Width}, MCRegister());
+ if (!Inserted)
+ return CacheIt->second;
+
+ // The backend writes every integer type with signedness 0, so a signed and
+ // an unsigned DIBasicType of the same width share one OpTypeInt.
+ for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
+ if (MI->getOpcode() != Opcode)
+ continue;
+ if (IsBool || (MI->getOperand(1).getImm() == Width &&
+ (IsFloat || MI->getOperand(2).getImm() == 0))) {
+ CacheIt->second =
+ MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
+ return CacheIt->second;
+ }
+ }
+
+ // A non-semantic instruction "has no semantic impact, and can be safely
+ // removed from the module", so debug info must not make the module require
+ // something it otherwise would not. Declaring OpTypeInt 64 would force the
+ // module to declare Int64, and in Vulkan that ties it to a device feature,
+ // so we drop all the types that the module doesn't already have.
+ if (scalarTypeNeedsCapability(BT))
----------------
dnovillo wrote:
> Is it possible the scenario where a capability is already required but we may not have a type yet?
Yes. The check looks for the type rather than the capability, so it drops the record unless the module already declares a 64-bit integer. An image format can require `Int64` on its own, so a module can declare the capability without declaring the type. In that case we'd drop the constant unnecessarily.
> What type could have not been emitted yet but would not require a capability?
Only booleans and 32-bit floats reach that path.
https://github.com/llvm/llvm-project/pull/224158
More information about the llvm-commits
mailing list