mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-04 18:24:38 +00:00
instcombine: Migrate strcat and strncat optimizations
This patch migrates the strcat and strncat optimizations from the simplify-libcalls pass into the instcombine library call simplifier. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165874 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -133,105 +133,7 @@ static bool IsOnlyUsedInEqualityComparison(Value *V, Value *With) {
|
||||
// String and Memory LibCall Optimizations
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===---------------------------------------===//
|
||||
// 'strcat' Optimizations
|
||||
namespace {
|
||||
struct StrCatOpt : public LibCallOptimization {
|
||||
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
|
||||
// Verify the "strcat" function prototype.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 ||
|
||||
FT->getReturnType() != B.getInt8PtrTy() ||
|
||||
FT->getParamType(0) != FT->getReturnType() ||
|
||||
FT->getParamType(1) != FT->getReturnType())
|
||||
return 0;
|
||||
|
||||
// Extract some information from the instruction
|
||||
Value *Dst = CI->getArgOperand(0);
|
||||
Value *Src = CI->getArgOperand(1);
|
||||
|
||||
// See if we can get the length of the input string.
|
||||
uint64_t Len = GetStringLength(Src);
|
||||
if (Len == 0) return 0;
|
||||
--Len; // Unbias length.
|
||||
|
||||
// Handle the simple, do-nothing case: strcat(x, "") -> x
|
||||
if (Len == 0)
|
||||
return Dst;
|
||||
|
||||
// These optimizations require DataLayout.
|
||||
if (!TD) return 0;
|
||||
|
||||
return EmitStrLenMemCpy(Src, Dst, Len, B);
|
||||
}
|
||||
|
||||
Value *EmitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B) {
|
||||
// We need to find the end of the destination string. That's where the
|
||||
// memory is to be moved to. We just generate a call to strlen.
|
||||
Value *DstLen = EmitStrLen(Dst, B, TD, TLI);
|
||||
if (!DstLen)
|
||||
return 0;
|
||||
|
||||
// Now that we have the destination's length, we must index into the
|
||||
// destination's pointer to get the actual memcpy destination (end of
|
||||
// the string .. we're concatenating).
|
||||
Value *CpyDst = B.CreateGEP(Dst, DstLen, "endptr");
|
||||
|
||||
// We have enough information to now generate the memcpy call to do the
|
||||
// concatenation for us. Make a memcpy to copy the nul byte with align = 1.
|
||||
B.CreateMemCpy(CpyDst, Src,
|
||||
ConstantInt::get(TD->getIntPtrType(*Context), Len + 1), 1);
|
||||
return Dst;
|
||||
}
|
||||
};
|
||||
|
||||
//===---------------------------------------===//
|
||||
// 'strncat' Optimizations
|
||||
|
||||
struct StrNCatOpt : public StrCatOpt {
|
||||
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
|
||||
// Verify the "strncat" function prototype.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 3 ||
|
||||
FT->getReturnType() != B.getInt8PtrTy() ||
|
||||
FT->getParamType(0) != FT->getReturnType() ||
|
||||
FT->getParamType(1) != FT->getReturnType() ||
|
||||
!FT->getParamType(2)->isIntegerTy())
|
||||
return 0;
|
||||
|
||||
// Extract some information from the instruction
|
||||
Value *Dst = CI->getArgOperand(0);
|
||||
Value *Src = CI->getArgOperand(1);
|
||||
uint64_t Len;
|
||||
|
||||
// We don't do anything if length is not constant
|
||||
if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(CI->getArgOperand(2)))
|
||||
Len = LengthArg->getZExtValue();
|
||||
else
|
||||
return 0;
|
||||
|
||||
// See if we can get the length of the input string.
|
||||
uint64_t SrcLen = GetStringLength(Src);
|
||||
if (SrcLen == 0) return 0;
|
||||
--SrcLen; // Unbias length.
|
||||
|
||||
// Handle the simple, do-nothing cases:
|
||||
// strncat(x, "", c) -> x
|
||||
// strncat(x, c, 0) -> x
|
||||
if (SrcLen == 0 || Len == 0) return Dst;
|
||||
|
||||
// These optimizations require DataLayout.
|
||||
if (!TD) return 0;
|
||||
|
||||
// We don't optimize this case
|
||||
if (Len < SrcLen) return 0;
|
||||
|
||||
// strncat(x, s, c) -> strcat(x, s)
|
||||
// s is constant so the strcat can be optimized further
|
||||
return EmitStrLenMemCpy(Src, Dst, SrcLen, B);
|
||||
}
|
||||
};
|
||||
|
||||
//===---------------------------------------===//
|
||||
// 'strchr' Optimizations
|
||||
|
||||
@ -1564,7 +1466,7 @@ namespace {
|
||||
|
||||
StringMap<LibCallOptimization*> Optimizations;
|
||||
// String and Memory LibCall Optimizations
|
||||
StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrRChrOpt StrRChr;
|
||||
StrChrOpt StrChr; StrRChrOpt StrRChr;
|
||||
StrCmpOpt StrCmp; StrNCmpOpt StrNCmp;
|
||||
StrCpyOpt StrCpy; StrCpyOpt StrCpyChk;
|
||||
StpCpyOpt StpCpy; StpCpyOpt StpCpyChk;
|
||||
@ -1639,8 +1541,6 @@ void SimplifyLibCalls::AddOpt(LibFunc::Func F1, LibFunc::Func F2,
|
||||
/// we know.
|
||||
void SimplifyLibCalls::InitOptimizations() {
|
||||
// String and Memory LibCall Optimizations
|
||||
Optimizations["strcat"] = &StrCat;
|
||||
Optimizations["strncat"] = &StrNCat;
|
||||
Optimizations["strchr"] = &StrChr;
|
||||
Optimizations["strrchr"] = &StrRChr;
|
||||
Optimizations["strcmp"] = &StrCmp;
|
||||
|
Reference in New Issue
Block a user