Fix PR15293: ARM codegen ice - expected larger existing stack allocation
Stepan Dyatkovskiy
stpworld at narod.ru
Fri Apr 12 05:15:43 PDT 2013
Hello Manman,
I reattached full patch with fixes.
1. I've removedskipWastedByValRegs, addByValWastedRegs and Wasted flag.
2. Fixed usage of "offset" variable in LowerFormalArguments
3. And fixed regression test: added function with two byval structures.
*4.* One new change I've made is
CC_ARM_AAPCS_Common rule.
Currently, for align == 4 and parameter type <=i32, we try to assign it
to the first unallocated register from [r0-r3] range, but only if
getNextStackOffset() == 0.
I suppose that "getNextStackOffset() != 0" is treated as fact? that all
registers are used? and params goes to the stack now. After byval
structures will be implemented, the next case is possible:
void @f(%i32_struct* byval, i32)
Here, we need to allocate stack for first parameter, but after we still
have unallocated registers. And second parameter should be sent to r1.
Current CC_ARM_AAPCS_Common implementation will send second parameter to
the stack.
Though, I'm still not sure about this change, just because may be there
are more reasons to check nextStackOffset value.
>>> + // for byval parameters.
>>> + {
>>> + unsigned InRegsParamsCount = State->getInRegsParamsCount();
>>> + if (InRegsParamsCount) {
>>> + unsigned RB, RE;
>>> + State->getInRegsParamInfo(InRegsParamsCount-1, RB, RE);
>>> + assert(reg >= RE);
>>> + }
>>> + }
>> Is this only for assertion? Is this necessary?
> Yes. I've just moved this check from "if" statement, since it must be
> true always.
How do you think, do we need this assertion?
I didn't present refactor patch, just because main patch didn't get LGTM
community and hypothetically may contain some mistakes..
-Stepan
Stepan Dyatkovskiy wrote:
> Manman Ren wrote:
>>
>> Hi Stepan,
>>
>> One high-level question: do we need to insert the wasted record to
>> ByValRegs and later on skip those records?
>> It seems to me that we can only insert the records for the actual byval
>> parameters.
>> If that is true, we can remove addByValWastedRegs and
>> skipWastedByValRegs.
> Hm.. yes its reasonable. I'll try to fix.
>
>>
>>> +
>>> + // "offset" value would be usefull if byval parameter outsides
>>> + // the registers area. Note, in that case nextInRegsParam()
>>> will not
>>> + // skip any waste registers, since parameter fillup the whole
>>> rest
>>> + // of registers set.
>>> + unsigned RegsUsed = RegEnd - RegBegin;
>>> + if (!CCInfo.nextInRegsParam() && Flags.getByValSize() >
>>> 4*RegsUsed )
>>> + offset = RegEnd - RegBegin;
>>> }
>>>
>>> - if (Flags.getByValSize() - 4*offset > 0) {
>>> + if (offset) {
>>
>> This still does not look right.
>> There are 3 cases:
>> If the byval parameter is in registers partially, we should create a
>> COPY_STRUCT_BYVAL with the correct offset;
>> If the byval parameter is all in registers, there is no need to create a
>> COPY_STRUCT_BYVAL;
>> If the byval parameter is all on stack, we should create a
>> COPY_STRUCT_BYVAL with offset equal to 0.
>>
>> When looking at the above code, offset is default to zero, if
>> CurByValIdx >= ByValArgsCount (this byval parameter is all on stack),
>> offset will still be zero,
>> and we will not create a COPY_STRUCT_BYVAL.
>> The correct logic seems to be always updating offset inside the if and
>> check Flags.getByValSize() > 4*offset
>> if (CurByValIdx < ByValArgsCount) {
>> …
>> offset = RegEnd - RegBegin; //number of registers occupied by this
>> byval parameter
>> CCInfo.nextInRegsParam(); // go to the next byval parameter that is
>> in registers partially or all
>> }
>> if (Flags.getByValSize() > 4*offset) {
>> // Part of the byval parameter is on stack.
>> ...
> Oh.. I missed third case. Then we keep first variant here.
>
>>> - if ((!State->isFirstByValRegValid()) &&
>>> - (ARM::R0 <= reg) && (reg <= ARM::R3)) {
>>> + if ((ARM::R0 <= reg) && (reg <= ARM::R3)) {
>>> + // All registers reserved for byval parameters should be allocated.
>>> + // Check that first unallocated register is higher that last one
>>> used
>>> + // for byval parameters.
>>> + {
>>> + unsigned InRegsParamsCount = State->getInRegsParamsCount();
>>> + if (InRegsParamsCount) {
>>> + unsigned RB, RE;
>>> + State->getInRegsParamInfo(InRegsParamsCount-1, RB, RE);
>>> + assert(reg >= RE);
>>> + }
>>> + }
>> Is this only for assertion? Is this necessary?
> Yes. I've just moved this check from "if" statement, since it must be
> true always.
>
>>> -void
>>> -ARMTargetLowering::VarArgStyleRegisters(CCState &CCInfo, SelectionDAG
>>> &DAG,
>>> - DebugLoc dl, SDValue &Chain,
>>> - const Value *OrigArg,
>>> - unsigned OffsetFromOrigArg,
>>> - unsigned ArgOffset,
>>> - bool ForceMutable) const {
>>> +// Return: The frame index registers were stored into.
>>> +int
>>> +ARMTargetLowering::StoreByValRegs(CCState &CCInfo, SelectionDAG &DAG,
>>> + DebugLoc dl, SDValue &Chain,
>>> + const Value *OrigArg,
>>> + unsigned InRegsParamRecordIdx,
>>> + unsigned OffsetFromOrigArg,
>>> + unsigned ArgOffset,
>>> + bool ForceMutable) const {
>>
>> It would be much cleaner if we can move the refactoring of
>> VarArgStyleRegisters to a separate patch.
> For sure.
>
> P.S.: Today I had some troubles with electricity, so I'll try present
> new patch tomorrow.
>
> -Stepan.
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pr15293-2013-04-12.patch
Type: text/x-diff
Size: 22342 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130412/374ff159/attachment.patch>
More information about the llvm-commits
mailing list