File: assign_struct_init_without_stack.d

package info (click to toggle)
ldc 1%3A1.30.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 59,248 kB
  • sloc: cpp: 61,598; ansic: 14,545; sh: 1,014; makefile: 972; asm: 510; objc: 135; exp: 48; python: 12
file content (126 lines) | stat: -rw-r--r-- 4,276 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// 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
}