1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Verify that calls to snprintf with members of constant structs as arguments
3; are folded to constants as expected.
4; RUN: opt < %s -passes=instcombine -S | FileCheck %s
5
6declare i32 @snprintf(i8*, i64, i8*, ...)
7
8%struct.A = type { [5 x i8], [6 x i8], [7 x i8] }
9
10@a = constant [2 x %struct.A] [%struct.A { [5 x i8] c"1\00\00\00\00", [6 x i8] c"12\00\00\00\00", [7 x i8] c"123\00\00\00\00" }, %struct.A { [5 x i8] c"1234\00", [6 x i8] c"12345\00", [7 x i8] c"123456\00" }]
11
12@pcnt_s = constant [3 x i8] c"%s\00"
13
14
15; Fold snprintf(0, 0, "%s", a[I].M + C) for constant I in [0, 1],
16; member M in [a, b, c], and C in a valid range to a constant.
17
18define void @fold_snprintf_member_pC(i32* %pi) {
19; CHECK-LABEL: @fold_snprintf_member_pC(
20; CHECK-NEXT:    [[IA0A:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0))
21; CHECK-NEXT:    store i32 [[IA0A]], i32* [[PI:%.*]], align 4
22; CHECK-NEXT:    [[IA0AP1:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 1))
23; CHECK-NEXT:    [[PIA0AP1:%.*]] = getelementptr i32, i32* [[PI]], i64 1
24; CHECK-NEXT:    store i32 [[IA0AP1]], i32* [[PIA0AP1]], align 4
25; CHECK-NEXT:    [[IA0B:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 0))
26; CHECK-NEXT:    [[PIA0B:%.*]] = getelementptr i32, i32* [[PI]], i64 2
27; CHECK-NEXT:    store i32 [[IA0B]], i32* [[PIA0B]], align 4
28; CHECK-NEXT:    [[IA0BP1:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1))
29; CHECK-NEXT:    [[PIA0BP1:%.*]] = getelementptr i32, i32* [[PI]], i64 3
30; CHECK-NEXT:    store i32 [[IA0BP1]], i32* [[PIA0BP1]], align 4
31; CHECK-NEXT:    [[IA0BP2:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 2))
32; CHECK-NEXT:    [[PIA0BP2:%.*]] = getelementptr i32, i32* [[PI]], i64 4
33; CHECK-NEXT:    store i32 [[IA0BP2]], i32* [[PIA0BP2]], align 4
34; CHECK-NEXT:    [[IA0C:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 0))
35; CHECK-NEXT:    [[PIA0C:%.*]] = getelementptr i32, i32* [[PI]], i64 5
36; CHECK-NEXT:    store i32 [[IA0C]], i32* [[PIA0C]], align 4
37; CHECK-NEXT:    [[IA1A:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 0))
38; CHECK-NEXT:    [[PIA1A:%.*]] = getelementptr i32, i32* [[PI]], i64 6
39; CHECK-NEXT:    store i32 [[IA1A]], i32* [[PIA1A]], align 4
40; CHECK-NEXT:    [[IA1B:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 0))
41; CHECK-NEXT:    [[PIA1B:%.*]] = getelementptr i32, i32* [[PI]], i64 7
42; CHECK-NEXT:    store i32 [[IA1B]], i32* [[PIA1B]], align 4
43; CHECK-NEXT:    [[IA1C:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 0))
44; CHECK-NEXT:    [[PIA1C:%.*]] = getelementptr i32, i32* [[PI]], i64 8
45; CHECK-NEXT:    store i32 [[IA1C]], i32* [[PIA1C]], align 4
46; CHECK-NEXT:    ret void
47;
48  %fmt = getelementptr [3 x i8], [3 x i8]* @pcnt_s, i32 0, i32 0
49; Fold snprintf(0, 0, "%s", a[0].a) to 1.
50  %pa0a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0
51  %ia0a = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0a)
52  %pia0a = getelementptr i32, i32* %pi, i32 0
53  store i32 %ia0a, i32* %pia0a
54
55; Fold snprintf(0, 0, "%s", a[0].a) to 0.
56  %pa0ap1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 1
57  %ia0ap1 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0ap1)
58  %pia0ap1 = getelementptr i32, i32* %pi, i32 1
59  store i32 %ia0ap1, i32* %pia0ap1
60
61; Fold snprintf(0, 0, "%s", a[0].b) to 2.
62  %pa0b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 0
63  %ia0b = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0b)
64  %pia0b = getelementptr i32, i32* %pi, i32 2
65  store i32 %ia0b, i32* %pia0b
66
67; Fold snprintf(0, 0, "%s", a[0].b + 1) to 1.
68  %pa0bp1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1
69  %ia0bp1 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0bp1)
70  %pia0bp1 = getelementptr i32, i32* %pi, i32 3
71  store i32 %ia0bp1, i32* %pia0bp1
72
73; Fold snprintf(0, 0, "%s", a[0].b + 2) to 0.
74  %pa0bp2 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 2
75  %ia0bp2 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0bp2)
76  %pia0bp2 = getelementptr i32, i32* %pi, i32 4
77  store i32 %ia0bp2, i32* %pia0bp2
78
79; Fold snprintf(0, 0, "%s", a[0].c) to 3.
80  %pa0c = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 0
81  %ia0c = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0c)
82  %pia0c = getelementptr i32, i32* %pi, i32 5
83  store i32 %ia0c, i32* %pia0c
84
85; Fold snprintf(0, 0, "%s", a[1].a) to 4.
86  %pa1a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 0
87  %ia1a = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa1a)
88  %pia1a = getelementptr i32, i32* %pi, i32 6
89  store i32 %ia1a, i32* %pia1a
90
91; Fold snprintf(0, 0, "%s", a[1].b) to 5.
92  %pa1b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 0
93  %ia1b = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa1b)
94  %pia1b = getelementptr i32, i32* %pi, i32 7
95  store i32 %ia1b, i32* %pia1b
96
97; Fold snprintf(0, 0, "%s", a[1].c) to 6.
98  %pa1c = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 0
99  %ia1c = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa1c)
100  %pia1c = getelementptr i32, i32* %pi, i32 8
101  store i32 %ia1c, i32* %pia1c
102
103  ret void
104}
105