How to Store variable allocation in Registers

Hello,

Im trying to build a Backend using LLVM. My Architecture doesnt have a stack. So,I need to store all the variables in Registers.

I found in xxxFrameLowering.cpp (where xxx is any target name) references to stack and frame pointer. I tried to remove all those references by placing Register class in place of stack but of no use.

Can anyone please suggest the way to do this…,would be very helpful if you can share some code or reference links too…

Thank you,

Avinash

What language are you compiling?

If it is anything remotely like C then you absolutely need a stack (or a heap), because of the possibility of recursion. If the hardware doesn’t provide one then you have to create your own using a normal pointer register (or, worst case, a global pointer variable).

It is possible to compile languages such as traditional FORTRAN and COBOL without a stack, but you still need a frame for each function to hold the return address and any local variables that don’t fit into registers. It’s just that the frames can be allocated as global variables instead of on a stack. You still need to calculate a frame layout. You probably even still want a frame pointer, to avoid having possibly large absolute addresses when referencing slots in the frame.

Hi Bruce!!

Im using “C” language.

As you said…,i tried using Global pointer…,but i still am not able to get the Registers exactly as i wanted.

I found “-mem2reg” as a better alternative. But Problem is even though the resulting Intermediate file( .ll ) is

good…,the final assembly file( .s) file is making a lot of DCE.

Im Posting an example :

Original Intermediate file :

define void @main() #0 {
%a = alloca i32, align 4
%b = alloca i32, align 4
%c = alloca i32, align 4
store i32 2, i32* %a, align 4
store i32 3, i32* %b, align 4
store i32 4, i32* %c, align 4
%1 = load i32* %a, align 4
%2 = add nsw i32 %1, 10
store i32 %2, i32* %a, align 4
%3 = load i32* %a, align 4
%4 = load i32* %b, align 4
%5 = add nsw i32 %3, %4
store i32 %5, i32* %a, align 4
store i32 5, i32* %a, align 4
%6 = load i32* %b, align 4
%7 = sub nsw i32 %6, 2
store i32 %7, i32* %b, align 4
%8 = load i32* %b, align 4
%9 = load i32* %a, align 4
%10 = sub nsw i32 %8, %9
store i32 %10, i32* %b, align 4
%11 = load i32* %c, align 4
%12 = xor i32 %11, 4
store i32 %12, i32* %c, align 4
%13 = load i32* %c, align 4
%14 = load i32* %c, align 4
%15 = xor i32 %13, %14
store i32 %15, i32* %c, align 4
%16 = load i32* %a, align 4
%17 = load i32* %b, align 4
%18 = or i32 %16, %17
store i32 %18, i32* %a, align 4
%19 = load i32* %b, align 4
%20 = and i32 %19, 2
store i32 %20, i32* %b, align 4
store i32 7, i32* %a, align 4
%21 = load i32* %a, align 4
%22 = or i32 %21, 2
%23 = load i32* %b, align 4
%24 = load i32* %c, align 4
%25 = or i32 %23, %24
%26 = and i32 %22, %25
store i32 %26, i32* %b, align 4
ret void
}

After using “-mem2reg”:

define void @main() #0 {
%1 = add nsw i32 2, 10
%2 = add nsw i32 %1, 3
%3 = sub nsw i32 3, 2
%4 = sub nsw i32 %3, 5
%5 = xor i32 4, 4
%6 = xor i32 %5, %5
%7 = or i32 5, %4
%8 = and i32 %4, 2
%9 = or i32 7, 2
%10 = or i32 %8, %6
%11 = and i32 %9, %10
ret void
}

Assembly file:

Return;

As you can see…,all the code is eliminated as dead code…,now is there a possibility to stop Dead code elimination?

Is there a way to stop dead code elimination? Yes of course. Use the results!

Why would you want to keep useless code, the results of which are not visible to the rest of the program? That’s exactly what we want an optimiser framework like LLVM to do.

If you write a C function like …

void foo(){
int v1 = 2 + 10;
int v2 = v1 + 3;
int v3 = 3 - 2;
int v4 = v3 - 5;
int v5 = 4 ^ 4;
int v6 = v5 ^ v5;
int v7 = 5 | v4;
int v8 = v4 & 2;
int v9 = 7 | 2;
int v10 = v8 | v6;
int v11 = v9 & v10;
return;
}

… then Clang (or gcc) will generate just a return instruction (and maybe saving/restoring a frame pointer for debugging purposes, depending on ABI) with any optimisation level of -O1 or more.

If you use -O0 then a stack frame will be generated, and all variable accesses will be to the stack frame, not registers. Again, for debugging purposes.

Thank you