xref: /llvm-project/llvm/test/Transforms/AggressiveInstCombine/strncmp-1.ll (revision 1241e7692a466ceb420be2780f1c3e8bbab7d469)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -S -passes=aggressive-instcombine < %s | FileCheck %s
3
4; check whether we generate the right IR
5
6declare i32 @strncmp(ptr nocapture, ptr nocapture, i64)
7declare i32 @strcmp(ptr nocapture, ptr nocapture)
8
9@s2 = constant [2 x i8] c"a\00"
10@s3 = constant [3 x i8] c"ab\00"
11@s3ff = constant [3 x i8] c"\FE\FF\00"
12
13define i1 @test_strncmp_1(ptr %s) {
14; CHECK-LABEL: define i1 @test_strncmp_1(
15; CHECK-SAME: ptr [[S:%.*]]) {
16; CHECK-NEXT:  entry:
17; CHECK-NEXT:    br label [[SUB:%.*]]
18; CHECK:       sub_0:
19; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[S]], align 1
20; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
21; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 97, [[TMP1]]
22; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
23; CHECK-NEXT:    br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]]
24; CHECK:       sub_1:
25; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1
26; CHECK-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
27; CHECK-NEXT:    [[TMP6:%.*]] = zext i8 [[TMP5]] to i32
28; CHECK-NEXT:    [[TMP7:%.*]] = sub i32 98, [[TMP6]]
29; CHECK-NEXT:    br label [[NE]]
30; CHECK:       ne:
31; CHECK-NEXT:    [[TMP8:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP7]], [[SUB1]] ]
32; CHECK-NEXT:    br label [[ENTRY:%.*]]
33; CHECK:       entry.tail:
34; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP8]], 0
35; CHECK-NEXT:    ret i1 [[CMP]]
36;
37entry:
38  %call = tail call i32 @strncmp(ptr nonnull dereferenceable(3) @s3, ptr nonnull dereferenceable(1) %s, i64 2)
39  %cmp = icmp eq i32 %call, 0
40  ret i1 %cmp
41}
42
43define i1 @test_strncmp_2(ptr %s) {
44; CHECK-LABEL: define i1 @test_strncmp_2(
45; CHECK-SAME: ptr [[S:%.*]]) {
46; CHECK-NEXT:  entry:
47; CHECK-NEXT:    br label [[SUB:%.*]]
48; CHECK:       sub_0:
49; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[S]], align 1
50; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
51; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 97, [[TMP1]]
52; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
53; CHECK-NEXT:    br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]]
54; CHECK:       sub_1:
55; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1
56; CHECK-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
57; CHECK-NEXT:    [[TMP6:%.*]] = zext i8 [[TMP5]] to i32
58; CHECK-NEXT:    [[TMP7:%.*]] = sub i32 98, [[TMP6]]
59; CHECK-NEXT:    [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0
60; CHECK-NEXT:    br i1 [[TMP8]], label [[NE]], label [[SUB2:%.*]]
61; CHECK:       sub_2:
62; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 2
63; CHECK-NEXT:    [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 1
64; CHECK-NEXT:    [[TMP11:%.*]] = zext i8 [[TMP10]] to i32
65; CHECK-NEXT:    [[TMP12:%.*]] = sub i32 0, [[TMP11]]
66; CHECK-NEXT:    br label [[NE]]
67; CHECK:       ne:
68; CHECK-NEXT:    [[TMP13:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP7]], [[SUB1]] ], [ [[TMP12]], [[SUB2]] ]
69; CHECK-NEXT:    br label [[ENTRY:%.*]]
70; CHECK:       entry.tail:
71; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP13]], 0
72; CHECK-NEXT:    ret i1 [[CMP]]
73;
74entry:
75  %call = tail call i32 @strncmp(ptr nonnull dereferenceable(3) @s3, ptr nonnull dereferenceable(1) %s, i64 3)
76  %cmp = icmp slt i32 %call, 0
77  ret i1 %cmp
78}
79
80define i1 @test_strncmp_3(ptr %s) {
81; CHECK-LABEL: define i1 @test_strncmp_3(
82; CHECK-SAME: ptr [[S:%.*]]) {
83; CHECK-NEXT:  entry:
84; CHECK-NEXT:    br label [[SUB:%.*]]
85; CHECK:       sub_0:
86; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[S]], align 1
87; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
88; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 97, [[TMP1]]
89; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
90; CHECK-NEXT:    br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]]
91; CHECK:       sub_1:
92; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1
93; CHECK-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
94; CHECK-NEXT:    [[TMP6:%.*]] = zext i8 [[TMP5]] to i32
95; CHECK-NEXT:    [[TMP7:%.*]] = sub i32 98, [[TMP6]]
96; CHECK-NEXT:    [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0
97; CHECK-NEXT:    br i1 [[TMP8]], label [[NE]], label [[SUB2:%.*]]
98; CHECK:       sub_2:
99; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 2
100; CHECK-NEXT:    [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 1
101; CHECK-NEXT:    [[TMP11:%.*]] = zext i8 [[TMP10]] to i32
102; CHECK-NEXT:    [[TMP12:%.*]] = sub i32 0, [[TMP11]]
103; CHECK-NEXT:    br label [[NE]]
104; CHECK:       ne:
105; CHECK-NEXT:    [[TMP13:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP7]], [[SUB1]] ], [ [[TMP12]], [[SUB2]] ]
106; CHECK-NEXT:    br label [[ENTRY:%.*]]
107; CHECK:       entry.tail:
108; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP13]], 0
109; CHECK-NEXT:    ret i1 [[CMP]]
110;
111entry:
112  %call = tail call i32 @strncmp(ptr nonnull dereferenceable(3) @s3, ptr nonnull dereferenceable(1) %s, i64 4)
113  %cmp = icmp sgt i32 %call, 0
114  ret i1 %cmp
115}
116
117define i1 @test_strcmp_1(ptr %s) {
118; CHECK-LABEL: define i1 @test_strcmp_1(
119; CHECK-SAME: ptr [[S:%.*]]) {
120; CHECK-NEXT:  entry:
121; CHECK-NEXT:    br label [[SUB:%.*]]
122; CHECK:       sub_0:
123; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[S]], align 1
124; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
125; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[TMP1]], 97
126; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
127; CHECK-NEXT:    br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]]
128; CHECK:       sub_1:
129; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1
130; CHECK-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
131; CHECK-NEXT:    [[TMP6:%.*]] = zext i8 [[TMP5]] to i32
132; CHECK-NEXT:    br label [[NE]]
133; CHECK:       ne:
134; CHECK-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP6]], [[SUB1]] ]
135; CHECK-NEXT:    br label [[ENTRY:%.*]]
136; CHECK:       entry.tail:
137; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[TMP7]], 0
138; CHECK-NEXT:    ret i1 [[CMP]]
139;
140entry:
141  %call = tail call i32 @strcmp(ptr nonnull dereferenceable(1) %s, ptr nonnull dereferenceable(2) @s2)
142  %cmp = icmp ne i32 %call, 0
143  ret i1 %cmp
144}
145
146define i1 @test_strcmp_2(ptr %s) {
147; CHECK-LABEL: define i1 @test_strcmp_2(
148; CHECK-SAME: ptr [[S:%.*]]) {
149; CHECK-NEXT:  entry:
150; CHECK-NEXT:    br label [[SUB:%.*]]
151; CHECK:       sub_0:
152; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[S]], align 1
153; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
154; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[TMP1]], 97
155; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
156; CHECK-NEXT:    br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]]
157; CHECK:       sub_1:
158; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1
159; CHECK-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
160; CHECK-NEXT:    [[TMP6:%.*]] = zext i8 [[TMP5]] to i32
161; CHECK-NEXT:    [[TMP7:%.*]] = sub i32 [[TMP6]], 98
162; CHECK-NEXT:    [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0
163; CHECK-NEXT:    br i1 [[TMP8]], label [[NE]], label [[SUB2:%.*]]
164; CHECK:       sub_2:
165; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 2
166; CHECK-NEXT:    [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 1
167; CHECK-NEXT:    [[TMP11:%.*]] = zext i8 [[TMP10]] to i32
168; CHECK-NEXT:    br label [[NE]]
169; CHECK:       ne:
170; CHECK-NEXT:    [[TMP12:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP7]], [[SUB1]] ], [ [[TMP11]], [[SUB2]] ]
171; CHECK-NEXT:    br label [[ENTRY:%.*]]
172; CHECK:       entry.tail:
173; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[TMP12]], 0
174; CHECK-NEXT:    ret i1 [[CMP]]
175;
176entry:
177  %call = tail call i32 @strcmp(ptr nonnull dereferenceable(1) %s, ptr nonnull dereferenceable(3) @s3)
178  %cmp = icmp sge i32 %call, 0
179  ret i1 %cmp
180}
181
182define i1 @test_strcmp_3(ptr %s) {
183; CHECK-LABEL: define i1 @test_strcmp_3(
184; CHECK-SAME: ptr [[S:%.*]]) {
185; CHECK-NEXT:  entry:
186; CHECK-NEXT:    br label [[SUB:%.*]]
187; CHECK:       sub_0:
188; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[S]], align 1
189; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
190; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 97, [[TMP1]]
191; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
192; CHECK-NEXT:    br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]]
193; CHECK:       sub_1:
194; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1
195; CHECK-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
196; CHECK-NEXT:    [[TMP6:%.*]] = zext i8 [[TMP5]] to i32
197; CHECK-NEXT:    [[TMP7:%.*]] = sub i32 98, [[TMP6]]
198; CHECK-NEXT:    [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0
199; CHECK-NEXT:    br i1 [[TMP8]], label [[NE]], label [[SUB2:%.*]]
200; CHECK:       sub_2:
201; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 2
202; CHECK-NEXT:    [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 1
203; CHECK-NEXT:    [[TMP11:%.*]] = zext i8 [[TMP10]] to i32
204; CHECK-NEXT:    [[TMP12:%.*]] = sub i32 0, [[TMP11]]
205; CHECK-NEXT:    br label [[NE]]
206; CHECK:       ne:
207; CHECK-NEXT:    [[TMP13:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP7]], [[SUB1]] ], [ [[TMP12]], [[SUB2]] ]
208; CHECK-NEXT:    br label [[ENTRY:%.*]]
209; CHECK:       entry.tail:
210; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[TMP13]], 0
211; CHECK-NEXT:    ret i1 [[CMP]]
212;
213entry:
214  %call = tail call i32 @strcmp(ptr nonnull dereferenceable(3) @s3, ptr nonnull dereferenceable(1) %s)
215  %cmp = icmp sle i32 %call, 0
216  ret i1 %cmp
217}
218
219define i1 @test_strcmp_4(ptr %s) {
220; CHECK-LABEL: define i1 @test_strcmp_4(
221; CHECK-SAME: ptr [[S:%.*]]) {
222; CHECK-NEXT:  entry:
223; CHECK-NEXT:    br label [[SUB_0:%.*]]
224; CHECK:       sub_0:
225; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[S]], align 1
226; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
227; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 254, [[TMP1]]
228; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
229; CHECK-NEXT:    br i1 [[TMP3]], label [[NE:%.*]], label [[SUB_1:%.*]]
230; CHECK:       sub_1:
231; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1
232; CHECK-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
233; CHECK-NEXT:    [[TMP6:%.*]] = zext i8 [[TMP5]] to i32
234; CHECK-NEXT:    [[TMP7:%.*]] = sub i32 255, [[TMP6]]
235; CHECK-NEXT:    [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0
236; CHECK-NEXT:    br i1 [[TMP8]], label [[NE]], label [[SUB_2:%.*]]
237; CHECK:       sub_2:
238; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 2
239; CHECK-NEXT:    [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 1
240; CHECK-NEXT:    [[TMP11:%.*]] = zext i8 [[TMP10]] to i32
241; CHECK-NEXT:    [[TMP12:%.*]] = sub i32 0, [[TMP11]]
242; CHECK-NEXT:    br label [[NE]]
243; CHECK:       ne:
244; CHECK-NEXT:    [[TMP13:%.*]] = phi i32 [ [[TMP2]], [[SUB_0]] ], [ [[TMP7]], [[SUB_1]] ], [ [[TMP12]], [[SUB_2]] ]
245; CHECK-NEXT:    br label [[ENTRY_TAIL:%.*]]
246; CHECK:       entry.tail:
247; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP13]], 0
248; CHECK-NEXT:    ret i1 [[CMP]]
249;
250entry:
251  %call = tail call i32 @strcmp(ptr nonnull dereferenceable(3) @s3ff, ptr nonnull dereferenceable(1) %s)
252  %cmp = icmp eq i32 %call, 0
253  ret i1 %cmp
254}
255