This is an archive of the discontinued LLVM Phabricator instance.

[IRBuilder] Generalize debug loc handling for arbitrary metadata.
ClosedPublic

Authored by fhahn on Dec 16 2020, 7:55 AM.

Details

Summary

This patch extends IRBuilder to allow adding/preserving arbitrary
metadata on created instructions.

Instead of using references to specific metadata nodes (like DebugLoc),
IRbuilder now keeps a vector of (metadata kind, MDNode *) pairs, which
are added to each created instruction.

The patch itself is a NFC and only moves the existing debug location
handling over to the new system. In a follow-up patch it will be used to
preserve !annotation metadata besides !dbg.

The current approach requires iterating over MetadataToCopy to avoid
adding duplicates, but given that the number of metadata kinds to
copy/preserve is going to be very small initially (0, 1 (for !dbg) or 2
(!dbg and !annotation)) that should not matter.

Diff Detail

Unit TestsFailed

Event Timeline

fhahn created this revision.Dec 16 2020, 7:55 AM
fhahn requested review of this revision.Dec 16 2020, 7:55 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 16 2020, 7:55 AM
lebedev.ri requested changes to this revision.EditedDec 16 2020, 11:17 AM
This comment has been deleted.
llvm/include/llvm/IR/IRBuilder.h
212–219

Don't you have an invalidation issue here?
What happens if we first call CollectMetadataToCopy() on an instruction that had metadata zz,
and then call it again on an instruction that didn't have that metadata? (the instcombine's pattern)

This revision now requires changes to proceed.Dec 16 2020, 11:17 AM
fhahn updated this revision to Diff 312416.Dec 17 2020, 2:24 AM

Update CollectMetadataToCopy to drop metadata kinds that are in MetadataToCopy but not on the source instruction. Also replace LLVMSetInstDebugLocation with LLVMAddInstMetadata.

lebedev.ri added inline comments.Dec 17 2020, 2:34 AM
llvm/include/llvm/IR/IRBuilder.h
212–219

Actually, my suggestion is still incorrect, because it still doesn't drop metadata
You want something like

void CollectMetadataToCopy(Instruction *Src,
                           ArrayRef<unsigned> MetadataKinds) {
  // First, refresh (either update or delete) all the existing metadata
  for (unsigned K : make_first_range(MetadataToCopy))
    AddOrRemoveMetadataToCopy(K, Src->getMetadata(K));
  // Then, add new metadata (either add or update)
  for (unsigned K : MetadataKinds)
    AddOrRemoveMetadataToCopy(K, Src->getMetadata(K));
}
fhahn added inline comments.Dec 17 2020, 2:36 AM
llvm/include/llvm/IR/IRBuilder.h
212–219

Yeah, originally I thought of collecting metadata to strictly increase the metadata to copy. But this is not in line with current practices for DebugLoc, where setting an empty DebugLoc removes the DebugLoc. I think in light of that, it makes sense for CollectMetadataToCopy to also remove entries from MetadataTocopy, if they are not present on Src. Also updated the comment

fhahn added inline comments.Dec 17 2020, 2:45 AM
llvm/include/llvm/IR/IRBuilder.h
212–219

Actually, my suggestion is still incorrect, because it still doesn't drop metadata

Yeah it only drops metadata that's in MetadataKinds, but not on the instruction. Entries that are in MetadataToCopy but not in MetadataKinds are left untouched. From the comment for the function, I would not expect to update the values for any entry in MetadataToCopy but not in MetadataKinds. I guess there are cases where either behavior could be useful.

I am not sure, but I think it might be simpler to just have CollectMetadataToCopy by purely additive (only add or update entries, but do not drop any) and provide a general way to remove entries, once there's a need. Currently this is only needed for debug locations via SetCurrentDebugLocation.

lebedev.ri accepted this revision.Dec 17 2020, 3:13 AM

Ah no, i guess i'm reading this wrong. LG.
I'm not sure about C API changes, they are likely ABI/API breaking and may require more changs, you might want for whoever maintains that to comment.

llvm/include/llvm/IR/IRBuilder.h
231

This should probably be AddMetadataToInst()/SetInstMetadata()/???,
because i have already misread what this does.

This revision is now accepted and ready to land.Dec 17 2020, 3:13 AM
fhahn updated this revision to Diff 312430.Dec 17 2020, 3:39 AM

Undo C API breaking changes, will submit them separately. Also changed the name to AddMetadataToInst.

llvm/include/llvm/IR/IRBuilder.h
231

Thanks, that name is much better! Changed.

This revision was landed with ongoing or failed builds.Dec 17 2020, 5:28 AM
This revision was automatically updated to reflect the committed changes.
fhahn added a comment.Dec 17 2020, 5:41 AM

LLVM-C API changes are in D93454

nikic added a subscriber: nikic.Dec 17 2020, 12:26 PM

FYI this has a noticeable compile-time impact: http://llvm-compile-time-tracker.com/compare.php?from=deae7e982a3b08996455e2cdfdc5062bf37895a3&to=01089c876bff43a7cde1cb9b1ef8c128169ec5b4&stat=instructions (including the change that adjusts InstCombine)

Something to keep in mind is that debug metadata is privileged, and a reference to it is stored in the instruction. Fetching the annotation metadata (even if it does not exist, but *some* kind of metadata exists) requires looking up the instruction in the metadata map and scanning the metadata vector.

fhahn added a comment.Dec 17 2020, 3:06 PM

FYI this has a noticeable compile-time impact: http://llvm-compile-time-tracker.com/compare.php?from=deae7e982a3b08996455e2cdfdc5062bf37895a3&to=01089c876bff43a7cde1cb9b1ef8c128169ec5b4&stat=instructions (including the change that adjusts InstCombine)

Something to keep in mind is that debug metadata is privileged, and a reference to it is stored in the instruction. Fetching the annotation metadata (even if it does not exist, but *some* kind of metadata exists) requires looking up the instruction in the metadata map and scanning the metadata vector.

Thanks for the heads up. This is definitely something that needs to be addressed. I'll try a few things tomorrow. Surprising to see there's actually a speedup with the ReleaseLTO + g