1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Verify that strncmp calls with members of constant structs are folded.
3;
4; RUN: opt < %s -passes=instcombine -S | FileCheck %s
5
6; struct A { char a[3], b[4], c[4]; };
7%struct.A = type { [3 x i8], [4 x i8], [4 x i8] }
8
9@a = constant %struct.A { [3 x i8] c"123", [4 x i8] c"1231", [4 x i8] c"2345" }
10
11declare i32 @strncmp(i8*, i8*, i64)
12
13define void @fold_strncmp_Aa_b(i32* %pcmp) {
14; CHECK-LABEL: @fold_strncmp_Aa_b(
15; CHECK-NEXT:    store i32 0, i32* [[PCMP:%.*]], align 4
16; CHECK-NEXT:    [[PCMP1:%.*]] = getelementptr i32, i32* [[PCMP]], i64 1
17; CHECK-NEXT:    store i32 0, i32* [[PCMP1]], align 4
18; CHECK-NEXT:    [[CMP2:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A:%.*]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 2)
19; CHECK-NEXT:    [[PCMP2:%.*]] = getelementptr i32, i32* [[PCMP]], i64 2
20; CHECK-NEXT:    store i32 [[CMP2]], i32* [[PCMP2]], align 4
21; CHECK-NEXT:    [[CMP3:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 3)
22; CHECK-NEXT:    [[PCMP3:%.*]] = getelementptr i32, i32* [[PCMP]], i64 3
23; CHECK-NEXT:    store i32 [[CMP3]], i32* [[PCMP3]], align 4
24; CHECK-NEXT:    [[CMP4:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 4)
25; CHECK-NEXT:    [[PCMP4:%.*]] = getelementptr i32, i32* [[PCMP]], i64 4
26; CHECK-NEXT:    store i32 [[CMP4]], i32* [[PCMP4]], align 4
27; CHECK-NEXT:    [[CMP5:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 5)
28; CHECK-NEXT:    [[PCMP5:%.*]] = getelementptr i32, i32* [[PCMP]], i64 5
29; CHECK-NEXT:    store i32 [[CMP5]], i32* [[PCMP5]], align 4
30; CHECK-NEXT:    [[CMP6:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 6)
31; CHECK-NEXT:    [[PCMP6:%.*]] = getelementptr i32, i32* [[PCMP]], i64 6
32; CHECK-NEXT:    store i32 [[CMP6]], i32* [[PCMP6]], align 4
33; CHECK-NEXT:    [[CMP7:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 7)
34; CHECK-NEXT:    [[PCMP7:%.*]] = getelementptr i32, i32* [[PCMP]], i64 7
35; CHECK-NEXT:    store i32 [[CMP7]], i32* [[PCMP7]], align 4
36; CHECK-NEXT:    [[CMP8:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 8)
37; CHECK-NEXT:    [[PCMP8:%.*]] = getelementptr i32, i32* [[PCMP]], i64 8
38; CHECK-NEXT:    store i32 [[CMP8]], i32* [[PCMP8]], align 4
39; CHECK-NEXT:    [[CMP9:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 9)
40; CHECK-NEXT:    [[PCMP9:%.*]] = getelementptr i32, i32* [[PCMP]], i64 9
41; CHECK-NEXT:    store i32 [[CMP9]], i32* [[PCMP9]], align 4
42; CHECK-NEXT:    ret void
43;
44; p1 = a.a
45  %p1 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 0, i32 0
46; p2 = a.b
47  %p2 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 1, i32 0
48
49; Fold strncmp(a.a = "123", a.b = "1231", 0) to 0.
50  %cmp0 = call i32 @strncmp(i8* %p1, i8* %p2, i64 0)
51  %pcmp0 = getelementptr i32, i32* %pcmp, i64 0
52  store i32 %cmp0, i32* %pcmp0
53
54; Fold strncmp(a.a = "123", a.b = "1231", 1) to 0.
55  %cmp1 = call i32 @strncmp(i8* %p1, i8* %p2, i64 1)
56  %pcmp1 = getelementptr i32, i32* %pcmp, i64 1
57  store i32 %cmp1, i32* %pcmp1
58
59; Fold strncmp(a.a = "123", a.b = "1231", 2) to 0.
60  %cmp2 = call i32 @strncmp(i8* %p1, i8* %p2, i64 2)
61  %pcmp2 = getelementptr i32, i32* %pcmp, i64 2
62  store i32 %cmp2, i32* %pcmp2
63
64; Fold strncmp(a.a = "123", a.b = "1231", 3) to 0.
65  %cmp3 = call i32 @strncmp(i8* %p1, i8* %p2, i64 3)
66  %pcmp3 = getelementptr i32, i32* %pcmp, i64 3
67  store i32 %cmp3, i32* %pcmp3
68
69; Fold strncmp(a.a = "123", a.b = "1231", 4) to 0.
70; In this and the subsequent tests, reading past the end of a.a is
71; strictly undefined in C/C++ (because it forms a pointer to a distinct
72; subobject) but handling such cases as if they were well-defined is
73; simpler than trying to exclude them.
74
75  %cmp4 = call i32 @strncmp(i8* %p1, i8* %p2, i64 4)
76  %pcmp4 = getelementptr i32, i32* %pcmp, i64 4
77  store i32 %cmp4, i32* %pcmp4
78
79; Fold strncmp("123", "1231" "2", 5) to 0.
80  %cmp5 = call i32 @strncmp(i8* %p1, i8* %p2, i64 5)
81  %pcmp5 = getelementptr i32, i32* %pcmp, i64 5
82  store i32 %cmp5, i32* %pcmp5
83
84; Fold strncmp("123", "1231" "23", 6) to 0.
85  %cmp6 = call i32 @strncmp(i8* %p1, i8* %p2, i64 6)
86  %pcmp6 = getelementptr i32, i32* %pcmp, i64 6
87  store i32 %cmp6, i32* %pcmp6
88
89; Fold strncmp("123", "1231" "2345", 7) to 1.
90  %cmp7 = call i32 @strncmp(i8* %p1, i8* %p2, i64 7)
91  %pcmp7 = getelementptr i32, i32* %pcmp, i64 7
92  store i32 %cmp7, i32* %pcmp7
93
94; Fold strncmp("123", "1231" "2345", 8) to 1.
95  %cmp8 = call i32 @strncmp(i8* %p1, i8* %p2, i64 8)
96  %pcmp8 = getelementptr i32, i32* %pcmp, i64 8
97  store i32 %cmp8, i32* %pcmp8
98
99; Fold strncmp("123", "1231" "2345", 9) to 1.
100  %cmp9 = call i32 @strncmp(i8* %p1, i8* %p2, i64 9)
101  %pcmp9 = getelementptr i32, i32* %pcmp, i64 9
102  store i32 %cmp9, i32* %pcmp9
103
104  ret void
105}
106
107
108define void @fold_strncmp_Ab_a(i32* %pcmp) {
109; CHECK-LABEL: @fold_strncmp_Ab_a(
110; CHECK-NEXT:    store i32 0, i32* [[PCMP:%.*]], align 4
111; CHECK-NEXT:    [[PCMP1:%.*]] = getelementptr i32, i32* [[PCMP]], i64 1
112; CHECK-NEXT:    store i32 0, i32* [[PCMP1]], align 4
113; CHECK-NEXT:    [[CMP2:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A:%.*]], %struct.A* @a, i64 0, i32 1, i64 3), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i64 2)
114; CHECK-NEXT:    [[PCMP2:%.*]] = getelementptr i32, i32* [[PCMP]], i64 2
115; CHECK-NEXT:    store i32 [[CMP2]], i32* [[PCMP2]], align 4
116; CHECK-NEXT:    [[CMP3:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 3), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i64 3)
117; CHECK-NEXT:    [[PCMP3:%.*]] = getelementptr i32, i32* [[PCMP]], i64 3
118; CHECK-NEXT:    store i32 [[CMP3]], i32* [[PCMP3]], align 4
119; CHECK-NEXT:    [[CMP4:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 3), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i64 4)
120; CHECK-NEXT:    [[PCMP4:%.*]] = getelementptr i32, i32* [[PCMP]], i64 4
121; CHECK-NEXT:    store i32 [[CMP4]], i32* [[PCMP4]], align 4
122; CHECK-NEXT:    [[CMP5:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 3), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i64 5)
123; CHECK-NEXT:    [[PCMP5:%.*]] = getelementptr i32, i32* [[PCMP]], i64 5
124; CHECK-NEXT:    store i32 [[CMP5]], i32* [[PCMP5]], align 4
125; CHECK-NEXT:    ret void
126;
127; p1 = &a.b[3]
128  %p1 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 1, i32 3
129; p2 = &a.a
130  %p2 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 0, i32 0
131
132; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 0) to 0.
133  %cmp0 = call i32 @strncmp(i8* %p1, i8* %p2, i64 0)
134  %pcmp0 = getelementptr i32, i32* %pcmp, i64 0
135  store i32 %cmp0, i32* %pcmp0
136
137; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 1) to 0.
138  %cmp1 = call i32 @strncmp(i8* %p1, i8* %p2, i64 1)
139  %pcmp1 = getelementptr i32, i32* %pcmp, i64 1
140  store i32 %cmp1, i32* %pcmp1
141
142; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 2) to 0.
143  %cmp2 = call i32 @strncmp(i8* %p1, i8* %p2, i64 2)
144  %pcmp2 = getelementptr i32, i32* %pcmp, i64 2
145  store i32 %cmp2, i32* %pcmp2
146
147; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 3) to 0.
148  %cmp3 = call i32 @strncmp(i8* %p1, i8* %p2, i64 3)
149  %pcmp3 = getelementptr i32, i32* %pcmp, i64 3
150  store i32 %cmp3, i32* %pcmp3
151
152; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 4) to 1.
153  %cmp4 = call i32 @strncmp(i8* %p1, i8* %p2, i64 4)
154  %pcmp4 = getelementptr i32, i32* %pcmp, i64 4
155  store i32 %cmp4, i32* %pcmp4
156
157; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 5) to 1.
158  %cmp5 = call i32 @strncmp(i8* %p1, i8* %p2, i64 5)
159  %pcmp5 = getelementptr i32, i32* %pcmp, i64 5
160  store i32 %cmp5, i32* %pcmp5
161
162  ret void
163}
164