aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Hexagon/HexagonInstrInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Hexagon/HexagonInstrInfo.cpp')
-rw-r--r--lib/Target/Hexagon/HexagonInstrInfo.cpp225
1 files changed, 157 insertions, 68 deletions
diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp
index 0a7dc6b49d00..b265a883da5c 100644
--- a/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -152,10 +152,11 @@ static unsigned nonDbgMICount(MachineBasicBlock::const_instr_iterator MIB,
/// On Hexagon, we have two instructions used to set-up the hardware loop
/// (LOOP0, LOOP1) with corresponding endloop (ENDLOOP0, ENDLOOP1) instructions
/// to indicate the end of a loop.
-static MachineInstr *findLoopInstr(MachineBasicBlock *BB, int EndLoopOp,
+static MachineInstr *findLoopInstr(MachineBasicBlock *BB, unsigned EndLoopOp,
+ MachineBasicBlock *TargetBB,
SmallPtrSet<MachineBasicBlock *, 8> &Visited) {
- int LOOPi;
- int LOOPr;
+ unsigned LOOPi;
+ unsigned LOOPr;
if (EndLoopOp == Hexagon::ENDLOOP0) {
LOOPi = Hexagon::J2_loop0i;
LOOPr = Hexagon::J2_loop0r;
@@ -165,26 +166,24 @@ static MachineInstr *findLoopInstr(MachineBasicBlock *BB, int EndLoopOp,
}
// The loop set-up instruction will be in a predecessor block
- for (MachineBasicBlock::pred_iterator PB = BB->pred_begin(),
- PE = BB->pred_end(); PB != PE; ++PB) {
+ for (MachineBasicBlock *PB : BB->predecessors()) {
// If this has been visited, already skip it.
- if (!Visited.insert(*PB).second)
+ if (!Visited.insert(PB).second)
continue;
- if (*PB == BB)
+ if (PB == BB)
continue;
- for (MachineBasicBlock::reverse_instr_iterator I = (*PB)->instr_rbegin(),
- E = (*PB)->instr_rend(); I != E; ++I) {
- int Opc = I->getOpcode();
+ for (auto I = PB->instr_rbegin(), E = PB->instr_rend(); I != E; ++I) {
+ unsigned Opc = I->getOpcode();
if (Opc == LOOPi || Opc == LOOPr)
return &*I;
- // We've reached a different loop, which means the loop0 has been removed.
- if (Opc == EndLoopOp)
+ // We've reached a different loop, which means the loop01 has been
+ // removed.
+ if (Opc == EndLoopOp && I->getOperand(0).getMBB() != TargetBB)
return nullptr;
}
// Check the predecessors for the LOOP instruction.
- MachineInstr *loop = findLoopInstr(*PB, EndLoopOp, Visited);
- if (loop)
- return loop;
+ if (MachineInstr *Loop = findLoopInstr(PB, EndLoopOp, TargetBB, Visited))
+ return Loop;
}
return nullptr;
}
@@ -597,7 +596,8 @@ unsigned HexagonInstrInfo::insertBranch(MachineBasicBlock &MBB,
// Since we're adding an ENDLOOP, there better be a LOOP instruction.
// Check for it, and change the BB target if needed.
SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs;
- MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, VisitedBBs);
+ MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, Cond[1].getMBB(),
+ VisitedBBs);
assert(Loop != 0 && "Inserting an ENDLOOP without a LOOP");
Loop->getOperand(0).setMBB(TBB);
// Add the ENDLOOP after the finding the LOOP0.
@@ -637,7 +637,8 @@ unsigned HexagonInstrInfo::insertBranch(MachineBasicBlock &MBB,
// Since we're adding an ENDLOOP, there better be a LOOP instruction.
// Check for it, and change the BB target if needed.
SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs;
- MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, VisitedBBs);
+ MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, Cond[1].getMBB(),
+ VisitedBBs);
assert(Loop != 0 && "Inserting an ENDLOOP without a LOOP");
Loop->getOperand(0).setMBB(TBB);
// Add the ENDLOOP after the finding the LOOP0.
@@ -687,7 +688,8 @@ unsigned HexagonInstrInfo::reduceLoopCount(MachineBasicBlock &MBB,
MachineFunction *MF = MBB.getParent();
DebugLoc DL = Cmp.getDebugLoc();
SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs;
- MachineInstr *Loop = findLoopInstr(&MBB, Cmp.getOpcode(), VisitedBBs);
+ MachineInstr *Loop = findLoopInstr(&MBB, Cmp.getOpcode(),
+ Cmp.getOperand(0).getMBB(), VisitedBBs);
if (!Loop)
return 0;
// If the loop trip count is a compile-time value, then just change the
@@ -1074,13 +1076,13 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
unsigned Offset = Is128B ? VecOffset << 7 : VecOffset << 6;
MachineInstr *MI1New =
BuildMI(MBB, MI, DL, get(NewOpc))
- .addOperand(MI.getOperand(0))
+ .add(MI.getOperand(0))
.addImm(MI.getOperand(1).getImm())
.addReg(SrcSubLo)
.setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
MI1New->getOperand(0).setIsKill(false);
BuildMI(MBB, MI, DL, get(NewOpc))
- .addOperand(MI.getOperand(0))
+ .add(MI.getOperand(0))
// The Vectors are indexed in multiples of vector size.
.addImm(MI.getOperand(1).getImm() + Offset)
.addReg(SrcSubHi)
@@ -1106,15 +1108,13 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
unsigned DstReg = MI.getOperand(0).getReg();
unsigned Offset = Is128B ? VecOffset << 7 : VecOffset << 6;
- MachineInstr *MI1New =
- BuildMI(MBB, MI, DL, get(NewOpc),
- HRI.getSubReg(DstReg, Hexagon::vsub_lo))
- .addOperand(MI.getOperand(1))
- .addImm(MI.getOperand(2).getImm());
+ MachineInstr *MI1New = BuildMI(MBB, MI, DL, get(NewOpc),
+ HRI.getSubReg(DstReg, Hexagon::vsub_lo))
+ .add(MI.getOperand(1))
+ .addImm(MI.getOperand(2).getImm());
MI1New->getOperand(1).setIsKill(false);
- BuildMI(MBB, MI, DL, get(NewOpc),
- HRI.getSubReg(DstReg, Hexagon::vsub_hi))
- .addOperand(MI.getOperand(1))
+ BuildMI(MBB, MI, DL, get(NewOpc), HRI.getSubReg(DstReg, Hexagon::vsub_hi))
+ .add(MI.getOperand(1))
// The Vectors are indexed in multiples of vector size.
.addImm(MI.getOperand(2).getImm() + Offset)
.setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
@@ -1227,18 +1227,18 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
bool IsDestLive = !LiveAtMI.available(MRI, Op0.getReg());
if (Op0.getReg() != Op2.getReg()) {
auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vcmov))
- .addOperand(Op0)
- .addOperand(Op1)
- .addOperand(Op2);
+ .add(Op0)
+ .add(Op1)
+ .add(Op2);
if (IsDestLive)
T.addReg(Op0.getReg(), RegState::Implicit);
IsDestLive = true;
}
if (Op0.getReg() != Op3.getReg()) {
auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vncmov))
- .addOperand(Op0)
- .addOperand(Op1)
- .addOperand(Op3);
+ .add(Op0)
+ .add(Op1)
+ .add(Op3);
if (IsDestLive)
T.addReg(Op0.getReg(), RegState::Implicit);
}
@@ -1259,10 +1259,10 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
unsigned SrcLo = HRI.getSubReg(Op2.getReg(), Hexagon::vsub_lo);
unsigned SrcHi = HRI.getSubReg(Op2.getReg(), Hexagon::vsub_hi);
auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vccombine))
- .addOperand(Op0)
- .addOperand(Op1)
- .addReg(SrcHi)
- .addReg(SrcLo);
+ .add(Op0)
+ .add(Op1)
+ .addReg(SrcHi)
+ .addReg(SrcLo);
if (IsDestLive)
T.addReg(Op0.getReg(), RegState::Implicit);
IsDestLive = true;
@@ -1271,10 +1271,10 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
unsigned SrcLo = HRI.getSubReg(Op3.getReg(), Hexagon::vsub_lo);
unsigned SrcHi = HRI.getSubReg(Op3.getReg(), Hexagon::vsub_hi);
auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vnccombine))
- .addOperand(Op0)
- .addOperand(Op1)
- .addReg(SrcHi)
- .addReg(SrcLo);
+ .add(Op0)
+ .add(Op1)
+ .addReg(SrcHi)
+ .addReg(SrcLo);
if (IsDestLive)
T.addReg(Op0.getReg(), RegState::Implicit);
}
@@ -1376,7 +1376,7 @@ bool HexagonInstrInfo::PredicateInstruction(
MachineOperand &Op = MI.getOperand(NOp);
if (!Op.isReg() || !Op.isDef() || Op.isImplicit())
break;
- T.addOperand(Op);
+ T.add(Op);
NOp++;
}
@@ -1386,7 +1386,7 @@ bool HexagonInstrInfo::PredicateInstruction(
assert(GotPredReg);
T.addReg(PredReg, PredRegFlags);
while (NOp < NumOps)
- T.addOperand(MI.getOperand(NOp++));
+ T.add(MI.getOperand(NOp++));
MI.setDesc(get(PredOpc));
while (unsigned n = MI.getNumOperands())
@@ -1413,18 +1413,28 @@ bool HexagonInstrInfo::DefinesPredicate(
auto &HRI = getRegisterInfo();
for (unsigned oper = 0; oper < MI.getNumOperands(); ++oper) {
MachineOperand MO = MI.getOperand(oper);
- if (MO.isReg() && MO.isDef()) {
+ if (MO.isReg()) {
+ if (!MO.isDef())
+ continue;
const TargetRegisterClass* RC = HRI.getMinimalPhysRegClass(MO.getReg());
if (RC == &Hexagon::PredRegsRegClass) {
Pred.push_back(MO);
return true;
}
+ continue;
+ } else if (MO.isRegMask()) {
+ for (unsigned PR : Hexagon::PredRegsRegClass) {
+ if (!MI.modifiesRegister(PR, &HRI))
+ continue;
+ Pred.push_back(MO);
+ return true;
+ }
}
}
return false;
}
-bool HexagonInstrInfo::isPredicable(MachineInstr &MI) const {
+bool HexagonInstrInfo::isPredicable(const MachineInstr &MI) const {
return MI.getDesc().isPredicable();
}
@@ -1715,7 +1725,7 @@ bool HexagonInstrInfo::isComplex(const MachineInstr &MI) const {
// Return true if the instruction is a compund branch instruction.
bool HexagonInstrInfo::isCompoundBranchInstr(const MachineInstr &MI) const {
- return (getType(MI) == HexagonII::TypeCOMPOUND && MI.isBranch());
+ return getType(MI) == HexagonII::TypeCJ && MI.isBranch();
}
bool HexagonInstrInfo::isCondInst(const MachineInstr &MI) const {
@@ -3009,10 +3019,12 @@ bool HexagonInstrInfo::producesStall(const MachineInstr &MI,
bool HexagonInstrInfo::predCanBeUsedAsDotNew(const MachineInstr &MI,
unsigned PredReg) const {
- for (unsigned opNum = 0; opNum < MI.getNumOperands(); opNum++) {
- const MachineOperand &MO = MI.getOperand(opNum);
+ for (const MachineOperand &MO : MI.operands()) {
+ // Predicate register must be explicitly defined.
+ if (MO.isRegMask() && MO.clobbersPhysReg(PredReg))
+ return false;
if (MO.isReg() && MO.isDef() && MO.isImplicit() && (MO.getReg() == PredReg))
- return false; // Predicate register must be explicitly defined.
+ return false;
}
// Hexagon Programmer's Reference says that decbin, memw_locked, and
@@ -3415,7 +3427,9 @@ int HexagonInstrInfo::getDotNewOp(const MachineInstr &MI) const {
return NVOpcode;
switch (MI.getOpcode()) {
- default: llvm_unreachable("Unknown .new type");
+ default:
+ llvm::report_fatal_error(std::string("Unknown .new type: ") +
+ std::to_string(MI.getOpcode()).c_str());
case Hexagon::S4_storerb_ur:
return Hexagon::S4_storerbnew_ur;
@@ -3456,20 +3470,75 @@ int HexagonInstrInfo::getDotNewOp(const MachineInstr &MI) const {
int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI,
const MachineBranchProbabilityInfo *MBPI) const {
// We assume that block can have at most two successors.
- bool taken = false;
const MachineBasicBlock *Src = MI.getParent();
const MachineOperand &BrTarget = MI.getOperand(1);
- const MachineBasicBlock *Dst = BrTarget.getMBB();
+ bool Taken = false;
+ const BranchProbability OneHalf(1, 2);
- const BranchProbability Prediction = MBPI->getEdgeProbability(Src, Dst);
- if (Prediction >= BranchProbability(1,2))
- taken = true;
+ if (BrTarget.isMBB()) {
+ const MachineBasicBlock *Dst = BrTarget.getMBB();
+ Taken = MBPI->getEdgeProbability(Src, Dst) >= OneHalf;
+ } else {
+ // The branch target is not a basic block (most likely a function).
+ // Since BPI only gives probabilities for targets that are basic blocks,
+ // try to identify another target of this branch (potentially a fall-
+ // -through) and check the probability of that target.
+ //
+ // The only handled branch combinations are:
+ // - one conditional branch,
+ // - one conditional branch followed by one unconditional branch.
+ // Otherwise, assume not-taken.
+ assert(MI.isConditionalBranch());
+ const MachineBasicBlock &B = *MI.getParent();
+ bool SawCond = false, Bad = false;
+ for (const MachineInstr &I : B) {
+ if (!I.isBranch())
+ continue;
+ if (I.isConditionalBranch()) {
+ SawCond = true;
+ if (&I != &MI) {
+ Bad = true;
+ break;
+ }
+ }
+ if (I.isUnconditionalBranch() && !SawCond) {
+ Bad = true;
+ break;
+ }
+ }
+ if (!Bad) {
+ MachineBasicBlock::const_instr_iterator It(MI);
+ MachineBasicBlock::const_instr_iterator NextIt = std::next(It);
+ if (NextIt == B.instr_end()) {
+ // If this branch is the last, look for the fall-through block.
+ for (const MachineBasicBlock *SB : B.successors()) {
+ if (!B.isLayoutSuccessor(SB))
+ continue;
+ Taken = MBPI->getEdgeProbability(Src, SB) < OneHalf;
+ break;
+ }
+ } else {
+ assert(NextIt->isUnconditionalBranch());
+ // Find the first MBB operand and assume it's the target.
+ const MachineBasicBlock *BT = nullptr;
+ for (const MachineOperand &Op : NextIt->operands()) {
+ if (!Op.isMBB())
+ continue;
+ BT = Op.getMBB();
+ break;
+ }
+ Taken = BT && MBPI->getEdgeProbability(Src, BT) < OneHalf;
+ }
+ } // if (!Bad)
+ }
+
+ // The Taken flag should be set to something reasonable by this point.
switch (MI.getOpcode()) {
case Hexagon::J2_jumpt:
- return taken ? Hexagon::J2_jumptnewpt : Hexagon::J2_jumptnew;
+ return Taken ? Hexagon::J2_jumptnewpt : Hexagon::J2_jumptnew;
case Hexagon::J2_jumpf:
- return taken ? Hexagon::J2_jumpfnewpt : Hexagon::J2_jumpfnew;
+ return Taken ? Hexagon::J2_jumpfnewpt : Hexagon::J2_jumpfnew;
default:
llvm_unreachable("Unexpected jump instruction.");
@@ -3479,26 +3548,46 @@ int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI,
// Return .new predicate version for an instruction.
int HexagonInstrInfo::getDotNewPredOp(const MachineInstr &MI,
const MachineBranchProbabilityInfo *MBPI) const {
- int NewOpcode = Hexagon::getPredNewOpcode(MI.getOpcode());
- if (NewOpcode >= 0) // Valid predicate new instruction
- return NewOpcode;
-
switch (MI.getOpcode()) {
// Condtional Jumps
case Hexagon::J2_jumpt:
case Hexagon::J2_jumpf:
return getDotNewPredJumpOp(MI, MBPI);
-
- default:
- assert(0 && "Unknown .new type");
}
- return 0;
+
+ int NewOpcode = Hexagon::getPredNewOpcode(MI.getOpcode());
+ if (NewOpcode >= 0)
+ return NewOpcode;
+
+ dbgs() << "Cannot convert to .new: " << getName(MI.getOpcode()) << '\n';
+ llvm_unreachable(nullptr);
}
-int HexagonInstrInfo::getDotOldOp(const int opc) const {
- int NewOp = opc;
+int HexagonInstrInfo::getDotOldOp(const MachineInstr &MI) const {
+ int NewOp = MI.getOpcode();
if (isPredicated(NewOp) && isPredicatedNew(NewOp)) { // Get predicate old form
NewOp = Hexagon::getPredOldOpcode(NewOp);
+ const MachineFunction &MF = *MI.getParent()->getParent();
+ const HexagonSubtarget &HST = MF.getSubtarget<HexagonSubtarget>();
+ // All Hexagon architectures have prediction bits on dot-new branches,
+ // but only Hexagon V60+ has prediction bits on dot-old ones. Make sure
+ // to pick the right opcode when converting back to dot-old.
+ if (!HST.getFeatureBits()[Hexagon::ArchV60]) {
+ switch (NewOp) {
+ case Hexagon::J2_jumptpt:
+ NewOp = Hexagon::J2_jumpt;
+ break;
+ case Hexagon::J2_jumpfpt:
+ NewOp = Hexagon::J2_jumpf;
+ break;
+ case Hexagon::J2_jumprtpt:
+ NewOp = Hexagon::J2_jumprt;
+ break;
+ case Hexagon::J2_jumprfpt:
+ NewOp = Hexagon::J2_jumprf;
+ break;
+ }
+ }
assert(NewOp >= 0 &&
"Couldn't change predicate new instruction to its old form.");
}