• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Test that the sprintf library call simplifier works correctly.
3;
4; RUN: opt < %s -instcombine -S | FileCheck %s
5; RUN: opt < %s -mtriple xcore-xmos-elf -instcombine -S | FileCheck %s -check-prefixes=CHECK,CHECK-IPRINTF
6; RUN: opt < %s -mtriple=i386-pc-windows-msvc -instcombine -S | FileCheck %s --check-prefixes=CHECK,WIN
7
8target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
9
10@hello_world = constant [13 x i8] c"hello world\0A\00"
11@null = constant [1 x i8] zeroinitializer
12@null_hello = constant [7 x i8] c"\00hello\00"
13@h = constant [2 x i8] c"h\00"
14@percent_c = constant [3 x i8] c"%c\00"
15@percent_d = constant [3 x i8] c"%d\00"
16@percent_f = constant [3 x i8] c"%f\00"
17@percent_s = constant [3 x i8] c"%s\00"
18
19declare i32 @sprintf(i8*, i8*, ...)
20
21; Check sprintf(dst, fmt) -> llvm.memcpy(str, fmt, strlen(fmt) + 1, 1).
22
23define void @test_simplify1(i8* %dst) {
24; CHECK-LABEL: @test_simplify1(
25; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(13) [[DST:%.*]], i8* nonnull align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false)
26; CHECK-NEXT:    ret void
27;
28  %fmt = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0
29  call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt)
30  ret void
31}
32
33define void @test_simplify2(i8* %dst) {
34; CHECK-LABEL: @test_simplify2(
35; CHECK-NEXT:    store i8 0, i8* [[DST:%.*]], align 1
36; CHECK-NEXT:    ret void
37;
38  %fmt = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0
39  call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt)
40  ret void
41}
42
43define void @test_simplify3(i8* %dst) {
44; CHECK-LABEL: @test_simplify3(
45; CHECK-NEXT:    store i8 0, i8* [[DST:%.*]], align 1
46; CHECK-NEXT:    ret void
47;
48  %fmt = getelementptr [7 x i8], [7 x i8]* @null_hello, i32 0, i32 0
49  call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt)
50  ret void
51}
52
53; Check sprintf(dst, "%c", chr) -> *(i8*)dst = chr; *((i8*)dst + 1) = 0.
54
55define void @test_simplify4(i8* %dst) {
56; CHECK-LABEL: @test_simplify4(
57; CHECK-NEXT:    store i8 104, i8* [[DST:%.*]], align 1
58; CHECK-NEXT:    [[NUL:%.*]] = getelementptr i8, i8* [[DST]], i32 1
59; CHECK-NEXT:    store i8 0, i8* [[NUL]], align 1
60; CHECK-NEXT:    ret void
61;
62  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_c, i32 0, i32 0
63  call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i8 104)
64  ret void
65}
66
67; Check sprintf(dst, "%s", str) -> strcpy(dst, "%s", str) if result is unused.
68
69define void @test_simplify5(i8* %dst, i8* %str) {
70; CHECK-LABEL: @test_simplify5(
71; CHECK-NEXT:    [[STRCPY:%.*]] = call i8* @strcpy(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* nonnull dereferenceable(1) [[STR:%.*]])
72; CHECK-NEXT:    ret void
73;
74  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_s, i32 0, i32 0
75  call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i8* %str)
76  ret void
77}
78
79; Check sprintf(dst, format, ...) -> siprintf(str, format, ...) if no floating.
80
81define void @test_simplify6(i8* %dst) {
82; CHECK-IPRINTF-LABEL: @test_simplify6(
83; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @siprintf(i8* [[DST:%.*]], i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187)
84; CHECK-IPRINTF-NEXT:    ret void
85;
86; WIN-LABEL: @test_simplify6(
87; WIN-NEXT:    [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187)
88; WIN-NEXT:    ret void
89;
90  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_d, i32 0, i32 0
91  call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i32 187)
92  ret void
93}
94
95; Check sprintf(dst, "%s", str) -> llvm.memcpy(dest, str, strlen(str) + 1, 1).
96
97define i32 @test_simplify7(i8* %dst, i8* %str) {
98; CHECK-IPRINTF-LABEL: @test_simplify7(
99; CHECK-IPRINTF-NEXT:    [[STPCPY:%.*]] = call i8* @stpcpy(i8* [[DST:%.*]], i8* [[STR:%.*]])
100; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = ptrtoint i8* [[STPCPY]] to i32
101; CHECK-IPRINTF-NEXT:    [[TMP2:%.*]] = ptrtoint i8* [[DST]] to i32
102; CHECK-IPRINTF-NEXT:    [[TMP3:%.*]] = sub i32 [[TMP1]], [[TMP2]]
103; CHECK-IPRINTF-NEXT:    ret i32 [[TMP3]]
104;
105; WIN-LABEL: @test_simplify7(
106; WIN-NEXT:    [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) [[STR:%.*]])
107; WIN-NEXT:    [[LENINC:%.*]] = add i32 [[STRLEN]], 1
108; WIN-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[DST:%.*]], i8* align 1 [[STR]], i32 [[LENINC]], i1 false)
109; WIN-NEXT:    ret i32 [[STRLEN]]
110;
111  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_s, i32 0, i32 0
112  %r = call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i8* %str)
113  ret i32 %r
114}
115
116; Check sprintf(dst, "%s", str) -> llvm.memcpy(dest, str, strlen(str) + 1, 1).
117define i32 @test_simplify8(i8* %dst) {
118; CHECK-LABEL: @test_simplify8(
119; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(13) [[DST:%.*]], i8* nonnull align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false)
120; CHECK-NEXT:    ret i32 12
121;
122  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_s, i32 0, i32 0
123  %str = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0
124  %r = call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i8* %str)
125  ret i32 %r
126}
127
128; Check sprintf(dst, "%s", str) -> stpcpy(dest, str) - dest
129
130define i32 @test_simplify9(i8* %dst, i8* %str) {
131; CHECK-IPRINTF-LABEL: @test_simplify9(
132; CHECK-IPRINTF-NEXT:    [[STPCPY:%.*]] = call i8* @stpcpy(i8* [[DST:%.*]], i8* [[STR:%.*]])
133; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = ptrtoint i8* [[STPCPY]] to i32
134; CHECK-IPRINTF-NEXT:    [[TMP2:%.*]] = ptrtoint i8* [[DST]] to i32
135; CHECK-IPRINTF-NEXT:    [[TMP3:%.*]] = sub i32 [[TMP1]], [[TMP2]]
136; CHECK-IPRINTF-NEXT:    ret i32 [[TMP3]]
137;
138; WIN-LABEL: @test_simplify9(
139; WIN-NEXT:    [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) [[STR:%.*]])
140; WIN-NEXT:    [[LENINC:%.*]] = add i32 [[STRLEN]], 1
141; WIN-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[DST:%.*]], i8* align 1 [[STR]], i32 [[LENINC]], i1 false)
142; WIN-NEXT:    ret i32 [[STRLEN]]
143;
144  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_s, i32 0, i32 0
145  %r = call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i8* %str)
146  ret i32 %r
147}
148
149define void @test_no_simplify1(i8* %dst) {
150; CHECK-LABEL: @test_no_simplify1(
151; CHECK-NEXT:    [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00)
152; CHECK-NEXT:    ret void
153;
154  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_f, i32 0, i32 0
155  call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, double 1.87)
156  ret void
157}
158
159define void @test_no_simplify2(i8* %dst, i8* %fmt, double %d) {
160; CHECK-LABEL: @test_no_simplify2(
161; CHECK-NEXT:    [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]])
162; CHECK-NEXT:    ret void
163;
164  call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, double %d)
165  ret void
166}
167
168define i32 @test_no_simplify3(i8* %dst, i8* %str) minsize {
169; CHECK-IPRINTF-LABEL: @test_no_simplify3(
170; CHECK-IPRINTF-NEXT:    [[STPCPY:%.*]] = call i8* @stpcpy(i8* [[DST:%.*]], i8* [[STR:%.*]])
171; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = ptrtoint i8* [[STPCPY]] to i32
172; CHECK-IPRINTF-NEXT:    [[TMP2:%.*]] = ptrtoint i8* [[DST]] to i32
173; CHECK-IPRINTF-NEXT:    [[TMP3:%.*]] = sub i32 [[TMP1]], [[TMP2]]
174; CHECK-IPRINTF-NEXT:    ret i32 [[TMP3]]
175;
176; WIN-LABEL: @test_no_simplify3(
177; WIN-NEXT:    [[R:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_s, i32 0, i32 0), i8* [[STR:%.*]])
178; WIN-NEXT:    ret i32 [[R]]
179;
180  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_s, i32 0, i32 0
181  %r = call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i8* %str)
182  ret i32 %r
183}
184