Use computeMaxCallFrameSize() introduced in D32622
to calculate MaxCallFrameSize after instruction selection.
Test that the value is computed before the Prologue/Epilogue pass
after which MaxCallFrameSize will have been computed anyway.
Differential D42534
[mips] Compute MaxCallFrame size early on smaksimovic on Jan 25 2018, 6:35 AM. Authored by
Details
Use computeMaxCallFrameSize() introduced in D32622 Test that the value is computed before the Prologue/Epilogue pass
Diff Detail Event TimelineComment Actions Looking again at the tests reported in the upstream issue I found that with these changes DebugInfo/Mips/dsr-fixed-objects.ll fails still. We could call the function which computes the maxCallFrameSize in MipsDAGToDAGISel::runOnMachineFunction() prior to running selectionDAG which would compute maxCallFrameSize, albeit erroneously. Comment Actions Ok, hold off on committing this for now, I want to check this, as I'd missed the debuginfo tests when reviewing this. Good catch though.
Comment Actions +CC'ing @MatzeB for additional insight on what needs to be changed. Found the bug. What's occurring with the debug information test failures with this patch, is that during the insertion of debug instructions for function arguments, it has to determine which register to assign to the debug instruction, see SelectionDAGISel.cpp:505. Here it asks for the frame pointer register which for some RISC like targets by the size of the frame for the function. It seems to me that we need to compute the max call frame size before that point (SelectionDAGISel.cpp:505) for targets which use call frame setup and destroy pseudo instructions, this however requires changes for every target which implements finalizeLowering() to compute the maxCallFrameSize. Comment Actions Yeah code calling hasFP() early in the process is a real annoyance. You can find me wiggling in the review of https://reviews.llvm.org/D32622 too. At the time it seemed to me like it only influences scheduling heuristic so I went with this hack in the ARM target: // hasFP ends up calling getMaxCallFrameComputed() which may not be // available when getPressureLimit() is called as part of // ScheduleDAGRRList. bool HasFP = MF.getFrameInfo().isMaxCallFrameSizeComputed() ? TFI->hasFP(MF) : true; instead. But it looks like you found a bigger problem than the heuristic. If you can find ways for ISel to not do this anymore I would certainly apreciate it! Comment Actions Sketch solution: Extend the ISD Opcodes to include READ_FP, as SelectionDAG cannot determine ahead of time if function uses a frame pointer (in the general case). The node takes a single argument, the input chain and returns a pair of results, the current value of the frame pointer and the output chain. The semantics of the node are that it returns the value of the frame pointer at that point if the function is using a frame pointer or the current value of stack pointer if the function does not use a frame pointer. The pseudo instruction is then eliminated early during the finalization of instruction selection by replacing it either with a ISD::COPY or by replacing the users of the result ISD::READ_FP with the physreg directly which now can be computed correctly. ISel can then use the result of this node without needing the maximum frame size during the selection of any block but then ScheduleDAGRRList would still get the wrong result as it only sees one block at a time. We could track if we have seen basic blocks whose instructions contain call setup/destroy instructions which trigger the creation of reserved call frame or some other target specific requirement for a frame pointer. This however would mean that getPressureLimit would see an inconsistent result for a function. |
Nit: whitespace here.