Пример #1
0
/// shouldInline - Return true if the inliner should attempt to inline
/// at the given CallSite.
bool Inliner::shouldInline(CallSite CS) {
    InlineCost IC = getInlineCost(CS);
    float FudgeFactor = getInlineFudgeFactor(CS);

    if (IC.isAlways()) {
        DOUT << "    Inlining: cost=always"
             << ", Call: " << *CS.getInstruction();
        return true;
    }

    if (IC.isNever()) {
        DOUT << "    NOT Inlining: cost=never"
             << ", Call: " << *CS.getInstruction();
        return false;
    }

    int Cost = IC.getValue();
    int CurrentThreshold = InlineThreshold;
    Function *Fn = CS.getCaller();
    if (Fn && !Fn->isDeclaration()
            && Fn->hasFnAttr(Attribute::OptimizeForSize)
            && InlineThreshold != 50) {
        CurrentThreshold = 50;
    }

    if (Cost >= (int)(CurrentThreshold * FudgeFactor)) {
        DOUT << "    NOT Inlining: cost=" << Cost
             << ", Call: " << *CS.getInstruction();
        return false;
    } else {
        DOUT << "    Inlining: cost=" << Cost
             << ", Call: " << *CS.getInstruction();
        return true;
    }
}
Пример #2
0
/// inlineFuctions - Walk all call sites in all functions supplied by
/// client. Inline as many call sites as possible. Delete completely
/// inlined functions.
void BasicInlinerImpl::inlineFunctions() {

    // Scan through and identify all call sites ahead of time so that we only
    // inline call sites in the original functions, not call sites that result
    // from inlining other functions.
    std::vector<CallSite> CallSites;

    for (std::vector<Function *>::iterator FI = Functions.begin(),
            FE = Functions.end(); FI != FE; ++FI) {
        Function *F = *FI;
        for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
            for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
                CallSite CS(cast<Value>(I));
                if (CS && CS.getCalledFunction()
                        && !CS.getCalledFunction()->isDeclaration())
                    CallSites.push_back(CS);
            }
    }

    DEBUG(dbgs() << ": " << CallSites.size() << " call sites.\n");

    // Inline call sites.
    bool Changed = false;
    do {
        Changed = false;
        for (unsigned index = 0; index != CallSites.size() && !CallSites.empty();
                ++index) {
            CallSite CS = CallSites[index];
            if (Function *Callee = CS.getCalledFunction()) {

                // Eliminate calls that are never inlinable.
                if (Callee->isDeclaration() ||
                        CS.getInstruction()->getParent()->getParent() == Callee) {
                    CallSites.erase(CallSites.begin() + index);
                    --index;
                    continue;
                }
                InlineCost IC = CA.getInlineCost(CS, NeverInline);
                if (IC.isAlways()) {
                    DEBUG(dbgs() << "  Inlining: cost=always"
                          <<", call: " << *CS.getInstruction());
                } else if (IC.isNever()) {
                    DEBUG(dbgs() << "  NOT Inlining: cost=never"
                          <<", call: " << *CS.getInstruction());
                    continue;
                } else {
                    int Cost = IC.getValue();

                    if (Cost >= (int) BasicInlineThreshold) {
                        DEBUG(dbgs() << "  NOT Inlining: cost = " << Cost
                              << ", call: " <<  *CS.getInstruction());
                        continue;
                    } else {
                        DEBUG(dbgs() << "  Inlining: cost = " << Cost
                              << ", call: " <<  *CS.getInstruction());
                    }
                }

                // Inline
                InlineFunctionInfo IFI(0, TD);
                if (InlineFunction(CS, IFI)) {
                    Callee->removeDeadConstantUsers();
                    if (Callee->isDefTriviallyDead())
                        DeadFunctions.insert(Callee);
                    Changed = true;
                    CallSites.erase(CallSites.begin() + index);
                    --index;
                }
            }
        }
    } while (Changed);

    // Remove completely inlined functions from module.
    for(SmallPtrSet<Function *, 8>::iterator I = DeadFunctions.begin(),
            E = DeadFunctions.end(); I != E; ++I) {
        Function *D = *I;
        Module *M = D->getParent();
        M->getFunctionList().remove(D);
    }
}
Пример #3
0
/// shouldInline - Return true if the inliner should attempt to inline
/// at the given CallSite.
bool Inliner::shouldInline(CallSite CS) {
  InlineCost IC = getInlineCost(CS);
  
  if (IC.isAlways()) {
    DEBUG(dbgs() << "    Inlining: cost=always"
          << ", Call: " << *CS.getInstruction() << "\n");
    return true;
  }
  
  if (IC.isNever()) {
    DEBUG(dbgs() << "    NOT Inlining: cost=never"
          << ", Call: " << *CS.getInstruction() << "\n");
    return false;
  }
  
  int Cost = IC.getValue();
  Function *Caller = CS.getCaller();
  int CurrentThreshold = getInlineThreshold(CS);
  float FudgeFactor = getInlineFudgeFactor(CS);
  int AdjThreshold = (int)(CurrentThreshold * FudgeFactor);
  if (Cost >= AdjThreshold) {
    DEBUG(dbgs() << "    NOT Inlining: cost=" << Cost
          << ", thres=" << AdjThreshold
          << ", Call: " << *CS.getInstruction() << "\n");
    return false;
  }
  
  // Try to detect the case where the current inlining candidate caller
  // (call it B) is a static function and is an inlining candidate elsewhere,
  // and the current candidate callee (call it C) is large enough that
  // inlining it into B would make B too big to inline later.  In these
  // circumstances it may be best not to inline C into B, but to inline B
  // into its callers.
  if (Caller->hasLocalLinkage()) {
    int TotalSecondaryCost = 0;
    bool outerCallsFound = false;
    bool allOuterCallsWillBeInlined = true;
    bool someOuterCallWouldNotBeInlined = false;
    for (Value::use_iterator I = Caller->use_begin(), E =Caller->use_end(); 
         I != E; ++I) {
      CallSite CS2(*I);

      // If this isn't a call to Caller (it could be some other sort
      // of reference) skip it.
      if (!CS2 || CS2.getCalledFunction() != Caller)
        continue;

      InlineCost IC2 = getInlineCost(CS2);
      if (IC2.isNever())
        allOuterCallsWillBeInlined = false;
      if (IC2.isAlways() || IC2.isNever())
        continue;

      outerCallsFound = true;
      int Cost2 = IC2.getValue();
      int CurrentThreshold2 = getInlineThreshold(CS2);
      float FudgeFactor2 = getInlineFudgeFactor(CS2);

      if (Cost2 >= (int)(CurrentThreshold2 * FudgeFactor2))
        allOuterCallsWillBeInlined = false;

      // See if we have this case.  We subtract off the penalty
      // for the call instruction, which we would be deleting.
      if (Cost2 < (int)(CurrentThreshold2 * FudgeFactor2) &&
          Cost2 + Cost - (InlineConstants::CallPenalty + 1) >= 
                (int)(CurrentThreshold2 * FudgeFactor2)) {
        someOuterCallWouldNotBeInlined = true;
        TotalSecondaryCost += Cost2;
      }
    }
    // If all outer calls to Caller would get inlined, the cost for the last
    // one is set very low by getInlineCost, in anticipation that Caller will
    // be removed entirely.  We did not account for this above unless there
    // is only one caller of Caller.
    if (allOuterCallsWillBeInlined && Caller->use_begin() != Caller->use_end())
      TotalSecondaryCost += InlineConstants::LastCallToStaticBonus;

    if (outerCallsFound && someOuterCallWouldNotBeInlined && 
        TotalSecondaryCost < Cost) {
      DEBUG(dbgs() << "    NOT Inlining: " << *CS.getInstruction() << 
           " Cost = " << Cost << 
           ", outer Cost = " << TotalSecondaryCost << '\n');
      return false;
    }
  }

  DEBUG(dbgs() << "    Inlining: cost=" << Cost
        << ", thres=" << AdjThreshold
        << ", Call: " << *CS.getInstruction() << '\n');
  return true;
}
Пример #4
0
/// shouldInline - Return true if the inliner should attempt to inline
/// at the given CallSite.
bool Inliner::shouldInline(CallSite CS) {
  InlineCost IC = getInlineCost(CS);
  
  if (IC.isAlways()) {
    DEBUG(dbgs() << "    Inlining: cost=always"
          << ", Call: " << *CS.getInstruction() << "\n");
    return true;
  }
  
  if (IC.isNever()) {
    DEBUG(dbgs() << "    NOT Inlining: cost=never"
          << ", Call: " << *CS.getInstruction() << "\n");
    return false;
  }
  
  int Cost = IC.getValue();
  Function *Caller = CS.getCaller();
  int CurrentThreshold = getInlineThreshold(CS);
  float FudgeFactor = getInlineFudgeFactor(CS);
  int AdjThreshold = (int)(CurrentThreshold * FudgeFactor);
  if (Cost >= AdjThreshold) {
    DEBUG(dbgs() << "    NOT Inlining: cost=" << Cost
          << ", thres=" << AdjThreshold
          << ", Call: " << *CS.getInstruction() << "\n");
    return false;
  }
  
  // Try to detect the case where the current inlining candidate caller (call
  // it B) is a static or linkonce-ODR function and is an inlining candidate
  // elsewhere, and the current candidate callee (call it C) is large enough
  // that inlining it into B would make B too big to inline later. In these
  // circumstances it may be best not to inline C into B, but to inline B into
  // its callers.
  //
  // This only applies to static and linkonce-ODR functions because those are
  // expected to be available for inlining in the translation units where they
  // are used. Thus we will always have the opportunity to make local inlining
  // decisions. Importantly the linkonce-ODR linkage covers inline functions
  // and templates in C++.
  if (Caller->hasLocalLinkage() ||
      Caller->getLinkage() == GlobalValue::LinkOnceODRLinkage) {
    int TotalSecondaryCost = 0;
    bool outerCallsFound = false;
    // This bool tracks what happens if we do NOT inline C into B.
    bool callerWillBeRemoved = true;
    // This bool tracks what happens if we DO inline C into B.
    bool inliningPreventsSomeOuterInline = false;
    for (Value::use_iterator I = Caller->use_begin(), E =Caller->use_end(); 
         I != E; ++I) {
      CallSite CS2(*I);

      // If this isn't a call to Caller (it could be some other sort
      // of reference) skip it.  Such references will prevent the caller
      // from being removed.
      if (!CS2 || CS2.getCalledFunction() != Caller) {
        callerWillBeRemoved = false;
        continue;
      }

      InlineCost IC2 = getInlineCost(CS2);
      if (IC2.isNever())
        callerWillBeRemoved = false;
      if (IC2.isAlways() || IC2.isNever())
        continue;

      outerCallsFound = true;
      int Cost2 = IC2.getValue();
      int CurrentThreshold2 = getInlineThreshold(CS2);
      float FudgeFactor2 = getInlineFudgeFactor(CS2);

      if (Cost2 >= (int)(CurrentThreshold2 * FudgeFactor2))
        callerWillBeRemoved = false;

      // See if we have this case.  We subtract off the penalty
      // for the call instruction, which we would be deleting.
      if (Cost2 < (int)(CurrentThreshold2 * FudgeFactor2) &&
          Cost2 + Cost - (InlineConstants::CallPenalty + 1) >= 
                (int)(CurrentThreshold2 * FudgeFactor2)) {
        inliningPreventsSomeOuterInline = true;
        TotalSecondaryCost += Cost2;
      }
    }
    // If all outer calls to Caller would get inlined, the cost for the last
    // one is set very low by getInlineCost, in anticipation that Caller will
    // be removed entirely.  We did not account for this above unless there
    // is only one caller of Caller.
    if (callerWillBeRemoved && Caller->use_begin() != Caller->use_end())
      TotalSecondaryCost += InlineConstants::LastCallToStaticBonus;

    if (outerCallsFound && inliningPreventsSomeOuterInline &&
        TotalSecondaryCost < Cost) {
      DEBUG(dbgs() << "    NOT Inlining: " << *CS.getInstruction() << 
           " Cost = " << Cost << 
           ", outer Cost = " << TotalSecondaryCost << '\n');
      return false;
    }
  }

  DEBUG(dbgs() << "    Inlining: cost=" << Cost
        << ", thres=" << AdjThreshold
        << ", Call: " << *CS.getInstruction() << '\n');
  return true;
}