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
|
/// a given pair of defs which both target the same register. This is usually
|
||||||
/// one.
|
/// one.
|
||||||
virtual unsigned getOutputLatency(const InstrItineraryData *ItinData,
|
virtual unsigned getOutputLatency(const InstrItineraryData *ItinData,
|
||||||
const MachineInstr *DefMI1,
|
const MachineInstr *DefMI, unsigned DefIdx,
|
||||||
const MachineInstr *DefMI2,
|
const MachineInstr *DepMI) const {
|
||||||
unsigned Reg) const {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,8 +281,8 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) {
|
|||||||
if (Kind == SDep::Anti)
|
if (Kind == SDep::Anti)
|
||||||
DefSU->addPred(SDep(SU, Kind, 0, /*Reg=*/Reg));
|
DefSU->addPred(SDep(SU, Kind, 0, /*Reg=*/Reg));
|
||||||
else {
|
else {
|
||||||
unsigned AOLat = TII->getOutputLatency(InstrItins, MI,
|
unsigned AOLat = TII->getOutputLatency(InstrItins, MI, j,
|
||||||
DefSU->getInstr(), Reg);
|
DefSU->getInstr());
|
||||||
DefSU->addPred(SDep(SU, Kind, AOLat, /*Reg=*/Reg));
|
DefSU->addPred(SDep(SU, Kind, AOLat, /*Reg=*/Reg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2360,7 +2360,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const MachineInstr *getBundledDefMI(const TargetRegisterInfo *TRI,
|
static const MachineInstr *getBundledDefMI(const TargetRegisterInfo *TRI,
|
||||||
const MachineInstr *MI,
|
const MachineInstr *MI, unsigned Reg,
|
||||||
unsigned &DefIdx, unsigned &Dist) {
|
unsigned &DefIdx, unsigned &Dist) {
|
||||||
Dist = 0;
|
Dist = 0;
|
||||||
|
|
||||||
@ -2370,7 +2370,6 @@ static const MachineInstr *getBundledDefMI(const TargetRegisterInfo *TRI,
|
|||||||
assert(II->isInsideBundle() && "Empty bundle?");
|
assert(II->isInsideBundle() && "Empty bundle?");
|
||||||
|
|
||||||
int Idx = -1;
|
int Idx = -1;
|
||||||
unsigned Reg = MI->getOperand(DefIdx).getReg();
|
|
||||||
while (II->isInsideBundle()) {
|
while (II->isInsideBundle()) {
|
||||||
Idx = II->findRegisterDefOperandIdx(Reg, false, true, TRI);
|
Idx = II->findRegisterDefOperandIdx(Reg, false, true, TRI);
|
||||||
if (Idx != -1)
|
if (Idx != -1)
|
||||||
@ -2385,7 +2384,7 @@ static const MachineInstr *getBundledDefMI(const TargetRegisterInfo *TRI,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const MachineInstr *getBundledUseMI(const TargetRegisterInfo *TRI,
|
static const MachineInstr *getBundledUseMI(const TargetRegisterInfo *TRI,
|
||||||
const MachineInstr *MI,
|
const MachineInstr *MI, unsigned Reg,
|
||||||
unsigned &UseIdx, unsigned &Dist) {
|
unsigned &UseIdx, unsigned &Dist) {
|
||||||
Dist = 0;
|
Dist = 0;
|
||||||
|
|
||||||
@ -2395,7 +2394,6 @@ static const MachineInstr *getBundledUseMI(const TargetRegisterInfo *TRI,
|
|||||||
|
|
||||||
// FIXME: This doesn't properly handle multiple uses.
|
// FIXME: This doesn't properly handle multiple uses.
|
||||||
int Idx = -1;
|
int Idx = -1;
|
||||||
unsigned Reg = MI->getOperand(UseIdx).getReg();
|
|
||||||
while (II != E && II->isInsideBundle()) {
|
while (II != E && II->isInsideBundle()) {
|
||||||
Idx = II->findRegisterUseOperandIdx(Reg, false, TRI);
|
Idx = II->findRegisterUseOperandIdx(Reg, false, TRI);
|
||||||
if (Idx != -1)
|
if (Idx != -1)
|
||||||
@ -2405,7 +2403,11 @@ static const MachineInstr *getBundledUseMI(const TargetRegisterInfo *TRI,
|
|||||||
++II;
|
++II;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Idx != -1 && "Cannot find bundled definition!");
|
if (Idx == -1) {
|
||||||
|
Dist = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
UseIdx = Idx;
|
UseIdx = Idx;
|
||||||
return II;
|
return II;
|
||||||
}
|
}
|
||||||
@ -2424,7 +2426,8 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
|||||||
const MCInstrDesc *DefMCID = &DefMI->getDesc();
|
const MCInstrDesc *DefMCID = &DefMI->getDesc();
|
||||||
const MCInstrDesc *UseMCID = &UseMI->getDesc();
|
const MCInstrDesc *UseMCID = &UseMI->getDesc();
|
||||||
const MachineOperand &DefMO = DefMI->getOperand(DefIdx);
|
const MachineOperand &DefMO = DefMI->getOperand(DefIdx);
|
||||||
if (DefMO.getReg() == ARM::CPSR) {
|
unsigned Reg = DefMO.getReg();
|
||||||
|
if (Reg == ARM::CPSR) {
|
||||||
if (DefMI->getOpcode() == ARM::FMSTAT) {
|
if (DefMI->getOpcode() == ARM::FMSTAT) {
|
||||||
// fpscr -> cpsr stalls over 20 cycles on A8 (and earlier?)
|
// fpscr -> cpsr stalls over 20 cycles on A8 (and earlier?)
|
||||||
return Subtarget.isCortexA9() ? 1 : 20;
|
return Subtarget.isCortexA9() ? 1 : 20;
|
||||||
@ -2436,11 +2439,16 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
|||||||
|
|
||||||
// Otherwise it takes the instruction latency (generally one).
|
// Otherwise it takes the instruction latency (generally one).
|
||||||
int Latency = getInstrLatency(ItinData, DefMI);
|
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
|
// For Thumb2 and -Os, prefer scheduling CPSR setting instruction close to
|
||||||
// size penalty (not able to use the CPSR setting 16-bit instructions).
|
// its uses. Instructions which are otherwise scheduled between them may
|
||||||
if (Latency > 0 && Subtarget.isThumb2())
|
// 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;
|
--Latency;
|
||||||
|
}
|
||||||
return Latency;
|
return Latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2451,7 +2459,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
|||||||
|
|
||||||
unsigned DefAdj = 0;
|
unsigned DefAdj = 0;
|
||||||
if (DefMI->isBundle()) {
|
if (DefMI->isBundle()) {
|
||||||
DefMI = getBundledDefMI(&getRegisterInfo(), DefMI, DefIdx, DefAdj);
|
DefMI = getBundledDefMI(&getRegisterInfo(), DefMI, Reg, DefIdx, DefAdj);
|
||||||
if (DefMI->isCopyLike() || DefMI->isInsertSubreg() ||
|
if (DefMI->isCopyLike() || DefMI->isInsertSubreg() ||
|
||||||
DefMI->isRegSequence() || DefMI->isImplicitDef())
|
DefMI->isRegSequence() || DefMI->isImplicitDef())
|
||||||
return 1;
|
return 1;
|
||||||
@ -2459,9 +2467,15 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
|||||||
}
|
}
|
||||||
unsigned UseAdj = 0;
|
unsigned UseAdj = 0;
|
||||||
if (UseMI->isBundle()) {
|
if (UseMI->isBundle()) {
|
||||||
UseMI = getBundledUseMI(&getRegisterInfo(), UseMI, UseIdx, UseAdj);
|
unsigned NewUseIdx;
|
||||||
|
const MachineInstr *NewUseMI = getBundledUseMI(&getRegisterInfo(), UseMI,
|
||||||
|
Reg, NewUseIdx, UseAdj);
|
||||||
|
if (NewUseMI) {
|
||||||
|
UseMI = NewUseMI;
|
||||||
|
UseIdx = NewUseIdx;
|
||||||
UseMCID = &UseMI->getDesc();
|
UseMCID = &UseMI->getDesc();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int Latency = getOperandLatency(ItinData, *DefMCID, DefIdx, DefAlign,
|
int Latency = getOperandLatency(ItinData, *DefMCID, DefIdx, DefAlign,
|
||||||
*UseMCID, UseIdx, UseAlign);
|
*UseMCID, UseIdx, UseAlign);
|
||||||
@ -2797,6 +2811,19 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
|||||||
return Latency;
|
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,
|
int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
|
||||||
const MachineInstr *MI,
|
const MachineInstr *MI,
|
||||||
unsigned *PredCost) const {
|
unsigned *PredCost) const {
|
||||||
|
@ -210,6 +210,10 @@ public:
|
|||||||
SDNode *DefNode, unsigned DefIdx,
|
SDNode *DefNode, unsigned DefIdx,
|
||||||
SDNode *UseNode, unsigned UseIdx) const;
|
SDNode *UseNode, unsigned UseIdx) const;
|
||||||
|
|
||||||
|
virtual unsigned getOutputLatency(const InstrItineraryData *ItinData,
|
||||||
|
const MachineInstr *DefMI, unsigned DefIdx,
|
||||||
|
const MachineInstr *DepMI) const;
|
||||||
|
|
||||||
/// VFP/NEON execution domains.
|
/// VFP/NEON execution domains.
|
||||||
std::pair<uint16_t, uint16_t>
|
std::pair<uint16_t, uint16_t>
|
||||||
getExecutionDomain(const MachineInstr *MI) const;
|
getExecutionDomain(const MachineInstr *MI) const;
|
||||||
|
Loading…
Reference in New Issue
Block a user