ldc/tests/codegen/assign_struct_init_without_stack.d
Martin Kinkelin b78ac2bb60 Fixup lit-test codegen/assign_struct_init_without_stack.d
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.
2019-05-24 18:56:13 +02:00

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
}