#ifndef LLVM_LIB_TARGET_HEXAGON_BITTRACKER_H
#define LLVM_LIB_TARGET_HEXAGON_BITTRACKER_H
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include <cassert>
#include <cstdint>
#include <map>
#include <queue>
#include <set>
#include <utility>
namespace llvm {
class BitVector;
class ConstantInt;
class MachineRegisterInfo;
class MachineBasicBlock;
class MachineFunction;
class raw_ostream;
class TargetRegisterClass;
class TargetRegisterInfo;
struct BitTracker {
struct BitRef;
struct RegisterRef;
struct BitValue;
struct BitMask;
struct RegisterCell;
struct MachineEvaluator;
using BranchTargetList = SetVector<const MachineBasicBlock *>;
using CellMapType = std::map<unsigned, RegisterCell>;
BitTracker(const MachineEvaluator &E, MachineFunction &F);
~BitTracker();
void run();
void trace(bool On = false) { Trace = On; }
bool has(unsigned Reg) const;
const RegisterCell &lookup(unsigned Reg) const;
RegisterCell get(RegisterRef RR) const;
void put(RegisterRef RR, const RegisterCell &RC);
void subst(RegisterRef OldRR, RegisterRef NewRR);
bool reached(const MachineBasicBlock *B) const;
void visit(const MachineInstr &MI);
void print_cells(raw_ostream &OS) const;
private:
void visitPHI(const MachineInstr &PI);
void visitNonBranch(const MachineInstr &MI);
void visitBranchesFrom(const MachineInstr &BI);
void visitUsesOf(Register Reg);
using CFGEdge = std::pair<int, int>;
using EdgeSetType = std::set<CFGEdge>;
using InstrSetType = std::set<const MachineInstr *>;
using EdgeQueueType = std::queue<CFGEdge>;
struct UseQueueType {
UseQueueType() : Uses(Dist) {}
unsigned size() const {
return Uses.size();
}
bool empty() const {
return size() == 0;
}
MachineInstr *front() const {
return Uses.top();
}
void push(MachineInstr *MI) {
if (Set.insert(MI).second)
Uses.push(MI);
}
void pop() {
Set.erase(front());
Uses.pop();
}
void reset() {
Dist.clear();
}
private:
struct Cmp {
Cmp(DenseMap<const MachineInstr*,unsigned> &Map) : Dist(Map) {}
bool operator()(const MachineInstr *MI, const MachineInstr *MJ) const;
DenseMap<const MachineInstr*,unsigned> &Dist;
};
std::priority_queue<MachineInstr*, std::vector<MachineInstr*>, Cmp> Uses;
DenseSet<const MachineInstr*> Set; DenseMap<const MachineInstr*,unsigned> Dist;
};
void reset();
void runEdgeQueue(BitVector &BlockScanned);
void runUseQueue();
const MachineEvaluator &ME;
MachineFunction &MF;
MachineRegisterInfo &MRI;
CellMapType ⤅
EdgeSetType EdgeExec; InstrSetType InstrExec; UseQueueType UseQ; EdgeQueueType FlowQ; DenseSet<unsigned> ReachedBB; bool Trace; };
struct BitTracker::BitRef {
BitRef(unsigned R = 0, uint16_t P = 0) : Reg(R), Pos(P) {}
bool operator== (const BitRef &BR) const {
return Reg == BR.Reg && (Reg == 0 || Pos == BR.Pos);
}
Register Reg;
uint16_t Pos;
};
struct BitTracker::RegisterRef {
RegisterRef(Register R = 0, unsigned S = 0) : Reg(R), Sub(S) {}
RegisterRef(const MachineOperand &MO)
: Reg(MO.getReg()), Sub(MO.getSubReg()) {}
Register Reg;
unsigned Sub;
};
struct BitTracker::BitValue {
enum ValueType {
Top, Zero, One, Ref };
ValueType Type;
BitRef RefI;
BitValue(ValueType T = Top) : Type(T) {}
BitValue(bool B) : Type(B ? One : Zero) {}
BitValue(unsigned Reg, uint16_t Pos) : Type(Ref), RefI(Reg, Pos) {}
bool operator== (const BitValue &V) const {
if (Type != V.Type)
return false;
if (Type == Ref && !(RefI == V.RefI))
return false;
return true;
}
bool operator!= (const BitValue &V) const {
return !operator==(V);
}
bool is(unsigned T) const {
assert(T == 0 || T == 1);
return T == 0 ? Type == Zero
: (T == 1 ? Type == One : false);
}
bool meet(const BitValue &V, const BitRef &Self) {
if (Type == Ref && RefI == Self) return false;
if (V.Type == Top) return false;
if (*this == V) return false;
if (Type == Top) {
Type = V.Type;
RefI = V.RefI; return true;
}
Type = Ref;
RefI = Self;
return true;
}
static BitValue ref(const BitValue &V);
static BitValue self(const BitRef &Self = BitRef());
bool num() const {
return Type == Zero || Type == One;
}
operator bool() const {
assert(Type == Zero || Type == One);
return Type == One;
}
friend raw_ostream &operator<<(raw_ostream &OS, const BitValue &BV);
};
inline BitTracker::BitValue
BitTracker::BitValue::ref(const BitValue &V) {
if (V.Type != Ref)
return BitValue(V.Type);
if (V.RefI.Reg != 0)
return BitValue(V.RefI.Reg, V.RefI.Pos);
return self();
}
inline BitTracker::BitValue
BitTracker::BitValue::self(const BitRef &Self) {
return BitValue(Self.Reg, Self.Pos);
}
struct BitTracker::BitMask {
BitMask() = default;
BitMask(uint16_t b, uint16_t e) : B(b), E(e) {}
uint16_t first() const { return B; }
uint16_t last() const { return E; }
private:
uint16_t B = 0;
uint16_t E = 0;
};
struct BitTracker::RegisterCell {
RegisterCell(uint16_t Width = DefaultBitN) : Bits(Width) {}
uint16_t width() const {
return Bits.size();
}
const BitValue &operator[](uint16_t BitN) const {
assert(BitN < Bits.size());
return Bits[BitN];
}
BitValue &operator[](uint16_t BitN) {
assert(BitN < Bits.size());
return Bits[BitN];
}
bool meet(const RegisterCell &RC, Register SelfR);
RegisterCell &insert(const RegisterCell &RC, const BitMask &M);
RegisterCell extract(const BitMask &M) const; RegisterCell &rol(uint16_t Sh); RegisterCell &fill(uint16_t B, uint16_t E, const BitValue &V);
RegisterCell &cat(const RegisterCell &RC); uint16_t cl(bool B) const;
uint16_t ct(bool B) const;
bool operator== (const RegisterCell &RC) const;
bool operator!= (const RegisterCell &RC) const {
return !operator==(RC);
}
RegisterCell ®ify(unsigned R);
static RegisterCell self(unsigned Reg, uint16_t Width);
static RegisterCell top(uint16_t Width);
static RegisterCell ref(const RegisterCell &C);
private:
static const unsigned DefaultBitN = 32;
using BitValueList = SmallVector<BitValue, DefaultBitN>;
BitValueList Bits;
friend raw_ostream &operator<<(raw_ostream &OS, const RegisterCell &RC);
};
inline bool BitTracker::has(unsigned Reg) const {
return Map.find(Reg) != Map.end();
}
inline const BitTracker::RegisterCell&
BitTracker::lookup(unsigned Reg) const {
CellMapType::const_iterator F = Map.find(Reg);
assert(F != Map.end());
return F->second;
}
inline BitTracker::RegisterCell
BitTracker::RegisterCell::self(unsigned Reg, uint16_t Width) {
RegisterCell RC(Width);
for (uint16_t i = 0; i < Width; ++i)
RC.Bits[i] = BitValue::self(BitRef(Reg, i));
return RC;
}
inline BitTracker::RegisterCell
BitTracker::RegisterCell::top(uint16_t Width) {
RegisterCell RC(Width);
for (uint16_t i = 0; i < Width; ++i)
RC.Bits[i] = BitValue(BitValue::Top);
return RC;
}
inline BitTracker::RegisterCell
BitTracker::RegisterCell::ref(const RegisterCell &C) {
uint16_t W = C.width();
RegisterCell RC(W);
for (unsigned i = 0; i < W; ++i)
RC[i] = BitValue::ref(C[i]);
return RC;
}
struct BitTracker::MachineEvaluator {
MachineEvaluator(const TargetRegisterInfo &T, MachineRegisterInfo &M)
: TRI(T), MRI(M) {}
virtual ~MachineEvaluator() = default;
uint16_t getRegBitWidth(const RegisterRef &RR) const;
RegisterCell getCell(const RegisterRef &RR, const CellMapType &M) const;
void putCell(const RegisterRef &RR, RegisterCell RC, CellMapType &M) const;
RegisterCell getRef(const RegisterRef &RR, const CellMapType &M) const {
RegisterCell RC = getCell(RR, M);
return RegisterCell::ref(RC);
}
bool isInt(const RegisterCell &A) const;
uint64_t toInt(const RegisterCell &A) const;
RegisterCell eIMM(int64_t V, uint16_t W) const;
RegisterCell eIMM(const ConstantInt *CI) const;
RegisterCell eADD(const RegisterCell &A1, const RegisterCell &A2) const;
RegisterCell eSUB(const RegisterCell &A1, const RegisterCell &A2) const;
RegisterCell eMLS(const RegisterCell &A1, const RegisterCell &A2) const;
RegisterCell eMLU(const RegisterCell &A1, const RegisterCell &A2) const;
RegisterCell eASL(const RegisterCell &A1, uint16_t Sh) const;
RegisterCell eLSR(const RegisterCell &A1, uint16_t Sh) const;
RegisterCell eASR(const RegisterCell &A1, uint16_t Sh) const;
RegisterCell eAND(const RegisterCell &A1, const RegisterCell &A2) const;
RegisterCell eORL(const RegisterCell &A1, const RegisterCell &A2) const;
RegisterCell eXOR(const RegisterCell &A1, const RegisterCell &A2) const;
RegisterCell eNOT(const RegisterCell &A1) const;
RegisterCell eSET(const RegisterCell &A1, uint16_t BitN) const;
RegisterCell eCLR(const RegisterCell &A1, uint16_t BitN) const;
RegisterCell eCLB(const RegisterCell &A1, bool B, uint16_t W) const;
RegisterCell eCTB(const RegisterCell &A1, bool B, uint16_t W) const;
RegisterCell eSXT(const RegisterCell &A1, uint16_t FromN) const;
RegisterCell eZXT(const RegisterCell &A1, uint16_t FromN) const;
RegisterCell eXTR(const RegisterCell &A1, uint16_t B, uint16_t E) const;
RegisterCell eINS(const RegisterCell &A1, const RegisterCell &A2,
uint16_t AtN) const;
virtual BitMask mask(Register Reg, unsigned Sub) const;
virtual bool track(const TargetRegisterClass *RC) const { return true; }
virtual bool evaluate(const MachineInstr &MI, const CellMapType &Inputs,
CellMapType &Outputs) const;
virtual bool evaluate(const MachineInstr &BI, const CellMapType &Inputs,
BranchTargetList &Targets, bool &FallsThru) const = 0;
virtual const TargetRegisterClass&
composeWithSubRegIndex(const TargetRegisterClass &RC, unsigned Idx) const {
if (Idx == 0)
return RC;
llvm_unreachable("Unimplemented composeWithSubRegIndex");
}
virtual uint16_t getPhysRegBitWidth(MCRegister Reg) const;
const TargetRegisterInfo &TRI;
MachineRegisterInfo &MRI;
};
}
#endif