1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

cleanups for strlen optimizer

llvm-svn: 35711
This commit is contained in:
Chris Lattner 2007-04-07 01:02:00 +00:00
parent 5f27ea3613
commit 312c204869

View File

@ -799,59 +799,46 @@ struct VISIBILITY_HIDDEN StrLenOptimization : public LibCallOptimization {
/// @brief Make sure that the "strlen" function has the right prototype /// @brief Make sure that the "strlen" function has the right prototype
virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){ virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
if (F->getReturnType() == SLC.getTargetData()->getIntPtrType()) const FunctionType *FT = F->getFunctionType();
if (F->arg_size() == 1) return FT->getNumParams() == 1 &&
if (Function::const_arg_iterator AI = F->arg_begin()) FT->getParamType(0) == PointerType::get(Type::Int8Ty) &&
if (AI->getType() == PointerType::get(Type::Int8Ty)) isa<IntegerType>(FT->getReturnType());
return true;
return false;
} }
/// @brief Perform the strlen optimization /// @brief Perform the strlen optimization
virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) virtual bool OptimizeCall(CallInst *CI, SimplifyLibCalls &SLC) {
{
// Make sure we're dealing with an sbyte* here. // Make sure we're dealing with an sbyte* here.
Value* str = ci->getOperand(1); Value *Str = CI->getOperand(1);
if (str->getType() != PointerType::get(Type::Int8Ty))
return false;
// Does the call to strlen have exactly one use? // Does the call to strlen have exactly one use?
if (ci->hasOneUse()) if (CI->hasOneUse()) {
// Is that single use a icmp operator? // Is that single use a icmp operator?
if (ICmpInst* bop = dyn_cast<ICmpInst>(ci->use_back())) if (ICmpInst *Cmp = dyn_cast<ICmpInst>(CI->use_back()))
// Is it compared against a constant integer? // Is it compared against a constant integer?
if (ConstantInt* CI = dyn_cast<ConstantInt>(bop->getOperand(1))) if (ConstantInt *Cst = dyn_cast<ConstantInt>(Cmp->getOperand(1))) {
{
// Get the value the strlen result is compared to
uint64_t val = CI->getZExtValue();
// If its compared against length 0 with == or != // If its compared against length 0 with == or !=
if (val == 0 && if (Cst->getZExtValue() == 0 && Cmp->isEquality()) {
(bop->getPredicate() == ICmpInst::ICMP_EQ ||
bop->getPredicate() == ICmpInst::ICMP_NE))
{
// strlen(x) != 0 -> *x != 0 // strlen(x) != 0 -> *x != 0
// strlen(x) == 0 -> *x == 0 // strlen(x) == 0 -> *x == 0
LoadInst* load = new LoadInst(str,str->getName()+".first",ci); Value *V = new LoadInst(Str, Str->getName()+".first", CI);
ICmpInst* rbop = new ICmpInst(bop->getPredicate(), load, V = new ICmpInst(Cmp->getPredicate(), V,
ConstantInt::get(Type::Int8Ty,0), ConstantInt::get(Type::Int8Ty, 0),
bop->getName()+".strlen", ci); Cmp->getName()+".strlen", CI);
bop->replaceAllUsesWith(rbop); Cmp->replaceAllUsesWith(V);
bop->eraseFromParent(); Cmp->eraseFromParent();
ci->eraseFromParent(); return ReplaceCallWith(CI, 0); // no uses.
return true;
} }
} }
}
// Get the length of the constant string operand // Get the length of the constant string operand
uint64_t len = 0, StartIdx; uint64_t StrLen = 0, StartIdx;
ConstantArray *A; ConstantArray *A;
if (!GetConstantStringInfo(ci->getOperand(1), A, len, StartIdx)) if (!GetConstantStringInfo(CI->getOperand(1), A, StrLen, StartIdx))
return false; return false;
// strlen("xyz") -> 3 (for example) // strlen("xyz") -> 3 (for example)
const Type *Ty = SLC.getTargetData()->getIntPtrType(); return ReplaceCallWith(CI, ConstantInt::get(CI->getType(), StrLen));
return ReplaceCallWith(ci, ConstantInt::get(Ty, len));
} }
} StrLenOptimizer; } StrLenOptimizer;