This is an archive of the discontinued LLVM Phabricator instance.

Refactor inline threshold update code.
ClosedPublic

Authored by eraman on Jan 5 2017, 10:59 AM.

Details

Summary

Functional change: Previously, if a callee is cold, we used ColdThreshold if it minimizes the existing threshold. This was irrespective of whether we were optimizing for minsize (-Oz) or not. But -Oz uses very low threshold to begin with and the inlining with -Oz is expected to be tuned for lowering code size, so there is no good reason to set an even lower threshold for cold callees. We now lower the threshold for cold callees only when -Oz is not used. For default values of -inlinethreshold and -inlinecold-threshold, this change has no effect and this simplifies the code.

NFC changes: Group all threshold updates that are guarded by !Caller->optForMinSize() and within that group threshold updates that require profile summary info.

Diff Detail

Repository
rL LLVM

Event Timeline

eraman updated this revision to Diff 83275.Jan 5 2017, 10:59 AM
eraman retitled this revision from to Refactor inline threshold update code. NFC..
eraman updated this object.
eraman added reviewers: chandlerc, davidxl.
eraman added a subscriber: llvm-commits.
davidxl edited edge metadata.Jan 6 2017, 3:03 PM

There is a slight difference here. In the old code, for hot callsite to hot callee, the threshold is max of (origthreshold, HintThreshold, HotCallSiteThreshold). With the new change, it becomes max (original_threshold, HotCallSiteThreshold).

eraman added a comment.Jan 6 2017, 3:18 PM

There is a slight difference here. In the old code, for hot callsite to hot callee, the threshold is max of (origthreshold, HintThreshold, HotCallSiteThreshold). With the new change, it becomes max (original_threshold, HotCallSiteThreshold).

Good catch! But I'll leave the patch as it is (except the NFC in the title) since the whole point is to move away from using hotness of callee to hotness of callsite. Also, this will have no impact with the default values since HotCallSiteThreshold >> HintThreshold.

eraman retitled this revision from Refactor inline threshold update code. NFC. to Refactor inline threshold update code. .Jan 6 2017, 3:19 PM
eraman edited edge metadata.

Should we honor optForMinSize for HotCallsite case as well?

I also suggest split the source hint based check from the profile driven check. Also check hotcallsite first:

if (!Caller->optForMinSize() ) {

if (...InlineHint)
  Threshold = MaxIfValid (...);

if (HotCallsite)
   ...
else if (HotCallee) 
  ..

}

eraman added a comment.Jan 6 2017, 3:36 PM

Should we honor optForMinSize for HotCallsite case as well?

Yes, unless and until someone tunes PGO + -Os case.

I also suggest split the source hint based check from the profile driven check. Also check hotcallsite first:

if (!Caller->optForMinSize() ) {

if (...InlineHint)
  Threshold = MaxIfValid (...);

if (HotCallsite)
   ...
else if (HotCallee) 
  ..

}

Note that HotCallsite and HotCallee are mutually exclusive and if the callsite is hot that takes precedence over HotCallee. So
your comment on "check hot callsite first" is already done. I also don't see much point in writing

if (Callee.hasFnAttribute(Attribute::InlineHint))

Threshold = MaxIfValid(Threshold, Params.HintThreshold);

if ( HotCallee)

Threshold = MaxIfValid(Threshold, Params.HintThreshold);

instead of the current

if (Callee.hasFnAttribute(Attribute::InlineHint) || HotCallee)

Threshold = MaxIfValid(Threshold, Params.HintThreshold);
chandlerc edited edge metadata.Jan 6 2017, 3:52 PM

Should we honor optForMinSize for HotCallsite case as well?

Yes, unless and until someone tunes PGO + -Os case.

This is the '-Oz' case, where PGO doesn't really matter, so I suspect this will always be structured this way.

I also suggest split the source hint based check from the profile driven check. Also check hotcallsite first:

if (!Caller->optForMinSize() ) {

if (...InlineHint)
  Threshold = MaxIfValid (...);

if (HotCallsite)
   ...
else if (HotCallee) 
  ..

}

Note that HotCallsite and HotCallee are mutually exclusive and if the callsite is hot that takes precedence over HotCallee. So
your comment on "check hot callsite first" is already done. I also don't see much point in writing

if (Callee.hasFnAttribute(Attribute::InlineHint))

Threshold = MaxIfValid(Threshold, Params.HintThreshold);

if ( HotCallee)

Threshold = MaxIfValid(Threshold, Params.HintThreshold);

instead of the current

if (Callee.hasFnAttribute(Attribute::InlineHint) || HotCallee)

Threshold = MaxIfValid(Threshold, Params.HintThreshold);

But I think this whole thing can be written much more simply, and with fewer variables and correlated conditions:

