forked from OSchip/llvm-project
Introduce a new ReplaceCallWith method, which simplifies a lot of code.
llvm-svn: 35710
This commit is contained in:
parent
6a6c1f1c30
commit
485b6415b1
|
@ -126,6 +126,13 @@ public:
|
||||||
/// @brief Get the name of the library call being optimized
|
/// @brief Get the name of the library call being optimized
|
||||||
const char *getFunctionName() const { return FunctionName; }
|
const char *getFunctionName() const { return FunctionName; }
|
||||||
|
|
||||||
|
bool ReplaceCallWith(CallInst *CI, Value *V) {
|
||||||
|
if (!CI->use_empty())
|
||||||
|
CI->replaceAllUsesWith(V);
|
||||||
|
CI->eraseFromParent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Called by SimplifyLibCalls to update the occurrences statistic.
|
/// @brief Called by SimplifyLibCalls to update the occurrences statistic.
|
||||||
void succeeded() {
|
void succeeded() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -487,11 +494,8 @@ public:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Handle the simple, do-nothing case
|
// Handle the simple, do-nothing case
|
||||||
if (SrcLength == 0) {
|
if (SrcLength == 0)
|
||||||
CI->replaceAllUsesWith(Dst);
|
return ReplaceCallWith(CI, Dst);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
// memory is to be moved to. We just generate a call to strlen (further
|
// memory is to be moved to. We just generate a call to strlen (further
|
||||||
|
@ -513,12 +517,7 @@ public:
|
||||||
};
|
};
|
||||||
new CallInst(SLC.get_memcpy(), Vals, 4, "", CI);
|
new CallInst(SLC.get_memcpy(), Vals, 4, "", CI);
|
||||||
|
|
||||||
// Finally, substitute the first operand of the strcat call for the
|
return ReplaceCallWith(CI, Dst);
|
||||||
// strcat call itself since strcat returns its first operand; and,
|
|
||||||
// kill the strcat CallInst.
|
|
||||||
CI->replaceAllUsesWith(Dst);
|
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} StrCatOptimizer;
|
} StrCatOptimizer;
|
||||||
|
|
||||||
|
@ -558,10 +557,8 @@ public:
|
||||||
CI->getOperand(2),
|
CI->getOperand(2),
|
||||||
ConstantInt::get(SLC.getIntPtrType(), StrLength+1)
|
ConstantInt::get(SLC.getIntPtrType(), StrLength+1)
|
||||||
};
|
};
|
||||||
CI->replaceAllUsesWith(new CallInst(SLC.get_memchr(), Args, 3,
|
return ReplaceCallWith(CI, new CallInst(SLC.get_memchr(), Args, 3,
|
||||||
CI->getName(), CI));
|
CI->getName(), CI));
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the character we're looking for
|
// Get the character we're looking for
|
||||||
|
@ -570,14 +567,10 @@ public:
|
||||||
if (StrLength == 0) {
|
if (StrLength == 0) {
|
||||||
// If the length of the string is zero, and we are searching for zero,
|
// If the length of the string is zero, and we are searching for zero,
|
||||||
// return the input pointer.
|
// return the input pointer.
|
||||||
if (CharValue == 0) {
|
if (CharValue == 0)
|
||||||
CI->replaceAllUsesWith(CI->getOperand(1));
|
return ReplaceCallWith(CI, CI->getOperand(1));
|
||||||
} else {
|
// Otherwise, char wasn't found.
|
||||||
// Otherwise, char wasn't found.
|
return ReplaceCallWith(CI, Constant::getNullValue(CI->getType()));
|
||||||
CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
|
|
||||||
}
|
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the offset
|
// Compute the offset
|
||||||
|
@ -588,12 +581,8 @@ public:
|
||||||
// Did we find our match?
|
// Did we find our match?
|
||||||
if (C->getSExtValue() == CharValue)
|
if (C->getSExtValue() == CharValue)
|
||||||
break;
|
break;
|
||||||
if (C->isZero()) {
|
if (C->isZero()) // We found the end of the string. strchr returns null.
|
||||||
// We found the end of the string. strchr returns null.
|
return ReplaceCallWith(CI, Constant::getNullValue(CI->getType()));
|
||||||
CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
|
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -604,9 +593,7 @@ public:
|
||||||
Value *GEP = new GetElementPtrInst(CI->getOperand(1), Idx,
|
Value *GEP = new GetElementPtrInst(CI->getOperand(1), Idx,
|
||||||
CI->getOperand(1)->getName() +
|
CI->getOperand(1)->getName() +
|
||||||
".strchr", CI);
|
".strchr", CI);
|
||||||
CI->replaceAllUsesWith(GEP);
|
return ReplaceCallWith(CI, GEP);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} StrChrOptimizer;
|
} StrChrOptimizer;
|
||||||
|
|
||||||
|
@ -634,12 +621,8 @@ public:
|
||||||
// because the call is a no-op.
|
// because the call is a no-op.
|
||||||
Value *Str1P = CI->getOperand(1);
|
Value *Str1P = CI->getOperand(1);
|
||||||
Value *Str2P = CI->getOperand(2);
|
Value *Str2P = CI->getOperand(2);
|
||||||
if (Str1P == Str2P) {
|
if (Str1P == Str2P) // strcmp(x,x) -> 0
|
||||||
// strcmp(x,x) -> 0
|
return ReplaceCallWith(CI, ConstantInt::get(CI->getType(), 0));
|
||||||
CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 0));
|
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t Str1Len, Str1StartIdx;
|
uint64_t Str1Len, Str1StartIdx;
|
||||||
ConstantArray *A1;
|
ConstantArray *A1;
|
||||||
|
@ -648,9 +631,7 @@ public:
|
||||||
// strcmp("", x) -> *x
|
// strcmp("", x) -> *x
|
||||||
Value *V = new LoadInst(Str2P, CI->getName()+".load", CI);
|
Value *V = new LoadInst(Str2P, CI->getName()+".load", CI);
|
||||||
V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
|
V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
|
||||||
CI->replaceAllUsesWith(V);
|
return ReplaceCallWith(CI, V);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Str2Len, Str2StartIdx;
|
uint64_t Str2Len, Str2StartIdx;
|
||||||
|
@ -660,9 +641,7 @@ public:
|
||||||
// strcmp(x,"") -> *x
|
// strcmp(x,"") -> *x
|
||||||
Value *V = new LoadInst(Str1P, CI->getName()+".load", CI);
|
Value *V = new LoadInst(Str1P, CI->getName()+".load", CI);
|
||||||
V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
|
V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
|
||||||
CI->replaceAllUsesWith(V);
|
return ReplaceCallWith(CI, V);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Str1IsCst && Str2IsCst && A1->isCString() && A2->isCString()) {
|
if (Str1IsCst && Str2IsCst && A1->isCString() && A2->isCString()) {
|
||||||
|
@ -670,9 +649,7 @@ public:
|
||||||
std::string S1 = A1->getAsString();
|
std::string S1 = A1->getAsString();
|
||||||
std::string S2 = A2->getAsString();
|
std::string S2 = A2->getAsString();
|
||||||
int R = strcmp(S1.c_str()+Str1StartIdx, S2.c_str()+Str2StartIdx);
|
int R = strcmp(S1.c_str()+Str1StartIdx, S2.c_str()+Str2StartIdx);
|
||||||
CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), R));
|
return ReplaceCallWith(CI, ConstantInt::get(CI->getType(), R));
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -704,12 +681,8 @@ public:
|
||||||
// because the call is a no-op.
|
// because the call is a no-op.
|
||||||
Value *Str1P = CI->getOperand(1);
|
Value *Str1P = CI->getOperand(1);
|
||||||
Value *Str2P = CI->getOperand(2);
|
Value *Str2P = CI->getOperand(2);
|
||||||
if (Str1P == Str2P) {
|
if (Str1P == Str2P) // strncmp(x,x) -> 0
|
||||||
// strncmp(x,x) -> 0
|
return ReplaceCallWith(CI, ConstantInt::get(CI->getType(), 0));
|
||||||
CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 0));
|
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the length argument, if it is Constant zero then the strings are
|
// Check the length argument, if it is Constant zero then the strings are
|
||||||
// considered equal.
|
// considered equal.
|
||||||
|
@ -721,9 +694,7 @@ public:
|
||||||
|
|
||||||
if (Length == 0) {
|
if (Length == 0) {
|
||||||
// strncmp(x,y,0) -> 0
|
// strncmp(x,y,0) -> 0
|
||||||
CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 0));
|
return ReplaceCallWith(CI, ConstantInt::get(CI->getType(), 0));
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Str1Len, Str1StartIdx;
|
uint64_t Str1Len, Str1StartIdx;
|
||||||
|
@ -733,9 +704,7 @@ public:
|
||||||
// strncmp("", x) -> *x
|
// strncmp("", x) -> *x
|
||||||
Value *V = new LoadInst(Str2P, CI->getName()+".load", CI);
|
Value *V = new LoadInst(Str2P, CI->getName()+".load", CI);
|
||||||
V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
|
V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
|
||||||
CI->replaceAllUsesWith(V);
|
return ReplaceCallWith(CI, V);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Str2Len, Str2StartIdx;
|
uint64_t Str2Len, Str2StartIdx;
|
||||||
|
@ -745,9 +714,7 @@ public:
|
||||||
// strncmp(x,"") -> *x
|
// strncmp(x,"") -> *x
|
||||||
Value *V = new LoadInst(Str1P, CI->getName()+".load", CI);
|
Value *V = new LoadInst(Str1P, CI->getName()+".load", CI);
|
||||||
V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
|
V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
|
||||||
CI->replaceAllUsesWith(V);
|
return ReplaceCallWith(CI, V);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Str1IsCst && Str2IsCst && A1->isCString() &&
|
if (Str1IsCst && Str2IsCst && A1->isCString() &&
|
||||||
|
@ -756,9 +723,7 @@ public:
|
||||||
std::string S1 = A1->getAsString();
|
std::string S1 = A1->getAsString();
|
||||||
std::string S2 = A2->getAsString();
|
std::string S2 = A2->getAsString();
|
||||||
int R = strncmp(S1.c_str()+Str1StartIdx, S2.c_str()+Str2StartIdx, Length);
|
int R = strncmp(S1.c_str()+Str1StartIdx, S2.c_str()+Str2StartIdx, Length);
|
||||||
CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), R));
|
return ReplaceCallWith(CI, ConstantInt::get(CI->getType(), R));
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -795,9 +760,7 @@ public:
|
||||||
Value *Src = CI->getOperand(2);
|
Value *Src = CI->getOperand(2);
|
||||||
if (Dst == Src) {
|
if (Dst == Src) {
|
||||||
// strcpy(x, x) -> x
|
// strcpy(x, x) -> x
|
||||||
CI->replaceAllUsesWith(Dst);
|
return ReplaceCallWith(CI, Dst);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the length of the constant string referenced by the Src operand.
|
// Get the length of the constant string referenced by the Src operand.
|
||||||
|
@ -810,9 +773,7 @@ public:
|
||||||
// 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 (SrcLen == 0) {
|
if (SrcLen == 0) {
|
||||||
new StoreInst(ConstantInt::get(Type::Int8Ty, 0), Dst, CI);
|
new StoreInst(ConstantInt::get(Type::Int8Ty, 0), Dst, CI);
|
||||||
CI->replaceAllUsesWith(Dst);
|
return ReplaceCallWith(CI, Dst);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have enough information to now generate the memcpy call to
|
// We have enough information to now generate the memcpy call to
|
||||||
|
@ -824,9 +785,7 @@ public:
|
||||||
};
|
};
|
||||||
new CallInst(SLC.get_memcpy(), MemcpyOps, 4, "", CI);
|
new CallInst(SLC.get_memcpy(), MemcpyOps, 4, "", CI);
|
||||||
|
|
||||||
CI->replaceAllUsesWith(Dst);
|
return ReplaceCallWith(CI, Dst);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} StrCpyOptimizer;
|
} StrCpyOptimizer;
|
||||||
|
|
||||||
|
@ -840,9 +799,9 @@ struct VISIBILITY_HIDDEN StrLenOptimization : public LibCallOptimization {
|
||||||
|
|
||||||
/// @brief Make sure that the "strlen" function has the right prototype
|
/// @brief Make sure that the "strlen" function has the right prototype
|
||||||
virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
|
virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
|
||||||
if (f->getReturnType() == SLC.getTargetData()->getIntPtrType())
|
if (F->getReturnType() == SLC.getTargetData()->getIntPtrType())
|
||||||
if (f->arg_size() == 1)
|
if (F->arg_size() == 1)
|
||||||
if (Function::const_arg_iterator AI = f->arg_begin())
|
if (Function::const_arg_iterator AI = F->arg_begin())
|
||||||
if (AI->getType() == PointerType::get(Type::Int8Ty))
|
if (AI->getType() == PointerType::get(Type::Int8Ty))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -892,10 +851,7 @@ struct VISIBILITY_HIDDEN StrLenOptimization : public LibCallOptimization {
|
||||||
|
|
||||||
// strlen("xyz") -> 3 (for example)
|
// strlen("xyz") -> 3 (for example)
|
||||||
const Type *Ty = SLC.getTargetData()->getIntPtrType();
|
const Type *Ty = SLC.getTargetData()->getIntPtrType();
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Ty, len));
|
return ReplaceCallWith(ci, ConstantInt::get(Ty, len));
|
||||||
|
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} StrLenOptimizer;
|
} StrLenOptimizer;
|
||||||
|
|
||||||
|
@ -949,9 +905,7 @@ struct VISIBILITY_HIDDEN memcmpOptimization : public LibCallOptimization {
|
||||||
// If the two operands are the same, return zero.
|
// If the two operands are the same, return zero.
|
||||||
if (LHS == RHS) {
|
if (LHS == RHS) {
|
||||||
// memcmp(s,s,x) -> 0
|
// memcmp(s,s,x) -> 0
|
||||||
CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
|
return ReplaceCallWith(CI, Constant::getNullValue(CI->getType()));
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we have a constant length.
|
// Make sure we have a constant length.
|
||||||
|
@ -963,9 +917,7 @@ struct VISIBILITY_HIDDEN memcmpOptimization : public LibCallOptimization {
|
||||||
switch (Len) {
|
switch (Len) {
|
||||||
case 0:
|
case 0:
|
||||||
// memcmp(s1,s2,0) -> 0
|
// memcmp(s1,s2,0) -> 0
|
||||||
CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
|
return ReplaceCallWith(CI, Constant::getNullValue(CI->getType()));
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
case 1: {
|
case 1: {
|
||||||
// memcmp(S1,S2,1) -> *(ubyte*)S1 - *(ubyte*)S2
|
// memcmp(S1,S2,1) -> *(ubyte*)S1 - *(ubyte*)S2
|
||||||
const Type *UCharPtr = PointerType::get(Type::Int8Ty);
|
const Type *UCharPtr = PointerType::get(Type::Int8Ty);
|
||||||
|
@ -979,9 +931,7 @@ struct VISIBILITY_HIDDEN memcmpOptimization : public LibCallOptimization {
|
||||||
if (RV->getType() != CI->getType())
|
if (RV->getType() != CI->getType())
|
||||||
RV = CastInst::createIntegerCast(RV, CI->getType(), false,
|
RV = CastInst::createIntegerCast(RV, CI->getType(), false,
|
||||||
RV->getName(), CI);
|
RV->getName(), CI);
|
||||||
CI->replaceAllUsesWith(RV);
|
return ReplaceCallWith(CI, RV);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
if (IsOnlyUsedInEqualsZeroComparison(CI)) {
|
if (IsOnlyUsedInEqualsZeroComparison(CI)) {
|
||||||
|
@ -1008,9 +958,7 @@ struct VISIBILITY_HIDDEN memcmpOptimization : public LibCallOptimization {
|
||||||
if (Or->getType() != CI->getType())
|
if (Or->getType() != CI->getType())
|
||||||
Or = CastInst::createIntegerCast(Or, CI->getType(), false /*ZExt*/,
|
Or = CastInst::createIntegerCast(Or, CI->getType(), false /*ZExt*/,
|
||||||
Or->getName(), CI);
|
Or->getName(), CI);
|
||||||
CI->replaceAllUsesWith(Or);
|
return ReplaceCallWith(CI, Or);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1064,12 +1012,10 @@ struct VISIBILITY_HIDDEN LLVMMemCpyMoveOptzn : public LibCallOptimization {
|
||||||
Value* dest = ci->getOperand(1);
|
Value* dest = ci->getOperand(1);
|
||||||
Value* src = ci->getOperand(2);
|
Value* src = ci->getOperand(2);
|
||||||
const Type* castType = 0;
|
const Type* castType = 0;
|
||||||
switch (len)
|
switch (len) {
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
// memcpy(d,s,0,a) -> noop
|
// memcpy(d,s,0,a) -> d
|
||||||
ci->eraseFromParent();
|
return ReplaceCallWith(ci, 0);
|
||||||
return true;
|
|
||||||
case 1: castType = Type::Int8Ty; break;
|
case 1: castType = Type::Int8Ty; break;
|
||||||
case 2: castType = Type::Int16Ty; break;
|
case 2: castType = Type::Int16Ty; break;
|
||||||
case 4: castType = Type::Int32Ty; break;
|
case 4: castType = Type::Int32Ty; break;
|
||||||
|
@ -1085,8 +1031,7 @@ struct VISIBILITY_HIDDEN LLVMMemCpyMoveOptzn : public LibCallOptimization {
|
||||||
dest, PointerType::get(castType),dest->getName()+".cast", ci);
|
dest, PointerType::get(castType),dest->getName()+".cast", ci);
|
||||||
LoadInst* LI = new LoadInst(SrcCast,SrcCast->getName()+".val",ci);
|
LoadInst* LI = new LoadInst(SrcCast,SrcCast->getName()+".val",ci);
|
||||||
new StoreInst(LI, DestCast, ci);
|
new StoreInst(LI, DestCast, ci);
|
||||||
ci->eraseFromParent();
|
return ReplaceCallWith(ci, 0);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1142,8 +1087,7 @@ struct VISIBILITY_HIDDEN LLVMMemSetOptimization : public LibCallOptimization {
|
||||||
// If the length is zero, this is a no-op
|
// If the length is zero, this is a no-op
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
// memset(d,c,0,a) -> noop
|
// memset(d,c,0,a) -> noop
|
||||||
ci->eraseFromParent();
|
return ReplaceCallWith(ci, 0);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the length is larger than the alignment, we can't optimize
|
// If the length is larger than the alignment, we can't optimize
|
||||||
|
@ -1194,8 +1138,7 @@ struct VISIBILITY_HIDDEN LLVMMemSetOptimization : public LibCallOptimization {
|
||||||
CastInst* DestCast = new BitCastInst(dest, PointerType::get(castType),
|
CastInst* DestCast = new BitCastInst(dest, PointerType::get(castType),
|
||||||
dest->getName()+".cast", ci);
|
dest->getName()+".cast", ci);
|
||||||
new StoreInst(ConstantInt::get(castType,fill_value),DestCast, ci);
|
new StoreInst(ConstantInt::get(castType,fill_value),DestCast, ci);
|
||||||
ci->eraseFromParent();
|
return ReplaceCallWith(ci, 0);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1226,38 +1169,27 @@ public:
|
||||||
Value* expn = ci->getOperand(2);
|
Value* expn = ci->getOperand(2);
|
||||||
if (ConstantFP *Op1 = dyn_cast<ConstantFP>(base)) {
|
if (ConstantFP *Op1 = dyn_cast<ConstantFP>(base)) {
|
||||||
double Op1V = Op1->getValue();
|
double Op1V = Op1->getValue();
|
||||||
if (Op1V == 1.0) {
|
if (Op1V == 1.0) // pow(1.0,x) -> 1.0
|
||||||
// pow(1.0,x) -> 1.0
|
return ReplaceCallWith(ci, ConstantFP::get(Ty, 1.0));
|
||||||
ci->replaceAllUsesWith(ConstantFP::get(Ty,1.0));
|
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (ConstantFP* Op2 = dyn_cast<ConstantFP>(expn)) {
|
} else if (ConstantFP* Op2 = dyn_cast<ConstantFP>(expn)) {
|
||||||
double Op2V = Op2->getValue();
|
double Op2V = Op2->getValue();
|
||||||
if (Op2V == 0.0) {
|
if (Op2V == 0.0) {
|
||||||
// pow(x,0.0) -> 1.0
|
// pow(x,0.0) -> 1.0
|
||||||
ci->replaceAllUsesWith(ConstantFP::get(Ty,1.0));
|
return ReplaceCallWith(ci, ConstantFP::get(Ty,1.0));
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
} else if (Op2V == 0.5) {
|
} else if (Op2V == 0.5) {
|
||||||
// pow(x,0.5) -> sqrt(x)
|
// pow(x,0.5) -> sqrt(x)
|
||||||
CallInst* sqrt_inst = new CallInst(SLC.get_sqrt(), base,
|
CallInst* sqrt_inst = new CallInst(SLC.get_sqrt(), base,
|
||||||
ci->getName()+".pow",ci);
|
ci->getName()+".pow",ci);
|
||||||
ci->replaceAllUsesWith(sqrt_inst);
|
return ReplaceCallWith(ci, sqrt_inst);
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
} else if (Op2V == 1.0) {
|
} else if (Op2V == 1.0) {
|
||||||
// pow(x,1.0) -> x
|
// pow(x,1.0) -> x
|
||||||
ci->replaceAllUsesWith(base);
|
return ReplaceCallWith(ci, base);
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
} else if (Op2V == -1.0) {
|
} else if (Op2V == -1.0) {
|
||||||
// pow(x,-1.0) -> 1.0/x
|
// pow(x,-1.0) -> 1.0/x
|
||||||
BinaryOperator* div_inst= BinaryOperator::createFDiv(
|
Value *div_inst =
|
||||||
ConstantFP::get(Ty,1.0), base, ci->getName()+".pow", ci);
|
BinaryOperator::createFDiv(ConstantFP::get(Ty, 1.0), base,
|
||||||
ci->replaceAllUsesWith(div_inst);
|
ci->getName()+".pow", ci);
|
||||||
ci->eraseFromParent();
|
return ReplaceCallWith(ci, div_inst);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false; // opt failed
|
return false; // opt failed
|
||||||
|
@ -1319,8 +1251,7 @@ public:
|
||||||
std::vector<Value*> args;
|
std::vector<Value*> args;
|
||||||
new CallInst(SLC.get_puts(), CastToCStr(ci->getOperand(2), *ci),
|
new CallInst(SLC.get_puts(), CastToCStr(ci->getOperand(2), *ci),
|
||||||
ci->getName(), ci);
|
ci->getName(), ci);
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty, len));
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty, len));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 'c':
|
case 'c':
|
||||||
{
|
{
|
||||||
|
@ -1331,14 +1262,12 @@ public:
|
||||||
CastInst *Char = CastInst::createSExtOrBitCast(
|
CastInst *Char = CastInst::createSExtOrBitCast(
|
||||||
ci->getOperand(2), Type::Int32Ty, CI->getName()+".int", ci);
|
ci->getOperand(2), Type::Int32Ty, CI->getName()+".int", ci);
|
||||||
new CallInst(SLC.get_putchar(), Char, "", ci);
|
new CallInst(SLC.get_putchar(), Char, "", ci);
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty, 1));
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty, 1));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ci->eraseFromParent();
|
return false;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} PrintfOptimizer;
|
} PrintfOptimizer;
|
||||||
|
|
||||||
|
@ -1403,9 +1332,7 @@ public:
|
||||||
ci->getOperand(1)
|
ci->getOperand(1)
|
||||||
};
|
};
|
||||||
new CallInst(SLC.get_fwrite(FILEptr_type), args, 4, ci->getName(), ci);
|
new CallInst(SLC.get_fwrite(FILEptr_type), args, 4, ci->getName(), ci);
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,len));
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty,len));
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The remaining optimizations require the format string to be length 2
|
// The remaining optimizations require the format string to be length 2
|
||||||
|
@ -1421,8 +1348,7 @@ public:
|
||||||
// Get the second character and switch on its value
|
// Get the second character and switch on its value
|
||||||
ConstantInt* CI = dyn_cast<ConstantInt>(CA->getOperand(1));
|
ConstantInt* CI = dyn_cast<ConstantInt>(CA->getOperand(1));
|
||||||
switch (CI->getZExtValue()) {
|
switch (CI->getZExtValue()) {
|
||||||
case 's':
|
case 's': {
|
||||||
{
|
|
||||||
uint64_t len, StartIdx;
|
uint64_t len, StartIdx;
|
||||||
ConstantArray* CA = 0;
|
ConstantArray* CA = 0;
|
||||||
if (GetConstantStringInfo(ci->getOperand(3), CA, len, StartIdx)) {
|
if (GetConstantStringInfo(ci->getOperand(3), CA, len, StartIdx)) {
|
||||||
|
@ -1435,32 +1361,26 @@ public:
|
||||||
ci->getOperand(1)
|
ci->getOperand(1)
|
||||||
};
|
};
|
||||||
new CallInst(SLC.get_fwrite(FILEptr_type), args, 4,ci->getName(), ci);
|
new CallInst(SLC.get_fwrite(FILEptr_type), args, 4,ci->getName(), ci);
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty, len));
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty, len));
|
||||||
} else {
|
|
||||||
// fprintf(file,"%s",str) -> fputs(str,file)
|
|
||||||
const Type* FILEptr_type = ci->getOperand(1)->getType();
|
|
||||||
new CallInst(SLC.get_fputs(FILEptr_type),
|
|
||||||
CastToCStr(ci->getOperand(3), *ci),
|
|
||||||
ci->getOperand(1), ci->getName(),ci);
|
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,len));
|
|
||||||
}
|
}
|
||||||
break;
|
// fprintf(file,"%s",str) -> fputs(str,file)
|
||||||
|
const Type* FILEptr_type = ci->getOperand(1)->getType();
|
||||||
|
new CallInst(SLC.get_fputs(FILEptr_type),
|
||||||
|
CastToCStr(ci->getOperand(3), *ci),
|
||||||
|
ci->getOperand(1), ci->getName(),ci);
|
||||||
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty,len));
|
||||||
}
|
}
|
||||||
case 'c':
|
case 'c': {
|
||||||
{
|
|
||||||
// fprintf(file,"%c",c) -> fputc(c,file)
|
// fprintf(file,"%c",c) -> fputc(c,file)
|
||||||
const Type* FILEptr_type = ci->getOperand(1)->getType();
|
const Type* FILEptr_type = ci->getOperand(1)->getType();
|
||||||
CastInst* cast = CastInst::createSExtOrBitCast(
|
CastInst* cast = CastInst::createSExtOrBitCast(
|
||||||
ci->getOperand(3), Type::Int32Ty, CI->getName()+".int", ci);
|
ci->getOperand(3), Type::Int32Ty, CI->getName()+".int", ci);
|
||||||
new CallInst(SLC.get_fputc(FILEptr_type), cast,ci->getOperand(1),"",ci);
|
new CallInst(SLC.get_fputc(FILEptr_type), cast,ci->getOperand(1),"",ci);
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,1));
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty,1));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} FPrintFOptimizer;
|
} FPrintFOptimizer;
|
||||||
|
|
||||||
|
@ -1497,9 +1417,7 @@ public:
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
// If the length is 0, we just need to store a null byte
|
// If the length is 0, we just need to store a null byte
|
||||||
new StoreInst(ConstantInt::get(Type::Int8Ty,0),ci->getOperand(1),ci);
|
new StoreInst(ConstantInt::get(Type::Int8Ty,0),ci->getOperand(1),ci);
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,0));
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty,0));
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure there's no % in the constant array
|
// Make sure there's no % in the constant array
|
||||||
|
@ -1524,9 +1442,7 @@ public:
|
||||||
ConstantInt::get(Type::Int32Ty, 1)
|
ConstantInt::get(Type::Int32Ty, 1)
|
||||||
};
|
};
|
||||||
new CallInst(SLC.get_memcpy(), args, 4, "", ci);
|
new CallInst(SLC.get_memcpy(), args, 4, "", ci);
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,len));
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty,len));
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The remaining optimizations require the format string to be length 2
|
// The remaining optimizations require the format string to be length 2
|
||||||
|
@ -1568,8 +1484,7 @@ public:
|
||||||
Len->getName(), ci);
|
Len->getName(), ci);
|
||||||
ci->replaceAllUsesWith(Len);
|
ci->replaceAllUsesWith(Len);
|
||||||
}
|
}
|
||||||
ci->eraseFromParent();
|
return ReplaceCallWith(ci, 0);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case 'c': {
|
case 'c': {
|
||||||
// sprintf(dest,"%c",chr) -> store chr, dest
|
// sprintf(dest,"%c",chr) -> store chr, dest
|
||||||
|
@ -1580,9 +1495,7 @@ public:
|
||||||
ConstantInt::get(Type::Int32Ty,1),ci->getOperand(1)->getName()+".end",
|
ConstantInt::get(Type::Int32Ty,1),ci->getOperand(1)->getName()+".end",
|
||||||
ci);
|
ci);
|
||||||
new StoreInst(ConstantInt::get(Type::Int8Ty,0),gep,ci);
|
new StoreInst(ConstantInt::get(Type::Int8Ty,0),gep,ci);
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,1));
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty, 1));
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1648,8 +1561,7 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ci->eraseFromParent();
|
return ReplaceCallWith(ci, 0); // Known to have no uses (see above).
|
||||||
return true; // success
|
|
||||||
}
|
}
|
||||||
} PutsOptimizer;
|
} PutsOptimizer;
|
||||||
|
|
||||||
|
@ -1672,12 +1584,10 @@ public:
|
||||||
if (ConstantInt* CI = dyn_cast<ConstantInt>(ci->getOperand(1))) {
|
if (ConstantInt* CI = dyn_cast<ConstantInt>(ci->getOperand(1))) {
|
||||||
// isdigit(c) -> 0 or 1, if 'c' is constant
|
// isdigit(c) -> 0 or 1, if 'c' is constant
|
||||||
uint64_t val = CI->getZExtValue();
|
uint64_t val = CI->getZExtValue();
|
||||||
if (val >= '0' && val <='9')
|
if (val >= '0' && val <= '9')
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,1));
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty, 1));
|
||||||
else
|
else
|
||||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,0));
|
return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty, 0));
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isdigit(c) -> (unsigned)c - '0' <= 9
|
// isdigit(c) -> (unsigned)c - '0' <= 9
|
||||||
|
@ -1691,9 +1601,7 @@ public:
|
||||||
ci->getOperand(1)->getName()+".cmp",ci);
|
ci->getOperand(1)->getName()+".cmp",ci);
|
||||||
CastInst* c2 = new ZExtInst(setcond_inst, Type::Int32Ty,
|
CastInst* c2 = new ZExtInst(setcond_inst, Type::Int32Ty,
|
||||||
ci->getOperand(1)->getName()+".isdigit", ci);
|
ci->getOperand(1)->getName()+".isdigit", ci);
|
||||||
ci->replaceAllUsesWith(c2);
|
return ReplaceCallWith(ci, c2);
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} isdigitOptimizer;
|
} isdigitOptimizer;
|
||||||
|
|
||||||
|
@ -1716,9 +1624,7 @@ public:
|
||||||
V->getName()+".isascii", CI);
|
V->getName()+".isascii", CI);
|
||||||
if (Cmp->getType() != CI->getType())
|
if (Cmp->getType() != CI->getType())
|
||||||
Cmp = new BitCastInst(Cmp, CI->getType(), Cmp->getName(), CI);
|
Cmp = new BitCastInst(Cmp, CI->getType(), Cmp->getName(), CI);
|
||||||
CI->replaceAllUsesWith(Cmp);
|
return ReplaceCallWith(CI, Cmp);
|
||||||
CI->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} isasciiOptimizer;
|
} isasciiOptimizer;
|
||||||
|
|
||||||
|
@ -1742,12 +1648,10 @@ public:
|
||||||
/// @brief Perform the toascii optimization.
|
/// @brief Perform the toascii optimization.
|
||||||
virtual bool OptimizeCall(CallInst *ci, SimplifyLibCalls &SLC) {
|
virtual bool OptimizeCall(CallInst *ci, SimplifyLibCalls &SLC) {
|
||||||
// toascii(c) -> (c & 0x7f)
|
// toascii(c) -> (c & 0x7f)
|
||||||
Value* chr = ci->getOperand(1);
|
Value *chr = ci->getOperand(1);
|
||||||
BinaryOperator* and_inst = BinaryOperator::createAnd(chr,
|
Value *and_inst = BinaryOperator::createAnd(chr,
|
||||||
ConstantInt::get(chr->getType(),0x7F),ci->getName()+".toascii",ci);
|
ConstantInt::get(chr->getType(),0x7F),ci->getName()+".toascii",ci);
|
||||||
ci->replaceAllUsesWith(and_inst);
|
return ReplaceCallWith(ci, and_inst);
|
||||||
ci->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} ToAsciiOptimizer;
|
} ToAsciiOptimizer;
|
||||||
|
|
||||||
|
@ -1788,9 +1692,7 @@ public:
|
||||||
val >>= 1;
|
val >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TheCall->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty, result));
|
return ReplaceCallWith(TheCall, ConstantInt::get(Type::Int32Ty, result));
|
||||||
TheCall->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ffs(x) -> x == 0 ? 0 : llvm.cttz(x)+1
|
// ffs(x) -> x == 0 ? 0 : llvm.cttz(x)+1
|
||||||
|
@ -1826,9 +1728,7 @@ public:
|
||||||
TheCall);
|
TheCall);
|
||||||
V2 = new SelectInst(Cond, ConstantInt::get(Type::Int32Ty, 0), V2,
|
V2 = new SelectInst(Cond, ConstantInt::get(Type::Int32Ty, 0), V2,
|
||||||
TheCall->getName(), TheCall);
|
TheCall->getName(), TheCall);
|
||||||
TheCall->replaceAllUsesWith(V2);
|
return ReplaceCallWith(TheCall, V2);
|
||||||
TheCall->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} FFSOptimizer;
|
} FFSOptimizer;
|
||||||
|
|
||||||
|
@ -1874,7 +1774,7 @@ struct UnaryDoubleFPOptimizer : public LibCallOptimization {
|
||||||
/// no precision loss.
|
/// no precision loss.
|
||||||
static bool ShrinkFunctionToFloatVersion(CallInst *CI, SimplifyLibCalls &SLC,
|
static bool ShrinkFunctionToFloatVersion(CallInst *CI, SimplifyLibCalls &SLC,
|
||||||
Constant *(SimplifyLibCalls::*FP)()){
|
Constant *(SimplifyLibCalls::*FP)()){
|
||||||
if (CastInst *Cast = dyn_cast<CastInst>(CI->getOperand(1)))
|
if (FPExtInst *Cast = dyn_cast<FPExtInst>(CI->getOperand(1)))
|
||||||
if (Cast->getOperand(0)->getType() == Type::FloatTy) {
|
if (Cast->getOperand(0)->getType() == Type::FloatTy) {
|
||||||
Value *New = new CallInst((SLC.*FP)(), Cast->getOperand(0),
|
Value *New = new CallInst((SLC.*FP)(), Cast->getOperand(0),
|
||||||
CI->getName(), CI);
|
CI->getName(), CI);
|
||||||
|
|
Loading…
Reference in New Issue