Skip to content

Missing optimization around __rust_alloc and unknown functions if panic=unwind #46515

Description

@RalfJung

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;
}

becomes

; 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();
    }
}

becomes

; 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();
    }
}

becomes

; 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.)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-allocatorsArea: Custom and system allocatorsC-enhancementCategory: An issue proposing an enhancement or a PR with one.I-slowIssue: Problems and improvements with respect to performance of generated code.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions