[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