Itay Bookstein via llvm-dev
2021-Nov-12 16:39 UTC
[llvm-dev] [IR] GlobalIFunc with declaration as resolver
Hi all, We've had a lengthy discussion in [1] regarding GlobalIFunc whose resolver is a declaration, and I wanted to get wider feedback for the IR-level semantics. The ELF object file semantics require the resolver to be defined in the same TU as the ifunc [2] and Clang and GCC require the same when using 'plain' attribute((ifunc("..."))), diagnosing that it must be a defined function [3]. The same applies for aliases and their aliasees. The LLVM Verifier requires that aliasees not be declarations [4], but the same currently does not hold for GlobalIFunc (Verifier code for GlobalIFunc was added in [1], defined-check was reverted due to breaking CFE attribute cpu_specific). The implementation of attributes cpu_dispatch and cpu_specific in CFE currently depends on GlobalIFunc with a declaration for a resolver, in the case when cpu_specific is specified in a TU and cpu_dispatch is not. Trunk currently has broken codegen for references against such ifuncs in the same TU [5], but there's reference to a downstream (codegen-level?) patch which could fix it [6]. I don't know what semantics the patch implements, but two options come to mind: * Replace uses of GlobalIFunc with result of call to resolver; this can work only in code, not in gvar initializers, and it nullifies benefit of using an ifunc. * 'downgrade' GlobalIFunc to a function declaration, dropping 'connection' to resolver (valid only when it has odr linkage? didn't think this through). This creates a small representational redundancy (ifunc with undefined resolver ~== func decl). A different approach is to declare GlobalIFunc with undefined resolver to be invalid IR, and thus bring it in line with the very similar construct of GlobalAlias. This would necessitate a change to the implementation of cpu_specific/cpu_dispatch to avoid breaking support for defining them in separate TUs. A problem with that is that it creates an issue similar to [7], where CFE would sometimes need to emit a function declaration and later 'upgrade' it to a GlobalIFunc upon encountering cpu_dispatch. CFE devs wish to avoid introducing additional RAUW module mutations in this way. My understanding is that this is because it harms incremental compilation scenarios, but I don't know the full technical aspects of this. ~ Itay [1] https://reviews.llvm.org/D112349 [2] https://sourceware.org/glibc/wiki/GNU_IFUNC [3] https://github.com/llvm/llvm-project/blob/99d5cbbd7e33b620f5f4725ffa04ce15d2794a14/clang/lib/CodeGen/CodeGenModule.cpp#L345 [4] https://github.com/llvm/llvm-project/blob/99d5cbbd7e33b620f5f4725ffa04ce15d2794a14/llvm/lib/IR/Verifier.cpp#L785 [5] https://reviews.llvm.org/D112349#3109211 [6] https://reviews.llvm.org/D112349#3116519 [7] https://github.com/llvm/llvm-project/blob/05f34ffa216975f132fa1bd4cbf8424053a19147/clang/lib/CodeGen/CodeGenModule.cpp#L4971-L4982 -- This e-mail message and any attachments thereto are intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any retransmission, dissemination, copying or other use of, or taking of any action in reliance upon this information is prohibited. If you are not the intended addressee, please contact the sender immediately and delete the materials and information from your device and system and confirm the deletion by reply e-mail.