[cfe-dev] [RFC] Encoding Compile Flags into the IR

Rafael Espíndola rafael.espindola at gmail.com
Sun Apr 29 17:39:56 PDT 2012

On 29 April 2012 18:44, Bill Wendling <wendling at apple.com> wrote:
> Hi,
> Link-Time Optimization has a problem. We need to preserve some of the flags with which the modules were compiled so that the semantics of the resulting program are correct. For example, a module compiled with `-msoft-float' should use library calls for floating point. And that's only the tip of the proverbial iceberg.
> Goals
> =====
> My goals for whichever solution we come up with are to be:
> 1) Flexible enough to differentiate between flags which affect a module as a whole and those which affect individual functions.
> 2) Quick to query for specific flags.
> 3) Easily extensible, preferably without changing the IR for each new flag.
> Proposed Solution
> =================
> My solution to this is to use a mixture of module-level flags and named metadata. It gives us the flexibility asked for in (1), they are relatively quick to query (after being read in, the module flags could be placed into an efficient data structure), and can be extended by updating the LangRef.html doc.
> - Module-level flags would be used for those options which affect the whole module and which prevent two modules that do not have that flag set from being merged together. For example, `-msoft-float' changes the calling convention in the output file. Therefore, it's only useful if the whole program is compiled with it. It would be a module-level IR flag:
>        !0 = metadata !{ i32 1, metadata !"-msoft-float", i1 true }
>        !llvm.module.flags = !{ !0 }

So the objective in here is to diagnose cases where the program would
already be broken even without LTO, correct? If so I think this going
on the right direction, I am just not sure if a 1:1 mapping with
command line options is the best solution. These are basic "abi

> - Named metadata would be used for those options which affect code generation for the functions, but which doesn't prevent two modules from being merged together. For example, `-fomit-frame-pointer' applies to individual functions, but it doesn't prevent a module compiled with `-fno-omit-frame-pointer' from being merged with one compiled with `-fomit-frame-pointer'. We would use a named metadata flag:
>        define void @foo () { ... }
>        define double @bar(i32 %a) { ... }
>        ; A list of the functions affected by `-fno-omit-frame-pointer' within the Module.
>        !0 = metadata !{ void ()* @foo, double (i32)* @bar }
>        !fno.omit.frame.pointer = !{ !0 }
> And so on.

This part I am not so sure about. I fixed a similar problem for unwind
tables by adding an attribute. It could be safely done with a metadata
with the oposite meaning (nouwtable). The things I am uncomfortable
with this part of the proposal are:

* Why not use metadata attached directly to the functions? They are
the closest thing to an easy to add attribute.

* The recent discussion about metadata points out that it is not
really safe to add information that only part of the compiler reasons
about. Metadata adds the nice property that it is safe to drop, but
that is it. Passes have to know about it, it should be documented in
the language ref and the verifier should check it. I am afraid that
this part of the proposal would again create a feeling that we have a
magic bullet for passing semantic info from the FE to some passes.

* As you mention, this is probably the tip of the iceberg. Maybe we
should explore it a bit more with the tools we have before declaring
them insufficient. Duncan is working on fp precision, you can probably
add a no_frame_pointer metadata to functions and from there we will
have a better idea of how things are going.


More information about the cfe-dev mailing list