xref: /llvm-project/llvm/test/Transforms/AggressiveInstCombine/memchr.ll (revision b0924ed64e0d814ab23fa474c2047030dd3a2f46)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2; RUN: opt -S -passes=aggressive-instcombine --memchr-inline-threshold=5 < %s | FileCheck %s
3
4@str = constant [5 x i8] c"01\002\00", align 1
5@str_long = constant [8 x i8] c"0123456\00", align 1
6
7declare ptr @memchr(ptr, i32, i64)
8
9define i1 @test_memchr_null(i32 %x) {
10; CHECK-LABEL: define i1 @test_memchr_null(
11; CHECK-SAME: i32 [[X:%.*]]) {
12; CHECK-NEXT:  [[ENTRY:.*]]:
13; CHECK-NEXT:    [[TMP0:%.*]] = trunc i32 [[X]] to i8
14; CHECK-NEXT:    switch i8 [[TMP0]], label %[[ENTRY_SPLIT:.*]] [
15; CHECK-NEXT:      i8 48, label %[[MEMCHR_CASE:.*]]
16; CHECK-NEXT:      i8 49, label %[[MEMCHR_CASE1:.*]]
17; CHECK-NEXT:      i8 0, label %[[MEMCHR_CASE2:.*]]
18; CHECK-NEXT:      i8 50, label %[[MEMCHR_CASE3:.*]]
19; CHECK-NEXT:    ]
20; CHECK:       [[MEMCHR_CASE]]:
21; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS:.*]]
22; CHECK:       [[MEMCHR_CASE1]]:
23; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS]]
24; CHECK:       [[MEMCHR_CASE2]]:
25; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS]]
26; CHECK:       [[MEMCHR_CASE3]]:
27; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS]]
28; CHECK:       [[MEMCHR_SUCCESS]]:
29; CHECK-NEXT:    [[MEMCHR_IDX:%.*]] = phi i64 [ 0, %[[MEMCHR_CASE]] ], [ 1, %[[MEMCHR_CASE1]] ], [ 2, %[[MEMCHR_CASE2]] ], [ 3, %[[MEMCHR_CASE3]] ]
30; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr @str, i64 [[MEMCHR_IDX]]
31; CHECK-NEXT:    br label %[[ENTRY_SPLIT]]
32; CHECK:       [[ENTRY_SPLIT]]:
33; CHECK-NEXT:    [[MEMCHR4:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[TMP1]], %[[MEMCHR_SUCCESS]] ]
34; CHECK-NEXT:    [[ISNULL:%.*]] = icmp eq ptr [[MEMCHR4]], null
35; CHECK-NEXT:    ret i1 [[ISNULL]]
36;
37entry:
38  %memchr = call ptr @memchr(ptr @str, i32 %x, i64 5)
39  %isnull = icmp eq ptr %memchr, null
40  ret i1 %isnull
41}
42
43define ptr @test_memchr(i32 %x) {
44; CHECK-LABEL: define ptr @test_memchr(
45; CHECK-SAME: i32 [[X:%.*]]) {
46; CHECK-NEXT:  [[ENTRY:.*]]:
47; CHECK-NEXT:    [[TMP0:%.*]] = trunc i32 [[X]] to i8
48; CHECK-NEXT:    switch i8 [[TMP0]], label %[[ENTRY_SPLIT:.*]] [
49; CHECK-NEXT:      i8 48, label %[[MEMCHR_CASE:.*]]
50; CHECK-NEXT:      i8 49, label %[[MEMCHR_CASE1:.*]]
51; CHECK-NEXT:      i8 0, label %[[MEMCHR_CASE2:.*]]
52; CHECK-NEXT:      i8 50, label %[[MEMCHR_CASE3:.*]]
53; CHECK-NEXT:    ]
54; CHECK:       [[MEMCHR_CASE]]:
55; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS:.*]]
56; CHECK:       [[MEMCHR_CASE1]]:
57; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS]]
58; CHECK:       [[MEMCHR_CASE2]]:
59; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS]]
60; CHECK:       [[MEMCHR_CASE3]]:
61; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS]]
62; CHECK:       [[MEMCHR_SUCCESS]]:
63; CHECK-NEXT:    [[MEMCHR_IDX:%.*]] = phi i64 [ 0, %[[MEMCHR_CASE]] ], [ 1, %[[MEMCHR_CASE1]] ], [ 2, %[[MEMCHR_CASE2]] ], [ 3, %[[MEMCHR_CASE3]] ]
64; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr @str, i64 [[MEMCHR_IDX]]
65; CHECK-NEXT:    br label %[[ENTRY_SPLIT]]
66; CHECK:       [[ENTRY_SPLIT]]:
67; CHECK-NEXT:    [[MEMCHR4:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[TMP1]], %[[MEMCHR_SUCCESS]] ]
68; CHECK-NEXT:    ret ptr [[MEMCHR4]]
69;
70entry:
71  %memchr = call ptr @memchr(ptr @str, i32 %x, i64 5)
72  ret ptr %memchr
73}
74
75define ptr @test_memchr_smaller_n(i32 %x) {
76; CHECK-LABEL: define ptr @test_memchr_smaller_n(
77; CHECK-SAME: i32 [[X:%.*]]) {
78; CHECK-NEXT:  [[ENTRY:.*]]:
79; CHECK-NEXT:    [[TMP0:%.*]] = trunc i32 [[X]] to i8
80; CHECK-NEXT:    switch i8 [[TMP0]], label %[[ENTRY_SPLIT:.*]] [
81; CHECK-NEXT:      i8 48, label %[[MEMCHR_CASE:.*]]
82; CHECK-NEXT:      i8 49, label %[[MEMCHR_CASE1:.*]]
83; CHECK-NEXT:      i8 0, label %[[MEMCHR_CASE2:.*]]
84; CHECK-NEXT:    ]
85; CHECK:       [[MEMCHR_CASE]]:
86; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS:.*]]
87; CHECK:       [[MEMCHR_CASE1]]:
88; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS]]
89; CHECK:       [[MEMCHR_CASE2]]:
90; CHECK-NEXT:    br label %[[MEMCHR_SUCCESS]]
91; CHECK:       [[MEMCHR_SUCCESS]]:
92; CHECK-NEXT:    [[MEMCHR_IDX:%.*]] = phi i64 [ 0, %[[MEMCHR_CASE]] ], [ 1, %[[MEMCHR_CASE1]] ], [ 2, %[[MEMCHR_CASE2]] ]
93; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr @str, i64 [[MEMCHR_IDX]]
94; CHECK-NEXT:    br label %[[ENTRY_SPLIT]]
95; CHECK:       [[ENTRY_SPLIT]]:
96; CHECK-NEXT:    [[MEMCHR3:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[TMP1]], %[[MEMCHR_SUCCESS]] ]
97; CHECK-NEXT:    ret ptr [[MEMCHR3]]
98;
99entry:
100  %memchr = call ptr @memchr(ptr @str, i32 %x, i64 3)
101  ret ptr %memchr
102}
103
104; negative tests
105
106define ptr @test_memchr_larger_n(i32 %x) {
107; CHECK-LABEL: define ptr @test_memchr_larger_n(
108; CHECK-SAME: i32 [[X:%.*]]) {
109; CHECK-NEXT:  [[ENTRY:.*:]]
110; CHECK-NEXT:    [[MEMCHR:%.*]] = call ptr @memchr(ptr @str, i32 [[X]], i64 6)
111; CHECK-NEXT:    ret ptr [[MEMCHR]]
112;
113entry:
114  %memchr = call ptr @memchr(ptr @str, i32 %x, i64 6)
115  ret ptr %memchr
116}
117
118define ptr @test_memchr_non_constant(i32 %x, ptr %str) {
119; CHECK-LABEL: define ptr @test_memchr_non_constant(
120; CHECK-SAME: i32 [[X:%.*]], ptr [[STR:%.*]]) {
121; CHECK-NEXT:  [[ENTRY:.*:]]
122; CHECK-NEXT:    [[MEMCHR:%.*]] = call ptr @memchr(ptr [[STR]], i32 [[X]], i64 5)
123; CHECK-NEXT:    ret ptr [[MEMCHR]]
124;
125entry:
126  %memchr = call ptr @memchr(ptr %str, i32 %x, i64 5)
127  ret ptr %memchr
128}
129
130define ptr @test_memchr_constant_ch() {
131; CHECK-LABEL: define ptr @test_memchr_constant_ch() {
132; CHECK-NEXT:  [[ENTRY:.*:]]
133; CHECK-NEXT:    [[MEMCHR:%.*]] = call ptr @memchr(ptr @str, i32 49, i64 5)
134; CHECK-NEXT:    ret ptr [[MEMCHR]]
135;
136entry:
137  %memchr = call ptr @memchr(ptr @str, i32 49, i64 5)
138  ret ptr %memchr
139}
140
141define ptr @test_memchr_dynamic_n(i32 %x, i32 %y) {
142; CHECK-LABEL: define ptr @test_memchr_dynamic_n(
143; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
144; CHECK-NEXT:  [[ENTRY:.*:]]
145; CHECK-NEXT:    [[MEMCHR:%.*]] = call ptr @memchr(ptr @str, i32 [[X]], i32 [[Y]])
146; CHECK-NEXT:    ret ptr [[MEMCHR]]
147;
148entry:
149  %memchr = call ptr @memchr(ptr @str, i32 %x, i32 %y)
150  ret ptr %memchr
151}
152
153define ptr @test_memchr_long(i32 %x) {
154; CHECK-LABEL: define ptr @test_memchr_long(
155; CHECK-SAME: i32 [[X:%.*]]) {
156; CHECK-NEXT:  [[ENTRY:.*:]]
157; CHECK-NEXT:    [[MEMCHR:%.*]] = call ptr @memchr(ptr @str_long, i32 [[X]], i64 8)
158; CHECK-NEXT:    ret ptr [[MEMCHR]]
159;
160entry:
161  %memchr = call ptr @memchr(ptr @str_long, i32 %x, i64 8)
162  ret ptr %memchr
163}
164
165; We want to check that the compiler still calls memchr if the length is non-constant:
166define ptr @test_memchr_non_constant_length2(i32 %x, i64 %len) {
167; CHECK-LABEL: define ptr @test_memchr_non_constant_length2(
168; CHECK-SAME: i32 [[X:%.*]], i64 [[LEN:%.*]]) {
169; CHECK-NEXT:  [[ENTRY:.*:]]
170; CHECK-NEXT:    [[MEMCHR:%.*]] = call ptr @memchr(ptr @str, i32 [[X]], i64 [[LEN]])
171; CHECK-NEXT:    ret ptr [[MEMCHR]]
172;
173entry:
174  %memchr = call ptr @memchr(ptr @str, i32 %x, i64 %len)
175  ret ptr %memchr
176}
177