Pasi Parviainen
2014-May-30 23:48 UTC
[LLVMdev] Question about callee saved registers in x86
On 31.5.2014 2:04, Pasi Parviainen wrote:> On 28.5.2014 2:57, Sanjoy Das wrote: >> Hi llvmdev, >> >> I'm trying to figure how llvm remembers stack slots allotted to callee >> saved registers on x86. In particular, llvm pushes registers in >> decreasing order of FrameIdxs [1], so the offsets they get (as >> returned by MFI->getObjectOffset) don't directly correspond to their >> actual stack locations. In X86FrameLowering's >> emitCalleeSavedFrameMoves, when emitting DWARF information, this >> discrepancy gets fixed up by subtracting the offset reported by >> MFI->getObjectOffset from the minimum offset for any CSR (this is done >> by the "Offset = MaxOffset - Offset + saveAreaOffset;" line). Is >> there a reason why llvm doesn't keep around the offsets in the right >> order from very beginning, by pushing the CSRs in increasing order of >> FrameIdxs? > > Now, that you mention it, I remember being down to the same rabbit hole. > With certain calling conventions (coldcc, I think it was which can for > sure expose this for x86), it is possible to generate invalid CFI > directives for the registers in a frame. Especially when XMM registers > must be preserved along with general purpose registers. And the reason > for this was the offset fixing logic within emitCalleeSavedFrameMoves, > which breaks when fixing offset for XMM registers. > > To fix this disparity, I concluded that it could be done by reversing > definition order of general purpose registers within X86CallingConv.td > for all calling conventions, since llvm prefers to use push/pop model > for storing GPR:s (for x86). With this change stack slots and registers > would have 1:1 mapping, without extra offset calculations and > emitCalleeSavedFrameMoves could be simplified by removing extra magic to > determine slots, and to generate correct CFI directives in unusual cases.Now that checking out some old experimental code to solve this, it also seems to require to reversing the order of XMM/YMM registers within calling convention definitions in X86CallingConv.td, and to do other minor changes to account for these.>> [1]: in fact, the way X86FrameLowering's spillCalleeSavedRegisters and >> PEI's calculateCalleeSavedRegisters are set up, I don't see a reason >> why the FrameIdxs and the generated push instructions have any >> relation at all. It seems that the code relies on >> MFI->CreateStackObject returning sequential integers. >> >> Thanks! >> -- Sanjoy >> >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> >
Vadim Chugunov
2014-May-31 00:12 UTC
[LLVMdev] Question about callee saved registers in x86
Hi, I have a related question. The spilled x86 GPRs are assigned positive frame indices, which seems problematic in cases when stack needs to be realigned: they are pushed before stack is re-aligned, so they cannot be addressed relative to the stack pointer (because there is a random gap caused by SP re-alignment). Shouldn't they be assigned negative indices, i.e. be fixed objects, in which case they can be addressed relative to BP? Vadim On Fri, May 30, 2014 at 4:48 PM, Pasi Parviainen <pasi.parviainen at iki.fi> wrote:> On 31.5.2014 2:04, Pasi Parviainen wrote: > >> On 28.5.2014 2:57, Sanjoy Das wrote: >> >>> Hi llvmdev, >>> >>> I'm trying to figure how llvm remembers stack slots allotted to callee >>> saved registers on x86. In particular, llvm pushes registers in >>> decreasing order of FrameIdxs [1], so the offsets they get (as >>> returned by MFI->getObjectOffset) don't directly correspond to their >>> actual stack locations. In X86FrameLowering's >>> emitCalleeSavedFrameMoves, when emitting DWARF information, this >>> discrepancy gets fixed up by subtracting the offset reported by >>> MFI->getObjectOffset from the minimum offset for any CSR (this is done >>> by the "Offset = MaxOffset - Offset + saveAreaOffset;" line). Is >>> there a reason why llvm doesn't keep around the offsets in the right >>> order from very beginning, by pushing the CSRs in increasing order of >>> FrameIdxs? >>> >> >> Now, that you mention it, I remember being down to the same rabbit hole. >> With certain calling conventions (coldcc, I think it was which can for >> sure expose this for x86), it is possible to generate invalid CFI >> directives for the registers in a frame. Especially when XMM registers >> must be preserved along with general purpose registers. And the reason >> for this was the offset fixing logic within emitCalleeSavedFrameMoves, >> which breaks when fixing offset for XMM registers. >> >> To fix this disparity, I concluded that it could be done by reversing >> definition order of general purpose registers within X86CallingConv.td >> for all calling conventions, since llvm prefers to use push/pop model >> for storing GPR:s (for x86). With this change stack slots and registers >> would have 1:1 mapping, without extra offset calculations and >> emitCalleeSavedFrameMoves could be simplified by removing extra magic to >> determine slots, and to generate correct CFI directives in unusual cases. >> > > Now that checking out some old experimental code to solve this, it also > seems to require to reversing the order of XMM/YMM registers within calling > convention definitions in X86CallingConv.td, and to do other minor changes > to account for these. > > > [1]: in fact, the way X86FrameLowering's spillCalleeSavedRegisters and >>> PEI's calculateCalleeSavedRegisters are set up, I don't see a reason >>> why the FrameIdxs and the generated push instructions have any >>> relation at all. It seems that the code relies on >>> MFI->CreateStackObject returning sequential integers. >>> >>> Thanks! >>> -- Sanjoy >>> >>> _______________________________________________ >>> LLVM Developers mailing list >>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>> >>> >> > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140530/0aa12411/attachment.html>
Hi! On May 30, 2014, at 5:12 PM, Vadim Chugunov <vadimcn at gmail.com> wrote:> Hi, > I have a related question. The spilled x86 GPRs are assigned positive frame indices, which seems problematic in cases when stack needs to be realigned: they are pushed before stack is re-aligned, so they cannot be addressed relative to the stack pointer (because there is a random gap caused by SP re-alignment). > > Shouldn't they be assigned negative indices, i.e. be fixed objects, in which case they can be addressed relative to BP?Does llvm actually emit code to directly access the callee saved registers? As long as all llvm does is push them on entry and pop them on exit, you don't really care very much about offsets. As far as DWARF information is concerned, I'd expect the locations of the callee saved register spills be in terms of the CFA (Canonical Frame Address), and as long as llvm emits a correct expression to calculate the CFA at all points of the function body, DWARF readers should do fine. My initial point of confusion was that it seems llvm has some internal discrepancies about what slots CSRs get mapped to -- the actual code seems to push them in an different order than the they are assigned slots on the stack. This gets corrected later on, and we do get accurate .cfi directives, so I figured that this may be some convention that I had missed. However, (thanks to Pasi's hint) there are cases where llvm generates incorrect .cfi directives, and this leads me to think that the issue is, in fact, the lack of co-ordination between the code that emits the PUSH instructions and the code that assigns stack slots to the CSR frame indices. I think I have a reproducible test case now, and I've filed a bug at http://llvm.org/bugs/show_bug.cgi?id=19905. Unless someone else wants to tackle this, I'll have a go at it next week. -- Sanjoy> > Vadim > > > > On Fri, May 30, 2014 at 4:48 PM, Pasi Parviainen <pasi.parviainen at iki.fi> wrote: > On 31.5.2014 2:04, Pasi Parviainen wrote: > On 28.5.2014 2:57, Sanjoy Das wrote: > Hi llvmdev, > > I'm trying to figure how llvm remembers stack slots allotted to callee > saved registers on x86. In particular, llvm pushes registers in > decreasing order of FrameIdxs [1], so the offsets they get (as > returned by MFI->getObjectOffset) don't directly correspond to their > actual stack locations. In X86FrameLowering's > emitCalleeSavedFrameMoves, when emitting DWARF information, this > discrepancy gets fixed up by subtracting the offset reported by > MFI->getObjectOffset from the minimum offset for any CSR (this is done > by the "Offset = MaxOffset - Offset + saveAreaOffset;" line). Is > there a reason why llvm doesn't keep around the offsets in the right > order from very beginning, by pushing the CSRs in increasing order of > FrameIdxs? > > Now, that you mention it, I remember being down to the same rabbit hole. > With certain calling conventions (coldcc, I think it was which can for > sure expose this for x86), it is possible to generate invalid CFI > directives for the registers in a frame. Especially when XMM registers > must be preserved along with general purpose registers. And the reason > for this was the offset fixing logic within emitCalleeSavedFrameMoves, > which breaks when fixing offset for XMM registers. > > To fix this disparity, I concluded that it could be done by reversing > definition order of general purpose registers within X86CallingConv.td > for all calling conventions, since llvm prefers to use push/pop model > for storing GPR:s (for x86). With this change stack slots and registers > would have 1:1 mapping, without extra offset calculations and > emitCalleeSavedFrameMoves could be simplified by removing extra magic to > determine slots, and to generate correct CFI directives in unusual cases. > > Now that checking out some old experimental code to solve this, it also seems to require to reversing the order of XMM/YMM registers within calling convention definitions in X86CallingConv.td, and to do other minor changes to account for these. > > > [1]: in fact, the way X86FrameLowering's spillCalleeSavedRegisters and > PEI's calculateCalleeSavedRegisters are set up, I don't see a reason > why the FrameIdxs and the generated push instructions have any > relation at all. It seems that the code relies on > MFI->CreateStackObject returning sequential integers. > > Thanks! > -- Sanjoy > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > >