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

Reid Spencer reid at x10sys.com
Sat May 7 13:16:33 PDT 2005



Changes in directory llvm/lib/Transforms/IPO:

SimplifyLibCalls.cpp updated: 1.32 -> 1.33
---
Log message:

* Add two strlen optimizations:
    strlen(x) != 0 -> *x != 0
    strlen(x) == 0 -> *x == 0
* Change nested statistics to use style of other LLVM statistics so that
  only the name of the optimization (simplify-libcalls) is used as the
  statistic name, and the description indicates which specific all is
  optimized. Cuts down on some redundancy and saves a few bytes of space.
* Make note of stpcpy optimization that could be done.


---
Diffs of the changes:  (+56 -23)

 SimplifyLibCalls.cpp |   79 ++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 56 insertions(+), 23 deletions(-)


Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp
diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.32 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.33
--- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.32	Fri May  6 23:59:45 2005
+++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp	Sat May  7 15:15:59 2005
@@ -35,7 +35,7 @@
 /// This statistic keeps track of the total number of library calls that have
 /// been simplified regardless of which call it is.
 Statistic<> SimplifiedLibCalls("simplify-libcalls", 
-  "Number of well-known library calls simplified");
+  "Total number of library calls simplified");
 
 // Forward declarations
 class LibCallOptimization;
@@ -65,11 +65,10 @@
   /// The \p fname argument must be the name of the library function being 
   /// optimized by the subclass.
   /// @brief Constructor that registers the optimization.
-  LibCallOptimization(const char* fname, 
-                      const char* stat_name, const char* description )
+  LibCallOptimization(const char* fname, const char* description )
     : func_name(fname)
 #ifndef NDEBUG
-    , occurrences(stat_name,description)
+    , occurrences("simplify-libcalls",description)
 #endif
   {
     // Register this call optimizer in the optlist (a hash_map)
@@ -374,7 +373,7 @@
 struct ExitInMainOptimization : public LibCallOptimization
 {
   ExitInMainOptimization() : LibCallOptimization("exit",
-      "simplify-libcalls:exit","Number of 'exit' calls simplified") {}
+      "Number of 'exit' calls simplified") {}
   virtual ~ExitInMainOptimization() {}
 
   // Make sure the called function looks like exit (int argument, int return
@@ -440,7 +439,7 @@
 public:
   /// @brief Default constructor
   StrCatOptimization() : LibCallOptimization("strcat",
-      "simplify-libcalls:strcat","Number of 'strcat' calls simplified") {}
+      "Number of 'strcat' calls simplified") {}
 
 public:
   /// @breif  Destructor
@@ -531,7 +530,7 @@
 {
 public:
   StrChrOptimization() : LibCallOptimization("strchr",
-      "simplify-libcalls:strchr","Number of 'strchr' calls simplified") {}
+      "Number of 'strchr' calls simplified") {}
   virtual ~StrChrOptimization() {}
 
   /// @brief Make sure that the "strchr" function has the right prototype
@@ -623,7 +622,7 @@
 {
 public:
   StrCmpOptimization() : LibCallOptimization("strcmp",
-      "simplify-libcalls:strcmp","Number of 'strcmp' calls simplified") {}
+      "Number of 'strcmp' calls simplified") {}
   virtual ~StrCmpOptimization() {}
 
   /// @brief Make sure that the "strcpy" function has the right prototype
@@ -708,7 +707,7 @@
 {
 public:
   StrNCmpOptimization() : LibCallOptimization("strncmp",
-      "simplify-libcalls:strncmp","Number of 'strncmp' calls simplified") {}
+      "Number of 'strncmp' calls simplified") {}
   virtual ~StrNCmpOptimization() {}
 
   /// @brief Make sure that the "strcpy" function has the right prototype
@@ -811,7 +810,7 @@
 {
 public:
   StrCpyOptimization() : LibCallOptimization("strcpy",
-      "simplify-libcalls:strcpy","Number of 'strcpy' calls simplified") {}
+      "Number of 'strcpy' calls simplified") {}
   virtual ~StrCpyOptimization() {}
 
   /// @brief Make sure that the "strcpy" function has the right prototype
@@ -899,7 +898,7 @@
 struct StrLenOptimization : public LibCallOptimization
 {
   StrLenOptimization() : LibCallOptimization("strlen",
-      "simplify-libcalls:strlen","Number of 'strlen' calls simplified") {}
+      "Number of 'strlen' calls simplified") {}
   virtual ~StrLenOptimization() {}
 
   /// @brief Make sure that the "strlen" function has the right prototype
