xref: /llvm-project/llvm/test/Transforms/InstCombine/wcslen-5.ll (revision 23a239267e8a1d20ed10d3545feaf2a2bb70b085)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Verify that wcslen calls with conditional expressions involving constant
3; string arguments with nonconstant offsets are folded as expected.  See
4; strlen-4.ll for the corresponding strlen test.
5;
6; RUN: opt < %s -passes=instcombine -S | FileCheck %s
7
8declare i64 @wcslen(ptr)
9
10!0 = !{i32 1, !"wchar_size", i32 4}
11!llvm.module.flags = !{!0}
12
13@ws3 = constant [4 x i32] [i32 1, i32 2, i32 3, i32 0]
14@ws5 = constant [6 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 0]
15@ws5_3 = constant [10 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 0, i32 6, i32 7, i32 8, i32 0]
16
17
18; Fold wcslen (x ? s3 + i: s5) to x ? 3 - i : 5.
19
20define dso_local i64 @fold_wcslen_s3_pi_s5(i1 zeroext %0, i64 %1) {
21; CHECK-LABEL: @fold_wcslen_s3_pi_s5(
22; CHECK-NEXT:    [[PS3_PI:%.*]] = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 [[TMP1:%.*]]
23; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr [[PS3_PI]], ptr @ws5
24; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]])
25; CHECK-NEXT:    ret i64 [[LEN]]
26;
27
28  %ps3_pi = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 %1
29  %sel = select i1 %0, ptr %ps3_pi, ptr @ws5
30  %len = tail call i64 @wcslen(ptr %sel)
31  ret i64 %len
32}
33
34
35; More complex expressions like the one below are not handled yet.
36; Fold: wcslen (x ? s3 + i + 1 : s5 + j + 2) to x ? 2 - i : 3 - j.
37
38define dso_local i64 @fold_wcslen_s3_pi_p1_s5(i1 zeroext %0, i64 %1) {
39; XFAIL-CHECK-LABEL: @fold_wcslen_s3_pi_p1_s5(
40; XFAIL-CHECK-NEXT:    [[DIF_I:%.*]] = sub i64 2, %1
41; XFAIL-CHECK-NEXT:    [[SEL:%.*]] = select i1 %0, i64 [[DIF_I]], i64 5
42; XFAIL-CHECK-NEXT:    ret i64 [[SEL]]
43; CHECK-LABEL: @fold_wcslen_s3_pi_p1_s5(
44; CHECK-NEXT:    [[PS3_PI:%.*]] = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 [[TMP1:%.*]]
45; CHECK-NEXT:    [[PS3_PI_P1:%.*]] = getelementptr inbounds nuw i8, ptr [[PS3_PI]], i64 4
46; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr [[PS3_PI_P1]], ptr @ws5
47; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]])
48; CHECK-NEXT:    ret i64 [[LEN]]
49;
50
51  %ps3_pi = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 %1
52  %ps3_pi_p1 = getelementptr inbounds i32, ptr %ps3_pi, i64 1
53  %sel = select i1 %0, ptr %ps3_pi_p1, ptr @ws5
54  %len = tail call i64 @wcslen(ptr %sel)
55  ret i64 %len
56}
57
58
59; Avoid folding calls with conditional expressions involving constant
60; string arguments with embedded nuls such as:
61;   wcslen (x ? s5_3 + i : s5).
62
63define dso_local i64 @call_wcslen_s5_3_pi_s5(i1 zeroext %0, i64 %1) {
64; CHECK-LABEL: @call_wcslen_s5_3_pi_s5(
65; CHECK-NEXT:    [[PS5_3_PI:%.*]] = getelementptr inbounds [10 x i32], ptr @ws5_3, i64 0, i64 [[TMP1:%.*]]
66; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr [[PS5_3_PI]], ptr @ws5
67; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]])
68; CHECK-NEXT:    ret i64 [[LEN]]
69;
70
71  %ps5_3_pi = getelementptr inbounds [10 x i32], ptr @ws5_3, i64 0, i64 %1
72  %sel = select i1 %0, ptr %ps5_3_pi, ptr @ws5
73  %len = tail call i64 @wcslen(ptr %sel)
74  ret i64 %len
75}
76
77
78; But do fold wcslen (x ? s5_3 : s5 + j) to x ? 5 : 5 - j.
79
80define dso_local i64 @call_wcslen_s5_3_s5_pj(i1 zeroext %0, i64 %1) {
81; CHECK-LABEL: @call_wcslen_s5_3_s5_pj(
82; CHECK-NEXT:    [[PS5:%.*]] = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 [[TMP1:%.*]]
83; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr @ws5_3, ptr [[PS5]]
84; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]])
85; CHECK-NEXT:    ret i64 [[LEN]]
86;
87
88  %ps5 = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 %1
89  %sel = select i1 %0, ptr @ws5_3, ptr %ps5
90  %len = tail call i64 @wcslen(ptr %sel)
91  ret i64 %len
92}
93
94
95; Fold wcslen (x ? s3: s5 + j) to x ? 3 : 5 - j.
96
97define dso_local i64 @fold_wcslen_s3_s5_pj(i1 zeroext %0, i64 %1) {
98; CHECK-LABEL: @fold_wcslen_s3_s5_pj(
99; CHECK-NEXT:    [[PS5_PJ:%.*]] = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 [[TMP1:%.*]]
100; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr @ws3, ptr [[PS5_PJ]]
101; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]])
102; CHECK-NEXT:    ret i64 [[LEN]]
103;
104
105  %ps5_pj = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 %1
106  %sel = select i1 %0, ptr @ws3, ptr %ps5_pj
107  %len = tail call i64 @wcslen(ptr %sel)
108  ret i64 %len
109}
110
111
112; Same as above, avoid folding calls with conditional expressions involving
113; constant string arguments with embedded nuls such as:
114;   wcslen (x ? s3 : s5_3 + j).
115
116define dso_local i64 @call_wcslen_s3_s5_3_pj(i1 zeroext %0, i64 %1) {
117; CHECK-LABEL: @call_wcslen_s3_s5_3_pj(
118; CHECK-NEXT:    [[PS5_3_PJ:%.*]] = getelementptr inbounds [10 x i32], ptr @ws5_3, i64 0, i64 [[TMP1:%.*]]
119; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr @ws3, ptr [[PS5_3_PJ]]
120; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]])
121; CHECK-NEXT:    ret i64 [[LEN]]
122;
123
124  %ps5_3_pj = getelementptr inbounds [10 x i32], ptr @ws5_3, i64 0, i64 %1
125  %sel = select i1 %0, ptr @ws3, ptr %ps5_3_pj
126  %len = tail call i64 @wcslen(ptr %sel)
127  ret i64 %len
128}
129
130
131; Fold wcslen (x ? s3 + i: s5 + j) to x ? 3 - i : 5 - j.
132
133define dso_local i64 @fold_wcslen_s3_pi_s5_pj(i1 zeroext %0, i64 %1, i64 %2) {
134; CHECK-LABEL: @fold_wcslen_s3_pi_s5_pj(
135; CHECK-NEXT:    [[PS3_PI:%.*]] = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 [[TMP1:%.*]]
136; CHECK-NEXT:    [[PS5_PJ:%.*]] = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 [[TMP2:%.*]]
137; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP0:%.*]], ptr [[PS3_PI]], ptr [[PS5_PJ]]
138; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull [[SEL]])
139; CHECK-NEXT:    ret i64 [[LEN]]
140;
141
142  %ps3_pi = getelementptr inbounds [4 x i32], ptr @ws3, i64 0, i64 %1
143  %ps5_pj = getelementptr inbounds [6 x i32], ptr @ws5, i64 0, i64 %2
144  %sel = select i1 %0, ptr %ps3_pi, ptr %ps5_pj
145  %len = tail call i64 @wcslen(ptr %sel)
146  ret i64 %len
147}
148