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