This is an archive of the discontinued LLVM Phabricator instance.

[PartialInline] Bail out on asm-goto/callbr
ClosedPublic

Authored by wenlei on Jan 17 2022, 12:07 PM.

Details

Summary

Fixing ICE when partial inline tries to deal with blockaddress uses of function which is typical for asm-goto/callbr. We ran into this with PGO multi-region partial inline.

Diff Detail

Event Timeline

wenlei created this revision.Jan 17 2022, 12:07 PM
wenlei requested review of this revision.Jan 17 2022, 12:07 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 17 2022, 12:07 PM
davidxl added inline comments.Jan 17 2022, 1:40 PM
llvm/lib/Transforms/IPO/PartialInlining.cpp
1420

Is it legal to partial inline in case when the function's block address is taken?

ormris removed a subscriber: ormris.Jan 18 2022, 9:22 AM
hoy added inline comments.Jan 18 2022, 11:12 AM
llvm/lib/Transforms/IPO/PartialInlining.cpp
974

Moving the check into getSupportedCallBase? The assertion llvm_unreachable("All uses must be calls"); there seems too strong.

1420

I think so. The non-inlined callsites will still call the original version, while the inlined callsites will pull in the new version. The new version has some context-irrelevant code outlined, but both versions should be semantically equal. Please correct me if I'm missing anything?

davidxl added inline comments.Jan 18 2022, 11:48 AM
llvm/lib/Transforms/IPO/PartialInlining.cpp
1420

what if the labels and references from asm goto are in different regions -- one in inlined region, and the other in the outllined region?

hoy added inline comments.Jan 18 2022, 11:56 AM
llvm/lib/Transforms/IPO/PartialInlining.cpp
1420

If internal blocks of an inlinee are address taken, the inlining should be disabled during the cost analysis: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/InlineCost.cpp#L2656

wenlei added inline comments.Jan 18 2022, 10:42 PM
llvm/lib/Transforms/IPO/PartialInlining.cpp
974

Thought about that but didn't do that for two reasons:

  1. The API assume we would get one call for each User, but BlockAddress is a constant, so it doesn't have 1:1 mapping even for CallBr.
  2. The contract of assuming valid Call makes sense for other use cases, e.g. getOneCallSiteTo. If we return null for all BlockAddress in getSupportedCallBase, there will be more error handling for getOneCallSiteTo and its caller, which is less clean.

So I choose to make changes on the caller side so that the assumption holds for getSupportedCallBase.

1420

what if the labels and references from asm goto are in different regions -- one in inlined region, and the other in the outllined region?

Is this concerning side entrance into the outlined region through asm goto? The outlining for partial inline requires single entry single exit region, so asm goto should not introduce side entrance.

If internal blocks of an inlinee are address taken, the inlining should be disabled during the cost analysis: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/InlineCost.cpp#L2656

The code you linked still allow callbr/asm-goto, it disables inlining if address taken blocks are used outside of asm-goto.

davidxl accepted this revision.Jan 19 2022, 8:06 AM

lgtm

llvm/lib/Transforms/IPO/PartialInlining.cpp
1420

In general, the legality check should be done earlier otherwise we may end up with situation where function outlining happens but partial inlining is disabled -- resulting in less efficient code.

However as Wenlei mentioned, cross region jumps may not be an issue.

This revision is now accepted and ready to land.Jan 19 2022, 8:06 AM
hoy accepted this revision.Jan 19 2022, 8:51 AM
hoy added inline comments.
llvm/lib/Transforms/IPO/PartialInlining.cpp
974

Sounds good.

1420

The code you linked still allow callbr/asm-goto, it disables inlining if address taken blocks are used outside of asm-goto.

Is asm-goto equivalent to callbr? I thought callbr can only deal with function entry but not internal blocks.

wenlei added inline comments.Jan 19 2022, 10:33 AM
llvm/lib/Transforms/IPO/PartialInlining.cpp
1420

The code you linked still allow callbr/asm-goto, it disables inlining if address taken blocks are used outside of asm-goto.

Is asm-goto equivalent to callbr? I thought callbr can only deal with function entry but not internal blocks.

The only use of callbr is for asm-goto, so yes in practice they're equivalent.

But the code you linked only bails out when the use of block address is *not* callbr. So it doesn't block callbr, which means this statement below isn't true.

If internal blocks of an inlinee are address taken, the inlining should be disabled during the cost analysis

if (BB->hasAddressTaken())
      for (User *U : BlockAddress::get(&*BB)->users())
        if (!isa<CallBrInst>(*U))
          return InlineResult::failure("blockaddress used outside of callbr");
This revision was landed with ongoing or failed builds.Jan 19 2022, 10:58 AM
This revision was automatically updated to reflect the committed changes.