[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / wcslen-3.ll
blob9fd94752c81ea351f71e4bb92330bcad962670b9
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)
28   ret i64 %hello_l
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)
37   ret i64 %null_l
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)
46   ret i64 %null_hello_l
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
54   ret i64 %len
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
66   ret i1 %eq_hello
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
77   ret i1 %eq_null
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
89   ret i1 %ne_hello
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
100   ret i1 %ne_null
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)
112   ret i64 %l
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)
126   ret i64 %hello_l
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]]
138   %and = and i16 %x, 7
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)
141   ret i64 %hello_l
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)
153   ret i64 %a_l
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)
167   ret i64 %hello_l
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)
183   ret i64 %hello_l
186 @str32 = constant [1 x i32] [i32 0]
188 ; This could in principle be simplified, but the current implementation bails on
189 ; type mismatches.
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*))
196   ret i64 %l