mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
Add the StrNCmpOptimization which is similar to strcmp.
Unfortunately, this optimization didn't trigger on any llvm-test tests. llvm-svn: 21660
This commit is contained in:
parent
da05f00bbf
commit
123f4e393f
@ -573,6 +573,107 @@ public:
|
||||
}
|
||||
} StrCmpOptimizer;
|
||||
|
||||
/// This LibCallOptimization will simplify a call to the strncmp library
|
||||
/// function. It optimizes out cases where one or both arguments are constant
|
||||
/// and the result can be determined statically.
|
||||
/// @brief Simplify the strncmp library function.
|
||||
struct StrNCmpOptimization : public LibCallOptimization
|
||||
{
|
||||
public:
|
||||
StrNCmpOptimization() : LibCallOptimization("strncmp") {}
|
||||
virtual ~StrNCmpOptimization() {}
|
||||
|
||||
/// @brief Make sure that the "strcpy" function has the right prototype
|
||||
virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC)
|
||||
{
|
||||
if (f->getReturnType() == Type::IntTy && f->arg_size() == 3)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief Perform the strncpy optimization
|
||||
virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC)
|
||||
{
|
||||
// First, check to see if src and destination are the same. If they are,
|
||||
// then the optimization is to replace the CallInst with a constant 0
|
||||
// because the call is a no-op.
|
||||
Value* s1 = ci->getOperand(1);
|
||||
Value* s2 = ci->getOperand(2);
|
||||
if (s1 == s2)
|
||||
{
|
||||
// strncmp(x,x,l) -> 0
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy,0));
|
||||
ci->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the length argument, if it is Constant zero then the strings are
|
||||
// considered equal.
|
||||
uint64_t len_arg = 0;
|
||||
bool len_arg_is_const = false;
|
||||
if (ConstantInt* len_CI = dyn_cast<ConstantInt>(ci->getOperand(3)))
|
||||
{
|
||||
len_arg_is_const = true;
|
||||
len_arg = len_CI->getRawValue();
|
||||
if (len_arg == 0)
|
||||
{
|
||||
// strncmp(x,y,0) -> 0
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy,0));
|
||||
ci->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isstr_1 = false;
|
||||
uint64_t len_1 = 0;
|
||||
ConstantArray* A1;
|
||||
if (getConstantStringLength(s1,len_1,&A1))
|
||||
{
|
||||
isstr_1 = true;
|
||||
if (len_1 == 0)
|
||||
{
|
||||
// strncmp("",x) -> *x
|
||||
LoadInst* load = new LoadInst(s1,ci->getName()+".load",ci);
|
||||
CastInst* cast =
|
||||
new CastInst(load,Type::IntTy,ci->getName()+".int",ci);
|
||||
ci->replaceAllUsesWith(cast);
|
||||
ci->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isstr_2 = false;
|
||||
uint64_t len_2 = 0;
|
||||
ConstantArray* A2;
|
||||
if (getConstantStringLength(s2,len_2,&A2))
|
||||
{
|
||||
isstr_2 = true;
|
||||
if (len_2 == 0)
|
||||
{
|
||||
// strncmp(x,"") -> *x
|
||||
LoadInst* load = new LoadInst(s2,ci->getName()+".val",ci);
|
||||
CastInst* cast =
|
||||
new CastInst(load,Type::IntTy,ci->getName()+".int",ci);
|
||||
ci->replaceAllUsesWith(cast);
|
||||
ci->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isstr_1 && isstr_2 && len_arg_is_const)
|
||||
{
|
||||
// strncmp(x,y,const) -> constant
|
||||
std::string str1 = A1->getAsString();
|
||||
std::string str2 = A2->getAsString();
|
||||
int result = strncmp(str1.c_str(), str2.c_str(), len_arg);
|
||||
ci->replaceAllUsesWith(ConstantSInt::get(Type::IntTy,result));
|
||||
ci->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} StrNCmpOptimizer;
|
||||
|
||||
/// This LibCallOptimization will simplify a call to the strcpy library
|
||||
/// function. Two optimizations are possible:
|
||||
/// (1) If src and dest are the same and not volatile, just return dest
|
||||
@ -1276,24 +1377,11 @@ bool getConstantStringLength(Value* V, uint64_t& len, ConstantArray** CA )
|
||||
// (if c is a constant integer and s is a constant string)
|
||||
// * strrchr(s1,0) -> strchr(s1,0)
|
||||
//
|
||||
// strcmp:
|
||||
// * strcmp(x,x) -> 0
|
||||
// * strcmp(x,"") -> *x
|
||||
// * strcmp("",x) -> *x
|
||||
// * strcmp(x,y) -> cnst (if both x and y are constant strings)
|
||||
//
|
||||
// strncat:
|
||||
// * strncat(x,y,0) -> x
|
||||
// * strncat(x,y,0) -> x (if strlen(y) = 0)
|
||||
// * strncat(x,y,l) -> strcat(x,y) (if y and l are constants an l > strlen(y))
|
||||
//
|
||||
// strncmp:
|
||||
// * strncmp(x,y,0) -> 0
|
||||
// * strncmp(x,x,l) -> 0
|
||||
// * strncmp(x,"",l) -> *x
|
||||
// * strncmp("",x,l) -> *x
|
||||
// * strncmp(x,y,1) -> *x - *y
|
||||
//
|
||||
// strncpy:
|
||||
// * strncpy(d,s,0) -> d
|
||||
// * strncpy(d,s,l) -> memcpy(d,s,l,1)
|
||||
|
Loading…
Reference in New Issue
Block a user