#include "HexagonInstrInfo.h"
#include "HexagonRegisterInfo.h"
#include "HexagonSubtarget.h"
-
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/Constants.h"
-#include "llvm/Support/CommandLine.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetInstrInfo.h"
-
+#include "llvm/Target/TargetRegisterInfo.h"
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <iterator>
#include <map>
#include <queue>
#include <set>
+#include <utility>
+#include <vector>
using namespace llvm;
namespace {
- class LatticeCell;
// Properties of a value that are tracked by the propagation.
// A property that is marked as present (i.e. bit is set) dentes that the
static uint32_t deduce(const Constant *C);
};
-
// A representation of a register as it can appear in a MachineOperand,
// i.e. a pair register:subregister.
struct Register {
unsigned Reg, SubReg;
+
explicit Register(unsigned R, unsigned SR = 0) : Reg(R), SubReg(SR) {}
explicit Register(const MachineOperand &MO)
: Reg(MO.getReg()), SubReg(MO.getSubReg()) {}
- void print(const TargetRegisterInfo *TRI = 0) const {
+
+ void print(const TargetRegisterInfo *TRI = nullptr) const {
dbgs() << PrintReg(Reg, TRI, SubReg);
}
+
bool operator== (const Register &R) const {
return (Reg == R.Reg) && (SubReg == R.SubReg);
}
};
-
// Lattice cell, based on that was described in the W-Z paper on constant
// propagation.
// Latice cell will be allowed to hold multiple constant values. While
class LatticeCell {
private:
enum { Normal, Top, Bottom };
+
static const unsigned MaxCellSize = 4;
+
unsigned Kind:2;
unsigned Size:3;
unsigned IsSpecial:1;
LatticeCell() : Kind(Top), Size(0), IsSpecial(false) {
for (unsigned i = 0; i < MaxCellSize; ++i)
- Values[i] = 0;
+ Values[i] = nullptr;
}
bool meet(const LatticeCell &L);
bool isProperty() const { return IsSpecial; }
bool isTop() const { return Kind == Top; }
bool isBottom() const { return Kind == Bottom; }
+
bool setBottom() {
bool Changed = (Kind != Bottom);
Kind = Bottom;
IsSpecial = false;
return Changed;
}
+
void print(raw_ostream &os) const;
private:
Size = 0;
Kind = Normal;
}
+
bool convertToProperty();
};
assert(Top.isTop());
Bottom.setBottom();
}
+
void clear() { Map.clear(); }
+
bool has(unsigned R) const {
// All non-virtual registers are considered "bottom".
if (!TargetRegisterInfo::isVirtualRegister(R))
MapType::const_iterator F = Map.find(R);
return F != Map.end();
}
+
const LatticeCell &get(unsigned R) const {
if (!TargetRegisterInfo::isVirtualRegister(R))
return Bottom;
return F->second;
return Top;
}
+
// Invalidates any const references.
void update(unsigned R, const LatticeCell &L) {
Map[R] = L;
}
+
void print(raw_ostream &os, const TargetRegisterInfo &TRI) const;
+
private:
typedef std::map<unsigned,LatticeCell> MapType;
MapType Map;
// this cell in "get". Also, have a "Bottom" cell to return from
// get when a value of a physical register is requested.
LatticeCell Top, Bottom;
+
public:
typedef MapType::const_iterator const_iterator;
const_iterator begin() const { return Map.begin(); }
QueueOfCFGEdge FlowQ;
};
-
// The "evaluator/rewriter" of machine instructions. This is an abstract
// base class that provides the interface that the propagator will use,
// as well as some helper functions that are target-independent.
MachineConstEvaluator(MachineFunction &Fn)
: TRI(*Fn.getSubtarget().getRegisterInfo()),
MF(Fn), CX(Fn.getFunction()->getContext()) {}
- virtual ~MachineConstEvaluator() {}
+ virtual ~MachineConstEvaluator() = default;
// The required interface:
// - A set of three "evaluate" functions. Each returns "true" if the
GTu = G | U,
GEu = G | EQ | U
};
+
static uint32_t negate(uint32_t Cmp) {
if (Cmp == EQ)
return NE;
APInt &Result);
};
-}
+} // end anonymous namespace
uint32_t ConstantProperties::deduce(const Constant *C) {
if (isa<ConstantInt>(C)) {
return Unknown;
}
-
// Convert a cell from a set of specific values to a cell that tracks
// properties.
bool LatticeCell::convertToProperty() {
return true;
}
-
void LatticeCell::print(raw_ostream &os) const {
if (isProperty()) {
os << "{ ";
os << " }";
}
-
// "Meet" operation on two cells. This is the key of the propagation
// algorithm.
bool LatticeCell::meet(const LatticeCell &L) {
return Changed;
}
-
// Add a new constant to the cell. This is actually where the cell update
// happens. If a cell has room for more constants, the new constant is added.
// Otherwise, the cell is converted to a "property" cell (i.e. a cell that
return Changed;
}
-
// Add a property to the cell. This will force the cell to become a property-
// tracking cell.
bool LatticeCell::add(uint32_t Property) {
return true;
}
-
// Return the properties of the values in the cell. This is valid for any
// cell, and does not alter the cell itself.
uint32_t LatticeCell::properties() const {
return Ps;
}
-
void MachineConstPropagator::CellMap::print(raw_ostream &os,
const TargetRegisterInfo &TRI) const {
for (auto &I : Map)
dbgs() << " " << PrintReg(I.first, &TRI) << " -> " << I.second << '\n';
}
-
void MachineConstPropagator::visitPHI(const MachineInstr &PN) {
const MachineBasicBlock *MB = PN.getParent();
unsigned MBN = MB->getNumber();
visitUsesOf(DefR.Reg);
}
-
void MachineConstPropagator::visitNonBranch(const MachineInstr &MI) {
DEBUG(dbgs() << "Visiting MI(BB#" << MI.getParent()->getNumber()
<< "): " << MI);
}
}
-
// \brief Starting at a given branch, visit remaining branches in the block.
// Traverse over the subsequent branches for as long as the preceding one
// can fall through. Add all the possible targets to the flow work queue,
}
}
-
void MachineConstPropagator::visitUsesOf(unsigned Reg) {
DEBUG(dbgs() << "Visiting uses of " << PrintReg(Reg, &MCE.TRI)
<< Cells.get(Reg) << '\n');
return true;
}
-
void MachineConstPropagator::removeCFGEdge(MachineBasicBlock *From,
MachineBasicBlock *To) {
// First, remove the CFG successor/predecessor information.
}
}
-
void MachineConstPropagator::propagate(MachineFunction &MF) {
MachineBasicBlock *Entry = GraphTraits<MachineFunction*>::getEntryNode(&MF);
unsigned EntryNum = Entry->getNumber();
});
}
-
bool MachineConstPropagator::rewrite(MachineFunction &MF) {
bool Changed = false;
// Rewrite all instructions based on the collected cell information.
return Changed;
}
-
// This is the constant propagation algorithm as described by Wegman-Zadeck.
// Most of the terminology comes from there.
bool MachineConstPropagator::run(MachineFunction &MF) {
return Changed;
}
-
// --------------------------------------------------------------------
// Machine const evaluator.
return Eval && !RC.isBottom();
}
-
bool MachineConstEvaluator::constToInt(const Constant *C,
APInt &Val) const {
const ConstantInt *CI = dyn_cast<ConstantInt>(C);
return true;
}
-
const ConstantInt *MachineConstEvaluator::intToConst(const APInt &Val) const {
return ConstantInt::get(CX, Val);
}
-
bool MachineConstEvaluator::evaluateCMPrr(uint32_t Cmp, const Register &R1,
const Register &R2, const CellMap &Inputs, bool &Result) {
assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
return IsTrue || IsFalse;
}
-
bool MachineConstEvaluator::evaluateCMPri(uint32_t Cmp, const Register &R1,
const APInt &A2, const CellMap &Inputs, bool &Result) {
assert(Inputs.has(R1.Reg));
return IsTrue || IsFalse;
}
-
bool MachineConstEvaluator::evaluateCMPrp(uint32_t Cmp, const Register &R1,
uint64_t Props2, const CellMap &Inputs, bool &Result) {
assert(Inputs.has(R1.Reg));
return IsTrue || IsFalse;
}
-
bool MachineConstEvaluator::evaluateCMPii(uint32_t Cmp, const APInt &A1,
const APInt &A2, bool &Result) {
// NE is a special kind of comparison (not composed of smaller properties).
return true;
}
-
bool MachineConstEvaluator::evaluateCMPpi(uint32_t Cmp, uint32_t Props,
const APInt &A2, bool &Result) {
if (Props == ConstantProperties::Unknown)
return false;
}
-
bool MachineConstEvaluator::evaluateCMPpp(uint32_t Cmp, uint32_t Props1,
uint32_t Props2, bool &Result) {
typedef ConstantProperties P;
return false;
}
-
bool MachineConstEvaluator::evaluateCOPY(const Register &R1,
const CellMap &Inputs, LatticeCell &Result) {
return getCell(R1, Inputs, Result);
}
-
bool MachineConstEvaluator::evaluateANDrr(const Register &R1,
const Register &R2, const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
return !Result.isBottom();
}
-
bool MachineConstEvaluator::evaluateANDri(const Register &R1,
const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(R1.Reg));
return !Result.isBottom();
}
-
bool MachineConstEvaluator::evaluateANDii(const APInt &A1,
const APInt &A2, APInt &Result) {
Result = A1 & A2;
return true;
}
-
bool MachineConstEvaluator::evaluateORrr(const Register &R1,
const Register &R2, const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
return !Result.isBottom();
}
-
bool MachineConstEvaluator::evaluateORri(const Register &R1,
const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(R1.Reg));
return !Result.isBottom();
}
-
bool MachineConstEvaluator::evaluateORii(const APInt &A1,
const APInt &A2, APInt &Result) {
Result = A1 | A2;
return true;
}
-
bool MachineConstEvaluator::evaluateXORrr(const Register &R1,
const Register &R2, const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
return !Result.isBottom();
}
-
bool MachineConstEvaluator::evaluateXORri(const Register &R1,
const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(R1.Reg));
return !Result.isBottom();
}
-
bool MachineConstEvaluator::evaluateXORii(const APInt &A1,
const APInt &A2, APInt &Result) {
Result = A1 ^ A2;
return true;
}
-
bool MachineConstEvaluator::evaluateZEXTr(const Register &R1, unsigned Width,
unsigned Bits, const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(R1.Reg));
return true;
}
-
bool MachineConstEvaluator::evaluateZEXTi(const APInt &A1, unsigned Width,
unsigned Bits, APInt &Result) {
unsigned BW = A1.getBitWidth();
return true;
}
-
bool MachineConstEvaluator::evaluateSEXTr(const Register &R1, unsigned Width,
unsigned Bits, const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(R1.Reg));
return true;
}
-
bool MachineConstEvaluator::evaluateSEXTi(const APInt &A1, unsigned Width,
unsigned Bits, APInt &Result) {
unsigned BW = A1.getBitWidth();
return true;
}
-
bool MachineConstEvaluator::evaluateCLBr(const Register &R1, bool Zeros,
bool Ones, const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(R1.Reg));
return true;
}
-
bool MachineConstEvaluator::evaluateCLBi(const APInt &A1, bool Zeros,
bool Ones, APInt &Result) {
unsigned BW = A1.getBitWidth();
return true;
}
-
bool MachineConstEvaluator::evaluateCTBr(const Register &R1, bool Zeros,
bool Ones, const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(R1.Reg));
return true;
}
-
bool MachineConstEvaluator::evaluateCTBi(const APInt &A1, bool Zeros,
bool Ones, APInt &Result) {
unsigned BW = A1.getBitWidth();
return true;
}
-
bool MachineConstEvaluator::evaluateEXTRACTr(const Register &R1,
unsigned Width, unsigned Bits, unsigned Offset, bool Signed,
const CellMap &Inputs, LatticeCell &Result) {
return true;
}
-
bool MachineConstEvaluator::evaluateEXTRACTi(const APInt &A1, unsigned Bits,
unsigned Offset, bool Signed, APInt &Result) {
unsigned BW = A1.getBitWidth();
return true;
}
-
bool MachineConstEvaluator::evaluateSplatr(const Register &R1,
unsigned Bits, unsigned Count, const CellMap &Inputs,
LatticeCell &Result) {
return true;
}
-
bool MachineConstEvaluator::evaluateSplati(const APInt &A1, unsigned Bits,
unsigned Count, APInt &Result) {
assert(Count > 0);
return true;
}
-
// ----------------------------------------------------------------------
// Hexagon-specific code.
namespace llvm {
+
FunctionPass *createHexagonConstPropagationPass();
void initializeHexagonConstPropagationPass(PassRegistry &Registry);
-}
+
+} // end namespace llvm
namespace {
+
class HexagonConstEvaluator : public MachineConstEvaluator {
public:
HexagonConstEvaluator(MachineFunction &Fn);
override;
bool rewrite(MachineInstr &MI, const CellMap &Inputs) override;
-
private:
unsigned getRegBitWidth(unsigned Reg) const;
const HexagonRegisterInfo &HRI;
};
-
class HexagonConstPropagation : public MachineFunctionPass {
public:
static char ID;
+
HexagonConstPropagation() : MachineFunctionPass(ID) {
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeHexagonConstPropagationPass(Registry);
}
+
StringRef getPassName() const override {
return "Hexagon Constant Propagation";
}
+
bool runOnMachineFunction(MachineFunction &MF) override {
const Function *F = MF.getFunction();
if (!F)
};
char HexagonConstPropagation::ID = 0;
-}
+
+} // end anonymous namespace
INITIALIZE_PASS(HexagonConstPropagation, "hcp", "Hexagon Constant Propagation",
false, false)
-
HexagonConstEvaluator::HexagonConstEvaluator(MachineFunction &Fn)
: MachineConstEvaluator(Fn),
HII(*Fn.getSubtarget<HexagonSubtarget>().getInstrInfo()),
MRI = &Fn.getRegInfo();
}
-
bool HexagonConstEvaluator::evaluate(const MachineInstr &MI,
const CellMap &Inputs, CellMap &Outputs) {
if (MI.isCall())
case Hexagon::S2_ct1p:
{
using namespace Hexagon;
+
bool Ones = (Opc == S2_ct1) || (Opc == S2_ct1p);
Register R1(MI.getOperand(1));
assert(Inputs.has(R1.Reg));
case Hexagon::S2_clbp:
{
using namespace Hexagon;
+
bool OnlyZeros = (Opc == S2_cl0) || (Opc == S2_cl0p);
bool OnlyOnes = (Opc == S2_cl1) || (Opc == S2_cl1p);
Register R1(MI.getOperand(1));
return true;
}
-
bool HexagonConstEvaluator::evaluate(const Register &R,
const LatticeCell &Input, LatticeCell &Result) {
if (!R.SubReg) {
return true;
}
-
bool HexagonConstEvaluator::evaluate(const MachineInstr &BrI,
const CellMap &Inputs, SetVector<const MachineBasicBlock*> &Targets,
bool &FallsThru) {
return true;
}
-
bool HexagonConstEvaluator::rewrite(MachineInstr &MI, const CellMap &Inputs) {
if (MI.isBranch())
return rewriteHexBranch(MI, Inputs);
return Changed;
}
-
unsigned HexagonConstEvaluator::getRegBitWidth(unsigned Reg) const {
const TargetRegisterClass *RC = MRI->getRegClass(Reg);
if (Hexagon::IntRegsRegClass.hasSubClassEq(RC))
return 0;
}
-
uint32_t HexagonConstEvaluator::getCmp(unsigned Opc) {
switch (Opc) {
case Hexagon::C2_cmpeq:
return Comparison::Unk;
}
-
APInt HexagonConstEvaluator::getCmpImm(unsigned Opc, unsigned OpX,
const MachineOperand &MO) {
bool Signed = false;
return APInt(32, Val, Signed);
}
-
void HexagonConstEvaluator::replaceWithNop(MachineInstr &MI) {
MI.setDesc(HII.get(Hexagon::A2_nop));
while (MI.getNumOperands() > 0)
MI.RemoveOperand(0);
}
-
bool HexagonConstEvaluator::evaluateHexRSEQ32(Register RL, Register RH,
const CellMap &Inputs, LatticeCell &Result) {
assert(Inputs.has(RL.Reg) && Inputs.has(RH.Reg));
return !Result.isBottom();
}
-
bool HexagonConstEvaluator::evaluateHexCompare(const MachineInstr &MI,
const CellMap &Inputs, CellMap &Outputs) {
unsigned Opc = MI.getOpcode();
return false;
}
-
bool HexagonConstEvaluator::evaluateHexCompare2(unsigned Opc,
const MachineOperand &Src1, const MachineOperand &Src2,
const CellMap &Inputs, bool &Result) {
return false;
}
-
bool HexagonConstEvaluator::evaluateHexLogical(const MachineInstr &MI,
const CellMap &Inputs, CellMap &Outputs) {
unsigned Opc = MI.getOpcode();
return Eval;
}
-
bool HexagonConstEvaluator::evaluateHexCondMove(const MachineInstr &MI,
const CellMap &Inputs, CellMap &Outputs) {
// Dst0 = Cond1 ? Src2 : Src3
return false;
}
-
bool HexagonConstEvaluator::evaluateHexExt(const MachineInstr &MI,
const CellMap &Inputs, CellMap &Outputs) {
// Dst0 = ext R1
return true;
}
-
bool HexagonConstEvaluator::evaluateHexVector1(const MachineInstr &MI,
const CellMap &Inputs, CellMap &Outputs) {
// DefR = op R1
return true;
}
-
bool HexagonConstEvaluator::rewriteHexConstDefs(MachineInstr &MI,
const CellMap &Inputs, bool &AllDefs) {
AllDefs = false;
// Some diagnostics.
// DEBUG({...}) gets confused with all this code as an argument.
#ifndef NDEBUG
- bool Debugging = llvm::DebugFlag &&
- llvm::isCurrentDebugType(DEBUG_TYPE);
+ bool Debugging = DebugFlag && isCurrentDebugType(DEBUG_TYPE);
if (Debugging) {
bool Const = true, HasUse = false;
for (const MachineOperand &MO : MI.operands()) {
return ChangedNum > 0;
}
-
bool HexagonConstEvaluator::rewriteHexConstUses(MachineInstr &MI,
const CellMap &Inputs) {
bool Changed = false;
MachineBasicBlock &B = *MI.getParent();
const DebugLoc &DL = MI.getDebugLoc();
MachineBasicBlock::iterator At = MI.getIterator();
- MachineInstr *NewMI = NULL;
+ MachineInstr *NewMI = nullptr;
switch (Opc) {
case Hexagon::M2_maci:
return Changed;
}
-
void HexagonConstEvaluator::replaceAllRegUsesWith(unsigned FromReg,
unsigned ToReg) {
assert(TargetRegisterInfo::isVirtualRegister(FromReg));
}
}
-
bool HexagonConstEvaluator::rewriteHexBranch(MachineInstr &BrI,
const CellMap &Inputs) {
MachineBasicBlock &B = *BrI.getParent();
return true;
}
-
-// --------------------------------------------------------------------
FunctionPass *llvm::createHexagonConstPropagationPass() {
return new HexagonConstPropagation();
}
-
#define DEBUG_TYPE "hexagon-eif"
+#include "Hexagon.h"
+#include "HexagonInstrInfo.h"
+#include "HexagonSubtarget.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "HexagonTargetMachine.h"
-
-#include <functional>
+#include "llvm/Target/TargetRegisterInfo.h"
+#include <cassert>
+#include <iterator>
using namespace llvm;
namespace llvm {
+
FunctionPass *createHexagonEarlyIfConversion();
void initializeHexagonEarlyIfConversionPass(PassRegistry& Registry);
-}
+
+} // end namespace llvm
namespace {
+
cl::opt<bool> EnableHexagonBP("enable-hexagon-br-prob", cl::Hidden,
cl::init(false), cl::desc("Enable branch probability info"));
cl::opt<unsigned> SizeLimit("eif-limit", cl::init(6), cl::Hidden,
}
struct FlowPattern {
- FlowPattern() : SplitB(0), TrueB(0), FalseB(0), JoinB(0), PredR(0) {}
+ FlowPattern() = default;
FlowPattern(MachineBasicBlock *B, unsigned PR, MachineBasicBlock *TB,
MachineBasicBlock *FB, MachineBasicBlock *JB)
: SplitB(B), TrueB(TB), FalseB(FB), JoinB(JB), PredR(PR) {}
- MachineBasicBlock *SplitB;
- MachineBasicBlock *TrueB, *FalseB, *JoinB;
- unsigned PredR;
+ MachineBasicBlock *SplitB = nullptr;
+ MachineBasicBlock *TrueB = nullptr;
+ MachineBasicBlock *FalseB = nullptr;
+ MachineBasicBlock *JoinB = nullptr;
+ unsigned PredR = 0;
};
+
struct PrintFP {
PrintFP(const FlowPattern &P, const TargetRegisterInfo &T)
: FP(P), TRI(T) {}
+
const FlowPattern &FP;
const TargetRegisterInfo &TRI;
friend raw_ostream &operator<< (raw_ostream &OS, const PrintFP &P);
class HexagonEarlyIfConversion : public MachineFunctionPass {
public:
static char ID;
+
HexagonEarlyIfConversion() : MachineFunctionPass(ID),
- HII(0), TRI(0), MFN(0), MRI(0), MDT(0), MLI(0) {
+ HII(nullptr), TRI(nullptr), MFN(nullptr), MRI(nullptr), MDT(nullptr),
+ MLI(nullptr) {
initializeHexagonEarlyIfConversionPass(*PassRegistry::getPassRegistry());
}
+
StringRef getPassName() const override {
return "Hexagon early if conversion";
}
+
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineBranchProbabilityInfo>();
AU.addRequired<MachineDominatorTree>();
AU.addRequired<MachineLoopInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
}
+
bool runOnMachineFunction(MachineFunction &MF) override;
private:
};
char HexagonEarlyIfConversion::ID = 0;
-}
+
+} // end anonymous namespace
INITIALIZE_PASS(HexagonEarlyIfConversion, "hexagon-eif",
"Hexagon early if conversion", false, false)
return L && SB == L->getHeader();
}
-
bool HexagonEarlyIfConversion::matchFlowPattern(MachineBasicBlock *B,
MachineLoop *L, FlowPattern &FP) {
DEBUG(dbgs() << "Checking flow pattern at BB#" << B->getNumber() << "\n");
// Interested only in conditional branches, no .new, no new-value, etc.
// Check the terminators directly, it's easier than handling all responses
// from AnalyzeBranch.
- MachineBasicBlock *TB = 0, *FB = 0;
+ MachineBasicBlock *TB = nullptr, *FB = nullptr;
MachineBasicBlock::const_iterator T1I = B->getFirstTerminator();
if (T1I == B->end())
return false;
// Get the layout successor, or 0 if B does not have one.
MachineFunction::iterator NextBI = std::next(MachineFunction::iterator(B));
- MachineBasicBlock *NextB = (NextBI != MFN->end()) ? &*NextBI : 0;
+ MachineBasicBlock *NextB = (NextBI != MFN->end()) ? &*NextBI : nullptr;
MachineBasicBlock *T1B = T1I->getOperand(1).getMBB();
MachineBasicBlock::const_iterator T2I = std::next(T1I);
if (!TOk && !FOk)
return false;
- MachineBasicBlock *TSB = (TNS > 0) ? *TB->succ_begin() : 0;
- MachineBasicBlock *FSB = (FNS > 0) ? *FB->succ_begin() : 0;
- MachineBasicBlock *JB = 0;
+ MachineBasicBlock *TSB = (TNS > 0) ? *TB->succ_begin() : nullptr;
+ MachineBasicBlock *FSB = (FNS > 0) ? *FB->succ_begin() : nullptr;
+ MachineBasicBlock *JB = nullptr;
if (TOk) {
if (FOk) {
// TOk && !FOk
if (TSB == FB) {
JB = FB;
- FB = 0;
+ FB = nullptr;
}
}
} else {
// !TOk && FOk (at least one must be true by now).
if (FSB == TB) {
JB = TB;
- TB = 0;
+ TB = nullptr;
}
}
// Don't try to predicate loop preheaders.
return true;
}
-
// KLUDGE: HexagonInstrInfo::AnalyzeBranch won't work on a block that
// contains EH_LABEL.
bool HexagonEarlyIfConversion::hasEHLabel(const MachineBasicBlock *B) const {
return false;
}
-
// KLUDGE: HexagonInstrInfo::AnalyzeBranch may be unable to recognize
// that a block can never fall-through.
bool HexagonEarlyIfConversion::hasUncondBranch(const MachineBasicBlock *B)
return false;
}
-
bool HexagonEarlyIfConversion::isValidCandidate(const MachineBasicBlock *B)
const {
if (!B)
return true;
}
-
bool HexagonEarlyIfConversion::usesUndefVReg(const MachineInstr *MI) const {
for (const MachineOperand &MO : MI->operands()) {
if (!MO.isReg() || !MO.isUse())
return false;
}
-
bool HexagonEarlyIfConversion::isValid(const FlowPattern &FP) const {
if (hasEHLabel(FP.SplitB)) // KLUDGE: see function definition
return false;
return true;
}
-
unsigned HexagonEarlyIfConversion::computePhiCost(MachineBasicBlock *B) const {
assert(B->pred_size() <= 2);
if (B->pred_size() < 2)
return Cost;
}
-
unsigned HexagonEarlyIfConversion::countPredicateDefs(
const MachineBasicBlock *B) const {
unsigned PredDefs = 0;
return PredDefs;
}
-
bool HexagonEarlyIfConversion::isProfitable(const FlowPattern &FP) const {
if (FP.TrueB && FP.FalseB) {
return true;
}
-
bool HexagonEarlyIfConversion::visitBlock(MachineBasicBlock *B,
MachineLoop *L) {
bool Changed = false;
return true;
}
-
bool HexagonEarlyIfConversion::visitLoop(MachineLoop *L) {
- MachineBasicBlock *HB = L ? L->getHeader() : 0;
+ MachineBasicBlock *HB = L ? L->getHeader() : nullptr;
DEBUG((L ? dbgs() << "Visiting loop H:" << PrintMB(HB)
: dbgs() << "Visiting function") << "\n");
bool Changed = false;
return Changed;
}
-
bool HexagonEarlyIfConversion::isPredicableStore(const MachineInstr *MI)
const {
// HexagonInstrInfo::isPredicable will consider these stores are non-
return MI->mayStore() && HII->isPredicable(const_cast<MachineInstr&>(*MI));
}
-
bool HexagonEarlyIfConversion::isSafeToSpeculate(const MachineInstr *MI)
const {
if (MI->mayLoad() || MI->mayStore())
return true;
}
-
unsigned HexagonEarlyIfConversion::getCondStoreOpcode(unsigned Opc,
bool IfTrue) const {
return HII->getCondOpcode(Opc, !IfTrue);
}
-
void HexagonEarlyIfConversion::predicateInstr(MachineBasicBlock *ToB,
MachineBasicBlock::iterator At, MachineInstr *MI,
unsigned PredR, bool IfTrue) {
llvm_unreachable("Unexpected instruction");
}
-
// Predicate/speculate non-branch instructions from FromB into block ToB.
// Leave the branches alone, they will be handled later. Btw, at this point
// FromB should have at most one branch, and it should be unconditional.
}
}
-
void HexagonEarlyIfConversion::updatePhiNodes(MachineBasicBlock *WhereB,
const FlowPattern &FP) {
// Visit all PHI nodes in the WhereB block and generate MUX instructions
assert(TR && FR);
using namespace Hexagon;
+
unsigned DR = PN->getOperand(0).getReg();
const TargetRegisterClass *RC = MRI->getRegClass(DR);
unsigned Opc = 0;
}
}
-
void HexagonEarlyIfConversion::convert(const FlowPattern &FP) {
- MachineBasicBlock *TSB = 0, *FSB = 0;
+ MachineBasicBlock *TSB = nullptr, *FSB = nullptr;
MachineBasicBlock::iterator OldTI = FP.SplitB->getFirstTerminator();
assert(OldTI != FP.SplitB->end());
DebugLoc DL = OldTI->getDebugLoc();
// Regenerate new terminators in the split block and update the successors.
// First, remember any information that may be needed later and remove the
// existing terminators/successors from the split block.
- MachineBasicBlock *SSB = 0;
+ MachineBasicBlock *SSB = nullptr;
FP.SplitB->erase(OldTI, FP.SplitB->end());
while (FP.SplitB->succ_size() > 0) {
MachineBasicBlock *T = *FP.SplitB->succ_begin();
}
}
-
void HexagonEarlyIfConversion::removeBlock(MachineBasicBlock *B) {
DEBUG(dbgs() << "Removing block " << PrintMB(B) << "\n");
MFN->erase(B->getIterator());
}
-
void HexagonEarlyIfConversion::eliminatePhis(MachineBasicBlock *B) {
DEBUG(dbgs() << "Removing phi nodes from block " << PrintMB(B) << "\n");
MachineBasicBlock::iterator I, NextI, NonPHI = B->getFirstNonPHI();
}
}
-
void HexagonEarlyIfConversion::replacePhiEdges(MachineBasicBlock *OldB,
MachineBasicBlock *NewB) {
for (auto I = OldB->succ_begin(), E = OldB->succ_end(); I != E; ++I) {
}
}
-
void HexagonEarlyIfConversion::mergeBlocks(MachineBasicBlock *PredB,
MachineBasicBlock *SuccB) {
DEBUG(dbgs() << "Merging blocks " << PrintMB(PredB) << " and "
PredB->updateTerminator();
}
-
void HexagonEarlyIfConversion::simplifyFlowGraph(const FlowPattern &FP) {
if (FP.TrueB)
removeBlock(FP.TrueB);
mergeBlocks(FP.SplitB, SB);
}
-
bool HexagonEarlyIfConversion::runOnMachineFunction(MachineFunction &MF) {
if (skipFunction(*MF.getFunction()))
return false;
for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); I != E; ++I)
Changed |= visitLoop(*I);
- Changed |= visitLoop(0);
+ Changed |= visitLoop(nullptr);
return Changed;
}
FunctionPass *llvm::createHexagonEarlyIfConversion() {
return new HexagonEarlyIfConversion();
}
-
#define DEBUG_TYPE "expand-condsets"
-#include "HexagonTargetMachine.h"
+#include "HexagonInstrInfo.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
-#include "llvm/CodeGen/Passes.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/CodeGen/SlotIndexes.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-
-#include <algorithm>
+#include "llvm/Target/TargetRegisterInfo.h"
+#include <cassert>
#include <iterator>
#include <set>
#include <utility>
cl::init(~0U), cl::Hidden, cl::desc("Max number of segment coalescings"));
namespace llvm {
+
void initializeHexagonExpandCondsetsPass(PassRegistry&);
FunctionPass *createHexagonExpandCondsets();
-}
+
+} // end namespace llvm
namespace {
+
class HexagonExpandCondsets : public MachineFunctionPass {
public:
static char ID;
+
HexagonExpandCondsets() :
- MachineFunctionPass(ID), HII(0), TRI(0), MRI(0),
- LIS(0), CoaLimitActive(false),
+ MachineFunctionPass(ID), HII(nullptr), TRI(nullptr), MRI(nullptr),
+ LIS(nullptr), CoaLimitActive(false),
TfrLimitActive(false), CoaCounter(0), TfrCounter(0) {
if (OptCoaLimit.getPosition())
CoaLimitActive = true, CoaLimit = OptCoaLimit;
}
StringRef getPassName() const override { return "Hexagon Expand Condsets"; }
+
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<LiveIntervals>();
AU.addPreserved<LiveIntervals>();
AU.addPreserved<MachineDominatorTree>();
MachineFunctionPass::getAnalysisUsage(AU);
}
+
bool runOnMachineFunction(MachineFunction &MF) override;
private:
RegisterRef(const MachineOperand &Op) : Reg(Op.getReg()),
Sub(Op.getSubReg()) {}
RegisterRef(unsigned R = 0, unsigned S = 0) : Reg(R), Sub(S) {}
+
bool operator== (RegisterRef RR) const {
return Reg == RR.Reg && Sub == RR.Sub;
}
bool operator< (RegisterRef RR) const {
return Reg < RR.Reg || (Reg == RR.Reg && Sub < RR.Sub);
}
+
unsigned Reg, Sub;
};
bool coalesceSegments(const SmallVectorImpl<MachineInstr*> &Condsets,
std::set<unsigned> &UpdRegs);
};
-}
+
+} // end anonymous namespace
char HexagonExpandCondsets::ID = 0;
namespace llvm {
+
char &HexagonExpandCondsetsID = HexagonExpandCondsets::ID;
-}
+
+} // end namespace llvm
INITIALIZE_PASS_BEGIN(HexagonExpandCondsets, "expand-condsets",
"Hexagon Expand Condsets", false, false)
return false;
}
-
LaneBitmask HexagonExpandCondsets::getLaneMask(unsigned Reg, unsigned Sub) {
assert(TargetRegisterInfo::isVirtualRegister(Reg));
return Sub != 0 ? TRI->getSubRegIndexLaneMask(Sub)
: MRI->getMaxLaneMaskForVReg(Reg);
}
-
void HexagonExpandCondsets::addRefToMap(RegisterRef RR, ReferenceMap &Map,
unsigned Exec) {
unsigned Mask = getMaskForSub(RR.Sub) | Exec;
F->second |= Mask;
}
-
bool HexagonExpandCondsets::isRefInMap(RegisterRef RR, ReferenceMap &Map,
unsigned Exec) {
ReferenceMap::iterator F = Map.find(RR.Reg);
return false;
}
-
void HexagonExpandCondsets::updateKillFlags(unsigned Reg) {
auto KillAt = [this,Reg] (SlotIndex K, LaneBitmask LM) -> void {
// Set the <kill> flag on a use of Reg whose lane mask is contained in LM.
}
}
-
void HexagonExpandCondsets::updateDeadsInRange(unsigned Reg, LaneBitmask LM,
LiveRange &Range) {
assert(TargetRegisterInfo::isVirtualRegister(Reg));
}
}
-
void HexagonExpandCondsets::updateDeadFlags(unsigned Reg) {
LiveInterval &LI = LIS->getInterval(Reg);
if (LI.hasSubRanges()) {
}
}
-
void HexagonExpandCondsets::recalculateLiveInterval(unsigned Reg) {
LIS->removeInterval(Reg);
LIS->createAndComputeVirtRegInterval(Reg);
}
-
void HexagonExpandCondsets::removeInstr(MachineInstr &MI) {
LIS->RemoveMachineInstrFromMaps(MI);
MI.eraseFromParent();
}
-
void HexagonExpandCondsets::updateLiveness(std::set<unsigned> &RegSet,
bool Recalc, bool UpdateKills, bool UpdateDeads) {
UpdateKills |= UpdateDeads;
}
}
-
/// Get the opcode for a conditional transfer of the value in SO (source
/// operand). The condition (true/false) is given in Cond.
unsigned HexagonExpandCondsets::getCondTfrOpcode(const MachineOperand &SO,
bool IfTrue) {
using namespace Hexagon;
+
if (SO.isReg()) {
unsigned PhysR;
RegisterRef RS = SO;
llvm_unreachable("Unexpected source operand");
}
-
/// Generate a conditional transfer, copying the value SrcOp to the
/// destination register DstR:DstSR, and using the predicate register from
/// PredOp. The Cond argument specifies whether the predicate is to be
return &*MIB;
}
-
/// Replace a MUX instruction MI with a pair A2_tfrt/A2_tfrf. This function
/// performs all necessary changes to complete the replacement.
bool HexagonExpandCondsets::split(MachineInstr &MI,
return true;
}
-
/// Find the reaching definition for a predicated use of RD. The RD is used
/// under the conditions given by PredR and Cond, and this function will ignore
/// definitions that set RD under the opposite conditions.
MachineBasicBlock &B = *UseIt->getParent();
MachineBasicBlock::iterator I = UseIt, S = B.begin();
if (I == S)
- return 0;
+ return nullptr;
bool PredValid = true;
do {
if (RR.Sub == RD.Sub)
return MI;
if (RR.Sub == 0 || RD.Sub == 0)
- return 0;
+ return nullptr;
// We have different subregisters, so we can continue looking.
}
} while (I != S);
- return 0;
+ return nullptr;
}
-
/// Check if the instruction MI can be safely moved over a set of instructions
/// whose side-effects (in terms of register defs and uses) are expressed in
/// the maps Defs and Uses. These maps reflect the conditional defs and uses
return true;
}
-
/// Check if the instruction accessing memory (TheI) can be moved to the
/// location ToI.
bool HexagonExpandCondsets::canMoveMemTo(MachineInstr &TheI, MachineInstr &ToI,
return true;
}
-
/// Generate a predicated version of MI (where the condition is given via
/// PredR and Cond) at the point indicated by Where.
void HexagonExpandCondsets::predicateAt(const MachineOperand &DefOp,
UpdRegs.insert(Op.getReg());
}
-
/// In the range [First, Last], rename all references to the "old" register RO
/// to the "new" register RN, but only in instructions predicated on the given
/// condition.
}
}
-
/// For a given conditional copy, predicate the definition of the source of
/// the copy under the given condition (using the same predicate register as
/// the copy).
// conditions when collecting def and use information.
bool PredValid = true;
for (MachineBasicBlock::iterator I = std::next(DefIt); I != TfrIt; ++I) {
- if (!I->modifiesRegister(PredR, 0))
+ if (!I->modifiesRegister(PredR, nullptr))
continue;
PredValid = false;
break;
return true;
}
-
/// Predicate all cases of conditional copies in the specified block.
bool HexagonExpandCondsets::predicateInBlock(MachineBasicBlock &B,
std::set<unsigned> &UpdRegs) {
return Changed;
}
-
bool HexagonExpandCondsets::isIntReg(RegisterRef RR, unsigned &BW) {
if (!TargetRegisterInfo::isVirtualRegister(RR.Reg))
return false;
return false;
}
-
bool HexagonExpandCondsets::isIntraBlocks(LiveInterval &LI) {
for (LiveInterval::iterator I = LI.begin(), E = LI.end(); I != E; ++I) {
LiveRange::Segment &LR = *I;
return true;
}
-
bool HexagonExpandCondsets::coalesceRegisters(RegisterRef R1, RegisterRef R2) {
if (CoaLimitActive) {
if (CoaCounter >= CoaLimit)
return true;
}
-
/// Attempt to coalesce one of the source registers to a MUX instruction with
/// the destination register. This could lead to having only one predicated
/// instruction in the end instead of two.
return Changed;
}
-
bool HexagonExpandCondsets::runOnMachineFunction(MachineFunction &MF) {
if (skipFunction(*MF.getFunction()))
return false;
return Changed;
}
-
//===----------------------------------------------------------------------===//
// Public Constructor Functions
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
-#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/PatternMatch.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
using namespace llvm;
cl::desc("Require & in extract patterns"));
namespace llvm {
+
void initializeHexagonGenExtractPass(PassRegistry&);
FunctionPass *createHexagonGenExtract();
-}
+} // end namespace llvm
namespace {
+
class HexagonGenExtract : public FunctionPass {
public:
static char ID;
+
HexagonGenExtract() : FunctionPass(ID), ExtractCount(0) {
initializeHexagonGenExtractPass(*PassRegistry::getPassRegistry());
}
- virtual StringRef getPassName() const override {
+
+ StringRef getPassName() const override {
return "Hexagon generate \"extract\" instructions";
}
- virtual bool runOnFunction(Function &F) override;
- virtual void getAnalysisUsage(AnalysisUsage &AU) const override {
+
+ bool runOnFunction(Function &F) override;
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<DominatorTreeWrapperPass>();
AU.addPreserved<DominatorTreeWrapperPass>();
FunctionPass::getAnalysisUsage(AU);
}
+
private:
bool visitBlock(BasicBlock *B);
bool convert(Instruction *In);
};
char HexagonGenExtract::ID = 0;
-}
+
+} // end anonymous namespace
INITIALIZE_PASS_BEGIN(HexagonGenExtract, "hextract", "Hexagon generate "
"\"extract\" instructions", false, false)
INITIALIZE_PASS_END(HexagonGenExtract, "hextract", "Hexagon generate "
"\"extract\" instructions", false, false)
-
bool HexagonGenExtract::convert(Instruction *In) {
using namespace PatternMatch;
- Value *BF = 0;
- ConstantInt *CSL = 0, *CSR = 0, *CM = 0;
+
+ Value *BF = nullptr;
+ ConstantInt *CSL = nullptr, *CSR = nullptr, *CM = nullptr;
BasicBlock *BB = In->getParent();
LLVMContext &Ctx = BB->getContext();
bool LogicalSR;
m_ConstantInt(CM)));
}
if (!Match) {
- CM = 0;
+ CM = nullptr;
// (shl (lshr x, #sr), #sl)
LogicalSR = true;
Match = match(In, m_Shl(m_LShr(m_Value(BF), m_ConstantInt(CSR)),
m_ConstantInt(CSL)));
}
if (!Match) {
- CM = 0;
+ CM = nullptr;
// (shl (ashr x, #sr), #sl)
LogicalSR = false;
Match = match(In, m_Shl(m_AShr(m_Value(BF), m_ConstantInt(CSR)),
return true;
}
-
bool HexagonGenExtract::visitBlock(BasicBlock *B) {
// Depth-first, bottom-up traversal.
DomTreeNode *DTN = DT->getNode(B);
return Changed;
}
-
bool HexagonGenExtract::runOnFunction(Function &F) {
if (skipFunction(F))
return false;
return Changed;
}
-
FunctionPass *llvm::createHexagonGenExtract() {
return new HexagonGenExtract();
}
#define DEBUG_TYPE "hexinsert"
+#include "BitTracker.h"
+#include "HexagonBitTracker.h"
+#include "HexagonInstrInfo.h"
+#include "HexagonRegisterInfo.h"
+#include "HexagonSubtarget.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
-#include "llvm/PassRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Timer.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/Timer.h"
#include "llvm/Target/TargetRegisterInfo.h"
-
-#include "Hexagon.h"
-#include "HexagonRegisterInfo.h"
-#include "HexagonTargetMachine.h"
-#include "HexagonBitTracker.h"
-
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <utility>
#include <vector>
using namespace llvm;
static cl::opt<bool> OptConst("insert-const", cl::init(false), cl::Hidden,
cl::ZeroOrMore);
-namespace {
- // The preprocessor gets confused when the DEBUG macro is passed larger
- // chunks of code. Use this function to detect debugging.
- inline bool isDebug() {
+// The preprocessor gets confused when the DEBUG macro is passed larger
+// chunks of code. Use this function to detect debugging.
+inline static bool isDebug() {
#ifndef NDEBUG
- return ::llvm::DebugFlag && ::llvm::isCurrentDebugType(DEBUG_TYPE);
+ return DebugFlag && isCurrentDebugType(DEBUG_TYPE);
#else
- return false;
+ return false;
#endif
- }
}
-
namespace {
+
// Set of virtual registers, based on BitVector.
struct RegisterSet : private BitVector {
RegisterSet() = default;
if (size() <= Idx)
resize(std::max(Idx+1, 32U));
}
+
static inline unsigned v2x(unsigned v) {
return TargetRegisterInfo::virtReg2Index(v);
}
+
static inline unsigned x2v(unsigned x) {
return TargetRegisterInfo::index2VirtReg(x);
}
};
-
struct PrintRegSet {
PrintRegSet(const RegisterSet &S, const TargetRegisterInfo *RI)
: RS(S), TRI(RI) {}
+
friend raw_ostream &operator<< (raw_ostream &OS,
const PrintRegSet &P);
+
private:
const RegisterSet &RS;
const TargetRegisterInfo *TRI;
OS << " }";
return OS;
}
-}
-
-namespace {
// A convenience class to associate unsigned numbers (such as virtual
// registers) with unsigned numbers.
struct UnsignedMap : public DenseMap<unsigned,unsigned> {
- UnsignedMap() : BaseType() {}
+ UnsignedMap() = default;
+
private:
typedef DenseMap<unsigned,unsigned> BaseType;
};
// by a potentially expensive comparison function, or obtained by a proce-
// dure that should not be repeated each time two registers are compared.
struct RegisterOrdering : public UnsignedMap {
- RegisterOrdering() : UnsignedMap() {}
+ RegisterOrdering() = default;
+
unsigned operator[](unsigned VR) const {
const_iterator F = find(VR);
assert(F != end());
return F->second;
}
+
// Add operator(), so that objects of this class can be used as
// comparators in std::sort et al.
bool operator() (unsigned VR1, unsigned VR2) const {
return operator[](VR1) < operator[](VR2);
}
};
-}
-
-namespace {
// Ordering of bit values. This class does not have operator[], but
// is supplies a comparison operator() for use in std:: algorithms.
// The order is as follows:
// or ord(ref1.Reg) == ord(ref2.Reg), and ref1.Pos < ref2.Pos.
struct BitValueOrdering {
BitValueOrdering(const RegisterOrdering &RB) : BaseOrd(RB) {}
+
bool operator() (const BitTracker::BitValue &V1,
const BitTracker::BitValue &V2) const;
+
const RegisterOrdering &BaseOrd;
};
-}
+} // end anonymous namespace
bool BitValueOrdering::operator() (const BitTracker::BitValue &V1,
const BitTracker::BitValue &V2) const {
return V1.RefI.Pos < V2.RefI.Pos;
}
-
namespace {
+
// Cache for the BitTracker's cell map. Map lookup has a logarithmic
// complexity, this class will memoize the lookup results to reduce
// the access time for repeated lookups of the same cell.
struct CellMapShadow {
CellMapShadow(const BitTracker &T) : BT(T) {}
+
const BitTracker::RegisterCell &lookup(unsigned VR) {
unsigned RInd = TargetRegisterInfo::virtReg2Index(VR);
// Grow the vector to at least 32 elements.
if (RInd >= CVect.size())
- CVect.resize(std::max(RInd+16, 32U), 0);
+ CVect.resize(std::max(RInd+16, 32U), nullptr);
const BitTracker::RegisterCell *CP = CVect[RInd];
- if (CP == 0)
+ if (CP == nullptr)
CP = CVect[RInd] = &BT.lookup(VR);
return *CP;
}
typedef std::vector<const BitTracker::RegisterCell*> CellVectType;
CellVectType CVect;
};
-}
-
-namespace {
// Comparator class for lexicographic ordering of virtual registers
// according to the corresponding BitTracker::RegisterCell objects.
struct RegisterCellLexCompare {
RegisterCellLexCompare(const BitValueOrdering &BO, CellMapShadow &M)
: BitOrd(BO), CM(M) {}
+
bool operator() (unsigned VR1, unsigned VR2) const;
+
private:
const BitValueOrdering &BitOrd;
CellMapShadow &CM;
RegisterCellBitCompareSel(unsigned R, unsigned B, unsigned N,
const BitValueOrdering &BO, CellMapShadow &M)
: SelR(R), SelB(B), BitN(N), BitOrd(BO), CM(M) {}
+
bool operator() (unsigned VR1, unsigned VR2) const;
+
private:
const unsigned SelR, SelB;
const unsigned BitN;
const BitValueOrdering &BitOrd;
CellMapShadow &CM;
};
-}
+} // end anonymous namespace
bool RegisterCellLexCompare::operator() (unsigned VR1, unsigned VR2) const {
// Ordering of registers, made up from two given orderings:
return BitOrd.BaseOrd[VR1] < BitOrd.BaseOrd[VR2];
}
-
bool RegisterCellBitCompareSel::operator() (unsigned VR1, unsigned VR2) const {
if (VR1 == VR2)
return false;
return false;
}
-
namespace {
+
class OrderedRegisterList {
typedef std::vector<unsigned> ListType;
+
public:
OrderedRegisterList(const RegisterOrdering &RO) : Ord(RO) {}
+
void insert(unsigned VR);
void remove(unsigned VR);
+
unsigned operator[](unsigned Idx) const {
assert(Idx < Seq.size());
return Seq[Idx];
}
+
unsigned size() const {
return Seq.size();
}
// Convenience function to convert an iterator to the corresponding index.
unsigned idx(iterator It) const { return It-begin(); }
+
private:
ListType Seq;
const RegisterOrdering &Ord;
};
-
struct PrintORL {
PrintORL(const OrderedRegisterList &L, const TargetRegisterInfo *RI)
: RL(L), TRI(RI) {}
+
friend raw_ostream &operator<< (raw_ostream &OS, const PrintORL &P);
+
private:
const OrderedRegisterList &RL;
const TargetRegisterInfo *TRI;
OS << ')';
return OS;
}
-}
+} // end anonymous namespace
void OrderedRegisterList::insert(unsigned VR) {
iterator L = std::lower_bound(Seq.begin(), Seq.end(), VR, Ord);
Seq.insert(L, VR);
}
-
void OrderedRegisterList::remove(unsigned VR) {
iterator L = std::lower_bound(Seq.begin(), Seq.end(), VR, Ord);
assert(L != Seq.end());
Seq.erase(L);
}
-
namespace {
+
// A record of the insert form. The fields correspond to the operands
// of the "insert" instruction:
// ... = insert(SrcR, InsR, #Wdh, #Off)
struct IFRecord {
IFRecord(unsigned SR = 0, unsigned IR = 0, uint16_t W = 0, uint16_t O = 0)
: SrcR(SR), InsR(IR), Wdh(W), Off(O) {}
+
unsigned SrcR, InsR;
uint16_t Wdh, Off;
};
struct PrintIFR {
PrintIFR(const IFRecord &R, const TargetRegisterInfo *RI)
: IFR(R), TRI(RI) {}
+
private:
+ friend raw_ostream &operator<< (raw_ostream &OS, const PrintIFR &P);
+
const IFRecord &IFR;
const TargetRegisterInfo *TRI;
- friend raw_ostream &operator<< (raw_ostream &OS, const PrintIFR &P);
};
raw_ostream &operator<< (raw_ostream &OS, const PrintIFR &P) {
}
typedef std::pair<IFRecord,RegisterSet> IFRecordWithRegSet;
-}
+} // end anonymous namespace
namespace llvm {
+
void initializeHexagonGenInsertPass(PassRegistry&);
FunctionPass *createHexagonGenInsert();
-}
+} // end namespace llvm
namespace {
+
class HexagonGenInsert : public MachineFunctionPass {
public:
static char ID;
- HexagonGenInsert() : MachineFunctionPass(ID), HII(0), HRI(0) {
+
+ HexagonGenInsert() : MachineFunctionPass(ID), HII(nullptr), HRI(nullptr) {
initializeHexagonGenInsertPass(*PassRegistry::getPassRegistry());
}
- virtual StringRef getPassName() const {
+
+ StringRef getPassName() const override {
return "Hexagon generate \"insert\" instructions";
}
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineDominatorTree>();
AU.addPreserved<MachineDominatorTree>();
MachineFunctionPass::getAnalysisUsage(AU);
}
- virtual bool runOnMachineFunction(MachineFunction &MF);
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
private:
typedef DenseMap<std::pair<unsigned,unsigned>,unsigned> PairMapType;
};
char HexagonGenInsert::ID = 0;
-}
+} // end anonymous namespace
void HexagonGenInsert::dump_map() const {
typedef IFMapType::const_iterator iterator;
}
}
-
void HexagonGenInsert::buildOrderingMF(RegisterOrdering &RO) const {
unsigned Index = 0;
typedef MachineFunction::const_iterator mf_iterator;
// in the map.
}
-
void HexagonGenInsert::buildOrderingBT(RegisterOrdering &RB,
RegisterOrdering &RO) const {
// Create a vector of all virtual registers (collect them from the base
RO.insert(std::make_pair(VRs[i], i));
}
-
inline bool HexagonGenInsert::isIntClass(const TargetRegisterClass *RC) const {
return RC == &Hexagon::IntRegsRegClass || RC == &Hexagon::DoubleRegsRegClass;
}
-
bool HexagonGenInsert::isConstant(unsigned VR) const {
const BitTracker::RegisterCell &RC = CMS->lookup(VR);
uint16_t W = RC.width();
return true;
}
-
bool HexagonGenInsert::isSmallConstant(unsigned VR) const {
const BitTracker::RegisterCell &RC = CMS->lookup(VR);
uint16_t W = RC.width();
return isInt<8>(Lo_32(V)) && isInt<8>(Hi_32(V));
}
-
bool HexagonGenInsert::isValidInsertForm(unsigned DstR, unsigned SrcR,
unsigned InsR, uint16_t L, uint16_t S) const {
const TargetRegisterClass *DstRC = MRI->getRegClass(DstR);
return true;
}
-
bool HexagonGenInsert::findSelfReference(unsigned VR) const {
const BitTracker::RegisterCell &RC = CMS->lookup(VR);
for (uint16_t i = 0, w = RC.width(); i < w; ++i) {
return false;
}
-
bool HexagonGenInsert::findNonSelfReference(unsigned VR) const {
BitTracker::RegisterCell RC = CMS->lookup(VR);
for (uint16_t i = 0, w = RC.width(); i < w; ++i) {
return false;
}
-
void HexagonGenInsert::getInstrDefs(const MachineInstr *MI,
RegisterSet &Defs) const {
for (unsigned i = 0, n = MI->getNumOperands(); i < n; ++i) {
}
}
-
void HexagonGenInsert::getInstrUses(const MachineInstr *MI,
RegisterSet &Uses) const {
for (unsigned i = 0, n = MI->getNumOperands(); i < n; ++i) {
}
}
-
unsigned HexagonGenInsert::distance(const MachineBasicBlock *FromB,
const MachineBasicBlock *ToB, const UnsignedMap &RPO,
PairMapType &M) const {
return MaxD;
}
-
unsigned HexagonGenInsert::distance(MachineBasicBlock::const_iterator FromI,
MachineBasicBlock::const_iterator ToI, const UnsignedMap &RPO,
PairMapType &M) const {
return D1+D2+D3;
}
-
bool HexagonGenInsert::findRecordInsertForms(unsigned VR,
OrderedRegisterList &AVs) {
if (isDebug()) {
}
}
-
bool Recorded = false;
for (iterator I = AVs.begin(), E = AVs.end(); I != E; ++I) {
return Recorded;
}
-
void HexagonGenInsert::collectInBlock(MachineBasicBlock *B,
OrderedRegisterList &AVs) {
if (isDebug())
AVs.remove(VR);
}
-
void HexagonGenInsert::findRemovableRegisters(unsigned VR, IFRecord IF,
RegisterSet &RMs) const {
// For a given register VR and a insert form, find the registers that are
RMs.remove(VR);
}
-
void HexagonGenInsert::computeRemovableRegisters() {
for (IFMapType::iterator I = IFMap.begin(), E = IFMap.end(); I != E; ++I) {
IFListType &LL = I->second;
}
}
-
void HexagonGenInsert::pruneEmptyLists() {
// Remove all entries from the map, where the register has no insert forms
// associated with it.
typedef SmallVector<IFMapType::iterator,16> IterListType;
IterListType Prune;
for (IFMapType::iterator I = IFMap.begin(), E = IFMap.end(); I != E; ++I) {
- if (I->second.size() == 0)
+ if (I->second.empty())
Prune.push_back(I);
}
for (unsigned i = 0, n = Prune.size(); i < n; ++i)
IFMap.erase(Prune[i]);
}
-
void HexagonGenInsert::pruneCoveredSets(unsigned VR) {
IFMapType::iterator F = IFMap.find(VR);
assert(F != IFMap.end());
auto IsEmpty = [] (const IFRecordWithRegSet &IR) -> bool {
return IR.second.empty();
};
- auto End = remove_if(LL, IsEmpty);
+ auto End = llvm::remove_if(LL, IsEmpty);
if (End != LL.end())
LL.erase(End, LL.end());
} else {
}
}
-
void HexagonGenInsert::pruneUsesTooFar(unsigned VR, const UnsignedMap &RPO,
PairMapType &M) {
IFMapType::iterator F = IFMap.find(VR);
}
}
-
void HexagonGenInsert::pruneRegCopies(unsigned VR) {
IFMapType::iterator F = IFMap.find(VR);
assert(F != IFMap.end());
auto IsCopy = [] (const IFRecordWithRegSet &IR) -> bool {
return IR.first.Wdh == 32 && (IR.first.Off == 0 || IR.first.Off == 32);
};
- auto End = remove_if(LL, IsCopy);
+ auto End = llvm::remove_if(LL, IsCopy);
if (End != LL.end())
LL.erase(End, LL.end());
}
-
void HexagonGenInsert::pruneCandidates() {
// Remove candidates that are not beneficial, regardless of the final
// selection method.
pruneRegCopies(I->first);
}
-
namespace {
+
// Class for comparing IF candidates for registers that have multiple of
// them. The smaller the candidate, according to this ordering, the better.
// First, compare the number of zeros in the associated potentially remova-
struct IFOrdering {
IFOrdering(const UnsignedMap &UC, const RegisterOrdering &BO)
: UseC(UC), BaseOrd(BO) {}
+
bool operator() (const IFRecordWithRegSet &A,
const IFRecordWithRegSet &B) const;
+
private:
void stats(const RegisterSet &Rs, unsigned &Size, unsigned &Zero,
unsigned &Sum) const;
+
const UnsignedMap &UseC;
const RegisterOrdering &BaseOrd;
};
-}
+} // end anonymous namespace
bool IFOrdering::operator() (const IFRecordWithRegSet &A,
const IFRecordWithRegSet &B) const {
return A.first.Off < B.first.Off;
}
-
void IFOrdering::stats(const RegisterSet &Rs, unsigned &Size, unsigned &Zero,
unsigned &Sum) const {
for (unsigned R = Rs.find_first(); R; R = Rs.find_next(R)) {
}
}
-
void HexagonGenInsert::selectCandidates() {
// Some registers may have multiple valid candidates. Pick the best one
// (or decide not to use any).
UseC[R] = (C > D) ? C-D : 0; // doz
}
-
bool SelectAll0 = OptSelectAll0, SelectHas0 = OptSelectHas0;
if (!SelectAll0 && !SelectHas0)
SelectAll0 = true;
AllRMs.clear();
for (IFMapType::iterator I = IFMap.begin(); I != End; ++I) {
const IFListType &LL = I->second;
- if (LL.size() > 0)
+ if (!LL.empty())
AllRMs.insert(LL[0].second);
}
for (IFMapType::iterator I = IFMap.begin(); I != End; ++I) {
IFListType &LL = I->second;
- if (LL.size() == 0)
+ if (LL.empty())
continue;
unsigned SR = LL[0].first.SrcR, IR = LL[0].first.InsR;
if (AllRMs[SR] || AllRMs[IR])
pruneEmptyLists();
}
-
bool HexagonGenInsert::generateInserts() {
// Create a new register for each one from IFMap, and store them in the
// map.
return true;
}
-
bool HexagonGenInsert::removeDeadCode(MachineDomTreeNode *N) {
bool Changed = false;
typedef GraphTraits<MachineDomTreeNode*> GTN;
return Changed;
}
-
bool HexagonGenInsert::runOnMachineFunction(MachineFunction &MF) {
if (skipFunction(*MF.getFunction()))
return false;
return true;
}
-
FunctionPass *llvm::createHexagonGenInsert() {
return new HexagonGenInsert();
}
-
//===----------------------------------------------------------------------===//
// Public Constructor Functions
//===----------------------------------------------------------------------===//