Path: blob/main/contrib/llvm-project/llvm/lib/Target/Hexagon/BitTracker.h
35266 views
//===- BitTracker.h ---------------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIB_TARGET_HEXAGON_BITTRACKER_H9#define LLVM_LIB_TARGET_HEXAGON_BITTRACKER_H1011#include "llvm/ADT/DenseSet.h"12#include "llvm/ADT/SetVector.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/CodeGen/MachineInstr.h"15#include "llvm/CodeGen/MachineOperand.h"16#include <cassert>17#include <cstdint>18#include <map>19#include <queue>20#include <set>21#include <utility>2223namespace llvm {2425class BitVector;26class ConstantInt;27class MachineRegisterInfo;28class MachineBasicBlock;29class MachineFunction;30class raw_ostream;31class TargetRegisterClass;32class TargetRegisterInfo;3334struct BitTracker {35struct BitRef;36struct RegisterRef;37struct BitValue;38struct BitMask;39struct RegisterCell;40struct MachineEvaluator;4142using BranchTargetList = SetVector<const MachineBasicBlock *>;43using CellMapType = std::map<unsigned, RegisterCell>;4445BitTracker(const MachineEvaluator &E, MachineFunction &F);46~BitTracker();4748void run();49void trace(bool On = false) { Trace = On; }50bool has(unsigned Reg) const;51const RegisterCell &lookup(unsigned Reg) const;52RegisterCell get(RegisterRef RR) const;53void put(RegisterRef RR, const RegisterCell &RC);54void subst(RegisterRef OldRR, RegisterRef NewRR);55bool reached(const MachineBasicBlock *B) const;56void visit(const MachineInstr &MI);5758void print_cells(raw_ostream &OS) const;5960private:61void visitPHI(const MachineInstr &PI);62void visitNonBranch(const MachineInstr &MI);63void visitBranchesFrom(const MachineInstr &BI);64void visitUsesOf(Register Reg);6566using CFGEdge = std::pair<int, int>;67using EdgeSetType = std::set<CFGEdge>;68using InstrSetType = std::set<const MachineInstr *>;69using EdgeQueueType = std::queue<CFGEdge>;7071// Priority queue of instructions using modified registers, ordered by72// their relative position in a basic block.73struct UseQueueType {74UseQueueType() : Uses(Dist) {}7576unsigned size() const {77return Uses.size();78}79bool empty() const {80return size() == 0;81}82MachineInstr *front() const {83return Uses.top();84}85void push(MachineInstr *MI) {86if (Set.insert(MI).second)87Uses.push(MI);88}89void pop() {90Set.erase(front());91Uses.pop();92}93void reset() {94Dist.clear();95}96private:97struct Cmp {98Cmp(DenseMap<const MachineInstr*,unsigned> &Map) : Dist(Map) {}99bool operator()(const MachineInstr *MI, const MachineInstr *MJ) const;100DenseMap<const MachineInstr*,unsigned> &Dist;101};102std::priority_queue<MachineInstr*, std::vector<MachineInstr*>, Cmp> Uses;103DenseSet<const MachineInstr*> Set; // Set to avoid adding duplicate entries.104DenseMap<const MachineInstr*,unsigned> Dist;105};106107void reset();108void runEdgeQueue(BitVector &BlockScanned);109void runUseQueue();110111const MachineEvaluator &ME;112MachineFunction &MF;113MachineRegisterInfo &MRI;114CellMapType ⤅115116EdgeSetType EdgeExec; // Executable flow graph edges.117InstrSetType InstrExec; // Executable instructions.118UseQueueType UseQ; // Work queue of register uses.119EdgeQueueType FlowQ; // Work queue of CFG edges.120DenseSet<unsigned> ReachedBB; // Cache of reached blocks.121bool Trace; // Enable tracing for debugging.122};123124// Abstraction of a reference to bit at position Pos from a register Reg.125struct BitTracker::BitRef {126BitRef(unsigned R = 0, uint16_t P = 0) : Reg(R), Pos(P) {}127128bool operator== (const BitRef &BR) const {129// If Reg is 0, disregard Pos.130return Reg == BR.Reg && (Reg == 0 || Pos == BR.Pos);131}132133Register Reg;134uint16_t Pos;135};136137// Abstraction of a register reference in MachineOperand. It contains the138// register number and the subregister index.139// FIXME: Consolidate duplicate definitions of RegisterRef140struct BitTracker::RegisterRef {141RegisterRef(Register R = 0, unsigned S = 0) : Reg(R), Sub(S) {}142RegisterRef(const MachineOperand &MO)143: Reg(MO.getReg()), Sub(MO.getSubReg()) {}144145Register Reg;146unsigned Sub;147};148149// Value that a single bit can take. This is outside of the context of150// any register, it is more of an abstraction of the two-element set of151// possible bit values. One extension here is the "Ref" type, which152// indicates that this bit takes the same value as the bit described by153// RefInfo.154struct BitTracker::BitValue {155enum ValueType {156Top, // Bit not yet defined.157Zero, // Bit = 0.158One, // Bit = 1.159Ref // Bit value same as the one described in RefI.160// Conceptually, there is no explicit "bottom" value: the lattice's161// bottom will be expressed as a "ref to itself", which, in the context162// of registers, could be read as "this value of this bit is defined by163// this bit".164// The ordering is:165// x <= Top,166// Self <= x, where "Self" is "ref to itself".167// This makes the value lattice different for each virtual register168// (even for each bit in the same virtual register), since the "bottom"169// for one register will be a simple "ref" for another register.170// Since we do not store the "Self" bit and register number, the meet171// operation will need to take it as a parameter.172//173// In practice there is a special case for values that are not associa-174// ted with any specific virtual register. An example would be a value175// corresponding to a bit of a physical register, or an intermediate176// value obtained in some computation (such as instruction evaluation).177// Such cases are identical to the usual Ref type, but the register178// number is 0. In such case the Pos field of the reference is ignored.179//180// What is worthy of notice is that in value V (that is a "ref"), as long181// as the RefI.Reg is not 0, it may actually be the same register as the182// one in which V will be contained. If the RefI.Pos refers to the posi-183// tion of V, then V is assumed to be "bottom" (as a "ref to itself"),184// otherwise V is taken to be identical to the referenced bit of the185// same register.186// If RefI.Reg is 0, however, such a reference to the same register is187// not possible. Any value V that is a "ref", and whose RefI.Reg is 0188// is treated as "bottom".189};190ValueType Type;191BitRef RefI;192193BitValue(ValueType T = Top) : Type(T) {}194BitValue(bool B) : Type(B ? One : Zero) {}195BitValue(unsigned Reg, uint16_t Pos) : Type(Ref), RefI(Reg, Pos) {}196197bool operator== (const BitValue &V) const {198if (Type != V.Type)199return false;200if (Type == Ref && !(RefI == V.RefI))201return false;202return true;203}204bool operator!= (const BitValue &V) const {205return !operator==(V);206}207208bool is(unsigned T) const {209assert(T == 0 || T == 1);210return T == 0 ? Type == Zero211: (T == 1 ? Type == One : false);212}213214// The "meet" operation is the "." operation in a semilattice (L, ., T, B):215// (1) x.x = x216// (2) x.y = y.x217// (3) x.(y.z) = (x.y).z218// (4) x.T = x (i.e. T = "top")219// (5) x.B = B (i.e. B = "bottom")220//221// This "meet" function will update the value of the "*this" object with222// the newly calculated one, and return "true" if the value of *this has223// changed, and "false" otherwise.224// To prove that it satisfies the conditions (1)-(5), it is sufficient225// to show that a relation226// x <= y <=> x.y = x227// defines a partial order (i.e. that "meet" is same as "infimum").228bool meet(const BitValue &V, const BitRef &Self) {229// First, check the cases where there is nothing to be done.230if (Type == Ref && RefI == Self) // Bottom.meet(V) = Bottom (i.e. This)231return false;232if (V.Type == Top) // This.meet(Top) = This233return false;234if (*this == V) // This.meet(This) = This235return false;236237// At this point, we know that the value of "this" will change.238// If it is Top, it will become the same as V, otherwise it will239// become "bottom" (i.e. Self).240if (Type == Top) {241Type = V.Type;242RefI = V.RefI; // This may be irrelevant, but copy anyway.243return true;244}245// Become "bottom".246Type = Ref;247RefI = Self;248return true;249}250251// Create a reference to the bit value V.252static BitValue ref(const BitValue &V);253// Create a "self".254static BitValue self(const BitRef &Self = BitRef());255256bool num() const {257return Type == Zero || Type == One;258}259260operator bool() const {261assert(Type == Zero || Type == One);262return Type == One;263}264265friend raw_ostream &operator<<(raw_ostream &OS, const BitValue &BV);266};267268// This operation must be idempotent, i.e. ref(ref(V)) == ref(V).269inline BitTracker::BitValue270BitTracker::BitValue::ref(const BitValue &V) {271if (V.Type != Ref)272return BitValue(V.Type);273if (V.RefI.Reg != 0)274return BitValue(V.RefI.Reg, V.RefI.Pos);275return self();276}277278inline BitTracker::BitValue279BitTracker::BitValue::self(const BitRef &Self) {280return BitValue(Self.Reg, Self.Pos);281}282283// A sequence of bits starting from index B up to and including index E.284// If E < B, the mask represents two sections: [0..E] and [B..W) where285// W is the width of the register.286struct BitTracker::BitMask {287BitMask() = default;288BitMask(uint16_t b, uint16_t e) : B(b), E(e) {}289290uint16_t first() const { return B; }291uint16_t last() const { return E; }292293private:294uint16_t B = 0;295uint16_t E = 0;296};297298// Representation of a register: a list of BitValues.299struct BitTracker::RegisterCell {300RegisterCell(uint16_t Width = DefaultBitN) : Bits(Width) {}301302uint16_t width() const {303return Bits.size();304}305306const BitValue &operator[](uint16_t BitN) const {307assert(BitN < Bits.size());308return Bits[BitN];309}310BitValue &operator[](uint16_t BitN) {311assert(BitN < Bits.size());312return Bits[BitN];313}314315bool meet(const RegisterCell &RC, Register SelfR);316RegisterCell &insert(const RegisterCell &RC, const BitMask &M);317RegisterCell extract(const BitMask &M) const; // Returns a new cell.318RegisterCell &rol(uint16_t Sh); // Rotate left.319RegisterCell &fill(uint16_t B, uint16_t E, const BitValue &V);320RegisterCell &cat(const RegisterCell &RC); // Concatenate.321uint16_t cl(bool B) const;322uint16_t ct(bool B) const;323324bool operator== (const RegisterCell &RC) const;325bool operator!= (const RegisterCell &RC) const {326return !operator==(RC);327}328329// Replace the ref-to-reg-0 bit values with the given register.330RegisterCell ®ify(unsigned R);331332// Generate a "ref" cell for the corresponding register. In the resulting333// cell each bit will be described as being the same as the corresponding334// bit in register Reg (i.e. the cell is "defined" by register Reg).335static RegisterCell self(unsigned Reg, uint16_t Width);336// Generate a "top" cell of given size.337static RegisterCell top(uint16_t Width);338// Generate a cell that is a "ref" to another cell.339static RegisterCell ref(const RegisterCell &C);340341private:342// The DefaultBitN is here only to avoid frequent reallocation of the343// memory in the vector.344static const unsigned DefaultBitN = 32;345using BitValueList = SmallVector<BitValue, DefaultBitN>;346BitValueList Bits;347348friend raw_ostream &operator<<(raw_ostream &OS, const RegisterCell &RC);349};350351inline bool BitTracker::has(unsigned Reg) const {352return Map.find(Reg) != Map.end();353}354355inline const BitTracker::RegisterCell&356BitTracker::lookup(unsigned Reg) const {357CellMapType::const_iterator F = Map.find(Reg);358assert(F != Map.end());359return F->second;360}361362inline BitTracker::RegisterCell363BitTracker::RegisterCell::self(unsigned Reg, uint16_t Width) {364RegisterCell RC(Width);365for (uint16_t i = 0; i < Width; ++i)366RC.Bits[i] = BitValue::self(BitRef(Reg, i));367return RC;368}369370inline BitTracker::RegisterCell371BitTracker::RegisterCell::top(uint16_t Width) {372RegisterCell RC(Width);373for (uint16_t i = 0; i < Width; ++i)374RC.Bits[i] = BitValue(BitValue::Top);375return RC;376}377378inline BitTracker::RegisterCell379BitTracker::RegisterCell::ref(const RegisterCell &C) {380uint16_t W = C.width();381RegisterCell RC(W);382for (unsigned i = 0; i < W; ++i)383RC[i] = BitValue::ref(C[i]);384return RC;385}386387// A class to evaluate target's instructions and update the cell maps.388// This is used internally by the bit tracker. A target that wants to389// utilize this should implement the evaluation functions (noted below)390// in a subclass of this class.391struct BitTracker::MachineEvaluator {392MachineEvaluator(const TargetRegisterInfo &T, MachineRegisterInfo &M)393: TRI(T), MRI(M) {}394virtual ~MachineEvaluator() = default;395396uint16_t getRegBitWidth(const RegisterRef &RR) const;397398RegisterCell getCell(const RegisterRef &RR, const CellMapType &M) const;399void putCell(const RegisterRef &RR, RegisterCell RC, CellMapType &M) const;400401// A result of any operation should use refs to the source cells, not402// the cells directly. This function is a convenience wrapper to quickly403// generate a ref for a cell corresponding to a register reference.404RegisterCell getRef(const RegisterRef &RR, const CellMapType &M) const {405RegisterCell RC = getCell(RR, M);406return RegisterCell::ref(RC);407}408409// Helper functions.410// Check if a cell is an immediate value (i.e. all bits are either 0 or 1).411bool isInt(const RegisterCell &A) const;412// Convert cell to an immediate value.413uint64_t toInt(const RegisterCell &A) const;414415// Generate cell from an immediate value.416RegisterCell eIMM(int64_t V, uint16_t W) const;417RegisterCell eIMM(const ConstantInt *CI) const;418419// Arithmetic.420RegisterCell eADD(const RegisterCell &A1, const RegisterCell &A2) const;421RegisterCell eSUB(const RegisterCell &A1, const RegisterCell &A2) const;422RegisterCell eMLS(const RegisterCell &A1, const RegisterCell &A2) const;423RegisterCell eMLU(const RegisterCell &A1, const RegisterCell &A2) const;424425// Shifts.426RegisterCell eASL(const RegisterCell &A1, uint16_t Sh) const;427RegisterCell eLSR(const RegisterCell &A1, uint16_t Sh) const;428RegisterCell eASR(const RegisterCell &A1, uint16_t Sh) const;429430// Logical.431RegisterCell eAND(const RegisterCell &A1, const RegisterCell &A2) const;432RegisterCell eORL(const RegisterCell &A1, const RegisterCell &A2) const;433RegisterCell eXOR(const RegisterCell &A1, const RegisterCell &A2) const;434RegisterCell eNOT(const RegisterCell &A1) const;435436// Set bit, clear bit.437RegisterCell eSET(const RegisterCell &A1, uint16_t BitN) const;438RegisterCell eCLR(const RegisterCell &A1, uint16_t BitN) const;439440// Count leading/trailing bits (zeros/ones).441RegisterCell eCLB(const RegisterCell &A1, bool B, uint16_t W) const;442RegisterCell eCTB(const RegisterCell &A1, bool B, uint16_t W) const;443444// Sign/zero extension.445RegisterCell eSXT(const RegisterCell &A1, uint16_t FromN) const;446RegisterCell eZXT(const RegisterCell &A1, uint16_t FromN) const;447448// Extract/insert449// XTR R,b,e: extract bits from A1 starting at bit b, ending at e-1.450// INS R,S,b: take R and replace bits starting from b with S.451RegisterCell eXTR(const RegisterCell &A1, uint16_t B, uint16_t E) const;452RegisterCell eINS(const RegisterCell &A1, const RegisterCell &A2,453uint16_t AtN) const;454455// User-provided functions for individual targets:456457// Return a sub-register mask that indicates which bits in Reg belong458// to the subregister Sub. These bits are assumed to be contiguous in459// the super-register, and have the same ordering in the sub-register460// as in the super-register. It is valid to call this function with461// Sub == 0, in this case, the function should return a mask that spans462// the entire register Reg (which is what the default implementation463// does).464virtual BitMask mask(Register Reg, unsigned Sub) const;465// Indicate whether a given register class should be tracked.466virtual bool track(const TargetRegisterClass *RC) const { return true; }467// Evaluate a non-branching machine instruction, given the cell map with468// the input values. Place the results in the Outputs map. Return "true"469// if evaluation succeeded, "false" otherwise.470virtual bool evaluate(const MachineInstr &MI, const CellMapType &Inputs,471CellMapType &Outputs) const;472// Evaluate a branch, given the cell map with the input values. Fill out473// a list of all possible branch targets and indicate (through a flag)474// whether the branch could fall-through. Return "true" if this information475// has been successfully computed, "false" otherwise.476virtual bool evaluate(const MachineInstr &BI, const CellMapType &Inputs,477BranchTargetList &Targets, bool &FallsThru) const = 0;478// Given a register class RC, return a register class that should be assumed479// when a register from class RC is used with a subregister of index Idx.480virtual const TargetRegisterClass&481composeWithSubRegIndex(const TargetRegisterClass &RC, unsigned Idx) const {482if (Idx == 0)483return RC;484llvm_unreachable("Unimplemented composeWithSubRegIndex");485}486// Return the size in bits of the physical register Reg.487virtual uint16_t getPhysRegBitWidth(MCRegister Reg) const;488489const TargetRegisterInfo &TRI;490MachineRegisterInfo &MRI;491};492493} // end namespace llvm494495#endif // LLVM_LIB_TARGET_HEXAGON_BITTRACKER_H496497498