In the LLVM test suite and SPEC2006, ~67% of all function declarations
are non-exact, thus they can be replaced at link-time. While we cannot
generally use them to perform inter-procedural (IP) reasoning, it is
allowed to "internalize" them first and derive IP information
afterwards. In fact, we can use the information we derived assuming they
have exact definitions to reason if internalization might be beneficial.
This patch allows the Attributor to employ shallow wrappers, the
cheapest internalization method I could think of. A shallow wrapper is a
function with the same type (and attributes) as the original one. Inside
the wrapper there is only call to the original one and a return of the
result. The scheme is shown below:
Assuming the declaration of looks like:
rty F(aty0 arg0, ..., atyN argN);
The wrapper will then look as follows:
rty wrapper(aty0 arg0, ..., atyN argN) { return F(arg0, ..., argN); }
Once the wrapper was created we can change the linkage type of the
original function to internal which allows us to use it for recursive
reasoning. We can also manifest the results, e.g., annotate the
arguments with attributes.
Shallow wrappers are cheap because the new internal function has a
single call site. This likely means we inline them later which results
in "similar" code as we started out with except that passes in-between
the Attributor and the inliner can use the annotated information.
A separate patch will introduce deep wrappers that replace the known
uses of the function with the internalized version. Afterwards, we need
to work on a cost heuristic. I will also see if we can disable inlining
for "wrapper-like" functions and post my findings on the list.
FYI, I don't think we have a reserved prefix for llvm-produced functions, but you can make it anonymous with F.setName("");. Since the function has internal linkage, it doesn't need a name to link with other modules.