Skip to content

Commit

Permalink
[SimplifyLibcalls] Replace locked IO with unlocked IO
Browse files Browse the repository at this point in the history
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

Subscribers: lebedev.ri, llvm-commits

Differential Revision: https://reviews.llvm.org/D45736

llvm-svn: 331002
  • Loading branch information
davidbolvansky committed Apr 26, 2018
1 parent ad78e66 commit 2c9cc9c
Show file tree
Hide file tree
Showing 7 changed files with 465 additions and 21 deletions.
27 changes: 27 additions & 0 deletions llvm/include/llvm/Analysis/TargetLibraryInfo.def
Expand Up @@ -637,12 +637,18 @@ TLI_DEFINE_STRING_INTERNAL("ffsll")
/// int fgetc(FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fgetc)
TLI_DEFINE_STRING_INTERNAL("fgetc")
/// int fgetc_unlocked(FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fgetc_unlocked)
TLI_DEFINE_STRING_INTERNAL("fgetc_unlocked")
/// int fgetpos(FILE *stream, fpos_t *pos);
TLI_DEFINE_ENUM_INTERNAL(fgetpos)
TLI_DEFINE_STRING_INTERNAL("fgetpos")
/// char *fgets(char *s, int n, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fgets)
TLI_DEFINE_STRING_INTERNAL("fgets")
/// char *fgets_unlocked(char *s, int n, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fgets_unlocked)
TLI_DEFINE_STRING_INTERNAL("fgets_unlocked")
/// int fileno(FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fileno)
TLI_DEFINE_STRING_INTERNAL("fileno")
Expand Down Expand Up @@ -709,12 +715,21 @@ TLI_DEFINE_STRING_INTERNAL("fprintf")
/// int fputc(int c, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fputc)
TLI_DEFINE_STRING_INTERNAL("fputc")
/// int fputc_unlocked(int c, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fputc_unlocked)
TLI_DEFINE_STRING_INTERNAL("fputc_unlocked")
/// int fputs(const char *s, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fputs)
TLI_DEFINE_STRING_INTERNAL("fputs")
/// int fputs_unlocked(const char *s, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fputs_unlocked)
TLI_DEFINE_STRING_INTERNAL("fputs_unlocked")
/// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fread)
TLI_DEFINE_STRING_INTERNAL("fread")
/// size_t fread_unlocked(void *ptr, size_t size, size_t nitems, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fread_unlocked)
TLI_DEFINE_STRING_INTERNAL("fread_unlocked")
/// void free(void *ptr);
TLI_DEFINE_ENUM_INTERNAL(free)
TLI_DEFINE_STRING_INTERNAL("free")
Expand Down Expand Up @@ -772,6 +787,9 @@ TLI_DEFINE_STRING_INTERNAL("funlockfile")
/// size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fwrite)
TLI_DEFINE_STRING_INTERNAL("fwrite")
/// size_t fwrite_unlocked(const void *ptr, size_t size, size_t nitems, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(fwrite_unlocked)
TLI_DEFINE_STRING_INTERNAL("fwrite_unlocked")
/// int getc(FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(getc)
TLI_DEFINE_STRING_INTERNAL("getc")
Expand All @@ -781,6 +799,9 @@ TLI_DEFINE_STRING_INTERNAL("getc_unlocked")
/// int getchar(void);
TLI_DEFINE_ENUM_INTERNAL(getchar)
TLI_DEFINE_STRING_INTERNAL("getchar")
/// int getchar_unlocked(void);
TLI_DEFINE_ENUM_INTERNAL(getchar_unlocked)
TLI_DEFINE_STRING_INTERNAL("getchar_unlocked")
/// char *getenv(const char *name);
TLI_DEFINE_ENUM_INTERNAL(getenv)
TLI_DEFINE_STRING_INTERNAL("getenv")
Expand Down Expand Up @@ -986,9 +1007,15 @@ TLI_DEFINE_STRING_INTERNAL("printf")
/// int putc(int c, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(putc)
TLI_DEFINE_STRING_INTERNAL("putc")
/// int putc_unlocked(int c, FILE *stream);
TLI_DEFINE_ENUM_INTERNAL(putc_unlocked)
TLI_DEFINE_STRING_INTERNAL("putc_unlocked")
/// int putchar(int c);
TLI_DEFINE_ENUM_INTERNAL(putchar)
TLI_DEFINE_STRING_INTERNAL("putchar")
/// int putchar_unlocked(int c);
TLI_DEFINE_ENUM_INTERNAL(putchar_unlocked)
TLI_DEFINE_STRING_INTERNAL("putchar_unlocked")
/// int puts(const char *s);
TLI_DEFINE_ENUM_INTERNAL(puts)
TLI_DEFINE_STRING_INTERNAL("puts")
Expand Down
33 changes: 32 additions & 1 deletion llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
Expand Up @@ -111,11 +111,21 @@ namespace llvm {
Value *emitFPutC(Value *Char, Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);

/// Emit a call to the puts function. Str is required to be a pointer and
/// Emit a call to the fputc_unlocked function. This assumes that Char is an
/// i32, and File is a pointer to FILE.
Value *emitFPutCUnlocked(Value *Char, Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);

/// Emit a call to the fputs function. Str is required to be a pointer and
/// File is a pointer to FILE.
Value *emitFPutS(Value *Str, Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);

/// Emit a call to the fputs_unlocked function. Str is required to be a
/// pointer and File is a pointer to FILE.
Value *emitFPutSUnlocked(Value *Str, Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);

/// Emit a call to the fwrite function. This assumes that Ptr is a pointer,
/// Size is an 'intptr_t', and File is a pointer to FILE.
Value *emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
Expand All @@ -128,6 +138,27 @@ namespace llvm {
/// Emit a call to the calloc function.
Value *emitCalloc(Value *Num, Value *Size, const AttributeList &Attrs,
IRBuilder<> &B, const TargetLibraryInfo &TLI);

/// Emit a call to the fwrite_unlocked function. This assumes that Ptr is a
/// pointer, Size is an 'intptr_t', N is nmemb and File is a pointer to FILE.
Value *emitFWriteUnlocked(Value *Ptr, Value *Size, Value *N, Value *File,
IRBuilder<> &B, const DataLayout &DL,
const TargetLibraryInfo *TLI);

/// Emit a call to the fgetc_unlocked function. File is a pointer to FILE.
Value *emitFGetCUnlocked(Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);

/// Emit a call to the fgets_unlocked function. Str is required to be a
/// pointer, Size is an i32 and File is a pointer to FILE.
Value *emitFGetSUnlocked(Value *Str, Value *Size, Value *File, IRBuilder<> &B,
const TargetLibraryInfo *TLI);

/// Emit a call to the fread_unlocked function. This assumes that Ptr is a
/// pointer, Size is an 'intptr_t', N is nmemb and File is a pointer to FILE.
Value *emitFReadUnlocked(Value *Ptr, Value *Size, Value *N, Value *File,
IRBuilder<> &B, const DataLayout &DL,
const TargetLibraryInfo *TLI);
}

#endif
4 changes: 4 additions & 0 deletions llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
Expand Up @@ -161,7 +161,11 @@ class LibCallSimplifier {
Value *optimizeSPrintF(CallInst *CI, IRBuilder<> &B);
Value *optimizeFPrintF(CallInst *CI, IRBuilder<> &B);
Value *optimizeFWrite(CallInst *CI, IRBuilder<> &B);
Value *optimizeFRead(CallInst *CI, IRBuilder<> &B);
Value *optimizeFPuts(CallInst *CI, IRBuilder<> &B);
Value *optimizeFGets(CallInst *CI, IRBuilder<> &B);
Value *optimizeFPutc(CallInst *CI, IRBuilder<> &B);
Value *optimizeFGetc(CallInst *CI, IRBuilder<> &B);
Value *optimizePuts(CallInst *CI, IRBuilder<> &B);

// Helper methods
Expand Down
42 changes: 41 additions & 1 deletion llvm/lib/Analysis/TargetLibraryInfo.cpp
Expand Up @@ -62,6 +62,18 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
}) &&
"TargetLibraryInfoImpl function names must be sorted");

