Hi all, So, after long rounds to define how the build attributes are going to be represented in IR, and after Jason has implemented build attributes in MC, I have a proposal on how to represent this in IR. First, we need to distinguish between target dependent and independent attributes. Generic things like optimization level, specific optimizations, use of vector instructions, use of exceptions, floating-point compatibility can all go in to the generic list of attributes. Local attributes like use ARM or Thumb, interoperability, extensions, CPU name and architecture go into a target-specific section. Following the current rule in IR for specific attributes that are not directly represented, and Chris' suggestion, I propose to use global variables to represent them. Representation: The type has an identifier (Enum somewhere in LLVM) and a description or value: %llvm.attribute = type { i32, i8* } The generic attribute list can have, for instance, the optimization level used: // suppose 1 is the key to "optimization level" @llvm.attributes = appending global [2 x %llvm.attribute] [%llvm.attribute { i32 1, i8* getelementptr inbounds ([3 x i8]* @.str, i32 0, i32 0) }, %llvm.attribute zeroinitializer], align 4 @.str = private constant [3 x i8] c"O3\00" And the target-specific has something like the CPU name and whether it's using R9 as SB: // 5 is CPU_name in ARM ABI, 14 is ABI_PCS_R9_use @llvm.arm.attributes = appending global [2 x %llvm.attribute] [%llvm.attribute { i32 5, i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0) }, %llvm.attribute { i32 14, i8* null }], align 4 @.str1 = private constant [10 x i8] c"ARM946E-S\00" Documentation: It'd be good to have a list of all options, generic or otherwise. The attributes enum could have a few lines explaining the options, but the accepted values is more difficult to find in the code, so a documentation (not LangRef) would be good, especially for the generic part. The ARM options are already explained in the ABI documents and I believe for other platforms as well. Front-end/Back-End: The front-end should be responsible for validating the build-attributes, both for the generic and the specific parts, to make sure at least that the identifiers are valid and their values in the correct range (or in a given set of acceptable strings). The front-end should not generate attributes that were not required, directly or indirectly, but the user. Default behaviours should be already covered by the back-end already, so no need to restate the obvious. The back-end, and especially the linker, is free to assume whatever they want to make the objects link without breaking any user requests. The final executable should have only the build attributes necessary to compile and link correctly. I don't know how the back-end will get this, but there should be no difference from the current implementation of other @llvm. globals. There is already a place holder for ARM build attributes which will have to be hooked to this values. Use: So, the biggest problem we have today in the LLVM back-end is that it assumes too much. If given ARMv7A, it assumes A8+NEON, which is not always true. Even if given Cortex-A8 or A9 specifically, it still assumes NEON, which again, is not 1 to 1. For instance, the new Tegra2 boards sport an A9 without NEON. LLVM generated code would probably break on them. While putting a special case for Tegra2 would work, in ARM world, there are more exceptions than rules, so that's not the optimal solution. The ARM back-end doesn't print ".fpu" in the ASM file. GAS assumes that you want NEON support if it sees NEON instructions in the code, but not all linkers assume that much. The NEON instruction could be a bug in the code generation pass, and you'd never notice if the linker wouldn't complain about it. These are the things that come to my mind now (as I've dealt with them recently) but the number of examples are to great to list them here. I hope to have conveyed the idea. ;) In the case of lack of build attributes, the back-end is free to assume whatever it wants, but it should *always* honour the attributes to give the user most flexibility. Please let me know your thoughts so I can start looking into plugging the ARM part in the ARM back-end. -- cheers, --renato
Hi Renato,> So, after long rounds to define how the build attributes are going to > be represented in IR, and after Jason has implemented build attributes > in MC, I have a proposal on how to represent this in IR. > > First, we need to distinguish between target dependent and independent > attributes. Generic things like optimization level, specific > optimizations, use of vector instructions, use of exceptions, > floating-point compatibility can all go in to the generic list of > attributes.I don't see why you would want to put any of these things in the module at all: * optimization level: if you want the linker to optimize at -O3, I think you should just pass -O3 to the linker. I don't see why the fact that the original files were optimized at -O3, -O0, -O0 and -O3 (for example) is relevant to link time optimization. * specific optimizations: likewise. * use of vector instructions: if you want the linker to codegen for SSE3, then pass -msse3 to the linker. * use of exceptions: if a file is compiled with -fno-exceptions then all functions have the nounwind attribute and contain no invokes. This is all that is needed to automatically have the code generators not generate unwind info for them, so no special module level attribute is needed, everything is there already. * floating point compatibility: not sure what you mean by this. Ciao, Duncan.
Hi Duncan, I'm not sure you're arguing against having global build attributes (instead of just specific ones), or against the whole idea of having build attributes. I'll assume the former, as I take it that having support for ARM build attributes in LLVM is important (for compatibility, at least). On 12 November 2010 16:20, Duncan Sands <baldrick at free.fr> wrote:> * optimization level: if you want the linker to optimize at -O3, I think > you should just pass -O3 to the linker. I don't see why the fact that > the original files were optimized at -O3, -O0, -O0 and -O3 (for example) > is relevant to link time optimization. > > * specific optimizations: likewise. > > * floating point compatibility: not sure what you mean by this.I don't have any specific optimization in mind, but some ARM build attributes refer to the way optimizations and floating-point were assumed when compiling. If the user required IEEE 754 precision when compiling, you should honour that, possibly using libraries that guarantee you won't diverge from the standard. Please read the Addenda for more information: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045c/index.html (chapter 2.3.7) There could be similar assumption in Intel or PowerPC, they're not exclusively on ARM, so having them on a global attribute list (that can easily be ignored by any target), could help.> * use of vector instructions: if you want the linker to codegen for SSE3, > then pass -msse3 to the linker.It's not always that simple. In some benchmarks or build systems you can't easily fiddle with the linker parameters and the compilation is done in multiple, separated steps, so it's also not easy to propagate the user options as they don't share the same driver. Also, a vectorized attribute would tell if you have to link with vectorized libraries or normal ones, and if you have multiple styles of vector code (mmx, sse, etc) you could choose which one, even if the user haven't asked for a specific one. AFAIK, GCC assumes that, if you have vectorized code, you want vectorized libraries and vice-versa. But that's very simplistic. It may occur that your code was so small that couldn't be vectorized, but you still want vectorized libraries or vice-versa. While you can do that by passing arguments to the linker, you may be in a situation where you cannot pass arguments to the linker in the first place, or you can't re-compile part of your program (no source?) and want to enforce a different set of rules to the rest of the system.> * use of exceptions: if a file is compiled with -fno-exceptions then > all functions have the nounwind attribute and contain no invokes. > This is all that is needed to automatically have the code generators > not generate unwind info for them, so no special module level attribute > is needed, everything is there already.Well, not generating unwind information for your functions doesn't mean you can't have them in the libraries. If your code is not expecting exceptions to be thrown, and you have libraries that don't throw them, you can use the appropriate libraries for your code. Also, if you have nounwind in one source but not in the other, the compiler can't predict all the interoperability problems that will come from that, if you compile all of them together. With such a build attribute, the compiler might print a warning (or even an error) for cases where there could be potential problems when intermixing different assumptions. See, I'm not enforcing a standard behaviour on the global @llvm.attributes. I don't even need it, to be honest, but I didn't want to propose such a system without accounting for the general case.>From my point of view, it's important to have ARM build attributes inthe front-end all the way to the back-end. If other platforms can use the same encoding, better, if not, I don't mind. Just having @llvm.arm.attributes would be fine for me... cheers, --renato
On Nov 12, 2010, at 8:20 AM, Duncan Sands wrote:> Hi Renato, > >> So, after long rounds to define how the build attributes are going to >> be represented in IR, and after Jason has implemented build attributes >> in MC, I have a proposal on how to represent this in IR. >> >> First, we need to distinguish between target dependent and independent >> attributes. Generic things like optimization level, specific >> optimizations, use of vector instructions, use of exceptions, >> floating-point compatibility can all go in to the generic list of >> attributes. > > I don't see why you would want to put any of these things in the module > at all:In fact they are more suitable as function attributes. For example, we already have function attributes for -Os. - Devang> > * optimization level: if you want the linker to optimize at -O3, I think > you should just pass -O3 to the linker. I don't see why the fact that > the original files were optimized at -O3, -O0, -O0 and -O3 (for example) > is relevant to link time optimization. > > * specific optimizations: likewise. > > * use of vector instructions: if you want the linker to codegen for SSE3, > then pass -msse3 to the linker. > > * use of exceptions: if a file is compiled with -fno-exceptions then > all functions have the nounwind attribute and contain no invokes. > This is all that is needed to automatically have the code generators > not generate unwind info for them, so no special module level attribute > is needed, everything is there already. > > * floating point compatibility: not sure what you mean by this. > > Ciao, > > Duncan. > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev