diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index 914d333c34c..c54ce530c04 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -650,7 +650,8 @@ SystemZInstrInfo::getLongDispOpc(unsigned Opc) const { case SystemZ::FMOV64mr: return get(SystemZ::FMOV64mry); case SystemZ::FMOV32rm: return get(SystemZ::FMOV32rmy); case SystemZ::FMOV64rm: return get(SystemZ::FMOV64rmy); - default: return get(Opc); + default: + assert(0 && "Don't have long disp version of this instruction"); } } diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h index 0ef3ca93bea..ba94cede00d 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/lib/Target/SystemZ/SystemZInstrInfo.h @@ -106,6 +106,13 @@ public: SystemZCC::CondCodes getCondFromBranchOpc(unsigned Opc) const; const TargetInstrDesc& getBrCond(SystemZCC::CondCodes CC) const; const TargetInstrDesc& getLongDispOpc(unsigned Opc) const; + + const TargetInstrDesc& getMemoryInstr(unsigned Opc, int64_t Offset = 0) const { + if (Offset < 0 || Offset >= 4096) + return getLongDispOpc(Opc); + else + return get(Opc); + } }; } diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp index c829e43fb17..643d681563d 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -133,8 +133,7 @@ void SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int Offset = getFrameIndexOffset(MF, FrameIndex) + MI.getOperand(i+1).getImm(); // Check whether displacement is too long to fit into 12 bit zext field. - if (Offset < 0 || Offset >= 4096) - MI.setDesc(TII.getLongDispOpc(MI.getOpcode())); + MI.setDesc(TII.getMemoryInstr(MI.getOpcode(), Offset)); MI.getOperand(i+1).ChangeToImmediate(Offset); } @@ -179,11 +178,18 @@ SystemZRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, static void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, int64_t NumBytes, const TargetInstrInfo &TII) { - // FIXME: Handle different stack sizes here. + unsigned Opc; uint64_t Chunk; bool isSub = NumBytes < 0; uint64_t Offset = isSub ? -NumBytes : NumBytes; - unsigned Opc = SystemZ::ADD64ri16; - uint64_t Chunk = (1LL << 15) - 1; + + if (Offset >= (1LL << 15) - 1) { + Opc = SystemZ::ADD64ri32; + Chunk = (1LL << 31) - 1; + } else { + Opc = SystemZ::ADD64ri16; + Chunk = (1LL << 15) - 1; + } + DebugLoc DL = (MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc::getUnknownLoc()); @@ -293,7 +299,17 @@ void SystemZRegisterInfo::emitEpilogue(MachineFunction &MF, assert(i < MI.getNumOperands() && "Unexpected restore code!"); } - MI.getOperand(i).ChangeToImmediate(NumBytes + MI.getOperand(i).getImm()); + uint64_t Offset = NumBytes + MI.getOperand(i).getImm(); + // If Offset does not fit into 20-bit signed displacement field we need to + // emit some additional code... + if (Offset > 524287) { + // Fold the displacement into load instruction as much as possible. + NumBytes = Offset - 524287; + Offset = 524287; + emitSPUpdate(MBB, MBBI, NumBytes, TII); + } + + MI.getOperand(i).ChangeToImmediate(Offset); } }