diff --git a/llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp b/llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp new file mode 100644 index 000000000000..f7b4eb9e425e --- /dev/null +++ b/llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp @@ -0,0 +1,167 @@ +//===- SimplifyLibCalls.cpp - Optimize specific well-known librayr calls --===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer group 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. Many of the ideas for these +// optimizations were taken from GCC's "builtins.c" file but their +// implementation here is completely knew and LLVM-centric +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/IPO.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Instructions.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +namespace { + Statistic<> SimplifiedLibCalls("simplified-lib-calls", + "Number of well-known library calls simplified"); + + /// 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 provides the basic infrastructure for handling + /// runOnModule. Subclasses register themselves and provide two methods: + /// RecognizeCall and OptimizeCall. Whenever this class finds a function call, + /// it asks the subclasses to recognize the call. If it is recognized, then + /// the OptimizeCall method is called on that subclass instance. In this way + /// the subclasses implement the calling conditions on which they trigger and + /// the action to perform, making it easy to add new optimizations of this + /// form. + /// @brief A ModulePass for optimizing well-known function calls + struct SimplifyLibCalls : public ModulePass { + + + /// For this pass, process all of the function calls in the module, calling + /// RecognizeCall and OptimizeCall as appropriate. + virtual bool runOnModule(Module &M); + + }; + + RegisterOpt + X("simplify-libcalls","Simplify well-known library calls"); + + struct CallOptimizer + { + /// @brief Constructor that registers the optimization + CallOptimizer(); + + virtual ~CallOptimizer(); + + /// The implementations of this function in subclasses is the heart of the + /// SimplifyLibCalls algorithm. Sublcasses of this class implement + /// OptimizeCall to determine if (a) the conditions are right for optimizing + /// 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, const Function* f) const = 0; + }; + + /// @brief The list of optimizations deriving from CallOptimizer + std::vector optlist; + + CallOptimizer::CallOptimizer() + { + // Register this call optimizer + optlist.push_back(this); + } + + /// Make sure we get our virtual table in this file. + CallOptimizer::~CallOptimizer() {} +} + +ModulePass *llvm::createSimplifyLibCallsPass() +{ + return new SimplifyLibCalls(); +} + +bool SimplifyLibCalls::runOnModule(Module &M) +{ + for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) + { + // All the "well-known" functions are external because they live in a + // runtime library somewhere and were (probably) not compiled by LLVM. + // So, we only act on external functions that have non-empty uses. + if (FI->isExternal() && !FI->use_empty()) + { + // Loop over each of the uses of the function + for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end(); + UI != UE ; ) + { + CallInst* CI = dyn_cast(*UI); + ++UI; + + // If the use of the function is a call instruction + if (CI) + { + // Loop over each of the registered optimizations and find the one + // that can optimize this call. + std::vector::iterator OI = optlist.begin(); + std::vector::iterator OE = optlist.end(); + for ( ; OI != OE ; ++OI) + { + if ((*OI)->OptimizeCall(CI,&(*FI))) + { + ++SimplifiedLibCalls; + break; + } + } + } + } + } + } + return true; +} + +namespace { + +/// This CallOptimizer 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. +/// @brief Replace calls to exit in main with a simple return +struct ExitInMainOptimization : public CallOptimizer +{ +virtual ~ExitInMainOptimization() {} +bool OptimizeCall(CallInst* ci, const Function* func) const +{ + // If this isn't the exit function then we don't act + if (func->getName() != "exit") + return false; + + // If the call isn't coming from main then we don't act + if (const Function* f = ci->getParent()->getParent()) + if (f->getName() != "main") + return false; + + // Okay, time to replace it. Get the basic block of the call instruction + BasicBlock* bb = ci->getParent(); + + // Create a return instruction that we'll replace the call with. Note that + // the argument of the return is the argument of the call instruction. + ReturnInst* ri = new ReturnInst(ci->getOperand(1), ci); + + // Erase everything from the call instruction to the end of the block. There + // really shouldn't be anything other than the call instruction, but just in + // case there is we delete it all because its now dead. + bb->getInstList().erase(ci, bb->end()); + + return true; +} + +} ExitInMainOptimizer; + +}