mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
Add constant folding for strspn and strcspn to SimplifyLibCalls.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115116 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1340,12 +1340,6 @@ void foo (int a, struct T b)
|
|||||||
|
|
||||||
simplifylibcalls should do several optimizations for strspn/strcspn:
|
simplifylibcalls should do several optimizations for strspn/strcspn:
|
||||||
|
|
||||||
strcspn(x, "") -> strlen(x)
|
|
||||||
strcspn("", x) -> 0
|
|
||||||
strspn("", x) -> 0
|
|
||||||
strspn(x, "") -> strlen(x)
|
|
||||||
strspn(x, "a") -> strchr(x, 'a')-x
|
|
||||||
|
|
||||||
strcspn(x, "a") -> inlined loop for up to 3 letters (similarly for strspn):
|
strcspn(x, "a") -> inlined loop for up to 3 letters (similarly for strspn):
|
||||||
|
|
||||||
size_t __strcspn_c3 (__const char *__s, int __reject1, int __reject2,
|
size_t __strcspn_c3 (__const char *__s, int __reject1, int __reject2,
|
||||||
|
@@ -583,6 +583,67 @@ struct StrToOpt : public LibCallOptimization {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//===---------------------------------------===//
|
||||||
|
// 'strspn' Optimizations
|
||||||
|
|
||||||
|
struct StrSpnOpt : 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()->isIntegerTy())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
std::string S1, S2;
|
||||||
|
bool HasS1 = GetConstantStringInfo(CI->getArgOperand(0), S1);
|
||||||
|
bool HasS2 = GetConstantStringInfo(CI->getArgOperand(1), S2);
|
||||||
|
|
||||||
|
// strspn(s, "") -> 0
|
||||||
|
// strspn("", s) -> 0
|
||||||
|
if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))
|
||||||
|
return Constant::getNullValue(CI->getType());
|
||||||
|
|
||||||
|
// Constant folding.
|
||||||
|
if (HasS1 && HasS2)
|
||||||
|
return ConstantInt::get(CI->getType(), strspn(S1.c_str(), S2.c_str()));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//===---------------------------------------===//
|
||||||
|
// 'strcspn' Optimizations
|
||||||
|
|
||||||
|
struct StrCSpnOpt : 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()->isIntegerTy())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
std::string S1, S2;
|
||||||
|
bool HasS1 = GetConstantStringInfo(CI->getArgOperand(0), S1);
|
||||||
|
bool HasS2 = GetConstantStringInfo(CI->getArgOperand(1), S2);
|
||||||
|
|
||||||
|
// strcspn("", s) -> 0
|
||||||
|
if (HasS1 && S1.empty())
|
||||||
|
return Constant::getNullValue(CI->getType());
|
||||||
|
|
||||||
|
// Constant folding.
|
||||||
|
if (HasS1 && HasS2)
|
||||||
|
return ConstantInt::get(CI->getType(), strcspn(S1.c_str(), S2.c_str()));
|
||||||
|
|
||||||
|
// strcspn(s, "") -> strlen(s)
|
||||||
|
if (TD && HasS2 && S2.empty())
|
||||||
|
return EmitStrLen(CI->getArgOperand(0), B, TD);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//===---------------------------------------===//
|
//===---------------------------------------===//
|
||||||
// 'strstr' Optimizations
|
// 'strstr' Optimizations
|
||||||
|
|
||||||
@@ -1297,7 +1358,7 @@ namespace {
|
|||||||
StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrRChrOpt StrRChr;
|
StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrRChrOpt StrRChr;
|
||||||
StrCmpOpt StrCmp; StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrCpyOpt StrCpyChk;
|
StrCmpOpt StrCmp; StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrCpyOpt StrCpyChk;
|
||||||
StrNCpyOpt StrNCpy; StrLenOpt StrLen; StrPBrkOpt StrPBrk;
|
StrNCpyOpt StrNCpy; StrLenOpt StrLen; StrPBrkOpt StrPBrk;
|
||||||
StrToOpt StrTo; StrStrOpt StrStr;
|
StrToOpt StrTo; StrSpnOpt StrSpn; StrCSpnOpt StrCSpn; StrStrOpt StrStr;
|
||||||
MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet;
|
MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet;
|
||||||
// Math Library Optimizations
|
// Math Library Optimizations
|
||||||
PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP;
|
PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP;
|
||||||
@@ -1357,6 +1418,8 @@ void SimplifyLibCalls::InitOptimizations() {
|
|||||||
Optimizations["strtoll"] = &StrTo;
|
Optimizations["strtoll"] = &StrTo;
|
||||||
Optimizations["strtold"] = &StrTo;
|
Optimizations["strtold"] = &StrTo;
|
||||||
Optimizations["strtoull"] = &StrTo;
|
Optimizations["strtoull"] = &StrTo;
|
||||||
|
Optimizations["strspn"] = &StrSpn;
|
||||||
|
Optimizations["strcspn"] = &StrCSpn;
|
||||||
Optimizations["strstr"] = &StrStr;
|
Optimizations["strstr"] = &StrStr;
|
||||||
Optimizations["memcmp"] = &MemCmp;
|
Optimizations["memcmp"] = &MemCmp;
|
||||||
Optimizations["memcpy"] = &MemCpy;
|
Optimizations["memcpy"] = &MemCpy;
|
||||||
@@ -2250,14 +2313,6 @@ bool SimplifyLibCalls::doInitialization(Module &M) {
|
|||||||
// * stpcpy(str, "literal") ->
|
// * stpcpy(str, "literal") ->
|
||||||
// llvm.memcpy(str,"literal",strlen("literal")+1,1)
|
// llvm.memcpy(str,"literal",strlen("literal")+1,1)
|
||||||
//
|
//
|
||||||
// strspn, strcspn:
|
|
||||||
// * strspn(s,a) -> const_int (if both args are constant)
|
|
||||||
// * strspn("",a) -> 0
|
|
||||||
// * strspn(s,"") -> 0
|
|
||||||
// * strcspn(s,a) -> const_int (if both args are constant)
|
|
||||||
// * strcspn("",a) -> 0
|
|
||||||
// * strcspn(s,"") -> strlen(a)
|
|
||||||
//
|
|
||||||
// tan, tanf, tanl:
|
// tan, tanf, tanl:
|
||||||
// * tan(atan(x)) -> x
|
// * tan(atan(x)) -> x
|
||||||
//
|
//
|
||||||
|
41
test/Transforms/SimplifyLibCalls/StrSpn.ll
Normal file
41
test/Transforms/SimplifyLibCalls/StrSpn.ll
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
; RUN: opt < %s -simplify-libcalls -S | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "-p:64:64:64"
|
||||||
|
|
||||||
|
@abcba = constant [6 x i8] c"abcba\00"
|
||||||
|
@abc = constant [4 x i8] c"abc\00"
|
||||||
|
@null = constant [1 x i8] zeroinitializer
|
||||||
|
|
||||||
|
declare i64 @strspn(i8*, i8*)
|
||||||
|
|
||||||
|
define i64 @testspn(i8* %s1, i8* %s2) {
|
||||||
|
%abcba_p = getelementptr [6 x i8]* @abcba, i32 0, i32 0
|
||||||
|
%abc_p = getelementptr [4 x i8]* @abc, i32 0, i32 0
|
||||||
|
%null_p = getelementptr [1 x i8]* @null, i32 0, i32 0
|
||||||
|
%test1 = call i64 @strspn(i8* %s1, i8* %null_p)
|
||||||
|
%test2 = call i64 @strspn(i8* %null_p, i8* %s2)
|
||||||
|
%test3 = call i64 @strspn(i8* %abcba_p, i8* %abc_p)
|
||||||
|
; CHECK-NOT: call i64 @strspn
|
||||||
|
%test4 = call i64 @strspn(i8* %s1, i8* %s2)
|
||||||
|
; CHECK: call i64 @strspn(i8* %s1, i8* %s2)
|
||||||
|
ret i64 %test3
|
||||||
|
; CHECK ret i64 5
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i64 @strcspn(i8*, i8*)
|
||||||
|
|
||||||
|
define i64 @testcspn(i8* %s1, i8* %s2) {
|
||||||
|
%abcba_p = getelementptr [6 x i8]* @abcba, i32 0, i32 0
|
||||||
|
%abc_p = getelementptr [4 x i8]* @abc, i32 0, i32 0
|
||||||
|
%null_p = getelementptr [1 x i8]* @null, i32 0, i32 0
|
||||||
|
%test1 = call i64 @strcspn(i8* %s1, i8* %null_p)
|
||||||
|
; CHECK: call i64 @strlen(i8* %s1)
|
||||||
|
%test2 = call i64 @strcspn(i8* %null_p, i8* %s2)
|
||||||
|
%test3 = call i64 @strcspn(i8* %abcba_p, i8* %abc_p)
|
||||||
|
; CHECK-NOT: call i64 @strcspn
|
||||||
|
%test4 = call i64 @strcspn(i8* %s1, i8* %s2)
|
||||||
|
; CHECK: call i64 @strcspn(i8* %s1, i8* %s2)
|
||||||
|
%add0 = add i64 %test1, %test3
|
||||||
|
; CHECK: add i64 %{{.+}}, 0
|
||||||
|
ret i64 %add0
|
||||||
|
}
|
Reference in New Issue
Block a user