//===- SimplifyLibCalls.cpp - Optimize specific well-known library calls --===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a variety of small optimizations for calls to specific
// well-known (e.g. runtime library) function calls. For example, a call to the
// function "exit(3)" that occurs within the main() function can be transformed
// into a simple "return 3" instruction. Any optimization that takes this form
// (replace call to library function with simpler code that provides same
// result) belongs in this file.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "simplify-libcalls"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/ADT/hash_map"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include <iostream>
using namespace llvm;
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");
// 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 SimplifyLibCalls pass will call the
/// ValidateCalledFunction method to ask the optimization if a given Function
/// 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
class LibCallOptimization
{
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 )
: func_name(fname)
#ifndef NDEBUG
, stat_name(std::string("simplify-libcalls:")+fname)
, stat_desc(std::string("Number of ")+fname+"(...) calls simplified")
, occurrences(stat_name.c_str(),stat_desc.c_str())
#endif
{
// Register this call optimizer in the optlist (a hash_map)
optlist[func_name] = this;
}
/// @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
/// SimplifyLibCalls::runOnModule to short circuit visiting all the call
/// sites of such a function if that function is not suitable in the first
/// p