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

Bill Wendling wendling at apple.com
Sun Apr 29 15:44:39 PDT 2012


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.


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 }

- 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.

The second part of the solution (using named metadata) could be replaced by function attributes. However, I see a couple of problems with that. First, the number of flags could be quite large. We would soon run out of space in the Attributes structure, not to mention that printing the function becomes unwieldy.. Second, it's not very extensible. Adding a new flag requires changing the IR. While it's relatively easy to change the IR in this case, it is less desirable to me than simply adding a note in LangRef.html about the flag and its semantics.

Code Generation

The part of the compiler most effected by this change will be the back-end. (The front-end already has mechanisms in place to handling merging metadata.) Several different flags are currently specified as function-level attributes, which is fine, and those need not change. But other flags, which are specified in an ad hoc manner, will need to change to be queried for by the back-end. This is good as it will consolidate these flags into one interface, but it will take some work to complete.


LTO definitely needs this, or an equivalent, solution to the current problem. Without it, we cannot claim that LTO is "ready for prime-time."

No part of this proposal is set in stone, and I'm open to modifications and other ideas. (Dons asbestos suit.) ;-)

Share and enjoy!

More information about the cfe-dev mailing list