summaryrefslogtreecommitdiff
path: root/lib/Target/Hexagon/HexagonHardwareLoops.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Hexagon/HexagonHardwareLoops.cpp')
-rw-r--r--lib/Target/Hexagon/HexagonHardwareLoops.cpp105
1 files changed, 66 insertions, 39 deletions
diff --git a/lib/Target/Hexagon/HexagonHardwareLoops.cpp b/lib/Target/Hexagon/HexagonHardwareLoops.cpp
index 86a8089401c2..715fd52f3acd 100644
--- a/lib/Target/Hexagon/HexagonHardwareLoops.cpp
+++ b/lib/Target/Hexagon/HexagonHardwareLoops.cpp
@@ -1,4 +1,4 @@
-//===-- HexagonHardwareLoops.cpp - Identify and generate hardware loops ---===//
+//===- HexagonHardwareLoops.cpp - Identify and generate hardware loops ----===//
//
// The LLVM Compiler Infrastructure
//
@@ -27,6 +27,8 @@
#include "HexagonInstrInfo.h"
#include "HexagonSubtarget.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
@@ -40,6 +42,7 @@
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
@@ -48,13 +51,13 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetRegisterInfo.h"
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <iterator>
#include <map>
#include <set>
+#include <string>
#include <utility>
#include <vector>
@@ -108,9 +111,7 @@ namespace {
public:
static char ID;
- HexagonHardwareLoops() : MachineFunctionPass(ID) {
- initializeHexagonHardwareLoopsPass(*PassRegistry::getPassRegistry());
- }
+ HexagonHardwareLoops() : MachineFunctionPass(ID) {}
bool runOnMachineFunction(MachineFunction &MF) override;
@@ -123,7 +124,7 @@ namespace {
}
private:
- typedef std::map<unsigned, MachineInstr *> LoopFeederMap;
+ using LoopFeederMap = std::map<unsigned, MachineInstr *>;
/// Kinds of comparisons in the compare instructions.
struct Comparison {
@@ -275,7 +276,7 @@ namespace {
/// value, either directly, or via a register.
void setImmediate(MachineOperand &MO, int64_t Val);
- /// \brief Fix the data flow of the induction varible.
+ /// \brief Fix the data flow of the induction variable.
/// The desired flow is: phi ---> bump -+-> comparison-in-latch.
/// |
/// +-> back to phi
@@ -344,17 +345,19 @@ namespace {
assert(isReg() && "Wrong CountValue accessor");
return Contents.R.Reg;
}
+
unsigned getSubReg() const {
assert(isReg() && "Wrong CountValue accessor");
return Contents.R.Sub;
}
+
unsigned getImm() const {
assert(isImm() && "Wrong CountValue accessor");
return Contents.ImmVal;
}
void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr) const {
- if (isReg()) { OS << PrintReg(Contents.R.Reg, TRI, Contents.R.Sub); }
+ if (isReg()) { OS << printReg(Contents.R.Reg, TRI, Contents.R.Sub); }
if (isImm()) { OS << Contents.ImmVal; }
}
};
@@ -374,7 +377,7 @@ FunctionPass *llvm::createHexagonHardwareLoops() {
bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) {
DEBUG(dbgs() << "********* Hexagon Hardware Loops *********\n");
- if (skipFunction(*MF.getFunction()))
+ if (skipFunction(MF.getFunction()))
return false;
bool Changed = false;
@@ -410,17 +413,18 @@ bool HexagonHardwareLoops::findInductionRegister(MachineLoop *L,
// This pair represents an induction register together with an immediate
// value that will be added to it in each loop iteration.
- typedef std::pair<unsigned,int64_t> RegisterBump;
+ using RegisterBump = std::pair<unsigned, int64_t>;
// Mapping: R.next -> (R, bump), where R, R.next and bump are derived
// from an induction operation
// R.next = R + bump
// where bump is an immediate value.
- typedef std::map<unsigned,RegisterBump> InductionMap;
+ using InductionMap = std::map<unsigned, RegisterBump>;
InductionMap IndMap;
- typedef MachineBasicBlock::instr_iterator instr_iterator;
+ using instr_iterator = MachineBasicBlock::instr_iterator;
+
for (instr_iterator I = Header->instr_begin(), E = Header->instr_end();
I != E && I->isPHI(); ++I) {
MachineInstr *Phi = &*I;
@@ -507,8 +511,8 @@ HexagonHardwareLoops::getComparisonKind(unsigned CondOpc,
int64_t IVBump) const {
Comparison::Kind Cmp = (Comparison::Kind)0;
switch (CondOpc) {
- case Hexagon::C2_cmpeqi:
case Hexagon::C2_cmpeq:
+ case Hexagon::C2_cmpeqi:
case Hexagon::C2_cmpeqp:
Cmp = Comparison::EQ;
break;
@@ -516,21 +520,35 @@ HexagonHardwareLoops::getComparisonKind(unsigned CondOpc,
case Hexagon::C4_cmpneqi:
Cmp = Comparison::NE;
break;
+ case Hexagon::C2_cmplt:
+ Cmp = Comparison::LTs;
+ break;
+ case Hexagon::C2_cmpltu:
+ Cmp = Comparison::LTu;
+ break;
case Hexagon::C4_cmplte:
+ case Hexagon::C4_cmpltei:
Cmp = Comparison::LEs;
break;
case Hexagon::C4_cmplteu:
+ case Hexagon::C4_cmplteui:
Cmp = Comparison::LEu;
break;
- case Hexagon::C2_cmpgtui:
+ case Hexagon::C2_cmpgt:
+ case Hexagon::C2_cmpgti:
+ case Hexagon::C2_cmpgtp:
+ Cmp = Comparison::GTs;
+ break;
case Hexagon::C2_cmpgtu:
+ case Hexagon::C2_cmpgtui:
case Hexagon::C2_cmpgtup:
Cmp = Comparison::GTu;
break;
- case Hexagon::C2_cmpgti:
- case Hexagon::C2_cmpgt:
- case Hexagon::C2_cmpgtp:
- Cmp = Comparison::GTs;
+ case Hexagon::C2_cmpgei:
+ Cmp = Comparison::GEs;
+ break;
+ case Hexagon::C2_cmpgeui:
+ Cmp = Comparison::GEs;
break;
default:
return (Comparison::Kind)0;
@@ -679,15 +697,21 @@ CountValue *HexagonHardwareLoops::getLoopTripCount(MachineLoop *L,
if (InitialValue->isReg()) {
unsigned R = InitialValue->getReg();
MachineBasicBlock *DefBB = MRI->getVRegDef(R)->getParent();
- if (!MDT->properlyDominates(DefBB, Header))
- return nullptr;
+ if (!MDT->properlyDominates(DefBB, Header)) {
+ int64_t V;
+ if (!checkForImmediate(*InitialValue, V))
+ return nullptr;
+ }
OldInsts.push_back(MRI->getVRegDef(R));
}
if (EndValue->isReg()) {
unsigned R = EndValue->getReg();
MachineBasicBlock *DefBB = MRI->getVRegDef(R)->getParent();
- if (!MDT->properlyDominates(DefBB, Header))
- return nullptr;
+ if (!MDT->properlyDominates(DefBB, Header)) {
+ int64_t V;
+ if (!checkForImmediate(*EndValue, V))
+ return nullptr;
+ }
OldInsts.push_back(MRI->getVRegDef(R));
}
@@ -970,6 +994,7 @@ bool HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI,
// Check if the instruction defines a hardware loop register.
using namespace Hexagon;
+
static const unsigned Regs01[] = { LC0, SA0, LC1, SA1 };
static const unsigned Regs1[] = { LC1, SA1 };
auto CheckRegs = IsInnerHWLoop ? makeArrayRef(Regs01, array_lengthof(Regs01))
@@ -986,7 +1011,7 @@ bool HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI,
bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L,
bool IsInnerHWLoop) const {
const std::vector<MachineBasicBlock *> &Blocks = L->getBlocks();
- DEBUG(dbgs() << "\nhw_loop head, BB#" << Blocks[0]->getNumber(););
+ DEBUG(dbgs() << "\nhw_loop head, " << printMBBReference(*Blocks[0]));
for (unsigned i = 0, e = Blocks.size(); i != e; ++i) {
MachineBasicBlock *MBB = Blocks[i];
for (MachineBasicBlock::iterator
@@ -1017,7 +1042,7 @@ bool HexagonHardwareLoops::isDead(const MachineInstr *MI,
if (MRI->use_nodbg_empty(Reg))
continue;
- typedef MachineRegisterInfo::use_nodbg_iterator use_nodbg_iterator;
+ using use_nodbg_iterator = MachineRegisterInfo::use_nodbg_iterator;
// This instruction has users, but if the only user is the phi node for the
// parent block, and the only use of that phi node is this instruction, then
@@ -1231,7 +1256,7 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L,
// if the immediate fits in the instructions. Otherwise, we need to
// create a new virtual register.
int64_t CountImm = TripCount->getImm();
- if (!TII->isValidOffset(LOOP_i, CountImm)) {
+ if (!TII->isValidOffset(LOOP_i, CountImm, TRI)) {
unsigned CountReg = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::A2_tfrsi), CountReg)
.addImm(CountImm);
@@ -1300,7 +1325,8 @@ bool HexagonHardwareLoops::orderBumpCompare(MachineInstr *BumpI,
if (CmpI->getParent() != BB)
return false;
- typedef MachineBasicBlock::instr_iterator instr_iterator;
+ using instr_iterator = MachineBasicBlock::instr_iterator;
+
// Check if things are in order to begin with.
for (instr_iterator I(BumpI), E = BB->instr_end(); I != E; ++I)
if (&*I == CmpI)
@@ -1341,7 +1367,7 @@ bool HexagonHardwareLoops::isLoopFeeder(MachineLoop *L, MachineBasicBlock *A,
LoopFeederMap &LoopFeederPhi) const {
if (LoopFeederPhi.find(MO->getReg()) == LoopFeederPhi.end()) {
const std::vector<MachineBasicBlock *> &Blocks = L->getBlocks();
- DEBUG(dbgs() << "\nhw_loop head, BB#" << Blocks[0]->getNumber(););
+ DEBUG(dbgs() << "\nhw_loop head, " << printMBBReference(*Blocks[0]));
// Ignore all BBs that form Loop.
for (unsigned i = 0, e = Blocks.size(); i != e; ++i) {
MachineBasicBlock *MBB = Blocks[i];
@@ -1493,14 +1519,13 @@ bool HexagonHardwareLoops::checkForImmediate(const MachineOperand &MO,
case Hexagon::A2_tfrsi:
case Hexagon::A2_tfrpi:
case Hexagon::CONST32:
- case Hexagon::CONST64: {
+ case Hexagon::CONST64:
// Call recursively to avoid an extra check whether operand(1) is
// indeed an immediate (it could be a global address, for example),
// plus we can handle COPY at the same time.
if (!checkForImmediate(DI->getOperand(1), TV))
return false;
break;
- }
case Hexagon::A2_combineii:
case Hexagon::A4_combineir:
case Hexagon::A4_combineii:
@@ -1589,17 +1614,18 @@ bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) {
// These data structures follow the same concept as the corresponding
// ones in findInductionRegister (where some comments are).
- typedef std::pair<unsigned,int64_t> RegisterBump;
- typedef std::pair<unsigned,RegisterBump> RegisterInduction;
- typedef std::set<RegisterInduction> RegisterInductionSet;
+ using RegisterBump = std::pair<unsigned, int64_t>;
+ using RegisterInduction = std::pair<unsigned, RegisterBump>;
+ using RegisterInductionSet = std::set<RegisterInduction>;
// Register candidates for induction variables, with their associated bumps.
RegisterInductionSet IndRegs;
// Look for induction patterns:
- // vreg1 = PHI ..., [ latch, vreg2 ]
- // vreg2 = ADD vreg1, imm
- typedef MachineBasicBlock::instr_iterator instr_iterator;
+ // %1 = PHI ..., [ latch, %2 ]
+ // %2 = ADD %1, imm
+ using instr_iterator = MachineBasicBlock::instr_iterator;
+
for (instr_iterator I = Header->instr_begin(), E = Header->instr_end();
I != E && I->isPHI(); ++I) {
MachineInstr *Phi = &*I;
@@ -1694,7 +1720,7 @@ bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) {
MachineOperand &MO = PredDef->getOperand(i);
if (MO.isReg()) {
// Skip all implicit references. In one case there was:
- // %vreg140<def> = FCMPUGT32_rr %vreg138, %vreg139, %USR<imp-use>
+ // %140 = FCMPUGT32_rr %138, %139, implicit %usr
if (MO.isImplicit())
continue;
if (MO.isUse()) {
@@ -1834,18 +1860,19 @@ MachineBasicBlock *HexagonHardwareLoops::createPreheaderForLoop(
DebugLoc DL;
#ifndef NDEBUG
- if ((PHFn != "") && (PHFn != MF->getName()))
+ if ((!PHFn.empty()) && (PHFn != MF->getName()))
return nullptr;
#endif
if (!Latch || !ExitingBlock || Header->hasAddressTaken())
return nullptr;
- typedef MachineBasicBlock::instr_iterator instr_iterator;
+ using instr_iterator = MachineBasicBlock::instr_iterator;
// Verify that all existing predecessors have analyzable branches
// (or no branches at all).
- typedef std::vector<MachineBasicBlock*> MBBVector;
+ using MBBVector = std::vector<MachineBasicBlock *>;
+
MBBVector Preds(Header->pred_begin(), Header->pred_end());
SmallVector<MachineOperand,2> Tmp1;
MachineBasicBlock *TB = nullptr, *FB = nullptr;