mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
During PEI, if the immediate value of sp + offset is too large (i.e. something
that would require > 3 instructions to materialize), load the immediate from a constpool entry. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33667 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
db43c63389
commit
36640905e1
@ -18,14 +18,16 @@
|
|||||||
#include "ARMMachineFunctionInfo.h"
|
#include "ARMMachineFunctionInfo.h"
|
||||||
#include "ARMRegisterInfo.h"
|
#include "ARMRegisterInfo.h"
|
||||||
#include "ARMSubtarget.h"
|
#include "ARMSubtarget.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/Constants.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/CodeGen/MachineLocation.h"
|
#include "llvm/CodeGen/MachineLocation.h"
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
#include "llvm/Type.h"
|
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -281,7 +283,7 @@ bool ARMRegisterInfo::hasFP(const MachineFunction &MF) const {
|
|||||||
return NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects();
|
return NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emitARMRegPlusImmediate - Emit a series of instructions to materialize
|
/// emitARMRegPlusImmediate - Emits a series of instructions to materialize
|
||||||
/// a destreg = basereg + immediate in ARM code.
|
/// a destreg = basereg + immediate in ARM code.
|
||||||
static
|
static
|
||||||
void emitARMRegPlusImmediate(MachineBasicBlock &MBB,
|
void emitARMRegPlusImmediate(MachineBasicBlock &MBB,
|
||||||
@ -323,7 +325,70 @@ static bool isLowRegister(unsigned Reg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emitThumbRegPlusImmediate - Emit a series of instructions to materialize
|
/// calcNumMI - Returns the number of instructions required to materialize
|
||||||
|
/// the specific add / sub r, c instruction.
|
||||||
|
static unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes,
|
||||||
|
unsigned NumBits, unsigned Scale) {
|
||||||
|
unsigned NumMIs = 0;
|
||||||
|
unsigned Chunk = ((1 << NumBits) - 1) * Scale;
|
||||||
|
|
||||||
|
if (Opc == ARM::tADDrSPi) {
|
||||||
|
unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
|
||||||
|
Bytes -= ThisVal;
|
||||||
|
NumMIs++;
|
||||||
|
NumBits = 8;
|
||||||
|
Scale = 1;
|
||||||
|
Chunk = ((1 << NumBits) - 1) * Scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
NumMIs += Bytes / Chunk;
|
||||||
|
if ((Bytes % Chunk) != 0)
|
||||||
|
NumMIs++;
|
||||||
|
if (ExtraOpc)
|
||||||
|
NumMIs++;
|
||||||
|
return NumMIs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitThumbRegPlusConstPool - Emits a series of instructions to materialize
|
||||||
|
/// a destreg = basereg + immediate in Thumb code. Load the immediate from a
|
||||||
|
/// constpool entry.
|
||||||
|
static
|
||||||
|
void emitThumbRegPlusConstPool(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator &MBBI,
|
||||||
|
unsigned DestReg, unsigned BaseReg,
|
||||||
|
int NumBytes, const TargetInstrInfo &TII) {
|
||||||
|
MachineFunction &MF = *MBB.getParent();
|
||||||
|
MachineConstantPool *ConstantPool = MF.getConstantPool();
|
||||||
|
bool isHigh = !isLowRegister(DestReg) || !isLowRegister(BaseReg);
|
||||||
|
bool isSub = false;
|
||||||
|
// Subtract doesn't have high register version. Load the negative value
|
||||||
|
// if either base or dest register is a high register.
|
||||||
|
if (NumBytes < 0 && !isHigh) {
|
||||||
|
isSub = true;
|
||||||
|
NumBytes = -NumBytes;
|
||||||
|
}
|
||||||
|
Constant *C = ConstantInt::get(Type::Int32Ty, NumBytes);
|
||||||
|
unsigned Idx = ConstantPool->getConstantPoolIndex(C, 2);
|
||||||
|
unsigned LdReg = DestReg;
|
||||||
|
if (DestReg == ARM::SP) {
|
||||||
|
assert(BaseReg == ARM::SP && "Unexpected!");
|
||||||
|
LdReg = ARM::R3;
|
||||||
|
BuildMI(MBB, MBBI, TII.get(ARM::tMOVrr), ARM::R12).addReg(ARM::R3);
|
||||||
|
}
|
||||||
|
// Load the constant.
|
||||||
|
BuildMI(MBB, MBBI, TII.get(ARM::tLDRpci), LdReg).addConstantPoolIndex(Idx);
|
||||||
|
// Emit add / sub.
|
||||||
|
int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr);
|
||||||
|
const MachineInstrBuilder MIB = BuildMI(MBB, MBBI, TII.get(Opc), DestReg);
|
||||||
|
if (DestReg == ARM::SP)
|
||||||
|
MIB.addReg(BaseReg).addReg(LdReg);
|
||||||
|
else
|
||||||
|
MIB.addReg(LdReg).addReg(BaseReg);
|
||||||
|
if (DestReg == ARM::SP)
|
||||||
|
BuildMI(MBB, MBBI, TII.get(ARM::tMOVrr), ARM::R3).addReg(ARM::R12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize
|
||||||
/// a destreg = basereg + immediate in Thumb code.
|
/// a destreg = basereg + immediate in Thumb code.
|
||||||
static
|
static
|
||||||
void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
||||||
@ -335,10 +400,11 @@ void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
|||||||
if (isSub) Bytes = -NumBytes;
|
if (isSub) Bytes = -NumBytes;
|
||||||
bool isMul4 = (Bytes & 3) == 0;
|
bool isMul4 = (Bytes & 3) == 0;
|
||||||
bool isTwoAddr = false;
|
bool isTwoAddr = false;
|
||||||
|
bool DstNeBase = false;
|
||||||
unsigned NumBits = 1;
|
unsigned NumBits = 1;
|
||||||
unsigned Scale = 1;
|
unsigned Scale = 1;
|
||||||
unsigned Opc = 0;
|
int Opc = 0;
|
||||||
unsigned ExtraOpc = 0;
|
int ExtraOpc = 0;
|
||||||
|
|
||||||
if (DestReg == BaseReg && BaseReg == ARM::SP) {
|
if (DestReg == BaseReg && BaseReg == ARM::SP) {
|
||||||
assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
|
assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
|
||||||
@ -359,24 +425,39 @@ void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
|||||||
Scale = 4;
|
Scale = 4;
|
||||||
Opc = ARM::tADDrSPi;
|
Opc = ARM::tADDrSPi;
|
||||||
} else {
|
} else {
|
||||||
if (DestReg != BaseReg) {
|
// sp = sub sp, c
|
||||||
if (isLowRegister(DestReg) && isLowRegister(BaseReg)) {
|
// r1 = sub sp, c
|
||||||
// If both are low registers, emit DestReg = add BaseReg, max(Imm, 7)
|
// r8 = sub sp, c
|
||||||
unsigned Chunk = (1 << 3) - 1;
|
if (DestReg != BaseReg)
|
||||||
unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
|
DstNeBase = true;
|
||||||
Bytes -= ThisVal;
|
|
||||||
BuildMI(MBB, MBBI, TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3), DestReg)
|
|
||||||
.addReg(BaseReg).addImm(ThisVal);
|
|
||||||
} else {
|
|
||||||
BuildMI(MBB, MBBI, TII.get(ARM::tMOVrr), DestReg).addReg(BaseReg);
|
|
||||||
}
|
|
||||||
BaseReg = DestReg;
|
|
||||||
}
|
|
||||||
NumBits = 8;
|
NumBits = 8;
|
||||||
Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
|
Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
|
||||||
isTwoAddr = true;
|
isTwoAddr = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale);
|
||||||
|
unsigned Threshold = (DestReg == ARM::SP) ? 4 : 3;
|
||||||
|
if (NumMIs > Threshold) {
|
||||||
|
// This will expand into too many instructions. Load the immediate from a
|
||||||
|
// constpool entry.
|
||||||
|
emitThumbRegPlusConstPool(MBB, MBBI, DestReg, BaseReg, NumBytes, TII);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DstNeBase) {
|
||||||
|
if (isLowRegister(DestReg) && isLowRegister(BaseReg)) {
|
||||||
|
// If both are low registers, emit DestReg = add BaseReg, max(Imm, 7)
|
||||||
|
unsigned Chunk = (1 << 3) - 1;
|
||||||
|
unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
|
||||||
|
Bytes -= ThisVal;
|
||||||
|
BuildMI(MBB, MBBI, TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3), DestReg)
|
||||||
|
.addReg(BaseReg).addImm(ThisVal);
|
||||||
|
} else {
|
||||||
|
BuildMI(MBB, MBBI, TII.get(ARM::tMOVrr), DestReg).addReg(BaseReg);
|
||||||
|
}
|
||||||
|
BaseReg = DestReg;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned Chunk = ((1 << NumBits) - 1) * Scale;
|
unsigned Chunk = ((1 << NumBits) - 1) * Scale;
|
||||||
while (Bytes) {
|
while (Bytes) {
|
||||||
unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
|
unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes;
|
||||||
@ -643,7 +724,7 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, it didn't fit. Pull in what we can to simplify the immediate.
|
// Otherwise, it didn't fit. Pull in what we can to simplify the immediate.
|
||||||
if (AddrMode == ARMII::AddrModeTs) {
|
if (AddrMode == ARMII::AddrModeTs) {
|
||||||
// Thumb tLDRspi, tSTRspi. These will change to instructions that use a
|
// Thumb tLDRspi, tSTRspi. These will change to instructions that use a
|
||||||
// different base register.
|
// different base register.
|
||||||
|
Loading…
Reference in New Issue
Block a user