Fix PR15293: ARM codegen ice - expected larger existing stack allocation

Stepan Dyatkovskiy stpworld at narod.ru
Fri Mar 29 11:05:45 PDT 2013


Hello,

Below some results of my small investigation.

[code]
target triple = "arm--linux-gnueabihf"
define void @t(i32 %a, %struct.s* byval %s, ...) nounwind {
define void @caller() {
   call void (i32, %struct.s*, ...)* @t(i32 0, %struct.s* @v, i32 777);
   ret void
}
[/code]

llc generates wrong asm code for IR above.

After some simple tests I conclude the next:

X86: tries don't use "byval" IR attribute in all cases its possible: it 
replaces structures with set of smaller params, does bitcasts and so on. 
But in some narrow set of cases it emits "byval" attributes.

ARM:
     clang: just casts structures to arrays and doesn't use byval at all.
     IR: generates bad code when two byval params passed, or
     "byval" + "..." pair passed. The only case works fine here is
     the big byval structure that splitted onto reg-part and stack-part.

That because CCState assumes that only parameter could be passed by value.

I propose to replace the term of "FirstByValRegister" with 
"SmallVector<std::pair<StartReg, RegsCount> ByValInRegArgs". The last 
one allows to track several small structures passed by value; it also 
automatically solves problem when we have single tiny "byval" structure 
(PR15293).

And BTW since arm-linux-gnueabi-clang avoids byval IR attribute, this 
feature will not be activated after llvm will fixed. Or I'm wrong? Are 
there some cases when arm-clang still emits something with "byval" 
attribute?
If no - byval structures handling shouldn't change clang behaviour.

Well, if I properly read the code, there are 3 points to be fixed in LLVM:

Callee side:
1. ARMTargetLowering::HandleByVal, since it allocates stack areas for 
arguments passed by value. Its also "caller" side though: for caller it 
just mark necessary amount of regs as byval.
2. ARMTargetLowering::LowerFormalArguments. Both for byval args and for 
var-arg function it calls VarArgStyleRegisters that allocates 
stack-frames for them and stores stores registers that contains byval 
arguments. Note if both byval parameter and "..." are presented it will 
store *the same* registers into all stack frames.

Caller side:
1. ARMTargetLowering::LowerCall. This funtion saves byval arguments into 
registers. If argument is too big to be stored in regs, method splits it 
onto reg-part and stack-part.

-Stepan.



More information about the llvm-commits mailing list