Invoke instruction can have both branch_weights and indirect-call VP count.
We currently only have indirect-call VP count for it.
This patch enables branch_weight metadata for invoke instruction.
Details
Diff Detail
Event Timeline
llvm/include/llvm/IR/Instructions.h | ||
---|---|---|
3969 | nit: metadat -> metadata | |
3973 | I'm wondering if this function can be made more generic and not restrict to invoke instruction only. I feel it's likely in the future that more types of metadata will be allowed for an instruction. How about returning a something like a hash map with the keys being the type of metadata? | |
4011 | nit: the return nullptr isn't necessary as BranchWeightMD will be set to null if the branch metadata isn't there? Similarly below. | |
llvm/lib/IR/Metadata.cpp | ||
1512 | This seems to change existing behavior for invokes from legacy IR that have only VP metadata. |
Why is invoke unique here? Can regular call never have both VP and branch weights? Ideally we'd avoid special case for a narrow type of instruction.
llvm/include/llvm/IR/Instructions.h | ||
---|---|---|
3973 | As of now, the branch weight metadata is only attached to terminator instructions in FDO. | |
4011 | that's correct. Fixed. |
In FDO, branch weights only attached to terminal instruction (and call instruction is not, while invoke is). Indirect-call VP only attached to indirect-call or invoke instruction.
In SampleFDO, we also attach a branch weight to direct-call. But again indirect-call only only for indirect-call and invoke.
So only invoke instruction can have both profile metadata.
llvm/lib/IR/Metadata.cpp | ||
---|---|---|
1512 | Sorry that I missed this comment. Yes. you are right on this. Currently we return the VP counts as the total count. I will check both VP and branch_weights. |
Thanks for the change. Wondering if you saw performance improvement with it.
The corresponding change on the sample profile side isn't included, do you have any plan for it?
llvm/lib/ProfileData/InstrProf.cpp | ||
---|---|---|
1077 | Can we use get instead of getDistinct so that invokes with same metadata can potentially share the same node? | |
llvm/lib/Transforms/Utils/Local.cpp | ||
2168 | Should the check be if (ProfileData)? If the original invoke doesn't have !VP, the new call should end up with no metadata based on the existing behavior. |
llvm/lib/ProfileData/InstrProf.cpp | ||
---|---|---|
1077 | Yes. get() seems to be better suited here. | |
llvm/lib/Transforms/Utils/Local.cpp | ||
2168 | If the original invoke does not have VP, it can still have branch_weights. Maybe my words in patch description is confusing: this patch tries to fix the case where invoke calls to a indirect function. For this transformation, mostly like the invoke is a direct function, in which case, we will annotate a total counts -- FDO will not use If here the newcall is an indirect function, we have have two annotations in invoke and can only have one in the new call. I choose to keep the indirect metadata. This changes the semantic but I think it's the right thing to do. |
Yes. For AutoFDO, we still need some change for the invoke in sampleloader
The situation is slightly different in AutoFDO. In FDO, we do branch_weight annotation first, then do the VP.
In AutoFDO, we do VP annotation first and then branch_weight annotation. We need to set the branch_weight metadata where there is already a VP metadata (which is the reverse of FDO).
I was planning to have a separated patch for AutoFDO, but I can also include it in this patch.
A separate patch sounds good, thanks.
llvm/lib/Transforms/Utils/Local.cpp | ||
---|---|---|
2168 | I see, thanks for the explanation. |
AutoFDO is less problematic as branch_weights metadata overwrites VP in the end. (and many VP metadata is already consumed by the prompting in preinliner).
In FDO, VP metadata overwrites branch_weights -- This is bad as we lost more information in BPI/BFI.
(branch_weights is more important for downstream opt).
It looks like same happens to autofdo, i.e, no branch_weights assigned to indirect invokes? https://github.com/llvm/llvm-project/blob/7b81a81d5f9cccb1b091cfc5264bc483b0acc83a/llvm/lib/Transforms/IPO/SampleProfile.cpp#L1628
Oh, I guess branch_weight is attached to invokes that are promoted from an indirect invoke, so it is better handled than the FDO case.
llvm/lib/ProfileData/InstrProf.cpp | ||
---|---|---|
1077 | LGTM after this is fixed. |
llvm/include/llvm/IR/Instructions.h | ||
---|---|---|
3973 | A slight preference for this to be generic. The problem you're dealing with is the unordered nature of MD. Previously it works because there's the assumption that only one profile MD exists, which is not true for invoke. It's cleaner and more robust if you simply make all APIs not depending on MD order. You don't need a hashmap, but how about just always search through MD when looking for branch_weights or VP. Specifically, that's changing the general implementation of extractBranchWeights and extractProfTotalWeight to be order independent regardless of the opcode. |
llvm/include/llvm/IR/Instructions.h | ||
---|---|---|
3973 | OK. This makes sense. I'll update the patch with this suggestion. |
the branch weight for invoke is set in line 1724 (https://github.com/llvm/llvm-project/blob/7b81a81d5f9cccb1b091cfc5264bc483b0acc83a/llvm/lib/Transforms/IPO/SampleProfile.cpp#L1724)
line 1628 sets the call's branch-weight (which is a single number, call counts) -- this should be overwritten by line 1724.
Line 1724 is guarded by !TI->extractProfTotalWeight(TempWeight) which is non-zero for invokes with !VP?
Yes. This is the place that need to be changed.
Here TI is the invoke. It can have either call-count branch weight metadata (set in 1628), or VP metadata set in line 878.
We need to set the right branch_weight here -- if there is a VP metadada, we create a compound one. If this is single callcount weight, we replace it with real branch_weight.
Ohhh no!
I just want to do suggested edit for a comment (around IndirectCallPromotion.cpp line 316) but obviously this is not the correct way to do it.. I suppose there is a way you could get it back?
Looks like you could commandeer it back (https://stackoverflow.com/questions/28296729/how-to-undo-commandeer-revision-in-phabricator) My apologies about it :(
nit: metadat -> metadata