xref: /llvm-project/llvm/test/Transforms/InstCombine/snprintf.ll (revision 462cb3cd6cecd0511ecaf0e3ebcaba455ece587d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4@.str = private unnamed_addr constant [4 x i8] c"str\00", align 1
5@.str.1 = private unnamed_addr constant [3 x i8] c"%%\00", align 1
6@.str.2 = private unnamed_addr constant [3 x i8] c"%c\00", align 1
7@.str.3 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
8@.str.4 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
9
10
11declare i32 @snprintf(ptr, i64, ptr, ...) #1
12
13define void @test_not_const_fmt(ptr %buf, ptr %fmt) #0 {
14; CHECK-LABEL: @test_not_const_fmt(
15; CHECK-NEXT:    [[CALL:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[BUF:%.*]], i64 32, ptr [[FMT:%.*]])
16; CHECK-NEXT:    ret void
17;
18  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 32, ptr %fmt) #2
19  ret void
20}
21
22; size is '0', do not add nonnull attribute
23define void @test_not_const_fmt_zero_size_return_value(ptr %buf, ptr %fmt) #0 {
24; CHECK-LABEL: @test_not_const_fmt_zero_size_return_value(
25; CHECK-NEXT:    [[CALL:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[BUF:%.*]], i64 0, ptr [[FMT:%.*]])
26; CHECK-NEXT:    ret void
27;
28  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 0, ptr %fmt) #2
29  ret void
30}
31
32define void @test_not_const_size(ptr %buf, i64 %size) #0 {
33; CHECK-LABEL: @test_not_const_size(
34; CHECK-NEXT:    [[CALL:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[BUF:%.*]], i64 [[SIZE:%.*]], ptr nonnull @.str)
35; CHECK-NEXT:    ret void
36;
37  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 %size, ptr @.str) #2
38  ret void
39}
40
41
42define i32 @test_return_value(ptr %buf) #0 {
43; CHECK-LABEL: @test_return_value(
44; CHECK-NEXT:    ret i32 3
45;
46  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 0, ptr @.str) #2
47  ret i32 %call
48}
49
50define void @test_percentage(ptr %buf) #0 {
51; CHECK-LABEL: @test_percentage(
52; CHECK-NEXT:    [[CALL:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[BUF:%.*]], i64 32, ptr nonnull @.str.1)
53; CHECK-NEXT:    ret void
54;
55  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 32, ptr @.str.1) #2
56  ret void
57}
58
59define i32 @test_null_buf_return_value() #0 {
60; CHECK-LABEL: @test_null_buf_return_value(
61; CHECK-NEXT:    ret i32 3
62;
63  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str) #2
64  ret i32 %call
65}
66
67define i32 @test_percentage_return_value() #0 {
68; CHECK-LABEL: @test_percentage_return_value(
69; CHECK-NEXT:    [[CALL:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr nonnull @.str.1)
70; CHECK-NEXT:    ret i32 [[CALL]]
71;
72  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str.1) #3
73  ret i32 %call
74}
75
76
77define void @test_correct_copy(ptr %buf) #0 {
78; CHECK-LABEL: @test_correct_copy(
79; CHECK-NEXT:    store i32 7500915, ptr [[BUF:%.*]], align 1
80; CHECK-NEXT:    ret void
81;
82  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 32, ptr @.str) #2
83  ret void
84}
85
86define i32 @test_char_zero_size(ptr %buf) #0 {
87; CHECK-LABEL: @test_char_zero_size(
88; CHECK-NEXT:    ret i32 1
89;
90  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 0, ptr @.str.2, i32 65) #2
91  ret i32 %call
92}
93
94define i32 @test_char_small_size(ptr %buf) #0 {
95; CHECK-LABEL: @test_char_small_size(
96; CHECK-NEXT:    store i8 0, ptr [[BUF:%.*]], align 1
97; CHECK-NEXT:    ret i32 1
98;
99  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 1, ptr @.str.2, i32 65) #2
100  ret i32 %call
101}
102
103define i32 @test_char_ok_size(ptr %buf) #0 {
104; CHECK-LABEL: @test_char_ok_size(
105; CHECK-NEXT:    store i8 65, ptr [[BUF:%.*]], align 1
106; CHECK-NEXT:    [[NUL:%.*]] = getelementptr inbounds nuw i8, ptr [[BUF]], i64 1
107; CHECK-NEXT:    store i8 0, ptr [[NUL]], align 1
108; CHECK-NEXT:    ret i32 1
109;
110  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 32, ptr @.str.2, i32 65) #2
111  ret i32 %call
112}
113
114define i32 @test_str_zero_size(ptr %buf) #0 {
115; CHECK-LABEL: @test_str_zero_size(
116; CHECK-NEXT:    ret i32 3
117;
118  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 0, ptr @.str.3, ptr @.str) #2
119  ret i32 %call
120}
121
122define i32 @test_str_small_size(ptr %buf) #0 {
123; CHECK-LABEL: @test_str_small_size(
124; CHECK-NEXT:    store i8 0, ptr [[BUF:%.*]], align 1
125; CHECK-NEXT:    ret i32 3
126;
127  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 1, ptr @.str.3, ptr @.str) #2
128  ret i32 %call
129}
130
131define i32 @test_str_ok_size(ptr %buf) #0 {
132; CHECK-LABEL: @test_str_ok_size(
133; CHECK-NEXT:    store i32 7500915, ptr [[BUF:%.*]], align 1
134; CHECK-NEXT:    ret i32 3
135;
136  %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 32, ptr @.str.3, ptr @.str) #2
137  ret i32 %call
138}
139
140; snprintf(buf, 32, "") -> memcpy -> store
141define i32 @test_str_ok_size_tail(ptr %buf) {
142; CHECK-LABEL: @test_str_ok_size_tail(
143; CHECK-NEXT:    store i8 0, ptr [[BUF:%.*]], align 1
144; CHECK-NEXT:    ret i32 0
145;
146  %1 = tail call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 8, ptr @.str.4)
147  ret i32 %1
148}
149
150define i32 @test_str_ok_size_musttail(ptr %buf, i64 %x, ptr %y, ...) {
151; CHECK-LABEL: @test_str_ok_size_musttail(
152; CHECK-NEXT:    [[TMP1:%.*]] = musttail call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[BUF:%.*]], i64 8, ptr nonnull @.str.4, ...)
153; CHECK-NEXT:    ret i32 [[TMP1]]
154;
155  %1 = musttail call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 8, ptr @.str.4, ...)
156  ret i32 %1
157}
158
159; snprintf(buf, 32, "%s", "str") -> memcpy -> store
160define i32 @test_str_ok_size_tail2(ptr %buf) {
161; CHECK-LABEL: @test_str_ok_size_tail2(
162; CHECK-NEXT:    store i32 7500915, ptr [[BUF:%.*]], align 1
163; CHECK-NEXT:    ret i32 3
164;
165  %1 = tail call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 8, ptr @.str.3, ptr @.str)
166  ret i32 %1
167}
168
169define i32 @test_str_ok_size_musttail2(ptr %buf, i64 %x, ptr %y, ...) {
170; CHECK-LABEL: @test_str_ok_size_musttail2(
171; CHECK-NEXT:    [[TMP1:%.*]] = musttail call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[BUF:%.*]], i64 8, ptr nonnull @.str.3, ptr nonnull @.str, ...)
172; CHECK-NEXT:    ret i32 [[TMP1]]
173;
174  %1 = musttail call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 8, ptr @.str.3, ptr @.str, ...)
175  ret i32 %1
176}
177