Skip to content

Conversation

mikdusan
Copy link
Member

reduction

const State = union(enum) {
    one: void,
    two: u32,
};

fn make1() State {
    return State{ .one = {} }; // regression: copy-elision-3
}

fn make2() State {
    return State{ .two = 99 };
}

export fn foobar() void {
    _ = make1(); 
    _ = make2();
}

const builtin = @import("builtin");
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
    while (true) {}
}

broken IR (branch: copy-elision-3)

fn make1() { // (analyzed)
Entry_0:
    #8  | *State      | 3 | @ReturnPtr
    #9  | *void       | 0 | @UnionFieldPtr(&#8.one)
    #14 | State       | 0 | loadptr(#8)result=(null)
    #16 | State       | 0 | loadptr(#8)result=(null)
    #20 | noreturn    | - | return 
}

fn make2() { // (analyzed)
Entry_0:
    #8  | *State      | 3 | @ReturnPtr
    #9  | *u32        | 1 | @UnionFieldPtr(&#8.two)
    #13 | void        | - | *#9 = 99
    #15 | State       | 0 | loadptr(#8)result=(null)
    #17 | State       | 0 | loadptr(#8)result=(null)
    #21 | noreturn    | - | return 
}

broken LLVM-IR (branch: copy-elision-3)

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make1(%State* nonnull sret) unnamed_addr #2 !dbg !48 {
Entry:
  ret void, !dbg !60
}

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make2(%State* nonnull sret) unnamed_addr #2 !dbg !62 {
Entry:
  %1 = getelementptr inbounds %State, %State* %0, i32 0, i32 1, !dbg !63
  store i1 true, i1* %1, !dbg !63
  %2 = getelementptr inbounds %State, %State* %0, i32 0, i32 0, !dbg !63
  store i32 99, i32* %2, align 4, !dbg !63
  ret void, !dbg !65
}

patched IR

fn make1() { // (analyzed)
Entry_0:
    #8  | *State      | 3 | @ReturnPtr
    #9  | *void       | 1 | @UnionFieldPtr(&#8.one)
    #12 | void        | - | *#9 = {}
    #14 | State       | 0 | loadptr(#8)result=(null)
    #16 | State       | 0 | loadptr(#8)result=(null)
    #20 | noreturn    | - | return 
}

fn make2() { // (analyzed)
Entry_0:
    #8  | *State      | 3 | @ReturnPtr
    #9  | *u32        | 1 | @UnionFieldPtr(&#8.two)
    #13 | void        | - | *#9 = 99
    #15 | State       | 0 | loadptr(#8)result=(null)
    #17 | State       | 0 | loadptr(#8)result=(null)
    #21 | noreturn    | - | return 
}

patched LLVM-IR

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make1(%State* nonnull sret) unnamed_addr #2 !dbg !48 {
Entry:
  %1 = getelementptr inbounds %State, %State* %0, i32 0, i32 1, !dbg !60
  store i1 false, i1* %1, !dbg !60
  ret void, !dbg !62
}

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make2(%State* nonnull sret) unnamed_addr #2 !dbg !63 {
Entry:
  %1 = getelementptr inbounds %State, %State* %0, i32 0, i32 1, !dbg !64
  store i1 true, i1* %1, !dbg !64
  %2 = getelementptr inbounds %State, %State* %0, i32 0, i32 0, !dbg !64
  store i32 99, i32* %2, align 4, !dbg !64
  ret void, !dbg !66
}

reference IR (branch: master)

fn make1() { // (analyzed)
Entry_0:
    #8  | noreturn    | - | return State { .one = {}}
}

fn make2() { // (analyzed)
Entry_0:
    #9  | noreturn    | - | return State { .two = 99}
}

reference LLVM-IR (branch: master)

@0 = internal unnamed_addr constant %State { i32 undef, i1 false }, align 4
@1 = internal unnamed_addr constant %State { i32 99, i1 true }, align 4

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make1(%State* nonnull sret) unnamed_addr #2 !dbg !48 {
Entry:
  %1 = bitcast %State* %0 to i8*, !dbg !60
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%State* @0 to i8*), i64 8, i1 false), !dbg !60
  ret void, !dbg !60
}

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make2(%State* nonnull sret) unnamed_addr #2 !dbg !62 {
Entry:
  %1 = bitcast %State* %0 to i8*, !dbg !63
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%State* @1 to i8*), i64 8, i1 false), !dbg !63
  ret void, !dbg !63
}

@mikdusan
Copy link
Member Author

closing issue: better fix committed c61e0a0

@mikdusan mikdusan closed this Jun 25, 2019
@andrewrk
Copy link
Member

Ah, sorry, I actually hadn't seen this yet when I coded my solution.

@mikdusan mikdusan deleted the result-location-union-init-void branch November 28, 2019 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants