From 476bfb7a1043f5aa07e23bef9188542b9bea3bd1 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Wed, 29 Sep 2010 23:52:12 +0000 Subject: [PATCH] Add strpbrk folding to SimplifyLibCalls. llvm-svn: 115111 --- lib/Transforms/Scalar/SimplifyLibCalls.cpp | 49 ++++++++++++++++++--- test/Transforms/SimplifyLibCalls/StrPBrk.ll | 25 +++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 test/Transforms/SimplifyLibCalls/StrPBrk.ll diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 75754a55854..c4787c82f53 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -522,6 +522,46 @@ struct StrLenOpt : public LibCallOptimization { } }; + +//===---------------------------------------===// +// 'strpbrk' Optimizations + +struct StrPBrkOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || + FT->getParamType(0) != Type::getInt8PtrTy(*Context) || + FT->getParamType(1) != FT->getParamType(0) || + FT->getReturnType() != FT->getParamType(0)) + return 0; + + std::string S1, S2; + bool HasS1 = GetConstantStringInfo(CI->getArgOperand(0), S1); + bool HasS2 = GetConstantStringInfo(CI->getArgOperand(1), S2); + + // strpbrk(s, "") -> NULL + // strpbrk("", s) -> NULL + if ((HasS1 && S1.empty()) || (HasS2 && S2.empty())) + return Constant::getNullValue(CI->getType()); + + // Constant folding. + if (HasS1 && HasS2) { + size_t I = S1.find_first_of(S2); + if (I == std::string::npos) // No match. + return Constant::getNullValue(CI->getType()); + + Value *Idx = ConstantInt::get(Type::getInt64Ty(*Context), I); + return B.CreateGEP(CI->getArgOperand(0), Idx, "strpbrk"); + } + + // strpbrk(s, "a") -> strchr(s, 'a') + if (TD && HasS2 && S2.size() == 1) + return EmitStrChr(CI->getArgOperand(0), S2[0], B, TD); + + return 0; + } +}; + //===---------------------------------------===// // 'strto*' Optimizations. This handles strtol, strtod, strtof, strtoul, etc. @@ -1256,7 +1296,7 @@ namespace { // String and Memory LibCall Optimizations StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrRChrOpt StrRChr; StrCmpOpt StrCmp; StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrCpyOpt StrCpyChk; - StrNCpyOpt StrNCpy; StrLenOpt StrLen; + StrNCpyOpt StrNCpy; StrLenOpt StrLen; StrPBrkOpt StrPBrk; StrToOpt StrTo; StrStrOpt StrStr; MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet; // Math Library Optimizations @@ -1309,6 +1349,7 @@ void SimplifyLibCalls::InitOptimizations() { Optimizations["strcpy"] = &StrCpy; Optimizations["strncpy"] = &StrNCpy; Optimizations["strlen"] = &StrLen; + Optimizations["strpbrk"] = &StrPBrk; Optimizations["strtol"] = &StrTo; Optimizations["strtod"] = &StrTo; Optimizations["strtof"] = &StrTo; @@ -2209,12 +2250,6 @@ bool SimplifyLibCalls::doInitialization(Module &M) { // * stpcpy(str, "literal") -> // llvm.memcpy(str,"literal",strlen("literal")+1,1) // -// strpbrk: -// * strpbrk(s,a) -> offset_in_for(s,a) -// (if s and a are both constant strings) -// * strpbrk(s,"") -> 0 -// * strpbrk(s,a) -> strchr(s,a[0]) (if a is constant string of length 1) -// // strspn, strcspn: // * strspn(s,a) -> const_int (if both args are constant) // * strspn("",a) -> 0 diff --git a/test/Transforms/SimplifyLibCalls/StrPBrk.ll b/test/Transforms/SimplifyLibCalls/StrPBrk.ll new file mode 100644 index 00000000000..29c3b7477b4 --- /dev/null +++ b/test/Transforms/SimplifyLibCalls/StrPBrk.ll @@ -0,0 +1,25 @@ +; RUN: opt < %s -simplify-libcalls -S | FileCheck %s + +target datalayout = "-p:64:64:64" + +@hello = constant [12 x i8] c"hello world\00" +@w = constant [2 x i8] c"w\00" +@null = constant [1 x i8] zeroinitializer + +declare i8* @strpbrk(i8*, i8*) + +define void @test(i8* %s1, i8* %s2) { + %hello_p = getelementptr [12 x i8]* @hello, i32 0, i32 0 + %w_p = getelementptr [2 x i8]* @w, i32 0, i32 0 + %null_p = getelementptr [1 x i8]* @null, i32 0, i32 0 + %test1 = call i8* @strpbrk(i8* %null_p, i8* %s2) + %test2 = call i8* @strpbrk(i8* %s1, i8* %null_p) +; CHECK-NOT: call i8* @strpbrk + %test3 = call i8* @strpbrk(i8* %s1, i8* %w_p) +; CHECK: call i8* @strchr(i8* %s1, i32 119) + %test4 = call i8* @strpbrk(i8* %hello_p, i8* %w_p) +; CHECK: getelementptr i8* %hello_p, i64 6 + %test5 = call i8* @strpbrk(i8* %s1, i8* %s2) +; CHECK: call i8* @strpbrk(i8* %s1, i8* %s2) + ret void +}