[LLVMdev] [RFC] Passing Options to Different Parts of the Compiler Using Attributes

Meador Inge meadori at codesourcery.com
Tue Nov 20 11:03:44 PST 2012


On Nov 13, 2012, at 12:20 AM, Bill Wendling wrote:

> IR Changes
> ----------
> 
> The attributes will be specified within the IR. This allows us to generate code
> that the user wants. This also has the advantage that it will no longer be
> necessary to specify all of the command line options when compiling the bit code
> (via 'llc' or 'clang'). E.g., '-mcpu=cortex-a8' will be an attribute and won't
> be required on llc's command line. However, explicit flags (like `-mcpu') on the
> llc command line will override flags specified in the module.
> 
> The core of this proposal is the idea of an "attribute group". As the name
> implies, it's a group of attributes that are then referenced by objects within
> the IR. An attribute group is a module-level object. The BNF of the syntax is:
> 
> attribute_group := attrgroup <attrgroup_id> = { <attribute_list> }
> attrgroup_id    := #<number>
> attribute_list  := <attribute> (, <attribute>)*
> attribute       := <name> (= <value>)?
> 
> To use an attribute group, an object references the attribute group's ID:
> 
> attribute_group_ref := attrgroup(<attrgroup_id>)
> 
> This is an example of an attribute group for a function that should always be
> inlined, has stack alignment of 4, and doesn't unwind:
> 
> attrgroup #1 = { alwaysinline, nounwind, alignstack=4 }
> 
> void @foo() attrgroup(#1) { ret void }
> 
> An object may refer to more than one attribute group. In that situation, the
> attributes are merged.
> 
> Attribute groups are important for keeping `.ll' files readable, because a lot
> of functions will use the same attributes. In the degenerative case of a `.ll'
> file that corresponds to a single `.c' file, the single `attrgroup' will capture
> the command line flags used to build that file.

A few comments on the new syntax:

   1. I think most folks will understand what 'attrgroup' means, but it is a little cryptic. 
      How about just 'attributes'?  The following reads easier to my eyes:

         attributes #1 = { alwaysinline, nounwind, alignstack=4 }
         void @foo() attributes(#1) { ret void }

   2. Are group references allowed in all attribute contexts (parameter, return value, function)?
      I think the answer should be yes.  Also, it might be worth considering using the same attribute
      list syntax in the current context and the new attribute group definition (i.e. comma-separated
      v.s. space-separated).  This way we have a consistent syntax for groups of attributes and the
      main addition this proposal adds is to give a name to those attributes for later reference.
      
   3. Can attribute groups and single attributes be inter-mixed?
      For example:
     
         void @foo attrgroup(#1) alwaysinline attrgroup(#2) nounwind

   4. Do we really want the attribute references limited to a number?  Code will be more readable
      if you can use actual names that indicate the intent.  For example:

         attrgroup #compile_options = { … }
         void @foo attrgroup(#compile_options)

   5. Can attributes be nested?  For example:

         attrgroup #1 = { foo, bar }
         attrgroup #2 = { #1, baz }

      Might be nice.

   6. Do we really need to specify the attrgroup keyword twice? (Once in the group definition and once in the use)
      ISTM, that the hash-mark is enough to announce a group reference in the use.  For example:

         void @foo #1 alwaysinline #2 no unwind

In other words, I think something like the following might be nicer:

attribute_group := attributes <attrgroup_id> = { <attribute_list> }
attrgroup_id    := #<id>
attribute_list  := <attribute> ( <attribute>)*
attribute       := <name> (= <value>)?
                 | <attribuge_id>

…

function_def    := <attribute_list> <result_type> @<id> ([argument_list]) <attribute_list>


> Target-Dependent Attributes in IR
> ---------------------------------
> 
> The front-end is responsible for knowing which target-dependent options are 
> interesting to the target. Target-dependent attributes are specified as strings,
> which are understood by the target's back-end. E.g.:
> 
> attrgroup #0 = { "long-calls", "cpu=cortex-a8", "thumb" }
> 
> define void @func() attrgroup(#0) { ret void }
> 
> The ARM back-end is the only target that knows about these options and what to
> do with them.
> 
> Some of the `cl::opt' options in the backend could move into attribute groups.
> This will clean up the compiler.
> 

Isn't calling these "target-dependent" a little artificial?  Surely there are many uses
for string attributes one of which is for target-specific data.  I think organizing the
proposal to add these new arbitrary string attributes and using the target-specific bits
as examples will be clearer.

> Updating IR
> -----------
> 
> The current attributes that are specified on functions will be moved into an
> attribute group. The LLVM assembly reader will still honor those but when the
> assembly file is emitted, those attributes will be output as an attribute group
> by the assembly writer. As usual, LLVM 3.3 will be able to read and auto-upgrade
> previous bitcode and `.ll' files.
> 
> Querying
> --------
> 
> The attributes are attached to the function. It's therefore trivial to access
> the attributes within the middle- and the back-ends. Here's an example of how
> attributes are queried:
> 
> Attributes &A = F.getAttributes();
> 
> // Target-independent attribute query.
> A.hasAttribute(Attributes::NoInline);
> 
> // Target-dependent attribute query.
> A.hasAttribute("no-sse");
> 
> // Retrieving value of a target-independent attribute.
> int Alignment = A.getIntValue(Attributes::Alignment);
> 
> // Retrieving value of a target-dependent attribute.
> StringRef CPU = A.getStringValue("cpu");

Maybe some set attribute examples too?


Overall, I think this is a nice addition!

--
Meador Inge
CodeSourcery / Mentor Embedded
http://www.mentor.com/embedded-software





More information about the llvm-dev mailing list