1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Verify that strlen calls with elements of constant arrays are folded.
3;
4; RUN: opt < %s -passes=instcombine -S | FileCheck %s
5
6declare i32 @strcmp(i8*, i8*)
7
8@a5 = constant [5 x [4 x i8]] [[4 x i8] c"123\00", [4 x i8] c"123\00", [4 x i8] c"12\00\00", [4 x i8] zeroinitializer, [4 x i8] zeroinitializer]
9
10
11; Fold strcmp(a5[0], a5[1]) to '1' - '1'.
12
13define i32 @fold_strcmp_a5i0_a5i1_to_0() {
14; CHECK-LABEL: @fold_strcmp_a5i0_a5i1_to_0(
15; CHECK-NEXT:    ret i32 0
16;
17  %p = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 0
18  %q = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 1, i64 0
19
20  %cmp = call i32 @strcmp(i8* %p, i8* %q)
21  ret i32 %cmp
22}
23
24
25; Do not fold strcmp(a5[0], a5[I]) where the index I is not constant.
26
27define i32 @call_strcmp_a5i0_a5iI(i64 %I) {
28; CHECK-LABEL: @call_strcmp_a5i0_a5iI(
29; CHECK-NEXT:    [[Q:%.*]] = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 [[I:%.*]], i64 0
30; CHECK-NEXT:    [[CMP:%.*]] = call i32 @strcmp(i8* noundef nonnull dereferenceable(4) getelementptr inbounds ([5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 0), i8* noundef nonnull dereferenceable(1) [[Q]])
31; CHECK-NEXT:    ret i32 [[CMP]]
32;
33  %p = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 0
34  %q = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 %I, i64 0
35
36  %cmp = call i32 @strcmp(i8* %p, i8* %q)
37  ret i32 %cmp
38}
39
40
41; Same as above but for strcmp(a5[I], a5[0]).
42
43define i32 @call_strcmp_a5iI_a5i0(i64 %I) {
44; CHECK-LABEL: @call_strcmp_a5iI_a5i0(
45; CHECK-NEXT:    [[P:%.*]] = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 [[I:%.*]], i64 0
46; CHECK-NEXT:    [[CMP:%.*]] = call i32 @strcmp(i8* noundef nonnull dereferenceable(1) [[P]], i8* noundef nonnull dereferenceable(4) getelementptr inbounds ([5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 0))
47; CHECK-NEXT:    ret i32 [[CMP]]
48;
49  %p = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 %I, i64 0
50  %q = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 0
51
52  %cmp = call i32 @strcmp(i8* %p, i8* %q)
53  ret i32 %cmp
54}
55
56
57; Fold strcmp(a5[0], &a5[1][1]) to '1' - '2'.
58
59define i32 @fold_strcmp_a5i0_a5i1_p1_to_0() {
60; CHECK-LABEL: @fold_strcmp_a5i0_a5i1_p1_to_0(
61; CHECK-NEXT:    ret i32 -1
62;
63  %p = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 0
64  %q = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 1, i64 1
65
66  %cmp = call i32 @strcmp(i8* %p, i8* %q)
67  ret i32 %cmp
68}
69
70
71; Do not fold strcmp(a5[0], &a5[1][I]) when the index I is not constant.
72
73define i32 @call_strcmp_a5i0_a5i1_pI(i64 %I) {
74; CHECK-LABEL: @call_strcmp_a5i0_a5i1_pI(
75; CHECK-NEXT:    [[Q:%.*]] = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 1, i64 [[I:%.*]]
76; CHECK-NEXT:    [[CMP:%.*]] = call i32 @strcmp(i8* noundef nonnull dereferenceable(4) getelementptr inbounds ([5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 0), i8* noundef nonnull dereferenceable(1) [[Q]])
77; CHECK-NEXT:    ret i32 [[CMP]]
78;
79  %p = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 0
80  %q = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 1, i64 %I
81
82  %cmp = call i32 @strcmp(i8* %p, i8* %q)
83  ret i32 %cmp
84}
85
86
87; Fold strcmp(&a5[0][1], a5[1]) to '2' - '1'.
88
89define i32 @fold_strcmp_a5i0_p1_a5i1_to_0() {
90; CHECK-LABEL: @fold_strcmp_a5i0_p1_a5i1_to_0(
91; CHECK-NEXT:    ret i32 1
92;
93  %p = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 1
94  %q = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 1, i64 0
95
96  %cmp = call i32 @strcmp(i8* %p, i8* %q)
97  ret i32 %cmp
98}
99
100
101; Fold strcmp(a5[0], a5[2]) to a5[0][2] - a5[2][2] or 1.
102
103define i32 @fold_strcmp_a5i0_a5i2_to_0() {
104; CHECK-LABEL: @fold_strcmp_a5i0_a5i2_to_0(
105; CHECK-NEXT:    ret i32 1
106;
107  %p = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 0
108  %q = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 2, i64 0
109
110  %cmp = call i32 @strcmp(i8* %p, i8* %q)
111  ret i32 %cmp
112}
113
114
115; Fold strcmp(a5[2], a5[0]) to a5[0][2] - a5[2][2] or 1.
116
117define i32 @fold_strcmp_a5i2_a5i0_to_m1() {
118; CHECK-LABEL: @fold_strcmp_a5i2_a5i0_to_m1(
119; CHECK-NEXT:    ret i32 -1
120;
121  %p = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 0, i64 0
122  %q = getelementptr [5 x [4 x i8]], [5 x [4 x i8]]* @a5, i64 0, i64 2, i64 0
123
124  %cmp = call i32 @strcmp(i8* %q, i8* %p)
125  ret i32 %cmp
126}
127