mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
* Add two strlen optimizations:
strlen(x) != 0 -> *x != 0 strlen(x) == 0 -> *x == 0 * Change nested statistics to use style of other LLVM statistics so that only the name of the optimization (simplify-libcalls) is used as the statistic name, and the description indicates which specific all is optimized. Cuts down on some redundancy and saves a few bytes of space. * Make note of stpcpy optimization that could be done. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21766 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
673c1a9170
commit
789082af03
@ -35,7 +35,7 @@ namespace {
|
||||
/// This statistic keeps track of the total number of library calls that have
|
||||
/// been simplified regardless of which call it is.
|
||||
Statistic<> SimplifiedLibCalls("simplify-libcalls",
|
||||
"Number of well-known library calls simplified");
|
||||
"Total number of library calls simplified");
|
||||
|
||||
// Forward declarations
|
||||
class LibCallOptimization;
|
||||
@ -65,11 +65,10 @@ public:
|
||||
/// The \p fname argument must be the name of the library function being
|
||||
/// optimized by the subclass.
|
||||
/// @brief Constructor that registers the optimization.
|
||||
LibCallOptimization(const char* fname,
|
||||
const char* stat_name, const char* description )
|
||||
LibCallOptimization(const char* fname, const char* description )
|
||||
: func_name(fname)
|
||||
#ifndef NDEBUG
|
||||
, occurrences(stat_name,description)
|
||||
, occurrences("simplify-libcalls",description)
|
||||
#endif
|
||||
{
|
||||
// Register this call optimizer in the optlist (a hash_map)
|
||||
@ -374,7 +373,7 @@ bool getConstantStringLength(Value* V, uint64_t& len, ConstantArray** A = 0 );
|
||||
struct ExitInMainOptimization : public LibCallOptimization
|
||||
{
|
||||
ExitInMainOptimization() : LibCallOptimization("exit",
|
||||
"simplify-libcalls:exit","Number of 'exit' calls simplified") {}
|
||||
"Number of 'exit' calls simplified") {}
|
||||
virtual ~ExitInMainOptimization() {}
|
||||
|
||||
// Make sure the called function looks like exit (int argument, int return
|
||||
@ -440,7 +439,7 @@ struct StrCatOptimization : public LibCallOptimization
|
||||
public:
|
||||
/// @brief Default constructor
|
||||
StrCatOptimization() : LibCallOptimization("strcat",
|
||||
"simplify-libcalls:strcat","Number of 'strcat' calls simplified") {}
|
||||
"Number of 'strcat' calls simplified") {}
|
||||
|
||||
public:
|
||||
/// @breif Destructor
|
||||
@ -531,7 +530,7 @@ struct StrChrOptimization : public LibCallOptimization
|
||||
{
|
||||
public:
|
||||
StrChrOptimization() : LibCallOptimization("strchr",
|
||||
"simplify-libcalls:strchr","Number of 'strchr' calls simplified") {}
|
||||
"Number of 'strchr' calls simplified") {}
|
||||
virtual ~StrChrOptimization() {}
|
||||
|
||||
/// @brief Make sure that the "strchr" function has the right prototype
|
||||
@ -623,7 +622,7 @@ struct StrCmpOptimization : public LibCallOptimization
|
||||
{
|
||||
public:
|
||||
StrCmpOptimization() : LibCallOptimization("strcmp",
|
||||
"simplify-libcalls:strcmp","Number of 'strcmp' calls simplified") {}
|
||||
"Number of 'strcmp' calls simplified") {}
|
||||
virtual ~StrCmpOptimization() {}
|
||||
|
||||
/// @brief Make sure that the "strcpy" function has the right prototype
|
||||
@ -708,7 +707,7 @@ struct StrNCmpOptimization : public LibCallOptimization
|
||||
{
|
||||
public:
|
||||
StrNCmpOptimization() : LibCallOptimization("strncmp",
|
||||
"simplify-libcalls:strncmp","Number of 'strncmp' calls simplified") {}
|
||||
"Number of 'strncmp' calls simplified") {}
|
||||
virtual ~StrNCmpOptimization() {}
|
||||
|
||||
/// @brief Make sure that the "strcpy" function has the right prototype
|
||||
@ -811,7 +810,7 @@ struct StrCpyOptimization : public LibCallOptimization
|
||||
{
|
||||
public:
|
||||
StrCpyOptimization() : LibCallOptimization("strcpy",
|
||||
"simplify-libcalls:strcpy","Number of 'strcpy' calls simplified") {}
|
||||
"Number of 'strcpy' calls simplified") {}
|
||||
virtual ~StrCpyOptimization() {}
|
||||
|
||||
/// @brief Make sure that the "strcpy" function has the right prototype
|
||||
@ -899,7 +898,7 @@ public:
|
||||
struct StrLenOptimization : public LibCallOptimization
|
||||
{
|
||||
StrLenOptimization() : LibCallOptimization("strlen",
|
||||
"simplify-libcalls:strlen","Number of 'strlen' calls simplified") {}
|
||||
"Number of 'strlen' calls simplified") {}
|
||||
virtual ~StrLenOptimization() {}
|
||||
|
||||
/// @brief Make sure that the "strlen" function has the right prototype
|
||||
@ -916,11 +915,45 @@ struct StrLenOptimization : public LibCallOptimization
|
||||
/// @brief Perform the strlen optimization
|
||||
virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC)
|
||||
{
|
||||
// Get the length of the string
|
||||
// Make sure we're dealing with an sbyte* here.
|
||||
Value* str = ci->getOperand(1);
|
||||
if (str->getType() != PointerType::get(Type::SByteTy))
|
||||
return false;
|
||||
|
||||
// Does the call to strlen have exactly one use?
|
||||
if (ci->hasOneUse())
|
||||
// Is that single use a binary operator?
|
||||
if (BinaryOperator* bop = dyn_cast<BinaryOperator>(ci->use_back()))
|
||||
// Is it compared against a constant integer?
|
||||
if (ConstantInt* CI = dyn_cast<ConstantInt>(bop->getOperand(1)))
|
||||
{
|
||||
// Get the value the strlen result is compared to
|
||||
uint64_t val = CI->getRawValue();
|
||||
|
||||
// If its compared against length 0 with == or !=
|
||||
if (val == 0 &&
|
||||
(bop->getOpcode() == Instruction::SetEQ ||
|
||||
bop->getOpcode() == Instruction::SetNE))
|
||||
{
|
||||
// strlen(x) != 0 -> *x != 0
|
||||
// strlen(x) == 0 -> *x == 0
|
||||
LoadInst* load = new LoadInst(str,str->getName()+".first",ci);
|
||||
BinaryOperator* rbop = BinaryOperator::create(bop->getOpcode(),
|
||||
load, ConstantSInt::get(Type::SByteTy,0),
|
||||
bop->getName()+".strlen", ci);
|
||||
bop->replaceAllUsesWith(rbop);
|
||||
bop->eraseFromParent();
|
||||
ci->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the length of the constant string operand
|
||||
uint64_t len = 0;
|
||||
if (!getConstantStringLength(ci->getOperand(1),len))
|
||||
return false;
|
||||
|
||||
// strlen("xyz") -> 3 (for example)
|
||||
ci->replaceAllUsesWith(
|
||||
ConstantInt::get(SLC.getTargetData()->getIntPtrType(),len));
|
||||
ci->eraseFromParent();
|
||||
@ -937,13 +970,12 @@ struct LLVMMemCpyOptimization : public LibCallOptimization
|
||||
{
|
||||
/// @brief Default Constructor
|
||||
LLVMMemCpyOptimization() : LibCallOptimization("llvm.memcpy",
|
||||
"simplify-libcalls:llvm.memcpy",
|
||||
"Number of 'llvm.memcpy' calls simplified") {}
|
||||
|
||||
protected:
|
||||
/// @brief Subclass Constructor
|
||||
LLVMMemCpyOptimization(const char* fname, const char* sname, const char* desc)
|
||||
: LibCallOptimization(fname, sname, desc) {}
|
||||
LLVMMemCpyOptimization(const char* fname, const char* desc)
|
||||
: LibCallOptimization(fname, desc) {}
|
||||
public:
|
||||
/// @brief Destructor
|
||||
virtual ~LLVMMemCpyOptimization() {}
|
||||
@ -1017,7 +1049,6 @@ struct LLVMMemMoveOptimization : public LLVMMemCpyOptimization
|
||||
{
|
||||
/// @brief Default Constructor
|
||||
LLVMMemMoveOptimization() : LLVMMemCpyOptimization("llvm.memmove",
|
||||
"simplify-libcalls:llvm.memmove",
|
||||
"Number of 'llvm.memmove' calls simplified") {}
|
||||
|
||||
} LLVMMemMoveOptimizer;
|
||||
@ -1029,7 +1060,6 @@ struct LLVMMemSetOptimization : public LibCallOptimization
|
||||
{
|
||||
/// @brief Default Constructor
|
||||
LLVMMemSetOptimization() : LibCallOptimization("llvm.memset",
|
||||
"simplify-libcalls:llvm.memset",
|
||||
"Number of 'llvm.memset' calls simplified") {}
|
||||
|
||||
public:
|
||||
@ -1139,7 +1169,7 @@ struct PowOptimization : public LibCallOptimization
|
||||
public:
|
||||
/// @brief Default Constructor
|
||||
PowOptimization() : LibCallOptimization("pow",
|
||||
"simplify-libcalls:pow", "Number of 'pow' calls simplified") {}
|
||||
"Number of 'pow' calls simplified") {}
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~PowOptimization() {}
|
||||
@ -1216,7 +1246,7 @@ struct FPrintFOptimization : public LibCallOptimization
|
||||
public:
|
||||
/// @brief Default Constructor
|
||||
FPrintFOptimization() : LibCallOptimization("fprintf",
|
||||
"simplify-libcalls:fprintf", "Number of 'fprintf' calls simplified") {}
|
||||
"Number of 'fprintf' calls simplified") {}
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~FPrintFOptimization() {}
|
||||
@ -1346,7 +1376,7 @@ struct SPrintFOptimization : public LibCallOptimization
|
||||
public:
|
||||
/// @brief Default Constructor
|
||||
SPrintFOptimization() : LibCallOptimization("sprintf",
|
||||
"simplify-libcalls:sprintf", "Number of 'sprintf' calls simplified") {}
|
||||
"Number of 'sprintf' calls simplified") {}
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~SPrintFOptimization() {}
|
||||
@ -1489,7 +1519,7 @@ struct PutsOptimization : public LibCallOptimization
|
||||
public:
|
||||
/// @brief Default Constructor
|
||||
PutsOptimization() : LibCallOptimization("fputs",
|
||||
"simplify-libcalls:fputs", "Number of 'fputs' calls simplified") {}
|
||||
"Number of 'fputs' calls simplified") {}
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~PutsOptimization() {}
|
||||
@ -1562,7 +1592,7 @@ struct IsDigitOptimization : public LibCallOptimization
|
||||
public:
|
||||
/// @brief Default Constructor
|
||||
IsDigitOptimization() : LibCallOptimization("isdigit",
|
||||
"simplify-libcalls:isdigit", "Number of 'isdigit' calls simplified") {}
|
||||
"Number of 'isdigit' calls simplified") {}
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~IsDigitOptimization() {}
|
||||
@ -1617,7 +1647,7 @@ struct ToAsciiOptimization : public LibCallOptimization
|
||||
public:
|
||||
/// @brief Default Constructor
|
||||
ToAsciiOptimization() : LibCallOptimization("toascii",
|
||||
"simplify-libcalls:toascii", "Number of 'toascii' calls simplified") {}
|
||||
"Number of 'toascii' calls simplified") {}
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~ToAsciiOptimization() {}
|
||||
@ -1810,6 +1840,9 @@ bool getConstantStringLength(Value* V, uint64_t& len, ConstantArray** CA )
|
||||
// * sqrt(Nroot(x)) -> pow(x,1/(2*N))
|
||||
// * sqrt(pow(x,y)) -> pow(|x|,y*0.5)
|
||||
//
|
||||
// stpcpy:
|
||||
// * stpcpy(str, "literal") ->
|
||||
// llvm.memcpy(str,"literal",strlen("literal")+1,1)
|
||||
// strrchr:
|
||||
// * strrchr(s,c) -> reverse_offset_of_in(c,s)
|
||||
// (if c is a constant integer and s is a constant string)
|
||||
|
Loading…
Reference in New Issue
Block a user