This is an archive of the discontinued LLVM Phabricator instance.

[SPIRV] Add support for SPV_INTEL_optnone
ClosedPublic

Authored by pmatos on Jul 26 2023, 12:50 AM.

Details

Summary

Adds support for SPV_INTEL_optnone.

Diff Detail

Event Timeline

pmatos created this revision.Jul 26 2023, 12:50 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 26 2023, 12:50 AM
pmatos requested review of this revision.Jul 26 2023, 12:50 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 26 2023, 12:50 AM

This is a draft patch - I want to discuss somethings inline.

The output for optnone.ll is:

bin/llc -O0 -mtriple=spirv32-unknown-unknown ../llvm/test/CodeGen/SPIRV/optnone.ll -o -
	OpCapability Kernel
	OpCapability Addresses
	OpCapability Linkage
	%1 = OpExtInstImport "OpenCL.std"
	OpMemoryModel Physical32 OpenCL
	OpExecutionMode %4 ContractionOff
	OpSource Unknown 0
	OpName %4 "_Z3foov"
	OpDecorate %4 LinkageAttributes "_Z3foov" Export
	%2 = OpTypeVoid
	%3 = OpTypeFunction %2
	OpCapability OptNoneINTEL               ; -- Begin function _Z3foov
	OpExtension "�" "�" "�" "�" "�" "�"
	%4 = OpFunction %2 DontInline %3
	%5 = OpLabel
	OpReturn
	OpFunctionEnd

OpExtension emits some funky unicode characters, I feel like I am doing this incorrectly but similarly to what's being done in SPIRVAsmPrinter::outputGlobalRequirements() :

MCInst Inst;
    Inst.setOpcode(SPIRV::OpExtension);
    addStringImm(getSymbolicOperandMnemonic(
                     SPIRV::OperandCategory::ExtensionOperand, Ext),
                 Inst);
    outputMCInst(Inst);

The other issue is that afaiu the OpExtension declaractions need to come up the top of the module. How is this organized in the backend so that I can emit these at the top of the module? Do I need to add these to the module requirements somehow?

llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
127 ↗(On Diff #544243)

Is this the best place to issue the instruction or is it preferable to do so during lowering for each function?

I just checked section 2.4 of the spirv spec and all caps and exts need to come at the beginning: https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_logical_layout_of_a_module

So actually, I will move this code to a pass on MFs that adds the required extension and caps to the module.

This is a draft patch - I want to discuss somethings inline.

The output for optnone.ll is:

bin/llc -O0 -mtriple=spirv32-unknown-unknown ../llvm/test/CodeGen/SPIRV/optnone.ll -o -
	OpCapability Kernel
	OpCapability Addresses
	OpCapability Linkage
	%1 = OpExtInstImport "OpenCL.std"
	OpMemoryModel Physical32 OpenCL
	OpExecutionMode %4 ContractionOff
	OpSource Unknown 0
	OpName %4 "_Z3foov"
	OpDecorate %4 LinkageAttributes "_Z3foov" Export
	%2 = OpTypeVoid
	%3 = OpTypeFunction %2
	OpCapability OptNoneINTEL               ; -- Begin function _Z3foov
	OpExtension "�" "�" "�" "�" "�" "�"
	%4 = OpFunction %2 DontInline %3
	%5 = OpLabel
	OpReturn
	OpFunctionEnd

OpExtension emits some funky unicode characters, I feel like I am doing this incorrectly but similarly to what's being done in SPIRVAsmPrinter::outputGlobalRequirements() :

MCInst Inst;
    Inst.setOpcode(SPIRV::OpExtension);
    addStringImm(getSymbolicOperandMnemonic(
                     SPIRV::OperandCategory::ExtensionOperand, Ext),
                 Inst);
    outputMCInst(Inst);

The other issue is that afaiu the OpExtension declaractions need to come up the top of the module. How is this organized in the backend so that I can emit these at the top of the module? Do I need to add these to the module requirements somehow?

Thank you for the patch @pmatos!

The OpExtension instructions should be added earlier in the pipeline. If the OpExtension instruction is added explicitly to MIR, it should be added before SPIRVModuleAnalysis. All explicit OpExtension instructions are then collected in this method. Please take a look at the draft pull request adding an extension here -- this should also help address the issue with incorrect unicode characters printed out in the SPIR-V assembly.

There are draft patches splitting SPIRVModuleAnalysis into smaller passes on our GitHub, but this can be done later (I am currently a bit busy, but promise to get back to this in August).

Paulo, please also add a lit test which checks the new feature.

llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
127 ↗(On Diff #544243)

A more appropriate place to add the required capability is inside collectReqs() in SPIRVModuleAnalysis.cpp.

As for the extension, I'm not sure we should add it by default, having a function with optnone. I assume that SPIRV translator issues OpExtension instructions if we pass a command line option (like this --spirv-ext=+SPV_INTEL_optnone) and have a corresponding trigger in IR (like a function with optnone). Probably other ways to enable desirable extensions are suitable (e.g. in module metadata).

We don't have support for the command line option yet, perhaps it can be implemented inside SPIRVSubtarget::initAvailableExtensions using cl::opt<string> and string parsing. Then we check function's optnone and availability of the extension inside collectReqs() and add the extension, as we do with capabilities.

pmatos added inline comments.Jul 31 2023, 12:41 AM
llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
127 ↗(On Diff #544243)

Thanks Iliya, I think for now I will add it by default if there's a function with optnone. I think later once we get some command line arguments, we can make it optional depending on if the command line argument is present or not. I think Michal already has some code in this direction so I would prefer no to duplicate this.

pmatos updated this revision to Diff 545544.Jul 31 2023, 2:00 AM

Add INTEL optnone work to PreLegalizer.
Alternatively this could be done on its own pass. Doing it here runs the risk
of just using the PreLegalizer to too much of this kind of work.

In any case we are now generating better code with extension
declaration and capability at the top of the function.

Current patch generates:

	OpCapability Kernel
	OpCapability Addresses
	OpCapability Linkage
	OpCapability OptNoneINTEL
	OpExtension "SPV_INTEL_optnone"
	%1 = OpExtInstImport "OpenCL.std"
	OpMemoryModel Physical32 OpenCL
	OpExecutionMode %4 ContractionOff
	OpSource Unknown 0
	OpName %4 "_Z3foov"
	OpDecorate %4 LinkageAttributes "_Z3foov" Export
	%2 = OpTypeVoid
	%3 = OpTypeFunction %2
	%4 = OpFunction %2 DontInline %3        ; -- Begin function _Z3foov
	%5 = OpLabel
	OpReturn
	OpFunctionEnd
                                        ; -- End function

which looks good to me. If you think this approach works well, I will tidy up the patch and fix up the test.

pmatos updated this revision to Diff 545552.Jul 31 2023, 2:29 AM

Update test.

pmatos edited the summary of this revision. (Show Details)Jul 31 2023, 2:30 AM
pmatos updated this revision to Diff 545553.Jul 31 2023, 2:31 AM

Remove unnecessary header include.

This is ready for review. Will wait for further comments.

Add INTEL optnone work to PreLegalizer.
Alternatively this could be done on its own pass. Doing it here runs the risk
of just using the PreLegalizer to too much of this kind of work.

In any case we are now generating better code with extension
declaration and capability at the top of the function.

The output code is Ok and these instructions can be generated at this place. However, I think it's better to make such instructions as late as possible. If we insert this code into collectReqs (SPIRVModuleAnalysis.cpp), the output will be the same:

@@ -898,6 +902,12 @@ static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI,
       MAI.Reqs.getAndAddRequirements(
           SPIRV::OperandCategory::ExecutionModeOperand,
           SPIRV::ExecutionMode::VecTypeHint, ST);
+    if (F.hasOptNone() &&
+        ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
+      // Output OpCapability OptNoneINTEL.
+      MAI.Reqs.addExtension(SPIRV::Extension::SPV_INTEL_optnone);
+      MAI.Reqs.addCapability(SPIRV::Capability::OptNoneINTEL);
+    }
   }
 }

but we even don't generate the instructions in IR (since we add exts and caps directly to requirements), so IR becomes simpler and there is less work for the backend.

llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
587–596 ↗(On Diff #545553)

Please format this code properly (i.e. you can apply clang-format to all c++ files).

llvm/test/CodeGen/SPIRV/optnone.ll
18

Don't need this empty line?

19–22

Is it necessary to move this check after the foo() declaration? Maybe it's better to leave it in the same place and put OpCapability/OpExtension checks before it.

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
555

Please add '.' at the end of the sentence.

pmatos updated this revision to Diff 545963.Aug 1 2023, 1:58 AM
pmatos marked an inline comment as done.

Address Iliya's comments. Thanks for the review.

pmatos marked 2 inline comments as done.Aug 1 2023, 1:58 AM
pmatos updated this revision to Diff 545965.Aug 1 2023, 2:00 AM

Run clang-format.

iliya-diyachkov accepted this revision.Aug 1 2023, 3:35 AM

Thanks, Paulo. The patch looks good to me.

This revision is now accepted and ready to land.Aug 1 2023, 3:35 AM
This revision was automatically updated to reflect the committed changes.