use string length computation to generalize several xforms.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50464 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2008-04-30 03:07:53 +00:00
parent 21d972ad04
commit ea8650cddf

View File

@ -496,14 +496,13 @@ public:
Value *Dst = CI->getOperand(1);
Value *Src = CI->getOperand(2);
// Extract the initializer (while making numerous checks) from the
// source operand of the call to strcat.
std::string SrcStr;
if (!GetConstantStringInfo(Src, SrcStr))
return false;
// See if we can get the length of the input string.
uint64_t Len = GetStringLength(Src);
if (Len == 0) return false;
--Len; // Unbias length.
// Handle the simple, do-nothing case
if (SrcStr.empty())
if (Len == 0)
return ReplaceCallWith(CI, Dst);
// We need to find the end of the destination string. That's where the
@ -520,7 +519,7 @@ public:
// do the concatenation for us.
Value *Vals[] = {
Dst, Src,
ConstantInt::get(SLC.getIntPtrType(), SrcStr.size()+1), // copy nul byte.
ConstantInt::get(SLC.getIntPtrType(), Len+1), // copy nul byte.
ConstantInt::get(Type::Int32Ty, 1) // alignment
};
CallInst::Create(SLC.get_memcpy(), Vals, Vals + 4, "", CI);
@ -549,23 +548,29 @@ public:
/// @brief Perform the strchr optimizations
virtual bool OptimizeCall(CallInst *CI, SimplifyLibCalls &SLC) {
// Check that the first argument to strchr is a constant array of sbyte.
std::string Str;
if (!GetConstantStringInfo(CI->getOperand(1), Str))
return false;
// If the second operand is not constant, just lower this to memchr since we
// know the length of the input string.
Value *SrcStr = CI->getOperand(1);
// If the second operand is not constant, see if we can compute the length
// and turn this into memchr.
ConstantInt *CSI = dyn_cast<ConstantInt>(CI->getOperand(2));
if (!CSI) {
if (CSI == 0) {
uint64_t Len = GetStringLength(SrcStr);
if (Len == 0) return false;
Value *Args[3] = {
CI->getOperand(1),
CI->getOperand(2),
ConstantInt::get(SLC.getIntPtrType(), Str.size()+1)
ConstantInt::get(SLC.getIntPtrType(), Len) // include nul.
};
return ReplaceCallWith(CI, CallInst::Create(SLC.get_memchr(), Args, Args + 3,
return ReplaceCallWith(CI, CallInst::Create(SLC.get_memchr(),
Args, Args + 3,
CI->getName(), CI));
}
// Otherwise, the character is a constant, see if the first argument is
// a string literal. If so, we can constant fold.
std::string Str;
if (!GetConstantStringInfo(SrcStr, Str))
return false;
// strchr can find the nul character.
Str += '\0';
@ -747,14 +752,14 @@ public:
return ReplaceCallWith(CI, Dst);
}
// Get the length of the constant string referenced by the Src operand.
std::string SrcStr;
if (!GetConstantStringInfo(Src, SrcStr))
return false;
// See if we can get the length of the input string.
uint64_t Len = GetStringLength(Src);
if (Len == 0) return false;
--Len; // Unbias length.
// If the constant string's length is zero we can optimize this by just
// doing a store of 0 at the first byte of the destination
if (SrcStr.empty()) {
// doing a store of 0 at the first byte of the destination.
if (Len == 0) {
new StoreInst(ConstantInt::get(Type::Int8Ty, 0), Dst, CI);
return ReplaceCallWith(CI, Dst);
}
@ -762,8 +767,8 @@ public:
// We have enough information to now generate the memcpy call to
// do the concatenation for us.
Value *MemcpyOps[] = {
Dst, Src, // Pass length including nul byte.
ConstantInt::get(SLC.getIntPtrType(), SrcStr.size()+1),
Dst, Src,
ConstantInt::get(SLC.getIntPtrType(), Len+1),// Length including nul byte.
ConstantInt::get(Type::Int32Ty, 1) // alignment
};
CallInst::Create(SLC.get_memcpy(), MemcpyOps, MemcpyOps + 4, "", CI);
@ -1525,21 +1530,19 @@ public:
if (!CI->use_empty())
return false;
// All the optimizations depend on the length of the first argument and the
// fact that it is a constant string array. Check that now
std::string Str;
if (!GetConstantStringInfo(CI->getOperand(1), Str))
return false;
// All the optimizations depend on the length of the first argument.
uint64_t Len = GetStringLength(CI->getOperand(1));
if (!Len) return false;
const Type *FILETy = CI->getOperand(2)->getType();
// fputs(s,F) -> fwrite(s,1,len,F) (if s is constant and strlen(s) > 1)
Value *FWriteParms[4] = {
// fputs(s,F) -> fwrite(s,1,strlen(s),F)
Value *Ops[4] = {
CI->getOperand(1),
ConstantInt::get(SLC.getIntPtrType(), Str.size()),
ConstantInt::get(SLC.getIntPtrType(), Len-1),
ConstantInt::get(SLC.getIntPtrType(), 1),
CI->getOperand(2)
};
CallInst::Create(SLC.get_fwrite(FILETy), FWriteParms, FWriteParms + 4, "", CI);
CallInst::Create(SLC.get_fwrite(FILETy), Ops, Ops + 4, "", CI);
return ReplaceCallWith(CI, 0); // Known to have no uses (see above).
}
} FPutsOptimizer;