[llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp
Reid Spencer
reid at x10sys.com
Mon May 2 16:59:37 PDT 2005
Changes in directory llvm/lib/Transforms/IPO:
SimplifyLibCalls.cpp updated: 1.25 -> 1.26
---
Log message:
Implement the fprintf optimization which converts calls like this:
fprintf(F,"hello") -> fwrite("hello",strlen("hello"),1,F)
fprintf(F,"%s","hello") -> fwrite("hello",strlen("hello"),1,F)
fprintf(F,"%c",'x') -> fputc('c',F)
This optimization fires severals times in llvm-test:
313 MultiSource/Applications/Burg
302 MultiSource/Benchmarks/Prolangs-C/TimberWolfMC
189 MultiSource/Benchmarks/Prolangs-C/mybison
175 MultiSource/Benchmarks/Prolangs-C/football
130 MultiSource/Benchmarks/Prolangs-C/unix-tbl
---
Diffs of the changes: (+126 -7)
SimplifyLibCalls.cpp | 133 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 126 insertions(+), 7 deletions(-)
Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp
diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.25 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.26
--- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.25 Sat Apr 30 01:45:47 2005
+++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Mon May 2 18:59:26 2005
@@ -858,6 +858,132 @@
}
} PowOptimizer;
+/// This LibCallOptimization will simplify calls to the "fprintf" library
+/// function. It looks for cases where the result of fprintf is not used and the
+/// operation can be reduced to something simpler.
+/// @brief Simplify the pow library function.
+struct FPrintFOptimization : public LibCallOptimization
+{
+public:
+ /// @brief Default Constructor
+ FPrintFOptimization() : LibCallOptimization("fprintf") {}
+
+ /// @brief Destructor
+ virtual ~FPrintFOptimization() {}
+
+ /// @brief Make sure that the "fprintf" function has the right prototype
+ virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC)
+ {
+ // Just make sure this has at least 2 arguments
+ return (f->arg_size() >= 2);
+ }
+
+ /// @brief Perform the fprintf optimization.
+ virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC)
+ {
+ // If the call has more than 3 operands, we can't optimize it
+ if (ci->getNumOperands() > 4 || ci->getNumOperands() <= 2)
+ return false;
+
+ // If the result of the fprintf call is used, none of these optimizations
+ // can be made.
+ if (!ci->hasNUses(0))
+ return false;
+
+ // All the optimizations depend on the length of the second argument and the
+ // fact that it is a constant string array. Check that now
+ uint64_t len = 0;
+ ConstantArray* CA = 0;
+ if (!getConstantStringLength(ci->getOperand(2), len, &CA))
+ return false;
+
+ if (ci->getNumOperands() == 3)
+ {
+ // Make sure there's no % in the constant array
+ for (unsigned i = 0; i < len; ++i)
+ {
+ if (ConstantInt* CI = dyn_cast<ConstantInt>(CA->getOperand(i)))
+ {
+ // Check for the null terminator
+ if (CI->getRawValue() == '%')
+ return false; // we found end of string
+ }
+ else
+ return false;
+ }
+
+ // fprintf(file,fmt) -> fwrite(fmt,strlen(fmt),1file)
+ const Type* FILEptr_type = ci->getOperand(1)->getType();
+ Function* fwrite_func = SLC.get_fwrite(FILEptr_type);
+ if (!fwrite_func)
+ return false;
+ std::vector<Value*> args;
+ args.push_back(ci->getOperand(2));
+ args.push_back(ConstantUInt::get(SLC.getIntPtrType(),len));
+ args.push_back(ConstantUInt::get(SLC.getIntPtrType(),1));
+ args.push_back(ci->getOperand(1));
+ new CallInst(fwrite_func,args,"",ci);
+ ci->eraseFromParent();
+ return true;
+ }
+
+ // The remaining optimizations require the format string to be length 2
+ // "%s" or "%c".
+ if (len != 2)
+ return false;
+
+ // The first character has to be a %
+ if (ConstantInt* CI = dyn_cast<ConstantInt>(CA->getOperand(0)))
+ if (CI->getRawValue() != '%')
+ return false;
+
+ // Get the second character and switch on its value
+ ConstantInt* CI = dyn_cast<ConstantInt>(CA->getOperand(1));
+ switch (CI->getRawValue())
+ {
+ case 's':
+ {
+ uint64_t len = 0;
+ ConstantArray* CA = 0;
+ if (!getConstantStringLength(ci->getOperand(3), len, &CA))
+ return false;
+
+ // fprintf(file,fmt) -> fwrite(fmt,strlen(fmt),1,file)
+ const Type* FILEptr_type = ci->getOperand(1)->getType();
+ Function* fwrite_func = SLC.get_fwrite(FILEptr_type);
+ if (!fwrite_func)
+ return false;
+ std::vector<Value*> args;
+ args.push_back(ci->getOperand(3));
+ args.push_back(ConstantUInt::get(SLC.getIntPtrType(),len));
+ args.push_back(ConstantUInt::get(SLC.getIntPtrType(),1));
+ args.push_back(ci->getOperand(1));
+ new CallInst(fwrite_func,args,"",ci);
+ break;
+ }
+ case 'c':
+ {
+ ConstantInt* CI = dyn_cast<ConstantInt>(ci->getOperand(3));
+ if (!CI)
+ return false;
+
+ const Type* FILEptr_type = ci->getOperand(1)->getType();
+ Function* fputc_func = SLC.get_fputc(FILEptr_type);
+ if (!fputc_func)
+ return false;
+ CastInst* cast = new CastInst(CI,Type::IntTy,CI->getName()+".int",ci);
+ new CallInst(fputc_func,cast,ci->getOperand(1),"",ci);
+ break;
+ }
+ default:
+ return false;
+ }
+ ci->eraseFromParent();
+ return true;
+ }
+} FPrintFOptimizer;
+
+
/// 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.
@@ -1083,13 +1209,6 @@
// ffs, ffsl, ffsll:
// * ffs(cnst) -> cnst'
//
-// fprintf:
-// * fprintf(file,fmt) -> fputs(fmt,file)
-// (if fmt is constant and constains no % characters)
-// * fprintf(file,"%s",str) -> fputs(orig,str)
-// (only if the fprintf result is not used)
-// * fprintf(file,"%c",chr) -> fputc(chr,file)
-//
// isascii:
// * isascii(c) -> ((c & ~0x7f) == 0)
//
More information about the llvm-commits
mailing list