#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 *
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,
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.
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;
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,
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