[ScalarizeMaskedMemIntrin] Preserve metadata during scalarization (#218753)
I based `copyMetadataForScalarizedLoad` on the `copyMetadataForLoad`
helper in Local.cpp. These both preserve:
- `!tbaa`
- `!fpmath`
- `!invariant.load`
- `!alias.scope`
- `!noalias`
- `!nontemporal`
- `!mem.cache_hint`
- `!llvm.mem.parallel_loop_access`
- `!llvm.access.group`
- `!noalias.addrspace`
- `!range` - range metadata applies elementwise, so the range guarantee
works for each scalarized load/store.
`copyMetadataForLoad` additionally preserves:
- `!nonnull`, `!align`, `!dereferenceable`, `!dereferenceable_or_null`,
`!noundef`, `!nofpclass`, and `!invariant.group`, which are not valid on
intrinsics
- `!prof`, which I don't think we can propagate. `copyMetadataForLoad`
is documented to only be used when we change a load instruction's type.
This profiling doesn't look valid to propagate for more complex
transformations.
- `!tbaa.struct`, which I don't think we can propagate because this is
specifying an offset into a struct we access and our transformations are
too complex.
- `!dbg`, which I don't think we need to propagate because we call
`Builder.SetCurrentDebugLocation(CI->getDebugLoc());`
`copyMetadataForScalarizedLoad` additionally preserves:
- `!annotation`, I don't know why `copyMetadataForLoad` doesn't preserve
this. I think this is meant to be preserved through transformations,
maybe a bug.
- `!nosanitize`
- `!mmra`
`copyMemCacheHint` was necessary because for the histogram add intrinsic
unfortunately the pointer we store to is operand 0, when it should
really be operand 1 for consistency.
We only preserve `!DIAssignID` when we do a 1-1 transformation. I think
otherwise you'd need to do some smarter splitting of `dbg_assign`
records like SROA does in `migrateDebugInfo`, but I'm not so familiar
with debug so I don't want to implement this.
Disclaimer: I'm not familiar with all of these metadatas so I might've
gotten something wrong.
Assisted by AI.