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.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
llvm/lib/Transforms/IPO/PartialInlining.cpp | ||
---|---|---|
1420 | Is it legal to partial inline in case when the function's block address is taken? |
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? |
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? |
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 |
llvm/lib/Transforms/IPO/PartialInlining.cpp | ||
---|---|---|
974 | Thought about that but didn't do that for two reasons:
So I choose to make changes on the caller side so that the assumption holds for getSupportedCallBase. | |
1420 |
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.
The code you linked still allow callbr/asm-goto, it disables inlining if address taken blocks are used outside of asm-goto. |
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. |
llvm/lib/Transforms/IPO/PartialInlining.cpp | ||
---|---|---|
1420 |
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 (BB->hasAddressTaken()) for (User *U : BlockAddress::get(&*BB)->users()) if (!isa<CallBrInst>(*U)) return InlineResult::failure("blockaddress used outside of callbr"); |
Moving the check into getSupportedCallBase? The assertion llvm_unreachable("All uses must be calls"); there seems too strong.