mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-11 05:35:11 +00:00
Model ARM predicated write as read-mod-write. e.g.
r0 = mov #0 r0 = moveq #1 Then the second instruction has an implicit data dependency on the first instruction. Sadly I have yet to come up with a small test case that demonstrate the post-ra scheduler taking advantage of this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146583 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e90ac9bce9
commit
020f4106f8
@ -652,9 +652,8 @@ public:
|
||||
/// a given pair of defs which both target the same register. This is usually
|
||||
/// one.
|
||||
virtual unsigned getOutputLatency(const InstrItineraryData *ItinData,
|
||||
const MachineInstr *DefMI1,
|
||||
const MachineInstr *DefMI2,
|
||||
unsigned Reg) const {
|
||||
const MachineInstr *DefMI, unsigned DefIdx,
|
||||
const MachineInstr *DepMI) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -281,8 +281,8 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) {
|
||||
if (Kind == SDep::Anti)
|
||||
DefSU->addPred(SDep(SU, Kind, 0, /*Reg=*/Reg));
|
||||
else {
|
||||
unsigned AOLat = TII->getOutputLatency(InstrItins, MI,
|
||||
DefSU->getInstr(), Reg);
|
||||
unsigned AOLat = TII->getOutputLatency(InstrItins, MI, j,
|
||||
DefSU->getInstr());
|
||||
DefSU->addPred(SDep(SU, Kind, AOLat, /*Reg=*/Reg));
|
||||
}
|
||||
}
|
||||
|
@ -2360,7 +2360,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
||||
}
|
||||
|
||||
static const MachineInstr *getBundledDefMI(const TargetRegisterInfo *TRI,
|
||||
const MachineInstr *MI,
|
||||
const MachineInstr *MI, unsigned Reg,
|
||||
unsigned &DefIdx, unsigned &Dist) {
|
||||
Dist = 0;
|
||||
|
||||
@ -2370,7 +2370,6 @@ static const MachineInstr *getBundledDefMI(const TargetRegisterInfo *TRI,
|
||||
assert(II->isInsideBundle() && "Empty bundle?");
|
||||
|
||||
int Idx = -1;
|
||||
unsigned Reg = MI->getOperand(DefIdx).getReg();
|
||||
while (II->isInsideBundle()) {
|
||||
Idx = II->findRegisterDefOperandIdx(Reg, false, true, TRI);
|
||||
if (Idx != -1)
|
||||
@ -2385,7 +2384,7 @@ static const MachineInstr *getBundledDefMI(const TargetRegisterInfo *TRI,
|
||||
}
|
||||
|
||||
static const MachineInstr *getBundledUseMI(const TargetRegisterInfo *TRI,
|
||||
const MachineInstr *MI,
|
||||
const MachineInstr *MI, unsigned Reg,
|
||||
unsigned &UseIdx, unsigned &Dist) {
|
||||
Dist = 0;
|
||||
|
||||
@ -2395,7 +2394,6 @@ static const MachineInstr *getBundledUseMI(const TargetRegisterInfo *TRI,
|
||||
|
||||
// FIXME: This doesn't properly handle multiple uses.
|
||||
int Idx = -1;
|
||||
unsigned Reg = MI->getOperand(UseIdx).getReg();
|
||||
while (II != E && II->isInsideBundle()) {
|
||||
Idx = II->findRegisterUseOperandIdx(Reg, false, TRI);
|
||||
if (Idx != -1)
|
||||
@ -2405,7 +2403,11 @@ static const MachineInstr *getBundledUseMI(const TargetRegisterInfo *TRI,
|
||||
++II;
|
||||
}
|
||||
|
||||
assert(Idx != -1 && "Cannot find bundled definition!");
|
||||
if (Idx == -1) {
|
||||
Dist = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
UseIdx = Idx;
|
||||
return II;
|
||||
}
|
||||
@ -2424,7 +2426,8 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
||||
const MCInstrDesc *DefMCID = &DefMI->getDesc();
|
||||
const MCInstrDesc *UseMCID = &UseMI->getDesc();
|
||||
const MachineOperand &DefMO = DefMI->getOperand(DefIdx);
|
||||
if (DefMO.getReg() == ARM::CPSR) {
|
||||
unsigned Reg = DefMO.getReg();
|
||||
if (Reg == ARM::CPSR) {
|
||||
if (DefMI->getOpcode() == ARM::FMSTAT) {
|
||||
// fpscr -> cpsr stalls over 20 cycles on A8 (and earlier?)
|
||||
return Subtarget.isCortexA9() ? 1 : 20;
|
||||
@ -2436,11 +2439,16 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
||||
|
||||
// Otherwise it takes the instruction latency (generally one).
|
||||
int Latency = getInstrLatency(ItinData, DefMI);
|
||||
// For Thumb2, prefer scheduling CPSR setting instruction close to its uses.
|
||||
// Instructions which are otherwise scheduled between them may incur a code
|
||||
// size penalty (not able to use the CPSR setting 16-bit instructions).
|
||||
if (Latency > 0 && Subtarget.isThumb2())
|
||||
--Latency;
|
||||
|
||||
// For Thumb2 and -Os, prefer scheduling CPSR setting instruction close to
|
||||
// its uses. Instructions which are otherwise scheduled between them may
|
||||
// incur a code size penalty (not able to use the CPSR setting 16-bit
|
||||
// instructions).
|
||||
if (Latency > 0 && Subtarget.isThumb2()) {
|
||||
const MachineFunction *MF = DefMI->getParent()->getParent();
|
||||
if (MF->getFunction()->hasFnAttr(Attribute::OptimizeForSize))
|
||||
--Latency;
|
||||
}
|
||||
return Latency;
|
||||
}
|
||||
|
||||
@ -2451,7 +2459,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
||||
|
||||
unsigned DefAdj = 0;
|
||||
if (DefMI->isBundle()) {
|
||||
DefMI = getBundledDefMI(&getRegisterInfo(), DefMI, DefIdx, DefAdj);
|
||||
DefMI = getBundledDefMI(&getRegisterInfo(), DefMI, Reg, DefIdx, DefAdj);
|
||||
if (DefMI->isCopyLike() || DefMI->isInsertSubreg() ||
|
||||
DefMI->isRegSequence() || DefMI->isImplicitDef())
|
||||
return 1;
|
||||
@ -2459,8 +2467,14 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
||||
}
|
||||
unsigned UseAdj = 0;
|
||||
if (UseMI->isBundle()) {
|
||||
UseMI = getBundledUseMI(&getRegisterInfo(), UseMI, UseIdx, UseAdj);
|
||||
UseMCID = &UseMI->getDesc();
|
||||
unsigned NewUseIdx;
|
||||
const MachineInstr *NewUseMI = getBundledUseMI(&getRegisterInfo(), UseMI,
|
||||
Reg, NewUseIdx, UseAdj);
|
||||
if (NewUseMI) {
|
||||
UseMI = NewUseMI;
|
||||
UseIdx = NewUseIdx;
|
||||
UseMCID = &UseMI->getDesc();
|
||||
}
|
||||
}
|
||||
|
||||
int Latency = getOperandLatency(ItinData, *DefMCID, DefIdx, DefAlign,
|
||||
@ -2797,6 +2811,19 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
||||
return Latency;
|
||||
}
|
||||
|
||||
unsigned
|
||||
ARMBaseInstrInfo::getOutputLatency(const InstrItineraryData *ItinData,
|
||||
const MachineInstr *DefMI, unsigned DefIdx,
|
||||
const MachineInstr *DepMI) const {
|
||||
unsigned Reg = DefMI->getOperand(DefIdx).getReg();
|
||||
if (DepMI->readsRegister(Reg, &getRegisterInfo()) || !isPredicated(DepMI))
|
||||
return 1;
|
||||
|
||||
// If the second MI is predicated, then there is an implicit use dependency.
|
||||
return getOperandLatency(ItinData, DefMI, DefIdx, DepMI,
|
||||
DepMI->getNumOperands());
|
||||
}
|
||||
|
||||
int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
|
||||
const MachineInstr *MI,
|
||||
unsigned *PredCost) const {
|
||||
|
@ -210,6 +210,10 @@ public:
|
||||
SDNode *DefNode, unsigned DefIdx,
|
||||
SDNode *UseNode, unsigned UseIdx) const;
|
||||
|
||||
virtual unsigned getOutputLatency(const InstrItineraryData *ItinData,
|
||||
const MachineInstr *DefMI, unsigned DefIdx,
|
||||
const MachineInstr *DepMI) const;
|
||||
|
||||
/// VFP/NEON execution domains.
|
||||
std::pair<uint16_t, uint16_t>
|
||||
getExecutionDomain(const MachineInstr *MI) const;
|
||||
|
Loading…
Reference in New Issue
Block a user