[llvm-branch-commits] [llvm] [CodeGen][NPM] Clear MachineFunctions without using PA (PR #139517)
https://github.com/optimisan edited https://github.com/llvm/llvm-project/pull/139517 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147094)
https://github.com/inbelic created https://github.com/llvm/llvm-project/pull/147094 At the moment, when we report diagnostics from `SemaHLSL` we only provide the source location of the root signature attr. This allows for significantly less helpful diagnostics (for eg. reporting resource range overlaps). This pr implements a way to retain the source location of a root element when it is parsed, so that we can output the `SourceLocation` of each root element that causes the overlap in the diagnostics during semantic analysis. This pr defines a wrapper struct `clang::hlsl::RootSignatureElement` in `SemaHLSL` that will contain the underlying `RootElement` and can hold any additional diagnostic information. This struct will be what is used in `HLSLRootSignatureParser` and in `SemaHLSL`. Then the diagnostic information will be stripped and the underlying element will be stored in the `RootSignatureDecl`. For the reporting of diagnostics, we can now use the retained `SourceLocation` of each `RootElement` when reporting the range overlap, and we can add a `note` diagnostic to highlight the other root element as well. - Defines `RootSignatureElement` in the `hlsl` namespace in `SemaHLSL` (defined in `SemaHLSL` because `Parse` has a dependency on `Sema`) - Updates parsing logic to construct `RootSignatureElement`s and retain the source loction in `ParseHLSLRootSignature` - Updates `SemaHLSL` when it constructs the `RootSignatureDecl` to take the new `RootSignatureElement` and store the underlying `RootElement` - Updates the current tests to ensure the new `note` diagnostic is produced and that the `SourceLocation` is seen - Adds a test to demonstrate the `SourceLocation` of both elements being correctly pointed out Resolves: https://github.com/llvm/llvm-project/issues/145819 >From 4a5cde3f77dc0c371d1f33b10be9507d3aeff3e3 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 27 Jun 2025 18:36:38 + Subject: [PATCH 1/8] nfc: introduce wrapper `RootSignatureElement` around `RootElement` to retain clang diag info --- .../clang/Parse/ParseHLSLRootSignature.h | 17 ++- clang/include/clang/Sema/SemaHLSL.h | 10 +- clang/lib/Parse/ParseDeclCXX.cpp | 2 +- clang/lib/Parse/ParseHLSLRootSignature.cpp| 21 ++-- clang/lib/Sema/SemaHLSL.cpp | 6 +- .../Parse/ParseHLSLRootSignatureTest.cpp | 115 +- 6 files changed, 99 insertions(+), 72 deletions(-) diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index b0ef617a13c28..53001d2ba461f 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -26,10 +26,22 @@ namespace clang { namespace hlsl { +// Introduce a wrapper struct around the underlying RootElement. This structure +// will retain extra clang diagnostic information that is not available in llvm. +struct RootSignatureElement { + RootSignatureElement(llvm::hlsl::rootsig::RootElement Element) + : Element(Element) {} + + const llvm::hlsl::rootsig::RootElement &getElement() const { return Element; } + +private: + llvm::hlsl::rootsig::RootElement Element; +}; + class RootSignatureParser { public: RootSignatureParser(llvm::dxbc::RootSignatureVersion Version, - SmallVector &Elements, + SmallVector &Elements, StringLiteral *Signature, Preprocessor &PP); /// Consumes tokens from the Lexer and constructs the in-memory @@ -196,7 +208,8 @@ class RootSignatureParser { private: llvm::dxbc::RootSignatureVersion Version; - SmallVector &Elements; + SmallVector &Elements; + clang::StringLiteral *Signature; RootSignatureLexer Lexer; clang::Preprocessor &PP; diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 7d7eae4db532c..1af706da702c2 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -32,6 +32,10 @@ class ParsedAttr; class Scope; class VarDecl; +namespace hlsl { +struct RootSignatureElement; +} + using llvm::dxil::ResourceClass; // FIXME: This can be hidden (as static function in SemaHLSL.cpp) once we no @@ -130,9 +134,9 @@ class SemaHLSL : public SemaBase { /// Creates the Root Signature decl of the parsed Root Signature elements /// onto the AST and push it onto current Scope - void ActOnFinishRootSignatureDecl( - SourceLocation Loc, IdentifierInfo *DeclIdent, - SmallVector &Elements); + void + ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, + ArrayRef Elements); // Returns true when D is invalid and a diagnostic was produced bool handleRootSignatureDecl(HLSLRootSignatureDecl *D, SourceLocation Loc); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d3bc6f1e89832..d06bb6a25efa5 100
[llvm-branch-commits] [llvm] [DirectX] Add missing verifications during `validate` of `DXILRootSignature` (PR #147111)
https://github.com/inbelic edited https://github.com/llvm/llvm-project/pull/147111 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] [mlir] NFC - refactor id builder and avoid leaking impl details (PR #146922)
https://github.com/ftynse approved this pull request. https://github.com/llvm/llvm-project/pull/146922 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] WIP: retain source location for sema validation diagnostics and move validations out to library (PR #146150)
https://github.com/inbelic closed https://github.com/llvm/llvm-project/pull/146150 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [DirectX][Draft] validate registers are bound to root signature (PR #146785)
https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/146785 >From 76d633d2b2b70ae6eaa1e7c40ef09e5f6ef9ae74 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 19:28:01 + Subject: [PATCH 1/6] refactoring --- .../lib/Target/DirectX/DXContainerGlobals.cpp | 9 ++-- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 12 ++--- llvm/lib/Target/DirectX/DXILRootSignature.h | 45 ++- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 9c38901f6821f..fa27c4665cfbe 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -160,18 +160,17 @@ void DXContainerGlobals::addRootSignature(Module &M, assert(MMI.EntryPropertyVec.size() == 1); - auto &RSA = getAnalysis(); + auto &RSA = getAnalysis().getRSInfo(); const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; - const auto &FuncRs = RSA.find(EntryFunction); + const auto &RS = RSA.getDescForFunction(EntryFunction); - if (FuncRs == RSA.end()) + if (!RS ) return; - const RootSignatureDesc &RS = FuncRs->second; SmallString<256> Data; raw_svector_ostream OS(Data); - RS.write(OS); + RS->write(OS); Constant *Constant = ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false); diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 29e78fcce5262..4094df160ef6f 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -554,9 +554,9 @@ analyzeModule(Module &M) { AnalysisKey RootSignatureAnalysis::Key; -SmallDenseMap -RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { - return analyzeModule(M); +RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M, +ModuleAnalysisManager &AM) { + return RootSignatureBindingInfo(analyzeModule(M)); } //===--===// @@ -564,8 +564,7 @@ RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, ModuleAnalysisManager &AM) { - SmallDenseMap &RSDMap = - AM.getResult(M); + RootSignatureBindingInfo &RSDMap = AM.getResult(M); OS << "Root Signature Definitions" << "\n"; @@ -636,7 +635,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, //===--===// bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { - FuncToRsMap = analyzeModule(M); + FuncToRsMap = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); return false; } diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index b45cebc15fd39..fef933811f840 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -33,16 +33,43 @@ enum class RootSignatureElementKind { CBV = 5, DescriptorTable = 6, }; + +class RootSignatureBindingInfo { + private: +SmallDenseMap FuncToRsMap; + + public: + using iterator = +SmallDenseMap::iterator; + + RootSignatureBindingInfo () = default; + RootSignatureBindingInfo(SmallDenseMap Map) : FuncToRsMap(Map) {}; + + iterator find(const Function *F) { return FuncToRsMap.find(F); } + + iterator end() { return FuncToRsMap.end(); } + + std::optional getDescForFunction(const Function* F) { +const auto FuncRs = find(F); +if (FuncRs == end()) + return std::nullopt; + +return FuncRs->second; + } + +}; + class RootSignatureAnalysis : public AnalysisInfoMixin { friend AnalysisInfoMixin; static AnalysisKey Key; public: - RootSignatureAnalysis() = default; - using Result = SmallDenseMap; +RootSignatureAnalysis() = default; - SmallDenseMap + using Result = RootSignatureBindingInfo; + + RootSignatureBindingInfo run(Module &M, ModuleAnalysisManager &AM); }; @@ -52,20 +79,16 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { /// passes which run through the legacy pass manager. class RootSignatureAnalysisWrapper : public ModulePass { private: - SmallDenseMap FuncToRsMap; + std::unique_ptr FuncToRsMap; public: static char ID; + using Result = RootSignatureBindingInfo; RootSignatureAnalysisWrapper() : ModulePass(ID) {} - using iterator = - SmallDenseMap::iterator; - - iterator find(const Function *F) { return FuncToRsMap.find(F); } - - iterator end() { return FuncToRsMap.end(); } - + RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;} + bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override; >From 75
[llvm-branch-commits] [clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)
https://github.com/joaosaffran edited https://github.com/llvm/llvm-project/pull/146785 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [X86] Ignore NSW when DstSVT is i32 (#131755) (PR #147034)
https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/147034 >From c50b409b6b523fa4b8164b80515a93b12e1b5cd4 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Tue, 18 Mar 2025 13:04:23 +0100 Subject: [PATCH] [X86] Ignore NSW when DstSVT is i32 (#131755) We don't have PACKSS for i64->i32. Fixes: https://godbolt.org/z/qb8nxnPbK, which was introduced by ddd2f57b (cherry picked from commit 3d631914677b58a5479b310f480ac76e27d41e7e) --- llvm/lib/Target/X86/X86ISelLowering.cpp | 3 +- llvm/test/CodeGen/X86/vector-trunc-nowrap.ll | 88 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 4413fbb77f415..12c40b501f627 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -20889,7 +20889,8 @@ static SDValue matchTruncateWithPACK(unsigned &PackOpcode, EVT DstVT, return SDValue(); unsigned MinSignBits = NumSrcEltBits - NumPackedSignBits; - if (Flags.hasNoSignedWrap() || MinSignBits < NumSignBits) { + if ((Flags.hasNoSignedWrap() && DstSVT != MVT::i32) || + MinSignBits < NumSignBits) { PackOpcode = X86ISD::PACKSS; return In; } diff --git a/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll b/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll index 2b8eedfbbdc9c..863f30e03d2d6 100644 --- a/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll +++ b/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll @@ -1592,3 +1592,91 @@ entry: %1 = bitcast <8 x i8> %0 to i64 ret i64 %1 } + +define void @foo(<4 x i64> %a, <4 x i64> %b, ptr %p) "min-legal-vector-width"="256" "prefer-vector-width"="256" { +; SSE-LABEL: foo: +; SSE: # %bb.0: # %entry +; SSE-NEXT:shufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; SSE-NEXT:shufps {{.*#+}} xmm2 = xmm2[0,2],xmm3[0,2] +; SSE-NEXT:movaps %xmm2, 16(%rdi) +; SSE-NEXT:movaps %xmm0, (%rdi) +; SSE-NEXT:retq +; +; AVX1-LABEL: foo: +; AVX1: # %bb.0: # %entry +; AVX1-NEXT:vextractf128 $1, %ymm0, %xmm2 +; AVX1-NEXT:vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; AVX1-NEXT:vextractf128 $1, %ymm1, %xmm2 +; AVX1-NEXT:vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; AVX1-NEXT:vmovaps %xmm1, 16(%rdi) +; AVX1-NEXT:vmovaps %xmm0, (%rdi) +; AVX1-NEXT:vzeroupper +; AVX1-NEXT:retq +; +; AVX2-SLOW-LABEL: foo: +; AVX2-SLOW: # %bb.0: # %entry +; AVX2-SLOW-NEXT:vextractf128 $1, %ymm0, %xmm2 +; AVX2-SLOW-NEXT:vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; AVX2-SLOW-NEXT:vextractf128 $1, %ymm1, %xmm2 +; AVX2-SLOW-NEXT:vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; AVX2-SLOW-NEXT:vmovaps %xmm1, 16(%rdi) +; AVX2-SLOW-NEXT:vmovaps %xmm0, (%rdi) +; AVX2-SLOW-NEXT:vzeroupper +; AVX2-SLOW-NEXT:retq +; +; AVX2-FAST-ALL-LABEL: foo: +; AVX2-FAST-ALL: # %bb.0: # %entry +; AVX2-FAST-ALL-NEXT:vmovaps {{.*#+}} ymm2 = [0,2,4,6,4,6,6,7] +; AVX2-FAST-ALL-NEXT:vpermps %ymm0, %ymm2, %ymm0 +; AVX2-FAST-ALL-NEXT:vpermps %ymm1, %ymm2, %ymm1 +; AVX2-FAST-ALL-NEXT:vmovaps %xmm1, 16(%rdi) +; AVX2-FAST-ALL-NEXT:vmovaps %xmm0, (%rdi) +; AVX2-FAST-ALL-NEXT:vzeroupper +; AVX2-FAST-ALL-NEXT:retq +; +; AVX2-FAST-PERLANE-LABEL: foo: +; AVX2-FAST-PERLANE: # %bb.0: # %entry +; AVX2-FAST-PERLANE-NEXT:vextractf128 $1, %ymm0, %xmm2 +; AVX2-FAST-PERLANE-NEXT:vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; AVX2-FAST-PERLANE-NEXT:vextractf128 $1, %ymm1, %xmm2 +; AVX2-FAST-PERLANE-NEXT:vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; AVX2-FAST-PERLANE-NEXT:vmovaps %xmm1, 16(%rdi) +; AVX2-FAST-PERLANE-NEXT:vmovaps %xmm0, (%rdi) +; AVX2-FAST-PERLANE-NEXT:vzeroupper +; AVX2-FAST-PERLANE-NEXT:retq +; +; AVX512F-LABEL: foo: +; AVX512F: # %bb.0: # %entry +; AVX512F-NEXT:# kill: def $ymm0 killed $ymm0 def $zmm0 +; AVX512F-NEXT:vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512F-NEXT:vpmovqd %zmm0, (%rdi) +; AVX512F-NEXT:vzeroupper +; AVX512F-NEXT:retq +; +; AVX512VL-LABEL: foo: +; AVX512VL: # %bb.0: # %entry +; AVX512VL-NEXT:vpmovqd %ymm1, 16(%rdi) +; AVX512VL-NEXT:vpmovqd %ymm0, (%rdi) +; AVX512VL-NEXT:vzeroupper +; AVX512VL-NEXT:retq +; +; AVX512BW-LABEL: foo: +; AVX512BW: # %bb.0: # %entry +; AVX512BW-NEXT:# kill: def $ymm0 killed $ymm0 def $zmm0 +; AVX512BW-NEXT:vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512BW-NEXT:vpmovqd %zmm0, (%rdi) +; AVX512BW-NEXT:vzeroupper +; AVX512BW-NEXT:retq +; +; AVX512BWVL-LABEL: foo: +; AVX512BWVL: # %bb.0: # %entry +; AVX512BWVL-NEXT:vpmovqd %ymm1, 16(%rdi) +; AVX512BWVL-NEXT:vpmovqd %ymm0, (%rdi) +; AVX512BWVL-NEXT:vzeroupper +; AVX512BWVL-NEXT:retq +entry: + %0 = shufflevector <4 x i64> %a, <4 x i64> %b, <8 x i32> + %1 = trunc nsw <8 x i64> %0 to <8 x i32> + store <8 x i32> %1, ptr %p, align 16 + ret void +} ___ llvm-bran
[llvm-branch-commits] [clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)
https://github.com/joaosaffran edited https://github.com/llvm/llvm-project/pull/146785 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [AArch64][PAC] Introduce AArch64::PAC pseudo instruction (PR #146488)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/146488 >From ba9d8965de86e63cce18fc9c2d0fe9484f172e1f Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Sat, 28 Jun 2025 10:50:46 +0300 Subject: [PATCH 1/2] [AArch64][PAC] Introduce AArch64::PAC pseudo instruction Introduce a pseudo instruction to be selected instead of a pair of `MOVKXi` and `PAC[DI][AB]` carrying address and immediate modifiers as separate operands. The new pseudo instruction is expanded in AsmPrinter, so that MOVKXi is emitted immediately before `PAC[DI][AB]`. This way, an attacker cannot control the immediate modifier used to sign the value, even if address modifier can be substituted. To simplify the instruction selection, select AArch64::PAC pseudo using TableGen pattern and post-process its $AddrDisc operand by custom inserter hook - this eliminates duplication of the logic for DAGISel and GlobalISel. Furthermore, this improves cross-BB analysis in case of DAGISel. --- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 32 +++ .../Target/AArch64/AArch64ISelLowering.cpp| 74 +++ llvm/lib/Target/AArch64/AArch64ISelLowering.h | 7 + llvm/lib/Target/AArch64/AArch64InstrInfo.td | 21 +- llvm/test/CodeGen/AArch64/ptrauth-isel.ll | 205 ++ 5 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-isel.ll diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index dd10050592190..f34217a3a8133 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -171,6 +171,9 @@ class AArch64AsmPrinter : public AsmPrinter { // Emit the sequence for AUT or AUTPAC. void emitPtrauthAuthResign(const MachineInstr *MI); + // Emit the sequence for PAC. + void emitPtrauthSign(const MachineInstr *MI); + // Emit the sequence to compute the discriminator. // // ScratchReg should be x16/x17. @@ -2173,6 +2176,31 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) { OutStreamer->emitLabel(EndSym); } +void AArch64AsmPrinter::emitPtrauthSign(const MachineInstr *MI) { + Register Val = MI->getOperand(1).getReg(); + auto Key = (AArch64PACKey::ID)MI->getOperand(2).getImm(); + uint64_t Disc = MI->getOperand(3).getImm(); + Register AddrDisc = MI->getOperand(4).getReg(); + bool AddrDiscKilled = MI->getOperand(4).isKill(); + + // Compute aut discriminator into x17 + assert(isUInt<16>(Disc)); + Register DiscReg = emitPtrauthDiscriminator( + Disc, AddrDisc, AArch64::X17, /*MayUseAddrAsScratch=*/AddrDiscKilled); + bool IsZeroDisc = DiscReg == AArch64::XZR; + unsigned Opc = getPACOpcodeForKey(Key, IsZeroDisc); + + // paciza x16 ; if IsZeroDisc + // pacia x16, x17 ; if !IsZeroDisc + MCInst PACInst; + PACInst.setOpcode(Opc); + PACInst.addOperand(MCOperand::createReg(Val)); + PACInst.addOperand(MCOperand::createReg(Val)); + if (!IsZeroDisc) +PACInst.addOperand(MCOperand::createReg(DiscReg)); + EmitToStreamer(*OutStreamer, PACInst); +} + void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) { bool IsCall = MI->getOpcode() == AArch64::BLRA; unsigned BrTarget = MI->getOperand(0).getReg(); @@ -2867,6 +2895,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { emitPtrauthAuthResign(MI); return; + case AArch64::PAC: +emitPtrauthSign(MI); +return; + case AArch64::LOADauthptrstatic: LowerLOADauthptrstatic(*MI); return; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index fb8bd81c033af..c8eb9f3dd01ad 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3073,6 +3073,75 @@ AArch64TargetLowering::EmitGetSMESaveSize(MachineInstr &MI, return BB; } +// Helper function to find the instruction that defined a virtual register. +// If unable to find such instruction, returns nullptr. +static MachineInstr *stripVRegCopies(const MachineRegisterInfo &MRI, + Register Reg) { + while (Reg.isVirtual()) { +MachineInstr *DefMI = MRI.getVRegDef(Reg); +assert(DefMI && "Virtual register definition not found"); +unsigned Opcode = DefMI->getOpcode(); + +if (Opcode == AArch64::COPY) { + Reg = DefMI->getOperand(1).getReg(); + // Vreg is defined by copying from physreg. + if (Reg.isPhysical()) +return DefMI; + continue; +} +if (Opcode == AArch64::SUBREG_TO_REG) { + Reg = DefMI->getOperand(2).getReg(); + continue; +} + +return DefMI; + } + return nullptr; +} + +void AArch64TargetLowering::fixupBlendComponents( +MachineInstr &MI, MachineBasicBlock *BB, MachineOperand &IntDiscOp, +MachineOperand &AddrDiscOp, const TargetRegisterClass *AddrDiscRC) const { + const TargetInstrInfo *TII = Subt
[llvm-branch-commits] [llvm] [AArch64][PAC] Rework discriminator analysis in AUT and AUTPAC (PR #146489)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/146489 >From 13b218dc895bcfb176bfe5616c6479c3982cfde7 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Sat, 28 Jun 2025 11:09:01 +0300 Subject: [PATCH] [AArch64][PAC] Rework discriminator analysis in AUT and AUTPAC Make use of post-processing the discriminator components by custom inserter hook to eliminate duplication for DAGISel and GlobalISel and improve cross-BB analysis for DAGISel. --- .../Target/AArch64/AArch64ISelDAGToDAG.cpp| 51 +--- .../Target/AArch64/AArch64ISelLowering.cpp| 10 + llvm/lib/Target/AArch64/AArch64InstrInfo.td | 2 + .../GISel/AArch64InstructionSelector.cpp | 27 +- llvm/test/CodeGen/AArch64/ptrauth-isel.ll | 235 +- 5 files changed, 256 insertions(+), 69 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp index da617b7e19266..5d3fd48f448b5 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -1487,39 +1487,6 @@ void AArch64DAGToDAGISel::SelectTable(SDNode *N, unsigned NumVecs, unsigned Opc, ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops)); } -static std::tuple -extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG) { - SDLoc DL(Disc); - SDValue AddrDisc; - SDValue ConstDisc; - - // If this is a blend, remember the constant and address discriminators. - // Otherwise, it's either a constant discriminator, or a non-blended - // address discriminator. - if (Disc->getOpcode() == ISD::INTRINSIC_WO_CHAIN && - Disc->getConstantOperandVal(0) == Intrinsic::ptrauth_blend) { -AddrDisc = Disc->getOperand(1); -ConstDisc = Disc->getOperand(2); - } else { -ConstDisc = Disc; - } - - // If the constant discriminator (either the blend RHS, or the entire - // discriminator value) isn't a 16-bit constant, bail out, and let the - // discriminator be computed separately. - auto *ConstDiscN = dyn_cast(ConstDisc); - if (!ConstDiscN || !isUInt<16>(ConstDiscN->getZExtValue())) -return std::make_tuple(DAG->getTargetConstant(0, DL, MVT::i64), Disc); - - // If there's no address discriminator, use XZR directly. - if (!AddrDisc) -AddrDisc = DAG->getRegister(AArch64::XZR, MVT::i64); - - return std::make_tuple( - DAG->getTargetConstant(ConstDiscN->getZExtValue(), DL, MVT::i64), - AddrDisc); -} - void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) { SDLoc DL(N); // IntrinsicID is operand #0 @@ -1530,13 +1497,11 @@ void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) { unsigned AUTKeyC = cast(AUTKey)->getZExtValue(); AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64); - SDValue AUTAddrDisc, AUTConstDisc; - std::tie(AUTConstDisc, AUTAddrDisc) = - extractPtrauthBlendDiscriminators(AUTDisc, CurDAG); + SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i64); SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, AArch64::X16, Val, SDValue()); - SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X16Copy.getValue(1)}; + SDValue Ops[] = {AUTKey, Zero, AUTDisc, X16Copy.getValue(1)}; SDNode *AUT = CurDAG->getMachineNode(AArch64::AUT, DL, MVT::i64, Ops); ReplaceNode(N, AUT); @@ -1557,19 +1522,13 @@ void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *N) { AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64); PACKey = CurDAG->getTargetConstant(PACKeyC, DL, MVT::i64); - SDValue AUTAddrDisc, AUTConstDisc; - std::tie(AUTConstDisc, AUTAddrDisc) = - extractPtrauthBlendDiscriminators(AUTDisc, CurDAG); - - SDValue PACAddrDisc, PACConstDisc; - std::tie(PACConstDisc, PACAddrDisc) = - extractPtrauthBlendDiscriminators(PACDisc, CurDAG); + SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i64); SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, AArch64::X16, Val, SDValue()); - SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc,PACKey, - PACConstDisc, PACAddrDisc, X16Copy.getValue(1)}; + SDValue Ops[] = { + AUTKey, Zero, AUTDisc, PACKey, Zero, PACDisc, X16Copy.getValue(1)}; SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC, DL, MVT::i64, Ops); ReplaceNode(N, AUTPAC); diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 17f9f36474d9f..f6d763b3aef1a 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3242,10 +3242,20 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( case AArch64::MOVT_TIZ_PSEUDO: return EmitZTInstr(MI, BB, AArch64::MOVT_TIZ, /*Op0IsDef=*/true); + case AArch64::AUT: +fixupBlendComponents(MI, BB, MI.getOperand(1), MI.getOperand(2), +
[llvm-branch-commits] [llvm] [AArch64][PAC] Rework discriminator analysis in AUT and AUTPAC (PR #146489)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/146489 >From 13b218dc895bcfb176bfe5616c6479c3982cfde7 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Sat, 28 Jun 2025 11:09:01 +0300 Subject: [PATCH] [AArch64][PAC] Rework discriminator analysis in AUT and AUTPAC Make use of post-processing the discriminator components by custom inserter hook to eliminate duplication for DAGISel and GlobalISel and improve cross-BB analysis for DAGISel. --- .../Target/AArch64/AArch64ISelDAGToDAG.cpp| 51 +--- .../Target/AArch64/AArch64ISelLowering.cpp| 10 + llvm/lib/Target/AArch64/AArch64InstrInfo.td | 2 + .../GISel/AArch64InstructionSelector.cpp | 27 +- llvm/test/CodeGen/AArch64/ptrauth-isel.ll | 235 +- 5 files changed, 256 insertions(+), 69 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp index da617b7e19266..5d3fd48f448b5 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -1487,39 +1487,6 @@ void AArch64DAGToDAGISel::SelectTable(SDNode *N, unsigned NumVecs, unsigned Opc, ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops)); } -static std::tuple -extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG) { - SDLoc DL(Disc); - SDValue AddrDisc; - SDValue ConstDisc; - - // If this is a blend, remember the constant and address discriminators. - // Otherwise, it's either a constant discriminator, or a non-blended - // address discriminator. - if (Disc->getOpcode() == ISD::INTRINSIC_WO_CHAIN && - Disc->getConstantOperandVal(0) == Intrinsic::ptrauth_blend) { -AddrDisc = Disc->getOperand(1); -ConstDisc = Disc->getOperand(2); - } else { -ConstDisc = Disc; - } - - // If the constant discriminator (either the blend RHS, or the entire - // discriminator value) isn't a 16-bit constant, bail out, and let the - // discriminator be computed separately. - auto *ConstDiscN = dyn_cast(ConstDisc); - if (!ConstDiscN || !isUInt<16>(ConstDiscN->getZExtValue())) -return std::make_tuple(DAG->getTargetConstant(0, DL, MVT::i64), Disc); - - // If there's no address discriminator, use XZR directly. - if (!AddrDisc) -AddrDisc = DAG->getRegister(AArch64::XZR, MVT::i64); - - return std::make_tuple( - DAG->getTargetConstant(ConstDiscN->getZExtValue(), DL, MVT::i64), - AddrDisc); -} - void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) { SDLoc DL(N); // IntrinsicID is operand #0 @@ -1530,13 +1497,11 @@ void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) { unsigned AUTKeyC = cast(AUTKey)->getZExtValue(); AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64); - SDValue AUTAddrDisc, AUTConstDisc; - std::tie(AUTConstDisc, AUTAddrDisc) = - extractPtrauthBlendDiscriminators(AUTDisc, CurDAG); + SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i64); SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, AArch64::X16, Val, SDValue()); - SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X16Copy.getValue(1)}; + SDValue Ops[] = {AUTKey, Zero, AUTDisc, X16Copy.getValue(1)}; SDNode *AUT = CurDAG->getMachineNode(AArch64::AUT, DL, MVT::i64, Ops); ReplaceNode(N, AUT); @@ -1557,19 +1522,13 @@ void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *N) { AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64); PACKey = CurDAG->getTargetConstant(PACKeyC, DL, MVT::i64); - SDValue AUTAddrDisc, AUTConstDisc; - std::tie(AUTConstDisc, AUTAddrDisc) = - extractPtrauthBlendDiscriminators(AUTDisc, CurDAG); - - SDValue PACAddrDisc, PACConstDisc; - std::tie(PACConstDisc, PACAddrDisc) = - extractPtrauthBlendDiscriminators(PACDisc, CurDAG); + SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i64); SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, AArch64::X16, Val, SDValue()); - SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc,PACKey, - PACConstDisc, PACAddrDisc, X16Copy.getValue(1)}; + SDValue Ops[] = { + AUTKey, Zero, AUTDisc, PACKey, Zero, PACDisc, X16Copy.getValue(1)}; SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC, DL, MVT::i64, Ops); ReplaceNode(N, AUTPAC); diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 17f9f36474d9f..f6d763b3aef1a 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3242,10 +3242,20 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( case AArch64::MOVT_TIZ_PSEUDO: return EmitZTInstr(MI, BB, AArch64::MOVT_TIZ, /*Op0IsDef=*/true); + case AArch64::AUT: +fixupBlendComponents(MI, BB, MI.getOperand(1), MI.getOperand(2), +
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147115)
https://github.com/inbelic created https://github.com/llvm/llvm-project/pull/147115 At the moment, when we report diagnostics from `SemaHLSL` we only provide the source location of the root signature attr. This allows for significantly less helpful diagnostics (for eg. reporting resource range overlaps). This pr implements a way to retain the source location of a root element when it is parsed, so that we can output the `SourceLocation` of each root element that causes the overlap in the diagnostics during semantic analysis. This pr defines a wrapper struct `clang::hlsl::RootSignatureElement` in `SemaHLSL` that will contain the underlying `RootElement` and can hold any additional diagnostic information. This struct will be what is used in `HLSLRootSignatureParser` and in `SemaHLSL`. Then the diagnostic information will be stripped and the underlying element will be stored in the `RootSignatureDecl`. For the reporting of diagnostics, we can now use the retained `SourceLocation` of each `RootElement` when reporting the range overlap, and we can add a `note` diagnostic to highlight the other root element as well. - Defines `RootSignatureElement` in the `hlsl` namespace in `SemaHLSL` (defined in `SemaHLSL` because `Parse` has a dependency on `Sema`) - Updates parsing logic to construct `RootSignatureElement`s and retain the source loction in `ParseHLSLRootSignature` - Updates `SemaHLSL` when it constructs the `RootSignatureDecl` to take the new `RootSignatureElement` and store the underlying `RootElement` - Updates the current tests to ensure the new `note` diagnostic is produced and that the `SourceLocation` is seen - Adds a test to demonstrate the `SourceLocation` of both elements being correctly pointed out Resolves: https://github.com/llvm/llvm-project/issues/145819 >From 4a5cde3f77dc0c371d1f33b10be9507d3aeff3e3 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 27 Jun 2025 18:36:38 + Subject: [PATCH 1/8] nfc: introduce wrapper `RootSignatureElement` around `RootElement` to retain clang diag info --- .../clang/Parse/ParseHLSLRootSignature.h | 17 ++- clang/include/clang/Sema/SemaHLSL.h | 10 +- clang/lib/Parse/ParseDeclCXX.cpp | 2 +- clang/lib/Parse/ParseHLSLRootSignature.cpp| 21 ++-- clang/lib/Sema/SemaHLSL.cpp | 6 +- .../Parse/ParseHLSLRootSignatureTest.cpp | 115 +- 6 files changed, 99 insertions(+), 72 deletions(-) diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index b0ef617a13c28..53001d2ba461f 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -26,10 +26,22 @@ namespace clang { namespace hlsl { +// Introduce a wrapper struct around the underlying RootElement. This structure +// will retain extra clang diagnostic information that is not available in llvm. +struct RootSignatureElement { + RootSignatureElement(llvm::hlsl::rootsig::RootElement Element) + : Element(Element) {} + + const llvm::hlsl::rootsig::RootElement &getElement() const { return Element; } + +private: + llvm::hlsl::rootsig::RootElement Element; +}; + class RootSignatureParser { public: RootSignatureParser(llvm::dxbc::RootSignatureVersion Version, - SmallVector &Elements, + SmallVector &Elements, StringLiteral *Signature, Preprocessor &PP); /// Consumes tokens from the Lexer and constructs the in-memory @@ -196,7 +208,8 @@ class RootSignatureParser { private: llvm::dxbc::RootSignatureVersion Version; - SmallVector &Elements; + SmallVector &Elements; + clang::StringLiteral *Signature; RootSignatureLexer Lexer; clang::Preprocessor &PP; diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 7d7eae4db532c..1af706da702c2 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -32,6 +32,10 @@ class ParsedAttr; class Scope; class VarDecl; +namespace hlsl { +struct RootSignatureElement; +} + using llvm::dxil::ResourceClass; // FIXME: This can be hidden (as static function in SemaHLSL.cpp) once we no @@ -130,9 +134,9 @@ class SemaHLSL : public SemaBase { /// Creates the Root Signature decl of the parsed Root Signature elements /// onto the AST and push it onto current Scope - void ActOnFinishRootSignatureDecl( - SourceLocation Loc, IdentifierInfo *DeclIdent, - SmallVector &Elements); + void + ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, + ArrayRef Elements); // Returns true when D is invalid and a diagnostic was produced bool handleRootSignatureDecl(HLSLRootSignatureDecl *D, SourceLocation Loc); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d3bc6f1e89832..d06bb6a25efa5 100
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147115)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Finn Plummer (inbelic) Changes At the moment, when we report diagnostics from `SemaHLSL` we only provide the source location of the root signature attr. This allows for significantly less helpful diagnostics (for eg. reporting resource range overlaps). This pr implements a way to retain the source location of a root element when it is parsed, so that we can output the `SourceLocation` of each root element that causes the overlap in the diagnostics during semantic analysis. This pr defines a wrapper struct `clang::hlsl::RootSignatureElement` in `SemaHLSL` that will contain the underlying `RootElement` and can hold any additional diagnostic information. This struct will be what is used in `HLSLRootSignatureParser` and in `SemaHLSL`. Then the diagnostic information will be stripped and the underlying element will be stored in the `RootSignatureDecl`. For the reporting of diagnostics, we can now use the retained `SourceLocation` of each `RootElement` when reporting the range overlap, and we can add a `note` diagnostic to highlight the other root element as well. - Defines `RootSignatureElement` in the `hlsl` namespace in `SemaHLSL` (defined in `SemaHLSL` because `Parse` has a dependency on `Sema`) - Updates parsing logic to construct `RootSignatureElement`s and retain the source loction in `ParseHLSLRootSignature` - Updates `SemaHLSL` when it constructs the `RootSignatureDecl` to take the new `RootSignatureElement` and store the underlying `RootElement` - Updates the current tests to ensure the new `note` diagnostic is produced and that the `SourceLocation` is seen - Adds a test to demonstrate the `SourceLocation` of both elements being correctly pointed out Resolves: https://github.com/llvm/llvm-project/issues/145819 --- Patch is 44.85 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/147115.diff 9 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+1) - (modified) clang/include/clang/Parse/ParseHLSLRootSignature.h (+4-2) - (modified) clang/include/clang/Sema/SemaHLSL.h (+25-4) - (modified) clang/lib/Parse/ParseDeclCXX.cpp (+1-1) - (modified) clang/lib/Parse/ParseHLSLRootSignature.cpp (+19-8) - (modified) clang/lib/Sema/SemaHLSL.cpp (+38-10) - (modified) clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl (+41) - (modified) clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp (+74-73) - (modified) llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h (+3) ``diff diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 968edd967e0c5..4fe0abb972a61 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13079,6 +13079,7 @@ def err_hlsl_resource_range_overlap: Error< "resource ranges %sub{subst_hlsl_format_ranges}0,1,2,3 and %sub{subst_hlsl_format_ranges}4,5,6,7 " "overlap within space = %8 and visibility = " "%select{All|Vertex|Hull|Domain|Geometry|Pixel|Amplification|Mesh}9">; +def note_hlsl_resource_range_here: Note<"overlapping resource range here">; // Layout randomization diagnostics. def err_non_designated_init_used : Error< diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index b0ef617a13c28..9ef5b64d7b4a5 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -17,6 +17,7 @@ #include "clang/Basic/DiagnosticParse.h" #include "clang/Lex/LexHLSLRootSignature.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/SemaHLSL.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -29,7 +30,7 @@ namespace hlsl { class RootSignatureParser { public: RootSignatureParser(llvm::dxbc::RootSignatureVersion Version, - SmallVector &Elements, + SmallVector &Elements, StringLiteral *Signature, Preprocessor &PP); /// Consumes tokens from the Lexer and constructs the in-memory @@ -196,7 +197,8 @@ class RootSignatureParser { private: llvm::dxbc::RootSignatureVersion Version; - SmallVector &Elements; + SmallVector &Elements; + clang::StringLiteral *Signature; RootSignatureLexer Lexer; clang::Preprocessor &PP; diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 7d7eae4db532c..910e0e640796b 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -32,6 +32,25 @@ class ParsedAttr; class Scope; class VarDecl; +namespace hlsl { + +// Introduce a wrapper struct around the underlying RootElement. This structure +// will retain extra clang diagnostic information that is not available in llvm. +struct RootSignatureElement { + RootSignatureElement(SourceLocation Loc, +
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147094)
inbelic wrote: Whoops, accidently pushed to the wrong upstream branch. Looks like I can't unmerge it to the stacked branch... https://github.com/llvm/llvm-project/pull/147094 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147094)
https://github.com/inbelic closed https://github.com/llvm/llvm-project/pull/147094 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147115)
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/147115 >From 4a5cde3f77dc0c371d1f33b10be9507d3aeff3e3 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 27 Jun 2025 18:36:38 + Subject: [PATCH 1/9] nfc: introduce wrapper `RootSignatureElement` around `RootElement` to retain clang diag info --- .../clang/Parse/ParseHLSLRootSignature.h | 17 ++- clang/include/clang/Sema/SemaHLSL.h | 10 +- clang/lib/Parse/ParseDeclCXX.cpp | 2 +- clang/lib/Parse/ParseHLSLRootSignature.cpp| 21 ++-- clang/lib/Sema/SemaHLSL.cpp | 6 +- .../Parse/ParseHLSLRootSignatureTest.cpp | 115 +- 6 files changed, 99 insertions(+), 72 deletions(-) diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index b0ef617a13c28..53001d2ba461f 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -26,10 +26,22 @@ namespace clang { namespace hlsl { +// Introduce a wrapper struct around the underlying RootElement. This structure +// will retain extra clang diagnostic information that is not available in llvm. +struct RootSignatureElement { + RootSignatureElement(llvm::hlsl::rootsig::RootElement Element) + : Element(Element) {} + + const llvm::hlsl::rootsig::RootElement &getElement() const { return Element; } + +private: + llvm::hlsl::rootsig::RootElement Element; +}; + class RootSignatureParser { public: RootSignatureParser(llvm::dxbc::RootSignatureVersion Version, - SmallVector &Elements, + SmallVector &Elements, StringLiteral *Signature, Preprocessor &PP); /// Consumes tokens from the Lexer and constructs the in-memory @@ -196,7 +208,8 @@ class RootSignatureParser { private: llvm::dxbc::RootSignatureVersion Version; - SmallVector &Elements; + SmallVector &Elements; + clang::StringLiteral *Signature; RootSignatureLexer Lexer; clang::Preprocessor &PP; diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 7d7eae4db532c..1af706da702c2 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -32,6 +32,10 @@ class ParsedAttr; class Scope; class VarDecl; +namespace hlsl { +struct RootSignatureElement; +} + using llvm::dxil::ResourceClass; // FIXME: This can be hidden (as static function in SemaHLSL.cpp) once we no @@ -130,9 +134,9 @@ class SemaHLSL : public SemaBase { /// Creates the Root Signature decl of the parsed Root Signature elements /// onto the AST and push it onto current Scope - void ActOnFinishRootSignatureDecl( - SourceLocation Loc, IdentifierInfo *DeclIdent, - SmallVector &Elements); + void + ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, + ArrayRef Elements); // Returns true when D is invalid and a diagnostic was produced bool handleRootSignatureDecl(HLSLRootSignatureDecl *D, SourceLocation Loc); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d3bc6f1e89832..d06bb6a25efa5 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -4951,7 +4951,7 @@ void Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) { // signature string and construct the in-memory elements if (!Found) { // Invoke the root signature parser to construct the in-memory constructs -SmallVector RootElements; +SmallVector RootElements; hlsl::RootSignatureParser Parser(getLangOpts().HLSLRootSigVer, RootElements, Signature, PP); if (Parser.parse()) { diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index ebaf7ba60fa17..76e50fb85c8d7 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -19,33 +19,34 @@ using TokenKind = RootSignatureToken::Kind; RootSignatureParser::RootSignatureParser( llvm::dxbc::RootSignatureVersion Version, -SmallVector &Elements, StringLiteral *Signature, +SmallVector &Elements, StringLiteral *Signature, Preprocessor &PP) : Version(Version), Elements(Elements), Signature(Signature), Lexer(Signature->getString()), PP(PP), CurToken(0) {} bool RootSignatureParser::parse() { - // Iterate as many RootElements as possible + // Iterate as many RootSignatureElements as possible do { +std::optional Element = std::nullopt; if (tryConsumeExpectedToken(TokenKind::kw_RootFlags)) { auto Flags = parseRootFlags(); if (!Flags.has_value()) return true; - Elements.push_back(*Flags); + Element = RootSignatureElement(*Flags); } if (tryConsumeExpectedToken(TokenKind::kw_RootConstants)) { auto Co
[llvm-branch-commits] [clang] [llvm] [NFC][HLSL] Move resource range logic from `SemaHLSL` to `RootSignatureValidations` (PR #147117)
https://github.com/inbelic created https://github.com/llvm/llvm-project/pull/147117 This pr abstracts out the logic of detecting resource range overlap from `SemaHLSL` into the `RootSignatureValidations` library. For more context see linked issue. - Moves the validation logic from `SemaHLSL` to `RootSignatureValidations` - Updates `SemaHLSL` to use the new interface for the validations Resolves: https://github.com/llvm/llvm-project/issues/146393 >From 969f316004ae500d707be081e6f2f4abc669fff3 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 27 Jun 2025 19:58:15 + Subject: [PATCH] nfc: move collection of overlaps to `RootSignatureValidations` --- clang/lib/Sema/SemaHLSL.cpp | 101 ++ .../Frontend/HLSL/RootSignatureValidations.h | 32 ++ .../HLSL/RootSignatureValidations.cpp | 73 + 3 files changed, 115 insertions(+), 91 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 3feb27ac44bd6..18b84c33b39c8 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1083,29 +1083,8 @@ void SemaHLSL::ActOnFinishRootSignatureDecl( bool SemaHLSL::handleRootSignatureElements( ArrayRef Elements) { - // The following conducts analysis on resource ranges to detect and report - // any overlaps in resource ranges. - // - // A resource range overlaps with another resource range if they have: - // - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler) - // - equivalent resource space - // - overlapping visbility - // - // The following algorithm is implemented in the following steps: - // - // 1. Collect RangeInfo from relevant RootElements: - // - RangeInfo will retain the interval, ResourceClass, Space and Visibility - // 2. Sort the RangeInfo's such that they are grouped together by - // ResourceClass and Space (GroupT defined below) - // 3. Iterate through the collected RangeInfos by their groups - // - For each group we will have a ResourceRange for each visibility - // - As we iterate through we will: - // A: Insert the current RangeInfo into the corresponding Visibility - // ResourceRange - // B: Check for overlap with any overlapping Visibility ResourceRange using RangeInfo = llvm::hlsl::rootsig::RangeInfo; - using ResourceRange = llvm::hlsl::rootsig::ResourceRange; - using GroupT = std::pair; + using OverlappingRanges = llvm::hlsl::rootsig::OverlappingRanges; // Introduce a mapping from the collected RangeInfos back to the // RootSignatureElement that will retain its diagnostics info @@ -1188,40 +1167,10 @@ bool SemaHLSL::handleRootSignatureElements( } } - // 2. Sort the RangeInfo's by their GroupT to form groupings - std::sort(Infos.begin(), Infos.end(), [](RangeInfo A, RangeInfo B) { -return std::tie(A.Class, A.Space) < std::tie(B.Class, B.Space); - }); - - // 3. First we will init our state to track: - if (Infos.size() == 0) -return false; // No ranges to overlap - GroupT CurGroup = {Infos[0].Class, Infos[0].Space}; - bool HadOverlap = false; - - // Create a ResourceRange for each Visibility - ResourceRange::MapT::Allocator Allocator; - std::array Ranges = { - ResourceRange(Allocator), // All - ResourceRange(Allocator), // Vertex - ResourceRange(Allocator), // Hull - ResourceRange(Allocator), // Domain - ResourceRange(Allocator), // Geometry - ResourceRange(Allocator), // Pixel - ResourceRange(Allocator), // Amplification - ResourceRange(Allocator), // Mesh - }; - - // Reset the ResourceRanges for when we iterate through a new group - auto ClearRanges = [&Ranges]() { -for (ResourceRange &Range : Ranges) - Range.clear(); - }; - // Helper to report diagnostics - auto ReportOverlap = [this, InfoIndexMap, &HadOverlap]( - const RangeInfo *Info, const RangeInfo *OInfo) { -HadOverlap = true; + auto ReportOverlap = [this, InfoIndexMap](OverlappingRanges Overlap) { +const RangeInfo *Info = Overlap.A; +const RangeInfo *OInfo = Overlap.B; auto CommonVis = Info->Visibility == llvm::dxbc::ShaderVisibility::All ? OInfo->Visibility : Info->Visibility; @@ -1240,42 +1189,12 @@ bool SemaHLSL::handleRootSignatureElements( this->Diag(OInfoLoc, diag::note_hlsl_resource_range_here); }; - // 3: Iterate through collected RangeInfos - for (const RangeInfo &Info : Infos) { -GroupT InfoGroup = {Info.Class, Info.Space}; -// Reset our ResourceRanges when we enter a new group -if (CurGroup != InfoGroup) { - ClearRanges(); - CurGroup = InfoGroup; -} - -// 3A: Insert range info into corresponding Visibility ResourceRange -ResourceRange &VisRange = Ranges[llvm::to_underlying(Info.Visibility)]; -if (std::optional Overlapping = VisRange.insert(Info)) - ReportOverlap(&Info, Overlapping.value()); - -// 3B: Check for
[llvm-branch-commits] [clang] [llvm] [NFC][HLSL] Move resource range logic from `SemaHLSL` to `RootSignatureValidations` (PR #147117)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Finn Plummer (inbelic) Changes This pr abstracts out the logic of detecting resource range overlap from `SemaHLSL` into the `RootSignatureValidations` library. For more context see linked issue. - Moves the validation logic from `SemaHLSL` to `RootSignatureValidations` - Updates `SemaHLSL` to use the new interface for the validations Resolves: https://github.com/llvm/llvm-project/issues/146393 --- Full diff: https://github.com/llvm/llvm-project/pull/147117.diff 3 Files Affected: - (modified) clang/lib/Sema/SemaHLSL.cpp (+10-91) - (modified) llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h (+32) - (modified) llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp (+73) ``diff diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 3feb27ac44bd6..18b84c33b39c8 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1083,29 +1083,8 @@ void SemaHLSL::ActOnFinishRootSignatureDecl( bool SemaHLSL::handleRootSignatureElements( ArrayRef Elements) { - // The following conducts analysis on resource ranges to detect and report - // any overlaps in resource ranges. - // - // A resource range overlaps with another resource range if they have: - // - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler) - // - equivalent resource space - // - overlapping visbility - // - // The following algorithm is implemented in the following steps: - // - // 1. Collect RangeInfo from relevant RootElements: - // - RangeInfo will retain the interval, ResourceClass, Space and Visibility - // 2. Sort the RangeInfo's such that they are grouped together by - // ResourceClass and Space (GroupT defined below) - // 3. Iterate through the collected RangeInfos by their groups - // - For each group we will have a ResourceRange for each visibility - // - As we iterate through we will: - // A: Insert the current RangeInfo into the corresponding Visibility - // ResourceRange - // B: Check for overlap with any overlapping Visibility ResourceRange using RangeInfo = llvm::hlsl::rootsig::RangeInfo; - using ResourceRange = llvm::hlsl::rootsig::ResourceRange; - using GroupT = std::pair; + using OverlappingRanges = llvm::hlsl::rootsig::OverlappingRanges; // Introduce a mapping from the collected RangeInfos back to the // RootSignatureElement that will retain its diagnostics info @@ -1188,40 +1167,10 @@ bool SemaHLSL::handleRootSignatureElements( } } - // 2. Sort the RangeInfo's by their GroupT to form groupings - std::sort(Infos.begin(), Infos.end(), [](RangeInfo A, RangeInfo B) { -return std::tie(A.Class, A.Space) < std::tie(B.Class, B.Space); - }); - - // 3. First we will init our state to track: - if (Infos.size() == 0) -return false; // No ranges to overlap - GroupT CurGroup = {Infos[0].Class, Infos[0].Space}; - bool HadOverlap = false; - - // Create a ResourceRange for each Visibility - ResourceRange::MapT::Allocator Allocator; - std::array Ranges = { - ResourceRange(Allocator), // All - ResourceRange(Allocator), // Vertex - ResourceRange(Allocator), // Hull - ResourceRange(Allocator), // Domain - ResourceRange(Allocator), // Geometry - ResourceRange(Allocator), // Pixel - ResourceRange(Allocator), // Amplification - ResourceRange(Allocator), // Mesh - }; - - // Reset the ResourceRanges for when we iterate through a new group - auto ClearRanges = [&Ranges]() { -for (ResourceRange &Range : Ranges) - Range.clear(); - }; - // Helper to report diagnostics - auto ReportOverlap = [this, InfoIndexMap, &HadOverlap]( - const RangeInfo *Info, const RangeInfo *OInfo) { -HadOverlap = true; + auto ReportOverlap = [this, InfoIndexMap](OverlappingRanges Overlap) { +const RangeInfo *Info = Overlap.A; +const RangeInfo *OInfo = Overlap.B; auto CommonVis = Info->Visibility == llvm::dxbc::ShaderVisibility::All ? OInfo->Visibility : Info->Visibility; @@ -1240,42 +1189,12 @@ bool SemaHLSL::handleRootSignatureElements( this->Diag(OInfoLoc, diag::note_hlsl_resource_range_here); }; - // 3: Iterate through collected RangeInfos - for (const RangeInfo &Info : Infos) { -GroupT InfoGroup = {Info.Class, Info.Space}; -// Reset our ResourceRanges when we enter a new group -if (CurGroup != InfoGroup) { - ClearRanges(); - CurGroup = InfoGroup; -} - -// 3A: Insert range info into corresponding Visibility ResourceRange -ResourceRange &VisRange = Ranges[llvm::to_underlying(Info.Visibility)]; -if (std::optional Overlapping = VisRange.insert(Info)) - ReportOverlap(&Info, Overlapping.value()); - -// 3B: Check for overlap in all overlapping Visibility ResourceRanges -// -// If the range that we are inserting has ShaderVisiblity::All it needs to -// check f
[llvm-branch-commits] [clang] [llvm] [NFC][HLSL] Move resource range logic from `SemaHLSL` to `RootSignatureValidations` (PR #147117)
llvmbot wrote: @llvm/pr-subscribers-hlsl Author: Finn Plummer (inbelic) Changes This pr abstracts out the logic of detecting resource range overlap from `SemaHLSL` into the `RootSignatureValidations` library. For more context see linked issue. - Moves the validation logic from `SemaHLSL` to `RootSignatureValidations` - Updates `SemaHLSL` to use the new interface for the validations Resolves: https://github.com/llvm/llvm-project/issues/146393 --- Full diff: https://github.com/llvm/llvm-project/pull/147117.diff 3 Files Affected: - (modified) clang/lib/Sema/SemaHLSL.cpp (+10-91) - (modified) llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h (+32) - (modified) llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp (+73) ``diff diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 3feb27ac44bd6..18b84c33b39c8 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1083,29 +1083,8 @@ void SemaHLSL::ActOnFinishRootSignatureDecl( bool SemaHLSL::handleRootSignatureElements( ArrayRef Elements) { - // The following conducts analysis on resource ranges to detect and report - // any overlaps in resource ranges. - // - // A resource range overlaps with another resource range if they have: - // - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler) - // - equivalent resource space - // - overlapping visbility - // - // The following algorithm is implemented in the following steps: - // - // 1. Collect RangeInfo from relevant RootElements: - // - RangeInfo will retain the interval, ResourceClass, Space and Visibility - // 2. Sort the RangeInfo's such that they are grouped together by - // ResourceClass and Space (GroupT defined below) - // 3. Iterate through the collected RangeInfos by their groups - // - For each group we will have a ResourceRange for each visibility - // - As we iterate through we will: - // A: Insert the current RangeInfo into the corresponding Visibility - // ResourceRange - // B: Check for overlap with any overlapping Visibility ResourceRange using RangeInfo = llvm::hlsl::rootsig::RangeInfo; - using ResourceRange = llvm::hlsl::rootsig::ResourceRange; - using GroupT = std::pair; + using OverlappingRanges = llvm::hlsl::rootsig::OverlappingRanges; // Introduce a mapping from the collected RangeInfos back to the // RootSignatureElement that will retain its diagnostics info @@ -1188,40 +1167,10 @@ bool SemaHLSL::handleRootSignatureElements( } } - // 2. Sort the RangeInfo's by their GroupT to form groupings - std::sort(Infos.begin(), Infos.end(), [](RangeInfo A, RangeInfo B) { -return std::tie(A.Class, A.Space) < std::tie(B.Class, B.Space); - }); - - // 3. First we will init our state to track: - if (Infos.size() == 0) -return false; // No ranges to overlap - GroupT CurGroup = {Infos[0].Class, Infos[0].Space}; - bool HadOverlap = false; - - // Create a ResourceRange for each Visibility - ResourceRange::MapT::Allocator Allocator; - std::array Ranges = { - ResourceRange(Allocator), // All - ResourceRange(Allocator), // Vertex - ResourceRange(Allocator), // Hull - ResourceRange(Allocator), // Domain - ResourceRange(Allocator), // Geometry - ResourceRange(Allocator), // Pixel - ResourceRange(Allocator), // Amplification - ResourceRange(Allocator), // Mesh - }; - - // Reset the ResourceRanges for when we iterate through a new group - auto ClearRanges = [&Ranges]() { -for (ResourceRange &Range : Ranges) - Range.clear(); - }; - // Helper to report diagnostics - auto ReportOverlap = [this, InfoIndexMap, &HadOverlap]( - const RangeInfo *Info, const RangeInfo *OInfo) { -HadOverlap = true; + auto ReportOverlap = [this, InfoIndexMap](OverlappingRanges Overlap) { +const RangeInfo *Info = Overlap.A; +const RangeInfo *OInfo = Overlap.B; auto CommonVis = Info->Visibility == llvm::dxbc::ShaderVisibility::All ? OInfo->Visibility : Info->Visibility; @@ -1240,42 +1189,12 @@ bool SemaHLSL::handleRootSignatureElements( this->Diag(OInfoLoc, diag::note_hlsl_resource_range_here); }; - // 3: Iterate through collected RangeInfos - for (const RangeInfo &Info : Infos) { -GroupT InfoGroup = {Info.Class, Info.Space}; -// Reset our ResourceRanges when we enter a new group -if (CurGroup != InfoGroup) { - ClearRanges(); - CurGroup = InfoGroup; -} - -// 3A: Insert range info into corresponding Visibility ResourceRange -ResourceRange &VisRange = Ranges[llvm::to_underlying(Info.Visibility)]; -if (std::optional Overlapping = VisRange.insert(Info)) - ReportOverlap(&Info, Overlapping.value()); - -// 3B: Check for overlap in all overlapping Visibility ResourceRanges -// -// If the range that we are inserting has ShaderVisiblity::All it needs to -// check fo
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147115)
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/147115 >From 4a5cde3f77dc0c371d1f33b10be9507d3aeff3e3 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 27 Jun 2025 18:36:38 + Subject: [PATCH 1/9] nfc: introduce wrapper `RootSignatureElement` around `RootElement` to retain clang diag info --- .../clang/Parse/ParseHLSLRootSignature.h | 17 ++- clang/include/clang/Sema/SemaHLSL.h | 10 +- clang/lib/Parse/ParseDeclCXX.cpp | 2 +- clang/lib/Parse/ParseHLSLRootSignature.cpp| 21 ++-- clang/lib/Sema/SemaHLSL.cpp | 6 +- .../Parse/ParseHLSLRootSignatureTest.cpp | 115 +- 6 files changed, 99 insertions(+), 72 deletions(-) diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index b0ef617a13c28..53001d2ba461f 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -26,10 +26,22 @@ namespace clang { namespace hlsl { +// Introduce a wrapper struct around the underlying RootElement. This structure +// will retain extra clang diagnostic information that is not available in llvm. +struct RootSignatureElement { + RootSignatureElement(llvm::hlsl::rootsig::RootElement Element) + : Element(Element) {} + + const llvm::hlsl::rootsig::RootElement &getElement() const { return Element; } + +private: + llvm::hlsl::rootsig::RootElement Element; +}; + class RootSignatureParser { public: RootSignatureParser(llvm::dxbc::RootSignatureVersion Version, - SmallVector &Elements, + SmallVector &Elements, StringLiteral *Signature, Preprocessor &PP); /// Consumes tokens from the Lexer and constructs the in-memory @@ -196,7 +208,8 @@ class RootSignatureParser { private: llvm::dxbc::RootSignatureVersion Version; - SmallVector &Elements; + SmallVector &Elements; + clang::StringLiteral *Signature; RootSignatureLexer Lexer; clang::Preprocessor &PP; diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 7d7eae4db532c..1af706da702c2 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -32,6 +32,10 @@ class ParsedAttr; class Scope; class VarDecl; +namespace hlsl { +struct RootSignatureElement; +} + using llvm::dxil::ResourceClass; // FIXME: This can be hidden (as static function in SemaHLSL.cpp) once we no @@ -130,9 +134,9 @@ class SemaHLSL : public SemaBase { /// Creates the Root Signature decl of the parsed Root Signature elements /// onto the AST and push it onto current Scope - void ActOnFinishRootSignatureDecl( - SourceLocation Loc, IdentifierInfo *DeclIdent, - SmallVector &Elements); + void + ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, + ArrayRef Elements); // Returns true when D is invalid and a diagnostic was produced bool handleRootSignatureDecl(HLSLRootSignatureDecl *D, SourceLocation Loc); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d3bc6f1e89832..d06bb6a25efa5 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -4951,7 +4951,7 @@ void Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) { // signature string and construct the in-memory elements if (!Found) { // Invoke the root signature parser to construct the in-memory constructs -SmallVector RootElements; +SmallVector RootElements; hlsl::RootSignatureParser Parser(getLangOpts().HLSLRootSigVer, RootElements, Signature, PP); if (Parser.parse()) { diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index ebaf7ba60fa17..76e50fb85c8d7 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -19,33 +19,34 @@ using TokenKind = RootSignatureToken::Kind; RootSignatureParser::RootSignatureParser( llvm::dxbc::RootSignatureVersion Version, -SmallVector &Elements, StringLiteral *Signature, +SmallVector &Elements, StringLiteral *Signature, Preprocessor &PP) : Version(Version), Elements(Elements), Signature(Signature), Lexer(Signature->getString()), PP(PP), CurToken(0) {} bool RootSignatureParser::parse() { - // Iterate as many RootElements as possible + // Iterate as many RootSignatureElements as possible do { +std::optional Element = std::nullopt; if (tryConsumeExpectedToken(TokenKind::kw_RootFlags)) { auto Flags = parseRootFlags(); if (!Flags.has_value()) return true; - Elements.push_back(*Flags); + Element = RootSignatureElement(*Flags); } if (tryConsumeExpectedToken(TokenKind::kw_RootConstants)) { auto Co
[llvm-branch-commits] [clang] [llvm] [NFC][HLSL] Move resource range logic from `SemaHLSL` to `RootSignatureValidations` (PR #147117)
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/147117 >From d66a67d9660ab1114d55f75ef2ad5a9cfd35f8f6 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 4 Jul 2025 22:17:37 + Subject: [PATCH 1/2] self-review: remove unused Loc --- clang/include/clang/Sema/SemaHLSL.h | 3 +-- clang/lib/Sema/SemaHLSL.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 910e0e640796b..42abd29b01ea7 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -155,8 +155,7 @@ class SemaHLSL : public SemaBase { // Returns true when D is invalid and a diagnostic was produced bool - handleRootSignatureElements(ArrayRef Elements, - SourceLocation Loc); + handleRootSignatureElements(ArrayRef Elements); void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL); void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL); void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL); diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index f490f957f9667..3feb27ac44bd6 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1082,7 +1082,7 @@ void SemaHLSL::ActOnFinishRootSignatureDecl( } bool SemaHLSL::handleRootSignatureElements( -ArrayRef Elements, SourceLocation Loc) { +ArrayRef Elements) { // The following conducts analysis on resource ranges to detect and report // any overlaps in resource ranges. // >From 969f316004ae500d707be081e6f2f4abc669fff3 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 27 Jun 2025 19:58:15 + Subject: [PATCH 2/2] nfc: move collection of overlaps to `RootSignatureValidations` --- clang/lib/Sema/SemaHLSL.cpp | 101 ++ .../Frontend/HLSL/RootSignatureValidations.h | 32 ++ .../HLSL/RootSignatureValidations.cpp | 73 + 3 files changed, 115 insertions(+), 91 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 3feb27ac44bd6..18b84c33b39c8 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1083,29 +1083,8 @@ void SemaHLSL::ActOnFinishRootSignatureDecl( bool SemaHLSL::handleRootSignatureElements( ArrayRef Elements) { - // The following conducts analysis on resource ranges to detect and report - // any overlaps in resource ranges. - // - // A resource range overlaps with another resource range if they have: - // - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler) - // - equivalent resource space - // - overlapping visbility - // - // The following algorithm is implemented in the following steps: - // - // 1. Collect RangeInfo from relevant RootElements: - // - RangeInfo will retain the interval, ResourceClass, Space and Visibility - // 2. Sort the RangeInfo's such that they are grouped together by - // ResourceClass and Space (GroupT defined below) - // 3. Iterate through the collected RangeInfos by their groups - // - For each group we will have a ResourceRange for each visibility - // - As we iterate through we will: - // A: Insert the current RangeInfo into the corresponding Visibility - // ResourceRange - // B: Check for overlap with any overlapping Visibility ResourceRange using RangeInfo = llvm::hlsl::rootsig::RangeInfo; - using ResourceRange = llvm::hlsl::rootsig::ResourceRange; - using GroupT = std::pair; + using OverlappingRanges = llvm::hlsl::rootsig::OverlappingRanges; // Introduce a mapping from the collected RangeInfos back to the // RootSignatureElement that will retain its diagnostics info @@ -1188,40 +1167,10 @@ bool SemaHLSL::handleRootSignatureElements( } } - // 2. Sort the RangeInfo's by their GroupT to form groupings - std::sort(Infos.begin(), Infos.end(), [](RangeInfo A, RangeInfo B) { -return std::tie(A.Class, A.Space) < std::tie(B.Class, B.Space); - }); - - // 3. First we will init our state to track: - if (Infos.size() == 0) -return false; // No ranges to overlap - GroupT CurGroup = {Infos[0].Class, Infos[0].Space}; - bool HadOverlap = false; - - // Create a ResourceRange for each Visibility - ResourceRange::MapT::Allocator Allocator; - std::array Ranges = { - ResourceRange(Allocator), // All - ResourceRange(Allocator), // Vertex - ResourceRange(Allocator), // Hull - ResourceRange(Allocator), // Domain - ResourceRange(Allocator), // Geometry - ResourceRange(Allocator), // Pixel - ResourceRange(Allocator), // Amplification - ResourceRange(Allocator), // Mesh - }; - - // Reset the ResourceRanges for when we iterate through a new group - auto ClearRanges = [&Ranges]() { -for (ResourceRange &Range : Ranges) - Range.clear(); - }; - // Helper to report diagnostics - auto ReportOverlap = [this, InfoIndexMap, &HadOverlap]( -
[llvm-branch-commits] [llvm] [SelectionDAG] Deal with POISON for INSERT_VECTOR_ELT/INSERT_SUBVECTOR (part 2) (PR #143103)
https://github.com/bjope updated https://github.com/llvm/llvm-project/pull/143103 From fe73a97a1ef8c1c2df5999e0b6abecde0e89733b Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Tue, 3 Jun 2025 10:01:01 +0200 Subject: [PATCH] [SelectionDAG] Deal with POISON for INSERT_VECTOR_ELT/INSERT_SUBVECTOR (part 2) Add support in isGuaranteedNotToBeUndefOrPoison to avoid regressions seen after a previous commit fixing #141034. --- llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 6 + .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 71 ++ llvm/test/CodeGen/Thumb2/mve-vld3.ll | 4 +- .../X86/merge-consecutive-loads-128.ll| 78 ++ llvm/test/CodeGen/X86/mmx-build-vector.ll | 233 +- llvm/test/CodeGen/X86/pr62286.ll | 14 +- .../CodeGen/X86/vector-shuffle-combining.ll | 41 ++- .../zero_extend_vector_inreg_of_broadcast.ll | 8 +- 8 files changed, 191 insertions(+), 264 deletions(-) diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index a3675eecfea3f..08db31c63367d 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1889,6 +1889,12 @@ LLVM_ABI SDValue peekThroughExtractSubvectors(SDValue V); /// If \p V is not a truncation, it is returned as-is. LLVM_ABI SDValue peekThroughTruncates(SDValue V); +/// Recursively peek through INSERT_VECTOR_ELT nodes, returning the source +/// vector operand of \p V, as long as \p V is an INSERT_VECTOR_ELT operation +/// that do not insert into any of the demanded vector elts. +LLVM_ABI SDValue peekThroughInsertVectorElt(SDValue V, +const APInt &DemandedElts); + /// Returns true if \p V is a bitwise not operation. Assumes that an all ones /// constant is canonicalized to be operand 1. LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs = false); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 3b4802d4b47b1..17fe550d38c55 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -5456,6 +5456,60 @@ bool SelectionDAG::isGuaranteedNotToBeUndefOrPoison(SDValue Op, } return true; + case ISD::INSERT_SUBVECTOR: { +if (Op.getValueType().isScalableVector()) + break; +SDValue Src = Op.getOperand(0); +SDValue Sub = Op.getOperand(1); +uint64_t Idx = Op.getConstantOperandVal(2); +unsigned NumSubElts = Sub.getValueType().getVectorNumElements(); +APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx); +APInt DemandedSrcElts = DemandedElts; +DemandedSrcElts.clearBits(Idx, Idx + NumSubElts); + +if (!!DemandedSubElts && !isGuaranteedNotToBeUndefOrPoison( + Sub, DemandedSubElts, PoisonOnly, Depth + 1)) + return false; +if (!!DemandedSrcElts && !isGuaranteedNotToBeUndefOrPoison( + Src, DemandedSrcElts, PoisonOnly, Depth + 1)) + return false; +return true; + } + + case ISD::INSERT_VECTOR_ELT: { +SDValue InVec = Op.getOperand(0); +SDValue InVal = Op.getOperand(1); +SDValue EltNo = Op.getOperand(2); +EVT VT = InVec.getValueType(); +auto *IndexC = dyn_cast(EltNo); +if (IndexC && VT.isFixedLengthVector() && +IndexC->getZExtValue() < VT.getVectorNumElements()) { + if (DemandedElts[IndexC->getZExtValue()] && + !isGuaranteedNotToBeUndefOrPoison(InVal, PoisonOnly, Depth + 1)) +return false; + APInt InVecDemandedElts = DemandedElts; + InVecDemandedElts.clearBit(IndexC->getZExtValue()); + if (!!InVecDemandedElts && + !isGuaranteedNotToBeUndefOrPoison( + peekThroughInsertVectorElt(InVec, InVecDemandedElts), + InVecDemandedElts, PoisonOnly, Depth + 1)) +return false; + return true; +} +break; + } + + case ISD::SCALAR_TO_VECTOR: +// Check upper (known undef) elements. +if (DemandedElts.ugt(1) && !PoisonOnly) + return false; +// Check element zero. +if (DemandedElts[0] && !isGuaranteedNotToBeUndefOrPoison(Op.getOperand(0), + PoisonOnly, + Depth + 1)) + return false; +return true; + case ISD::SPLAT_VECTOR: return isGuaranteedNotToBeUndefOrPoison(Op.getOperand(0), PoisonOnly, Depth + 1); @@ -12508,6 +12562,23 @@ SDValue llvm::peekThroughTruncates(SDValue V) { return V; } +SDValue llvm::peekThroughInsertVectorElt(SDValue V, const APInt &DemandedElts) { + while (V.getOpcode() == ISD::INSERT_VECTOR_ELT) { +SDValue InVec = V.getOperand(0); +SDValue EltNo = V.getOperand(2); +EVT VT = InVec.getValueType(); +auto *IndexC = dyn_cast(EltNo); +if (IndexC && VT.isF
[llvm-branch-commits] [llvm] [SelectionDAG] Deal with POISON for INSERT_VECTOR_ELT/INSERT_SUBVECTOR (part 3) (PR #143105)
https://github.com/bjope updated https://github.com/llvm/llvm-project/pull/143105 From be4f7432d8f35a8b07dc745736dccac6ae742743 Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Sat, 31 May 2025 09:37:27 +0200 Subject: [PATCH] [SelectionDAG] Deal with POISON for INSERT_VECTOR_ELT/INSERT_SUBVECTOR (part 3) Target specific patches to avoid regressions seen after "part 1" aiming at fixing github issue #141034. One perhaps controversial change here is that convertToScalableVector now uses POISON instead of UNDEF for any additional elements added when converting to the scalable vector. This can avoid that we end up with things like t31: nxv1f32 = t32: v2f32 = extract_subvector t31, Constant:i64<0> t38: nxv1f32 = insert_subvector undef:nxv1f32, t32, Constant:i64<0> since if we instead try to insert into poison we can just use t31 instead of t38 without the risk that t31 would be more poisonous. --- llvm/include/llvm/CodeGen/SelectionDAG.h | 11 +- .../Target/AArch64/AArch64ISelLowering.cpp| 9 +- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 18 +-- .../AArch64/sve-fixed-length-fp-vselect.ll| 81 + .../AArch64/sve-fixed-length-frame-offests.ll | 8 +- .../AArch64/sve-fixed-length-int-vselect.ll | 108 ++ .../AArch64/sve-fixed-length-masked-gather.ll | 6 +- ...-streaming-mode-fixed-length-fp-vselect.ll | 21 ...streaming-mode-fixed-length-int-vselect.ll | 28 - .../fixed-vectors-vfw-web-simplification.ll | 90 +-- .../fixed-vectors-vw-web-simplification.ll| 55 +++-- 11 files changed, 93 insertions(+), 342 deletions(-) diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h index a98e46c587273..3abdafac4b411 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -953,8 +953,17 @@ class SelectionDAG { } /// Insert \p SubVec at the \p Idx element of \p Vec. + /// If \p SkipUndef is true and \p SubVec is UNDEF/POISON, then \p Vec is + /// returned. SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, - unsigned Idx) { + unsigned Idx, bool SkipUndef = false) { +// Skipping insert of UNDEF could result in POISON elements remaining in the +// resulting vector. The SkipUndef is useful in situations when getNode +// can't reason well enough about ignoring the insert, e.g. when having +// scalable vectors and the user of this method knows that the subvector +// being replaced isn't POISON. +if (SkipUndef && SubVec.isUndef()) + return Vec; return getNode(ISD::INSERT_SUBVECTOR, DL, Vec.getValueType(), Vec, SubVec, getVectorIdxConstant(Idx, DL)); } diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index fb8bd81c033af..761f7eaa13dc4 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -15125,11 +15125,14 @@ SDValue AArch64TargetLowering::LowerBUILD_VECTOR(SDValue Op, if (PreferDUPAndInsert) { // First, build a constant vector with the common element. -SmallVector Ops(NumElts, Value); +// Make sure to freeze the common element first, since we will use it also +// for indices that should be UNDEF (so we want to avoid making those +// elements more poisonous). +SmallVector Ops(NumElts, DAG.getFreeze(Value)); SDValue NewVector = LowerBUILD_VECTOR(DAG.getBuildVector(VT, DL, Ops), DAG); // Next, insert the elements that do not match the common value. for (unsigned I = 0; I < NumElts; ++I) - if (Op.getOperand(I) != Value) + if (Op.getOperand(I) != Value && !Op.getOperand(I).isUndef()) NewVector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, NewVector, Op.getOperand(I), DAG.getConstant(I, DL, MVT::i64)); @@ -28721,7 +28724,7 @@ static SDValue convertToScalableVector(SelectionDAG &DAG, EVT VT, SDValue V) { "Expected a fixed length vector operand!"); SDLoc DL(V); SDValue Zero = DAG.getConstant(0, DL, MVT::i64); - return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, DAG.getUNDEF(VT), V, Zero); + return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, DAG.getPOISON(VT), V, Zero); } // Shrink V so it's just big enough to maintain a VT's worth of data. diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 4f280c3e562b8..55e352ad21019 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -2859,7 +2859,7 @@ static SDValue convertToScalableVector(EVT VT, SDValue V, SelectionDAG &DAG, assert(V.getValueType().isFixedLengthVector() && "Expected a fixed length vector operand!"); SDLoc DL(V); - return DAG.getInsertSubvector(DL, DAG.getUNDE
[llvm-branch-commits] [mlir] [MLIR][OpenMP] Add canonical loop LLVM-IR lowering (PR #147069)
https://github.com/Meinersbur created https://github.com/llvm/llvm-project/pull/147069 Support for translating the operations introduced in #144785 to LLVM-IR. >From da2613d525deb4edcf0fac41e865ca0510c75210 Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Fri, 4 Jul 2025 16:26:20 +0200 Subject: [PATCH] omp.canonical_loop and omp.unroll_heuristic lowering --- .../mlir/Target/LLVMIR/ModuleTranslation.h| 43 + .../Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp | 10 + .../OpenMP/OpenMPToLLVMIRTranslation.cpp | 78 .../LLVMIR/openmp-cli-canonical_loop.mlir | 175 ++ .../LLVMIR/openmp-cli-unroll-heuristic01.mlir | 56 ++ .../LLVMIR/openmp-cli-unroll-heuristic02.mlir | 93 ++ 6 files changed, 455 insertions(+) create mode 100644 mlir/test/Target/LLVMIR/openmp-cli-canonical_loop.mlir create mode 100644 mlir/test/Target/LLVMIR/openmp-cli-unroll-heuristic01.mlir create mode 100644 mlir/test/Target/LLVMIR/openmp-cli-unroll-heuristic02.mlir diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h index 79e8bb6add0da..5d52cf3f04b6a 100644 --- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h @@ -15,6 +15,7 @@ #define MLIR_TARGET_LLVMIR_MODULETRANSLATION_H #include "mlir/Dialect/LLVMIR/LLVMInterfaces.h" +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "mlir/IR/Operation.h" #include "mlir/IR/SymbolTable.h" #include "mlir/IR/Value.h" @@ -24,6 +25,7 @@ #include "mlir/Target/LLVMIR/TypeToLLVM.h" #include "llvm/ADT/SetVector.h" +#include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/IR/FPEnv.h" namespace llvm { @@ -108,6 +110,41 @@ class ModuleTranslation { return blockMapping.lookup(block); } + /// Find the LLVM-IR loop that represents an MLIR loop. + llvm::CanonicalLoopInfo *lookupOMPLoop(omp::NewCliOp mlir) const { +llvm::CanonicalLoopInfo *result = loopMapping.lookup(mlir); +assert(result && "attempt to get non-existing loop"); +return result; + } + + /// Find the LLVM-IR loop that represents an MLIR loop. + llvm::CanonicalLoopInfo *lookupOMPLoop(Value mlir) const { +return lookupOMPLoop(mlir.getDefiningOp()); + } + + /// Mark an OpenMP loop as having been consumed. + void invalidateOmpLoop(omp::NewCliOp mlir) { loopMapping.erase(mlir); } + + /// Mark an OpenMP loop as having been consumed. + void invalidateOmpLoop(Value mlir) { +invalidateOmpLoop(mlir.getDefiningOp()); + } + + /// Map an MLIR OpenMP dialect CanonicalLoopInfo to its lowered LLVM-IR + /// OpenMPIRBuilder CanonicalLoopInfo + void mapOmpLoop(omp::NewCliOp mlir, llvm::CanonicalLoopInfo *llvm) { +assert(llvm && "argument must be non-null"); +llvm::CanonicalLoopInfo *&cur = loopMapping[mlir]; +assert(cur == nullptr && "attempting to map a loop that is already mapped"); +cur = llvm; + } + + /// Map an MLIR OpenMP dialect CanonicalLoopInfo to its lowered LLVM-IR + /// OpenMPIRBuilder CanonicalLoopInfo + void mapOmpLoop(Value mlir, llvm::CanonicalLoopInfo *llvm) { +mapOmpLoop(mlir.getDefiningOp(), llvm); + } + /// Stores the mapping between an MLIR operation with successors and a /// corresponding LLVM IR instruction. void mapBranch(Operation *mlir, llvm::Instruction *llvm) { @@ -381,6 +418,12 @@ class ModuleTranslation { DenseMap valueMapping; DenseMap blockMapping; + /// List of not yet consumed MLIR loop handles (represented by an omp.new_cli + /// operation which creates a value of type CanonicalLoopInfoType) and their + /// LLVM-IR representation as CanonicalLoopInfo which is managed by the + /// OpenMPIRBuilder. + DenseMap loopMapping; + /// A mapping between MLIR LLVM dialect terminators and LLVM IR terminators /// they are converted to. This allows for connecting PHI nodes to the source /// values after all operations are converted. diff --git a/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp b/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp index 7a0a7f86bc1e9..e77c4a0b94de9 100644 --- a/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp +++ b/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp @@ -42,6 +42,16 @@ template struct OpenMPOpConversion : public ConvertOpToLLVMPattern { using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern; + OpenMPOpConversion(LLVMTypeConverter &typeConverter, + PatternBenefit benefit = 1) + : ConvertOpToLLVMPattern(typeConverter, benefit) { +// Operations using CanonicalLoopInfoType are lowered only by +// mlir::translateModuleToLLVMIR() using the OpenMPIRBuilder. Until then, +// the type and operations using it must be preserved. +typeConverter.addConversion( +[&](::mlir::omp::CanonicalLoopInfoType type) { return type; }); + } + LogicalResult matchAndRewrite(T op, typename T::Adaptor adaptor, ConversionPatternRewriter &rewr
[llvm-branch-commits] [llvm] release/20.x: [X86] Ignore NSW when DstSVT is i32 (#131755) (PR #147034)
llvmbot wrote: @llvm/pr-subscribers-backend-x86 Author: None (llvmbot) Changes Backport 3d631914677b58a5479b310f480ac76e27d41e7e Requested by: @nikic --- Full diff: https://github.com/llvm/llvm-project/pull/147034.diff 2 Files Affected: - (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+2-1) - (modified) llvm/test/CodeGen/X86/vector-trunc-nowrap.ll (+86) ``diff diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 4413fbb77f415..12c40b501f627 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -20889,7 +20889,8 @@ static SDValue matchTruncateWithPACK(unsigned &PackOpcode, EVT DstVT, return SDValue(); unsigned MinSignBits = NumSrcEltBits - NumPackedSignBits; - if (Flags.hasNoSignedWrap() || MinSignBits < NumSignBits) { + if ((Flags.hasNoSignedWrap() && DstSVT != MVT::i32) || + MinSignBits < NumSignBits) { PackOpcode = X86ISD::PACKSS; return In; } diff --git a/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll b/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll index 2b8eedfbbdc9c..85cca4f6f9a57 100644 --- a/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll +++ b/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll @@ -1592,3 +1592,89 @@ entry: %1 = bitcast <8 x i8> %0 to i64 ret i64 %1 } + +define void @foo(<4 x i64> %a, <4 x i64> %b, ptr %p) "min-legal-vector-width"="256" "prefer-vector-width"="256" { +; SSE-LABEL: foo: +; SSE: # %bb.0: # %entry +; SSE-NEXT:shufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; SSE-NEXT:shufps {{.*#+}} xmm2 = xmm2[0,2],xmm3[0,2] +; SSE-NEXT:movaps %xmm2, 16(%rdi) +; SSE-NEXT:movaps %xmm0, (%rdi) +; SSE-NEXT:retq +; +; AVX1-LABEL: foo: +; AVX1: # %bb.0: # %entry +; AVX1-NEXT:vperm2f128 {{.*#+}} ymm2 = ymm0[2,3],ymm1[2,3] +; AVX1-NEXT:vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1-NEXT:vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm2[0,2],ymm0[4,6],ymm2[4,6] +; AVX1-NEXT:vmovups %ymm0, (%rdi) +; AVX1-NEXT:vzeroupper +; AVX1-NEXT:retq +; +; AVX2-SLOW-LABEL: foo: +; AVX2-SLOW: # %bb.0: # %entry +; AVX2-SLOW-NEXT:vextractf128 $1, %ymm0, %xmm2 +; AVX2-SLOW-NEXT:vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; AVX2-SLOW-NEXT:vextractf128 $1, %ymm1, %xmm2 +; AVX2-SLOW-NEXT:vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; AVX2-SLOW-NEXT:vmovaps %xmm1, 16(%rdi) +; AVX2-SLOW-NEXT:vmovaps %xmm0, (%rdi) +; AVX2-SLOW-NEXT:vzeroupper +; AVX2-SLOW-NEXT:retq +; +; AVX2-FAST-ALL-LABEL: foo: +; AVX2-FAST-ALL: # %bb.0: # %entry +; AVX2-FAST-ALL-NEXT:vmovaps {{.*#+}} ymm2 = [0,2,4,6,4,6,6,7] +; AVX2-FAST-ALL-NEXT:vpermps %ymm0, %ymm2, %ymm0 +; AVX2-FAST-ALL-NEXT:vpermps %ymm1, %ymm2, %ymm1 +; AVX2-FAST-ALL-NEXT:vmovaps %xmm1, 16(%rdi) +; AVX2-FAST-ALL-NEXT:vmovaps %xmm0, (%rdi) +; AVX2-FAST-ALL-NEXT:vzeroupper +; AVX2-FAST-ALL-NEXT:retq +; +; AVX2-FAST-PERLANE-LABEL: foo: +; AVX2-FAST-PERLANE: # %bb.0: # %entry +; AVX2-FAST-PERLANE-NEXT:vextractf128 $1, %ymm0, %xmm2 +; AVX2-FAST-PERLANE-NEXT:vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; AVX2-FAST-PERLANE-NEXT:vextractf128 $1, %ymm1, %xmm2 +; AVX2-FAST-PERLANE-NEXT:vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; AVX2-FAST-PERLANE-NEXT:vmovaps %xmm1, 16(%rdi) +; AVX2-FAST-PERLANE-NEXT:vmovaps %xmm0, (%rdi) +; AVX2-FAST-PERLANE-NEXT:vzeroupper +; AVX2-FAST-PERLANE-NEXT:retq +; +; AVX512F-LABEL: foo: +; AVX512F: # %bb.0: # %entry +; AVX512F-NEXT:# kill: def $ymm0 killed $ymm0 def $zmm0 +; AVX512F-NEXT:vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512F-NEXT:vpmovqd %zmm0, (%rdi) +; AVX512F-NEXT:vzeroupper +; AVX512F-NEXT:retq +; +; AVX512VL-LABEL: foo: +; AVX512VL: # %bb.0: # %entry +; AVX512VL-NEXT:vpmovqd %ymm1, 16(%rdi) +; AVX512VL-NEXT:vpmovqd %ymm0, (%rdi) +; AVX512VL-NEXT:vzeroupper +; AVX512VL-NEXT:retq +; +; AVX512BW-LABEL: foo: +; AVX512BW: # %bb.0: # %entry +; AVX512BW-NEXT:# kill: def $ymm0 killed $ymm0 def $zmm0 +; AVX512BW-NEXT:vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512BW-NEXT:vpmovqd %zmm0, (%rdi) +; AVX512BW-NEXT:vzeroupper +; AVX512BW-NEXT:retq +; +; AVX512BWVL-LABEL: foo: +; AVX512BWVL: # %bb.0: # %entry +; AVX512BWVL-NEXT:vpmovqd %ymm1, 16(%rdi) +; AVX512BWVL-NEXT:vpmovqd %ymm0, (%rdi) +; AVX512BWVL-NEXT:vzeroupper +; AVX512BWVL-NEXT:retq +entry: + %0 = shufflevector <4 x i64> %a, <4 x i64> %b, <8 x i32> + %1 = trunc nsw <8 x i64> %0 to <8 x i32> + store <8 x i32> %1, ptr %p, align 16 + ret void +} `` https://github.com/llvm/llvm-project/pull/147034 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [X86] Ignore NSW when DstSVT is i32 (#131755) (PR #147034)
https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/147034 Backport 3d631914677b58a5479b310f480ac76e27d41e7e Requested by: @nikic >From d21a84221a9dbd5af4296fc07d6a43c4d8bdf9e9 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Tue, 18 Mar 2025 13:04:23 +0100 Subject: [PATCH] [X86] Ignore NSW when DstSVT is i32 (#131755) We don't have PACKSS for i64->i32. Fixes: https://godbolt.org/z/qb8nxnPbK, which was introduced by ddd2f57b (cherry picked from commit 3d631914677b58a5479b310f480ac76e27d41e7e) --- llvm/lib/Target/X86/X86ISelLowering.cpp | 3 +- llvm/test/CodeGen/X86/vector-trunc-nowrap.ll | 86 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 4413fbb77f415..12c40b501f627 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -20889,7 +20889,8 @@ static SDValue matchTruncateWithPACK(unsigned &PackOpcode, EVT DstVT, return SDValue(); unsigned MinSignBits = NumSrcEltBits - NumPackedSignBits; - if (Flags.hasNoSignedWrap() || MinSignBits < NumSignBits) { + if ((Flags.hasNoSignedWrap() && DstSVT != MVT::i32) || + MinSignBits < NumSignBits) { PackOpcode = X86ISD::PACKSS; return In; } diff --git a/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll b/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll index 2b8eedfbbdc9c..85cca4f6f9a57 100644 --- a/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll +++ b/llvm/test/CodeGen/X86/vector-trunc-nowrap.ll @@ -1592,3 +1592,89 @@ entry: %1 = bitcast <8 x i8> %0 to i64 ret i64 %1 } + +define void @foo(<4 x i64> %a, <4 x i64> %b, ptr %p) "min-legal-vector-width"="256" "prefer-vector-width"="256" { +; SSE-LABEL: foo: +; SSE: # %bb.0: # %entry +; SSE-NEXT:shufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; SSE-NEXT:shufps {{.*#+}} xmm2 = xmm2[0,2],xmm3[0,2] +; SSE-NEXT:movaps %xmm2, 16(%rdi) +; SSE-NEXT:movaps %xmm0, (%rdi) +; SSE-NEXT:retq +; +; AVX1-LABEL: foo: +; AVX1: # %bb.0: # %entry +; AVX1-NEXT:vperm2f128 {{.*#+}} ymm2 = ymm0[2,3],ymm1[2,3] +; AVX1-NEXT:vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1-NEXT:vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm2[0,2],ymm0[4,6],ymm2[4,6] +; AVX1-NEXT:vmovups %ymm0, (%rdi) +; AVX1-NEXT:vzeroupper +; AVX1-NEXT:retq +; +; AVX2-SLOW-LABEL: foo: +; AVX2-SLOW: # %bb.0: # %entry +; AVX2-SLOW-NEXT:vextractf128 $1, %ymm0, %xmm2 +; AVX2-SLOW-NEXT:vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; AVX2-SLOW-NEXT:vextractf128 $1, %ymm1, %xmm2 +; AVX2-SLOW-NEXT:vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; AVX2-SLOW-NEXT:vmovaps %xmm1, 16(%rdi) +; AVX2-SLOW-NEXT:vmovaps %xmm0, (%rdi) +; AVX2-SLOW-NEXT:vzeroupper +; AVX2-SLOW-NEXT:retq +; +; AVX2-FAST-ALL-LABEL: foo: +; AVX2-FAST-ALL: # %bb.0: # %entry +; AVX2-FAST-ALL-NEXT:vmovaps {{.*#+}} ymm2 = [0,2,4,6,4,6,6,7] +; AVX2-FAST-ALL-NEXT:vpermps %ymm0, %ymm2, %ymm0 +; AVX2-FAST-ALL-NEXT:vpermps %ymm1, %ymm2, %ymm1 +; AVX2-FAST-ALL-NEXT:vmovaps %xmm1, 16(%rdi) +; AVX2-FAST-ALL-NEXT:vmovaps %xmm0, (%rdi) +; AVX2-FAST-ALL-NEXT:vzeroupper +; AVX2-FAST-ALL-NEXT:retq +; +; AVX2-FAST-PERLANE-LABEL: foo: +; AVX2-FAST-PERLANE: # %bb.0: # %entry +; AVX2-FAST-PERLANE-NEXT:vextractf128 $1, %ymm0, %xmm2 +; AVX2-FAST-PERLANE-NEXT:vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; AVX2-FAST-PERLANE-NEXT:vextractf128 $1, %ymm1, %xmm2 +; AVX2-FAST-PERLANE-NEXT:vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; AVX2-FAST-PERLANE-NEXT:vmovaps %xmm1, 16(%rdi) +; AVX2-FAST-PERLANE-NEXT:vmovaps %xmm0, (%rdi) +; AVX2-FAST-PERLANE-NEXT:vzeroupper +; AVX2-FAST-PERLANE-NEXT:retq +; +; AVX512F-LABEL: foo: +; AVX512F: # %bb.0: # %entry +; AVX512F-NEXT:# kill: def $ymm0 killed $ymm0 def $zmm0 +; AVX512F-NEXT:vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512F-NEXT:vpmovqd %zmm0, (%rdi) +; AVX512F-NEXT:vzeroupper +; AVX512F-NEXT:retq +; +; AVX512VL-LABEL: foo: +; AVX512VL: # %bb.0: # %entry +; AVX512VL-NEXT:vpmovqd %ymm1, 16(%rdi) +; AVX512VL-NEXT:vpmovqd %ymm0, (%rdi) +; AVX512VL-NEXT:vzeroupper +; AVX512VL-NEXT:retq +; +; AVX512BW-LABEL: foo: +; AVX512BW: # %bb.0: # %entry +; AVX512BW-NEXT:# kill: def $ymm0 killed $ymm0 def $zmm0 +; AVX512BW-NEXT:vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512BW-NEXT:vpmovqd %zmm0, (%rdi) +; AVX512BW-NEXT:vzeroupper +; AVX512BW-NEXT:retq +; +; AVX512BWVL-LABEL: foo: +; AVX512BWVL: # %bb.0: # %entry +; AVX512BWVL-NEXT:vpmovqd %ymm1, 16(%rdi) +; AVX512BWVL-NEXT:vpmovqd %ymm0, (%rdi) +; AVX512BWVL-NEXT:vzeroupper +; AVX512BWVL-NEXT:retq +entry: + %0 = shufflevector <4 x i64> %a, <4 x i64> %b, <8 x i32> + %1 = trunc nsw <8 x i64> %0 to <8 x i32> + store <8 x i32> %1, ptr %p, align 16 + ret void +} _
[llvm-branch-commits] [llvm] release/20.x: [X86] Ignore NSW when DstSVT is i32 (#131755) (PR #147034)
llvmbot wrote: @RKSimon What do you think about merging this PR to the release branch? https://github.com/llvm/llvm-project/pull/147034 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [X86] Ignore NSW when DstSVT is i32 (#131755) (PR #147034)
https://github.com/llvmbot milestoned https://github.com/llvm/llvm-project/pull/147034 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT][NFC] Update nfc-check-setup.py guidance (PR #146659)
https://github.com/paschalis-mpeis updated https://github.com/llvm/llvm-project/pull/146659 >From 4284499a9286ceb7708531ae9b1108e25f58267c Mon Sep 17 00:00:00 2001 From: Paschalis Mpeis Date: Fri, 4 Jul 2025 14:54:58 +0100 Subject: [PATCH] [BOLT][NFC] Update nfc-check-setup.py guidance --- bolt/utils/nfc-check-setup.py | 53 --- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/bolt/utils/nfc-check-setup.py b/bolt/utils/nfc-check-setup.py index 18bf7522de17b..7191bbe122a9f 100755 --- a/bolt/utils/nfc-check-setup.py +++ b/bolt/utils/nfc-check-setup.py @@ -7,6 +7,8 @@ import sys import textwrap +msg_prefix="\n> NFC-Mode:" + def get_relevant_bolt_changes(dir: str) -> str: # Return a list of bolt source changes that are relevant to testing. all_changes = subprocess.run( @@ -49,7 +51,7 @@ def switch_back( # the HEAD is. Must be called after checking out the previous commit on all # exit paths. if switch_back: -print("Switching back to current revision..") +print(f"{msg_prefix} Switching back to current revision..") if stash: subprocess.run(shlex.split("git stash pop"), cwd=source_dir) subprocess.run(shlex.split(f"git checkout {old_ref}"), cwd=source_dir) @@ -64,8 +66,10 @@ def main(): parser = argparse.ArgumentParser( description=textwrap.dedent( """ -This script builds two versions of BOLT (with the current and -previous revision). +This script builds two versions of BOLT: +llvm-bolt.new, using the current revision, and llvm-bolt.old using +the previous revision. These can be used to check whether the +current revision changes BOLT's functional behavior. """ ) ) @@ -104,7 +108,7 @@ def main(): if not args.create_wrapper and len(wrapper_args) > 0: parser.parse_args() -# find the repo directory +# Find the repo directory. source_dir = None try: CMCacheFilename = f"{args.build_dir}/CMakeCache.txt" @@ -118,13 +122,13 @@ def main(): except Exception as e: sys.exit(e) -# clean the previous llvm-bolt if it exists +# Clean the previous llvm-bolt if it exists. bolt_path = f"{args.build_dir}/bin/llvm-bolt" if os.path.exists(bolt_path): os.remove(bolt_path) -# build the current commit -print("NFC-Setup: Building current revision..") +# Build the current commit. +print(f"{msg_prefix} Building current revision..") subprocess.run( shlex.split("cmake --build . --target llvm-bolt"), cwd=args.build_dir ) @@ -132,9 +136,8 @@ def main(): if not os.path.exists(bolt_path): sys.exit(f"Failed to build the current revision: '{bolt_path}'") -# rename llvm-bolt +# Rename llvm-bolt and memorize the old hash for logging. os.replace(bolt_path, f"{bolt_path}.new") -# memorize the old hash for logging old_ref = get_git_ref_or_rev(source_dir) if args.check_bolt_sources: @@ -147,7 +150,7 @@ def main(): print(f"BOLT source changes were found:\n{file_changes}") open(marker, "a").close() -# determine whether a stash is needed +# Determine whether a stash is needed. stash = subprocess.run( shlex.split("git status --porcelain"), cwd=source_dir, @@ -156,32 +159,33 @@ def main(): text=True, ).stdout if stash: -# save local changes before checkout +# Save local changes before checkout. subprocess.run(shlex.split("git stash push -u"), cwd=source_dir) -# check out the previous/cmp commit + +# Check out the previous/cmp commit and get its commit hash for logging. subprocess.run(shlex.split(f"git checkout -f {args.cmp_rev}"), cwd=source_dir) -# get the parent commit hash for logging new_ref = get_git_ref_or_rev(source_dir) -# build the previous commit -print("NFC-Setup: Building previous revision..") +# Build the previous commit. +print(f"{msg_prefix} Building previous revision..") subprocess.run( shlex.split("cmake --build . --target llvm-bolt"), cwd=args.build_dir ) -# rename llvm-bolt +# Rename llvm-bolt. if not os.path.exists(bolt_path): print(f"Failed to build the previous revision: '{bolt_path}'") switch_back(args.switch_back, stash, source_dir, old_ref, new_ref) sys.exit(1) os.replace(bolt_path, f"{bolt_path}.old") -# symlink llvm-bolt-wrapper +# Symlink llvm-bolt-wrapper if args.create_wrapper: +print(f"{msg_prefix} Creating llvm-bolt wrapper..") script_dir = os.path.dirname(os.path.abspath(__file__)) wrapper_path = f"{script_dir}/llvm-bolt-wrapper.py" try: -# set up llvm-bolt-wrapper.ini +# Set up llvm-bolt-wrapper.ini ini = subprocess.che
[llvm-branch-commits] [mlir] [MLIR][OpenMP] Add canonical loop operations (PR #147061)
https://github.com/Meinersbur created https://github.com/llvm/llvm-project/pull/147061 Add the supporting OpenMP Dialect operations, types, and interfaces for modelling MLIR Operations: * omp.newcli * omp.canonical_loop MLIR Types: * !omp.cli MLIR Interfaces: * LoopTransformationInterface As a first loop transformations to be able to use these new operation in follow-up PRs (#144785) * omp.unroll_heuristic If bikeshedding on the operation names, pretty formatting of operations inkl. future transformations such as `omp.tile`, and names of omp.cli values computed by `getAsmResultNames` (e.g. `%canonloop_s0`), I think this PR would be the right place. >From c7ed06d92dc7e256bff5370eb3d74d3a43547625 Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Fri, 4 Jul 2025 14:50:46 +0200 Subject: [PATCH] Add omp.canonical_loop and omp.unroll modelling --- .../mlir/Dialect/OpenMP/OpenMPDialect.h | 5 + .../mlir/Dialect/OpenMP/OpenMPOpBase.td | 11 + mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 207 ++ .../Dialect/OpenMP/OpenMPOpsInterfaces.td | 86 + mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 353 ++ .../OpenMP/cli-canonical_loop-invalid.mlir| 50 +++ .../Dialect/OpenMP/cli-canonical_loop.mlir| 157 .../Dialect/OpenMP/cli-unroll-heuristic.mlir | 59 +++ 8 files changed, 928 insertions(+) create mode 100644 mlir/test/Dialect/OpenMP/cli-canonical_loop-invalid.mlir create mode 100644 mlir/test/Dialect/OpenMP/cli-canonical_loop.mlir create mode 100644 mlir/test/Dialect/OpenMP/cli-unroll-heuristic.mlir diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h index ab11a6094e3e7..7cf738352ba47 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h @@ -37,4 +37,9 @@ #define GET_OP_CLASSES #include "mlir/Dialect/OpenMP/OpenMPOps.h.inc" +namespace mlir::omp { +/// Find the omp.new_cli, generator, and consumer of a canonical loop info. +std::tuple decodeCli(mlir::Value cli); +} // namespace mlir::omp + #endif // MLIR_DIALECT_OPENMP_OPENMPDIALECT_H_ diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td index f3dd44d2c0717..bbcfb87fa03c6 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td @@ -204,4 +204,15 @@ class OpenMP_Op traits = [], let regions = !if(singleRegion, (region AnyRegion:$region), (region)); } + +// Base class for OpenMP loop transformations (that either consume or generate +// loops) +// +// Doesn't actually create a C++ base class (only defines default values for +// tablegen classes that derive from this). Use LoopTransformationInterface +// instead for common operations. +class OpenMPTransform_Op traits = []> : + OpenMP_Op], traits) > { +} + #endif // OPENMP_OP_BASE diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td index ac80926053a2d..703384a0680d0 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -22,6 +22,7 @@ include "mlir/Dialect/OpenMP/OpenMPOpBase.td" include "mlir/Interfaces/ControlFlowInterfaces.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/EnumAttr.td" +include "mlir/IR/OpAsmInterface.td" include "mlir/IR/OpBase.td" include "mlir/IR/SymbolInterfaces.td" @@ -356,6 +357,212 @@ def SingleOp : OpenMP_Op<"single", traits = [ let hasVerifier = 1; } +//===-===// +// OpenMP Canonical Loop Info Type +//===-===// + +def CanonicalLoopInfoType : OpenMP_Type<"CanonicalLoopInfo", "cli"> { + let summary = "Type for representing a reference to a canonical loop"; + let description = [{ +A variable of type CanonicalLoopInfo refers to an OpenMP-compatible +canonical loop in the same function. Values of this type are not +available at runtime and therefore cannot be used by the program itself, +i.e. an opaque type. It is similar to the transform dialect's +`!transform.interface` type, but instead of implementing an interface +for each transformation, the OpenMP dialect itself defines possible +operations on this type. + +A value of type CanonicalLoopInfoType (in the following: CLI) value can be + +1. created by omp.new_cli. +2. passed to omp.canonical_loop to associate the loop to that CLI. A CLI + can only be associated once. +3. passed to an omp loop transformation operation that modifies the loop + associated with the CLI. The CLI is the "applyee" and the operation is + the consumer. A CLI can only be consumed once. +4. passed to an omp loop transformation operation to associate the cli with +
[llvm-branch-commits] [llvm] [BOLT][NFC] Update nfc-check-setup.py guidance (PR #146659)
github-actions[bot] wrote: :warning: Python code formatter, darker found issues in your code. :warning: You can test this locally with the following command: ``bash darker --check --diff -r HEAD~1...HEAD bolt/utils/nfc-check-setup.py `` View the diff from darker here. ``diff --- nfc-check-setup.py 2025-07-04 14:10:54.00 + +++ nfc-check-setup.py 2025-07-04 14:15:42.929615 + @@ -5,11 +5,12 @@ import shlex import subprocess import sys import textwrap -msg_prefix="\n> NFC-Mode:" +msg_prefix = "\n> NFC-Mode:" + def get_relevant_bolt_changes(dir: str) -> str: # Return a list of bolt source changes that are relevant to testing. all_changes = subprocess.run( shlex.split("git show HEAD --name-only --pretty=''"), @@ -209,10 +210,10 @@ if args.create_wrapper: print( "Can run BOLT tests using:\n" "\tbin/llvm-lit -sv tools/bolt/test\nor\n" "\tbin/llvm-lit -sv tools/bolttests" -) +) if __name__ == "__main__": main() `` https://github.com/llvm/llvm-project/pull/146659 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT][NFC] Update nfc-check-setup.py guidance (PR #146659)
https://github.com/paschalis-mpeis updated https://github.com/llvm/llvm-project/pull/146659 >From 2b5e54e8f3ed5f29a495a92e4e93725c74df Mon Sep 17 00:00:00 2001 From: Paschalis Mpeis Date: Fri, 4 Jul 2025 14:54:58 +0100 Subject: [PATCH] [BOLT][NFC] Update nfc-check-setup.py guidance --- bolt/utils/nfc-check-setup.py | 53 --- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/bolt/utils/nfc-check-setup.py b/bolt/utils/nfc-check-setup.py index 18bf7522de17b..d8666e2158499 100755 --- a/bolt/utils/nfc-check-setup.py +++ b/bolt/utils/nfc-check-setup.py @@ -7,6 +7,8 @@ import sys import textwrap +msg_prefix = "\n> NFC-Mode:" + def get_relevant_bolt_changes(dir: str) -> str: # Return a list of bolt source changes that are relevant to testing. all_changes = subprocess.run( @@ -49,7 +51,7 @@ def switch_back( # the HEAD is. Must be called after checking out the previous commit on all # exit paths. if switch_back: -print("Switching back to current revision..") +print(f"{msg_prefix} Switching back to current revision..") if stash: subprocess.run(shlex.split("git stash pop"), cwd=source_dir) subprocess.run(shlex.split(f"git checkout {old_ref}"), cwd=source_dir) @@ -64,8 +66,10 @@ def main(): parser = argparse.ArgumentParser( description=textwrap.dedent( """ -This script builds two versions of BOLT (with the current and -previous revision). +This script builds two versions of BOLT: +llvm-bolt.new, using the current revision, and llvm-bolt.old using +the previous revision. These can be used to check whether the +current revision changes BOLT's functional behavior. """ ) ) @@ -104,7 +108,7 @@ def main(): if not args.create_wrapper and len(wrapper_args) > 0: parser.parse_args() -# find the repo directory +# Find the repo directory. source_dir = None try: CMCacheFilename = f"{args.build_dir}/CMakeCache.txt" @@ -118,13 +122,13 @@ def main(): except Exception as e: sys.exit(e) -# clean the previous llvm-bolt if it exists +# Clean the previous llvm-bolt if it exists. bolt_path = f"{args.build_dir}/bin/llvm-bolt" if os.path.exists(bolt_path): os.remove(bolt_path) -# build the current commit -print("NFC-Setup: Building current revision..") +# Build the current commit. +print(f"{msg_prefix} Building current revision..") subprocess.run( shlex.split("cmake --build . --target llvm-bolt"), cwd=args.build_dir ) @@ -132,9 +136,8 @@ def main(): if not os.path.exists(bolt_path): sys.exit(f"Failed to build the current revision: '{bolt_path}'") -# rename llvm-bolt +# Rename llvm-bolt and memorize the old hash for logging. os.replace(bolt_path, f"{bolt_path}.new") -# memorize the old hash for logging old_ref = get_git_ref_or_rev(source_dir) if args.check_bolt_sources: @@ -147,7 +150,7 @@ def main(): print(f"BOLT source changes were found:\n{file_changes}") open(marker, "a").close() -# determine whether a stash is needed +# Determine whether a stash is needed. stash = subprocess.run( shlex.split("git status --porcelain"), cwd=source_dir, @@ -156,32 +159,33 @@ def main(): text=True, ).stdout if stash: -# save local changes before checkout +# Save local changes before checkout. subprocess.run(shlex.split("git stash push -u"), cwd=source_dir) -# check out the previous/cmp commit + +# Check out the previous/cmp commit and get its commit hash for logging. subprocess.run(shlex.split(f"git checkout -f {args.cmp_rev}"), cwd=source_dir) -# get the parent commit hash for logging new_ref = get_git_ref_or_rev(source_dir) -# build the previous commit -print("NFC-Setup: Building previous revision..") +# Build the previous commit. +print(f"{msg_prefix} Building previous revision..") subprocess.run( shlex.split("cmake --build . --target llvm-bolt"), cwd=args.build_dir ) -# rename llvm-bolt +# Rename llvm-bolt. if not os.path.exists(bolt_path): print(f"Failed to build the previous revision: '{bolt_path}'") switch_back(args.switch_back, stash, source_dir, old_ref, new_ref) sys.exit(1) os.replace(bolt_path, f"{bolt_path}.old") -# symlink llvm-bolt-wrapper +# Symlink llvm-bolt-wrapper if args.create_wrapper: +print(f"{msg_prefix} Creating llvm-bolt wrapper..") script_dir = os.path.dirname(os.path.abspath(__file__)) wrapper_path = f"{script_dir}/llvm-bolt-wrapper.py" try: -# set up llvm-bolt-wrapper.ini +# Set up llvm-bolt-wrapper.ini ini = subprocess.c
[llvm-branch-commits] [llvm] [BOLT][NFC] Update nfc-check-setup.py guidance (PR #146659)
@@ -156,9 +158,8 @@ def main(): os.replace(bolt_path, f"{bolt_path}.old") print( -f"Build directory {args.build_dir} is ready to run BOLT tests, e.g.\n" -"\tbin/llvm-lit -sv tools/bolt/test\nor\n" -"\tbin/llvm-lit -sv tools/bolttests" +f"Build directory {args.build_dir} is ready for NFC-Mode comparison " +"between the two revisions." paschalis-mpeis wrote: Forced pushed to rebase and handle this. `llvm-bolt` is available only when the `--create-wrapper` flag is used (as a wrapper). In that case, the commands are valid and now printed. Also applied a few more nits. https://github.com/llvm/llvm-project/pull/146659 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [X86] Ignore NSW when DstSVT is i32 (#131755) (PR #147034)
https://github.com/RKSimon approved this pull request. https://github.com/llvm/llvm-project/pull/147034 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [AArch64][PAC] Combine signing with address materialization (PR #130809)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/130809 >From 4c5d1884605dbbb316b0764f48af199ad95818e9 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Mon, 10 Mar 2025 15:14:55 +0300 Subject: [PATCH 1/2] [AArch64][PAC] Precommit tests on merging MOVaddr/LOADgotAUTH with PAC* --- .../GlobalISel/ptrauth-constant-in-code.ll| 76 +++ .../AArch64/ptrauth-constant-in-code.ll | 71 + 2 files changed, 147 insertions(+) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll index 12a3448111fcb..140e29f942a79 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll @@ -78,6 +78,82 @@ define ptr @foo() { ret ptr ptrauth (ptr @g, i32 0) } +;--- finalize-isel.ll + +; RUN: llc < finalize-isel.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \ +; RUN: -verify-machineinstrs -global-isel-abort=1 -stop-after=finalize-isel | \ +; RUN: FileCheck --check-prefixes=ISEL,ISEL-ELF %s +; RUN: llc < finalize-isel.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=1 \ +; RUN: -verify-machineinstrs -global-isel-abort=1 -stop-after=finalize-isel | \ +; RUN: FileCheck --check-prefixes=ISEL %s + +@const_table_local = dso_local constant [3 x ptr] [ptr null, ptr null, ptr null] +@const_table_got = constant [3 x ptr] [ptr null, ptr null, ptr null] + +define void @store_signed_const_local(ptr %dest) { +; ISEL-LABEL: name: store_signed_const_local +; ISEL: body: +; ISEL: %0:gpr64common = COPY $x0 +; ISEL-NEXT:%10:gpr64common = MOVaddr target-flags(aarch64-page) @const_table_local + 8, target-flags(aarch64-pageoff, aarch64-nc) @const_table_local + 8 +; ISEL-NEXT:%2:gpr64noip = MOVKXi %0, 1234 +; ISEL-NEXT:%15:gpr64noip = COPY %0 +; ISEL-NEXT:%4:gpr64 = PAC %10, 2, 1234, %15, implicit-def dead $x17 +; ISEL-NEXT:%14:gpr64 = COPY %4 +; ISEL-NEXT:STRXui %14, %0, 0 :: (store (p0) into %ir.dest) +; ISEL-NEXT:RET_ReallyLR + %dest.i = ptrtoint ptr %dest to i64 + %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234) + %signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_local, i32 0, i32 1) to i64), i32 2, i64 %discr) + %signed.ptr = inttoptr i64 %signed.i to ptr + store ptr %signed.ptr, ptr %dest + ret void +} + +define void @store_signed_const_got(ptr %dest) { +; ISEL-ELF-LABEL: name: store_signed_const_got +; ISEL-ELF: body: +; ISEL-ELF: %0:gpr64common = COPY $x0 +; ISEL-ELF-NEXT:%7:gpr64common = LOADgotAUTH target-flags(aarch64-got) @const_table_got +; ISEL-ELF-NEXT:%6:gpr64common = ADDXri %7, 8, 0 +; ISEL-ELF-NEXT:%2:gpr64noip = MOVKXi %0, 1234 +; ISEL-ELF-NEXT:%12:gpr64noip = COPY %0 +; ISEL-ELF-NEXT:%4:gpr64 = PAC %6, 2, 1234, %12, implicit-def dead $x17 +; ISEL-ELF-NEXT:%10:gpr64 = COPY %4 +; ISEL-ELF-NEXT:STRXui %10, %0, 0 :: (store (p0) into %ir.dest) +; ISEL-ELF-NEXT:RET_ReallyLR + %dest.i = ptrtoint ptr %dest to i64 + %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234) + %signed.i = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr ([2 x ptr], ptr @const_table_got, i32 0, i32 1) to i64), i32 2, i64 %discr) + %signed.ptr = inttoptr i64 %signed.i to ptr + store ptr %signed.ptr, ptr %dest + ret void +} + +define void @store_signed_arg(ptr %dest, ptr %p) { +; ISEL-LABEL: name: store_signed_arg +; ISEL: body: +; ISEL: %0:gpr64common = COPY $x0 +; ISEL-NEXT:%1:gpr64common = COPY $x1 +; ISEL-NEXT:%3:gpr64noip = MOVKXi %0, 1234 +; ISEL-NEXT:%6:gpr64common = ADDXri %1, 8, 0 +; ISEL-NEXT:%12:gpr64noip = COPY %0 +; ISEL-NEXT:%8:gpr64 = PAC %6, 2, 1234, %12, implicit-def dead $x17 +; ISEL-NEXT:%10:gpr64 = COPY %8 +; ISEL-NEXT:STRXui %10, %0, 0 :: (store (p0) into %ir.dest) +; ISEL-NEXT:RET_ReallyLR + %dest.i = ptrtoint ptr %dest to i64 + %discr = call i64 @llvm.ptrauth.blend(i64 %dest.i, i64 1234) + %p.offset = getelementptr [2 x ptr], ptr %p, i32 0, i32 1 + %p.offset.i = ptrtoint ptr %p.offset to i64 + %signed.i = call i64 @llvm.ptrauth.sign(i64 %p.offset.i, i32 2, i64 %discr) + %signed.ptr = inttoptr i64 %signed.i to ptr + store ptr %signed.ptr, ptr %dest + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} + ;--- ok.ll ; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \ diff --git a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll index 76339a7cc5791..429ff6e5489aa 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll @@ -69,6 +69,77 @@ define ptr @foo() { ret ptr ptrauth (ptr @g, i32 0) } +;--- finalize-isel.ll + +; RUN: llc < final
[llvm-branch-commits] [clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)
https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/146785 >From a49aa19297811e5800ffce364d8d6a225109d93f Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 19:28:01 + Subject: [PATCH 1/7] refactoring --- .../lib/Target/DirectX/DXContainerGlobals.cpp | 4 ++- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 14 +++- llvm/lib/Target/DirectX/DXILRootSignature.h | 33 +-- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 6c8ae8eaaea77..e076283b65193 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -160,11 +160,13 @@ void DXContainerGlobals::addRootSignature(Module &M, assert(MMI.EntryPropertyVec.size() == 1); + auto &RSA = getAnalysis().getRSInfo(); auto &RSA = getAnalysis().getRSInfo(); const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; const auto &RS = RSA.getDescForFunction(EntryFunction); + const auto &RS = RSA.getDescForFunction(EntryFunction); - if (!RS) + if (!RS ) return; SmallString<256> Data; diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 5a53ea8a3631b..4094df160ef6f 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -554,12 +554,9 @@ analyzeModule(Module &M) { AnalysisKey RootSignatureAnalysis::Key; -RootSignatureAnalysis::Result -RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { - if (!AnalysisResult) -AnalysisResult = std::make_unique( -RootSignatureBindingInfo(analyzeModule(M))); - return *AnalysisResult; +RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M, +ModuleAnalysisManager &AM) { + return RootSignatureBindingInfo(analyzeModule(M)); } //===--===// @@ -638,9 +635,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, //===--===// bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { - if (!FuncToRsMap) -FuncToRsMap = std::make_unique( -RootSignatureBindingInfo(analyzeModule(M))); + FuncToRsMap = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); return false; } diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 3832182277050..24b1a8d3d2abe 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -37,30 +37,28 @@ enum class RootSignatureElementKind { }; class RootSignatureBindingInfo { -private: - SmallDenseMap FuncToRsMap; + private: +SmallDenseMap FuncToRsMap; -public: + public: using iterator = - SmallDenseMap::iterator; +SmallDenseMap::iterator; - RootSignatureBindingInfo() = default; - RootSignatureBindingInfo( - SmallDenseMap Map) - : FuncToRsMap(Map) {}; + RootSignatureBindingInfo () = default; + RootSignatureBindingInfo(SmallDenseMap Map) : FuncToRsMap(Map) {}; iterator find(const Function *F) { return FuncToRsMap.find(F); } iterator end() { return FuncToRsMap.end(); } - std::optional - getDescForFunction(const Function *F) { + std::optional getDescForFunction(const Function* F) { const auto FuncRs = find(F); if (FuncRs == end()) return std::nullopt; return FuncRs->second; } + }; class RootSignatureAnalysis : public AnalysisInfoMixin { @@ -68,14 +66,13 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { static AnalysisKey Key; public: - RootSignatureAnalysis() = default; - - using Result = RootSignatureBindingInfo; - Result run(Module &M, ModuleAnalysisManager &AM); +RootSignatureAnalysis() = default; -private: - std::unique_ptr AnalysisResult; + using Result = RootSignatureBindingInfo; + + RootSignatureBindingInfo + run(Module &M, ModuleAnalysisManager &AM); }; /// Wrapper pass for the legacy pass manager. @@ -92,8 +89,8 @@ class RootSignatureAnalysisWrapper : public ModulePass { RootSignatureAnalysisWrapper() : ModulePass(ID) {} - RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; } - + RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;} + bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override; >From d90676feb6bfc0ca8bbdaee5c347ecc49e396b5b Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 21:37:11 + Subject: [PATCH 2/7] init refactoring --- .../SemaHLSL/RootSignature-Validation.hlsl| 42 + .../lib/Target/DirectX/DXContainerGlobals.cpp | 2 +- .../DXILPostOptimizationValidation.cpp| 47
[llvm-branch-commits] [clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)
https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/146785 >From a49aa19297811e5800ffce364d8d6a225109d93f Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 19:28:01 + Subject: [PATCH 1/8] refactoring --- .../lib/Target/DirectX/DXContainerGlobals.cpp | 4 ++- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 14 +++- llvm/lib/Target/DirectX/DXILRootSignature.h | 33 +-- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 6c8ae8eaaea77..e076283b65193 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -160,11 +160,13 @@ void DXContainerGlobals::addRootSignature(Module &M, assert(MMI.EntryPropertyVec.size() == 1); + auto &RSA = getAnalysis().getRSInfo(); auto &RSA = getAnalysis().getRSInfo(); const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; const auto &RS = RSA.getDescForFunction(EntryFunction); + const auto &RS = RSA.getDescForFunction(EntryFunction); - if (!RS) + if (!RS ) return; SmallString<256> Data; diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 5a53ea8a3631b..4094df160ef6f 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -554,12 +554,9 @@ analyzeModule(Module &M) { AnalysisKey RootSignatureAnalysis::Key; -RootSignatureAnalysis::Result -RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { - if (!AnalysisResult) -AnalysisResult = std::make_unique( -RootSignatureBindingInfo(analyzeModule(M))); - return *AnalysisResult; +RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M, +ModuleAnalysisManager &AM) { + return RootSignatureBindingInfo(analyzeModule(M)); } //===--===// @@ -638,9 +635,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, //===--===// bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { - if (!FuncToRsMap) -FuncToRsMap = std::make_unique( -RootSignatureBindingInfo(analyzeModule(M))); + FuncToRsMap = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); return false; } diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 3832182277050..24b1a8d3d2abe 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -37,30 +37,28 @@ enum class RootSignatureElementKind { }; class RootSignatureBindingInfo { -private: - SmallDenseMap FuncToRsMap; + private: +SmallDenseMap FuncToRsMap; -public: + public: using iterator = - SmallDenseMap::iterator; +SmallDenseMap::iterator; - RootSignatureBindingInfo() = default; - RootSignatureBindingInfo( - SmallDenseMap Map) - : FuncToRsMap(Map) {}; + RootSignatureBindingInfo () = default; + RootSignatureBindingInfo(SmallDenseMap Map) : FuncToRsMap(Map) {}; iterator find(const Function *F) { return FuncToRsMap.find(F); } iterator end() { return FuncToRsMap.end(); } - std::optional - getDescForFunction(const Function *F) { + std::optional getDescForFunction(const Function* F) { const auto FuncRs = find(F); if (FuncRs == end()) return std::nullopt; return FuncRs->second; } + }; class RootSignatureAnalysis : public AnalysisInfoMixin { @@ -68,14 +66,13 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { static AnalysisKey Key; public: - RootSignatureAnalysis() = default; - - using Result = RootSignatureBindingInfo; - Result run(Module &M, ModuleAnalysisManager &AM); +RootSignatureAnalysis() = default; -private: - std::unique_ptr AnalysisResult; + using Result = RootSignatureBindingInfo; + + RootSignatureBindingInfo + run(Module &M, ModuleAnalysisManager &AM); }; /// Wrapper pass for the legacy pass manager. @@ -92,8 +89,8 @@ class RootSignatureAnalysisWrapper : public ModulePass { RootSignatureAnalysisWrapper() : ModulePass(ID) {} - RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; } - + RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;} + bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override; >From d90676feb6bfc0ca8bbdaee5c347ecc49e396b5b Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 21:37:11 + Subject: [PATCH 2/8] init refactoring --- .../SemaHLSL/RootSignature-Validation.hlsl| 42 + .../lib/Target/DirectX/DXContainerGlobals.cpp | 2 +- .../DXILPostOptimizationValidation.cpp| 47
[llvm-branch-commits] [clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)
https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/146785 >From a49aa19297811e5800ffce364d8d6a225109d93f Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 19:28:01 + Subject: [PATCH 1/9] refactoring --- .../lib/Target/DirectX/DXContainerGlobals.cpp | 4 ++- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 14 +++- llvm/lib/Target/DirectX/DXILRootSignature.h | 33 +-- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 6c8ae8eaaea77..e076283b65193 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -160,11 +160,13 @@ void DXContainerGlobals::addRootSignature(Module &M, assert(MMI.EntryPropertyVec.size() == 1); + auto &RSA = getAnalysis().getRSInfo(); auto &RSA = getAnalysis().getRSInfo(); const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; const auto &RS = RSA.getDescForFunction(EntryFunction); + const auto &RS = RSA.getDescForFunction(EntryFunction); - if (!RS) + if (!RS ) return; SmallString<256> Data; diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 5a53ea8a3631b..4094df160ef6f 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -554,12 +554,9 @@ analyzeModule(Module &M) { AnalysisKey RootSignatureAnalysis::Key; -RootSignatureAnalysis::Result -RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { - if (!AnalysisResult) -AnalysisResult = std::make_unique( -RootSignatureBindingInfo(analyzeModule(M))); - return *AnalysisResult; +RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M, +ModuleAnalysisManager &AM) { + return RootSignatureBindingInfo(analyzeModule(M)); } //===--===// @@ -638,9 +635,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, //===--===// bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { - if (!FuncToRsMap) -FuncToRsMap = std::make_unique( -RootSignatureBindingInfo(analyzeModule(M))); + FuncToRsMap = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); return false; } diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 3832182277050..24b1a8d3d2abe 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -37,30 +37,28 @@ enum class RootSignatureElementKind { }; class RootSignatureBindingInfo { -private: - SmallDenseMap FuncToRsMap; + private: +SmallDenseMap FuncToRsMap; -public: + public: using iterator = - SmallDenseMap::iterator; +SmallDenseMap::iterator; - RootSignatureBindingInfo() = default; - RootSignatureBindingInfo( - SmallDenseMap Map) - : FuncToRsMap(Map) {}; + RootSignatureBindingInfo () = default; + RootSignatureBindingInfo(SmallDenseMap Map) : FuncToRsMap(Map) {}; iterator find(const Function *F) { return FuncToRsMap.find(F); } iterator end() { return FuncToRsMap.end(); } - std::optional - getDescForFunction(const Function *F) { + std::optional getDescForFunction(const Function* F) { const auto FuncRs = find(F); if (FuncRs == end()) return std::nullopt; return FuncRs->second; } + }; class RootSignatureAnalysis : public AnalysisInfoMixin { @@ -68,14 +66,13 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { static AnalysisKey Key; public: - RootSignatureAnalysis() = default; - - using Result = RootSignatureBindingInfo; - Result run(Module &M, ModuleAnalysisManager &AM); +RootSignatureAnalysis() = default; -private: - std::unique_ptr AnalysisResult; + using Result = RootSignatureBindingInfo; + + RootSignatureBindingInfo + run(Module &M, ModuleAnalysisManager &AM); }; /// Wrapper pass for the legacy pass manager. @@ -92,8 +89,8 @@ class RootSignatureAnalysisWrapper : public ModulePass { RootSignatureAnalysisWrapper() : ModulePass(ID) {} - RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; } - + RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;} + bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override; >From d90676feb6bfc0ca8bbdaee5c347ecc49e396b5b Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 21:37:11 + Subject: [PATCH 2/9] init refactoring --- .../SemaHLSL/RootSignature-Validation.hlsl| 42 + .../lib/Target/DirectX/DXContainerGlobals.cpp | 2 +- .../DXILPostOptimizationValidation.cpp| 47
[llvm-branch-commits] [clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)
llvmbot wrote: @llvm/pr-subscribers-hlsl Author: None (joaosaffran) Changes DXC checks if registers are correctly bound to root signature descriptors. This implements the same check. Closes: [126645](https://github.com/llvm/llvm-project/issues/126645) --- Full diff: https://github.com/llvm/llvm-project/pull/146785.diff 7 Files Affected: - (added) clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl (+35) - (added) clang/test/SemaHLSL/RootSignature-Validation.hlsl (+33) - (modified) llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp (+133-3) - (modified) llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h (+119) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll (+2-2) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll (+2-2) - (modified) llvm/test/CodeGen/DirectX/llc-pipeline.ll (+1) ``diff diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl new file mode 100644 index 0..b590ed67e7085 --- /dev/null +++ b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl @@ -0,0 +1,35 @@ +// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s + +// CHECK: error: register cbuffer (space=665, register=3) is not defined in Root Signature +// CHECK: error: register srv (space=0, register=0) is not defined in Root Signature +// CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature + + +#define ROOT_SIGNATURE \ +"CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX), " \ +"DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)" + +cbuffer CB : register(b3, space665) { + float a; +} + +StructuredBuffer In : register(t0, space0); +RWStructuredBuffer Out : register(u0); + +RWBuffer UAV : register(u4294967295); + +RWBuffer UAV1 : register(u2), UAV2 : register(u4); + +RWBuffer UAV3 : register(space0); + + + +// Compute Shader for UAV testing +[numthreads(8, 8, 1)] +[RootSignature(ROOT_SIGNATURE)] +void CSMain(uint id : SV_GroupID) +{ +Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0]; +} diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl new file mode 100644 index 0..5a7f5baf00619 --- /dev/null +++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl @@ -0,0 +1,33 @@ +// RUN: %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 + +// expected-no-diagnostics + + +#define ROOT_SIGNATURE \ +"CBV(b3, space=1, visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_VERTEX), " \ +"DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)" + +cbuffer CB : register(b3, space1) { + float a; +} + +StructuredBuffer In : register(t0, space0); +RWStructuredBuffer Out : register(u0); + +RWBuffer UAV : register(u4294967294); + +RWBuffer UAV1 : register(u2), UAV2 : register(u4); + +RWBuffer UAV3 : register(space0); + + + +// Compute Shader for UAV testing +[numthreads(8, 8, 1)] +[RootSignature(ROOT_SIGNATURE)] +void CSMain(uint id : SV_GroupID) +{ +Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0]; +} diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 398dcbb8d1737..a52a04323514c 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -7,6 +7,7 @@ //===--===// #include "DXILPostOptimizationValidation.h" +#include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/SmallString.h" @@ -84,8 +85,60 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } +static void reportRegNotBound(Module &M, Twine Type, + ResourceInfo::ResourceBinding Binding) { + SmallString<128> Message; + raw_svector_ostream OS(Message); + OS << "register " << Type << " (space=" << Binding.Space + << ", register=" << Binding.LowerBound << ")" + << " is not defined in Root Signature"; + M.getContext().diagnose(DiagnosticInfoGeneric(Message)); +} + +static dxbc::ShaderVisibility +tripleToVisibility(llvm::Triple::EnvironmentType ET) { + assert((ET == Triple::Pixel || ET == Triple::Vertex || + ET == Triple::Geometry || ET == Triple::Hull || + ET == Triple::Domain || ET == Triple::Mesh || + ET == Triple::Compute) && +
[llvm-branch-commits] [clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)
llvmbot wrote: @llvm/pr-subscribers-clang Author: None (joaosaffran) Changes DXC checks if registers are correctly bound to root signature descriptors. This implements the same check. Closes: [126645](https://github.com/llvm/llvm-project/issues/126645) --- Full diff: https://github.com/llvm/llvm-project/pull/146785.diff 7 Files Affected: - (added) clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl (+35) - (added) clang/test/SemaHLSL/RootSignature-Validation.hlsl (+33) - (modified) llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp (+133-3) - (modified) llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h (+119) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll (+2-2) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll (+2-2) - (modified) llvm/test/CodeGen/DirectX/llc-pipeline.ll (+1) ``diff diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl new file mode 100644 index 0..b590ed67e7085 --- /dev/null +++ b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl @@ -0,0 +1,35 @@ +// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s + +// CHECK: error: register cbuffer (space=665, register=3) is not defined in Root Signature +// CHECK: error: register srv (space=0, register=0) is not defined in Root Signature +// CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature + + +#define ROOT_SIGNATURE \ +"CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX), " \ +"DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)" + +cbuffer CB : register(b3, space665) { + float a; +} + +StructuredBuffer In : register(t0, space0); +RWStructuredBuffer Out : register(u0); + +RWBuffer UAV : register(u4294967295); + +RWBuffer UAV1 : register(u2), UAV2 : register(u4); + +RWBuffer UAV3 : register(space0); + + + +// Compute Shader for UAV testing +[numthreads(8, 8, 1)] +[RootSignature(ROOT_SIGNATURE)] +void CSMain(uint id : SV_GroupID) +{ +Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0]; +} diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl new file mode 100644 index 0..5a7f5baf00619 --- /dev/null +++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl @@ -0,0 +1,33 @@ +// RUN: %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 + +// expected-no-diagnostics + + +#define ROOT_SIGNATURE \ +"CBV(b3, space=1, visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_VERTEX), " \ +"DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)" + +cbuffer CB : register(b3, space1) { + float a; +} + +StructuredBuffer In : register(t0, space0); +RWStructuredBuffer Out : register(u0); + +RWBuffer UAV : register(u4294967294); + +RWBuffer UAV1 : register(u2), UAV2 : register(u4); + +RWBuffer UAV3 : register(space0); + + + +// Compute Shader for UAV testing +[numthreads(8, 8, 1)] +[RootSignature(ROOT_SIGNATURE)] +void CSMain(uint id : SV_GroupID) +{ +Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0]; +} diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 398dcbb8d1737..a52a04323514c 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -7,6 +7,7 @@ //===--===// #include "DXILPostOptimizationValidation.h" +#include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/SmallString.h" @@ -84,8 +85,60 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } +static void reportRegNotBound(Module &M, Twine Type, + ResourceInfo::ResourceBinding Binding) { + SmallString<128> Message; + raw_svector_ostream OS(Message); + OS << "register " << Type << " (space=" << Binding.Space + << ", register=" << Binding.LowerBound << ")" + << " is not defined in Root Signature"; + M.getContext().diagnose(DiagnosticInfoGeneric(Message)); +} + +static dxbc::ShaderVisibility +tripleToVisibility(llvm::Triple::EnvironmentType ET) { + assert((ET == Triple::Pixel || ET == Triple::Vertex || + ET == Triple::Geometry || ET == Triple::Hull || + ET == Triple::Domain || ET == Triple::Mesh || + ET == Triple::Compute) && +
[llvm-branch-commits] [clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)
llvmbot wrote: @llvm/pr-subscribers-backend-directx Author: None (joaosaffran) Changes DXC checks if registers are correctly bound to root signature descriptors. This implements the same check. Closes: [126645](https://github.com/llvm/llvm-project/issues/126645) --- Full diff: https://github.com/llvm/llvm-project/pull/146785.diff 7 Files Affected: - (added) clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl (+35) - (added) clang/test/SemaHLSL/RootSignature-Validation.hlsl (+33) - (modified) llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp (+133-3) - (modified) llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h (+119) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll (+2-2) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll (+2-2) - (modified) llvm/test/CodeGen/DirectX/llc-pipeline.ll (+1) ``diff diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl new file mode 100644 index 0..b590ed67e7085 --- /dev/null +++ b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl @@ -0,0 +1,35 @@ +// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s + +// CHECK: error: register cbuffer (space=665, register=3) is not defined in Root Signature +// CHECK: error: register srv (space=0, register=0) is not defined in Root Signature +// CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature + + +#define ROOT_SIGNATURE \ +"CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX), " \ +"DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)" + +cbuffer CB : register(b3, space665) { + float a; +} + +StructuredBuffer In : register(t0, space0); +RWStructuredBuffer Out : register(u0); + +RWBuffer UAV : register(u4294967295); + +RWBuffer UAV1 : register(u2), UAV2 : register(u4); + +RWBuffer UAV3 : register(space0); + + + +// Compute Shader for UAV testing +[numthreads(8, 8, 1)] +[RootSignature(ROOT_SIGNATURE)] +void CSMain(uint id : SV_GroupID) +{ +Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0]; +} diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl new file mode 100644 index 0..5a7f5baf00619 --- /dev/null +++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl @@ -0,0 +1,33 @@ +// RUN: %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 + +// expected-no-diagnostics + + +#define ROOT_SIGNATURE \ +"CBV(b3, space=1, visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL), " \ +"DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_VERTEX), " \ +"DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)" + +cbuffer CB : register(b3, space1) { + float a; +} + +StructuredBuffer In : register(t0, space0); +RWStructuredBuffer Out : register(u0); + +RWBuffer UAV : register(u4294967294); + +RWBuffer UAV1 : register(u2), UAV2 : register(u4); + +RWBuffer UAV3 : register(space0); + + + +// Compute Shader for UAV testing +[numthreads(8, 8, 1)] +[RootSignature(ROOT_SIGNATURE)] +void CSMain(uint id : SV_GroupID) +{ +Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0]; +} diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 398dcbb8d1737..a52a04323514c 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -7,6 +7,7 @@ //===--===// #include "DXILPostOptimizationValidation.h" +#include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/SmallString.h" @@ -84,8 +85,60 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } +static void reportRegNotBound(Module &M, Twine Type, + ResourceInfo::ResourceBinding Binding) { + SmallString<128> Message; + raw_svector_ostream OS(Message); + OS << "register " << Type << " (space=" << Binding.Space + << ", register=" << Binding.LowerBound << ")" + << " is not defined in Root Signature"; + M.getContext().diagnose(DiagnosticInfoGeneric(Message)); +} + +static dxbc::ShaderVisibility +tripleToVisibility(llvm::Triple::EnvironmentType ET) { + assert((ET == Triple::Pixel || ET == Triple::Vertex || + ET == Triple::Geometry || ET == Triple::Hull || + ET == Triple::Domain || ET == Triple::Mesh || + ET == Triple::Compu
[llvm-branch-commits] [clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)
https://github.com/joaosaffran ready_for_review https://github.com/llvm/llvm-project/pull/146785 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [DirectX] Add missing verifications during `validate` of `DXILRootSignature` (PR #147111)
https://github.com/inbelic created https://github.com/llvm/llvm-project/pull/147111 This pr resolves some discrepancies in verification during `validate` in `DXILRootSignature.cpp`. Namely, - `verifyDescriptorFlag` should be updated to check what flags are valid based on the root signature version, as reflected here https://github.com/llvm/wg-hlsl/pull/297. - There is currently no verification that `numDescriptors > 0` which should be added to be compliant with DXC: https://github.com/microsoft/DirectXShaderCompiler/blob/4fcf67f78f7d6ffd286316112694a3ae000860e2/lib/DxilRootSignature/DxilRootSignatureValidator.cpp#L197. - Updates `verifyDescriptorFlag` to check for valid flags based on version - Add test to demonstrate updated flag verifications - Adds `verifyNumDescriptors` to the validation of `DescriptorRange`s - Add a test to demonstrate `numDescriptors` verification - Updates a number of tests that mistakenly had an invalid `numDescriptors` specified Resolves: https://github.com/llvm/llvm-project/issues/147107 >From ab274d239bd12e39fc91d7cc2fc7e899be274e55 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 4 Jul 2025 20:54:50 + Subject: [PATCH 1/3] [HLSL][DirectX] Add `verifyNumDescriptors` --- .../Frontend/HLSL/RootSignatureValidations.h | 1 + .../HLSL/RootSignatureValidations.cpp | 4 llvm/lib/Target/DirectX/DXILRootSignature.cpp | 3 +++ ...-DescriptorTable-Invalid-NumDescriptors.ll | 19 +++ 4 files changed, 27 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-NumDescriptors.ll diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 9b68a524432cc..bcef20530559d 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -31,6 +31,7 @@ bool verifyDescriptorFlag(uint32_t Flags); bool verifyRangeType(uint32_t Type); bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, uint32_t FlagsVal); +bool verifyNumDescriptors(uint32_t NumDescriptors); bool verifySamplerFilter(uint32_t Value); bool verifyAddress(uint32_t Address); bool verifyMipLODBias(float MipLODBias); diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index b5b5fc0c74d83..6c238e0f04468 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -108,6 +108,10 @@ bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, return (Flags & ~Mask) == FlagT::None; } +bool verifyNumDescriptors(uint32_t NumDescriptors) { + return NumDescriptors > 0; +} + bool verifySamplerFilter(uint32_t Value) { switch (Value) { #define FILTER(Num, Val) case llvm::to_underlying(dxbc::SamplerFilter::Val): diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index e46b184a353f1..edad63bfe7ea7 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -447,6 +447,9 @@ static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) { if (!llvm::hlsl::rootsig::verifyRegisterSpace(Range.RegisterSpace)) return reportValueError(Ctx, "RegisterSpace", Range.RegisterSpace); +if (!llvm::hlsl::rootsig::verifyNumDescriptors(Range.NumDescriptors)) + return reportValueError(Ctx, "NumDescriptors", Range.NumDescriptors); + if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag( RSD.Version, Range.RangeType, Range.Flags)) return reportValueError(Ctx, "DescriptorFlag", Range.Flags); diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-NumDescriptors.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-NumDescriptors.ll new file mode 100644 index 0..99d126ee95443 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-NumDescriptors.ll @@ -0,0 +1,19 @@ +; RUN: not opt -passes='print' %s -S -o - 2>&1 | FileCheck %s + +target triple = "dxil-unknown-shadermodel6.0-compute" + +; CHECK: error: Invalid value for NumDescriptors: 0 +; CHECK-NOT: Root Signature Definitions + +define void @main() #0 { +entry: + ret void +} +attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } + + +!dx.rootsignatures = !{!2} ; list of function/root signature pairs +!2 = !{ ptr @main, !3, i32 2 } ; function, root signature +!3 = !{ !5 } ; list of root signature elements +!5 = !{ !"DescriptorTable", i32 0, !6} +!6 = !{ !"SRV", i32 0, i32 0, i32 10, i32 -1, i32 4 } >From 56ae9d9316fd02b588ba67ddf1820c9bd80bae49 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 4 Jul 2025 20:59:09 + Subject: [PA
[llvm-branch-commits] [llvm] [DirectX] Add missing verifications during `validate` of `DXILRootSignature` (PR #147111)
llvmbot wrote: @llvm/pr-subscribers-backend-directx Author: Finn Plummer (inbelic) Changes This pr resolves some discrepancies in verification during `validate` in `DXILRootSignature.cpp`. Namely, - `verifyDescriptorFlag` should be updated to check what flags are valid based on the root signature version, as reflected here https://github.com/llvm/wg-hlsl/pull/297. - There is currently no verification that `numDescriptors > 0` which should be added to be compliant with DXC: https://github.com/microsoft/DirectXShaderCompiler/blob/4fcf67f78f7d6ffd286316112694a3ae000860e2/lib/DxilRootSignature/DxilRootSignatureValidator.cpp#L197. - Updates `verifyDescriptorFlag` to check for valid flags based on version - Add test to demonstrate updated flag verifications - Adds `verifyNumDescriptors` to the validation of `DescriptorRange`s - Add a test to demonstrate `numDescriptors` verification - Updates a number of tests that mistakenly had an invalid `numDescriptors` specified Resolves: https://github.com/llvm/llvm-project/issues/147107 --- Full diff: https://github.com/llvm/llvm-project/pull/147111.diff 10 Files Affected: - (modified) llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h (+2-1) - (modified) llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp (+22-1) - (modified) llvm/lib/Target/DirectX/DXILRootSignature.cpp (+5-1) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll (+2-2) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-Flag.ll (+1-1) - (added) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-NumDescriptors.ll (+19) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-RangeType.ll (+1-1) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-RegisterSpace.ll (+1-1) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll (+2-2) - (modified) llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Parameters.ll (+2-2) ``diff diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 9b68a524432cc..03f4e2cf5bb8f 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -27,10 +27,11 @@ bool verifyRootFlag(uint32_t Flags); bool verifyVersion(uint32_t Version); bool verifyRegisterValue(uint32_t RegisterValue); bool verifyRegisterSpace(uint32_t RegisterSpace); -bool verifyDescriptorFlag(uint32_t Flags); +bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal); bool verifyRangeType(uint32_t Type); bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, uint32_t FlagsVal); +bool verifyNumDescriptors(uint32_t NumDescriptors); bool verifySamplerFilter(uint32_t Value); bool verifyAddress(uint32_t Address); bool verifyMipLODBias(float MipLODBias); diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index b5b5fc0c74d83..48d6b8639b2dc 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -32,7 +32,24 @@ bool verifyRegisterSpace(uint32_t RegisterSpace) { return !(RegisterSpace >= 0xFFF0 && RegisterSpace <= 0x); } -bool verifyDescriptorFlag(uint32_t Flags) { return (Flags & ~0xE) == 0; } +bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal) { + using FlagT = dxbc::RootDescriptorFlags; + FlagT Flags = FlagT(FlagsVal); + if (Version == 1) +return FlagsVal == FlagT::DataVolatile; + + assert(Version == 2 && "Provided invalid root signature version"); + + // The data-specific flags are mutually exclusive. + FlagT DataFlags = FlagT::DataVolatile | FlagT::DataStatic | +FlagT::DataStaticWhileSetAtExecute; + + if (popcount(llvm::to_underlying(Flags & DataFlags)) > 1) +return false; + + // Only a data flag or no flags is valid + return (FlagsVal & ~0xE) == 0; +} bool verifyRangeType(uint32_t Type) { switch (Type) { @@ -108,6 +125,10 @@ bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, return (Flags & ~Mask) == FlagT::None; } +bool verifyNumDescriptors(uint32_t NumDescriptors) { + return NumDescriptors > 0; +} + bool verifySamplerFilter(uint32_t Value) { switch (Value) { #define FILTER(Num, Val) case llvm::to_underlying(dxbc::SamplerFilter::Val): diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index e46b184a353f1..37a60075514ef 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -432,7 +432,8 @@ static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &R
[llvm-branch-commits] [llvm] [DirectX] Add missing verifications during `validate` of `DXILRootSignature` (PR #147111)
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/147111 >From ab274d239bd12e39fc91d7cc2fc7e899be274e55 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 4 Jul 2025 20:54:50 + Subject: [PATCH 1/6] [HLSL][DirectX] Add `verifyNumDescriptors` --- .../Frontend/HLSL/RootSignatureValidations.h | 1 + .../HLSL/RootSignatureValidations.cpp | 4 llvm/lib/Target/DirectX/DXILRootSignature.cpp | 3 +++ ...-DescriptorTable-Invalid-NumDescriptors.ll | 19 +++ 4 files changed, 27 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-NumDescriptors.ll diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 9b68a524432cc..bcef20530559d 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -31,6 +31,7 @@ bool verifyDescriptorFlag(uint32_t Flags); bool verifyRangeType(uint32_t Type); bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, uint32_t FlagsVal); +bool verifyNumDescriptors(uint32_t NumDescriptors); bool verifySamplerFilter(uint32_t Value); bool verifyAddress(uint32_t Address); bool verifyMipLODBias(float MipLODBias); diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index b5b5fc0c74d83..6c238e0f04468 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -108,6 +108,10 @@ bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, return (Flags & ~Mask) == FlagT::None; } +bool verifyNumDescriptors(uint32_t NumDescriptors) { + return NumDescriptors > 0; +} + bool verifySamplerFilter(uint32_t Value) { switch (Value) { #define FILTER(Num, Val) case llvm::to_underlying(dxbc::SamplerFilter::Val): diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index e46b184a353f1..edad63bfe7ea7 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -447,6 +447,9 @@ static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) { if (!llvm::hlsl::rootsig::verifyRegisterSpace(Range.RegisterSpace)) return reportValueError(Ctx, "RegisterSpace", Range.RegisterSpace); +if (!llvm::hlsl::rootsig::verifyNumDescriptors(Range.NumDescriptors)) + return reportValueError(Ctx, "NumDescriptors", Range.NumDescriptors); + if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag( RSD.Version, Range.RangeType, Range.Flags)) return reportValueError(Ctx, "DescriptorFlag", Range.Flags); diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-NumDescriptors.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-NumDescriptors.ll new file mode 100644 index 0..99d126ee95443 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-Invalid-NumDescriptors.ll @@ -0,0 +1,19 @@ +; RUN: not opt -passes='print' %s -S -o - 2>&1 | FileCheck %s + +target triple = "dxil-unknown-shadermodel6.0-compute" + +; CHECK: error: Invalid value for NumDescriptors: 0 +; CHECK-NOT: Root Signature Definitions + +define void @main() #0 { +entry: + ret void +} +attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } + + +!dx.rootsignatures = !{!2} ; list of function/root signature pairs +!2 = !{ ptr @main, !3, i32 2 } ; function, root signature +!3 = !{ !5 } ; list of root signature elements +!5 = !{ !"DescriptorTable", i32 0, !6} +!6 = !{ !"SRV", i32 0, i32 0, i32 10, i32 -1, i32 4 } >From 56ae9d9316fd02b588ba67ddf1820c9bd80bae49 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 4 Jul 2025 20:59:09 + Subject: [PATCH 2/6] fix up testcases using invalid num descriptors --- ...ootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll | 4 ++-- .../RootSignature-DescriptorTable-Invalid-Flag.ll | 2 +- .../RootSignature-DescriptorTable-Invalid-RangeType.ll| 2 +- .../RootSignature-DescriptorTable-Invalid-RegisterSpace.ll| 2 +- .../DirectX/ContainerData/RootSignature-DescriptorTable.ll| 4 ++-- .../CodeGen/DirectX/ContainerData/RootSignature-Parameters.ll | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll index 9d89dbdd9107b..053721de1eb1f 100644 --- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootS
[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)
@@ -744,8 +758,7 @@ static DiagnosedSilenceableFailure getThreadIdBuilder(std::optional transformOp, scf::ForallOp forallOp, ArrayRef blockSizes, int64_t warpSize, GpuIdBuilder &gpuIdBuilder) { - auto mappingAttr = cast( - forallOp.getMapping()->getValue().front()); + auto mappingAttr = forallOp.getDeviceMappingAttrs().front(); ftynse wrote: Nit: now that there's no more cast on the RHS, please expand `auto`. https://github.com/llvm/llvm-project/pull/146943 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)
@@ -78,7 +78,8 @@ struct GpuIdBuilder { /// If `useLinearMapping` is true, the `idBuilder` method returns nD values /// used for indexing rewrites as well as 1D sizes for predicate generation. struct GpuBlockIdBuilder : public GpuIdBuilder { - GpuBlockIdBuilder(MLIRContext *ctx, bool useLinearMapping = false); ftynse wrote: Could you please the comments above to reflect this new argument? Here and below. https://github.com/llvm/llvm-project/pull/146943 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)
@@ -60,8 +60,51 @@ def DeviceMappingAttrInterface : AttrInterface<"DeviceMappingAttrInterface"> { ]; } +def DeviceMaskingAttrInterface : AttrInterface<"DeviceMaskingAttrInterface"> { + let cppNamespace = "::mlir"; + let description = [{ +Attribute interface describing how to filter the processing units that a +region is mapped to. + +A popcount can be applied to determine the logical linear index that a +physical processing unit is responsible for. + }]; + + let methods = [ +InterfaceMethod< + /*desc=*/[{ +Return the logical active id for a given physical id. +Expects a physicalLinearMappingId of I64Type. + }], + /*retTy=*/"Value", + /*methodName=*/"getLogicalLinearMappingId", + /*args=*/(ins "OpBuilder&":$builder, "Value":$physicalLinearMappingId) +>, +InterfaceMethod< + /*desc=*/[{ +Return the dynamic condition determining whether a given physical id is +active under the mask. +Expects a physicalLinearMappingId of I64Type. + }], + /*retTy=*/"Value", + /*methodName=*/"getIsActiveIdPredicate", + /*args=*/(ins "OpBuilder&":$builder, "Value":$physicalLinearMappingId) +>, +InterfaceMethod< + /*desc=*/[{ +Return the maximal number of pysical ids supported. ftynse wrote: ```suggestion Return the maximal number of physical ids supported. ``` https://github.com/llvm/llvm-project/pull/146943 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)
@@ -60,8 +60,51 @@ def DeviceMappingAttrInterface : AttrInterface<"DeviceMappingAttrInterface"> { ]; } +def DeviceMaskingAttrInterface : AttrInterface<"DeviceMaskingAttrInterface"> { + let cppNamespace = "::mlir"; + let description = [{ +Attribute interface describing how to filter the processing units that a +region is mapped to. + +A popcount can be applied to determine the logical linear index that a +physical processing unit is responsible for. + }]; + + let methods = [ +InterfaceMethod< + /*desc=*/[{ +Return the logical active id for a given physical id. +Expects a physicalLinearMappingId of I64Type. + }], + /*retTy=*/"Value", + /*methodName=*/"getLogicalLinearMappingId", ftynse wrote: Optional naming nit: `bulidFoo` or `createFoo` instead of `getFoo` will make it clearer that some IR is being constructed. https://github.com/llvm/llvm-project/pull/146943 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)
@@ -60,8 +60,51 @@ def DeviceMappingAttrInterface : AttrInterface<"DeviceMappingAttrInterface"> { ]; } +def DeviceMaskingAttrInterface : AttrInterface<"DeviceMaskingAttrInterface"> { + let cppNamespace = "::mlir"; + let description = [{ +Attribute interface describing how to filter the processing units that a +region is mapped to. + +A popcount can be applied to determine the logical linear index that a +physical processing unit is responsible for. + }]; ftynse wrote: Could you please document what is understood by physical and logical ID here and how either of those can be linear. https://github.com/llvm/llvm-project/pull/146943 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)
https://github.com/ftynse edited https://github.com/llvm/llvm-project/pull/146943 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)
https://github.com/ftynse approved this pull request. Please address comments, okay otherwise https://github.com/llvm/llvm-project/pull/146943 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)
@@ -252,6 +252,24 @@ def GPULaneMappingAttr }]; } +def GPUMappingMaskAttr : GPU_Attr<"GPUMappingMask", "mask", [ + DeclareAttrInterfaceMethods ] > { + let parameters = (ins "uint64_t":$mask); + let assemblyFormat = "`<` params `>`"; + let description = [{ +Attribute describing how to filter the processing units that a +region is mapped to. + +In the first implementation the masking is a bitfield that specifies for +each processing unit whether it is active or not. + +In the future, we may want to implement this as a symbol to refer to +dynamically defined values. + +Extending op semantics with an operand is deemed too intrusive at this time. ftynse wrote: I think this rather belongs to code documentation or some rationale document, or even a commit message, not user-facing documentation. https://github.com/llvm/llvm-project/pull/146943 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)
@@ -60,8 +60,51 @@ def DeviceMappingAttrInterface : AttrInterface<"DeviceMappingAttrInterface"> { ]; } +def DeviceMaskingAttrInterface : AttrInterface<"DeviceMaskingAttrInterface"> { + let cppNamespace = "::mlir"; + let description = [{ +Attribute interface describing how to filter the processing units that a +region is mapped to. + +A popcount can be applied to determine the logical linear index that a +physical processing unit is responsible for. ftynse wrote: I'm not sure this part of the documentation is understandable by itself. It seems to imply that the attribute is systematically a bitfield, and I'm not sure I fully understand how a popcount is always needed to get a logical linear index. https://github.com/llvm/llvm-project/pull/146943 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [mlir] [mlir][GPU][transform] Add gpu_to_rocdl conversion pattern to transfo… (PR #146962)
@@ -129,6 +131,42 @@ LogicalResult transform::ApplyGPUSubgroupReduceToNVVMConversionPatternsOp:: return success(); } +void transform::ApplyGPUToROCDLConversionPatternsOp::populatePatterns( +TypeConverter &typeConverter, RewritePatternSet &patterns) { + auto &llvmTypeConverter = static_cast(typeConverter); + populateGpuMemorySpaceAttributeConversions( + llvmTypeConverter, [](AddressSpace space) { +switch (space) { +case AddressSpace::Global: + return 1; +case AddressSpace::Workgroup: + return 3; +case AddressSpace::Private: + return 5; ftynse wrote: Are you sure these address spaces are correct for ROCDL? https://github.com/llvm/llvm-project/pull/146962 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [mlir] [mlir][GPU][transform] Add gpu_to_rocdl conversion pattern to transfo… (PR #146962)
https://github.com/ftynse approved this pull request. Sounds good assuming the address space indices are correct. https://github.com/llvm/llvm-project/pull/146962 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147094)
@@ -1064,21 +1064,25 @@ SemaHLSL::ActOnStartRootSignatureDecl(StringRef Signature) { void SemaHLSL::ActOnFinishRootSignatureDecl( SourceLocation Loc, IdentifierInfo *DeclIdent, -SmallVector &Elements) { +ArrayRef RootElements) { + + if (handleRootSignatureElements(RootElements, Loc)) +return; + + SmallVector Elements; + for (auto &RootSigElement : RootElements) +Elements.push_back(RootSigElement.getElement()); auto *SignatureDecl = HLSLRootSignatureDecl::Create( SemaRef.getASTContext(), /*DeclContext=*/SemaRef.CurContext, Loc, DeclIdent, SemaRef.getLangOpts().HLSLRootSigVer, Elements); - if (handleRootSignatureDecl(SignatureDecl, Loc)) -return; - SignatureDecl->setImplicit(); SemaRef.PushOnScopeChains(SignatureDecl, SemaRef.getCurScope()); } -bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D, - SourceLocation Loc) { +bool SemaHLSL::handleRootSignatureElements( +ArrayRef Elements, SourceLocation Loc) { inbelic wrote: ```suggestion ArrayRef Elements) { ``` We no longer are required to use `Loc` https://github.com/llvm/llvm-project/pull/147094 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147094)
@@ -1103,9 +1107,15 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D, using ResourceRange = llvm::hlsl::rootsig::ResourceRange; using GroupT = std::pair; + // Introduce a mapping from the collected RangeInfos back to the + // RootSignatureElement that will retain its diagnostics info + llvm::DenseMap InfoIndexMap; inbelic wrote: ```suggestion llvm::SmallDenseMap InfoIndexMap; ``` https://github.com/llvm/llvm-project/pull/147094 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147094)
https://github.com/inbelic ready_for_review https://github.com/llvm/llvm-project/pull/147094 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Retain `SourceLocation` of `RootElement` for `SemaHLSL` diagnostics (PR #147094)
llvmbot wrote: @llvm/pr-subscribers-hlsl Author: Finn Plummer (inbelic) Changes At the moment, when we report diagnostics from `SemaHLSL` we only provide the source location of the root signature attr. This allows for significantly less helpful diagnostics (for eg. reporting resource range overlaps). This pr implements a way to retain the source location of a root element when it is parsed, so that we can output the `SourceLocation` of each root element that causes the overlap in the diagnostics during semantic analysis. This pr defines a wrapper struct `clang::hlsl::RootSignatureElement` in `SemaHLSL` that will contain the underlying `RootElement` and can hold any additional diagnostic information. This struct will be what is used in `HLSLRootSignatureParser` and in `SemaHLSL`. Then the diagnostic information will be stripped and the underlying element will be stored in the `RootSignatureDecl`. For the reporting of diagnostics, we can now use the retained `SourceLocation` of each `RootElement` when reporting the range overlap, and we can add a `note` diagnostic to highlight the other root element as well. - Defines `RootSignatureElement` in the `hlsl` namespace in `SemaHLSL` (defined in `SemaHLSL` because `Parse` has a dependency on `Sema`) - Updates parsing logic to construct `RootSignatureElement`s and retain the source loction in `ParseHLSLRootSignature` - Updates `SemaHLSL` when it constructs the `RootSignatureDecl` to take the new `RootSignatureElement` and store the underlying `RootElement` - Updates the current tests to ensure the new `note` diagnostic is produced and that the `SourceLocation` is seen - Adds a test to demonstrate the `SourceLocation` of both elements being correctly pointed out Resolves: https://github.com/llvm/llvm-project/issues/145819 --- Patch is 44.85 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/147094.diff 9 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+1) - (modified) clang/include/clang/Parse/ParseHLSLRootSignature.h (+4-2) - (modified) clang/include/clang/Sema/SemaHLSL.h (+25-4) - (modified) clang/lib/Parse/ParseDeclCXX.cpp (+1-1) - (modified) clang/lib/Parse/ParseHLSLRootSignature.cpp (+19-8) - (modified) clang/lib/Sema/SemaHLSL.cpp (+38-10) - (modified) clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl (+41) - (modified) clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp (+74-73) - (modified) llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h (+3) ``diff diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 968edd967e0c5..4fe0abb972a61 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13079,6 +13079,7 @@ def err_hlsl_resource_range_overlap: Error< "resource ranges %sub{subst_hlsl_format_ranges}0,1,2,3 and %sub{subst_hlsl_format_ranges}4,5,6,7 " "overlap within space = %8 and visibility = " "%select{All|Vertex|Hull|Domain|Geometry|Pixel|Amplification|Mesh}9">; +def note_hlsl_resource_range_here: Note<"overlapping resource range here">; // Layout randomization diagnostics. def err_non_designated_init_used : Error< diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index b0ef617a13c28..9ef5b64d7b4a5 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -17,6 +17,7 @@ #include "clang/Basic/DiagnosticParse.h" #include "clang/Lex/LexHLSLRootSignature.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/SemaHLSL.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -29,7 +30,7 @@ namespace hlsl { class RootSignatureParser { public: RootSignatureParser(llvm::dxbc::RootSignatureVersion Version, - SmallVector &Elements, + SmallVector &Elements, StringLiteral *Signature, Preprocessor &PP); /// Consumes tokens from the Lexer and constructs the in-memory @@ -196,7 +197,8 @@ class RootSignatureParser { private: llvm::dxbc::RootSignatureVersion Version; - SmallVector &Elements; + SmallVector &Elements; + clang::StringLiteral *Signature; RootSignatureLexer Lexer; clang::Preprocessor &PP; diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 7d7eae4db532c..910e0e640796b 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -32,6 +32,25 @@ class ParsedAttr; class Scope; class VarDecl; +namespace hlsl { + +// Introduce a wrapper struct around the underlying RootElement. This structure +// will retain extra clang diagnostic information that is not available in llvm. +struct RootSignatureElement { + RootSignatureElement(SourceLocation Loc, +
[llvm-branch-commits] [llvm] [DirectX] Improve error handling and validation in root signature parsing (PR #144577)
https://github.com/Icohedron approved this pull request. https://github.com/llvm/llvm-project/pull/144577 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [DirectX] Improve error accumulation in root signature parsing (PR #144465)
https://github.com/Icohedron approved this pull request. Looks fine to me https://github.com/llvm/llvm-project/pull/144465 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [NFC][HLSL] Move resource range logic from `SemaHLSL` to `RootSignatureValidations` (PR #147117)
https://github.com/Icohedron approved this pull request. https://github.com/llvm/llvm-project/pull/147117 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits