As part of the optimization work to emit dead-strippable symbols for Swift and enable GlobalDCE to remove those symbols when possible, we need to mark some Swift symbols as conditionally used based on a set of other symbols. Some background info can be found here: https://bugs.swift.org/browse/SR-14509.
We are proposing to add a module-level name metadata llvm.used.conditional. It contains a list of metadata triplets. Each triplet has the following form:
- The first element is the global variable from llvm.used that we are conditionally mark it as used.
- The second element is a boolean flag. 1 means when all GVs in the third element are alive, mark the first element as used. 0 means when any GV in the third element is alive, mark the first element as used.
- The third element is a list of GVs.
One example use case is for Swift protocol conformance data, we want to mark them as conditionally used, depending on the protocol descriptor and the nominal type descriptor. During GlobalDCE, we separate out the entries that are in llvm.used and also in llvm.used.conditional as the first element. We iteratively mark entries in this set as used by checking the GVs in the third element according to the flag in the second element. When one entry is marked as used, it can trigger other entries to be alive.
We are open to other alternatives to express this conditional usage.
The patch is based on initial patch from Kuba + some clean up. Testing cases will be added if this is the right approach to move forward.
nit: @llvm.used?
Does the global have to be in @llvm.used or could this requirement be dropped?