Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does gcc compile f(1199) and f(1200) differently?

What causes GCC 7.2.1 on ARM to use a load from memory (lr) for certain constants, and an immediate (mov) in some other cases? Concretely, I'm seeing the following:

GCC 7.2.1 for ARM compiles this:

extern void abc(int);
int test() { abc(1199); return 0; }

…into that:

test():
  push {r4, lr}
  ldr r0, .L4  // ??!
  bl abc(int)
  mov r0, #0
  pop {r4, lr}
  bx lr
.L4:
  .word 1199

and this:

extern void abc(int);
int test() { abc(1200); return 0; }

…into that:

test():
  push {r4, lr}
  mov r0, #1200  // OK
  bl abc(int)
  mov r0, #0
  pop {r4, lr}
  bx lr

At first I expected 1200 to be some sort of unique cutoff, but there are other cut-offs like this at 1024 (1024 yields a mov r0, #1024, whereas 1025 uses ldr) and at other values.

Why would GCC use a load from memory to fetch a constant, rather than using an immediate?

like image 911
Clément Avatar asked Feb 01 '18 23:02

Clément


People also ask

What can GCC compile?

GCC stands for “GNU Compiler Collection”. GCC is an integrated distribution of compilers for several major programming languages. These languages currently include C, C++, Objective-C, Objective-C++, Fortran, Ada, D, and Go.

What is option in GCC compilation?

When you invoke GCC, it normally does preprocessing, compilation, assembly and linking. The "overall options" allow you to stop this process at an intermediate stage. For example, the -c option says not to run the linker. Then the output consists of object files output by the assembler.

What is Wall flag in GCC?

gcc -Wall enables all compiler's warning messages. This option should always be used, in order to generate better code.


1 Answers

This has to do with the way that constant operands are encoded in the ARM instruction set. They are encoded as an (unsigned) 8-bit constant combined with a 4 bit rotate field -- the 8 bit value will be rotated by 2 times the value in that 4 bit field. So any value that fits in that form can be used as a constant argument.

The constant 1200 is 10010110000 in binary, so it can be encoded as the 8-bit constant 01001011 combined with a rotate of 4.

The constant 1199 is 10010101111 in binary, so there's no way to fit it in an ARM constant operand.

like image 112
Chris Dodd Avatar answered Oct 17 '22 19:10

Chris Dodd