1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; Test that the wcslen library call simplifier works correctly.
4 ; RUN: opt < %s -instcombine -S | FileCheck %s
6 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
8 ; Test behavior for wchar_size==2
9 !llvm.module.flags = !{!0}
10 !0 = !{i32 1, !"wchar_size", i32 2}
12 declare i64 @wcslen(i16*)
14 @hello = constant [6 x i16] [i16 104, i16 101, i16 108, i16 108, i16 111, i16 0]
15 @longer = constant [7 x i16] [i16 108, i16 111, i16 110, i16 103, i16 101, i16 114, i16 0]
16 @null = constant [1 x i16] zeroinitializer
17 @null_hello = constant [7 x i16] [i16 0, i16 104, i16 101, i16 108, i16 108, i16 111, i16 0]
18 @nullstring = constant i16 0
19 @a = common global [32 x i16] zeroinitializer, align 1
20 @null_hello_mid = constant [13 x i16] [i16 104, i16 101, i16 108, i16 108, i16 111, i16 32, i16 119, i16 111, i16 114, i16 0, i16 108, i16 100, i16 0]
22 define i64 @test_simplify1() {
23 ; CHECK-LABEL: @test_simplify1(
24 ; CHECK-NEXT: ret i64 5
26 %hello_p = getelementptr [6 x i16], [6 x i16]* @hello, i64 0, i64 0
27 %hello_l = call i64 @wcslen(i16* %hello_p)
31 define i64 @test_simplify2() {
32 ; CHECK-LABEL: @test_simplify2(
33 ; CHECK-NEXT: ret i64 0
35 %null_p = getelementptr [1 x i16], [1 x i16]* @null, i64 0, i64 0
36 %null_l = call i64 @wcslen(i16* %null_p)
40 define i64 @test_simplify3() {
41 ; CHECK-LABEL: @test_simplify3(
42 ; CHECK-NEXT: ret i64 0
44 %null_hello_p = getelementptr [7 x i16], [7 x i16]* @null_hello, i64 0, i64 0
45 %null_hello_l = call i64 @wcslen(i16* %null_hello_p)
49 define i64 @test_simplify4() {
50 ; CHECK-LABEL: @test_simplify4(
51 ; CHECK-NEXT: ret i64 0
53 %len = tail call i64 @wcslen(i16* @nullstring) nounwind
57 ; Check wcslen(x) == 0 --> *x == 0.
59 define i1 @test_simplify5() {
60 ; CHECK-LABEL: @test_simplify5(
61 ; CHECK-NEXT: ret i1 false
63 %hello_p = getelementptr [6 x i16], [6 x i16]* @hello, i64 0, i64 0
64 %hello_l = call i64 @wcslen(i16* %hello_p)
65 %eq_hello = icmp eq i64 %hello_l, 0
69 define i1 @test_simplify6(i16* %str_p) {
70 ; CHECK-LABEL: @test_simplify6(
71 ; CHECK-NEXT: [[STRLENFIRST:%.*]] = load i16, i16* [[STR_P:%.*]], align 2
72 ; CHECK-NEXT: [[EQ_NULL:%.*]] = icmp eq i16 [[STRLENFIRST]], 0
73 ; CHECK-NEXT: ret i1 [[EQ_NULL]]
75 %str_l = call i64 @wcslen(i16* %str_p)
76 %eq_null = icmp eq i64 %str_l, 0
80 ; Check wcslen(x) != 0 --> *x != 0.
82 define i1 @test_simplify7() {
83 ; CHECK-LABEL: @test_simplify7(
84 ; CHECK-NEXT: ret i1 true
86 %hello_p = getelementptr [6 x i16], [6 x i16]* @hello, i64 0, i64 0
87 %hello_l = call i64 @wcslen(i16* %hello_p)
88 %ne_hello = icmp ne i64 %hello_l, 0
92 define i1 @test_simplify8(i16* %str_p) {
93 ; CHECK-LABEL: @test_simplify8(
94 ; CHECK-NEXT: [[STRLENFIRST:%.*]] = load i16, i16* [[STR_P:%.*]], align 2
95 ; CHECK-NEXT: [[NE_NULL:%.*]] = icmp ne i16 [[STRLENFIRST]], 0
96 ; CHECK-NEXT: ret i1 [[NE_NULL]]
98 %str_l = call i64 @wcslen(i16* %str_p)
99 %ne_null = icmp ne i64 %str_l, 0
103 define i64 @test_simplify9(i1 %x) {
104 ; CHECK-LABEL: @test_simplify9(
105 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i64 5, i64 6
106 ; CHECK-NEXT: ret i64 [[TMP1]]
108 %hello = getelementptr [6 x i16], [6 x i16]* @hello, i64 0, i64 0
109 %longer = getelementptr [7 x i16], [7 x i16]* @longer, i64 0, i64 0
110 %s = select i1 %x, i16* %hello, i16* %longer
111 %l = call i64 @wcslen(i16* %s)
115 ; Check the case that should be simplified to a sub instruction.
116 ; wcslen(@hello + x) --> 5 - x
118 define i64 @test_simplify10(i16 %x) {
119 ; CHECK-LABEL: @test_simplify10(
120 ; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i64
121 ; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i64 5, [[TMP1]]
122 ; CHECK-NEXT: ret i64 [[TMP2]]
124 %hello_p = getelementptr inbounds [6 x i16], [6 x i16]* @hello, i16 0, i16 %x
125 %hello_l = call i64 @wcslen(i16* %hello_p)
129 ; wcslen(@null_hello_mid + (x & 7)) --> 9 - (x & 7)
131 define i64 @test_simplify11(i16 %x) {
132 ; CHECK-LABEL: @test_simplify11(
133 ; CHECK-NEXT: [[AND:%.*]] = and i16 [[X:%.*]], 7
134 ; CHECK-NEXT: [[NARROW:%.*]] = sub nuw nsw i16 9, [[AND]]
135 ; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[NARROW]] to i64
136 ; CHECK-NEXT: ret i64 [[TMP1]]
139 %hello_p = getelementptr inbounds [13 x i16], [13 x i16]* @null_hello_mid, i16 0, i16 %and
140 %hello_l = call i64 @wcslen(i16* %hello_p)
144 ; Check cases that shouldn't be simplified.
146 define i64 @test_no_simplify1() {
147 ; CHECK-LABEL: @test_no_simplify1(
148 ; CHECK-NEXT: [[A_L:%.*]] = call i64 @wcslen(i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a, i64 0, i64 0))
149 ; CHECK-NEXT: ret i64 [[A_L]]
151 %a_p = getelementptr [32 x i16], [32 x i16]* @a, i64 0, i64 0
152 %a_l = call i64 @wcslen(i16* %a_p)
156 ; wcslen(@null_hello + x) should not be simplified to a sub instruction.
158 define i64 @test_no_simplify2(i16 %x) {
159 ; CHECK-LABEL: @test_no_simplify2(
160 ; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i64
161 ; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [7 x i16], [7 x i16]* @null_hello, i64 0, i64 [[TMP1]]
162 ; CHECK-NEXT: [[HELLO_L:%.*]] = call i64 @wcslen(i16* nonnull [[HELLO_P]])
163 ; CHECK-NEXT: ret i64 [[HELLO_L]]
165 %hello_p = getelementptr inbounds [7 x i16], [7 x i16]* @null_hello, i16 0, i16 %x
166 %hello_l = call i64 @wcslen(i16* %hello_p)
170 ; wcslen(@null_hello_mid + (x & 15)) should not be simplified to a sub instruction.
172 define i64 @test_no_simplify3(i16 %x) {
173 ; CHECK-LABEL: @test_no_simplify3(
174 ; CHECK-NEXT: [[AND:%.*]] = and i16 [[X:%.*]], 15
175 ; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[AND]] to i64
176 ; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [13 x i16], [13 x i16]* @null_hello_mid, i64 0, i64 [[TMP1]]
177 ; CHECK-NEXT: [[HELLO_L:%.*]] = call i64 @wcslen(i16* nonnull [[HELLO_P]])
178 ; CHECK-NEXT: ret i64 [[HELLO_L]]
180 %and = and i16 %x, 15
181 %hello_p = getelementptr inbounds [13 x i16], [13 x i16]* @null_hello_mid, i16 0, i16 %and
182 %hello_l = call i64 @wcslen(i16* %hello_p)
186 @str32 = constant [1 x i32] [i32 0]
188 ; This could in principle be simplified, but the current implementation bails on
190 define i64 @test_no_simplify4() {
191 ; CHECK-LABEL: @test_no_simplify4(
192 ; CHECK-NEXT: [[L:%.*]] = call i64 @wcslen(i16* bitcast ([1 x i32]* @str32 to i16*))
193 ; CHECK-NEXT: ret i64 [[L]]
195 %l = call i64 @wcslen(i16* bitcast ([1 x i32]* @str32 to i16*))