[mips][msa] Add DLSA instruction.
[oota-llvm.git] / lib / Target / AArch64 / AArch64RegisterInfo.cpp
index ee34d76145c2c332cfff5b350f59b7451024a1dc..06e1ffbac51899e85a3d8cdb5926382d35d3cad8 100644 (file)
 #include "AArch64MachineFunctionInfo.h"
 #include "AArch64TargetMachine.h"
 #include "MCTargetDesc/AArch64MCTargetDesc.h"
+#include "llvm/ADT/BitVector.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/RegisterScavenging.h"
-#include "llvm/ADT/BitVector.h"
 
 #define GET_REGINFO_TARGET_DESC
 #include "AArch64GenRegisterInfo.inc"
 
 using namespace llvm;
 
-AArch64RegisterInfo::AArch64RegisterInfo(const AArch64InstrInfo &tii,
-                                         const AArch64Subtarget &sti)
-  : AArch64GenRegisterInfo(AArch64::X30), TII(tii) {
+AArch64RegisterInfo::AArch64RegisterInfo()
+  : AArch64GenRegisterInfo(AArch64::X30) {
 }
 
 const uint16_t *
@@ -77,6 +76,15 @@ AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   return Reserved;
 }
 
+static bool hasFrameOffset(int opcode) {
+  return opcode != AArch64::LD1x2_8B  && opcode != AArch64::LD1x3_8B  &&
+         opcode != AArch64::LD1x4_8B  && opcode != AArch64::ST1x2_8B  &&
+         opcode != AArch64::ST1x3_8B  && opcode != AArch64::ST1x4_8B  &&
+         opcode != AArch64::LD1x2_16B && opcode != AArch64::LD1x3_16B &&
+         opcode != AArch64::LD1x4_16B && opcode != AArch64::ST1x2_16B &&
+         opcode != AArch64::ST1x3_16B && opcode != AArch64::ST1x4_16B;
+}
+
 void
 AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI,
                                          int SPAdj,
@@ -111,8 +119,10 @@ AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI,
   int64_t Offset;
   Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj,
                                            IsCalleeSaveOp);
-
-  Offset += MI.getOperand(FIOperandNum + 1).getImm();
+  // A vector load/store instruction doesn't have an offset operand.
+  bool HasOffsetOp = hasFrameOffset(MI.getOpcode());
+  if (HasOffsetOp)
+    Offset += MI.getOperand(FIOperandNum + 1).getImm();
 
   // DBG_VALUE instructions have no real restrictions so they can be handled
   // easily.
@@ -122,8 +132,10 @@ AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI,
     return;
   }
 
+  const AArch64InstrInfo &TII =
+    *static_cast<const AArch64InstrInfo*>(MF.getTarget().getInstrInfo());
   int MinOffset, MaxOffset, OffsetScale;
-  if (MI.getOpcode() == AArch64::ADDxxi_lsl0_s) {
+  if (MI.getOpcode() == AArch64::ADDxxi_lsl0_s || !HasOffsetOp) {
     MinOffset = 0;
     MaxOffset = 0xfff;
     OffsetScale = 1;
@@ -132,10 +144,12 @@ AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI,
     TII.getAddressConstraints(MI, OffsetScale, MinOffset, MaxOffset);
   }
 
-  // The frame lowering has told us a base and offset it thinks we should use to
-  // access this variable, but it's still up to us to make sure the values are
-  // legal for the instruction in question.
-  if (Offset % OffsetScale != 0 || Offset < MinOffset || Offset > MaxOffset) {
+  // There are two situations we don't use frame + offset directly in the
+  // instruction:
+  // (1) The offset can't really be scaled
+  // (2) Can't encode offset as it doesn't have an offset operand
+  if ((Offset % OffsetScale != 0 || Offset < MinOffset || Offset > MaxOffset) ||
+      (!HasOffsetOp && Offset != 0)) {
     unsigned BaseReg =
       MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
     emitRegUpdate(MBB, MBBI, MBBI->getDebugLoc(), TII,
@@ -149,45 +163,8 @@ AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI,
   assert(Offset >= 0 && "Unexpected negative offset from SP");
 
   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, true);
-  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset / OffsetScale);
-}
-
-void
-AArch64RegisterInfo::eliminateCallFramePseudoInstr(MachineFunction &MF,
-                                         MachineBasicBlock &MBB,
-                                         MachineBasicBlock::iterator MI) const {
-  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
-  DebugLoc dl = MI->getDebugLoc();
-  int Opcode = MI->getOpcode();
-  bool IsDestroy = Opcode == TII.getCallFrameDestroyOpcode();
-  uint64_t CalleePopAmount = IsDestroy ? MI->getOperand(1).getImm() : 0;
-
-  if (!TFI->hasReservedCallFrame(MF)) {
-    unsigned Align = TFI->getStackAlignment();
-
-    int64_t Amount = MI->getOperand(0).getImm();
-    Amount = RoundUpToAlignment(Amount, Align);
-    if (!IsDestroy) Amount = -Amount;
-
-    // N.b. if CalleePopAmount is valid but zero (i.e. callee would pop, but it
-    // doesn't have to pop anything), then the first operand will be zero too so
-    // this adjustment is a no-op.
-    if (CalleePopAmount == 0) {
-      // FIXME: in-function stack adjustment for calls is limited to 12-bits
-      // because there's no guaranteed temporary register available. Mostly call
-      // frames will be allocated at the start of a function so this is OK, but
-      // it is a limitation that needs dealing with.
-      assert(Amount > -0xfff && Amount < 0xfff && "call frame too large");
-      emitSPUpdate(MBB, MI, dl, TII, AArch64::NoRegister, Amount);
-    }
-  } else if (CalleePopAmount != 0) {
-    // If the calling convention demands that the callee pops arguments from the
-    // stack, we want to add it back if we have a reserved call frame.
-    assert(CalleePopAmount < 0xfff && "call frame too large");
-    emitSPUpdate(MBB, MI, dl, TII, AArch64::NoRegister, -CalleePopAmount);
-  }
-
-  MBB.erase(MI);
+  if (HasOffsetOp)
+    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset / OffsetScale);
 }
 
 unsigned