summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Hexagon
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Hexagon')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp107
-rw-r--r--llvm/lib/Target/Hexagon/HexagonInstrInfo.h33
-rw-r--r--llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp3
3 files changed, 139 insertions, 4 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
index abba22273f0..4664e0c43d4 100644
--- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -660,6 +660,85 @@ unsigned HexagonInstrInfo::InsertBranch(MachineBasicBlock &MBB,
return 2;
}
+/// Analyze the loop code to find the loop induction variable and compare used
+/// to compute the number of iterations. Currently, we analyze loop that are
+/// controlled using hardware loops. In this case, the induction variable
+/// instruction is null. For all other cases, this function returns true, which
+/// means we're unable to analyze it.
+bool HexagonInstrInfo::analyzeLoop(MachineLoop &L,
+ MachineInstr *&IndVarInst,
+ MachineInstr *&CmpInst) const {
+
+ MachineBasicBlock *LoopEnd = L.getBottomBlock();
+ MachineBasicBlock::iterator I = LoopEnd->getFirstTerminator();
+ // We really "analyze" only hardware loops right now.
+ if (I != LoopEnd->end() && isEndLoopN(I->getOpcode())) {
+ IndVarInst = nullptr;
+ CmpInst = &*I;
+ return false;
+ }
+ return true;
+}
+
+/// Generate code to reduce the loop iteration by one and check if the loop is
+/// finished. Return the value/register of the new loop count. this function
+/// assumes the nth iteration is peeled first.
+unsigned HexagonInstrInfo::reduceLoopCount(MachineBasicBlock &MBB,
+ MachineInstr *IndVar, MachineInstr *Cmp,
+ SmallVectorImpl<MachineOperand> &Cond,
+ SmallVectorImpl<MachineInstr *> &PrevInsts,
+ unsigned Iter, unsigned MaxIter) const {
+ // We expect a hardware loop currently. This means that IndVar is set
+ // to null, and the compare is the ENDLOOP instruction.
+ assert((!IndVar) && isEndLoopN(Cmp->getOpcode())
+ && "Expecting a hardware loop");
+ MachineFunction *MF = MBB.getParent();
+ DebugLoc DL = Cmp->getDebugLoc();
+ SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs;
+ MachineInstr *Loop = findLoopInstr(&MBB, Cmp->getOpcode(), VisitedBBs);
+ if (!Loop)
+ return 0;
+ // If the loop trip count is a compile-time value, then just change the
+ // value.
+ if (Loop->getOpcode() == Hexagon::J2_loop0i ||
+ Loop->getOpcode() == Hexagon::J2_loop1i) {
+ int64_t Offset = Loop->getOperand(1).getImm();
+ if (Offset <= 1)
+ Loop->eraseFromParent();
+ else
+ Loop->getOperand(1).setImm(Offset - 1);
+ return Offset - 1;
+ }
+ // The loop trip count is a run-time value. We generate code to subtract
+ // one from the trip count, and update the loop instruction.
+ assert(Loop->getOpcode() == Hexagon::J2_loop0r && "Unexpected instruction");
+ unsigned LoopCount = Loop->getOperand(1).getReg();
+ // Check if we're done with the loop.
+ unsigned LoopEnd = createVR(MF, MVT::i1);
+ MachineInstr *NewCmp = BuildMI(&MBB, DL, get(Hexagon::C2_cmpgtui), LoopEnd).
+ addReg(LoopCount).addImm(1);
+ unsigned NewLoopCount = createVR(MF, MVT::i32);
+ MachineInstr *NewAdd = BuildMI(&MBB, DL, get(Hexagon::A2_addi), NewLoopCount).
+ addReg(LoopCount).addImm(-1);
+ // Update the previously generated instructions with the new loop counter.
+ for (SmallVectorImpl<MachineInstr *>::iterator I = PrevInsts.begin(),
+ E = PrevInsts.end(); I != E; ++I)
+ (*I)->substituteRegister(LoopCount, NewLoopCount, 0, getRegisterInfo());
+ PrevInsts.clear();
+ PrevInsts.push_back(NewCmp);
+ PrevInsts.push_back(NewAdd);
+ // Insert the new loop instruction if this is the last time the loop is
+ // decremented.
+ if (Iter == MaxIter)
+ BuildMI(&MBB, DL, get(Hexagon::J2_loop0r)).
+ addMBB(Loop->getOperand(0).getMBB()).addReg(NewLoopCount);
+ // Delete the old loop instruction.
+ if (Iter == 0)
+ Loop->eraseFromParent();
+ Cond.push_back(MachineOperand::CreateImm(Hexagon::J2_jumpf));
+ Cond.push_back(NewCmp->getOperand(0));
+ return NewLoopCount;
+}
bool HexagonInstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
unsigned NumCycles, unsigned ExtraPredCycles,
@@ -1592,6 +1671,22 @@ bool HexagonInstrInfo::areMemAccessesTriviallyDisjoint(
}
+/// If the instruction is an increment of a constant value, return the amount.
+bool HexagonInstrInfo::getIncrementValue(const MachineInstr *MI,
+ int &Value) const {
+ if (isPostIncrement(MI)) {
+ unsigned AccessSize;
+ return getBaseAndOffset(MI, Value, AccessSize);
+ }
+ if (MI->getOpcode() == Hexagon::A2_addi) {
+ Value = MI->getOperand(2).getImm();
+ return true;
+ }
+
+ return false;
+}
+
+
unsigned HexagonInstrInfo::createVR(MachineFunction* MF, MVT VT) const {
MachineRegisterInfo &MRI = MF->getRegInfo();
const TargetRegisterClass *TRC;
@@ -2878,6 +2973,18 @@ bool HexagonInstrInfo::addLatencyToSchedule(const MachineInstr *MI1,
}
+/// \brief Get the base register and byte offset of a load/store instr.
+bool HexagonInstrInfo::getMemOpBaseRegImmOfs(MachineInstr &LdSt,
+ unsigned &BaseReg, int64_t &Offset, const TargetRegisterInfo *TRI)
+ const {
+ unsigned AccessSize = 0;
+ int OffsetVal = 0;
+ BaseReg = getBaseAndOffset(&LdSt, OffsetVal, AccessSize);
+ Offset = OffsetVal;
+ return BaseReg != 0;
+}
+
+
/// \brief Can these instructions execute at the same time in a bundle.
bool HexagonInstrInfo::canExecuteInBundle(const MachineInstr *First,
const MachineInstr *Second) const {
diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.h b/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
index 66b6883c955..e4b2523aba9 100644
--- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
+++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
@@ -103,6 +103,22 @@ public:
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
const DebugLoc &DL) const override;
+ /// Analyze the loop code, return true if it cannot be understood. Upon
+ /// success, this function returns false and returns information about the
+ /// induction variable and compare instruction used at the end.
+ bool analyzeLoop(MachineLoop &L, MachineInstr *&IndVarInst,
+ MachineInstr *&CmpInst) const override;
+
+ /// Generate code to reduce the loop iteration by one and check if the loop is
+ /// finished. Return the value/register of the the new loop count. We need
+ /// this function when peeling off one or more iterations of a loop. This
+ /// function assumes the nth iteration is peeled first.
+ unsigned reduceLoopCount(MachineBasicBlock &MBB,
+ MachineInstr *IndVar, MachineInstr *Cmp,
+ SmallVectorImpl<MachineOperand> &Cond,
+ SmallVectorImpl<MachineInstr *> &PrevInsts,
+ unsigned Iter, unsigned MaxIter) const override;
+
/// Return true if it's profitable to predicate
/// instructions with accumulated instruction latency of "NumCycles"
/// of the specified basic block, where the probability of the instructions
@@ -172,6 +188,11 @@ public:
/// anything was changed.
bool expandPostRAPseudo(MachineInstr &MI) const override;
+ /// \brief Get the base register and byte offset of a load/store instr.
+ bool getMemOpBaseRegImmOfs(MachineInstr &LdSt, unsigned &BaseReg,
+ int64_t &Offset,
+ const TargetRegisterInfo *TRI) const override;
+
/// Reverses the branch condition of the specified condition list,
/// returning false on success and true if it cannot be reversed.
bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond)
@@ -248,6 +269,14 @@ public:
areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb,
AliasAnalysis *AA = nullptr) const override;
+ /// For instructions with a base and offset, return the position of the
+ /// base register and offset operands.
+ bool getBaseAndOffsetPosition(const MachineInstr *MI, unsigned &BasePos,
+ unsigned &OffsetPos) const override;
+
+ /// If the instruction is an increment of a constant value, return the amount.
+ bool getIncrementValue(const MachineInstr *MI, int &Value) const override;
+
/// HexagonInstrInfo specifics.
///
@@ -297,7 +326,7 @@ public:
bool isNewValueStore(const MachineInstr* MI) const;
bool isNewValueStore(unsigned Opcode) const;
bool isOperandExtended(const MachineInstr *MI, unsigned OperandNum) const;
- bool isPostIncrement(const MachineInstr* MI) const;
+ bool isPostIncrement(const MachineInstr* MI) const override;
bool isPredicatedNew(const MachineInstr &MI) const;
bool isPredicatedNew(unsigned Opcode) const;
bool isPredicatedTrue(const MachineInstr &MI) const;
@@ -348,8 +377,6 @@ public:
unsigned getAddrMode(const MachineInstr* MI) const;
unsigned getBaseAndOffset(const MachineInstr *MI, int &Offset,
unsigned &AccessSize) const;
- bool getBaseAndOffsetPosition(const MachineInstr *MI, unsigned &BasePos,
- unsigned &OffsetPos) const;
short getBaseWithLongOffset(short Opcode) const;
short getBaseWithLongOffset(const MachineInstr *MI) const;
short getBaseWithRegOffset(const MachineInstr *MI) const;
diff --git a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp
index 80f256cd586..17396942898 100644
--- a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp
@@ -27,7 +27,6 @@
using namespace llvm;
-
static cl::opt<bool> EnableRDFOpt("rdf-opt", cl::Hidden, cl::ZeroOrMore,
cl::init(true), cl::desc("Enable RDF-based optimizations"));
@@ -292,6 +291,8 @@ void HexagonPassConfig::addPreRegAlloc() {
if (!DisableHardwareLoops)
addPass(createHexagonHardwareLoops(), false);
}
+ if (TM->getOptLevel() >= CodeGenOpt::Default)
+ addPass(&MachinePipelinerID);
}
void HexagonPassConfig::addPostRegAlloc() {
OpenPOWER on IntegriCloud