clang (LLVM) inline assembly - multiple constraints with useless spills / reloads - gcc

clang / gcc : Some inline assembly operands can be satisfied with multiple constraints, e.g., "rm", when an operand can be satisfied with a register or memory location. As an example, the 64 x 64 = 128 bit multiply:
__asm__ ("mulq %q3" : "=a" (rl), "=d" (rh) : "%0" (x), "rm" (y) : "cc")
The generated code appears to choose a memory constraint for argument 3, which would be fine if we were register starved, to avoid a spill. Obviously there's less register pressure on x86-64 than on IA32. However, the assembly snippet generated (by clang) is:
movq %rcx, -8(%rbp)
## InlineAsm Start
mulq -8(%rbp)
## InlineAsm End
Choosing a memory constraint is clearly pointless! Changing the constraint to: "r" (y), however (forcing a register) we get:
## InlineAsm Start
mulq %rcx
## InlineAsm End
as expected. These results are for clang / LLVM 3.2 (current Xcode release). The first question: Why would clang select the less efficient constraint in this case?
Secondly, there is the less widely used, comma-separated, multiple alternative constraint syntax:
"r,m" (y), which should evaluate the costs of each alternative, and choose the one that results in less copying. This appears to work, but clang simply chooses the first - as evidenced by: "m,r" (y)
I could simply drop the "m" alternative constraints, but this doesn't express the range of possible legal operands. This brings me to the second question: Have these issues been resolved or at least acknowledged in 3.3? I've tried looking through LLVM dev archives, but I'd rather solicit some answers before unnecessarily restricting constraints further, or joining project discussions, etc.

