3

I'm taking the Computer Architecture course in my undergraduate study.

I see that in loop unrolling, one of the constraints is the number of available registers.

Since the number of registers depends on the architecture, is a generic pre-compiled binary targeted for the worst case (least number of available registers)?

I know that a software compiled from source is faster than downloading a pre compiled binary, and the reason is often explained as the generated assembly being more “targeted”. Is the loop unrolling one of the examples of this “targeted” compilation? As in, a software compiled for a processor with more registers than the generic case will utilize ALL those registers for its loops?

  • 1
    IIRC when I did code for such a generic library in one of past projects we simply provided several versions of code optimized for different amounts of registers, like 16, 32, 64, 128 etc – gnat Oct 6 '16 at 6:38
3

Since the number of registers depends on the architecture, is a generic pre-compiled binary targeted for the worst case (least number of available registers)?

There really isn't such thing as a generic pre-compiled binary. Binaries that are compiled necessarily target both a specific Instruction Set Architecture and a specific Application Binary Interface. That same binary won't run on a different ISA or different ABI, it will have to be recompiled for that.

It is the ISA that defines the available hardware register set; the ABI defines how the software is allowed to use the registers, especially when it comes to function calls.

When compiling, the ISA and ABI are selected by choosing the appropriate compiler or sometimes by compiler options.

For example, x86 is an intel 32-bit Instruction Set Architecture that specifies ~8 32-bit registers (not counting any floating point or xmm registers).

x64, on the other had has ~16 64-bit registers. And there are other processors, too.

A binary compiled for x86 will usually run in 32-bit compatibility mode as a feature of an x64 processor, however, an x64 compiled-binary won't run on an x86. (When a x64 processor runs an x86 binary that binary runs with the resources of the 32-bit instruction set architecture, which is to say it is limited to the ~8 32-bit registers and has a 4GB address space limit as well; it does not have access to the 16 64-bit registers or larger address space.)

Further, a binary compiled for windows will not run on linux and vise versa due to ABI differences, even for the same ISA.

Is the loop unrolling one of the examples of this “targeted” compilation?

All "pre" compilation is targeted to an exact ISA and ABI pair.

As in, a software compiled for a processor with more registers than the generic case will utilize ALL those registers for its loops?

Yes, to a degree. But I'd say there is no generic case, there are specific cases.


There is an area of compilation that is more dynamic, and this is Just In Time Compiling or JITing for short. Java and C# both use an intermediate binary form called byte code (different for each, of course), and then do final compilation on the target machine at runtime. Since the runtime knows more about the actual processor it is running on, it can do a better job of managing compilation not just for the specific ISA and ABI but also for the specific processor. This include the registers, and affects the use of optional processor features, like XMM registers. For example, in C# you can write code that uses the SIMD processor extensions, and if that hardware is present (i.e. it is currently running on a more expensive or more modern processor) the JIT will generate code to use them, and if that hardware is not present, it won't.

In a "pre" compiled environment, you'd have to create two separate pre-compiled binaries for that.

  • You should check out iOS bit code, which is quite clearly designed to support future (currently unknown) architectures. – gnasher729 Oct 9 '16 at 19:35
2

Considering loop unrolling alone, it is just that: save the iteration code, so I wouldn't consider it "targeted".

It does, however, enable all kind of other optimisations - which might make use of the given architecture. Rearranging operations and/or running them in parallel / vectorise, some of this might benefit from more registers, some don't. Some what surely fall into the "targeted" category.

Consider a tight loop that calls just a heavy function vs. one that does some vector multiplication. It depends.

2

Loop unrolling might increase (or decrease) register usage, which depends on the code inside the loop and the compiler. The topic is discussed controversial at this Wikipedia "Dubious" page about loop unrolling. So loop unrolling can lead to code where the optimization gain works better on one machine, and worse on another, but that depends heavily on the individual case.

  • Generic loop unrolling in essence actually tends to use less registers than more. – tofro Oct 6 '16 at 7:23
  • @tofro: of course, changed my answer a little bit. – Doc Brown Oct 6 '16 at 10:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.