Closed
Description
See e.g.
fn main() {
let x = Some("hello".to_owned());
x.map_or(0, |_| 1);
}
Which generates this initial IR:
; <core::option::Option<T>>::map_or
; Function Attrs: inlinehint uwtable
define internal i32 @"_ZN38_$LT$core..option..Option$LT$T$GT$$GT$6map_or17hf55f2f906b05703eE"(%"core::option::Option<alloc::string::String>"* noalias nocapture dereferenceable(24) %self, i32 %default) unnamed_addr #0 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
start:
%personalityslot = alloca { i8*, i32 }, align 8
%_12 = alloca i8, align 1
%_11 = alloca i8, align 1
%_10 = alloca i8, align 1
%_8 = alloca %"alloc::string::String", align 8
%_7 = alloca { [0 x i8], %"alloc::string::String", [0 x i8] }, align 8
%t = alloca %"alloc::string::String", align 8
%_0 = alloca i32, align 4
store i8 0, i8* %_12
store i8 0, i8* %_10
store i8 0, i8* %_11
store i8 1, i8* %_10
store i8 1, i8* %_11
store i8 1, i8* %_12
%0 = bitcast %"core::option::Option<alloc::string::String>"* %self to {}**
%1 = load {}*, {}** %0
%2 = icmp eq {}* %1, null
%3 = select i1 %2, i64 0, i64 1
switch i64 %3, label %bb3 [
i64 0, label %bb2
i64 1, label %bb4
]
bb1: ; preds = %bb11, %bb10, %bb12
%4 = bitcast { i8*, i32 }* %personalityslot to i8**
%5 = load i8*, i8** %4
%6 = getelementptr inbounds { i8*, i32 }, { i8*, i32 }* %personalityslot, i32 0, i32 1
%7 = load i32, i32* %6
%8 = insertvalue { i8*, i32 } undef, i8* %5, 0
%9 = insertvalue { i8*, i32 } %8, i32 %7, 1
resume { i8*, i32 } %9
bb2: ; preds = %start
store i8 0, i8* %_11
store i32 %default, i32* %_0
br label %bb5
bb3: ; preds = %start
unreachable
bb4: ; preds = %start
store i8 0, i8* %_10
%10 = bitcast %"core::option::Option<alloc::string::String>"* %self to %"core::option::Option<alloc::string::String>::Some"*
%11 = bitcast %"core::option::Option<alloc::string::String>::Some"* %10 to %"alloc::string::String"*
%12 = bitcast %"alloc::string::String"* %11 to i8*
%13 = bitcast %"alloc::string::String"* %t to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %13, i8* %12, i64 24, i32 8, i1 false)
store i8 0, i8* %_12
%14 = bitcast %"alloc::string::String"* %t to i8*
%15 = bitcast %"alloc::string::String"* %_8 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %15, i8* %14, i64 24, i32 8, i1 false)
%16 = bitcast { [0 x i8], %"alloc::string::String", [0 x i8] }* %_7 to %"alloc::string::String"*
%17 = bitcast %"alloc::string::String"* %_8 to i8*
%18 = bitcast %"alloc::string::String"* %16 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %18, i8* %17, i64 24, i32 8, i1 false)
%19 = bitcast { [0 x i8], %"alloc::string::String", [0 x i8] }* %_7 to %"alloc::string::String"*
; invoke map_example::main::{{closure}}
%20 = invoke i32 @"_ZN11map_example4main28_$u7b$$u7b$closure$u7d$$u7d$17h0799836f5ea6b921E"(%"alloc::string::String"* noalias nocapture dereferenceable(24) %19)
to label %bb7 unwind label %cleanup
bb5: ; preds = %bb2, %bb7
%21 = load i8, i8* %_12, !range !1
%22 = trunc i8 %21 to i1
br i1 %22, label %bb15, label %bb8
bb6: ; preds = %bb13, %bb14
%23 = bitcast %"core::option::Option<alloc::string::String>"* %self to {}**
%24 = load {}*, {}** %23
%25 = icmp eq {}* %24, null
%26 = select i1 %25, i64 0, i64 1
switch i64 %26, label %bb12 [
i64 1, label %bb10
]
bb7: ; preds = %bb4
store i32 %20, i32* %_0
br label %bb5
bb8: ; preds = %bb15, %bb5
%27 = load i8, i8* %_11, !range !1
%28 = trunc i8 %27 to i1
br i1 %28, label %bb16, label %bb9
bb9: ; preds = %bb16, %bb8
%29 = bitcast %"core::option::Option<alloc::string::String>"* %self to {}**
%30 = load {}*, {}** %29
%31 = icmp eq {}* %30, null
%32 = select i1 %31, i64 0, i64 1
switch i64 %32, label %bb20 [
i64 1, label %bb18
]
bb10: ; preds = %bb6
%33 = load i8, i8* %_10, !range !1
%34 = trunc i8 %33 to i1
br i1 %34, label %bb11, label %bb1
bb11: ; preds = %bb10
store i8 0, i8* %_10
%35 = bitcast %"core::option::Option<alloc::string::String>"* %self to %"core::option::Option<alloc::string::String>::Some"*
%36 = bitcast %"core::option::Option<alloc::string::String>::Some"* %35 to %"alloc::string::String"*
; call core::ptr::drop_in_place
call void @_ZN4core3ptr13drop_in_place17h5aaf0cb4e5af22beE(%"alloc::string::String"* %36) #8
br label %bb1
bb12: ; preds = %bb6
; call core::ptr::drop_in_place
call void @_ZN4core3ptr13drop_in_place17h85c4ff3726432e4eE(%"core::option::Option<alloc::string::String>"* %self) #8
br label %bb1
bb13: ; preds = %bb14
store i8 0, i8* %_11
br label %bb6
bb14: ; preds = %cleanup
%37 = load i8, i8* %_11, !range !1
%38 = trunc i8 %37 to i1
br i1 %38, label %bb13, label %bb6
bb15: ; preds = %bb5
store i8 0, i8* %_12
br label %bb8
bb16: ; preds = %bb8
store i8 0, i8* %_11
br label %bb9
bb17: ; preds = %bb19, %bb18, %bb20
%39 = load i32, i32* %_0
ret i32 %39
bb18: ; preds = %bb9
%40 = load i8, i8* %_10, !range !1
%41 = trunc i8 %40 to i1
br i1 %41, label %bb19, label %bb17
bb19: ; preds = %bb18
store i8 0, i8* %_10
%42 = bitcast %"core::option::Option<alloc::string::String>"* %self to %"core::option::Option<alloc::string::String>::Some"*
%43 = bitcast %"core::option::Option<alloc::string::String>::Some"* %42 to %"alloc::string::String"*
; call core::ptr::drop_in_place
call void @_ZN4core3ptr13drop_in_place17h5aaf0cb4e5af22beE(%"alloc::string::String"* %43)
br label %bb17
bb20: ; preds = %bb9
; call core::ptr::drop_in_place
call void @_ZN4core3ptr13drop_in_place17h85c4ff3726432e4eE(%"core::option::Option<alloc::string::String>"* %self)
br label %bb17
cleanup: ; preds = %bb4
%44 = landingpad { i8*, i32 }
cleanup
%45 = extractvalue { i8*, i32 } %44, 0
%46 = extractvalue { i8*, i32 } %44, 1
%47 = getelementptr inbounds { i8*, i32 }, { i8*, i32 }* %personalityslot, i32 0, i32 0
store i8* %45, i8** %47
%48 = getelementptr inbounds { i8*, i32 }, { i8*, i32 }* %personalityslot, i32 0, i32 1
store i32 %46, i32* %48
br label %bb14
Which is quite a bit of IR for such a little function:
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
match self {
Some(t) => f(t),
None => default,
}
}
I suspect #46525 might be involved in causing drop elaboration to go crazy
Metadata
Metadata
Assignees
Labels
Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlArea: Code generationCategory: An issue proposing an enhancement or a PR with one.Category: An issue highlighting optimization opportunities or PRs implementing suchIssue: Problems and improvements with respect to compile times.Relevant to the compiler team, which will review and decide on the PR/issue.