1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Test that the strcmp library call simplifier works correctly.
3; RUN: opt < %s -instcombine -S | FileCheck %s
4
5target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
6
7@hello = constant [6 x i8] c"hello\00"
8@hell = constant [5 x i8] c"hell\00"
9@bell = constant [5 x i8] c"bell\00"
10@null = constant [1 x i8] zeroinitializer
11
12declare i32 @strcmp(i8*, i8*)
13
14; strcmp("", x) -> -*x
15define arm_aapcscc i32 @test1(i8* %str2) {
16; CHECK-LABEL: @test1(
17; CHECK-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR2:%.*]], align 1
18; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32
19; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]]
20; CHECK-NEXT:    ret i32 [[TMP2]]
21;
22
23  %str1 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0
24  %temp1 = call arm_apcscc i32 @strcmp(i8* %str1, i8* %str2)
25  ret i32 %temp1
26
27}
28
29; strcmp(x, "") -> *x
30define arm_aapcscc i32 @test2(i8* %str1) {
31; CHECK-LABEL: @test2(
32; CHECK-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR1:%.*]], align 1
33; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32
34; CHECK-NEXT:    ret i32 [[TMP1]]
35;
36
37  %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0
38  %temp1 = call arm_aapcscc i32 @strcmp(i8* %str1, i8* %str2)
39  ret i32 %temp1
40}
41
42; strcmp(x, y)  -> cnst
43define arm_aapcscc i32 @test3() {
44; CHECK-LABEL: @test3(
45; CHECK-NEXT:    ret i32 -1
46;
47
48  %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0
49  %str2 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0
50  %temp1 = call arm_aapcscc i32 @strcmp(i8* %str1, i8* %str2)
51  ret i32 %temp1
52}
53
54define arm_aapcscc i32 @test4() {
55; CHECK-LABEL: @test4(
56; CHECK-NEXT:    ret i32 1
57;
58
59  %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0
60  %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0
61  %temp1 = call arm_aapcscc i32 @strcmp(i8* %str1, i8* %str2)
62  ret i32 %temp1
63}
64
65; strcmp(x, y)   -> memcmp(x, y, <known length>)
66; (This transform is rather difficult to trigger in a useful manner)
67define arm_aapcscc i32 @test5(i1 %b) {
68; CHECK-LABEL: @test5(
69; CHECK-NEXT:    [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0)
70; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* noundef nonnull dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* noundef nonnull dereferenceable(5) [[STR2]], i32 5)
71; CHECK-NEXT:    ret i32 [[MEMCMP]]
72;
73
74  %str1 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0
75  %temp1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0
76  %temp2 = getelementptr inbounds [5 x i8], [5 x i8]* @bell, i32 0, i32 0
77  %str2 = select i1 %b, i8* %temp1, i8* %temp2
78  %temp3 = call arm_aapcscc i32 @strcmp(i8* %str1, i8* %str2)
79  ret i32 %temp3
80}
81
82; strcmp(x,x)  -> 0
83define arm_aapcscc i32 @test6(i8* %str) {
84; CHECK-LABEL: @test6(
85; CHECK-NEXT:    ret i32 0
86;
87
88  %temp1 = call arm_aapcscc i32 @strcmp(i8* %str, i8* %str)
89  ret i32 %temp1
90}
91
92; strcmp("", x) -> -*x
93define arm_aapcs_vfpcc i32 @test1_vfp(i8* %str2) {
94; CHECK-LABEL: @test1_vfp(
95; CHECK-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR2:%.*]], align 1
96; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32
97; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]]
98; CHECK-NEXT:    ret i32 [[TMP2]]
99;
100
101  %str1 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0
102  %temp1 = call arm_aapcs_vfpcc i32 @strcmp(i8* %str1, i8* %str2)
103  ret i32 %temp1
104
105}
106
107; strcmp(x, "") -> *x
108define arm_aapcs_vfpcc i32 @test2_vfp(i8* %str1) {
109; CHECK-LABEL: @test2_vfp(
110; CHECK-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR1:%.*]], align 1
111; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32
112; CHECK-NEXT:    ret i32 [[TMP1]]
113;
114
115  %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0
116  %temp1 = call arm_aapcs_vfpcc i32 @strcmp(i8* %str1, i8* %str2)
117  ret i32 %temp1
118}
119
120; strcmp(x, y)  -> cnst
121define arm_aapcs_vfpcc i32 @test3_vfp() {
122; CHECK-LABEL: @test3_vfp(
123; CHECK-NEXT:    ret i32 -1
124;
125
126  %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0
127  %str2 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0
128  %temp1 = call arm_aapcs_vfpcc i32 @strcmp(i8* %str1, i8* %str2)
129  ret i32 %temp1
130}
131
132define arm_aapcs_vfpcc i32 @test4_vfp() {
133; CHECK-LABEL: @test4_vfp(
134; CHECK-NEXT:    ret i32 1
135;
136
137  %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0
138  %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0
139  %temp1 = call arm_aapcs_vfpcc i32 @strcmp(i8* %str1, i8* %str2)
140  ret i32 %temp1
141}
142
143; strcmp(x, y)   -> memcmp(x, y, <known length>)
144; (This transform is rather difficult to trigger in a useful manner)
145define arm_aapcs_vfpcc i32 @test5_vfp(i1 %b) {
146; CHECK-LABEL: @test5_vfp(
147; CHECK-NEXT:    [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0)
148; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* noundef nonnull dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* noundef nonnull dereferenceable(5) [[STR2]], i32 5)
149; CHECK-NEXT:    ret i32 [[MEMCMP]]
150;
151
152  %str1 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0
153  %temp1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0
154  %temp2 = getelementptr inbounds [5 x i8], [5 x i8]* @bell, i32 0, i32 0
155  %str2 = select i1 %b, i8* %temp1, i8* %temp2
156  %temp3 = call arm_aapcs_vfpcc i32 @strcmp(i8* %str1, i8* %str2)
157  ret i32 %temp3
158}
159
160; strcmp(x,x)  -> 0
161define arm_aapcs_vfpcc i32 @test6_vfp(i8* %str) {
162; CHECK-LABEL: @test6_vfp(
163; CHECK-NEXT:    ret i32 0
164;
165
166  %temp1 = call arm_aapcs_vfpcc i32 @strcmp(i8* %str, i8* %str)
167  ret i32 %temp1
168}
169