Skip to content

Conversation

ZuseZ4
Copy link
Member

@ZuseZ4 ZuseZ4 commented Sep 30, 2025

closes #147144

The two gsoc summer projects caused a bit of churn, which was to be expected, especially since we don't run autodiff in CI yet.
This adds a void return testcase that we should have had anyway, and fixes the regression.

r? @Zalathar (Just guessing since I've seen you in a few LLVM PRs and Oli is probably still busy. Feel free to reroll!)

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. F-autodiff `#![feature(autodiff)]` S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Sep 30, 2025
@rust-log-analyzer

This comment has been minimized.

@ZuseZ4 ZuseZ4 force-pushed the fix-autodiff-emptry-ret branch from 1791078 to 4125b9b Compare September 30, 2025 22:27
@rust-log-analyzer

This comment has been minimized.

@ZuseZ4 ZuseZ4 force-pushed the fix-autodiff-emptry-ret branch from 4125b9b to 8b8cbe0 Compare September 30, 2025 22:38
Comment on lines 381 to 388
let fn_ret_ty = builder.cx.val_ty(call);
if fn_ret_ty != builder.cx.type_void() && fn_ret_ty != builder.cx.type_struct(&[], false) {
builder.store_to_place(call, dest.val);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An equality test against an empty struct type seems unlikely to be the right check here, but I don't know enough about LLVM IR to say what the right check would be.

Also, is there any reasonable way to test the non-void case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every other test case in codegen-llvm/autodiff handles the non-void cases, we apparently just never had one for the void case since before the refactor it just used to work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, what I mean is the empty-struct case. Is that covered by tests?

Copy link
Member Author

@ZuseZ4 ZuseZ4 Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, that's what this test is testing.
// CHECK-NOT: store {} undef, ptr undef the line is currently generated by rustc master since the call (before this PR) returns an empty struct, {}. I haven't added a test for void ret, since we now (since the last refactor) don't seem to generate void returns anymore, so I can't test it. I still have added handling for it, just in case that this changes again in the future.

As an example for what we currently generate. I'm testing for us not generating the store anymore, since it's the part causing UB.

%27 = call {} (...) @__enzyme_autodiff_ZN5piprx8d_energy17hfdc5833849837ebfE(ptr @_ZN5piprx16f_energy_inplace17h5cbf6d64465cb049E, metadata !"enzyme_dup", ptr %18, ptr          %20, metadata !"enzyme_const", ptr %22, metadata !"enzyme_dup", ptr %24, ptr %26)
          store {} %27, ptr undef, align 1

Other than that, testing for equality against the empty struct {} isn't overly pretty, but at that point we already lost the Rust types and only have 'll types left, so we can't use all the nice Rust functions to check for things. It didn't seem worthwhile to me to carry them around till the end since it feels like too much code just to make the check a little prettier, but I don't have overly strong opinions about it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not necessarily sufficient, you can have an empty struct of an empty struct (and that is indeed used within enzyme).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

@ZuseZ4 ZuseZ4 Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering about using something more general, but if that's needed, we should likely update our logic elsewhere, where we generate those declarations.

Fyi, the bug here materialized before we ran enzyme. It was because we now generate the enzyme decl (if it doesn't return) as having the {} return type. In my previous code I had generated them to have void ret type, I'd be fine to change it back to void ret. Our logic doesn't generate __enzyme declarations with nested empty return types, so they can't show up here. If you have a better rule on how to generate the return type of enzyme for zst I'm also open to update it.

@Zalathar
Copy link
Contributor

Zalathar commented Oct 1, 2025

(If you just want to get the void fix rubber-stamped and worry about the finer details later, please add some kind of suitable FIXME and I'll approve.)

@ZuseZ4 ZuseZ4 force-pushed the fix-autodiff-emptry-ret branch from 8b8cbe0 to de189fa Compare October 1, 2025 02:47
@ZuseZ4
Copy link
Member Author

ZuseZ4 commented Oct 1, 2025

No worries, I'd like to land it but my colleagues are also used to use a custom rustc fork anyway, so there is no rubber-stamping needed if you see a better way of testing/handling it. I added some documentation since it clearly wasn't self-explanatory. Does that help?

@Zalathar
Copy link
Contributor

Zalathar commented Oct 1, 2025

It feels like there should be some more general way to ask LLVM “is this a type that makes no sense to store”, but I don't have enough LLVM knowledge to say what that better way would be.

At any rate, the check in this PR seems clearly better than the status quo, so I'm fine with merging it.

@bors r+

@bors
Copy link
Collaborator

bors commented Oct 1, 2025

📌 Commit de189fa has been approved by Zalathar

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 1, 2025
bors added a commit that referenced this pull request Oct 1, 2025
Rollup of 11 pull requests

Successful merges:

 - #146918 (add regression test)
 - #146980 (simplify setup_constraining_predicates, and note it is potentially cubic)
 - #147170 (compiletest: Pass around `DirectiveLine` instead of bare strings)
 - #147180 (add tests)
 - #147188 (Remove usage of `compiletest-use-stage0-libtest` from CI)
 - #147189 (Replace `rustc_span::Span` with a stripped down version for librustdoc's highlighter)
 - #147199 (remove outdated comment in (inner) `InferCtxt`)
 - #147200 (Fix autodiff empty ret regression)
 - #147209 (Remove `no-remap-src-base` from tests)
 - #147213 (Fix broken STD build for ESP-IDF)
 - #147217 (Don't create a top-level `true` directory when running UI tests)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 7b0236f into rust-lang:master Oct 1, 2025
10 checks passed
@rustbot rustbot added this to the 1.92.0 milestone Oct 1, 2025
rust-timer added a commit that referenced this pull request Oct 1, 2025
Rollup merge of #147200 - ZuseZ4:fix-autodiff-emptry-ret, r=Zalathar

Fix autodiff empty ret regression

closes #147144

The two gsoc summer projects caused a bit of churn, which was to be expected, especially since we don't run autodiff in CI yet.
This adds a void return testcase that we should have had anyway, and fixes the regression.

r? `@Zalathar` (Just guessing since I've seen you in a few LLVM PRs and Oli is probably still busy. Feel free to reroll!)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. F-autodiff `#![feature(autodiff)]` S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

autodiff not handling void returns
6 participants