// Set IO unlocked variants as unavailable
// Set them as available per system below
TLI.setUnavailable(LibFunc_getchar_unlocked);
TLI.setUnavailable(LibFunc_putc_unlocked);
TLI.setUnavailable(LibFunc_putchar_unlocked);
TLI.setUnavailable(LibFunc_fputc_unlocked);
TLI.setUnavailable(LibFunc_fgetc_unlocked);
TLI.setUnavailable(LibFunc_fread_unlocked);
TLI.setUnavailable(LibFunc_fwrite_unlocked);
TLI.setUnavailable(LibFunc_fputs_unlocked);
TLI.setUnavailable(LibFunc_fgets_unlocked);

bool ShouldExtI32Param = false, ShouldExtI32Return = false,
ShouldSignExtI32Param = false;
// PowerPC64, Sparc64, SystemZ need signext/zeroext on i32 parameters and
Expand Down Expand Up @@ -107,6 +119,12 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
// memset_pattern16 is only available on iOS 3.0 and Mac OS X 10.5 and later.
// All versions of watchOS support it.
if (T.isMacOSX()) {
// available IO unlocked variants on Mac OS X
TLI.setAvailable(LibFunc_getc_unlocked);
TLI.setAvailable(LibFunc_getchar_unlocked);
TLI.setAvailable(LibFunc_putc_unlocked);
TLI.setAvailable(LibFunc_putchar_unlocked);

if (T.isMacOSXVersionLT(10, 5))
TLI.setUnavailable(LibFunc_memset_pattern16);
} else if (T.isiOS()) {
Expand Down Expand Up @@ -265,7 +283,6 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
TLI.setUnavailable(LibFunc_ftello);
TLI.setUnavailable(LibFunc_ftrylockfile);
TLI.setUnavailable(LibFunc_funlockfile);
TLI.setUnavailable(LibFunc_getc_unlocked);
TLI.setUnavailable(LibFunc_getitimer);
TLI.setUnavailable(LibFunc_getlogin_r);
TLI.setUnavailable(LibFunc_getpwnam);
Expand Down Expand Up @@ -465,6 +482,20 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
TLI.setUnavailable(LibFunc_sinhl_finite);
}