I had a response on the cfe-dev (clang front end developers' list) from one of the developers:
LLVM currently always spills "rm" constraints in order to simplify the
handling of inline asm in the backend (you can ask on llvmdev if you want
details). I don't know of any plans to fix this in the near future.
So it's clearly a 'known' issue. One of the goals of clang is to correctly handle gcc's inline assembly syntax, amongst other extensions, which it does in this case - just not very efficiently. In short, this isn't a bug, per se.
Since this isn't a bug, I'm going to continue with the "r,m" constraint syntax. I figure that this is the best compromise for now. gcc will choose the best - presumably a register where possible - and clang will force the use of a register by ignoring further options after the comma. If nothing else, it still preserves the semantic intent of the assembly statement, i.e., describing possible constraints, even if they are ignored.
A final note (20130715) : This particular example will not compile using the "r,m" constraint in a single position - we would have to supply an alternative constraint match for each, e.g.,
: "=a,a" (rl), "=d,d" (rh) : "%0,0" (x), "r,m" (y)
This is required for multiple alternative constraints with GCC. But we're getting into territory where GCC has been known to exhibit bugs in the past - whether or not this is true as of 4.8.1, I don't know. Clang works without the alternatives in the other constraints, which is incompatible with GCC syntax, and must therefore be considered a bug.
If performance is critical, use "r", otherwise, stick with "rm" and maybe clang will address this in the future, even as it benefits GCC.

Related

Documentation for MIPS predefined macros

When I compile a C code using GCC to MIPS, it contains code like:
daddiu $28,$28,%lo(%neg(%gp_rel(f)))
And I have trouble understanding instructions starting with %.
I found that they are called macros and predefined macros are dependent on the assembler but I couldn't find description of the macros (as %lo, %neg etc.) in the documentation of gas.
So does there exist any official documentation that explains macros used by GCC when generating MIPS code?
EDIT: The snippet of the code comes from this code.
This is a very odd instruction to find in compiled C code, since this instruction is not just using $28/$gp as a source but also updating that register, which the compiler shouldn't be doing, I would think.  That register is the global data pointer, which is setup on program start, and used by all code accessing near global variables, so it shouldn't ever change once established.  (Share a godbolt.org example, if you would.)
The functions you're referring to are for composing the address of labels that are located in global data.  Unlike x86, MIPS cannot load (or otherwise have) a 32-bit immediate in one instruction, and so it uses multiple instructions to do work with 32-bit immediates including address immediates.  A 32-bit immediate is subdivided into 2 parts — the top 16-bits are loaded using an LUI and the bottom 16-bits using an ADDI (or LW/SW instruction), forming a 2 instruction sequence.
MARS does not support these built-in functions.  Instead, it uses the pseudo instruction, la $reg, label, which is expanded by the assembler into such a sequence.  MARS also allows lw $reg, label to directly access the value of a global variable, however, that also expands to multiple instruction sequence (sometimes 3 instructions of which only 2 are really necessary..).
%lo computes the low 16-bits of a 32-bit address for the label of the argument to the "function".  %hi computes the upper 16-bits of same, and would be used with LUI.  Fundamentally, I would look at these "functions" as being a syntax for the assembly author to communicate to the assembler to share certain relocation information/requirements to the linker.  (In reverse, a disassembler may read relocation information and determine usage of %lo or %hi, and reflect that in the disassembly.)
I don't know %neg() or %gp_rel(), though could guess that %neg negates and %gp_rel produces the $28/$gp relative value of the label.
%lo and %hi are a bit odd in that the value of the high immediate sometimes is offset by +1 — this is done when the low 16-bits will appear negative.  ADDI and LW/SW will sign extend, which will add -1 to the upper 16-bits loaded via LUI, so %hi offsets its value by +1 to compensate when that happens.  This is part of the linker's operation since it knows the full 32-bit address of the label.
That generated code is super weird, and completely different from that generated by the same compiler, but 32-bit version.  I added the option -msym32 and then the generated code looks like I would expect.
So, this has something to do with the large(?) memory model on MIPS 64, using a multiple instruction sequence to locate and invoke g, and swapping the $28/$gp register as part of the call.  Register $25/$t9 is somehow also involved as the generated code sources it without defining it; later, prior to where we would expect the call it sets $25.
One thing I particularly don't understand, though, is where is the actual function invocation in that sequence!  I would have expected a jalr instruction, if it's using an indirect branch because it doesn't know where g is (except as data), but there's virtually nothing but loads and stores.
There are two additional oddities in the output: one is the blank line near where the actual invocation should be (maybe those are normal, but usually don't see those inside a function) and the other is a nop that is unnecessary but might have been intended for use in the delay slot following an invocation instruction.

MOVXZ into register - "invalid operand for instruction"

I am trying to compile an assembler-based implementation of AES, viewable here. My assembler is giving me the following error, repeated several different times over what appear to be instances of the same error. The exact source location is here, but due to the large amount of preprocessor indirection used in this file, I have copied the exact error from my build output, which gives the exact code as seen by the compiler:
/Volumes/Sources/Andromeda/Kernel/libkern/crypto/aes/EncryptDecrypt.s:297:19: error: invalid operand for instruction
movzx 240(%r10), %rax
^~~~
I do not quite understand what may be causing this problem. If I understand it properly, this instruction moves a byte (or more, this is unclear, and may in fact be the source of the problem) into the RAX register, zero-extending it if the source is less than 64-bits in size. Do I need to explicitly specify a size by adding a tag to the movxz instruction (e.g. movzxb)? What else might be the cause of this problem? Thanks!
At&t syntax does not normally use movzx, but maybe some assembler versions accept it. My copy of GNU assembler 2.22 does, but maybe OSX version doesn't. In any case, the assembler generates code for a byte source. If you do in fact have that, the proper at&t syntax would be movzbq 240(%r10), %rax, or, taking advantage of automatic zero extension, movzbl 240(%r10), %eax.
If you have a 4 byte source, then you can't use movzx at all, since it does not exist for that operand type. All you need in this case is the automatic zero extension, so you can simply do movl 240(%r10), %eax.

Avoiding source-level "jumping around" in gdb

With C++ code built for debugging with g++ (i.e. options "-O0 -ggdb") and using the newest gcc (5.1.0) and gdb (7.9) the display of source code in gdb is still painfully non-linear when using the "next" command. As an example this function call might be expected to step through with a single "next":
7757| SDValue NewRoot = TLI->LowerFormalArguments(
7758| DAG.getRoot(), F.getCallingConv(), F.isVarArg(), Ins, dl, DAG, InVals);
however it takes four, with the displayed execution line being first 7757, then 7758, then again 7757, then again 7758. If the function call is condensed to a single line then just one "next" is needed. If the call is absurdly inflated then seven "next"s are needed (shown as the '#' annotations)
7757| SDValue
7758| NewRoot
7759| =
#1,6 7760| TLI
7761| ->
7762| LowerFormalArguments(
#5 7763| DAG.getRoot(),
7764| F.getCallingConv(),
#3 7765| F.isVarArg(),
7766| Ins,
7767| dl,
7768| DAG,
7769| InVals
#2,4,7 7770| );
So it's related to but not as simple as "each function call on a distinct line is a stepping point". This gets especially confusing with breakpoints in recursive functions, where I find myself checking the callstack to see whether it's really a new invocation or just a phony backwards step.
Since reflowing all of the LLVM source to contain function calls in a single line isn't really a viable option, is there some gcc/gdb option for controlling this behaviour?
EDIT: now checked with clang 3.5 and lldb 3.5: when built with clang only three "next"s occur. And gdb and lldb see the same "next" behaviour in either case (i.e. 4 with gcc, 3 with clang)
This sort of behavior from the debugger is a "GIGO" situation -- that is, normally gdb is just doing whatever the debug info tells it to do. That is, when there is odd behavior, it is generally due to decisions made by the compiler. It may be a bug, and probably worth a bug report, but I also wouldn't be surprised if it is intended to work this way for some reason.
You can investigate these kinds of problems by using readelf or objdump to examine the line table.

change instruction set in GCC

I want to test some architecture changes on an already existing architecture (x86) using simulators. However to properly test them and run benchmarks, I might have to make some changes to the instruction set, Is there a way to add these changes to GCC or any other compiler?
Simple solution:
One common approach is to add inline assembly, and encode the instruction bytes directly.
For example:
int main()
{
asm __volatile__ (".byte 0x90\n");
return 0;
}
compiles (gcc -O3) into:
00000000004005a0 <main>:
4005a0: 90 nop
4005a1: 31 c0 xor %eax,%eax
4005a3: c3 retq
So just replace 0x90 with your inst bytes. Of course you wont see the actual instruction on a regular objdump, and the program would likely not run on your system (unless you use one of the nop combinations), but the simulator should recognize it if it's properly implemented there.
Note that you can't expect the compiler to optimize well for you when it doesn't know this instruction, and you should take care and work with inline assembly clobber/input/output options if it changes state (registers, memory), to ensure correctness. Use optimizations only if you must.
Complicated solution
The alternative approach is to implement this in your compiler - it can be done in gcc, but as stated in the comments LLVM is probably one of the best ones to play with, as it's designed as a compiler development platform, but it's still very complicated as LLVM is best suited for IR optimization stages, and is somewhat less friendly when trying to modify the target-specific backends.
Still, it's doable, and you have to do that if you also plan to have your compiler decide when to issue this instruction. I'd suggest to start from the first option though, to see if your simulator even works with this addition, and only then spending time on the compiler side.
If and when you do decide to implement this in LLVM, your best bet is to define it as an intrinsic function, there's relatively more documentation about this in here - http://llvm.org/docs/ExtendingLLVM.html
You can add new instructions, or change existing by modifying group of files in GCC called "machine description". Instruction patterns in <target>.md file, some code in <target>.c file, predicates, constraints and so on. All of these lays in $GCCHOME/gcc/config/<target>/ folder. All of this stuff using on step of generation ASM code from RTL. You can also change cases of emiting instructions by change some other general GCC source files, change SSA tree generation, RTL generation, but all of this a little bit complicated.
A simple explanation what`s happened:
https://www.cse.iitb.ac.in/grc/slides/cgotut-gcc/topic5-md-intro.pdf
It's doable, and I've done it, but it's tedious. It is basically the process of porting the compiler to a new platform, using an existing platform as a model. Somewhere in GCC there is a file that defines the instruction set, and it goes through various processes during compilation that generate further code and data. It's 20+ years since I did it so I have forgotten all the details, sorry.

GCC's extended version of asm

I never thought I'd be posting an assembly question. :-)
In GCC, there is an extended version of the asm function. This function can take four parameters: assembly-code, output-list, input-list and overwrite-list.
My question is, are the registers in the overwrite-list zeroed out? What happens to the values that were previously in there (from other code executing).
Update: In considering my answers thus far (thank you!), I want to add that though a register is listed in the clobber-list, it (in my instance) is being used in a pop (popl) command. There is no other reference.
No, they are not zeroed out. The purpose of the overwrite list (more commonly called the clobber list) is to inform GCC that, as a result of the asm instructions the register(s) listed in the clobber list will be modified, and so the compiler should preserve any which are currently live.
For example, on x86 the cpuid instruction returns information in four parts using four fixed registers: %eax, %ebx, %ecx and %edx, based on the input value of %eax. If we were only interested in the result in %eax and %ebx, then we might (naively) write:
int input_res1 = 0; // also used for first part of result
int res2;
__asm__("cpuid" : "+a"(input_res1), "=b"(res2) );
This would get the first and second parts of the result in C variables input_res1 and res2; however if GCC was using %ecx and %edx to hold other data; they would be overwritten by the cpuid instruction without gcc knowing. To prevent this; we use the clobber list:
int input_res1 = 0; // also used for first part of result
int res2;
__asm__("cpuid" : "+a"(input_res1), "=b"(res2)
: : "%ecx", "%edx" );
As we have told GCC that %ecx and %edx will be overwritten by this asm call, it can handle the situation correctly - either by not using %ecx or %edx, or by saving their values to the stack before the asm function and restoring after.
Update:
With regards to your second question (why you are seeing a register listed in the clobber list for a popl instruction) - assuming your asm looks something like:
__asm__("popl %eax" : : : "%eax" );
Then the code here is popping an item off the stack, however it doesn't care about the actual value - it's probably just keeping the stack balanced, or the value isn't needed in this code path. By writing this way, as opposed to:
int trash // don't ever use this.
__asm__("popl %0" : "=r"(trash));
You don't have to explicitly create a temporary variable to hold the unwanted value. Admittedly in this case there isn't a huge difference between the two, but the version with the clobber makes it clear that you don't care about the value from the stack.
If by "zeroed out" you mean "the values in the registers are replaced with 0's to prevent me from knowing what some other function was doing" then no, the registers are not zeroed out before use. But it shouldn't matter because you're telling GCC you plan to store information there, not that you want to read information that's currently there.
You give this information to GCC so that (reading the documentation) "you need not guess which registers or memory locations will contain the data you want to use" when you're finished with the assembly code (eg., you don't have to remember if the data will be in the stack register, or some other register).
GCC needs a lot of help for assembly code because "The compiler ... does not parse the assembler instruction template and does not know what it means or even whether it is valid assembler input. The extended asm feature is most often used for machine instructions the compiler itself does not know exist."
Update
GCC is designed as a multi-pass compiler. Many of the passes are in fact entirely different programs. A set of programs forming "the compiler" translate your source from C, C++, Ada, Java, etc. into assembly code. Then a separate program (gas, for GNU Assembler) takes that assembly code and turns it into a binary (and then ld and collect2 do more things to the binary). Assembly blocks exist to pass text directly to gas, and the clobber-list (and input list) exist so that the compiler can do whatever set up is needed to pass information between the C, C++, Ada, Java, etc. side of things and the gas side of things, and to guarantee that any important information currently in registers can be protected from the assembly block by copying it to memory before the assembly block runs (and copying back from memory afterward).
The alternative would be to save and restore every register for every assembly code block. On a RISC machine with a large number of registers that could get expensive (the Itanium has 128 general registers, another 128 floating point registers and 64 1-bit registers, for instance).
It's been a while since I've written any assembly code. And I have much more experience using GCC's named registers feature than doing things with specific registers. So, looking at an example:
#include <stdio.h>
long foo(long l)
{
long result;
asm (
"movl %[l], %[reg];"
"incl %[reg];"
: [reg] "=r" (result)
: [l] "r" (l)
);
return result;
}
int main(int argc, char** argv)
{
printf("%ld\n", foo(5L));
}
I have asked for an output register, which I will call reg inside the assembly code, and that GCC will automatically copy to the result variable on completion. There is no need to give this variable different names in C code vs assembly code; I only did it to show that it is possible. Whichever physical register GCC decides to use -- whether it's %%eax, %%ebx, %%ecx, etc. -- GCC will take care of copying any important data from that register into memory when I enter the assembly block so that I have full use of that register until the end of the assembly block.
I have also asked for an input register, which I will call l both in C and in assembly. GCC promises that whatever physical register it decides to give me will have the value currently in the C variable l when I enter the assembly block. GCC will also do any needed recordkeeping to protect any data that happens to be in that register before I enter the assembly block.
What if I add a line to the assembly code? Say:
"addl %[reg], %%ecx;"
Since the compiler part of GCC doesn't check the assembly code it won't have protected the data in %%ecx. If I'm lucky, %%ecx may happen to be one of the registers GCC decided to use for %[reg] or %[l]. If I'm not lucky, I will have "mysteriously" changed a value in some other part of my program.
I suspect the overwrite list is just to give GCC a hint not to store anything of value in these registers across the ASM call; since GCC doesn't analyze what ASM you're giving it, and certain instructions have side-effects that touch other registers not explicitly named in the code, this is the way to tell GCC about it.

Resources