[llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp
Reid Spencer
reid at x10sys.com
Wed Apr 27 14:29:32 PDT 2005
Changes in directory llvm/lib/Transforms/IPO:
SimplifyLibCalls.cpp updated: 1.18 -> 1.19
---
Log message:
Doxygenate.
---
Diffs of the changes: (+71 -54)
SimplifyLibCalls.cpp | 125 ++++++++++++++++++++++++++++-----------------------
1 files changed, 71 insertions(+), 54 deletions(-)
Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp
diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.18 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.19
--- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.18 Wed Apr 27 12:46:54 2005
+++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Wed Apr 27 16:29:20 2005
@@ -37,23 +37,33 @@
Statistic<> SimplifiedLibCalls("simplify-libcalls",
"Number of well-known library calls simplified");
-/// @brief The list of optimizations deriving from LibCallOptimization
+// Forward declarations
class LibCallOptimization;
class SimplifyLibCalls;
+
+/// @brief The list of optimizations deriving from LibCallOptimization
hash_map<std::string,LibCallOptimization*> optlist;
/// This class is the abstract base class for the set of optimizations that
-/// corresponds to one library call. The SimplifyLibCall pass will call the
+/// corresponds to one library call. The SimplifyLibCalls pass will call the
/// ValidateCalledFunction method to ask the optimization if a given Function
-/// is the kind that the optimization can handle. It will also call the
-/// OptimizeCall method to perform, or attempt to perform, the optimization(s)
-/// for the library call. Subclasses of this class are located toward the
-/// end of this file.
+/// is the kind that the optimization can handle. If the subclass returns true,
+/// then SImplifyLibCalls will also call the OptimizeCall method to perform,
+/// or attempt to perform, the optimization(s) for the library call. Otherwise,
+/// OptimizeCall won't be called. Subclasses are responsible for providing the
+/// name of the library call (strlen, strcpy, etc.) to the LibCallOptimization
+/// constructor. This is used to efficiently select which call instructions to
+/// optimize. The criteria for a "lib call" is "anything with well known
+/// semantics", typically a library function that is defined by an international
+/// standard. Because the semantics are well known, the optimizations can
+/// generally short-circuit actually calling the function if there's a simpler
+/// way (e.g. strlen(X) can be reduced to a constant if X is a constant global).
/// @brief Base class for library call optimizations
struct LibCallOptimization
{
- /// @brief Constructor that registers the optimization. The \p fname argument
- /// must be the name of the library function being optimized by the subclass.
+ /// 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 )
: func_name(fname)
#ifndef NDEBUG
@@ -61,22 +71,23 @@
, occurrences(stat_name.c_str(),"Number of calls simplified")
#endif
{
- // Register this call optimizer
+ // Register this call optimizer in the optlist (a hash_map)
optlist[func_name] = this;
}
- /// @brief Destructor
- virtual ~LibCallOptimization() {}
+ /// @brief Deregister from the optlist
+ virtual ~LibCallOptimization() { optlist.erase(func_name); }
/// The implementation of this function in subclasses should determine if
/// \p F is suitable for the optimization. This method is called by
- /// runOnModule to short circuit visiting all the call sites of such a
- /// function if that function is not suitable in the first place.
- /// If the called function is suitabe, this method should return true;
+ /// SimplifyLibCalls::runOnModule to short circuit visiting all the call
+ /// sites of such a function if that function is not suitable in the first
+ /// place. If the called function is suitabe, this method should return true;
/// false, otherwise. This function should also perform any lazy
/// initialization that the LibCallOptimization needs to do, if its to return
/// true. This avoids doing initialization until the optimizer is actually
/// going to be called upon to do some optimization.
+ /// @brief Determine if the function is suitable for optimization
virtual bool ValidateCalledFunction(
const Function* F, ///< The function that is the target of call sites
SimplifyLibCalls& SLC ///< The pass object invoking us
@@ -88,8 +99,6 @@
/// the call and (b) to perform the optimization. If an action is taken
/// against ci, the subclass is responsible for returning true and ensuring
/// that ci is erased from its parent.
- /// @param ci the call instruction under consideration
- /// @param f the function that ci calls.
/// @brief Optimize a call, if possible.
virtual bool OptimizeCall(
CallInst* ci, ///< The call instruction that should be optimized.
@@ -100,7 +109,8 @@
const char * getFunctionName() const { return func_name; }
#ifndef NDEBUG
- void occurred() { ++occurrences; }
+ /// @brief Called by SimplifyLibCalls to update the occurrences statistic.
+ void succeeded() { ++occurrences; }
#endif
private:
@@ -111,23 +121,19 @@
#endif
};
-/// This class is the base class for a set of small but important
-/// optimizations of calls to well-known functions, such as those in the c
-/// library.
-
/// This class is an LLVM Pass that applies each of the LibCallOptimization
/// instances to all the call sites in a module, relatively efficiently. The
/// purpose of this pass is to provide optimizations for calls to well-known
/// functions with well-known semantics, such as those in the c library. The
-/// class provides the basic infrastructure for handling runOnModule.
-/// Whenever this pass finds a function call, it asks the subclasses to
-/// validate the call by calling ValidateLibraryCall. If it is validated, then
-/// the OptimizeCall method is called.
+/// class provides the basic infrastructure for handling runOnModule. Whenever /// this pass finds a function call, it asks the appropriate optimizer to
+/// validate the call (ValidateLibraryCall). If it is validated, then
+/// the OptimizeCall method is also called.
/// @brief A ModulePass for optimizing well-known function calls.
struct SimplifyLibCalls : public ModulePass
{
/// We need some target data for accurate signature details that are
/// target dependent. So we require target data in our AnalysisUsage.
+ /// @brief Require TargetData from AnalysisUsage.
virtual void getAnalysisUsage(AnalysisUsage& Info) const
{
// Ask that the TargetData analysis be performed before us so we can use
@@ -137,6 +143,7 @@
/// For this pass, process all of the function calls in the module, calling
/// ValidateLibraryCall and OptimizeCall as appropriate.
+ /// @brief Run all the lib call optimizations on a Module.
virtual bool runOnModule(Module &M)
{
reset(M);
@@ -183,7 +190,7 @@
++SimplifiedLibCalls;
found_optimization = result = true;
#ifndef NDEBUG
- CO->occurred();
+ CO->succeeded();
#endif
}
}
@@ -230,10 +237,8 @@
return memcpy_func;
}
- /// @brief Compute length of constant string
- bool getConstantStringLength(Value* V, uint64_t& len );
-
private:
+ /// @brief Reset our cached data for a new Module
void reset(Module& mod)
{
M = &mod;
@@ -243,10 +248,10 @@
}
private:
- Function* memcpy_func;
- Function* strlen_func;
- Module* M;
- TargetData* TD;
+ Function* memcpy_func; ///< Cached llvm.memcpy function
+ Function* strlen_func; ///< Cached strlen function
+ Module* M; ///< Cached Module
+ TargetData* TD; ///< Cached TargetData
};
// Register the pass
@@ -272,9 +277,8 @@
/// This LibCallOptimization will find instances of a call to "exit" that occurs
/// within the "main" function and change it to a simple "ret" instruction with
-/// the same value as passed to the exit function. It assumes that the
-/// instructions after the call to exit(3) can be deleted since they are
-/// unreachable anyway.
+/// the same value passed to the exit function. When this is done, it splits the
+/// basic block at the exit(3) call and deletes the call instruction.
/// @brief Replace calls to exit in main with a simple return
struct ExitInMainOptimization : public LibCallOptimization
{
@@ -335,16 +339,18 @@
/// This LibCallOptimization will simplify a call to the strcat library
/// function. The simplification is possible only if the string being
/// concatenated is a constant array or a constant expression that results in
-/// a constant array. In this case, if the array is small, we can generate a
-/// series of inline store instructions to effect the concatenation without
-/// calling strcat.
+/// a constant string. In this case we can replace it with strlen + llvm.memcpy
+/// of the constant string. Both of these calls are further reduced, if possible
+/// on subsequent passes.
/// @brief Simplify the strcat library function.
struct StrCatOptimization : public LibCallOptimization
{
public:
+ /// @brief Default constructor
StrCatOptimization() : LibCallOptimization("strcat") {}
public:
+ /// @breif Destructor
virtual ~StrCatOptimization() {}
/// @brief Make sure that the "strcat" function has the right prototype
@@ -425,8 +431,8 @@
}
} StrCatOptimizer;
-/// This LibCallOptimization will simplify a call to the strcpy library function.
-/// Several optimizations are possible:
+/// This LibCallOptimization will simplify a call to the strcpy library
+/// function. Two optimizations are possible:
/// (1) If src and dest are the same and not volatile, just return dest
/// (2) If the src is a constant then we can convert to llvm.memmove
/// @brief Simplify the strcpy library function.
@@ -514,9 +520,9 @@
}
} StrCpyOptimizer;
-/// This LibCallOptimization will simplify a call to the strlen library function by
-/// replacing it with a constant value if the string provided to it is a
-/// constant array.
+/// This LibCallOptimization will simplify a call to the strlen library
+/// function by replacing it with a constant value if the string provided to
+/// it is a constant array.
/// @brief Simplify the strlen library function.
struct StrLenOptimization : public LibCallOptimization
{
@@ -549,16 +555,20 @@
}
} StrLenOptimizer;
-/// This LibCallOptimization will simplify a call to the memcpy library function by
-/// expanding it out to a single store of size 0, 1, 2, 4, or 8 bytes depending
-/// on the length of the string and the alignment.
+/// This LibCallOptimization will simplify a call to the memcpy library
+/// function by expanding it out to a single store of size 0, 1, 2, 4, or 8
+/// bytes depending on the length of the string and the alignment. Additional
+/// optimizations are possible in code generation (sequence of immediate store)
/// @brief Simplify the memcpy library function.
struct MemCpyOptimization : public LibCallOptimization
{
+ /// @brief Default Constructor
MemCpyOptimization() : LibCallOptimization("llvm.memcpy") {}
protected:
+ /// @brief Subclass Constructor
MemCpyOptimization(const char* fname) : LibCallOptimization(fname) {}
public:
+ /// @brief Destructor
virtual ~MemCpyOptimization() {}
/// @brief Make sure that the "memcpy" function has the right prototype
@@ -620,19 +630,27 @@
}
} MemCpyOptimizer;
-/// This LibCallOptimization will simplify a call to the memmove library function. /// It is identical to MemCopyOptimization except for the name of the intrinsic.
+/// This LibCallOptimization will simplify a call to the memmove library
+/// function. It is identical to MemCopyOptimization except for the name of
+/// the intrinsic.
/// @brief Simplify the memmove library function.
struct MemMoveOptimization : public MemCpyOptimization
{
+ /// @brief Default Constructor
MemMoveOptimization() : MemCpyOptimization("llvm.memmove") {}
} MemMoveOptimizer;
-/// A function to compute the length of a null-terminated string of integers.
-/// This function can't rely on the size of the constant array because there
-/// could be a null terminator in the middle of the array. We also have to
-/// bail out if we find a non-integer constant initializer of one of the
-/// elements or if there is no null-terminator. The logic below checks
+/// A function to compute the length of a null-terminated constant array of
+/// integers. This function can't rely on the size of the constant array
+/// because there could be a null terminator in the middle of the array.
+/// We also have to bail out if we find a non-integer constant initializer
+/// of one of the elements or if there is no null-terminator. The logic
+/// below checks each of these conditions and will return true only if all
+/// conditions are met. In that case, the \p len parameter is set to the length
+/// of the null-terminated string. If false is returned, the conditions were
+/// not met and len is set to 0.
+/// @brief Get the length of a constant string (null-terminated array).
bool getConstantStringLength(Value* V, uint64_t& len )
{
assert(V != 0 && "Invalid args to getConstantStringLength");
@@ -723,7 +741,6 @@
return true; // success!
}
-
// TODO: Additional cases that we need to add to this file:
// 1. memmove -> memcpy if src is a global constant array
}
More information about the llvm-commits
mailing list