Fix PR15293: ARM codegen ice - expected larger existing stack allocation
Manman Ren
mren at apple.com
Fri Apr 12 16:02:32 PDT 2013
On Apr 12, 2013, at 5:15 AM, Stepan Dyatkovskiy wrote:
> 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.
The above looks good.
>
> *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.
Can we fix the above issue in a separate patch with additional testing case?
>
> >>> + // 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 don't really think it is necessary :)
>
> I didn't present refactor patch, just because main patch didn't get LGTM community and hypothetically may contain some mistakes..
LGTM otherwise.
Thanks,
Manman
>
> -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
>
> <pr15293-2013-04-12.patch>
More information about the llvm-commits
mailing list