llvm-project/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp

645 lines
23 KiB
C++

//===-- HexagonHardwareLoops.cpp - Identify and generate hardware loops ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass identifies loops where we can generate the Hexagon hardware
// loop instruction. The hardware loop can perform loop branches with a
// zero-cycle overhead.
//
// The pattern that defines the induction variable can changed depending on
// prior optimizations. For example, the IndVarSimplify phase run by 'opt'
// normalizes induction variables, and the Loop Strength Reduction pass
// run by 'llc' may also make changes to the induction variable.
// The pattern detected by this phase is due to running Strength Reduction.
//
// Criteria for hardware loops:
// - Countable loops (w/ ind. var for a trip count)
// - Assumes loops are normalized by IndVarSimplify
// - Try inner-most loops first
// - No nested hardware loops.
// - No function calls in loops.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "hwloops"
#include "Hexagon.h"
#include "HexagonTargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/PassSupport.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include <algorithm>
using namespace llvm;
STATISTIC(NumHWLoops, "Number of loops converted to hardware loops");
namespace {
class CountValue;
struct HexagonHardwareLoops : public MachineFunctionPass {
MachineLoopInfo *MLI;
MachineRegisterInfo *MRI;
const TargetInstrInfo *TII;
public:
static char ID; // Pass identification, replacement for typeid
HexagonHardwareLoops() : MachineFunctionPass(ID) {}
virtual bool runOnMachineFunction(MachineFunction &MF);
const char *getPassName() const { return "Hexagon Hardware Loops"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<MachineDominatorTree>();
AU.addPreserved<MachineDominatorTree>();
AU.addRequired<MachineLoopInfo>();
AU.addPreserved<MachineLoopInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
}
private:
/// getCanonicalInductionVariable - Check to see if the loop has a canonical
/// induction variable.
/// Should be defined in MachineLoop. Based upon version in class Loop.
const MachineInstr *getCanonicalInductionVariable(MachineLoop *L) const;
/// getTripCount - Return a loop-invariant LLVM register indicating the
/// number of times the loop will be executed. If the trip-count cannot
/// be determined, this return null.
CountValue *getTripCount(MachineLoop *L) const;
/// isInductionOperation - Return true if the instruction matches the
/// pattern for an opertion that defines an induction variable.
bool isInductionOperation(const MachineInstr *MI, unsigned IVReg) const;
/// isInvalidOperation - Return true if the instruction is not valid within
/// a hardware loop.
bool isInvalidLoopOperation(const MachineInstr *MI) const;
/// containsInavlidInstruction - Return true if the loop contains an
/// instruction that inhibits using the hardware loop.
bool containsInvalidInstruction(MachineLoop *L) const;
/// converToHardwareLoop - Given a loop, check if we can convert it to a
/// hardware loop. If so, then perform the conversion and return true.
bool convertToHardwareLoop(MachineLoop *L);
};
char HexagonHardwareLoops::ID = 0;
// CountValue class - Abstraction for a trip count of a loop. A
// smaller vesrsion of the MachineOperand class without the concerns
// of changing the operand representation.
class CountValue {
public:
enum CountValueType {
CV_Register,
CV_Immediate
};
private:
CountValueType Kind;
union Values {
unsigned RegNum;
int64_t ImmVal;
Values(unsigned r) : RegNum(r) {}
Values(int64_t i) : ImmVal(i) {}
} Contents;
bool isNegative;
public:
CountValue(unsigned r, bool neg) : Kind(CV_Register), Contents(r),
isNegative(neg) {}
explicit CountValue(int64_t i) : Kind(CV_Immediate), Contents(i),
isNegative(i < 0) {}
CountValueType getType() const { return Kind; }
bool isReg() const { return Kind == CV_Register; }
bool isImm() const { return Kind == CV_Immediate; }
bool isNeg() const { return isNegative; }
unsigned getReg() const {
assert(isReg() && "Wrong CountValue accessor");
return Contents.RegNum;
}
void setReg(unsigned Val) {
Contents.RegNum = Val;
}
int64_t getImm() const {
assert(isImm() && "Wrong CountValue accessor");
if (isNegative) {
return -Contents.ImmVal;
}
return Contents.ImmVal;
}
void setImm(int64_t Val) {
Contents.ImmVal = Val;
}
void print(raw_ostream &OS, const TargetMachine *TM = 0) const {
if (isReg()) { OS << PrintReg(getReg()); }
if (isImm()) { OS << getImm(); }
}
};
struct HexagonFixupHwLoops : public MachineFunctionPass {
public:
static char ID; // Pass identification, replacement for typeid.
HexagonFixupHwLoops() : MachineFunctionPass(ID) {}
virtual bool runOnMachineFunction(MachineFunction &MF);
const char *getPassName() const { return "Hexagon Hardware Loop Fixup"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
MachineFunctionPass::getAnalysisUsage(AU);
}
private:
/// Maximum distance between the loop instr and the basic block.
/// Just an estimate.
static const unsigned MAX_LOOP_DISTANCE = 200;
/// fixupLoopInstrs - Check the offset between each loop instruction and
/// the loop basic block to determine if we can use the LOOP instruction
/// or if we need to set the LC/SA registers explicitly.
bool fixupLoopInstrs(MachineFunction &MF);
/// convertLoopInstr - Add the instruction to set the LC and SA registers
/// explicitly.
void convertLoopInstr(MachineFunction &MF,
MachineBasicBlock::iterator &MII,
RegScavenger &RS);
};
char HexagonFixupHwLoops::ID = 0;
} // end anonymous namespace
/// isHardwareLoop - Returns true if the instruction is a hardware loop
/// instruction.
static bool isHardwareLoop(const MachineInstr *MI) {
return MI->getOpcode() == Hexagon::LOOP0_r ||
MI->getOpcode() == Hexagon::LOOP0_i;
}
/// isCompareEquals - Returns true if the instruction is a compare equals
/// instruction with an immediate operand.
static bool isCompareEqualsImm(const MachineInstr *MI) {
return MI->getOpcode() == Hexagon::CMPEQri;
}
/// createHexagonHardwareLoops - Factory for creating
/// the hardware loop phase.
FunctionPass *llvm::createHexagonHardwareLoops() {
return new HexagonHardwareLoops();
}
bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) {
DEBUG(dbgs() << "********* Hexagon Hardware Loops *********\n");
bool Changed = false;
// get the loop information
MLI = &getAnalysis<MachineLoopInfo>();
// get the register information
MRI = &MF.getRegInfo();
// the target specific instructio info.
TII = MF.getTarget().getInstrInfo();
for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end();
I != E; ++I) {
MachineLoop *L = *I;
if (!L->getParentLoop()) {
Changed |= convertToHardwareLoop(L);
}
}
return Changed;
}
/// getCanonicalInductionVariable - Check to see if the loop has a canonical
/// induction variable. We check for a simple recurrence pattern - an
/// integer recurrence that decrements by one each time through the loop and
/// ends at zero. If so, return the phi node that corresponds to it.
///
/// Based upon the similar code in LoopInfo except this code is specific to
/// the machine.
/// This method assumes that the IndVarSimplify pass has been run by 'opt'.
///
const MachineInstr
*HexagonHardwareLoops::getCanonicalInductionVariable(MachineLoop *L) const {
MachineBasicBlock *TopMBB = L->getTopBlock();
MachineBasicBlock::pred_iterator PI = TopMBB->pred_begin();
assert(PI != TopMBB->pred_end() &&
"Loop must have more than one incoming edge!");
MachineBasicBlock *Backedge = *PI++;
if (PI == TopMBB->pred_end()) return 0; // dead loop
MachineBasicBlock *Incoming = *PI++;
if (PI != TopMBB->pred_end()) return 0; // multiple backedges?
// make sure there is one incoming and one backedge and determine which
// is which.
if (L->contains(Incoming)) {
if (L->contains(Backedge))
return 0;
std::swap(Incoming, Backedge);
} else if (!L->contains(Backedge))
return 0;
// Loop over all of the PHI nodes, looking for a canonical induction variable:
// - The PHI node is "reg1 = PHI reg2, BB1, reg3, BB2".
// - The recurrence comes from the backedge.
// - the definition is an induction operatio.n
for (MachineBasicBlock::iterator I = TopMBB->begin(), E = TopMBB->end();
I != E && I->isPHI(); ++I) {
const MachineInstr *MPhi = &*I;
unsigned DefReg = MPhi->getOperand(0).getReg();
for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) {
// Check each operand for the value from the backedge.
MachineBasicBlock *MBB = MPhi->getOperand(i+1).getMBB();
if (L->contains(MBB)) { // operands comes from the backedge
// Check if the definition is an induction operation.
const MachineInstr *DI = MRI->getVRegDef(MPhi->getOperand(i).getReg());
if (isInductionOperation(DI, DefReg)) {
return MPhi;
}
}
}
}
return 0;
}
/// getTripCount - Return a loop-invariant LLVM value indicating the
/// number of times the loop will be executed. The trip count can
/// be either a register or a constant value. If the trip-count
/// cannot be determined, this returns null.
///
/// We find the trip count from the phi instruction that defines the
/// induction variable. We follow the links to the CMP instruction
/// to get the trip count.
///
/// Based upon getTripCount in LoopInfo.
///
CountValue *HexagonHardwareLoops::getTripCount(MachineLoop *L) const {
// Check that the loop has a induction variable.
const MachineInstr *IV_Inst = getCanonicalInductionVariable(L);
if (IV_Inst == 0) return 0;
// Canonical loops will end with a 'cmpeq_ri IV, Imm',
// if Imm is 0, get the count from the PHI opnd
// if Imm is -M, than M is the count
// Otherwise, Imm is the count
const MachineOperand *IV_Opnd;
const MachineOperand *InitialValue;
if (!L->contains(IV_Inst->getOperand(2).getMBB())) {
InitialValue = &IV_Inst->getOperand(1);
IV_Opnd = &IV_Inst->getOperand(3);
} else {
InitialValue = &IV_Inst->getOperand(3);
IV_Opnd = &IV_Inst->getOperand(1);
}
// Look for the cmp instruction to determine if we
// can get a useful trip count. The trip count can
// be either a register or an immediate. The location
// of the value depends upon the type (reg or imm).
while ((IV_Opnd = IV_Opnd->getNextOperandForReg())) {
const MachineInstr *MI = IV_Opnd->getParent();
if (L->contains(MI) && isCompareEqualsImm(MI)) {
const MachineOperand &MO = MI->getOperand(2);
assert(MO.isImm() && "IV Cmp Operand should be 0");
int64_t ImmVal = MO.getImm();
const MachineInstr *IV_DefInstr = MRI->getVRegDef(IV_Opnd->getReg());
assert(L->contains(IV_DefInstr->getParent()) &&
"IV definition should occurs in loop");
int64_t iv_value = IV_DefInstr->getOperand(2).getImm();
if (ImmVal == 0) {
// Make sure the induction variable changes by one on each iteration.
if (iv_value != 1 && iv_value != -1) {
return 0;
}
return new CountValue(InitialValue->getReg(), iv_value > 0);
} else {
assert(InitialValue->isReg() && "Expecting register for init value");
const MachineInstr *DefInstr = MRI->getVRegDef(InitialValue->getReg());
if (DefInstr && DefInstr->getOpcode() == Hexagon::TFRI) {
int64_t count = ImmVal - DefInstr->getOperand(1).getImm();
if ((count % iv_value) != 0) {
return 0;
}
return new CountValue(count/iv_value);
}
}
}
}
return 0;
}
/// isInductionOperation - return true if the operation is matches the
/// pattern that defines an induction variable:
/// add iv, c
///
bool
HexagonHardwareLoops::isInductionOperation(const MachineInstr *MI,
unsigned IVReg) const {
return (MI->getOpcode() ==
Hexagon::ADD_ri && MI->getOperand(1).getReg() == IVReg);
}
/// isInvalidOperation - Return true if the operation is invalid within
/// hardware loop.
bool
HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI) const {
// call is not allowed because the callee may use a hardware loop
if (MI->getDesc().isCall()) {
return true;
}
// do not allow nested hardware loops
if (isHardwareLoop(MI)) {
return true;
}
// check if the instruction defines a hardware loop register
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (MO.isReg() && MO.isDef() &&
(MO.getReg() == Hexagon::LC0 || MO.getReg() == Hexagon::LC1 ||
MO.getReg() == Hexagon::SA0 || MO.getReg() == Hexagon::SA0)) {
return true;
}
}
return false;
}
/// containsInvalidInstruction - Return true if the loop contains
/// an instruction that inhibits the use of the hardware loop function.
///
bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L) const {
const std::vector<MachineBasicBlock*> Blocks = L->getBlocks();
for (unsigned i = 0, e = Blocks.size(); i != e; ++i) {
MachineBasicBlock *MBB = Blocks[i];
for (MachineBasicBlock::iterator
MII = MBB->begin(), E = MBB->end(); MII != E; ++MII) {
const MachineInstr *MI = &*MII;
if (isInvalidLoopOperation(MI)) {
return true;
}
}
}
return false;
}
/// converToHardwareLoop - check if the loop is a candidate for
/// converting to a hardware loop. If so, then perform the
/// transformation.
///
/// This function works on innermost loops first. A loop can
/// be converted if it is a counting loop; either a register
/// value or an immediate.
///
/// The code makes several assumptions about the representation
/// of the loop in llvm.
bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) {
bool Changed = false;
// Process nested loops first.
for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I) {
Changed |= convertToHardwareLoop(*I);
}
// If a nested loop has been converted, then we can't convert this loop.
if (Changed) {
return Changed;
}
// Are we able to determine the trip count for the loop?
CountValue *TripCount = getTripCount(L);
if (TripCount == 0) {
return false;
}
// Does the loop contain any invalid instructions?
if (containsInvalidInstruction(L)) {
return false;
}
MachineBasicBlock *Preheader = L->getLoopPreheader();
// No preheader means there's not place for the loop instr.
if (Preheader == 0) {
return false;
}
MachineBasicBlock::iterator InsertPos = Preheader->getFirstTerminator();
MachineBasicBlock *LastMBB = L->getExitingBlock();
// Don't generate hw loop if the loop has more than one exit.
if (LastMBB == 0) {
return false;
}
MachineBasicBlock::iterator LastI = LastMBB->getFirstTerminator();
// Determine the loop start.
MachineBasicBlock *LoopStart = L->getTopBlock();
if (L->getLoopLatch() != LastMBB) {
// When the exit and latch are not the same, use the latch block as the
// start.
// The loop start address is used only after the 1st iteration, and the loop
// latch may contains instrs. that need to be executed after the 1st iter.
LoopStart = L->getLoopLatch();
// Make sure the latch is a successor of the exit, otherwise it won't work.
if (!LastMBB->isSuccessor(LoopStart)) {
return false;
}
}
// Convert the loop to a hardware loop
DEBUG(dbgs() << "Change to hardware loop at "; L->dump());
if (TripCount->isReg()) {
// Create a copy of the loop count register.
MachineFunction *MF = LastMBB->getParent();
const TargetRegisterClass *RC =
MF->getRegInfo().getRegClass(TripCount->getReg());
unsigned CountReg = MF->getRegInfo().createVirtualRegister(RC);
BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(),
TII->get(TargetOpcode::COPY), CountReg).addReg(TripCount->getReg());
if (TripCount->isNeg()) {
unsigned CountReg1 = CountReg;
CountReg = MF->getRegInfo().createVirtualRegister(RC);
BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(),
TII->get(Hexagon::NEG), CountReg).addReg(CountReg1);
}
// Add the Loop instruction to the begining of the loop.
BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(),
TII->get(Hexagon::LOOP0_r)).addMBB(LoopStart).addReg(CountReg);
} else {
assert(TripCount->isImm() && "Expecting immedate vaule for trip count");
// Add the Loop immediate instruction to the beginning of the loop.
int64_t CountImm = TripCount->getImm();
BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(),
TII->get(Hexagon::LOOP0_i)).addMBB(LoopStart).addImm(CountImm);
}
// Make sure the loop start always has a reference in the CFG. We need to
// create a BlockAddress operand to get this mechanism to work both the
// MachineBasicBlock and BasicBlock objects need the flag set.
LoopStart->setHasAddressTaken();
// This line is needed to set the hasAddressTaken flag on the BasicBlock
// object
BlockAddress::get(const_cast<BasicBlock *>(LoopStart->getBasicBlock()));
// Replace the loop branch with an endloop instruction.
DebugLoc dl = LastI->getDebugLoc();
BuildMI(*LastMBB, LastI, dl, TII->get(Hexagon::ENDLOOP0)).addMBB(LoopStart);
// The loop ends with either:
// - a conditional branch followed by an unconditional branch, or
// - a conditional branch to the loop start.
if (LastI->getOpcode() == Hexagon::JMP_c ||
LastI->getOpcode() == Hexagon::JMP_cNot) {
// delete one and change/add an uncond. branch to out of the loop
MachineBasicBlock *BranchTarget = LastI->getOperand(1).getMBB();
LastI = LastMBB->erase(LastI);
if (!L->contains(BranchTarget)) {
if (LastI != LastMBB->end()) {
TII->RemoveBranch(*LastMBB);
}
SmallVector<MachineOperand, 0> Cond;
TII->InsertBranch(*LastMBB, BranchTarget, 0, Cond, dl);
}
} else {
// Conditional branch to loop start; just delete it.
LastMBB->erase(LastI);
}
delete TripCount;
++NumHWLoops;
return true;
}
/// createHexagonFixupHwLoops - Factory for creating the hardware loop
/// phase.
FunctionPass *llvm::createHexagonFixupHwLoops() {
return new HexagonFixupHwLoops();
}
bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
DEBUG(dbgs() << "****** Hexagon Hardware Loop Fixup ******\n");
bool Changed = fixupLoopInstrs(MF);
return Changed;
}
/// fixupLoopInsts - For Hexagon, if the loop label is to far from the
/// loop instruction then we need to set the LC0 and SA0 registers
/// explicitly instead of using LOOP(start,count). This function
/// checks the distance, and generates register assignments if needed.
///
/// This function makes two passes over the basic blocks. The first
/// pass computes the offset of the basic block from the start.
/// The second pass checks all the loop instructions.
bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
// Offset of the current instruction from the start.
unsigned InstOffset = 0;
// Map for each basic block to it's first instruction.
DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset;
// First pass - compute the offset of each basic block.
for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
MBB != MBBe; ++MBB) {
BlockToInstOffset[MBB] = InstOffset;
InstOffset += (MBB->size() * 4);
}
// Second pass - check each loop instruction to see if it needs to
// be converted.
InstOffset = 0;
bool Changed = false;
RegScavenger RS;
// Loop over all the basic blocks.
for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
MBB != MBBe; ++MBB) {
InstOffset = BlockToInstOffset[MBB];
RS.enterBasicBlock(MBB);
// Loop over all the instructions.
MachineBasicBlock::iterator MIE = MBB->end();
MachineBasicBlock::iterator MII = MBB->begin();
while (MII != MIE) {
if (isHardwareLoop(MII)) {
RS.forward(MII);
assert(MII->getOperand(0).isMBB() &&
"Expect a basic block as loop operand");
int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
diff = (diff > 0 ? diff : -diff);
if ((unsigned)diff > MAX_LOOP_DISTANCE) {
// Convert to explicity setting LC0 and SA0.
convertLoopInstr(MF, MII, RS);
MII = MBB->erase(MII);
Changed = true;
} else {
++MII;
}
} else {
++MII;
}
InstOffset += 4;
}
}
return Changed;
}
/// convertLoopInstr - convert a loop instruction to a sequence of instructions
/// that set the lc and sa register explicitly.
void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF,
MachineBasicBlock::iterator &MII,
RegScavenger &RS) {
const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
MachineBasicBlock *MBB = MII->getParent();
DebugLoc DL = MII->getDebugLoc();
unsigned Scratch = RS.scavengeRegister(Hexagon::IntRegsRegisterClass, MII, 0);
// First, set the LC0 with the trip count.
if (MII->getOperand(1).isReg()) {
// Trip count is a register
BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
.addReg(MII->getOperand(1).getReg());
} else {
// Trip count is an immediate.
BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch)
.addImm(MII->getOperand(1).getImm());
BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
.addReg(Scratch);
}
// Then, set the SA0 with the loop start address.
BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch)
.addMBB(MII->getOperand(0).getMBB());
BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0).addReg(Scratch);
}