-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Allow enum
and union
literals to also create SSA values
#138759
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
base: master
Are you sure you want to change the base?
Conversation
r? @Nadrieril rustbot has assigned @Nadrieril. Use |
Some changes occurred in compiler/rustc_codegen_ssa |
This comment has been minimized.
This comment has been minimized.
These commits modify the If this was unintentional then you should revert the changes before this PR is merged. |
r? codegen |
Spiderman meme |
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
Allow `enum` and `union` literals to also create SSA values Today, `Some(x)` always goes through an `alloca`, even in trivial cases where the niching means the constructor doesn't even change the value. For example, <https://rust.godbolt.org/z/6KG6PqoYz> ```rust pub fn demo(r: &i32) -> Option<&i32> { Some(r) } ``` currently emits the IR ```llvm define align 4 ptr `@demo(ptr` align 4 %r) unnamed_addr { start: %_0 = alloca [8 x i8], align 8 store ptr %r, ptr %_0, align 8 %0 = load ptr, ptr %_0, align 8 ret ptr %0 } ``` but with this PR it becomes just ```llvm define align 4 ptr `@demo(ptr` align 4 %r) unnamed_addr { start: ret ptr %r } ``` (Of course the optimizer can clean that up, but it'd be nice if it didn't have to -- especially in debug where it doesn't run. This is like rust-lang#123886, but that only handled non-simd `struct`s -- this PR generalizes it to all non-simd ADTs.) There's two commits you can review independently: 1. The first is simplifying how the aggregate handling works. Past-me wrote something overly complicated, needing arrayvecs and zipping, depending on a careful iteration order of the fields, and fragile enough that even for just structs it needed extra double-checks to make sure it even made the right variant. It's replaced with something far more direct that works just like `extract_field`: use the offset to put it in exactly the correct immediate in the `OperandValue`. This doesn't support anything new, just refactors -- including moving some things off `FunctionCx` that had no reason to be there. (I have no idea why my past self put them there.) 2. The second extends that work to support more ADTs. That means handing variants other than `FIRST_VARIANT`, handling the active field for unions, refactoring the discriminant code so the Place and Operand parts can share the calculation, etc.
☀️ Try build successful - checks-actions |
This comment has been minimized.
This comment has been minimized.
Finished benchmarking commit (875f416): comparison URL. Overall result: ❌✅ regressions and improvements - please read the text belowBenchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf. Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @bors rollup=never Instruction countThis is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.
Max RSS (memory usage)Results (primary -2.3%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResults (secondary -2.1%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeResults (primary -0.1%, secondary -0.1%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Bootstrap: 775.297s -> 774.424s (-0.11%) |
This comment has been minimized.
This comment has been minimized.
9423566
to
a9031aa
Compare
Ben said I should re-roll this |
hello. |
…gjubilee Remove unneeded `FunctionCx` from some codegen methods No changes; just removing the `self` that wasn't needed. r? workingjubilee cc rust-lang#138759 (comment)
…gjubilee Remove unneeded `FunctionCx` from some codegen methods No changes; just removing the `self` that wasn't needed. r? workingjubilee cc rust-lang#138759 (comment)
Rollup merge of #142324 - scottmcm:less-functioncx, r=workingjubilee Remove unneeded `FunctionCx` from some codegen methods No changes; just removing the `self` that wasn't needed. r? workingjubilee cc #138759 (comment)
☔ The latest upstream changes (presumably #142358) made this pull request unmergeable. Please resolve the merge conflicts. |
Remove unneeded `FunctionCx` from some codegen methods No changes; just removing the `self` that wasn't needed. r? workingjubilee cc rust-lang/rust#138759 (comment)
…kingjubilee CodeGen: rework Aggregate implemention for rvalue_creates_operand cases A non-trivial refactor pulled out from rust-lang#138759 r? workingjubilee The previous implementation I'd written here based on `index_by_increasing_offset` is complicated to follow and difficult to extend to non-structs. This changes the implementation, without actually changing any codegen (thus no test changes either), to be more like the existing `extract_field` (<https://github.com/rust-lang/rust/blob/2b0274c71dba0e24370ebf65593da450e2e91868/compiler/rustc_codegen_ssa/src/mir/operand.rs#L345-L425>) in that it allows setting a particular field directly. Notably I've found this one much easier to get right, in particular because having the `OperandRef<Result<V, Scalar>>` gives a really useful thing to include in ICE messages if something did happen to go wrong.
…kingjubilee CodeGen: rework Aggregate implemention for rvalue_creates_operand cases A non-trivial refactor pulled out from rust-lang#138759 r? workingjubilee The previous implementation I'd written here based on `index_by_increasing_offset` is complicated to follow and difficult to extend to non-structs. This changes the implementation, without actually changing any codegen (thus no test changes either), to be more like the existing `extract_field` (<https://github.com/rust-lang/rust/blob/2b0274c71dba0e24370ebf65593da450e2e91868/compiler/rustc_codegen_ssa/src/mir/operand.rs#L345-L425>) in that it allows setting a particular field directly. Notably I've found this one much easier to get right, in particular because having the `OperandRef<Result<V, Scalar>>` gives a really useful thing to include in ICE messages if something did happen to go wrong.
…kingjubilee CodeGen: rework Aggregate implemention for rvalue_creates_operand cases A non-trivial refactor pulled out from rust-lang#138759 r? workingjubilee The previous implementation I'd written here based on `index_by_increasing_offset` is complicated to follow and difficult to extend to non-structs. This changes the implementation, without actually changing any codegen (thus no test changes either), to be more like the existing `extract_field` (<https://github.com/rust-lang/rust/blob/2b0274c71dba0e24370ebf65593da450e2e91868/compiler/rustc_codegen_ssa/src/mir/operand.rs#L345-L425>) in that it allows setting a particular field directly. Notably I've found this one much easier to get right, in particular because having the `OperandRef<Result<V, Scalar>>` gives a really useful thing to include in ICE messages if something did happen to go wrong.
Rollup merge of #142383 - scottmcm:operandref-builder, r=workingjubilee CodeGen: rework Aggregate implemention for rvalue_creates_operand cases A non-trivial refactor pulled out from #138759 r? workingjubilee The previous implementation I'd written here based on `index_by_increasing_offset` is complicated to follow and difficult to extend to non-structs. This changes the implementation, without actually changing any codegen (thus no test changes either), to be more like the existing `extract_field` (<https://github.com/rust-lang/rust/blob/2b0274c71dba0e24370ebf65593da450e2e91868/compiler/rustc_codegen_ssa/src/mir/operand.rs#L345-L425>) in that it allows setting a particular field directly. Notably I've found this one much easier to get right, in particular because having the `OperandRef<Result<V, Scalar>>` gives a really useful thing to include in ICE messages if something did happen to go wrong.
CodeGen: rework Aggregate implemention for rvalue_creates_operand cases A non-trivial refactor pulled out from rust-lang/rust#138759 r? workingjubilee The previous implementation I'd written here based on `index_by_increasing_offset` is complicated to follow and difficult to extend to non-structs. This changes the implementation, without actually changing any codegen (thus no test changes either), to be more like the existing `extract_field` (<https://github.com/rust-lang/rust/blob/2b0274c71dba0e24370ebf65593da450e2e91868/compiler/rustc_codegen_ssa/src/mir/operand.rs#L345-L425>) in that it allows setting a particular field directly. Notably I've found this one much easier to get right, in particular because having the `OperandRef<Result<V, Scalar>>` gives a really useful thing to include in ICE messages if something did happen to go wrong.
4c822e9
to
3c75d48
Compare
Perf was good three months ago, but having redone this a bunch it's probably worth double-checking: |
This comment has been minimized.
This comment has been minimized.
Allow `enum` and `union` literals to also create SSA values Today, `Some(x)` always goes through an `alloca`, even in trivial cases where the niching means the constructor doesn't even change the value. For example, <https://rust.godbolt.org/z/6KG6PqoYz> ```rust pub fn demo(r: &i32) -> Option<&i32> { Some(r) } ``` currently emits the IR ```llvm define align 4 ptr `@demo(ptr` align 4 %r) unnamed_addr { start: %_0 = alloca [8 x i8], align 8 store ptr %r, ptr %_0, align 8 %0 = load ptr, ptr %_0, align 8 ret ptr %0 } ``` but with this PR it becomes just ```llvm define align 4 ptr `@demo(ptr` align 4 %r) unnamed_addr { start: ret ptr %r } ``` (Of course the optimizer can clean that up, but it'd be nice if it didn't have to -- especially in debug where it doesn't run. This is like #123886, but that only handled non-simd `struct`s -- this PR generalizes it to all non-simd ADTs.) Doing this means handing variants other than `FIRST_VARIANT`, handling the active field for unions, refactoring the discriminant code so the Place and Operand parts can share the calculation, etc. Other PRs that led up to this one: - #142005 - #142103 - #142324 - #142383
This comment has been minimized.
This comment has been minimized.
mir::Rvalue::Aggregate(ref kind, _) => { | ||
let allowed_kind = match **kind { | ||
// This always produces a `ty::RawPtr`, so will be Immediate or Pair | ||
mir::AggregateKind::RawPtr(..) => true, | ||
mir::AggregateKind::Array(..) => false, | ||
mir::AggregateKind::Tuple => true, | ||
mir::AggregateKind::Adt(def_id, ..) => { | ||
let adt_def = self.cx.tcx().adt_def(def_id); | ||
adt_def.is_struct() && !adt_def.repr().simd() | ||
} | ||
mir::AggregateKind::Closure(..) => true, | ||
// FIXME: Can we do this for simple coroutines too? | ||
mir::AggregateKind::Coroutine(..) | mir::AggregateKind::CoroutineClosure(..) => false, | ||
}; | ||
allowed_kind && { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an update from previous revisions of this PR, note that we no longer need to check the AggregateKind here at all. The layout check is enough to cover all the possibilities.
☀️ Try build successful - checks-actions |
This comment has been minimized.
This comment has been minimized.
Finished benchmarking commit (cf39981): comparison URL. Overall result: ✅ improvements - no action neededBenchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf. @bors rollup=never Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -4.6%, secondary -0.5%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (secondary 8.7%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary -0.1%, secondary -0.1%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 692.997s -> 691.442s (-0.22%) |
Today,
Some(x)
always goes through analloca
, even in trivial cases where the niching means the constructor doesn't even change the value.For example, https://rust.godbolt.org/z/6KG6PqoYz
currently emits the IR
but with this PR it becomes just
(Of course the optimizer can clean that up, but it'd be nice if it didn't have to -- especially in debug where it doesn't run. This is like #123886, but that only handled non-simd
struct
s -- this PR generalizes it to all non-simd ADTs.)Doing this means handing variants other than
FIRST_VARIANT
, handling the active field for unions, refactoring the discriminant code so the Place and Operand parts can share the calculation, etc.Other PRs that led up to this one:
tag_field
toFieldIdx
inVariants::Multiple
#142005InterpCx::project_field
to takeFieldIdx
#142103FunctionCx
from some codegen methods #142324