summaryrefslogtreecommitdiff
path: root/lib/Transforms/IPO/SimplifyLibCalls.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-04-08 07:00:35 +0000
committerChris Lattner <sabre@nondot.org>2007-04-08 07:00:35 +0000
commit5cef3c6eb7d06eca8e6844dee43818d528b1f516 (patch)
treea584f5bd0f1fde22c957bacb5714af8b4378ae08 /lib/Transforms/IPO/SimplifyLibCalls.cpp
parenta397ce1cc2872b059a128f43b8fd300c61700793 (diff)
downloadllvm-5cef3c6eb7d06eca8e6844dee43818d528b1f516.tar.gz
llvm-5cef3c6eb7d06eca8e6844dee43818d528b1f516.tar.bz2
llvm-5cef3c6eb7d06eca8e6844dee43818d528b1f516.tar.xz
implement a fixme: move optimizations for fwrite out of fputs into a new
fwrite optimizer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35758 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/IPO/SimplifyLibCalls.cpp')
-rw-r--r--lib/Transforms/IPO/SimplifyLibCalls.cpp82
1 files changed, 56 insertions, 26 deletions
diff --git a/lib/Transforms/IPO/SimplifyLibCalls.cpp b/lib/Transforms/IPO/SimplifyLibCalls.cpp
index a5de34d89a..7d65028601 100644
--- a/lib/Transforms/IPO/SimplifyLibCalls.cpp
+++ b/lib/Transforms/IPO/SimplifyLibCalls.cpp
@@ -1388,7 +1388,7 @@ public:
/// This LibCallOptimization will simplify calls to the "fputs" library
/// function. It looks for cases where the result of fputs is not used and the
/// operation can be reduced to something simpler.
-/// @brief Simplify the puts library function.
+/// @brief Simplify the fputs library function.
struct VISIBILITY_HIDDEN FPutsOptimization : public LibCallOptimization {
public:
/// @brief Default Constructor
@@ -1413,36 +1413,66 @@ public:
if (!GetConstantStringInfo(CI->getOperand(1), Str))
return false;
- Value *Ptr = CI->getOperand(1);
const Type *FILETy = CI->getOperand(2)->getType();
- // FIXME: Remove these optimizations and fold fwrite with 0/1 length
- // instead.
- switch (Str.size()) {
- case 0:
- // fputs("",F) -> noop
- break;
- case 1: {
- // fputs(s,F) -> fputc(s[0],F) (if s is constant and strlen(s) == 1)
+ // fputs(s,F) -> fwrite(s,1,len,F) (if s is constant and strlen(s) > 1)
+ Value *FWriteParms[4] = {
+ CI->getOperand(1),
+ ConstantInt::get(SLC.getIntPtrType(), Str.size()),
+ ConstantInt::get(SLC.getIntPtrType(), 1),
+ CI->getOperand(2)
+ };
+ new CallInst(SLC.get_fwrite(FILETy), FWriteParms, 4, "", CI);
+ return ReplaceCallWith(CI, 0); // Known to have no uses (see above).
+ }
+} FPutsOptimizer;
+
+/// This LibCallOptimization will simplify calls to the "fwrite" function.
+struct VISIBILITY_HIDDEN FWriteOptimization : public LibCallOptimization {
+public:
+ /// @brief Default Constructor
+ FWriteOptimization() : LibCallOptimization("fwrite",
+ "Number of 'fwrite' calls simplified") {}
+
+ /// @brief Make sure that the "fputs" function has the right prototype
+ virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
+ const FunctionType *FT = F->getFunctionType();
+ return FT->getNumParams() == 4 &&
+ FT->getParamType(0) == PointerType::get(Type::Int8Ty) &&
+ FT->getParamType(1) == FT->getParamType(2) &&
+ isa<IntegerType>(FT->getParamType(1)) &&
+ isa<PointerType>(FT->getParamType(3)) &&
+ isa<IntegerType>(FT->getReturnType());
+ }
+
+ virtual bool OptimizeCall(CallInst *CI, SimplifyLibCalls &SLC) {
+ // Get the element size and count.
+ uint64_t EltSize, EltCount;
+ if (ConstantInt *C = dyn_cast<ConstantInt>(CI->getOperand(2)))
+ EltSize = C->getZExtValue();
+ else
+ return false;
+ if (ConstantInt *C = dyn_cast<ConstantInt>(CI->getOperand(3)))
+ EltCount = C->getZExtValue();
+ else
+ return false;
+
+ // If this is writing zero records, remove the call (it's a noop).
+ if (EltSize * EltCount == 0)
+ return ReplaceCallWith(CI, ConstantInt::get(CI->getType(), 0));
+
+ // If this is writing one byte, turn it into fputc.
+ if (EltSize == 1 && EltCount == 1) {
+ // fwrite(s,1,1,F) -> fputc(s[0],F)
+ Value *Ptr = CI->getOperand(1);
Value *Val = new LoadInst(Ptr, Ptr->getName()+".byte", CI);
Val = new ZExtInst(Val, Type::Int32Ty, Val->getName()+".int", CI);
- new CallInst(SLC.get_fputc(FILETy), Val, CI->getOperand(2), "", CI);
- break;
- }
- default: {
- // fputs(s,F) -> fwrite(s,1,len,F) (if s is constant and strlen(s) > 1)
- Value *FWriteParms[4] = {
- CI->getOperand(1),
- ConstantInt::get(SLC.getIntPtrType(), Str.size()),
- ConstantInt::get(SLC.getIntPtrType(), 1),
- CI->getOperand(2)
- };
- new CallInst(SLC.get_fwrite(FILETy), FWriteParms, 4, "", CI);
- break;
- }
+ const Type *FILETy = CI->getOperand(4)->getType();
+ new CallInst(SLC.get_fputc(FILETy), Val, CI->getOperand(4), "", CI);
+ return ReplaceCallWith(CI, ConstantInt::get(CI->getType(), 1));
}
- return ReplaceCallWith(CI, 0); // Known to have no uses (see above).
+ return false;
}
-} PutsOptimizer;
+} FWriteOptimizer;
/// This LibCallOptimization will simplify calls to the "isdigit" library
/// function. It simply does range checks the parameter explicitly.