Issue 122560
Summary [clang] Worse code gen when default constructing with `()` than `{}`
Labels clang
Assignees
Reporter davidstone
    The following translation unit

```c++
long get();
void unused() noexcept;

struct s {
	~s() {
		if (m0 != 0) {
			unused();
		}
	}

	long m0 = 0;
	long m1 = 0;
};


s f() {
#if defined USE_BRACES
	auto x = s{};
#else
	auto x = s();
#endif
	x.m1 = get();
	return x;
}
```

Generates the following code when compiled with `-DUSE_BRACES -O3 -emit-llvm`:

```
%struct.s = type { i64, i64 }

define dso_local void @f()(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.s) align 8 initializes((0, 16)) %agg.result) local_unnamed_addr #0 personality ptr @__gxx_personality_v0 !dbg !21 {
entry:
    #dbg_value(ptr %agg.result, !24, !DIExpression(DW_OP_deref), !25)
  %m1 = getelementptr inbounds nuw i8, ptr %agg.result, i64 8, !dbg !26
  store i64 0, ptr %agg.result, align 8, !dbg !26
  %call = tail call noundef i64 @get()(), !dbg !27
  store i64 %call, ptr %m1, align 8, !dbg !28
  ret void, !dbg !34
}

declare !dbg !35 noundef i64 @get()() local_unnamed_addr #1

declare i32 @__gxx_personality_v0(...)

attributes #0 = { mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
```

but generates the following when compiled with `-O3 -emit-llvm`:

```
%struct.s = type { i64, i64 }

define dso_local void @f()(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.s) align 8 initializes((0, 16)) %agg.result) local_unnamed_addr #0 personality ptr @__gxx_personality_v0 !dbg !21 {
entry:
 #dbg_value(ptr %agg.result, !24, !DIExpression(DW_OP_deref), !25)
 #dbg_value(ptr %agg.result, !26, !DIExpression(), !31)
  tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %agg.result, i8 0, i64 16, i1 false), !dbg !33
  %call = tail call noundef i64 @get()(), !dbg !34
  %m1 = getelementptr inbounds nuw i8, ptr %agg.result, i64 8, !dbg !35
  store i64 %call, ptr %m1, align 8, !dbg !36
 ret void, !dbg !42
}

declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #1

declare !dbg !43 noundef i64 @get()() local_unnamed_addr #2

declare i32 @__gxx_personality_v0(...)

attributes #0 = { mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { mustprogress nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
```

These correspond to the assembly

`-DUSE_BRACES`:

```asm
f():
        push    rbx
        mov rbx, rdi
        mov     qword ptr [rdi], 0
        call    get()@PLT
 mov     qword ptr [rbx + 8], rax
        mov     rax, rbx
 pop     rbx
        ret
```

and without:

```asm
f():
        push rbx
        mov     rbx, rdi
        xorps   xmm0, xmm0
        movups xmmword ptr [rdi], xmm0
        call    get()@PLT
        mov     qword ptr [rbx + 8], rax
        mov     rax, rbx
        pop     rbx
 ret
```

See it live: https://godbolt.org/z/hfcPeTsfo
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to