1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Test that the printf 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-prefix=CHECK-IPRINTF
6
7target 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"
8
9@hello_world = constant [13 x i8] c"hello world\0A\00"
10@h = constant [2 x i8] c"h\00"
11@h2 = constant [3 x i8] c"%%\00"
12@percent = constant [2 x i8] c"%\00"
13@percent_c = constant [3 x i8] c"%c\00"
14@percent_d = constant [3 x i8] c"%d\00"
15@percent_f = constant [3 x i8] c"%f\00"
16@percent_s = constant [4 x i8] c"%s\0A\00"
17@empty = constant [1 x i8] c"\00"
18; CHECK: [[$STR:@[a-z0-9]+]] = private unnamed_addr constant [12 x i8] c"hello world\00", align 1
19
20declare i32 @printf(i8*, ...)
21
22; Check printf("") -> noop.
23
24define void @test_simplify1() {
25; CHECK-LABEL: @test_simplify1(
26; CHECK-NEXT:    ret void
27;
28; CHECK-IPRINTF-LABEL: @test_simplify1(
29; CHECK-IPRINTF-NEXT:    ret void
30;
31  %fmt = getelementptr [1 x i8], [1 x i8]* @empty, i32 0, i32 0
32  call i32 (i8*, ...) @printf(i8* %fmt)
33  ret void
34}
35
36; Check printf("x") -> putchar('x'), even for '%'.
37
38define void @test_simplify2() {
39; CHECK-LABEL: @test_simplify2(
40; CHECK-NEXT:    [[PUTCHAR:%.*]] = call i32 @putchar(i32 104)
41; CHECK-NEXT:    ret void
42;
43; CHECK-IPRINTF-LABEL: @test_simplify2(
44; CHECK-IPRINTF-NEXT:    [[PUTCHAR:%.*]] = call i32 @putchar(i32 104)
45; CHECK-IPRINTF-NEXT:    ret void
46;
47  %fmt = getelementptr [2 x i8], [2 x i8]* @h, i32 0, i32 0
48  call i32 (i8*, ...) @printf(i8* %fmt)
49  ret void
50}
51
52; Special case: printf("%%") -> putchar('%').
53
54define void @test_simplify2b() {
55; CHECK-LABEL: @test_simplify2b(
56; CHECK-NEXT:    [[PUTCHAR:%.*]] = call i32 @putchar(i32 37)
57; CHECK-NEXT:    ret void
58;
59; CHECK-IPRINTF-LABEL: @test_simplify2b(
60; CHECK-IPRINTF-NEXT:    [[PUTCHAR:%.*]] = call i32 @putchar(i32 37)
61; CHECK-IPRINTF-NEXT:    ret void
62;
63  %fmt = getelementptr [3 x i8], [3 x i8]* @h2, i32 0, i32 0
64  call i32 (i8*, ...) @printf(i8* %fmt)
65  ret void
66}
67
68define void @test_simplify3() {
69; CHECK-LABEL: @test_simplify3(
70; CHECK-NEXT:    [[PUTCHAR:%.*]] = call i32 @putchar(i32 37)
71; CHECK-NEXT:    ret void
72;
73; CHECK-IPRINTF-LABEL: @test_simplify3(
74; CHECK-IPRINTF-NEXT:    [[PUTCHAR:%.*]] = call i32 @putchar(i32 37)
75; CHECK-IPRINTF-NEXT:    ret void
76;
77  %fmt = getelementptr [2 x i8], [2 x i8]* @percent, i32 0, i32 0
78  call i32 (i8*, ...) @printf(i8* %fmt)
79  ret void
80}
81
82; Check printf("foo\n") -> puts("foo").
83
84define void @test_simplify4() {
85; CHECK-LABEL: @test_simplify4(
86; CHECK-NEXT:    [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @str, i32 0, i32 0))
87; CHECK-NEXT:    ret void
88;
89; CHECK-IPRINTF-LABEL: @test_simplify4(
90; CHECK-IPRINTF-NEXT:    [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @str, i32 0, i32 0))
91; CHECK-IPRINTF-NEXT:    ret void
92;
93  %fmt = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0
94  call i32 (i8*, ...) @printf(i8* %fmt)
95  ret void
96}
97
98; Check printf("%c", chr) -> putchar(chr).
99
100define void @test_simplify5() {
101; CHECK-LABEL: @test_simplify5(
102; CHECK-NEXT:    [[PUTCHAR:%.*]] = call i32 @putchar(i32 104)
103; CHECK-NEXT:    ret void
104;
105; CHECK-IPRINTF-LABEL: @test_simplify5(
106; CHECK-IPRINTF-NEXT:    [[PUTCHAR:%.*]] = call i32 @putchar(i32 104)
107; CHECK-IPRINTF-NEXT:    ret void
108;
109  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_c, i32 0, i32 0
110  call i32 (i8*, ...) @printf(i8* %fmt, i8 104)
111  ret void
112}
113
114; Check printf("%s\n", str) -> puts(str).
115
116define void @test_simplify6() {
117; CHECK-LABEL: @test_simplify6(
118; CHECK-NEXT:    [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0))
119; CHECK-NEXT:    ret void
120;
121; CHECK-IPRINTF-LABEL: @test_simplify6(
122; CHECK-IPRINTF-NEXT:    [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0))
123; CHECK-IPRINTF-NEXT:    ret void
124;
125  %fmt = getelementptr [4 x i8], [4 x i8]* @percent_s, i32 0, i32 0
126  %str = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0
127  call i32 (i8*, ...) @printf(i8* %fmt, i8* %str)
128  ret void
129}
130
131; Check printf(format, ...) -> iprintf(format, ...) if no floating point.
132
133define void @test_simplify7() {
134; CHECK-LABEL: @test_simplify7(
135; CHECK-NEXT:    [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187)
136; CHECK-NEXT:    ret void
137;
138; CHECK-IPRINTF-LABEL: @test_simplify7(
139; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = call i32 (i8*, ...) @iprintf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187)
140; CHECK-IPRINTF-NEXT:    ret void
141;
142  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_d, i32 0, i32 0
143  call i32 (i8*, ...) @printf(i8* %fmt, i32 187)
144  ret void
145}
146
147define void @test_no_simplify1() {
148; CHECK-LABEL: @test_no_simplify1(
149; CHECK-NEXT:    [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00)
150; CHECK-NEXT:    ret void
151;
152; CHECK-IPRINTF-LABEL: @test_no_simplify1(
153; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00)
154; CHECK-IPRINTF-NEXT:    ret void
155;
156  %fmt = getelementptr [3 x i8], [3 x i8]* @percent_f, i32 0, i32 0
157  call i32 (i8*, ...) @printf(i8* %fmt, double 1.87)
158  ret void
159}
160
161define void @test_no_simplify2(i8* %fmt, double %d) {
162; CHECK-LABEL: @test_no_simplify2(
163; CHECK-NEXT:    [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]])
164; CHECK-NEXT:    ret void
165;
166; CHECK-IPRINTF-LABEL: @test_no_simplify2(
167; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]])
168; CHECK-IPRINTF-NEXT:    ret void
169;
170  call i32 (i8*, ...) @printf(i8* %fmt, double %d)
171  ret void
172}
173
174define i32 @test_no_simplify3() {
175; CHECK-LABEL: @test_no_simplify3(
176; CHECK-NEXT:    [[RET:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([2 x i8], [2 x i8]* @h, i32 0, i32 0))
177; CHECK-NEXT:    ret i32 [[RET]]
178;
179; CHECK-IPRINTF-LABEL: @test_no_simplify3(
180; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = call i32 (i8*, ...) @iprintf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @h, i32 0, i32 0))
181; CHECK-IPRINTF-NEXT:    ret i32 [[TMP1]]
182;
183  %fmt = getelementptr [2 x i8], [2 x i8]* @h, i32 0, i32 0
184  %ret = call i32 (i8*, ...) @printf(i8* %fmt)
185  ret i32 %ret
186}
187