use string length computation to generalize several xforms.

llvm-svn: 50464
This commit is contained in:
Chris Lattner 2008-04-30 03:07:53 +00:00
parent c110c4a526
commit 438e35c4d1
1 changed files with 39 additions and 36 deletions

View File

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