This is an archive of the discontinued LLVM Phabricator instance.

[Inliner] Preserve nonnull from callsites during inlining
Needs RevisionPublic

Authored by xbolva00 on Apr 6 2023, 5:09 AM.

Details

Summary

Inliner fails to simplify inlined function based on known callsite attributes

declare void @h(ptr %p)

define void @f(ptr %p) {
	call void @g(ptr nonnull %p)
	ret void
}

define void @g(ptr %p) {
	call void @h(ptr %p)
	ret void
}

Inliner inlines g into f but we lose extra info that %p was nonnull ptr. Implemented suggested solution, so insert nonnull assumes in Inliner to preserve knowledge.

Fixes https://github.com/llvm/llvm-project/issues/61966

Diff Detail

Event Timeline

xbolva00 created this revision.Apr 6 2023, 5:09 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 6 2023, 5:09 AM
xbolva00 requested review of this revision.Apr 6 2023, 5:09 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 6 2023, 5:09 AM
xbolva00 edited the summary of this revision. (Show Details)Apr 6 2023, 5:15 AM
xbolva00 updated this revision to Diff 511379.Apr 6 2023, 5:32 AM
xbolva00 updated this revision to Diff 511380.Apr 6 2023, 5:36 AM
xbolva00 updated this revision to Diff 511387.Apr 6 2023, 6:06 AM
xbolva00 updated this revision to Diff 511388.
xbolva00 updated this revision to Diff 511390.Apr 6 2023, 6:09 AM

what's the compile time impact of this?

llvm/lib/Transforms/Utils/InlineFunction.cpp
1475

are there tests for isKnownNonZero?

llvm/test/Transforms/Inline/assumptions-from-callsite-attrs.ll
3

redundant RUN line

4

I wouldn't worry about the module inliner, it's still experimental

llvm/test/Transforms/PhaseOrdering/dae-dce.ll
22

isn't this now UB?

nikic added a subscriber: nikic.Apr 13 2023, 12:34 AM
nikic added inline comments.
llvm/lib/Transforms/Utils/InlineFunction.cpp
1475

You need both nonnull and noundef to convert to assume.

nikic requested changes to this revision.Apr 13 2023, 1:34 AM
nikic added inline comments.
llvm/test/Transforms/PhaseOrdering/dae-dce.ll
22

I checked, and this is also caused by not respecting noundef. The noundef on the call is dropped by the time of inlining.

This revision now requires changes to proceed.Apr 13 2023, 1:34 AM

Added check 'CB.getAttributes().hasParamAttr(ArgNo, Attribute::NoUndef)'. The impact of this PR is non-trivial:
https://llvm-compile-time-tracker.com/compare.php?from=06ddb7bfe24891eee43bcf19252708b0cf684562&to=d1559cc73ad38f7684a026f8c69c6c96af9246a3&stat=instructions:u

especially for tramp3d-v4, where we can also observe a bigger codesize change.

yeah that compile time increase is unacceptable

I've run into related issues where we lose the return value alignment after inlining, as pointed out in https://reviews.llvm.org/D123052

xbolva00 added a comment.EditedApr 21 2023, 2:38 PM

alignment info generally hits same issue

https://llvm.org/doxygen/InlineFunction_8cpp.html#a4224e0e010bb5413dc74243c276724f5

Disabled by default, because the added alignment assumptions may increase
compile-time and block optimizations. This option is not suitable for use
with frontends that emit comprehensive parameter alignment annotations.

So ideally we should have cheap and more general solution for this problem. Any ideas?

Something "cheap" we could do is attach nonnull attributes to arguments of inlined calls, when appropriate.

llvm.assume is fundamentally pretty expensive; it bloats use-lists, and there's additional instructions feeding into the assume. There are some aspects we could make cheaper with an optimized form of llvm.assume, but it's not easy.

Something "cheap" we could do is attach nonnull attributes to arguments of inlined calls, when appropriate.

Lets assume following example:
https://godbolt.org/z/TY9h1PYqY

Clearly we fail to eliminate the "is not null" comparison and we have the attached nonnull attribute on the passed argument.
Can you please explain your approach more in details?

nikic added a comment.May 5 2023, 11:44 AM

@xbolva00 Could you please explain what the larger context here is? Which frontend generates nonnull on call-site only?

xbolva00 added a comment.EditedMay 5 2023, 12:19 PM

@xbolva00 Could you please explain what the larger context here is? Which frontend generates nonnull on call-site only?

I was working on something else and I then found testcases in https://github.com/llvm/llvm-project/blob/ca42cd3e1264f8b44304019da07b6059a610fd24/llvm/test/Transforms/Inline/nonnull.ll#L75 and I was experimenting why some combinations of nonnull attribute placements work and some not. I am not aware of such frontend, indeed, but there are many LLVM-based compilers, so who knows..

I was wondering if a frontend or midend passes in some cases / contexts could add additional nonnull call site attribute to preserve knowledge. Currently I am only aware of added attributes on call sites with C libcalls by SimplifyLibCalls, so probably I have no real motivation case.