Replacing module metadata uses of function

Hi all,

I’m working on an LLVM transformation that rewrites functions, adding an argument, and I’m struggling with how to update uses of the original function in named module metadata (like NVPTX’s nvvm.annotations). It seems like the only way to update uses of the function in there is to RAUW the old function, but that’s invalid as the type of the value changes (resulting in a failed assertion). Other uses of the function I’ve already rewritten ‘properly’ using CloneFunctionInto, but even with a value-mapper and module-level changes enabled that doesn’t touch the module metadata.

Is there an utility that I’m missing, or do I need to recreate module metadata myself? The fact that RAUW actually does contain this functionality (replacing module metadata uses of values), but doesn’t let me due to the aforementioned assertion, seems to imply that I shouldn’t hand-roll this.

You probably want to RAUW the old function with a bitcast of the new function to the old function type. Though I don’t know whether that would render the NVPTX metadata invalid – it’s also possible that you need to bail out from your transform if there are any uses that you cannot explicitly handle (this sounds plausible for a transform adding an argument).

Thanks for the suggestion. Although I could work with a (presumably ConstExpr?) bitcast for my use case, I don’t think it’ll be valid for the NVPTX metadata and others… Furthermore, it seems like GlobalDCE gets rid of that value?

source_filename = "SomeModule"

define i32 @dummy() {
entry:
  ret i32 42
}

!direct_use = !{!0}
!constexpr_use = !{!1}

!0 = !{i32 ()* @dummy}
!1 = !{void ()* bitcast (i32 ()* @dummy to void ()*)}
$ opt --globaldce wip.ll -S -o -
source_filename = "SomeModule"

define i32 @dummy() {
entry:
  ret i32 42
}

!direct_use = !{!0}
!constexpr_use = !{!1}

!0 = !{i32 ()* @dummy}
!1 = !{void ()* undef}

For doing a RAUW with the original values (i.e. without a bitcast), I discovered I can just do ValueAsMetadata::doRAUW, but there’s a similar assertion there

I had the same problem a while ago. IMO replacing values with different types should be allowed for metadata.

Anyway, I worked around it by doing an RAUW with a constantexpr bitcast and then walking through the metadata, using MDTuple->replaceOperandWith(I, ConstantAsMetadata::get(StrippedBitcastsMD)); to strip the bitcasts.

The AlwaysInliner is also converting bitcasts in metadata to undef (even if not inlining or removing any function!) because it assumes the function reference is dead.

1 Like

Thanks, that’s a good workaround. I’ve created a PR, ⚙ D125388 Allow type-mismatching RAUW of values in metadata, and add C API., to relax the assertion, and in the meantime I’ll be using your workaround :slight_smile: