[llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp

Evan Cheng evan.cheng at apple.com
Fri Jun 16 01:36:49 PDT 2006



Changes in directory llvm/lib/Transforms/IPO:

SimplifyLibCalls.cpp updated: 1.65 -> 1.66
---
Log message:

More libcall transformations:
printf("%s\n", str) -> puts(str)
printf("%c", c) -> putchar(c)
Also fixed fprintf(file, "%c", c) -> fputc(c, file)


---
Diffs of the changes:  (+110 -8)

 SimplifyLibCalls.cpp |  118 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 110 insertions(+), 8 deletions(-)


Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp
diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.65 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.66
--- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.65	Thu Jun 15 23:52:30 2006
+++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp	Fri Jun 16 03:36:35 2006
@@ -221,6 +221,23 @@
   /// @brief Return the size_t type -- syntactic shortcut
   const Type* getIntPtrType() const { return TD->getIntPtrType(); }
 
+  /// @brief Return a Function* for the putchar libcall
+  Function* get_putchar() {
+    if (!putchar_func)
+      putchar_func = M->getOrInsertFunction("putchar", Type::IntTy, Type::IntTy,
+                                            NULL);
+    return putchar_func;
+  }
+
+  /// @brief Return a Function* for the puts libcall
+  Function* get_puts() {
+    if (!puts_func)
+      puts_func = M->getOrInsertFunction("puts", Type::IntTy,
+                                         PointerType::get(Type::SByteTy),
+                                         NULL);
+    return puts_func;
+  }
+
   /// @brief Return a Function* for the fputc libcall
   Function* get_fputc(const Type* FILEptr_type) {
     if (!fputc_func)
@@ -318,6 +335,8 @@
   void reset(Module& mod) {
     M = &mod;
     TD = &getAnalysis<TargetData>();
+    putchar_func = 0;
+    puts_func = 0;
     fputc_func = 0;
     fputs_func = 0;
     fwrite_func = 0;
@@ -335,6 +354,7 @@
 
 private:
   /// Caches for function pointers.
+  Function *putchar_func, *puts_func;
   Function *fputc_func, *fputs_func, *fwrite_func;
   Function *memcpy_func, *memchr_func;
   Function* sqrt_func;
@@ -1264,10 +1284,94 @@
   }
 } PowOptimizer;
 
+/// This LibCallOptimization will simplify calls to the "printf" library
+/// function. It looks for cases where the result of printf is not used and the
+/// operation can be reduced to something simpler.
+/// @brief Simplify the printf library function.
+struct PrintfOptimization : public LibCallOptimization {
+public:
+  /// @brief Default Constructor
+  PrintfOptimization() : LibCallOptimization("printf",
+      "Number of 'printf' calls simplified") {}
+
+  /// @brief Make sure that the "printf" function has the right prototype
+  virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC){
+    // Just make sure this has at least 1 arguments
+    return (f->arg_size() >= 1);
+  }
+
+  /// @brief Perform the printf optimization.
+  virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) {
+    // If the call has more than 2 operands, we can't optimize it
+    if (ci->getNumOperands() > 3 || ci->getNumOperands() <= 2)
+      return false;
+
+    // If the result of the printf call is used, none of these optimizations
+    // can be made.
+    if (!ci->use_empty())
+      return false;
+
+    // All the optimizations depend on the length of the first 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(1), len, &CA))
+      return false;
+
+    if (len != 2 && len != 3)
+      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':
+      {
+        if (len != 3 ||
+            dyn_cast<ConstantInt>(CA->getOperand(2))->getRawValue() != '\n')
+          return false;
+
+        // printf("%s\n",str) -> puts(str)
+        Function* puts_func = SLC.get_puts();
+        if (!puts_func)
+          return false;
+        std::vector<Value*> args;
+        args.push_back(ci->getOperand(2));
+        new CallInst(puts_func,args,ci->getName(),ci);
+        ci->replaceAllUsesWith(ConstantSInt::get(Type::IntTy,len));
+        break;
+      }
+      case 'c':
+      {
+        // printf("%c",c) -> putchar(c)
+        if (len != 2)
+          return false;
+
+        Function* putchar_func = SLC.get_putchar();
+        if (!putchar_func)
+          return false;
+        CastInst* cast = new CastInst(ci->getOperand(2), Type::IntTy,
+                                      CI->getName()+".int", ci);
+        new CallInst(putchar_func, cast, "", ci);
+        ci->replaceAllUsesWith(ConstantSInt::get(Type::IntTy, 1));
+        break;
+      }
+      default:
+        return false;
+    }
+    ci->eraseFromParent();
+    return true;
+  }
+} PrintfOptimizer;
+
 /// 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.
+/// @brief Simplify the fprintf library function.
 struct FPrintFOptimization : public LibCallOptimization {
 public:
   /// @brief Default Constructor
@@ -1379,15 +1483,13 @@
       }
       case 'c':
       {
-        ConstantInt* CI = dyn_cast<ConstantInt>(ci->getOperand(3));
-        if (!CI)
-          return false;
-
+        // fprintf(file,"%c",c) -> fputc(c,file)
         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);
+        CastInst* cast = new CastInst(ci->getOperand(3), Type::IntTy,
+                                      CI->getName()+".int", ci);
         new CallInst(fputc_func,cast,ci->getOperand(1),"",ci);
         ci->replaceAllUsesWith(ConstantSInt::get(Type::IntTy,1));
         break;
@@ -1403,7 +1505,7 @@
 /// This LibCallOptimization will simplify calls to the "sprintf" library
 /// function. It looks for cases where the result of sprintf is not used and the
 /// operation can be reduced to something simpler.
-/// @brief Simplify the pow library function.
+/// @brief Simplify the sprintf library function.
 struct SPrintFOptimization : public LibCallOptimization {
 public:
   /// @brief Default Constructor
@@ -1530,7 +1632,7 @@
 /// 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 pow library function.
+/// @brief Simplify the puts library function.
 struct PutsOptimization : public LibCallOptimization {
 public:
   /// @brief Default Constructor






More information about the llvm-commits mailing list