// $Archive:: /Ti/inline/inline.h $ // $Date: Sun, 06 Jun 2004 02:33:00 -0700 $ // $Revision: 1.14 $ // Description: framework for method inlining // Copyright 2000, Dan Bonachea #ifndef _INLINE_H #define _INLINE_H /* General implementation notes: We generally care about 2 kinds of TreeNodes, MethodDecls and call sites code that manipulates call sites always holds a pointer to the statement containing the method call expression. We divide the task of inlining into policy and strategy, as suggested by [Kaser&Ramakrishnan98] Policy makes decisions about whether to inline a particular call site, and Strategy is the method for applying the policy to approximate a globally optimal solution Both are cast as abstract base classes which are implemented by actual inlining heurisitics that use policies and strategies of varying sophistication Inlining decisions are made on a site-by-site basis (pull from caller, rather than push from callee) Our current framework is to process the methods one at a time, making inlining decisions about all sites in a method before moving on to the next one For lots more information about the design of the method inliner, see method-inlining.pdf in the titanium-doc PRCS project */ #include "AST.h" //------------------------------------------------------------------------------------ class inlinePolicy { public: // called at the start of processing virtual void initializePolicy() { }; // called to get decision about whether to inline virtual bool shouldInline(TreeNode *callsite) = 0; // called after an inlining operation has been applied virtual void update(TreeNode *callSiteInlined, TreeNode *replacementCode) { }; // called at end of processing virtual void finalizePolicy() { } }; //------------------------------------------------------------------------------------ #define DEFAULT_MAX_INLINING_DEPTH 4 extern int opt_inline_maxdepth; class inlineStrategy { protected: inlinePolicy* policy; // the associated policy // parameters that can be tuned by subclasses // to change the behavior of the default run method bool considerSitesCreatedByInlining; // look at sites in inlined code int maxInliningDepth; // max depth of inlining into a given method (0 = unlimited) //bool inlineCallsFromStaticInitializers; // whether to inline calls in static blocks bool nextMethodChecked; // debug support - ensure methods don't get revisited public: inlineStrategy(inlinePolicy* policy) { this->policy = policy; // use the "safe" setting - considerSitesCreatedByInlining=true can cause // non-termination on recursive procedures if not handled carefully considerSitesCreatedByInlining = false; nextMethodChecked = true; // only necessary when considerSitesCreatedByInlining=true maxInliningDepth = (considerSitesCreatedByInlining ? opt_inline_maxdepth : 0); numSitesConsidered = 0; numSitesInlined = 0; numSitesRejectedByDepth = 0; } virtual ~inlineStrategy() { } // run the strategy - provides an intelligent default that should usually suffice // it makes calls to nextMethod() and queries the policy to direct behavior // most customization should happen there, not here void run(); static TreeNode * const DONTCARE; static TreeNode * const NOMORE; protected: // called by run() to choose the next method for consideration // method may return a ptr to a particular method, // DONTCARE to choose a random unvisited method, // or NOMORE to end processing virtual TreeNode* nextMethod() { return DONTCARE; } // called by run at the start of processing virtual void initializeStrategy() { }; // called by run at the end of processing virtual void finalizeStrategy() { }; // track some interesting bookeeping information int numSitesConsidered; int numSitesInlined; int numSitesRejectedByDepth; }; //------------------------------------------------------------------------------------ // decls for high-level inlining functions extern bool inlineDebug; extern bool inline2Debug; extern bool inlineStats; void doMethodInlining(); // the inlining phase TreeNode *inlineCallSite(TreeNode *t); // perform structural inlining at a call site void ensureLowered(TreeNode *method); // make sure a method has been lowered, do it now if necessary TreeNode *depthFirstSearch(TreeNode *t, bool (*filter)(const TreeNode *t), TreeNode * preorderaction(TreeNode *t)=NULL, TreeNode * postorderaction(TreeNode *t)=NULL, bool pruneSearchAtMatch = true); // framework for a depth-first search // filter decides (on initial visit) whether this node should get passed to pre and post order actions // pre and port order actions may return a modified subtree to replace current node, or NULL for no change // search may itself return a modified subtree llist *buildMethodList(bool onlyThoseSelectedForCodegen); // build a list of all methoddecls void fixupMethodAfterInline(TreeNode *methoddecl); // called after inlining operations have taken place on a method to fix up AST for subsequent phases //------------------------------------------------------------------------------------ // Useful utils for handling call statements bool isProcedure(const TreeNode *t); bool isProcedureCallNode(const TreeNode *t); bool isSimpleCallSite(const TreeNode *t); // just a call (return value ignored, if any) bool isCallAssignSite(const TreeNode *t); // a call-assign (return value is assigned into a variable) bool isProcedureCallSite(const TreeNode *t); bool isSuperThisCallSite(const TreeNode *callsite); // a call of the form super.method() (which is always statically bound) TreeNode *getSiteCallNode(const TreeNode *callsite); // given the call site stmt, return the actual call node TreeNode *getSiteCaller(TreeNode *callsite); // get caller of this site llist* getSiteCallees(TreeNode *callsite); // get all visible callees for this site TreeNode *getSiteCallee(TreeNode *callsite); // get the one-and-only callee for this site bool canCallStatically(TreeNode *callsite); llist *getPossibleMethodTargets(Decl *md, ClassDecl *targetObjectClassDecl); llist *getSystemEntryPoints(); // return list of all system execution entry points string getMethodFullName(TreeNode *method); // prints user-friendly info to identify this method string getMethodShortName(TreeNode *method); // just the method name string printMethodList(llist *methodlist); //outputs a list of method names #endif