[CodeGen] Add per-exit scratch register clearing - #13
Conversation
|
Hello @claude[bot] 👋 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, |
|
That inverts the principle this code states for itself — "silence is indistinguishable from having zeroed the registers" ( At an absolute minimum the flag must not bypass Detail, and the rest of the findings on this patch, in the write-up: https://claude.ai/code/artifact/accb9215-36b5-4022-ae0f-249ee54e99cb Generated by Claude Code |
4116012 to
3d68722
Compare
9c4ac60 to
3e2a3e5
Compare
3d68722 to
abdc7d6
Compare
3e2a3e5 to
3405cff
Compare
abdc7d6 to
656ebca
Compare
3405cff to
664634f
Compare
656ebca to
8517050
Compare
664634f to
ed4f423
Compare
ed4f423 to
a97bff7
Compare
8517050 to
4dc1dc5
Compare
4dc1dc5 to
8c05331
Compare
a97bff7 to
623c3eb
Compare
8c05331 to
973af63
Compare
623c3eb to
1c37db2
Compare
973af63 to
e1b413e
Compare
1c37db2 to
7e82218
Compare
e1b413e to
f27557a
Compare
7e82218 to
15fe301
Compare
f27557a to
f50f98d
Compare
15fe301 to
73ccafc
Compare
f50f98d to
d647dcc
Compare
73ccafc to
105571b
Compare
d647dcc to
e4b843d
Compare
105571b to
d3065b6
Compare
e4b843d to
3c79e20
Compare
d3065b6 to
b7d5d0d
Compare
3c79e20 to
44c97ff
Compare
b7d5d0d to
02b631a
Compare
44c97ff to
feed259
Compare
02b631a to
a2a7792
Compare
a2a7792 to
50f73ff
Compare
feed259 to
6f28360
Compare
6f28360 to
256c80a
Compare
50f73ff to
a062797
Compare
a062797 to
cabfa61
Compare
Require targets to opt in to scratch clearing for full-width registers that their emitter actually clears. Reject unsupported, reserved, live, callee-saved, and return-address registers in release and assertions-enabled builds. This prevents X86 AH clears from corrupting AL returns and rejects MMX scratch registers that the emitter skips. Restrict AArch64 declarations to the GPRs accepted by its clear emitter, including under preserve_nonecc and ghccc. Preserve unsupported-stack diagnostics when the scratch test hook is enabled, and remove private tracker references from source and test comments. Validation: rebuilt assertions-enabled llc with X86, ARM, AArch64, and RISCV. The relevant CodeGen suites passed 318 tests with 4 unsupported. Added negative and positive scratch regressions, including an AArch64 calling-convention test confirmed to fail before the fix. Changed-line clang-format and git diff --check passed.
Track scratch registers per exit and merge them into register clearing after candidate filtering. Validate target support, register width, reserved and finalized callee-saved registers, return addresses, and live exit operands before emission. Keep stack clearing capability-driven and remove the synthetic scratch-injection option. Exercise the shared consumer with 70 unit cases using real target backends, add an unsupported-stack regression, and register the sources in CMake and GN. Tighten clearing comments and remove private tracker references. Validation: assertions-enabled llc and CodeGenTests built successfully; 391 unit tests and 312 selected lit tests passed. GN source lists were checked; GN was unavailable locally. Co-authored-by: Claude <noreply@anthropic.com>
17234b3 to
72a7fe8
Compare
72a7fe8 to
17234b3
Compare
Requested by Francesco Bertolaccini · Slack thread
Stack clearing can dirty registers that the function's
zero-call-used-regsmode does not select. This PR adds preparatory infrastructure for a future stack-clearing producer: per-exit scratch bookkeeping and a shared consumer that validates declarations, merges them into the exit's filtered register set, and emits register clears.Targets explicitly identify full-width registers their emitter can clear. The helper rejects unsupported, reserved, live, return-address, and finalized callee-saved registers, including custom call-saved registers. Invalid declarations produce errors in both release and assertions-enabled builds.
Current production scope
No stack-clearing producer is implemented here.
planClearStack()never returnsEmit, and no production step populatesScratchRegs. Consequently, scratch-only register planning and nonempty scratch propagation and printing are dormant. The shared consumer is used by ordinary register clearing with an empty scratch set; this PR does not yet provide production scratch clearing.The production compiler has no scratch-injection flag or synthetic capability override. Unsupported stack requests retain their warning and are never reported as emitted. They can still compile successfully without clearing the frame; this PR does not change that diagnostic policy.
Coverage and follow-up
The 70 parameterized cases are helper unit tests using real X86, AArch64, and RISC-V backends. They directly supply candidate and scratch sets to test merging, instruction semantics, independent helper calls for different exits, and rejection of invalid declarations and custom call-saved registers.
The cases with absent or
skipregister attributes do not exercise PEI planning. Likewise, directly supplying filtered candidates or calling the helper for separate exits does not verify PEI filtering, scratch declaration, propagation between clearing steps, or printing. These cases establish the helper contract, not end-to-end PEI integration coverage.A production CodeGen regression checks that an unsupported stack clear does not force register clearing or report successful stack emission, while an explicit register-clearing request still runs independently.
The first real stack-clearing producer belongs in a follow-up PR stacked on this infrastructure. That follow-up must exercise the production path end to end: scratch declaration by the producer, required register clearing with absent/
skipattributes, merging after exit filtering, independent per-exit propagation, emitted clears, and scratch printing. The dormant integration should not be treated as a completed stack-clearing feature before that validation lands.Validation
Results recorded for the current implementation:
llcandCodeGenTestsbuild passed.zeroize-guaranteed-tailcall.lltest was excluded.AI tool use
This PR contains AI-assisted code and text. The original patch used Claude Code; subsequent review fixes and the unit-test fixture used Codex.