Skip to content

Commit e3e51b6

Browse files
committed
CodeGen tests
1 parent 9cc06ce commit e3e51b6

File tree

3 files changed

+333
-0
lines changed

3 files changed

+333
-0
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -disable-llvm-passes -emit-llvm -finclude-default-header -o - %s | FileCheck %s
2+
3+
// array truncation
4+
// CHECK-LABEL: define void {{.*}}call1
5+
// CHECK: [[A:%.*]] = alloca [2 x i32], align 4
6+
// CHECK-NEXT: [[B:%.*]] = alloca [1 x i32], align 4
7+
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
8+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 {{.*}}, i32 8, i1 false)
9+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[B]], ptr align 4 {{.*}}, i32 4, i1 false)
10+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
11+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [1 x i32], ptr [[B]], i32 0
12+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds [2 x i32], ptr [[Tmp]], i32 0
13+
// CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds [2 x i32], ptr [[Tmp]], i32 1
14+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G2]], align 4
15+
// CHECK-NEXT: store i32 [[L]], ptr [[G1]], align 4
16+
export void call1() {
17+
int A[2] = {0,1};
18+
int B[1] = {4};
19+
B = (int[1])A;
20+
}
21+
22+
// just a cast
23+
// CHECK-LABEL: define void {{.*}}call2
24+
// CHECK: [[A:%.*]] = alloca [1 x i32], align 4
25+
// CHECK-NEXT: [[B:%.*]] = alloca [1 x float], align 4
26+
// CHECK-NEXT: [[Tmp:%.*]] = alloca [1 x i32], align 4
27+
// CHECK-NEXT: call void @llvm.memset.p0.i32(ptr align 4 [[A]], i8 0, i32 4, i1 false)
28+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[B]], ptr align 4 {{.*}}, i32 4, i1 false)
29+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 4, i1 false)
30+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [1 x float], ptr [[B]], i32 0
31+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds [1 x i32], ptr [[Tmp]], i32 0
32+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G2]], align 4
33+
// CHECK-NEXT: [[C:%.*]] = sitofp i32 [[L]] to float
34+
// CHECK-NEXT: store float [[C]], ptr [[G1]], align 4
35+
export void call2() {
36+
int A[1] = {0};
37+
float B[1] = {1.0};
38+
B = (float[1])A;
39+
}
40+
41+
// vector to array
42+
// CHECK-LABEL: define void {{.*}}call3
43+
// CHECK: [[A:%.*]] = alloca <1 x float>, align 4
44+
// CHECK-NEXT: [[B:%.*]] = alloca [1 x i32], align 4
45+
// CHECK-NEXT: store <1 x float> splat (float 0x3FF3333340000000), ptr [[A]], align 4
46+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[B]], ptr align 4 {{.*}}, i32 4, i1 false)
47+
// CHECK-NEXT: [[C:%.*]] = load <1 x float>, ptr [[A]], align 4
48+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [1 x i32], ptr [[B]], i32 0
49+
// CHECK-NEXT: [[V:%.*]] = extractelement <1 x float> [[C]], i64 0
50+
// CHECK-NEXT: [[C:%.*]] = fptosi float [[V]] to i32
51+
// CHECK-NEXT: store i32 [[C]], ptr [[G1]], align 4
52+
export void call3() {
53+
float1 A = {1.2};
54+
int B[1] = {1};
55+
B = (int[1])A;
56+
}
57+
58+
// flatten array of vector to array with cast
59+
// CHECK-LABEL: define void {{.*}}call5
60+
// CHECK: [[A:%.*]] = alloca [1 x <2 x float>], align 8
61+
// CHECK-NEXT: [[B:%.*]] = alloca [2 x i32], align 4
62+
// CHECK-NEXT: [[Tmp:%.*]] = alloca [1 x <2 x float>], align 8
63+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[A]], ptr align 8 {{.*}}, i32 8, i1 false)
64+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[B]], ptr align 4 {{.*}}, i32 8, i1 false)
65+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[Tmp]], ptr align 8 [[A]], i32 8, i1 false)
66+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [2 x i32], ptr [[B]], i32 0
67+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds [2 x i32], ptr [[B]], i32 1
68+
// CHECK-NEXT: [[VG:%.*]] = getelementptr inbounds [1 x <2 x float>], ptr [[Tmp]], i32 0
69+
// CHECK-NEXT: [[L:%.*]] = load <2 x float>, ptr [[VG]], align 8
70+
// CHECK-NEXT: [[VL:%.*]] = extractelement <2 x float> [[L]], i32 0
71+
// CHECK-NEXT: [[C:%.*]] = fptosi float [[VL]] to i32
72+
// CHECK-NEXT: store i32 [[C]], ptr [[G1]], align 4
73+
// CHECK-NEXT: [[L4:%.*]] = load <2 x float>, ptr [[VG]], align 8
74+
// CHECK-NEXT: [[VL5:%.*]] = extractelement <2 x float> [[L4]], i32 1
75+
// CHECK-NEXT: [[C6:%.*]] = fptosi float [[VL5]] to i32
76+
// CHECK-NEXT: store i32 [[C6]], ptr [[G2]], align 4
77+
export void call5() {
78+
float2 A[1] = {{1.2,3.4}};
79+
int B[2] = {1,2};
80+
B = (int[2])A;
81+
}
82+
83+
// flatten 2d array
84+
// CHECK-LABEL: define void {{.*}}call6
85+
// CHECK: [[A:%.*]] = alloca [2 x [1 x i32]], align 4
86+
// CHECK-NEXT: [[B:%.*]] = alloca [2 x i32], align 4
87+
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x [1 x i32]], align 4
88+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 {{.*}}, i32 8, i1 false)
89+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[B]], ptr align 4 {{.*}}, i32 8, i1 false)
90+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
91+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [2 x i32], ptr [[B]], i32 0
92+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds [2 x i32], ptr [[B]], i32 1
93+
// CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds [2 x [1 x i32]], ptr [[Tmp]], i32 0, i32 0
94+
// CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds [2 x [1 x i32]], ptr [[Tmp]], i32 1, i32 0
95+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G3]], align 4
96+
// CHECK-NEXT: store i32 [[L]], ptr [[G1]], align 4
97+
// CHECK-NEXT: [[L4:%.*]] = load i32, ptr [[G4]], align 4
98+
// CHECK-NEXT: store i32 [[L4]], ptr [[G2]], align 4
99+
export void call6() {
100+
int A[2][1] = {{1},{3}};
101+
int B[2] = {1,2};
102+
B = (int[2])A;
103+
}
104+
105+
struct S {
106+
int X;
107+
float Y;
108+
};
109+
110+
// flatten and truncate from a struct
111+
// CHECK-LABEL: define void {{.*}}call7
112+
// CHECK: [[s:%.*]] = alloca %struct.S, align 4
113+
// CHECK-NEXT: [[A:%.*]] = alloca [1 x i32], align 4
114+
// CHECK-NEXT: [[Tmp:%.*]] = alloca %struct.S, align 4
115+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[s]], ptr align 4 {{.*}}, i32 8, i1 false)
116+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 {{.*}}, i32 4, i1 false)
117+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[s]], i32 8, i1 false)
118+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [1 x i32], ptr [[A]], i32 0
119+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds %struct.S, ptr [[Tmp]], i32 0
120+
// CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds %struct.S, ptr [[Tmp]], i32 1
121+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G2]], align 4
122+
// CHECK-NEXT: store i32 [[L]], ptr [[G1]], align 4
123+
export void call7() {
124+
S s = {1, 2.9};
125+
int A[1] = {1};
126+
A = (int[1])s;
127+
}
128+
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
2+
3+
struct S {
4+
int X;
5+
float Y;
6+
};
7+
8+
// struct from vector
9+
// CHECK-LABEL: define void {{.*}}call1
10+
// CHECK: [[A:%.*]] = alloca <2 x i32>, align 8
11+
// CHECK-NEXT: [[s:%.*]] = alloca %struct.S, align 4
12+
// CHECK-NEXT: store <2 x i32> <i32 1, i32 2>, ptr [[A]], align 8
13+
// CHECK-NEXT: [[L:%.*]] = load <2 x i32>, ptr [[A]], align 8
14+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds %struct.S, ptr [[s]], i32 0
15+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds %struct.S, ptr [[s]], i32 1
16+
// CHECK-NEXT: [[VL:%.*]] = extractelement <2 x i32> [[L]], i64 0
17+
// CHECK-NEXT: store i32 [[VL]], ptr [[G1]], align 4
18+
// CHECK-NEXT: [[VL2:%.*]] = extractelement <2 x i32> [[L]], i64 1
19+
// CHECK-NEXT: [[C:%.*]] = sitofp i32 [[VL2]] to float
20+
// CHECK-NEXT: store float [[C]], ptr [[G2]], align 4
21+
export void call1() {
22+
int2 A = {1,2};
23+
S s = (S)A;
24+
}
25+
26+
27+
// struct from array
28+
// CHECK-LABEL: define void {{.*}}call2
29+
// CHECK: [[A:%.*]] = alloca [2 x i32], align 4
30+
// CHECK-NEXT: [[s:%.*]] = alloca %struct.S, align 4
31+
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
32+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 {{.*}}, i32 8, i1 false)
33+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
34+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds %struct.S, ptr [[s]], i32 0
35+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds %struct.S, ptr [[s]], i32 1
36+
// CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds [2 x i32], ptr [[Tmp]], i32 0
37+
// CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds [2 x i32], ptr [[Tmp]], i32 1
38+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G3]], align 4
39+
// CHECK-NEXT: store i32 [[L]], ptr [[G1]], align 4
40+
// CHECK-NEXT: [[L4:%.*]] = load i32, ptr [[G4]], align 4
41+
// CHECK-NEXT: [[C:%.*]] = sitofp i32 [[L4]] to float
42+
// CHECK-NEXT: store float [[C]], ptr [[G2]], align 4
43+
export void call2() {
44+
int A[2] = {1,2};
45+
S s = (S)A;
46+
}
47+
48+
struct Q {
49+
int Z;
50+
};
51+
52+
struct R {
53+
Q q;
54+
float F;
55+
};
56+
57+
// struct from nested struct?
58+
// CHECK-LABEL: define void {{.*}}call6
59+
// CHECK: [[r:%.*]] = alloca %struct.R, align 4
60+
// CHECK-NEXT: [[s:%.*]] = alloca %struct.S, align 4
61+
// CHECK-NEXT: [[Tmp:%.*]] = alloca %struct.R, align 4
62+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[r]], ptr align 4 {{.*}}, i32 8, i1 false)
63+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[r]], i32 8, i1 false)
64+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds %struct.S, ptr [[s]], i32 0
65+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds %struct.S, ptr [[s]], i32 1
66+
// CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds %struct.R, ptr [[Tmp]], i32 0, i32 0
67+
// CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds %struct.R, ptr [[Tmp]], i32 1
68+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G3]], align 4
69+
// CHECK-NEXT: store i32 [[L]], ptr [[G1]], align 4
70+
// CHECK-NEXT: [[L4:%.*]] = load float, ptr [[G4]], align 4
71+
// CHECK-NEXT: store float [[L4]], ptr [[G2]], align 4
72+
export void call6() {
73+
R r = {{1}, 2.0};
74+
S s = (S)r;
75+
}
76+
77+
// nested struct from array?
78+
// CHECK-LABEL: define void {{.*}}call7
79+
// CHECK: [[A:%.*]] = alloca [2 x i32], align 4
80+
// CHECK-NEXT: [[r:%.*]] = alloca %struct.R, align 4
81+
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
82+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 {{.*}}, i32 8, i1 false)
83+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
84+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds %struct.R, ptr [[r]], i32 0, i32 0
85+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds %struct.R, ptr [[r]], i32 1
86+
// CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds [2 x i32], ptr [[Tmp]], i32 0
87+
// CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds [2 x i32], ptr [[Tmp]], i32 1
88+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G3]], align 4
89+
// CHECK-NEXT: store i32 [[L]], ptr [[G1]], align 4
90+
// CHECK-NEXT: [[L4:%.*]] = load i32, ptr [[G4]], align 4
91+
// CHECK-NEXT: [[C:%.*]] = sitofp i32 [[L4]] to float
92+
// CHECK-NEXT: store float [[C]], ptr [[G2]], align 4
93+
export void call7() {
94+
int A[2] = {1,2};
95+
R r = (R)A;
96+
}
97+
98+
struct T {
99+
int A;
100+
int B;
101+
int C;
102+
};
103+
104+
// struct truncation
105+
// CHECK-LABEL: define void {{.*}}call8
106+
// CHECK: [[t:%.*]] = alloca %struct.T, align 4
107+
// CHECK-NEXT: [[s:%.*]] = alloca %struct.S, align 4
108+
// CHECK-NEXT: [[Tmp:%.*]] = alloca %struct.T, align 4
109+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[t]], ptr align 4 {{.*}}, i32 12, i1 false)
110+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[t]], i32 12, i1 false)
111+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds %struct.S, ptr [[s]], i32 0
112+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds %struct.S, ptr [[s]], i32 1
113+
// CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds %struct.T, ptr [[Tmp]], i32 0
114+
// CHECK-NEXT: %gep3 = getelementptr inbounds %struct.T, ptr %agg-temp, i32 1
115+
// CHECK-NEXT: %gep4 = getelementptr inbounds %struct.T, ptr %agg-temp, i32 2
116+
// CHECK-NEXT: %load = load i32, ptr %gep2, align 4
117+
// CHECK-NEXT: store i32 %load, ptr %gep, align 4
118+
// CHECK-NEXT: %load5 = load i32, ptr %gep3, align 4
119+
// CHECK-NEXT: %conv = sitofp i32 %load5 to float
120+
// CHECK-NEXT: store float %conv, ptr %gep1, align 4
121+
export void call8() {
122+
T t = {1,2,3};
123+
S s = (S)t;
124+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
2+
3+
// vector flat cast from array
4+
// CHECK-LABEL: define void {{.*}}call2
5+
// CHECK: [[A:%.*]] = alloca [2 x [1 x i32]], align 4
6+
// CHECK-NEXT: [[B:%.*]] = alloca <2 x i32>, align 8
7+
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x [1 x i32]], align 4
8+
// CHECK-NEXT: [[Tmp2:%.*]] = alloca <2 x i32>, align 8
9+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 {{.*}}, i32 8, i1 false)
10+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
11+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [2 x [1 x i32]], ptr [[Tmp]], i32 0, i32 0
12+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds [2 x [1 x i32]], ptr [[Tmp]], i32 1, i32 0
13+
// CHECK-NEXT: [[C:%.*]] = load <2 x i32>, ptr [[Tmp2]], align 8
14+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G1]], align 4
15+
// CHECK-NEXT: [[D:%.*]] = insertelement <2 x i32> [[C]], i32 [[L]], i64 0
16+
// CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[G2]], align 4
17+
// CHECK-NEXT: [[E:%.*]] = insertelement <2 x i32> [[D]], i32 [[L2]], i64 1
18+
// CHECK-NEXT: store <2 x i32> [[E]], ptr [[B]], align 8
19+
export void call2() {
20+
int A[2][1] = {{1},{2}};
21+
int2 B = (int2)A;
22+
}
23+
24+
struct S {
25+
int X;
26+
float Y;
27+
};
28+
29+
// vector flat cast from struct
30+
// CHECK-LABEL: define void {{.*}}call3
31+
// CHECK: [[s:%.*]] = alloca %struct.S, align 4
32+
// CHECK-NEXT: [[A:%.*]] = alloca <2 x i32>, align 8
33+
// CHECK-NEXT: [[Tmp:%.*]] = alloca %struct.S, align 4
34+
// CHECK-NEXT: [[Tmp2:%.*]] = alloca <2 x i32>, align 8
35+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[s]], ptr align 4 {{.*}}, i32 8, i1 false)
36+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[s]], i32 8, i1 false)
37+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds %struct.S, ptr [[Tmp]], i32 0
38+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds %struct.S, ptr [[Tmp]], i32 1
39+
// CHECK-NEXT: [[B:%.*]] = load <2 x i32>, ptr [[Tmp2]], align 8
40+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G1]], align 4
41+
// CHECK-NEXT: [[C:%.*]] = insertelement <2 x i32> [[B]], i32 [[L]], i64 0
42+
// CHECK-NEXT: [[L2:%.*]] = load float, ptr [[G2]], align 4
43+
// CHECK-NEXT: [[D:%.*]] = fptosi float [[L2]] to i32
44+
// CHECK-NEXT: [[E:%.*]] = insertelement <2 x i32> [[C]], i32 [[D]], i64 1
45+
// CHECK-NEXT: store <2 x i32> [[E]], ptr [[A]], align 8
46+
export void call3() {
47+
S s = {1, 2.0};
48+
int2 A = (int2)s;
49+
}
50+
51+
// truncate array to scalar
52+
// CHECK-LABEL: define void {{.*}}call4
53+
// CHECK: [[A:%.*]] = alloca [2 x i32], align 4
54+
// CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
55+
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
56+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 {{.*}}, i32 8, i1 false)
57+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
58+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [2 x i32], ptr [[Tmp]], i32 0
59+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds [2 x i32], ptr [[Tmp]], i32 1
60+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G1]], align 4
61+
// CHECK-NEXT: store i32 [[L]], ptr [[B]], align 4
62+
export void call4() {
63+
int A[2] = {1,2};
64+
int B = (int)A;
65+
}
66+
67+
// truncate struct to scalar
68+
// CHECK-LABEL: define void {{.*}}call5
69+
// CHECK: [[s:%.*]] = alloca %struct.S, align 4
70+
// CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
71+
// CHECK-NEXT: [[Tmp:%.*]] = alloca %struct.S, align 4
72+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[s]], ptr align 4 {{.*}}, i32 8, i1 false)
73+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[s]], i32 8, i1 false)
74+
// CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds %struct.S, ptr [[Tmp]], i32 0
75+
// CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds %struct.S, ptr [[Tmp]], i32 1
76+
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[G1]], align 4
77+
// CHECK-NEXT: store i32 [[L]], ptr [[A]], align 4
78+
export void call5() {
79+
S s = {1, 2.0};
80+
int A = (int)s;
81+
}

0 commit comments

Comments
 (0)