Search code examples
attributesalignmentclangllvmmemory-alignment

Adding a new attribute on source code that propagates until MC level in LLVM?


I am interested in how the following is propagated:

void foo(int __attribute__((aligned(16)))* p) { ... }

In this case the “alignedness” of the pointer is available at the MC level, but it is evidently not using the LLVM-IR metadata approach to achieve this. The alignment information is very important to some targets which will change code-generation dependent on this value, and I think that what I need is more like this attribute.

How difficult would it be to add a new attribute such that it propagates through the compiler in the same way as ‘aligned’? So, I already added a new element to the LLVM-IR to do this. I also expect that the hardest part would be making other parts of LLVM ignore this new element when they don’t care about it.

It really is a pity that LLVM does not have a generic target independent way of passing target dependent information from parser to back-end.

Using the ‘DebugLoc’ approach was suggested in a similar question, but I think it’s a bit-of-a-hack since this is not related to debugging. But if the implementation is less difficult this way, then the hack might be acceptable.

UPDATE: Would inline assembly instead of the use of a new attribute work here? If yes, what are the pros/cons?


Solution

  • As you have demonstrated, alignment is not using metadata.

    • To anyone who doesn't know: alignment is mentioned (implicitly or explicitly) in all relevant instructions, so for example that function in the question will be compiled to something like this (notice the aligns):

      define void @foo(i32*) {
        %2 = alloca i32*, align 16        ; Allocate a 16-aligned pointer
        store i32* %0, i32** %2, align 16 ; An aligned store to place the arg there
        ...
      

    Now, if you want to attach some information to existing instructions and have most of the rest of the compiler ignore them, using metadata is a good idea. However, since metadata is a compiler-internal abstract thing, at some point you'll have to actually do something with it. Typically, by adding a pass of your own to consume it and do something accordingly.

    As for where to place your pass and how to implement it, it really depends on the actual information you're trying to pass and its intended effect.