Handle long-disp stuff more consistently
authorAnton Korobeynikov <asl@math.spbu.ru>
Thu, 16 Jul 2009 14:33:52 +0000 (14:33 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Thu, 16 Jul 2009 14:33:52 +0000 (14:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76059 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SystemZ/SystemZInstrInfo.cpp
lib/Target/SystemZ/SystemZInstrInfo.h
lib/Target/SystemZ/SystemZRegisterInfo.cpp

index 914d333c34caf5a4b2cb051858e8b573c3ce2c36..c54ce530c04f0e21d5566dc2d9c47513671441ed 100644 (file)
@@ -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");
   }
 }
 
index 0ef3ca93beacf2945cc894025413692e850edacf..ba94cede00d373fbcda988e2f8495a25275e9e0e 100644 (file)
@@ -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);
+  }
 };
 
 }
index c829e43fb1774ef5ed881a7793778879b8a8daa9..643d681563dda5325ad0efb8be191437af376bb8 100644 (file)
@@ -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);
   }
 }