Repository navigation
Missing optimization around __rust_alloc and unknown functions if panic=unwind #46515
Copy link
Copy link
Labels
A-allocatorsArea: Custom and system allocatorsArea: Custom and system allocatorsC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.
Description
The following code gets optimized as expected:
pub fn test() -> bool {
let x = &*Box::new(0);
let y = &*Box::new(0);
if x as *const _ == y as *const _ {
return true;
}
return false;
}; example::test
; Function Attrs: nounwind uwtable
define zeroext i1 @example::test() unnamed_addr #0 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality !dbg !18 {
ret i1 false, !dbg !22
}
However, if I let the code call an unknown function instead of return, the optimization disappears:
pub fn test(f: fn()) {
let x = &*Box::new(0);
let y = &*Box::new(0);
if x as *const _ == y as *const _ {
f();
}
}; example::test
; Function Attrs: uwtable
define void @example::test(void ()* nocapture nonnull %f) unnamed_addr #1 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality !dbg !36 {
%err.i.i.i10 = alloca %"core::mem::ManuallyDrop<alloc::allocator::AllocErr>", align 8
%_5.i.i.i.i11 = alloca %"alloc::allocator::AllocErr", align 8
%err.i.i.i = alloca %"core::mem::ManuallyDrop<alloc::allocator::AllocErr>", align 8
%_5.i.i.i.i = alloca %"alloc::allocator::AllocErr", align 8
%_9.sroa.9.i.i = alloca [16 x i8], align 8
%_9.sroa.9.0.sroa_idx9.i.i = getelementptr inbounds [16 x i8], [16 x i8]* %_9.sroa.9.i.i, i64 0, i64 0, !dbg !38
call void @llvm.lifetime.start(i64 16, i8* nonnull %_9.sroa.9.0.sroa_idx9.i.i), !dbg !38
%0 = getelementptr inbounds %"core::mem::ManuallyDrop<alloc::allocator::AllocErr>", %"core::mem::ManuallyDrop<alloc::allocator::AllocErr>"* %err.i.i.i, i64 0, i32 0, i64 0, !dbg !48
call void @llvm.lifetime.start(i64 24, i8* nonnull %0) #6, !dbg !48, !noalias !52
%1 = call i8* @__rust_alloc(i64 4, i64 4, i8* nonnull %0) #6, !dbg !55, !noalias !52
%2 = icmp eq i8* %1, null, !dbg !57
br i1 %2, label %bb3.i.i.i, label %"_ZN35_$LT$alloc..boxed..Box$LT$T$GT$$GT$3new17he6f20be442f24a38E.exit", !dbg !61
[snip]
That seems wrong, why should the optimization stop kicking in? The corresponding C++ code does not have any problem:
#include <memory>
void test(void (*f)()) {
auto x = std::make_unique<int>(0);
auto y = std::make_unique<int>(0);
if (&*x == &*y) {
f();
}
}; Function Attrs: uwtable
define void @test(void (*)())(void ()* nocapture) local_unnamed_addr #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) !dbg !1204 {
tail call void @llvm.dbg.value(metadata void ()* %0, i64 0, metadata !1208, metadata !1211), !dbg !1212
tail call void @llvm.dbg.value(metadata %"class.std::unique_ptr"* undef, i64 0, metadata !1209, metadata !1213), !dbg !1214
tail call void @llvm.dbg.value(metadata %"class.std::unique_ptr"* undef, i64 0, metadata !1209, metadata !1213), !dbg !1214
tail call void @llvm.dbg.value(metadata %"class.std::unique_ptr"* undef, i64 0, metadata !1210, metadata !1213), !dbg !1215
tail call void @llvm.dbg.value(metadata %"class.std::unique_ptr"* undef, i64 0, metadata !1210, metadata !1213), !dbg !1215
tail call void @llvm.dbg.value(metadata %"class.std::unique_ptr"* undef, i64 0, metadata !1209, metadata !1213), !dbg !1214
ret void, !dbg !1216
}
(I briefly thought maybe unwinding is the problem, but C++ should have the same kind of unwinding here.)
Metadata
Metadata
Assignees
Labels
A-allocatorsArea: Custom and system allocatorsArea: Custom and system allocatorsC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.
Activity
RalfJung commentedon Dec 5, 2017
@eddyb suggested I try
-C panic=abort, and indeed, that makes all the difference. However, the optimization is sound even with unwinding panics, so it should happen either way.[-]Missing optimization around __rust_alloc and unknown functions[/-][+]Missing optimization around __rust_alloc and unknown functions if panic=unwind[/+]RalfJung commentedon Dec 10, 2017
Aha! I think I got it. In the IR for the Rust program, the unwinding branch calls
@_ZN4core3ptr13drop_in_place17h91409ca23b53ad07Ewith thenoinlineattribute. So LLVM does not look through this call at all, and (I guess) it considers the pointer passed to it escaped. The pointer equality folding only happens if the pointer does not get escaped, so LLVM can guarantee that all comparisons of this pointer are folded consistently.So, to fix this, we'd have to remove this
noinline-- at least forBox<T>whereTdoes not itself implementDrop.Inline Box drop glue
SimonSapin commentedon Apr 1, 2018
CC @nox, @rust-lang/wg-codegen
nox commentedon Apr 1, 2018
Could this be preventing other optimisations than pointer equality folding? Cc @rust-lang/compiler
nagisa commentedon Apr 1, 2018
@nox definitely. My guess is that alias analysis is being overly conservative here and is declaring pointers to be
MayAlias, rather thanNoAlias, which what they definitely are. This will defeat many optimisations that check for aliasing (pretty much everything).RalfJung commentedon Apr 2, 2018
However, pointer equality optimizations and aliasing information are (AFAIK) mostly unrelated -- in particular, optimizing equalities based on
noaliasis incorrect:steveklabnik commentedon Jan 20, 2020
Triage: this optimization still does not happen.
11 remaining items
Rollup merge of rust-lang#102099 - InnovativeInventor:re-cold-land, r…
Auto merge of rust-lang#102099 - InnovativeInventor:re-cold-land, r=n…
Auto merge of rust-lang#102099 - InnovativeInventor:re-cold-land, r=n…
Auto merge of #102099 - InnovativeInventor:re-cold-land, r=nikic