Teach SimplifyLibCalls how to optimize strrchr.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115091 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Benjamin Kramer 2010-09-29 21:50:51 +00:00
parent 1a30123b60
commit 06f25cfb33
2 changed files with 67 additions and 6 deletions

View File

@ -271,6 +271,47 @@ struct StrChrOpt : public LibCallOptimization {
}
};
//===---------------------------------------===//
// 'strrchr' Optimizations
struct StrRChrOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strrchr" function prototype.
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
FT->getReturnType() != Type::getInt8PtrTy(*Context) ||
FT->getParamType(0) != FT->getReturnType())
return 0;
Value *SrcStr = CI->getArgOperand(0);
ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
// Cannot fold anything if we're not looking for a constant.
if (!CharC)
return 0;
std::string Str;
if (!GetConstantStringInfo(SrcStr, Str)) {
// strrchr(s, 0) -> strchr(s, 0)
if (TD && CharC->isZero())
return EmitStrChr(SrcStr, '\0', B, TD);
return 0;
}
// strrchr can find the nul character.
Str += '\0';
// Compute the offset.
size_t I = Str.rfind(CharC->getSExtValue());
if (I == std::string::npos) // Didn't find the char. Return null.
return Constant::getNullValue(CI->getType());
// strrchr(s+n,c) -> gep(s+n+i,c)
Value *Idx = ConstantInt::get(Type::getInt64Ty(*Context), I);
return B.CreateGEP(SrcStr, Idx, "strrchr");
}
};
//===---------------------------------------===//
// 'strcmp' Optimizations
@ -1220,8 +1261,8 @@ namespace {
class SimplifyLibCalls : public FunctionPass {
StringMap<LibCallOptimization*> Optimizations;
// String and Memory LibCall Optimizations
StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrCmpOpt StrCmp;
StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrCpyOpt StrCpyChk;
StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrRChrOpt StrRChr;
StrCmpOpt StrCmp; StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrCpyOpt StrCpyChk;
StrNCpyOpt StrNCpy; StrLenOpt StrLen;
StrToOpt StrTo; StrStrOpt StrStr;
MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet;
@ -1269,6 +1310,7 @@ void SimplifyLibCalls::InitOptimizations() {
Optimizations["strcat"] = &StrCat;
Optimizations["strncat"] = &StrNCat;
Optimizations["strchr"] = &StrChr;
Optimizations["strrchr"] = &StrRChr;
Optimizations["strcmp"] = &StrCmp;
Optimizations["strncmp"] = &StrNCmp;
Optimizations["strcpy"] = &StrCpy;
@ -2173,10 +2215,6 @@ bool SimplifyLibCalls::doInitialization(Module &M) {
// 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)
// * strrchr(s1,0) -> strchr(s1,0)
//
// strpbrk:
// * strpbrk(s,a) -> offset_in_for(s,a)

View File

@ -0,0 +1,23 @@
; Test that the StrRChrOptimizer works correctly
; RUN: opt < %s -simplify-libcalls -S | FileCheck %s
target datalayout = "-p:64:64:64"
@hello = constant [14 x i8] c"hello world\5Cn\00"
@null = constant [1 x i8] zeroinitializer
declare i8* @strrchr(i8*, i32)
define void @foo(i8* %bar) {
%hello_p = getelementptr [14 x i8]* @hello, i32 0, i32 0
%null_p = getelementptr [1 x i8]* @null, i32 0, i32 0
%world = call i8* @strrchr(i8* %hello_p, i32 119)
; CHECK: getelementptr i8* %hello_p, i64 6
%ignore = call i8* @strrchr(i8* %null_p, i32 119)
; CHECK-NOT: call i8* strrchr
%null = call i8* @strrchr(i8* %hello_p, i32 0)
; CHECK: getelementptr i8* %hello_p, i64 13
%strchr = call i8* @strrchr(i8* %bar, i32 0)
; CHECK: call i8* @strchr(i8* %bar, i32 0)
ret void
}