blob: 77eb9188138cd9b8d9fb44f0bf9c004a291cf24a [file] [log] [blame]
David Bolvanskyca22d422018-05-16 11:39:52 +00001; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
3
4%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
5%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }
6
7@.str = private unnamed_addr constant [5 x i8] c"file\00", align 1
8@.str.1 = private unnamed_addr constant [2 x i8] c"w\00", align 1
9@.str.2 = private unnamed_addr constant [4 x i8] c"str\00", align 1
10@global_file = common global %struct._IO_FILE* null, align 8
11
12define void @external_fgetc_test(%struct._IO_FILE* %f) {
13; CHECK-LABEL: @external_fgetc_test(
14; CHECK-NEXT: [[CALL:%.*]] = call i32 @fgetc(%struct._IO_FILE* [[F:%.*]])
15; CHECK-NEXT: ret void
16;
17 %call = call i32 @fgetc(%struct._IO_FILE* %f)
18 ret void
19}
20
21declare i32 @fgetc(%struct._IO_FILE* nocapture) #0
22
23define void @external_fgetc_test2() {
24; CHECK-LABEL: @external_fgetc_test2(
25; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
26; CHECK-NEXT: [[FPUTC_UNLOCKED:%.*]] = call i32 @fputc_unlocked(i32 99, %struct._IO_FILE* [[CALL]])
27; CHECK-NEXT: ret void
28;
29 %call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
30 %call1 = call i32 @fputc(i32 99, %struct._IO_FILE* %call)
31 ret void
32}
33
34declare %struct._IO_FILE* @fopen(i8*, i8*)
35declare i32 @fputc(i32, %struct._IO_FILE* nocapture) #0
36
37define internal void @fgetc_test() {
38; CHECK-LABEL: @fgetc_test(
39; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
40; CHECK-NEXT: [[FGETC_UNLOCKED:%.*]] = call i32 @fgetc_unlocked(%struct._IO_FILE* [[CALL]])
41; CHECK-NEXT: ret void
42;
43 %call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
44 %call1 = call i32 @fgetc(%struct._IO_FILE* %call)
45 ret void
46}
47
48define void @external_fgetc_internal_test() {
49; CHECK-LABEL: @external_fgetc_internal_test(
50; CHECK-NEXT: call void @fgetc_test()
51; CHECK-NEXT: ret void
52;
53 call void @fgetc_test()
54 ret void
55}
56
57define internal void @fwrite_test() {
58; CHECK-LABEL: @fwrite_test(
59; CHECK-NEXT: [[S:%.*]] = alloca [10 x i8], align 1
60; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
61; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], [10 x i8]* [[S]], i64 0, i64 0
62; CHECK-NEXT: [[TMP1:%.*]] = call i64 @fwrite_unlocked(i8* nonnull [[ARRAYDECAY]], i64 10, i64 10, %struct._IO_FILE* [[CALL]])
63; CHECK-NEXT: ret void
64;
65 %s = alloca [10 x i8], align 1
66 %call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
67 %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %s, i64 0, i64 0
68 %call1 = call i64 @fwrite(i8* nonnull %arraydecay, i64 10, i64 10, %struct._IO_FILE* %call)
69 ret void
70}
71
72define internal void @fread_test() {
73; CHECK-LABEL: @fread_test(
74; CHECK-NEXT: [[S:%.*]] = alloca [10 x i8], align 1
75; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
76; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], [10 x i8]* [[S]], i64 0, i64 0
77; CHECK-NEXT: [[TMP1:%.*]] = call i64 @fread_unlocked(i8* nonnull [[ARRAYDECAY]], i64 10, i64 10, %struct._IO_FILE* [[CALL]])
78; CHECK-NEXT: ret void
79;
80 %s = alloca [10 x i8], align 1
81 %call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
82 %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %s, i64 0, i64 0
83 %call1 = call i64 @fread(i8* nonnull %arraydecay, i64 10, i64 10, %struct._IO_FILE* %call)
84 ret void
85}
86
87define internal void @fputs_test() {
88; CHECK-LABEL: @fputs_test(
89; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
90; CHECK-NEXT: [[TMP1:%.*]] = call i64 @fwrite_unlocked(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), i64 3, i64 1, %struct._IO_FILE* [[CALL]])
91; CHECK-NEXT: ret void
92;
93 %call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
94 %call1 = call i32 @fputs(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), %struct._IO_FILE* %call)
95 ret void
96}
97
98define internal void @fgets_test() {
99; CHECK-LABEL: @fgets_test(
100; CHECK-NEXT: [[BUF:%.*]] = alloca [10 x i8], align 1
101; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
102; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], [10 x i8]* [[BUF]], i64 0, i64 0
Benjamin Kramer8ac15bf2018-05-16 21:45:39 +0000103; CHECK-NEXT: [[FGETS_UNLOCKED:%.*]] = call i8* @fgets_unlocked(i8* nonnull [[ARRAYDECAY]], i32 10, %struct._IO_FILE* [[CALL]])
David Bolvanskyca22d422018-05-16 11:39:52 +0000104; CHECK-NEXT: ret void
105;
106 %buf = alloca [10 x i8], align 1
107 %call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
108 %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %buf, i64 0, i64 0
109 %call1 = call i8* @fgets(i8* nonnull %arraydecay, i32 10, %struct._IO_FILE* %call)
110 ret void
111}
112
113define internal void @fputc_test() {
114; CHECK-LABEL: @fputc_test(
115; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
116; CHECK-NEXT: [[FPUTC_UNLOCKED:%.*]] = call i32 @fputc_unlocked(i32 99, %struct._IO_FILE* [[CALL]])
117; CHECK-NEXT: ret void
118;
119 %call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
120 %call1 = call i32 @fputc(i32 99, %struct._IO_FILE* %call)
121 ret void
122}
123
124define i32 @main() {
125; CHECK-LABEL: @main(
126; CHECK-NEXT: call void @fwrite_test()
127; CHECK-NEXT: call void @fread_test()
128; CHECK-NEXT: call void @fputs_test()
129; CHECK-NEXT: call void @fgets_test()
130; CHECK-NEXT: call void @fputc_test()
131; CHECK-NEXT: call void @fgetc_test()
132; CHECK-NEXT: ret i32 0
133;
134 call void @fwrite_test()
135 call void @fread_test()
136 call void @fputs_test()
137 call void @fgets_test()
138 call void @fputc_test()
139 call void @fgetc_test()
140 ret i32 0
141}
142
143declare i32 @fclose(%struct._IO_FILE* nocapture)
144
145define void @test_with_fclose() {
146; CHECK-LABEL: @test_with_fclose(
147; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
148; CHECK-NEXT: [[TMP1:%.*]] = call i64 @fwrite_unlocked(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), i64 3, i64 1, %struct._IO_FILE* [[CALL]])
149; CHECK-NEXT: [[CALL2:%.*]] = call i32 @fclose(%struct._IO_FILE* [[CALL]])
150; CHECK-NEXT: ret void
151;
152 %call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0)) #2
153 %call1 = call i64 @fwrite(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), i64 3, i64 1, %struct._IO_FILE* %call)
154 %call2 = call i32 @fclose(%struct._IO_FILE* %call) #2
155 ret void
156}
157
158declare void @modify_file(%struct._IO_FILE*)
159
160define void @test_captured_by_function(){
161; CHECK-LABEL: @test_captured_by_function(
162; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
163; CHECK-NEXT: call void @modify_file(%struct._IO_FILE* [[CALL]])
164; CHECK-NEXT: [[CALL1:%.*]] = call i64 @fwrite(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), i64 3, i64 1, %struct._IO_FILE* [[CALL]])
165; CHECK-NEXT: [[CALL2:%.*]] = call i32 @fclose(%struct._IO_FILE* [[CALL]])
166; CHECK-NEXT: ret void
167;
168 %call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0)) #2
169 call void @modify_file(%struct._IO_FILE* %call) #2
170 %call1 = call i64 @fwrite(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), i64 3, i64 1, %struct._IO_FILE* %call)
171 %call2 = call i32 @fclose(%struct._IO_FILE* %call) #2
172 ret void
173}
174
175define void @test_captured_by_global_value() {
176; CHECK-LABEL: @test_captured_by_global_value(
177; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
178; CHECK-NEXT: [[DOTCAST:%.*]] = ptrtoint %struct._IO_FILE* [[CALL]] to i64
179; CHECK-NEXT: store i64 [[DOTCAST]], i64* bitcast (%struct._IO_FILE** @global_file to i64*), align 8
180; CHECK-NEXT: [[CALL1:%.*]] = call i64 @fwrite(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), i64 3, i64 1, %struct._IO_FILE* [[CALL]])
181; CHECK-NEXT: [[CALL2:%.*]] = call i32 @fclose(%struct._IO_FILE* [[CALL]])
182; CHECK-NEXT: ret void
183;
184 %call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0)) #2
185 %.cast = ptrtoint %struct._IO_FILE* %call to i64
186 store i64 %.cast, i64* bitcast (%struct._IO_FILE** @global_file to i64*), align 8
187 %call1 = call i64 @fwrite(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), i64 3, i64 1, %struct._IO_FILE* %call)
188 %call2 = call i32 @fclose(%struct._IO_FILE* %call) #2
189 ret void
190}
191
192
193
194declare i64 @fwrite(i8* nocapture, i64, i64, %struct._IO_FILE* nocapture) #0
195declare i64 @fread(i8* nocapture, i64, i64, %struct._IO_FILE* nocapture) #0
196declare i32 @fputs(i8* nocapture readonly, %struct._IO_FILE* nocapture) #0
197declare i8* @fgets(i8*, i32, %struct._IO_FILE* nocapture) #0