-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Several trivial Vec<T>
methods (deref, as_ref, etc) end up in compiled output when optimizing for size.
#89389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think godbolt is running rustc to build a .o. Doesn't linking strip these from the final artifact? |
Hm, yeah I see your point — for the godbolt link I posted, I would imagine something can remove those as they are never called. I think the answer to your question is yest though. At least, they showed up in some of FWIW, I somewhat recently complained about this issue on the community discord server, and someone (@saethlin, unless that username refers to two separate people) said1 that they had seen it before, and that it goes away if you emit IR and run it manually through opt. That's too fiddly for me, so I didn't try it (I'd want to try fiddling with the passes list / inline threshold first)... but it indicates others hit this too. Footnotes
|
Yes, you got the right person :) I'm unclear if that godbolt link is demonstrating what you wanted. As far as I can tell, the problem is not that the symbols are left in the output. The problem is that these trivial functions aren't inlined. In my experience, these examples appear with I can currently reproduce this https://github.com/saethlin/fls,
by running I can find similar examples of this form (trivial function not inlined with From looking at the calls specifically to I have never fiddled with any LLVM flags in order to dig deeper. I really don't know what I'm doing there, and passing arguments to the LLVM components through cargo has always confused me. |
@thomcc the opt-level
@saethlin could you retest with |
Test case replicating situation created by MergeFunctions pass (inlining would work with opaque pointer types): ; ModuleID = 'a.ll'
source_filename = "fls.4e5c6cbe-cgu.3"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: nounwind nonlazybind
define hidden i32 @f() unnamed_addr #0 {
%1 = call { [0 x i32]*, i64 } bitcast ({ [0 x i64]*, i64 } ()* @g to { [0 x i32]*, i64 } ()*)() #0
ret i32 0
}
; Function Attrs: nounwind nonlazybind
define hidden { [0 x i64]*, i64 } @g() unnamed_addr #0 {
ret { [0 x i64]*, i64 } undef
}
attributes #0 = { nounwind nonlazybind "target-cpu"="x86-64" } @rustbot modify labels: +A-llvm |
@tmiasko I can confirm that for the examples that I have, |
I don't really know when this was fixed, but I'm not seeing the particular codegen that I complained about on 1.58.0 (latest stable) or nightly-2022-01-15 (latest nightly) anymore. |
Godbolt repro: https://rust.godbolt.org/z/caG4MEjsr
With
-Copt-level=s
and-Copt-level=z
the functions<Vec<T> as Deref>::deref
and<Vec<T> as AsRef<[T]>>::as_ref
show up in the output pointlessly. Similarly for the mut versions (AsMut, DerefMut, etc), and a few similar methods I tried (Borrow::borrow for example).There are probably some other similar issues too (it seems a lot of our library code is optimized for
-Copt-level=3
rather than with size optimizations...).Note that this can end up with a lot of copies of these functions, since you get at least one for each
T
you useVec<T>::deref
with, which is basically one for eachT
you put in aVec
.Also note that these get fully optimized away on both
-Copt-level=3
and-Copt-level=2
.One way to fix this is probably to make these
#[inline(always)]
, but it seems weird that these would show up at all, so perhaps there's a better way which can fix the issue more broadly.The text was updated successfully, but these errors were encountered: