InlineCost.h revision caa2c40a57040dc3e1a5e40401cd1e4ede845451
15faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org//===- InlineCost.h - Cost analysis for inliner -----------------*- C++ -*-===//
25faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org//
35faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org//                     The LLVM Compiler Infrastructure
45faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org//
55faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org// This file is distributed under the University of Illinois Open Source
65faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org// License. See LICENSE.TXT for details.
75faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org//
85faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org//===----------------------------------------------------------------------===//
95faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org//
105faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org// This file implements heuristics for inlining decisions.
115faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org//
125faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org//===----------------------------------------------------------------------===//
138640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
145faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#ifndef LLVM_ANALYSIS_INLINECOST_H
153bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#define LLVM_ANALYSIS_INLINECOST_H
16d698f77c13d97c61109b861eac4d25b14a5de935bsalomon@google.com
17dbe49f735484f8862e378b63d0a074a301093dd0bsalomon@google.com#include "llvm/Function.h"
182eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com#include "llvm/ADT/DenseMap.h"
1917fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com#include "llvm/ADT/SmallPtrSet.h"
2017fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com#include "llvm/ADT/ValueMap.h"
213bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#include "llvm/Analysis/CodeMetrics.h"
223bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#include <cassert>
237938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#include <climits>
247938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#include <vector>
257938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
267938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgnamespace llvm {
277938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
287938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org  class CallSite;
297938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org  class TargetData;
307938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
317938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org  namespace InlineConstants {
327938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    // Various magic constants used to adjust heuristics.
337938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    const int InstrCost = 5;
345faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    const int IndirectCallThreshold = 100;
355faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    const int CallPenalty = 25;
365faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    const int LastCallToStaticBonus = -15000;
375faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    const int ColdccPenalty = 2000;
388640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    const int NoreturnPenalty = 10000;
398640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org  }
405faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
415faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  /// \brief Represents the cost of inlining a function.
425faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  ///
433bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org  /// This supports special values for functions which should "always" or
445faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  /// "never" be inlined. Otherwise, the cost represents a unitless amount;
455faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  /// smaller values increase the likelihood of the function being inlined.
465faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  ///
475faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  /// Objects of this type also provide the adjusted threshold for inlining
487938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org  /// based on the information available for a particular callsite. They can be
497938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org  /// directly tested to determine if inlining should occur given the cost and
505faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  /// threshold for this cost metric.
515faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  class InlineCost {
525faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    enum SentinelValues {
535faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org      AlwaysInlineCost = INT_MIN,
540e51577a14f903ffeafa117a75954baeb173ffb9humper@google.com      NeverInlineCost = INT_MAX
555faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    };
565faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
575faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// \brief The estimated cost of inlining this callsite.
58528952b5afea0e82bf6db9ef22128533d50ef9e3senorblanco@chromium.org    const int Cost;
59528952b5afea0e82bf6db9ef22128533d50ef9e3senorblanco@chromium.org
605faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// \brief The adjusted threshold against which this cost was computed.
618640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    const int Threshold;
625faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
635faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    // Trivial constructor, interesting logic in the factory functions below.
645faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    InlineCost(int Cost, int Threshold)
655faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org      : Cost(Cost), Threshold(Threshold) {}
665faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
675faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  public:
685faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    static InlineCost get(int Cost, int Threshold) {
695faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org      assert(Cost > AlwaysInlineCost && "Cost crosses sentinel value");
705faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org      assert(Cost < NeverInlineCost && "Cost crosses sentinel value");
71528952b5afea0e82bf6db9ef22128533d50ef9e3senorblanco@chromium.org      return InlineCost(Cost, Threshold);
72528952b5afea0e82bf6db9ef22128533d50ef9e3senorblanco@chromium.org    }
735faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    static InlineCost getAlways() {
748640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org      return InlineCost(AlwaysInlineCost, 0);
755faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
765faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    static InlineCost getNever() {
775faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org      return InlineCost(NeverInlineCost, 0);
785faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
795faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
805faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// \brief Test whether the inline cost is low enough for inlining.
815faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    operator bool() const {
825faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org      return Cost < Threshold;
837938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    }
845faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
855faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    bool isAlways() const   { return Cost == AlwaysInlineCost; }
865faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    bool isNever() const    { return Cost == NeverInlineCost; }
875faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    bool isVariable() const { return !isAlways() && !isNever(); }
885faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
895faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// \brief Get the inline cost estimate.
907938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    /// It is an error to call this on an "always" or "never" InlineCost.
917938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    int getCost() const {
927938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org      assert(isVariable() && "Invalid access of InlineCost");
935faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org      return Cost;
945faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
955faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
965faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// \brief Get the cost delta from the threshold for inlining.
975faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// Only valid if the cost is of the variable kind. Returns a negative
985faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// value if the cost is too high to inline.
997938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    int getCostDelta() const { return Threshold - getCost(); }
1007938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org  };
1017938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
1027938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org  /// InlineCostAnalyzer - Cost analyzer used by inliner.
1037938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org  class InlineCostAnalyzer {
1045faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    // TargetData if available, or null.
1057938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    const TargetData *TD;
1067938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
1075faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  public:
1085faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    InlineCostAnalyzer(): TD(0) {}
1095faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1105faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    void setTargetData(const TargetData *TData) { TD = TData; }
1115faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1125faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// \brief Get an InlineCost object representing the cost of inlining this
1135faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// callsite.
1147938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    ///
1157938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    /// Note that threshold is passed into this function. Only costs below the
1165faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// threshold are computed with any accuracy. The threshold can be used to
1175faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// bound the computation necessary to determine whether the cost is
1185faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    /// sufficiently low to warrant inlining.
1195faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    InlineCost getInlineCost(CallSite CS, int Threshold);
1205faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  };
1215faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1225faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org  /// callIsSmall - If a call is likely to lower to a single target instruction,
1238640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org  /// or is otherwise deemed small return true.
1247938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org  bool callIsSmall(const Function *Callee);
1257938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org}
1267938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
1277938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org#endif
1285faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org