1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Verify that calls to memcmp with arrays of elements larger than char
3; are folded correctly.
4; RUN: opt < %s -passes=instcombine -S -data-layout="E" | FileCheck %s --check-prefixes=BE
5; RUN: opt < %s -passes=instcombine -S -data-layout="e" | FileCheck %s --check-prefixes=LE
6
7declare i32 @memcmp(i8*, i8*, i64)
8
9; BE representation: { 'a', 'b', 'c', ..., 'f', 'g', 'h' }
10; LE representation: { 'b', 'a', 'd', ..., 'e', 'h', 'g' }
11@ia16a = constant [4 x i16] [i16 24930, i16 25444, i16 25958, i16 26472]
12
13; Same as the BE representation above except ending in "gg".
14@i8a = constant [8 x i8] c"abcdefgg"
15
16; Fold memcmp(ia16a, i8a, N) for N in [0, 8].
17
18define void @fold_memcmp_ia16a_i8a(i32* %pcmp) {
19; BE-LABEL: @fold_memcmp_ia16a_i8a(
20; BE-NEXT:    store i32 0, i32* [[PCMP:%.*]], align 4
21; BE-NEXT:    [[PSTOR1:%.*]] = getelementptr i32, i32* [[PCMP]], i64 1
22; BE-NEXT:    store i32 0, i32* [[PSTOR1]], align 4
23; BE-NEXT:    [[PSTOR2:%.*]] = getelementptr i32, i32* [[PCMP]], i64 2
24; BE-NEXT:    store i32 0, i32* [[PSTOR2]], align 4
25; BE-NEXT:    [[PSTOR3:%.*]] = getelementptr i32, i32* [[PCMP]], i64 3
26; BE-NEXT:    store i32 0, i32* [[PSTOR3]], align 4
27; BE-NEXT:    [[PSTOR4:%.*]] = getelementptr i32, i32* [[PCMP]], i64 4
28; BE-NEXT:    store i32 0, i32* [[PSTOR4]], align 4
29; BE-NEXT:    [[PSTOR5:%.*]] = getelementptr i32, i32* [[PCMP]], i64 5
30; BE-NEXT:    store i32 0, i32* [[PSTOR5]], align 4
31; BE-NEXT:    [[PSTOR6:%.*]] = getelementptr i32, i32* [[PCMP]], i64 6
32; BE-NEXT:    store i32 0, i32* [[PSTOR6]], align 4
33; BE-NEXT:    [[PSTOR7:%.*]] = getelementptr i32, i32* [[PCMP]], i64 7
34; BE-NEXT:    store i32 0, i32* [[PSTOR7]], align 4
35; BE-NEXT:    [[PSTOR8:%.*]] = getelementptr i32, i32* [[PCMP]], i64 8
36; BE-NEXT:    store i32 1, i32* [[PSTOR8]], align 4
37; BE-NEXT:    ret void
38;
39; LE-LABEL: @fold_memcmp_ia16a_i8a(
40; LE-NEXT:    store i32 0, i32* [[PCMP:%.*]], align 4
41; LE-NEXT:    [[PSTOR1:%.*]] = getelementptr i32, i32* [[PCMP]], i64 1
42; LE-NEXT:    store i32 1, i32* [[PSTOR1]], align 4
43; LE-NEXT:    [[PSTOR2:%.*]] = getelementptr i32, i32* [[PCMP]], i64 2
44; LE-NEXT:    store i32 1, i32* [[PSTOR2]], align 4
45; LE-NEXT:    [[PSTOR3:%.*]] = getelementptr i32, i32* [[PCMP]], i64 3
46; LE-NEXT:    store i32 1, i32* [[PSTOR3]], align 4
47; LE-NEXT:    [[PSTOR4:%.*]] = getelementptr i32, i32* [[PCMP]], i64 4
48; LE-NEXT:    store i32 1, i32* [[PSTOR4]], align 4
49; LE-NEXT:    [[PSTOR5:%.*]] = getelementptr i32, i32* [[PCMP]], i64 5
50; LE-NEXT:    store i32 1, i32* [[PSTOR5]], align 4
51; LE-NEXT:    [[PSTOR6:%.*]] = getelementptr i32, i32* [[PCMP]], i64 6
52; LE-NEXT:    store i32 1, i32* [[PSTOR6]], align 4
53; LE-NEXT:    [[PSTOR7:%.*]] = getelementptr i32, i32* [[PCMP]], i64 7
54; LE-NEXT:    store i32 1, i32* [[PSTOR7]], align 4
55; LE-NEXT:    [[PSTOR8:%.*]] = getelementptr i32, i32* [[PCMP]], i64 8
56; LE-NEXT:    store i32 1, i32* [[PSTOR8]], align 4
57; LE-NEXT:    ret void
58;
59  %p0 = getelementptr [4 x i16], [4 x i16]* @ia16a, i64 0, i64 0
60  %p1 = bitcast i16* %p0 to i8*
61  %q = getelementptr [8 x i8], [8 x i8]* @i8a, i64 0, i64 0
62
63  %cmp0 = call i32 @memcmp(i8* %p1, i8* %q, i64 0)
64  %pstor0 = getelementptr i32, i32* %pcmp, i64 0
65  store i32 %cmp0, i32* %pstor0
66
67  %cmp1 = call i32 @memcmp(i8* %p1, i8* %q, i64 1)
68  %pstor1 = getelementptr i32, i32* %pcmp, i64 1
69  store i32 %cmp1, i32* %pstor1
70
71  %cmp2 = call i32 @memcmp(i8* %p1, i8* %q, i64 2)
72  %pstor2 = getelementptr i32, i32* %pcmp, i64 2
73  store i32 %cmp2, i32* %pstor2
74
75  %cmp3 = call i32 @memcmp(i8* %p1, i8* %q, i64 3)
76  %pstor3 = getelementptr i32, i32* %pcmp, i64 3
77  store i32 %cmp3, i32* %pstor3
78
79  %cmp4 = call i32 @memcmp(i8* %p1, i8* %q, i64 4)
80  %pstor4 = getelementptr i32, i32* %pcmp, i64 4
81  store i32 %cmp4, i32* %pstor4
82
83  %cmp5 = call i32 @memcmp(i8* %p1, i8* %q, i64 5)
84  %pstor5 = getelementptr i32, i32* %pcmp, i64 5
85  store i32 %cmp5, i32* %pstor5
86
87  %cmp6 = call i32 @memcmp(i8* %p1, i8* %q, i64 6)
88  %pstor6 = getelementptr i32, i32* %pcmp, i64 6
89  store i32 %cmp6, i32* %pstor6
90
91  %cmp7 = call i32 @memcmp(i8* %p1, i8* %q, i64 7)
92  %pstor7 = getelementptr i32, i32* %pcmp, i64 7
93  store i32 %cmp7, i32* %pstor7
94
95  %cmp8 = call i32 @memcmp(i8* %p1, i8* %q, i64 8)
96  %pstor8 = getelementptr i32, i32* %pcmp, i64 8
97  store i32 %cmp8, i32* %pstor8
98
99  ret void
100}
101
102
103; Fold memcmp(ia16a + 1, i8a + 2, N) for N in [0, 6].
104
105define void @fold_memcmp_ia16a_p1_i8a_p1(i32* %pcmp) {
106; BE-LABEL: @fold_memcmp_ia16a_p1_i8a_p1(
107; BE-NEXT:    store i32 0, i32* [[PCMP:%.*]], align 4
108; BE-NEXT:    [[PSTOR1:%.*]] = getelementptr i32, i32* [[PCMP]], i64 1
109; BE-NEXT:    store i32 1, i32* [[PSTOR1]], align 4
110; BE-NEXT:    [[PSTOR2:%.*]] = getelementptr i32, i32* [[PCMP]], i64 2
111; BE-NEXT:    store i32 1, i32* [[PSTOR2]], align 4
112; BE-NEXT:    [[PSTOR3:%.*]] = getelementptr i32, i32* [[PCMP]], i64 3
113; BE-NEXT:    store i32 1, i32* [[PSTOR3]], align 4
114; BE-NEXT:    [[PSTOR4:%.*]] = getelementptr i32, i32* [[PCMP]], i64 4
115; BE-NEXT:    store i32 1, i32* [[PSTOR4]], align 4
116; BE-NEXT:    [[PSTOR5:%.*]] = getelementptr i32, i32* [[PCMP]], i64 5
117; BE-NEXT:    store i32 1, i32* [[PSTOR5]], align 4
118; BE-NEXT:    [[PSTOR6:%.*]] = getelementptr i32, i32* [[PCMP]], i64 6
119; BE-NEXT:    store i32 1, i32* [[PSTOR6]], align 4
120; BE-NEXT:    ret void
121;
122; LE-LABEL: @fold_memcmp_ia16a_p1_i8a_p1(
123; LE-NEXT:    store i32 0, i32* [[PCMP:%.*]], align 4
124; LE-NEXT:    [[PSTOR1:%.*]] = getelementptr i32, i32* [[PCMP]], i64 1
125; LE-NEXT:    store i32 1, i32* [[PSTOR1]], align 4
126; LE-NEXT:    [[PSTOR2:%.*]] = getelementptr i32, i32* [[PCMP]], i64 2
127; LE-NEXT:    store i32 1, i32* [[PSTOR2]], align 4
128; LE-NEXT:    [[PSTOR3:%.*]] = getelementptr i32, i32* [[PCMP]], i64 3
129; LE-NEXT:    store i32 1, i32* [[PSTOR3]], align 4
130; LE-NEXT:    [[PSTOR4:%.*]] = getelementptr i32, i32* [[PCMP]], i64 4
131; LE-NEXT:    store i32 1, i32* [[PSTOR4]], align 4
132; LE-NEXT:    [[PSTOR5:%.*]] = getelementptr i32, i32* [[PCMP]], i64 5
133; LE-NEXT:    store i32 1, i32* [[PSTOR5]], align 4
134; LE-NEXT:    [[PSTOR6:%.*]] = getelementptr i32, i32* [[PCMP]], i64 6
135; LE-NEXT:    store i32 1, i32* [[PSTOR6]], align 4
136; LE-NEXT:    ret void
137;
138  %p0 = getelementptr [4 x i16], [4 x i16]* @ia16a, i64 0, i64 1
139  %p1 = bitcast i16* %p0 to i8*
140  %q = getelementptr [8 x i8], [8 x i8]* @i8a, i64 0, i64 1
141
142  %cmp0 = call i32 @memcmp(i8* %p1, i8* %q, i64 0)
143  %pstor0 = getelementptr i32, i32* %pcmp, i64 0
144  store i32 %cmp0, i32* %pstor0
145
146  %cmp1 = call i32 @memcmp(i8* %p1, i8* %q, i64 1)
147  %pstor1 = getelementptr i32, i32* %pcmp, i64 1
148  store i32 %cmp1, i32* %pstor1
149
150  %cmp2 = call i32 @memcmp(i8* %p1, i8* %q, i64 2)
151  %pstor2 = getelementptr i32, i32* %pcmp, i64 2
152  store i32 %cmp2, i32* %pstor2
153
154  %cmp3 = call i32 @memcmp(i8* %p1, i8* %q, i64 3)
155  %pstor3 = getelementptr i32, i32* %pcmp, i64 3
156  store i32 %cmp3, i32* %pstor3
157
158  %cmp4 = call i32 @memcmp(i8* %p1, i8* %q, i64 4)
159  %pstor4 = getelementptr i32, i32* %pcmp, i64 4
160  store i32 %cmp4, i32* %pstor4
161
162  %cmp5 = call i32 @memcmp(i8* %p1, i8* %q, i64 5)
163  %pstor5 = getelementptr i32, i32* %pcmp, i64 5
164  store i32 %cmp5, i32* %pstor5
165
166  %cmp6 = call i32 @memcmp(i8* %p1, i8* %q, i64 6)
167  %pstor6 = getelementptr i32, i32* %pcmp, i64 6
168  store i32 %cmp6, i32* %pstor6
169
170  ret void
171}
172