diff options
author | David Bolvansky <david.bolvansky@gmail.com> | 2018-05-16 11:39:52 +0000 |
---|---|---|
committer | David Bolvansky <david.bolvansky@gmail.com> | 2018-05-16 11:39:52 +0000 |
commit | ca22d427b94de946d4ef32b8acbdfb7e62e7cfa4 (patch) | |
tree | 01b8ba6b94791c2bcc898bcf34d39516a53dea10 /llvm/test/Transforms | |
parent | 5647e89f5a6369836b08212c14b8ff42db8e82d2 (diff) | |
download | bcm5719-llvm-ca22d427b94de946d4ef32b8acbdfb7e62e7cfa4.tar.gz bcm5719-llvm-ca22d427b94de946d4ef32b8acbdfb7e62e7cfa4.zip |
[SimplifyLibcalls] Replace locked IO with unlocked IO
Summary: If file stream arg is not captured and source is fopen, we could replace IO calls by unlocked IO ("_unlocked" function variants) to gain better speed,
Reviewers: efriedma, RKSimon, spatel, sanjoy, hfinkel, majnemer, lebedev.ri, rja
Reviewed By: rja
Subscribers: rja, srhines, efriedma, lebedev.ri, llvm-commits
Differential Revision: https://reviews.llvm.org/D45736
llvm-svn: 332452
Diffstat (limited to 'llvm/test/Transforms')
-rw-r--r-- | llvm/test/Transforms/InferFunctionAttrs/annotate.ll | 6 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/unlocked-stdio.ll | 197 |
2 files changed, 203 insertions, 0 deletions
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll index 80ac8f99edc..371f1ad065b 100644 --- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll +++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll @@ -514,6 +514,9 @@ declare i32 @getc_unlocked(%opaque*) ; CHECK: declare i32 @getchar() declare i32 @getchar() +; CHECK: declare i32 @getchar_unlocked() +declare i32 @getchar_unlocked() + ; CHECK: declare i8* @getenv(i8* nocapture) [[G1]] declare i8* @getenv(i8*) @@ -700,6 +703,9 @@ declare i32 @putc(i32, %opaque*) ; CHECK: declare i32 @putchar(i32) declare i32 @putchar(i32) +; CHECK: declare i32 @putchar_unlocked(i32) +declare i32 @putchar_unlocked(i32) + ; CHECK: declare i32 @puts(i8* nocapture readonly) [[G0]] declare i32 @puts(i8*) diff --git a/llvm/test/Transforms/InstCombine/unlocked-stdio.ll b/llvm/test/Transforms/InstCombine/unlocked-stdio.ll new file mode 100644 index 00000000000..fa5a9fa6d96 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/unlocked-stdio.ll @@ -0,0 +1,197 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s + +%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] } +%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 } + +@.str = private unnamed_addr constant [5 x i8] c"file\00", align 1 +@.str.1 = private unnamed_addr constant [2 x i8] c"w\00", align 1 +@.str.2 = private unnamed_addr constant [4 x i8] c"str\00", align 1 +@global_file = common global %struct._IO_FILE* null, align 8 + +define void @external_fgetc_test(%struct._IO_FILE* %f) { +; CHECK-LABEL: @external_fgetc_test( +; CHECK-NEXT: [[CALL:%.*]] = call i32 @fgetc(%struct._IO_FILE* [[F:%.*]]) +; CHECK-NEXT: ret void +; + %call = call i32 @fgetc(%struct._IO_FILE* %f) + ret void +} + +declare i32 @fgetc(%struct._IO_FILE* nocapture) #0 + +define void @external_fgetc_test2() { +; CHECK-LABEL: @external_fgetc_test2( +; 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)) +; CHECK-NEXT: [[FPUTC_UNLOCKED:%.*]] = call i32 @fputc_unlocked(i32 99, %struct._IO_FILE* [[CALL]]) +; CHECK-NEXT: ret void +; + %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)) + %call1 = call i32 @fputc(i32 99, %struct._IO_FILE* %call) + ret void +} + +declare %struct._IO_FILE* @fopen(i8*, i8*) +declare i32 @fputc(i32, %struct._IO_FILE* nocapture) #0 + +define internal void @fgetc_test() { +; CHECK-LABEL: @fgetc_test( +; 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)) +; CHECK-NEXT: [[FGETC_UNLOCKED:%.*]] = call i32 @fgetc_unlocked(%struct._IO_FILE* [[CALL]]) +; CHECK-NEXT: ret void +; + %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)) + %call1 = call i32 @fgetc(%struct._IO_FILE* %call) + ret void +} + +define void @external_fgetc_internal_test() { +; CHECK-LABEL: @external_fgetc_internal_test( +; CHECK-NEXT: call void @fgetc_test() +; CHECK-NEXT: ret void +; + call void @fgetc_test() + ret void +} + +define internal void @fwrite_test() { +; CHECK-LABEL: @fwrite_test( +; CHECK-NEXT: [[S:%.*]] = alloca [10 x i8], align 1 +; 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)) +; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], [10 x i8]* [[S]], i64 0, i64 0 +; CHECK-NEXT: [[TMP1:%.*]] = call i64 @fwrite_unlocked(i8* nonnull [[ARRAYDECAY]], i64 10, i64 10, %struct._IO_FILE* [[CALL]]) +; CHECK-NEXT: ret void +; + %s = alloca [10 x i8], align 1 + %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)) + %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %s, i64 0, i64 0 + %call1 = call i64 @fwrite(i8* nonnull %arraydecay, i64 10, i64 10, %struct._IO_FILE* %call) + ret void +} + +define internal void @fread_test() { +; CHECK-LABEL: @fread_test( +; CHECK-NEXT: [[S:%.*]] = alloca [10 x i8], align 1 +; 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)) +; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], [10 x i8]* [[S]], i64 0, i64 0 +; CHECK-NEXT: [[TMP1:%.*]] = call i64 @fread_unlocked(i8* nonnull [[ARRAYDECAY]], i64 10, i64 10, %struct._IO_FILE* [[CALL]]) +; CHECK-NEXT: ret void +; + %s = alloca [10 x i8], align 1 + %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)) + %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %s, i64 0, i64 0 + %call1 = call i64 @fread(i8* nonnull %arraydecay, i64 10, i64 10, %struct._IO_FILE* %call) + ret void +} + +define internal void @fputs_test() { +; CHECK-LABEL: @fputs_test( +; 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)) +; 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]]) +; CHECK-NEXT: ret void +; + %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)) + %call1 = call i32 @fputs(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), %struct._IO_FILE* %call) + ret void +} + +define internal void @fgets_test() { +; CHECK-LABEL: @fgets_test( +; CHECK-NEXT: [[BUF:%.*]] = alloca [10 x i8], align 1 +; 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)) +; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], [10 x i8]* [[BUF]], i64 0, i64 0 +; CHECK-NEXT: [[FGETS_UNLOCKED:%.*]] = call i32 @fgets_unlocked(i8* nonnull [[ARRAYDECAY]], i32 10, %struct._IO_FILE* [[CALL]]) +; CHECK-NEXT: ret void +; + %buf = alloca [10 x i8], align 1 + %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)) + %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %buf, i64 0, i64 0 + %call1 = call i8* @fgets(i8* nonnull %arraydecay, i32 10, %struct._IO_FILE* %call) + ret void +} + +define internal void @fputc_test() { +; CHECK-LABEL: @fputc_test( +; 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)) +; CHECK-NEXT: [[FPUTC_UNLOCKED:%.*]] = call i32 @fputc_unlocked(i32 99, %struct._IO_FILE* [[CALL]]) +; CHECK-NEXT: ret void +; + %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)) + %call1 = call i32 @fputc(i32 99, %struct._IO_FILE* %call) + ret void +} + +define i32 @main() { +; CHECK-LABEL: @main( +; CHECK-NEXT: call void @fwrite_test() +; CHECK-NEXT: call void @fread_test() +; CHECK-NEXT: call void @fputs_test() +; CHECK-NEXT: call void @fgets_test() +; CHECK-NEXT: call void @fputc_test() +; CHECK-NEXT: call void @fgetc_test() +; CHECK-NEXT: ret i32 0 +; + call void @fwrite_test() + call void @fread_test() + call void @fputs_test() + call void @fgets_test() + call void @fputc_test() + call void @fgetc_test() + ret i32 0 +} + +declare i32 @fclose(%struct._IO_FILE* nocapture) + +define void @test_with_fclose() { +; CHECK-LABEL: @test_with_fclose( +; 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)) +; 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]]) +; CHECK-NEXT: [[CALL2:%.*]] = call i32 @fclose(%struct._IO_FILE* [[CALL]]) +; CHECK-NEXT: ret void +; + %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 + %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) + %call2 = call i32 @fclose(%struct._IO_FILE* %call) #2 + ret void +} + +declare void @modify_file(%struct._IO_FILE*) + +define void @test_captured_by_function(){ +; CHECK-LABEL: @test_captured_by_function( +; 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)) +; CHECK-NEXT: call void @modify_file(%struct._IO_FILE* [[CALL]]) +; 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]]) +; CHECK-NEXT: [[CALL2:%.*]] = call i32 @fclose(%struct._IO_FILE* [[CALL]]) +; CHECK-NEXT: ret void +; + %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 + call void @modify_file(%struct._IO_FILE* %call) #2 + %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) + %call2 = call i32 @fclose(%struct._IO_FILE* %call) #2 + ret void +} + +define void @test_captured_by_global_value() { +; CHECK-LABEL: @test_captured_by_global_value( +; 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)) +; CHECK-NEXT: [[DOTCAST:%.*]] = ptrtoint %struct._IO_FILE* [[CALL]] to i64 +; CHECK-NEXT: store i64 [[DOTCAST]], i64* bitcast (%struct._IO_FILE** @global_file to i64*), align 8 +; 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]]) +; CHECK-NEXT: [[CALL2:%.*]] = call i32 @fclose(%struct._IO_FILE* [[CALL]]) +; CHECK-NEXT: ret void +; + %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 + %.cast = ptrtoint %struct._IO_FILE* %call to i64 + store i64 %.cast, i64* bitcast (%struct._IO_FILE** @global_file to i64*), align 8 + %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) + %call2 = call i32 @fclose(%struct._IO_FILE* %call) #2 + ret void +} + + + +declare i64 @fwrite(i8* nocapture, i64, i64, %struct._IO_FILE* nocapture) #0 +declare i64 @fread(i8* nocapture, i64, i64, %struct._IO_FILE* nocapture) #0 +declare i32 @fputs(i8* nocapture readonly, %struct._IO_FILE* nocapture) #0 +declare i8* @fgets(i8*, i32, %struct._IO_FILE* nocapture) #0 |