aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2005-05-07 20:15:59 +0000
committerReid Spencer <rspencer@reidspencer.com>2005-05-07 20:15:59 +0000
commit789082af0399576a80141a8bd6241f96e29e2902 (patch)
tree2035bf14753fa843865ce0d5d404bcd61003b812
parent673c1a917035a7fe04f4491fbba62a7e13de2069 (diff)
* 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21766 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/IPO/SimplifyLibCalls.cpp79
1 files changed, 56 insertions, 23 deletions
diff --git a/lib/Transforms/IPO/SimplifyLibCalls.cpp b/lib/Transforms/IPO/SimplifyLibCalls.cpp
index fef058045e..24bcf4ed63 100644
--- a/lib/Transforms/IPO/SimplifyLibCalls.cpp
+++ b/lib/Transforms/IPO/SimplifyLibCalls.cpp
@@ -35,7 +35,7 @@ namespace {
/// 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 @@ public:
/// 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 @@ bool getConstantStringLength(Value* V, uint64_t& len, ConstantArray** A = 0 );
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 @@ struct StrCatOptimization : public LibCallOptimization
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 @@ struct StrChrOptimization : public LibCallOptimization
{
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 @@ struct StrCmpOptimization : public LibCallOptimization
{
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 @@ struct StrNCmpOptimization : public LibCallOptimization
{
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 @@ struct StrCpyOptimization : public LibCallOptimization
{
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 @@ public:
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 @@ struct StrLenOptimization : public LibCallOptimization
/// @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 @@ struct LLVMMemCpyOptimization : public LibCallOptimization
{
/// @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 @@ struct LLVMMemMoveOptimization : public LLVMMemCpyOptimization
{
/// @brief Default Constructor
LLVMMemMoveOptimization() : LLVMMemCpyOptimization("llvm.memmove",
- "simplify-libcalls:llvm.memmove",
"Number of 'llvm.memmove' calls simplified") {}
} LLVMMemMoveOptimizer;
@@ -1029,7 +1060,6 @@ struct LLVMMemSetOptimization : public LibCallOptimization
{
/// @brief Default Constructor
LLVMMemSetOptimization() : LibCallOptimization("llvm.memset",
- "simplify-libcalls:llvm.memset",
"Number of 'llvm.memset' calls simplified") {}
public:
@@ -1139,7 +1169,7 @@ struct PowOptimization : public LibCallOptimization
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 @@ struct FPrintFOptimization : public LibCallOptimization
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 @@ struct SPrintFOptimization : public LibCallOptimization
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 @@ struct PutsOptimization : public LibCallOptimization
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 @@ struct IsDigitOptimization : public LibCallOptimization
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 @@ struct ToAsciiOptimization : public LibCallOptimization
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 @@ bool getConstantStringLength(Value* V, uint64_t& len, ConstantArray** CA )
// * 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)