if (T.isOSLinux()) {
// available IO unlocked variants on Linux
TLI.setAvailable(LibFunc_getc_unlocked);
TLI.setAvailable(LibFunc_getchar_unlocked);
TLI.setAvailable(LibFunc_putc_unlocked);
TLI.setAvailable(LibFunc_putchar_unlocked);
TLI.setAvailable(LibFunc_fputc_unlocked);
TLI.setAvailable(LibFunc_fgetc_unlocked);
TLI.setAvailable(LibFunc_fread_unlocked);
TLI.setAvailable(LibFunc_fwrite_unlocked);
TLI.setAvailable(LibFunc_fputs_unlocked);
TLI.setAvailable(LibFunc_fgets_unlocked);
}

// As currently implemented in clang, NVPTX code has no standard library to
// speak of. Headers provide a standard-ish library implementation, but many
// of the signatures are wrong -- for example, many libm functions are not
Expand Down Expand Up @@ -805,6 +836,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
case LibFunc_feof:
case LibFunc_fflush:
case LibFunc_fgetc:
case LibFunc_fgetc_unlocked:
case LibFunc_fileno:
case LibFunc_flockfile:
case LibFunc_free:
Expand Down Expand Up @@ -833,25 +865,30 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
FTy.getParamType(1)->isPointerTy());
case LibFunc_fputc:
case LibFunc_fputc_unlocked:
case LibFunc_fstat:
case LibFunc_frexp:
case LibFunc_frexpf:
case LibFunc_frexpl:
case LibFunc_fstatvfs:
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
case LibFunc_fgets:
case LibFunc_fgets_unlocked:
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
FTy.getParamType(2)->isPointerTy());
case LibFunc_fread:
case LibFunc_fread_unlocked:
return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() &&
FTy.getParamType(3)->isPointerTy());
case LibFunc_fwrite:
case LibFunc_fwrite_unlocked:
return (NumParams == 4 && FTy.getReturnType()->isIntegerTy() &&
FTy.getParamType(0)->isPointerTy() &&
FTy.getParamType(1)->isIntegerTy() &&
FTy.getParamType(2)->isIntegerTy() &&
FTy.getParamType(3)->isPointerTy());
case LibFunc_fputs:
case LibFunc_fputs_unlocked:
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
FTy.getParamType(1)->isPointerTy());
case LibFunc_fscanf:
Expand All @@ -864,6 +901,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
FTy.getParamType(1)->isPointerTy());
case LibFunc_getchar:
case LibFunc_getchar_unlocked:
return (NumParams == 0 && FTy.getReturnType()->isIntegerTy());
case LibFunc_gets:
return (NumParams == 1 && FTy.getParamType(0) == PCharTy);
Expand All @@ -876,6 +914,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
FTy.getParamType(1)->isPointerTy());
case LibFunc_putc:
case LibFunc_putc_unlocked:
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
case LibFunc_pread:
case LibFunc_pwrite:
Expand Down Expand Up @@ -1262,6 +1301,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
case LibFunc_isascii:
case LibFunc_toascii:
case LibFunc_putchar:
case LibFunc_putchar_unlocked:
return (NumParams == 1 && FTy.getReturnType()->isIntegerTy(32) &&
FTy.getReturnType() == FTy.getParamType(0));

Expand Down

0 comments on commit 2c9cc9c

Please sign in to comment.