This is an archive of the discontinued LLVM Phabricator instance.

[PartialInlining] Fix incorrect costing when IR has unreachable BBs
ClosedPublic

Authored by vedant-amd on Apr 25 2023, 12:38 AM.

Details

Summary

Partial Inlining identifies basic blocks that can be outlined into a
function. It is possible that an unreachable basic block is marked for
outlining. During costing of the outlined region, such unreachable basic
blocks are included as well. However, the CodeExtractor eliminates such
unreachable basic blocks and emits outlined function without them.

Thus, during costing of the outlined function, it is possible that the
cost of the outlined function comes out to be lesser than the cost of
outlined region, which triggers an assert.

Assertion `OutlinedFunctionCost >= Cloner.OutlinedRegionCost && "Outlined
function cost should be no less than the outlined region"' failed.

This patch adds code to eliminate unreachable blocks from the function
body before passing it on to be inlined. It also adds a test that checks
for behaviour of costing in case of unreachable basic blocks.

Discussion: https://discourse.llvm.org/t/incorrect-costing-in-partialinliner-if-ir-has-unreachable-basic-blocks/70163

Diff Detail

Event Timeline

vedant-amd created this revision.Apr 25 2023, 12:38 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 25 2023, 12:38 AM
vedant-amd requested review of this revision.Apr 25 2023, 12:38 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 25 2023, 12:38 AM

Generally, I don't believe we should run elimination in all passes.
Instead, use the dominance tree to walk the blocks of a function, or walk it by manually following the control edges.

fhahn added a comment.Apr 25 2023, 1:32 PM

If the block is unreachable, how come it is even considered for outlining?

If the block is unreachable, how come it is even considered for outlining?

This behaviour is triggered even if there are regions of unreachable basic blocks.

no predecessors -> A -> B -> C -> while.end

Generally, I don't believe we should run elimination in all passes.
Instead, use the dominance tree to walk the blocks of a function, or walk it by manually following the control edges.

Generally, I don't believe we should run elimination in all passes.
Instead, use the dominance tree to walk the blocks of a function, or walk it by manually following the control edges.

Adding a check here to see if the given basic block (or region of basic blocks) has a pred makes sense: https://github.com/llvm/llvm-project/blob/8fc1764ef3d18b65b52f82ca4a6bf56ac024e589/llvm/lib/Transforms/IPO/PartialInlining.cpp#L1182

Should I try to implement that using DT ?

If the block is unreachable, how come it is even considered for outlining?

I think there's simply no check in place, https://github.com/llvm/llvm-project/blob/8fc1764ef3d18b65b52f82ca4a6bf56ac024e589/llvm/lib/Transforms/IPO/PartialInlining.cpp#L1182

It just checks if the BB can be inlined, if not it marks it for outlining.

fhahn added a comment.Apr 26 2023, 2:18 AM

If the block is unreachable, how come it is even considered for outlining?

I think there's simply no check in place, https://github.com/llvm/llvm-project/blob/8fc1764ef3d18b65b52f82ca4a6bf56ac024e589/llvm/lib/Transforms/IPO/PartialInlining.cpp#L1182

It just checks if the BB can be inlined, if not it marks it for outlining.

Yeah that looks like the right place. Instead of iterating over all blocks in the function, it should probably iterate over all blocks reachable from the entry node (e.g. something like depth_first(Cloned->getEntryBlock()).

vedant-amd updated this revision to Diff 519789.May 5 2023, 3:09 AM

Removed pass wide unreachable block elimination added a depth_first approach to iterate over basic blocks

vedant-amd added a comment.EditedMay 5 2023, 3:11 AM

Hey @fhahn @jdoerfert Sorry for the delay, but I have updated the patch to reflect your requested changes. Please let me know if it looks okay ?

fhahn added a comment.May 8 2023, 9:57 AM

It looks like clang-format failed in the pre-commit tests. Could you please make sure the diff is properly formatted by running clang-format-diff?

Run clang-format-diff on the code

vedant-amd added a comment.EditedMay 8 2023, 11:31 AM

It looks like clang-format failed in the pre-commit tests. Could you please make sure the diff is properly formatted by running clang-format-diff?

Sure, I have updated the patch, it passes the clang check. Does the patch look good ?

fhahn accepted this revision.May 9 2023, 4:43 AM

LGTM, thanks!

This revision is now accepted and ready to land.May 9 2023, 4:43 AM
vedant-amd added a comment.EditedMay 9 2023, 5:20 AM

LGTM, thanks!

I pushed using arc patch D<code>, but it seems to have not worked or something

The patch doesn't reflect in the llvm-project repo yet, did I mess up something ?

Edit: It seems github is down: https://www.githubstatus.com/