// Listen to the inlinehint attribute or profile based hotness information
// when it would increase the threshold and the caller does not need to
// minimize its size.
if (!Caller->optForMinSize()) {
  if (Callee.hasFnAttribute(Attribute::InlineHint) || HotCallee)
    Threshold = MaxIfValid(Threshold, Params.HintThreshold);

  if (PSI) {
    uint64_t TotalWeight;
    if (CS.getInstruction()->extractProfTotalWeight(TotalWeight) &&
        PSI->isHotCount(TotalWeight)) {
    Threshold = MaxIfValid(Threshold, Params.HotCallSiteThreshold);
  } else if (PSI->isFunctionEntryHot(&Callee)) {
    // If callsite hotness can not be determined, we may still know
    // that the callee is hot and can use a smaller hint.
    Threshold = MaxIfValid(Threshold, Params.HintThreshold);
  } else if (PSI->isFunctionEntryCold(&Callee)) {
    Threshold = MinIfValid(Threshold, Params.ColdThreshold);
  }
}

This does remove the cold profile data from reducing the threshold in '-Oz' but I honestly can't understand why we would ever want a threshold *lower* than '-Oz'... at that level, we're only inlining when it actively shrinks code, and even for a cold call we would want to do that?

(obviously, my code had a bug, don't test for HotCallee when doing the inlinehint one)

Also, it might make sense to make the hot callee tunable independently from the inlinehint attribute even if the initial value is exactly the same.

eraman updated this revision to Diff 83467.Jan 6 2017, 5:01 PM
eraman edited edge metadata.

Rewrite as per Chandler's suggestion

eraman added a comment.Jan 6 2017, 5:03 PM

Should we honor optForMinSize for HotCallsite case as well?

Yes, unless and until someone tunes PGO + -Os case.

This is the '-Oz' case, where PGO doesn't really matter, so I suspect this will always be structured this way.

Right. It probably doesn't make sense to use the high threshold used for hot callee even with -Os, but that'll of course have to be a separate patch.

I also suggest split the source hint based check from the profile driven check. Also check hotcallsite first:

if (!Caller->optForMinSize() ) {

if (...InlineHint)
  Threshold = MaxIfValid (...);

if (HotCallsite)
   ...
else if (HotCallee) 
  ..

}

Note that HotCallsite and HotCallee are mutually exclusive and if the callsite is hot that takes precedence over HotCallee. So
your comment on "check hot callsite first" is already done. I also don't see much point in writing

if (Callee.hasFnAttribute(Attribute::InlineHint))

Threshold = MaxIfValid(Threshold, Params.HintThreshold);

if ( HotCallee)

Threshold = MaxIfValid(Threshold, Params.HintThreshold);

instead of the current

if (Callee.hasFnAttribute(Attribute::InlineHint) || HotCallee)

Threshold = MaxIfValid(Threshold, Params.HintThreshold);

But I think this whole thing can be written much more simply, and with fewer variables and correlated conditions:

// Listen to the inlinehint attribute or profile based hotness information
// when it would increase the threshold and the caller does not need to
// minimize its size.
if (!Caller->optForMinSize()) {
  if (Callee.hasFnAttribute(Attribute::InlineHint) || HotCallee)
    Threshold = MaxIfValid(Threshold, Params.HintThreshold);

  if (PSI) {
    uint64_t TotalWeight;
    if (CS.getInstruction()->extractProfTotalWeight(TotalWeight) &&
        PSI->isHotCount(TotalWeight)) {
    Threshold = MaxIfValid(Threshold, Params.HotCallSiteThreshold);
  } else if (PSI->isFunctionEntryHot(&Callee)) {
    // If callsite hotness can not be determined, we may still know
    // that the callee is hot and can use a smaller hint.
    Threshold = MaxIfValid(Threshold, Params.HintThreshold);
  } else if (PSI->isFunctionEntryCold(&Callee)) {
    Threshold = MinIfValid(Threshold, Params.ColdThreshold);
  }
}

Thanks. Rewrote as you suggested with a minor comment tweak.

This does remove the cold profile data from reducing the threshold in '-Oz' but I honestly can't understand why we would ever want a threshold *lower* than '-Oz'... at that level, we're only inlining when it actively shrinks code, and even for a cold call we would want to do that?

Makes sense.

davidxl accepted this revision.Jan 9 2017, 9:53 AM
davidxl edited edge metadata.

lgtm

This revision is now accepted and ready to land.Jan 9 2017, 9:53 AM

This LGTM, but please make sure you update the changed escription to explain exactly what all is changing here. For example with the cold vs. minsize, I think it's safe, and we can't even really usefully test it as in tree this never happens. But you may need to explain to people that if they *do* have a crazy minsize vs. cold threshold, they may need to fix them now.

Thanks for the refactoring!

eraman updated this object.Jan 9 2017, 1:33 PM
eraman edited edge metadata.

This LGTM, but please make sure you update the changed escription to explain exactly what all is changing here. For example with the cold vs. minsize, I think it's safe, and we can't even really usefully test it as in tree this never happens. But you may need to explain to people that if they *do* have a crazy minsize vs. cold threshold, they may need to fix them now.

Thanks for the refactoring!

Thanks. I've updated the description.

This revision was automatically updated to reflect the committed changes.