@@ -916,11 +915,45 @@
   /// @brief Perform the strlen optimization
   virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC)
   {
-    // Get the length of the string
+    // Make sure we're dealing with an sbyte* here.
+    Value* str = ci->getOperand(1);
+    if (str->getType() != PointerType::get(Type::SByteTy))
+      return false;
+
+    // Does the call to strlen have exactly one use?
+    if (ci->hasOneUse()) 
+      // Is that single use a binary operator?
+      if (BinaryOperator* bop = dyn_cast<BinaryOperator>(ci->use_back()))
+        // Is it compared against a constant integer?
+        if (ConstantInt* CI = dyn_cast<ConstantInt>(bop->getOperand(1)))
+        {
+          // Get the value the strlen result is compared to
+          uint64_t val = CI->getRawValue();
+
+          // If its compared against length 0 with == or !=
+          if (val == 0 &&
+              (bop->getOpcode() == Instruction::SetEQ ||
+               bop->getOpcode() == Instruction::SetNE))
+          {
+            // strlen(x) != 0 -> *x != 0
+            // strlen(x) == 0 -> *x == 0
+            LoadInst* load = new LoadInst(str,str->getName()+".first",ci);
+            BinaryOperator* rbop = BinaryOperator::create(bop->getOpcode(),
+              load, ConstantSInt::get(Type::SByteTy,0),
+              bop->getName()+".strlen", ci);
+            bop->replaceAllUsesWith(rbop);
+            bop->eraseFromParent();
+            ci->eraseFromParent();
+            return true;
+          }
+        }
+
+    // Get the length of the constant string operand
     uint64_t len = 0;
     if (!getConstantStringLength(ci->getOperand(1),len))
       return false;
 
+    // strlen("xyz") -> 3 (for example)
     ci->replaceAllUsesWith(
         ConstantInt::get(SLC.getTargetData()->getIntPtrType(),len));
     ci->eraseFromParent();
@@ -937,13 +970,12 @@
 {
   /// @brief Default Constructor
   LLVMMemCpyOptimization() : LibCallOptimization("llvm.memcpy",
-      "simplify-libcalls:llvm.memcpy",
       "Number of 'llvm.memcpy' calls simplified") {}
 
 protected:
   /// @brief Subclass Constructor 
-  LLVMMemCpyOptimization(const char* fname, const char* sname, const char* desc)
-    : LibCallOptimization(fname, sname, desc) {}
+  LLVMMemCpyOptimization(const char* fname, const char* desc)
+    : LibCallOptimization(fname, desc) {}
 public:
   /// @brief Destructor
   virtual ~LLVMMemCpyOptimization() {}
@@ -1017,7 +1049,6 @@
 {
   /// @brief Default Constructor
   LLVMMemMoveOptimization() : LLVMMemCpyOptimization("llvm.memmove",
-      "simplify-libcalls:llvm.memmove",
       "Number of 'llvm.memmove' calls simplified") {}
 
 } LLVMMemMoveOptimizer;
@@ -1029,7 +1060,6 @@
 {
   /// @brief Default Constructor
   LLVMMemSetOptimization() : LibCallOptimization("llvm.memset",
-      "simplify-libcalls:llvm.memset",
       "Number of 'llvm.memset' calls simplified") {}
 
 public:
@@ -1139,7 +1169,7 @@
 public:
   /// @brief Default Constructor
   PowOptimization() : LibCallOptimization("pow",
-      "simplify-libcalls:pow", "Number of 'pow' calls simplified") {}
+      "Number of 'pow' calls simplified") {}
 
   /// @brief Destructor
   virtual ~PowOptimization() {}
@@ -1216,7 +1246,7 @@
 public:
   /// @brief Default Constructor
   FPrintFOptimization() : LibCallOptimization("fprintf",
-      "simplify-libcalls:fprintf", "Number of 'fprintf' calls simplified") {}
+      "Number of 'fprintf' calls simplified") {}
 
   /// @brief Destructor
   virtual ~FPrintFOptimization() {}
@@ -1346,7 +1376,7 @@
 public:
   /// @brief Default Constructor
   SPrintFOptimization() : LibCallOptimization("sprintf",
-      "simplify-libcalls:sprintf", "Number of 'sprintf' calls simplified") {}
+      "Number of 'sprintf' calls simplified") {}
 
   /// @brief Destructor
   virtual ~SPrintFOptimization() {}
@@ -1489,7 +1519,7 @@
 public:
   /// @brief Default Constructor
   PutsOptimization() : LibCallOptimization("fputs",
-      "simplify-libcalls:fputs", "Number of 'fputs' calls simplified") {}
+      "Number of 'fputs' calls simplified") {}
 
   /// @brief Destructor
   virtual ~PutsOptimization() {}
@@ -1562,7 +1592,7 @@
 public:
   /// @brief Default Constructor
   IsDigitOptimization() : LibCallOptimization("isdigit",
-      "simplify-libcalls:isdigit", "Number of 'isdigit' calls simplified") {}
+      "Number of 'isdigit' calls simplified") {}
 
   /// @brief Destructor
   virtual ~IsDigitOptimization() {}
@@ -1617,7 +1647,7 @@
 public:
   /// @brief Default Constructor
   ToAsciiOptimization() : LibCallOptimization("toascii",
-      "simplify-libcalls:toascii", "Number of 'toascii' calls simplified") {}
+      "Number of 'toascii' calls simplified") {}
 
   /// @brief Destructor
   virtual ~ToAsciiOptimization() {}
@@ -1810,6 +1840,9 @@
 //   * sqrt(Nroot(x)) -> pow(x,1/(2*N))
 //   * sqrt(pow(x,y)) -> pow(|x|,y*0.5)
 //
+// stpcpy:
+//   * stpcpy(str, "literal") ->
+//           llvm.memcpy(str,"literal",strlen("literal")+1,1)
 // strrchr:
 //   * strrchr(s,c) -> reverse_offset_of_in(c,s)
 //      (if c is a constant integer and s is a constant string)






More information about the llvm-commits mailing list