mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 06:29:05 +00:00
Better handling of offsets on frame index references. rdar://8277890
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@111585 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -636,6 +636,12 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getFrameIndexInstrOffset - Get the offset from the referenced frame
|
||||||
|
/// index in the instruction, if the is one.
|
||||||
|
virtual int64_t getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// needsFrameBaseReg - Returns true if the instruction's frame index
|
/// needsFrameBaseReg - Returns true if the instruction's frame index
|
||||||
/// reference would be better served by a base register other than FP
|
/// reference would be better served by a base register other than FP
|
||||||
/// or SP. Used by LocalStackFrameAllocation to determine which frame index
|
/// or SP. Used by LocalStackFrameAllocation to determine which frame index
|
||||||
@@ -647,8 +653,8 @@ public:
|
|||||||
/// materializeFrameBaseRegister - Insert defining instruction(s) for
|
/// materializeFrameBaseRegister - Insert defining instruction(s) for
|
||||||
/// BaseReg to be a pointer to FrameIdx before insertion point I.
|
/// BaseReg to be a pointer to FrameIdx before insertion point I.
|
||||||
virtual void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
|
virtual void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
|
||||||
unsigned BaseReg,
|
unsigned BaseReg, int FrameIdx,
|
||||||
int FrameIdx) const {
|
int64_t Offset) const {
|
||||||
assert(0 && "materializeFrameBaseRegister does not exist on this target");
|
assert(0 && "materializeFrameBaseRegister does not exist on this target");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,11 +665,11 @@ public:
|
|||||||
assert(0 && "resolveFrameIndex does not exist on this target");
|
assert(0 && "resolveFrameIndex does not exist on this target");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isBaseRegInRange - Determine whether a given base register definition
|
/// isFrameOffsetLegal - Determine whether a given offset immediate is
|
||||||
/// is in range to resolve a frame index.
|
/// encodable to resolve a frame index.
|
||||||
virtual bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg,
|
virtual bool isFrameOffsetLegal(const MachineInstr *MI,
|
||||||
int64_t Offset) const {
|
int64_t Offset) const {
|
||||||
assert(0 && "isBaseRegInRange does not exist on this target");
|
assert(0 && "isFrameOffsetLegal does not exist on this target");
|
||||||
return false; // Must return a value in order to compile with VS 2005
|
return false; // Must return a value in order to compile with VS 2005
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -182,7 +182,7 @@ lookupCandidateBaseReg(const SmallVector<std::pair<unsigned, int64_t>, 8> &Regs,
|
|||||||
// Check if the relative offset from the where the base register references
|
// Check if the relative offset from the where the base register references
|
||||||
// to the target address is in range for the instruction.
|
// to the target address is in range for the instruction.
|
||||||
int64_t Offset = LocalFrameOffset - RegOffset.second;
|
int64_t Offset = LocalFrameOffset - RegOffset.second;
|
||||||
if (TRI->isBaseRegInRange(MI, RegOffset.first, Offset))
|
if (TRI->isFrameOffsetLegal(MI, Offset))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -225,6 +225,7 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
|
|||||||
// an object allocated in the local block.
|
// an object allocated in the local block.
|
||||||
if (MI->getOperand(i).isFI()) {
|
if (MI->getOperand(i).isFI()) {
|
||||||
int FrameIdx = MI->getOperand(i).getIndex();
|
int FrameIdx = MI->getOperand(i).getIndex();
|
||||||
|
|
||||||
// Don't try this with values not in the local block.
|
// Don't try this with values not in the local block.
|
||||||
if (!MFI->isObjectPreAllocated(FrameIdx))
|
if (!MFI->isObjectPreAllocated(FrameIdx))
|
||||||
continue;
|
continue;
|
||||||
@@ -232,13 +233,15 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
|
|||||||
DEBUG(dbgs() << "Considering: " << *MI);
|
DEBUG(dbgs() << "Considering: " << *MI);
|
||||||
if (TRI->needsFrameBaseReg(MI, i)) {
|
if (TRI->needsFrameBaseReg(MI, i)) {
|
||||||
unsigned BaseReg = 0;
|
unsigned BaseReg = 0;
|
||||||
unsigned Offset = 0;
|
int64_t Offset = 0;
|
||||||
|
|
||||||
DEBUG(dbgs() << " Replacing FI in: " << *MI);
|
DEBUG(dbgs() << " Replacing FI in: " << *MI);
|
||||||
|
|
||||||
// If we have a suitable base register available, use it; otherwise
|
// If we have a suitable base register available, use it; otherwise
|
||||||
// create a new one.
|
// create a new one. Note that any offset encoded in the
|
||||||
|
// instruction itself will be taken into account by the target,
|
||||||
|
// so we don't have to adjust for it here when reusing a base
|
||||||
|
// register.
|
||||||
std::pair<unsigned, int64_t> RegOffset;
|
std::pair<unsigned, int64_t> RegOffset;
|
||||||
if (lookupCandidateBaseReg(BaseRegisters, RegOffset,
|
if (lookupCandidateBaseReg(BaseRegisters, RegOffset,
|
||||||
LocalOffsets[FrameIdx], MI, TRI)) {
|
LocalOffsets[FrameIdx], MI, TRI)) {
|
||||||
@@ -250,15 +253,26 @@ void LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) {
|
|||||||
} else {
|
} else {
|
||||||
// No previously defined register was in range, so create a
|
// No previously defined register was in range, so create a
|
||||||
// new one.
|
// new one.
|
||||||
|
int64_t InstrOffset = TRI->getFrameIndexInstrOffset(MI, i);
|
||||||
const TargetRegisterClass *RC = TRI->getPointerRegClass();
|
const TargetRegisterClass *RC = TRI->getPointerRegClass();
|
||||||
BaseReg = Fn.getRegInfo().createVirtualRegister(RC);
|
BaseReg = Fn.getRegInfo().createVirtualRegister(RC);
|
||||||
|
|
||||||
|
DEBUG(dbgs() << " Materializing base register " << BaseReg <<
|
||||||
|
" at frame local offset " <<
|
||||||
|
LocalOffsets[FrameIdx] + InstrOffset << "\n");
|
||||||
// Tell the target to insert the instruction to initialize
|
// Tell the target to insert the instruction to initialize
|
||||||
// the base register.
|
// the base register.
|
||||||
TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx);
|
TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx,
|
||||||
|
InstrOffset);
|
||||||
|
|
||||||
BaseRegisters.push_back(std::pair<unsigned, int64_t>(BaseReg,
|
// The base register already includes any offset specified
|
||||||
Offset));
|
// by the instruction, so account for that so it doesn't get
|
||||||
|
// applied twice.
|
||||||
|
Offset = -InstrOffset;
|
||||||
|
|
||||||
|
BaseRegisters.push_back(
|
||||||
|
std::pair<unsigned, int64_t>(BaseReg,
|
||||||
|
LocalOffsets[FrameIdx] + InstrOffset));
|
||||||
++NumBaseRegisters;
|
++NumBaseRegisters;
|
||||||
}
|
}
|
||||||
assert(BaseReg != 0 && "Unable to allocate virtual base register!");
|
assert(BaseReg != 0 && "Unable to allocate virtual base register!");
|
||||||
|
@@ -1367,6 +1367,59 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
|||||||
MBB.erase(I);
|
MBB.erase(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64_t ARMBaseRegisterInfo::
|
||||||
|
getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const {
|
||||||
|
const TargetInstrDesc &Desc = MI->getDesc();
|
||||||
|
unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
|
||||||
|
int64_t InstrOffs = 0;;
|
||||||
|
int Scale = 1;
|
||||||
|
unsigned ImmIdx = 0;
|
||||||
|
switch(AddrMode) {
|
||||||
|
case ARMII::AddrModeT2_i8:
|
||||||
|
case ARMII::AddrModeT2_i12:
|
||||||
|
// i8 supports only negative, and i12 supports only positive, so
|
||||||
|
// based on Offset sign, consider the appropriate instruction
|
||||||
|
InstrOffs = MI->getOperand(Idx+1).getImm();
|
||||||
|
Scale = 1;
|
||||||
|
break;
|
||||||
|
case ARMII::AddrMode5: {
|
||||||
|
// VFP address mode.
|
||||||
|
const MachineOperand &OffOp = MI->getOperand(Idx+1);
|
||||||
|
int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm());
|
||||||
|
if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub)
|
||||||
|
InstrOffs = -InstrOffs;
|
||||||
|
Scale = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARMII::AddrMode2: {
|
||||||
|
ImmIdx = Idx+2;
|
||||||
|
InstrOffs = ARM_AM::getAM2Offset(MI->getOperand(ImmIdx).getImm());
|
||||||
|
if (ARM_AM::getAM2Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub)
|
||||||
|
InstrOffs = -InstrOffs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARMII::AddrMode3: {
|
||||||
|
ImmIdx = Idx+2;
|
||||||
|
InstrOffs = ARM_AM::getAM3Offset(MI->getOperand(ImmIdx).getImm());
|
||||||
|
if (ARM_AM::getAM3Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub)
|
||||||
|
InstrOffs = -InstrOffs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARMII::AddrModeT1_s: {
|
||||||
|
ImmIdx = Idx+1;
|
||||||
|
InstrOffs = MI->getOperand(ImmIdx).getImm();
|
||||||
|
Scale = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Unsupported addressing mode!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InstrOffs * Scale;
|
||||||
|
}
|
||||||
|
|
||||||
/// needsFrameBaseReg - Returns true if the instruction's frame index
|
/// needsFrameBaseReg - Returns true if the instruction's frame index
|
||||||
/// reference would be better served by a base register other than FP
|
/// reference would be better served by a base register other than FP
|
||||||
/// or SP. Used by LocalStackFrameAllocation to determine which frame index
|
/// or SP. Used by LocalStackFrameAllocation to determine which frame index
|
||||||
@@ -1404,8 +1457,8 @@ needsFrameBaseReg(MachineInstr *MI, unsigned operand) const {
|
|||||||
/// materializeFrameBaseRegister - Insert defining instruction(s) for
|
/// materializeFrameBaseRegister - Insert defining instruction(s) for
|
||||||
/// BaseReg to be a pointer to FrameIdx before insertion point I.
|
/// BaseReg to be a pointer to FrameIdx before insertion point I.
|
||||||
void ARMBaseRegisterInfo::
|
void ARMBaseRegisterInfo::
|
||||||
materializeFrameBaseRegister(MachineBasicBlock::iterator I,
|
materializeFrameBaseRegister(MachineBasicBlock::iterator I, unsigned BaseReg,
|
||||||
unsigned BaseReg, int FrameIdx) const {
|
int FrameIdx, int64_t Offset) const {
|
||||||
ARMFunctionInfo *AFI =
|
ARMFunctionInfo *AFI =
|
||||||
I->getParent()->getParent()->getInfo<ARMFunctionInfo>();
|
I->getParent()->getParent()->getInfo<ARMFunctionInfo>();
|
||||||
unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri :
|
unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri :
|
||||||
@@ -1413,7 +1466,7 @@ materializeFrameBaseRegister(MachineBasicBlock::iterator I,
|
|||||||
|
|
||||||
MachineInstrBuilder MIB =
|
MachineInstrBuilder MIB =
|
||||||
BuildMI(*I->getParent(), I, I->getDebugLoc(), TII.get(ADDriOpc), BaseReg)
|
BuildMI(*I->getParent(), I, I->getDebugLoc(), TII.get(ADDriOpc), BaseReg)
|
||||||
.addFrameIndex(FrameIdx).addImm(0);
|
.addFrameIndex(FrameIdx).addImm(Offset);
|
||||||
if (!AFI->isThumb1OnlyFunction())
|
if (!AFI->isThumb1OnlyFunction())
|
||||||
AddDefaultCC(AddDefaultPred(MIB));
|
AddDefaultCC(AddDefaultPred(MIB));
|
||||||
}
|
}
|
||||||
@@ -1445,8 +1498,8 @@ ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I,
|
|||||||
assert (Done && "Unable to resolve frame index!");
|
assert (Done && "Unable to resolve frame index!");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
|
bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI,
|
||||||
unsigned Reg, int64_t Offset) const {
|
int64_t Offset) const {
|
||||||
const TargetInstrDesc &Desc = MI->getDesc();
|
const TargetInstrDesc &Desc = MI->getDesc();
|
||||||
unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
|
unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
@@ -1464,6 +1517,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
|
|||||||
unsigned Scale = 1;
|
unsigned Scale = 1;
|
||||||
unsigned ImmIdx = 0;
|
unsigned ImmIdx = 0;
|
||||||
int InstrOffs = 0;;
|
int InstrOffs = 0;;
|
||||||
|
bool isSigned = true;
|
||||||
switch(AddrMode) {
|
switch(AddrMode) {
|
||||||
case ARMII::AddrModeT2_i8:
|
case ARMII::AddrModeT2_i8:
|
||||||
case ARMII::AddrModeT2_i12:
|
case ARMII::AddrModeT2_i12:
|
||||||
@@ -1509,6 +1563,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
|
|||||||
InstrOffs = MI->getOperand(ImmIdx).getImm();
|
InstrOffs = MI->getOperand(ImmIdx).getImm();
|
||||||
NumBits = 5;
|
NumBits = 5;
|
||||||
Scale = 4;
|
Scale = 4;
|
||||||
|
isSigned = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -1518,7 +1573,7 @@ bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
|
|||||||
|
|
||||||
Offset += InstrOffs * Scale;
|
Offset += InstrOffs * Scale;
|
||||||
assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
|
assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
|
||||||
if (Offset < 0)
|
if (isSigned && Offset < 0)
|
||||||
Offset = -Offset;
|
Offset = -Offset;
|
||||||
|
|
||||||
unsigned Mask = (1 << NumBits) - 1;
|
unsigned Mask = (1 << NumBits) - 1;
|
||||||
|
@@ -105,13 +105,14 @@ public:
|
|||||||
|
|
||||||
bool canRealignStack(const MachineFunction &MF) const;
|
bool canRealignStack(const MachineFunction &MF) const;
|
||||||
bool needsStackRealignment(const MachineFunction &MF) const;
|
bool needsStackRealignment(const MachineFunction &MF) const;
|
||||||
|
int64_t getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const;
|
||||||
bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const;
|
bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const;
|
||||||
void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
|
void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
|
||||||
unsigned BaseReg, int FrameIdx) const;
|
unsigned BaseReg, int FrameIdx,
|
||||||
|
int64_t Offset) const;
|
||||||
void resolveFrameIndex(MachineBasicBlock::iterator I,
|
void resolveFrameIndex(MachineBasicBlock::iterator I,
|
||||||
unsigned BaseReg, int64_t Offset) const;
|
unsigned BaseReg, int64_t Offset) const;
|
||||||
bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg,
|
bool isFrameOffsetLegal(const MachineInstr *MI, int64_t Offset) const;
|
||||||
int64_t Offset) const;
|
|
||||||
|
|
||||||
bool cannotEliminateFrame(const MachineFunction &MF) const;
|
bool cannotEliminateFrame(const MachineFunction &MF) const;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user