If a function has alwaysinline attribute and can be inlined, we can treat the function as it has exact definition and perform fix-point analysis on it
Details
Diff Detail
Event Timeline
llvm/include/llvm/Transforms/IPO/Attributor.h | ||
---|---|---|
1734 | Is FnScope always nonnull here? |
llvm/include/llvm/Transforms/IPO/Attributor.h | ||
---|---|---|
1734 | I think so, because the outer if has judgement: if(!FnScope || !FnScope->hasExactDefinition()) |
I have fixed the problem that FnScope may be null and cached the result of isInlineViable. I have also updated my test file to check the attributes.
When I said "cache the result" I meant that we should ensure to call isInlineViable for each function at most once. Maybe at the beginning of the Attributor::run method we can go over all the functions and categorize them. If they have exact linkage *or* are alwaysinline and and viable to be inlined, we say they are "IPO amendable" and we put them in a set. We can then lookup in the set if the function is fine w/o the need to look for all criteria again. Does that make sense?
llvm/test/Transforms/Attributor/alwaysinline.ll | ||
---|---|---|
10 | What do you mean by "removed safely" here? | |
22 | is this one not readnone? | |
34 | We analyze and annotate it because it is an exact definition, see Function::hasExactDefinition(). Make the function linkonce (or add another pair with linkonce) to see the difference. |
- Use InlineableFunctions ptr set to track functions that can be inlined
- As the ptr set is a private variable for Attributor, so in AA.initialize(), we cannot determine if the inexactly defined function can be inlined or not, so all inexactly defined functions that have alwayinline attribute will keep its state unchanged (just return from the function)
- In CreateAAFor function, search the ptr set for the function, if the function has alwayinline attribute but cannot be inlined, we cannot analyze it (indicatePessimisticFixpoint)
llvm/test/Transforms/Attributor/alwaysinline.ll | ||
---|---|---|
22 | I think it should be readnone, but I tried opt without the patch with the following example: define void @inner1() alwaysinline { [...] } and the outer1 function does not have the readnone attribute, either. define void @inner1() { [....] } The outer1 function will have the readnone attribute |
llvm/include/llvm/Transforms/IPO/Attributor.h | ||
---|---|---|
1119 | Nit: You can use !InfoCache.InlineableFunctions.count(FnScope) (it is shorter) |
In the initialize method in question, ask the Attributor if a function is "IPO amendable". We need a new helper method for that in the Attributor. It will look at the position, linkage (via the isexact definition), and alwaysinline + inlinable "attributes". This way it we have a single location to do the lookup. It is reusable and easier to understand.
llvm/lib/Transforms/IPO/Attributor.cpp | ||
---|---|---|
8216 | Only check this if the alwaysinline attribute is set, it is not free and otherwise not needed. | |
llvm/test/Transforms/Attributor/alwaysinline.ll | ||
22 | I'm confused. Take a look at https://godbolt.org/z/EsQWyN . without the linkonce we determine readnone in either case. |
Created a helper function in Attributor which determines whether the function is IPO amendable and replaced hasExactDefinition with this helper function.
I think this is all good, two minor comments below. Once fixed I commit it
llvm/include/llvm/Transforms/IPO/Attributor.h | ||
---|---|---|
641 | make it const function, and appropriate below. | |
804 | Nit: return InfoCache.InlineableFunctions.count(&F) (no braces) |
make it const function, and appropriate below.