Repository navigation
Conversation
|
Hello @xyyy1420 👋 Thank you for submitting a Pull Request (PR) to the LLVM Project. Since this is your first PR, here are a few useful links covering our main contribution policies and review practices.
Please reply to this message to confirm that you have read these policies, especially the LLVM AI Tool Use Policy, and that any AI tool usage has been noted in the PR description. Frequently asked questionsHow do I add reviewers? This PR will be automatically labeled, and the relevant teams will be notified. For some parts of the project, reviewers may also be added automatically. You can also add reviewers manually using the Reviewers section on this page. If you cannot use that section, it is probably because you do not have write permissions for the repository. In that case, you can request a review by tagging reviewers in a comment using What if there are no comments? If you have not received any comments on your PR after a week, you can request a review by pinging the PR with a comment such as “Ping”. The common courtesy ping rate is once a week. Please remember that you are asking for volunteer time from other developers. Are any special GitHub settings required to contribute to LLVM? We only require contributors to have a public email address associated with their GitHub commits, see this section of LLVM Developer Policy for details. If you have questions, feel free to leave a comment on this PR, or ask on LLVM Discord or LLVM Discourse. Thank you, |
a18a043 to
ed439f3
Compare
afdd098 to
375bf3e
Compare
zhanghb97
left a comment
There was a problem hiding this comment.
Thanks for the contribution!
Type System
The current implementation maps all ZAMES tile types (int8, fp8, fp16, bf16, and fp32) to a fixed 16 x i8 representation, while the corresponding register classes use different sizes (256 bits for tile registers and 1024 bits for accumulator registers).
Could you clarify the intended semantics of this underlying type representation?
In particular:
- Is the
16 x i8representation intended to describe the actual in-memory layout of a tile, or is it only a placeholder for an opaque hardware register resource? - If these types represent hardware register resources, do we need
TargetExtType::CanBeLocalandTargetExtType::HasZeroInit? These properties may allow LLVM to treat them as local storage objects or support zero initialization, which does not necessarily match the intended register-only semantics. - How should DataLayout queries, alloca, memory operations, and zero initialization behave for these types?
I suggest explicitly defining the memory and storage semantics of these target extension types before exposing them to generic LLVM transformations. Otherwise, the current fixed-size representation may lead to inconsistent assumptions between LLVM IR and the RISC-V register allocation model.
Naming Consistency
One additional suggestion regarding naming consistency and vendor namespace management.
Since ZAMES/ZMASYNC are XSAI vendor extensions, I suggest including an explicit XSAI prefix in LLVM-internal names to avoid potential naming conflicts with other vendors' matrix extensions, especially given that this implementation already encounters register-name conflicts with BOSC AME.
For example:
- Intrinsics:
llvm.riscv.xsai.zames.*andllvm.riscv.xsai.zmasync.* - TargetExtType:
riscv.xsai.ame.tile.*andriscv.xsai.ame.sync - MVT and register definitions:
riscv_xsai_ame_*andXSAI_ZAMES_* - Pseudo instructions:
PSEUDO_XSAI_ZAMES_* - TableGen filenames: include
XSAIin the relevant filenames.
The architectural extension names (ZAMES/ZMASYNC), instruction mnemonics, and -march feature names should remain consistent with the official ISA specification.
This would make the LLVM implementation more maintainable and provide a clearer vendor namespace for future extensions.
| @@ -0,0 +1,107 @@ | |||
| //===- IntrinsicsRISCVZamesZmasync.td - Zames/Zmasync intrinsics -*- tablegen -*-===// | |||
There was a problem hiding this comment.
License header wrong format: please follow 80-col limitation.
There was a problem hiding this comment.
License header wrong format: please follow 80-col limitation.
Fixed in 343a51a. The banner in the renamed XSAI file now fits within 80 columns. Thanks for pointing this out!
| @@ -0,0 +1,308 @@ | |||
| //===-- RISCVInstrInfoZames.td - ZAMES/ZMASYNC instructions -*- tablegen -*-===// | |||
There was a problem hiding this comment.
License header wrong format: please follow 80-col limitation.
There was a problem hiding this comment.
License header wrong format: please follow 80-col limitation.
Fixed in 343a51a. The banner in the renamed XSAI file now fits within 80 columns. Thanks for pointing this out!
| @@ -0,0 +1,595 @@ | |||
| //===-- RISCVInstrInfoZamesPatterns.td - ZAMES/ZMASYNC pseudos -*- tablegen -*-===// | |||
There was a problem hiding this comment.
License header wrong format: please follow 80-col limitation.
There was a problem hiding this comment.
License header wrong format: please follow 80-col limitation.
Fixed in 343a51a. The banner in the renamed XSAI file now fits within 80 columns. Thanks for pointing this out!
| @@ -0,0 +1,96 @@ | |||
| //===-- RISCVRegisterInfoZames.td - ZAMES/ZMASYNC registers -*- tablegen -*-===// | |||
There was a problem hiding this comment.
License header wrong format: please follow 80-col limitation.
There was a problem hiding this comment.
License header wrong format: please follow 80-col limitation.
Fixed in 343a51a. The banner in the renamed XSAI file now fits within 80 columns. Thanks for pointing this out!
| def int_riscv_zames_msb_whole : ZAMESWholeStoreIntrinsic; | ||
| def int_riscv_zames_msc_whole : ZAMESWholeStoreIntrinsic; | ||
|
|
||
| class ZMASYNCSyncResetIntrinsic |
There was a problem hiding this comment.
The memory effects of ZMASYNC intrinsics need to be revisited.
Currently, all ZMASYNC intrinsics are defined with IntrNoMem and IntrHasSideEffects.
IntrHasSideEffects prevents the intrinsic from being treated as a pure operation, but it does not fully describe its ordering relationship with ordinary memory accesses.
In particular, mrelease and macquire are expected to provide release/acquire synchronization semantics. With IntrNoMem, LLVM is not informed that these operations impose ordering constraints on ordinary loads and stores.
For example:
- Stores preceding
mreleasemust not be reordered after the release operation. - Loads following
macquiremust not be reordered before the acquire operation. mfencemust enforce the memory ordering required by the hardware specification.
Please consider using appropriate memory effects (e.g. IntrReadWriteMem as a conservative starting point), or mapping these operations to LLVM's native atomic/fence semantics where applicable.
The corresponding MachineInstr definitions should also be reviewed to ensure that machine scheduling preserves the required ordering.
Please add optimization-level tests covering load/store motion across these synchronization intrinsics, rather than only testing instruction selection and encoding.
There was a problem hiding this comment.
Thanks for raising this. I checked the effective IR attributes and the machine-scheduling behavior; there are several layers of semantics to distinguish.
Hardware semantics
Specifically, mrelease increments the synchronization counter by one after the relevant matrix store completes. mfence provides the ordering needed for scalar/vector writes to become visible to subsequent matrix accesses.
With
IntrNoMem, LLVM is not informed that these operations impose ordering constraints on ordinary loads and stores.
I checked how the LLVM revision used by this branch handles this combination of properties. In IntrinsicEmitter.cpp, when an intrinsic has both no-memory effects and IntrHasSideEffects, getEffectiveME() changes its effective memory effects to MemoryEffects::unknown().
Consequently, these intrinsics are not exposed to the optimizer as memory(none) operations; the current effective memory model is conservative. I agree that the TableGen spelling is confusing. The checks performed so far have not revealed a correctness issue, and the spelling can be clarified in a follow-up.
I also ran paired optimizer checks using the actual llvm.riscv.xsai.zmasync.mfence intrinsic:
- LICM: without the intrinsic, the load was hoisted out of the loop; with the intrinsic, the load remained inside the loop after it.
- DSE: without the intrinsic, the first of two stores to the same address was removed; with the intrinsic between the stores, both stores were retained.
These checks demonstrate the current conservative optimizer behavior.
Machine scheduling and regression tests
The synchronization instructions currently have hasSideEffects = 1. This is represented as unmodeled side effects, which makes TargetInstrInfo::isGlobalMemoryObject() classify them as barrier nodes in ScheduleDAGInstrs. Therefore, even with mayLoad = mayStore = 0, the scheduler adds barrier-chain dependencies for stores and non-invariant loads.
Coverage is still missing for the following scenarios:
- Scalar/vector store →
mfence→ matrix load; - Matrix store →
mrelease; - Ordering of consumer accesses after acquire;
- The corresponding machine-scheduling constraints.
These test cases can be added in a follow-up.
Add matrix and synchronization intrinsics, target extension types, register classes, instruction encodings, assembly and disassembly. Implement RV64 SelectionDAG lowering with pre-RA configuration materialization and post-RA expansion. Track matrix memory operands, validate intrinsic immediate ranges, and diagnose unsupported RV32 code generation. Add IR, MC, MIR and CodeGen coverage. Keep vector exp2, MXFP and XX8 conversion extensions out of this change. Validation: - Build LLVM, Clang and MLIR with RISCV and X86 backends. - Pass 25 patch-related test files and 11 smoke scenarios. Matrix copy/spill/reload and cross-function ABI support remain outside the supported scope.
Use XSAI-prefixed target-extension types, MVTs, intrinsics, registers, opcodes, pseudos and TableGen filenames for the native matrix backend. Migrate the implementing consumers and IR/MIR checks together without retaining legacy aliases. Keep architectural features, assembly spellings and instruction encodings unchanged. Leave target type storage properties and sync memory effects for separate review. No numerical change is intended. Validation: 28 targeted LLVM/MC/IR/driver/MLIR tests passed. Representative integer, floating-point and sync codegen text sections are byte-identical; storage and O2/O3 sync-ordering non-change smokes passed.
Shorten the four native matrix TableGen file banners and put long backend filenames on a separate comment line. Preserve the existing license text. This is comment-only and does not change declarations, code generation, instruction encodings or the architectural interface.
Replace the mixed riscv.xsai.ame target type namespace with riscv.xsai.zames.tile.* for matrix tiles and riscv.xsai.zmasync.sync for synchronization values. Align the MVT definitions, native register aliases, type conversions, overload suffixes and fixtures. Do not retain compatibility aliases for the mixed namespace. Keep type storage properties, sync memory effects, architectural features, assembly spellings and instruction encodings unchanged. No numerical change is intended. Validation: rebuilt the affected LLVM/MLIR tools; 28 targeted tests passed. Three representative integer, floating-point and sync text sections are byte-identical. All eight native storage types, invalid matrix/sync type parameters and O2/O3 sync ordering and machine verification smokes passed.
Native XSAI tile and synchronization values are register resources. Drop CanBeLocal and HasZeroInit, which were reserved for possible frontend support that is not currently planned. Keep explicit mzero and msyncregreset initialization and the existing native SSA interface. Add assembler regressions rejecting alloca, byval and zero constants. The remaining sized-layout limitation is unchanged: ordinary load/store/GEP can still pass generic verification and are not supported native uses. Validation: the property-only state passed 30 targeted LLVM tests, 27 native ZAMES tests and all 24 storage/zero rejection cases. Representative integer, floating-point and synchronization machine code is byte-identical; supported native computations have no numerical change.
Replace the sized tile and synchronization layout placeholders with void. The target extension identities remain intact, but ordinary LLVM memory objects and address arithmetic no longer acquire fictional sizes or strides. Extend assembler coverage to reject ordinary loads, stores and GEP, including constant-expression GEP, while retaining legal SSA phi/select carriers. Native select instruction selection and cross-function ABI support are unchanged. Validation: the final state passed 30 targeted LLVM tests, 27 native ZAMES tests, 64 negative storage/address cases and O2/O3 SSA optimization smoke. Representative integer, floating-point and synchronization machine code is byte-identical to the sized layout; supported native computations have no numerical change. Native tile select instruction selection remains an independently confirmed preexisting limitation.
|
Thanks for the detailed review. I agree that the register-resource semantics of these types should be explicit. In response to your review: Type system
The original representation was only a placeholder, not the intended in-memory layout. These types represent opaque hardware register resources carried through LLVM IR as SSA values. The fixed vector layout was indeed misleading. I have changed the layout of all seven native matrix tile types and the synchronization type to
No. Both properties have been removed.
The contract is now:
I added coverage in The property removal and unsized-layout changes are in c10ab12 and 5469e4b, respectively. Naming consistency
Agreed. I have added the XSAI namespace to the LLVM-internal intrinsic names, target extension types, MVTs, register definitions, pseudo opcodes, and relevant TableGen filenames, and updated the affected tests and callers. The intrinsic namespaces are now:
The target extension types use:
Rather than placing both under a shared The architectural extension names, instruction mnemonics, and These changes are in 006120a and e6b128e. ValidationAfter rebasing, all 33 tests in the selected LLVM/Clang/MLIR regression set passed. The emitted |
变更说明
本 PR 基于 riscv 分支,为两个 XSAI RISC-V vendor extension 增加 LLVM 后端支持:
主要修改:
由于 base 中 BOSC 与 ZAMES 共享 tr0/acc0 汇编名,RISCVAsmParser.cpp 中的寄存器 coercion 保留;
参考手册:
已知限制:
验证方式
平台与构建:
ZAMES/ZMASYNC 测试:
结果:23/23 PASS。
Clang driver:
结果:PASS。
格式/空白检查:
git -C llvm diff --check结果:clean。
检查清单