If a ScopStmt references a (scalar) value, there are multiple possibilities where this value can come. The decision about what kind of use it is must be handled consistently at different places, which can be error-prone. VirtualUse is meant to centralize the handling of the different types of value uses.
This patch makes ScopBuilder and CodeGeneration use VirtualUse. This already helps to show inconsistencies with the value handling. In order to keep this patch NFC, exceptions to the general rules are added. These might be fixed later if they turn to problems. Overall, this should result in fewer post-codegen IR-verification errors, but instead assertion failures in getNewValue that are closer to the actual error.
The "virtual" in VirtualUse/VirtualInstructions.h might be a misnomer as it currently has little to do with virtualizing instructions. I am open for other naming suggestions. The Virtual argument of VirtualUse::create is used to check the consistency of created MemoryAccesses, by the verifyUses function. The original intent to have Virtual in the name was that SCoP postprocessing-passes modify the accesses such that instructions are moved between ScopStmts. In order this to work, the BB an instruction resides in is less important.
For improving compile-time, caching the result of VirtualUse::create could be a possibility.
I started with using VirtualUse only for assertions. This unfortunately proved to be difficult as getNewValue as multiple returns and complete coverage.
Even if this is not committed, the study of inconsistencies of getNewValue could be useful.