This is an archive of the discontinued LLVM Phabricator instance.

[llvm][MemoryBuiltins] Add alloca support to getInitialValueOfAllocation
Needs ReviewPublic

Authored by jmciver on Jul 19 2023, 7:51 PM.

Details

Summary

This commit is in support of future uninitialized memory handling and adds
alloca instruction support to getInitialValueOfAllocation. This unifies initial
memory state querying (both stack and heap) to a single utility function.

Mem2Reg, GVN, and NewGVN optimizations are refactored to take advantage of
alloca support in getInitialValueOfAllocation.

To support uninitialized memory as poison we are proposing that in the future
load instructions support an attribute !freeze (or alternative) which will allow
freeze poison insertions where applicable. Thus the constant emitted by
getInitialValueOfAllocation will be dependent on the allocation
function/instruction and the load instruction attributes.

Diff Detail

Event Timeline

jmciver created this revision.Jul 19 2023, 7:51 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 19 2023, 7:51 PM
jmciver published this revision for review.Jul 19 2023, 10:15 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJul 19 2023, 10:15 PM
nikic requested changes to this revision.EditedJul 20 2023, 1:02 AM

This commit is in support of future uninitialized memory handling and adds
alloca instruction support to getInitialValueOfAllocation. This unifies initial
memory state querying (both stack and heap) to a single utility function.

Could you explain in more detail what future work you have based on this? Is this about the promotion of malloc (and similar) memory?

In any case, I don't think it's acceptable to add TLI as a required dependency for mem2reg. Alloca promotion doesn't need it, and that's what all the existing code is doing. This should at least be an optional dependency.

However, I think it would be better to directly pass the initial value to mem2reg instead (defaulting to UndefValue), rather than making it query it.

This revision now requires changes to proceed.Jul 20 2023, 1:02 AM

@nikic as per my GSoC project I am trying, under the guidance of @nlopes, a load attribute based approach to migrating uninitialized load to poison. The first attribute that I am working on is !freeze which effectively inserts a freeze poison if the load is uninitialized. Obviously this can only be done in
optimizations that allow instruction creation. In the future I am looking to add a load instruction parameter to getInitialValueOfAllocation to allow modification of the returned constant based on the allocation function/instruction and the presence of a load attribute.

So why pack the alloca test into getInitialValueOfAllocation? The reasoning is that attribute is on a per-load instruction, but allocation could be alloca or function. I agree if the application of the load attribute were universal passing in the default value to mem2reg would work, but as we are modulating the returned constant based on individual load instruction attributes this would not work. Hence the query based approach.

As for the TLI I agree that making it required is probably not ideal. @nlopes can vouch that I thought about this :-). Two options off the top of my head are:

  1. Make the TLI parameter of getInitialValueOfAllocation a pointer with defaults to nullptr.
  1. Add a separated query function for alloca instructions.

The advantage to option 1 is all allocation initial state queries are handled in one place. The detractor is we have a parameter that has a default nullptr.

The advantage to option 2 is allocation functions vs alloca instruction are handled by functions that have only the required parameterizations exposed. The detractor is there will be some combinatorial overlap between the two functions.

Thoughts?

jmciver updated this revision to Diff 542618.EditedJul 20 2023, 11:45 AM

Remove reliance on TLI objects where only alloca instructions are processed.

jmciver edited the summary of this revision. (Show Details)Jul 20 2023, 12:01 PM
jmciver updated this revision to Diff 545294.Jul 28 2023, 3:25 PM
jmciver edited the summary of this revision. (Show Details)

Refactor AMDGPUPromoteAlloca to use getInitialValueOfAllocation.

arsenm added inline comments.Aug 11 2023, 9:54 AM
llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
809–811

This is very specifically handling alloca, not any random allocation like function

jmciver added inline comments.Aug 11 2023, 11:03 AM
llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
809–811

@arsenm thanks for the feedback. I added functionality to getInitalValueOfAllocation to handle alloca instructions specifically. This is being done as preliminary to some possible refactorizations allowing uninitialized memory to move to poison semantics. The behavior for these changes would be the same for alloca and allocation like functions.

nikic added a comment.Aug 14 2023, 3:24 AM

@jmciver Thanks for the context. I would recommend you to put up the patch you have based on top of this, because it's pretty hard to tell whether this API design makes sense without seeing the use. I have some doubts about that, for two reasons:

  • If I understand correctly, for your use case getInitialValueOfAllocation() can't just return a constant anymore, it may have to insert an instruction. Additionally, there is no longer a single "initial value", but it may wary between different loads from the same allocation. This means that the API is going to change to the point that getInitialValueOfAllocation() is no longer recognizable (and probably no longer correctly named -- it would be more materializeInitialValueOfAllocation()).
  • As some of the changes in this patch show, we also have to give lifetime.start intrinsics similar treatment to allocas, but this doesn't quite fit the current API.

I think supporting allocas in getInitialValueOfAllocation() is perfectly fine, but I'm not sure this really brings you closer to what you want to do.

@nikic Thanks for responding. I will get a "work in progress" patch up in the next three days.

In the API adaptation, instruction insertion is still being handled in the caller as some passes are only allowed removal and not insertion.

@nikic I added this patch to a work in progress (WIP) "stack" of patches. D158352 and D158353 show what the intended progression looks like for mem2reg. I will add WIP SROA changes in the next few days.