ARM assembly

Hi All,

I am working to cross compile (just generate assembly code) a simple C code in ARM. First, I use CLANG to get LLVM bytecode, then I use llc to generate assembly for ARM. The problem is it never uses any other register except r0-r3 and always uses spill code even if other register are available to use. Anyone has any idea?

Thanks

Best Regards,
A. Yazdanbakhsh

Hi,

I am working to cross compile (just generate assembly code) a simple C code
in ARM. First, I use CLANG to get LLVM bytecode, then I use llc to generate
assembly for ARM. The problem is it never uses any other register except
r0-r3 and always uses spill code even if other register are available to
use. Anyone has any idea?

Some example code and output might be useful. Command line options
you're using too.

The only thing I can think of is you might not be generating enough
register pressure that it *needs* to go beyond r0-r3, and maybe
mistaking something else the compiler is doing for a pressure spill.
The following function uses r12 for me, for example ("llc -march=arm
-o - simple.ll"):

@var = global i32 0

define void @foo() {
  %val1 = load volatile i32* @var
  %val2 = load volatile i32* @var
  %val3 = load volatile i32* @var
  %val4 = load volatile i32* @var

  store volatile i32 %val1, i32* @var
  store volatile i32 %val2, i32* @var
  store volatile i32 %val3, i32* @var
  store volatile i32 %val4, i32* @var

  ret void
}

Tim.

Sound like you are not enabling optimization. Try with -O3.

Evan

Ah, of course! I'd forgotten about the extra allocas produced by clang.

To expand a little, the spills you're seeing are (probably)
specifically created by clang (it creates a shadow variable for each
local with alloca). "llc" on its own can't get rid of these, so you'll
either want to give clang "-O3" or run the LLVM bitcode through "opt"
before "llc".

Tim.

I used your code and it works fine. Once I increase the number of variable it uses the extra registers which I added. I have another problem.

To generate the assembly file for new ARM machine with extra registers,I follow these steps:

  1. clang -emit-llvm main.ll main.c
  2. llc -march=arm -o main.s main.bc

In this case it doesn’t use the registers which I added to the architecture. Do you have any ideas?

As far as I know, the generated ll code doesn’t depend on the target (right?), but I see this line in the ll code : target triple = “x86_64-unknown-linux-gnu”
Could it be the problem?

I really appreciate if anybody can help.

Hi Amir,

1) clang -emit-llvm main.ll main.c
2) llc -march=arm -o main.s main.bc

In this case it doesn't use the registers which I added to the architecture.
Do you have any ideas?

Evan's suggestion was probably a good one. If you replace the clang command with
$ clang -O3 -emit-llvm main.c

then llc should be able to use more registers for the resulting main.bc.

As far as I know, the generated ll code doesn't depend on the target
(right?), but I see this line in the ll code : target triple =
"x86_64-unknown-linux-gnu"
Could it be the problem?

It's not *this* problem, and as long as you don't try to do anything
too complicated (including trying to run the output) you'll probably
get away with it, but it's not ideal.

What you really want is a cross-toolchain and to point clang at this
toolchain. Most importantly with the option "-target
arm-none-linux-gnueabi" (or similar), but possibly also telling it
where the headers and libraries are with other options.

Tim.