mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-04 00:55:49 +03:00

An *inferred* `return` function attribute doesn't affect the mangled name anymore with 2.086 (dlang/dmd#9508). I haven't checked why it has been working before and only fails since advancing to DMD stable.
126 lines
4.2 KiB
D
126 lines
4.2 KiB
D
// Tests minimal use of temporaries in non-optimized builds for struct and array assignment.
|
|
// Tests `.init` assignment in particular.
|
|
|
|
// RUN: %ldc -output-ll %s -of=%t.ll && FileCheck %s < %t.ll
|
|
|
|
void opaque();
|
|
FloatStruct opaque(FloatStruct);
|
|
FloatStruct opaqueret();
|
|
|
|
struct FloatStruct {
|
|
float[10] data;
|
|
}
|
|
|
|
FloatStruct globalStruct;
|
|
|
|
// CHECK-LABEL: define{{.*}} @{{.*}}_D32assign_struct_init_without_stack3fooFZv
|
|
void foo() {
|
|
globalStruct = FloatStruct.init;
|
|
// There should be only one memcpy.
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK-NEXT: ret void
|
|
}
|
|
|
|
// CHECK-LABEL: define{{.*}} @{{.*}}_D32assign_struct_init_without_stack3hhhFZv
|
|
void hhh() {
|
|
globalStruct = FloatStruct([1, 0, 0, 0, 0, 0, 0, 0, 0, 42]);
|
|
// Future work: test optimized codegen (at -O0)
|
|
}
|
|
|
|
// CHECK-LABEL: define{{.*}} @{{.*}}_D32assign_struct_init_without_stack3gggFZv
|
|
void ggg() {
|
|
globalStruct = opaqueret();
|
|
// opaque() could be accessing globalStruct, in-place assignment not possible.
|
|
// CHECK: sret_tmp = alloca %assign_struct_init_without_stack.FloatStruct
|
|
// CHECK: call {{.*}}opaqueret
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK-NEXT: ret void
|
|
}
|
|
|
|
// CHECK-LABEL: define{{.*}} @{{.*}}_D32assign_struct_init_without_stack5localFZv
|
|
void local() {
|
|
FloatStruct local;
|
|
local = opaque(local);
|
|
// Not possible to do in-place assignment, so temporary must be created.
|
|
// CHECK: local = alloca %assign_struct_init_without_stack.FloatStruct
|
|
// CHECK: sret_tmp = alloca %assign_struct_init_without_stack.FloatStruct
|
|
// CHECK: call {{.*}}opaque
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK-NEXT: ret void
|
|
}
|
|
|
|
// CHECK-LABEL: define{{.*}} @{{.*}}_D32assign_struct_init_without_stack5arrayFZv
|
|
void array() {
|
|
int[5] arr = [0,1,2,3,4];
|
|
// Future work: test optimized codegen (at -O0)
|
|
}
|
|
|
|
// CHECK-LABEL: define{{.*}} @{{.*}}_D32assign_struct_init_without_stack6array2FKG3iZv
|
|
void array2(ref int[3] a) {
|
|
a = [4, a[0], 6];
|
|
// There should be a temporary!
|
|
// CHECK: alloca [3 x i32]
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK-NEXT: ret void
|
|
}
|
|
|
|
struct OpAssignStruct {
|
|
float[10] data;
|
|
ubyte a;
|
|
|
|
ref OpAssignStruct opAssign(R)(auto ref R rhs) return {
|
|
return this;
|
|
}
|
|
}
|
|
OpAssignStruct globalOpAssignStruct;
|
|
OpAssignStruct globalOpAssignStruct2;
|
|
|
|
// CHECK-LABEL: define{{.*}} @{{.*}}_D32assign_struct_init_without_stack16tupleassignByValFZv
|
|
void tupleassignByVal()
|
|
{
|
|
globalOpAssignStruct = OpAssignStruct.init;
|
|
// There should be one memcpy to a temporary.
|
|
// CHECK: alloca %assign_struct_init_without_stack.OpAssignStruct
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK-NOT: memcpy
|
|
// CHECK: call{{.*}} %assign_struct_init_without_stack.OpAssignStruct* @{{.*}}_D32assign_struct_init_without_stack14OpAssignStruct__T8opAssignTSQCmQBhZQsMFNaNbNcNiNjNfQyZQBb
|
|
// CHECK-NEXT: ret void
|
|
}
|
|
|
|
// CHECK-LABEL: define{{.*}} @{{.*}}_D32assign_struct_init_without_stack16tupleassignByRefFZv
|
|
void tupleassignByRef()
|
|
{
|
|
globalOpAssignStruct = globalOpAssignStruct2;
|
|
// There should not be a memcpy.
|
|
// CHECK-NOT: memcpy
|
|
// CHECK: call{{.*}} %assign_struct_init_without_stack.OpAssignStruct* @{{.*}}_D32assign_struct_init_without_stack14OpAssignStruct__T8opAssignTSQCmQBhZQsMFNaNbNcNiNjNfKQzZQBc
|
|
// CHECK-NEXT: ret void
|
|
}
|
|
|
|
struct DtorStruct {
|
|
float[10] data;
|
|
~this() { opaque(); }
|
|
}
|
|
struct CtorStruct {
|
|
float[10] data;
|
|
this(int i) { opaque(); }
|
|
}
|
|
DtorStruct dtorStruct;
|
|
CtorStruct ctorStruct;
|
|
|
|
// CHECK-LABEL: define{{.*}} @{{.*}}_D32assign_struct_init_without_stack4ctorFZv
|
|
void ctor() {
|
|
ctorStruct = ctorStruct.init;
|
|
// There is no dtor, so can be optimized to only a memcpy.
|
|
// CHECK-NEXT: call void @llvm.memcpy
|
|
// CHECK-NEXT: ret void
|
|
}
|
|
// CHECK-LABEL: define{{.*}} @{{.*}}_D32assign_struct_init_without_stack4dtorFZv
|
|
void dtor() {
|
|
dtorStruct = dtorStruct.init;
|
|
// There should be a temporary and a call to opAssign
|
|
// CHECK: alloca %assign_struct_init_without_stack.DtorStruct
|
|
// CHECK: call void @llvm.memcpy{{.*}}_D32assign_struct_init_without_stack10DtorStruct6__initZ
|
|
// CHECK-NEXT: call {{.*}}_D32assign_struct_init_without_stack10DtorStruct8opAssignMFNcNjSQCkQBfZQi
|
|
// CHECK-NEXT: ret void
|
|
}
|