xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Hexagon/BitTracker.h (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
10b57cec5SDimitry Andric //===- BitTracker.h ---------------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_HEXAGON_BITTRACKER_H
100b57cec5SDimitry Andric #define LLVM_LIB_TARGET_HEXAGON_BITTRACKER_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
130b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
170b57cec5SDimitry Andric #include <cassert>
180b57cec5SDimitry Andric #include <cstdint>
190b57cec5SDimitry Andric #include <map>
200b57cec5SDimitry Andric #include <queue>
210b57cec5SDimitry Andric #include <set>
220b57cec5SDimitry Andric #include <utility>
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace llvm {
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric class BitVector;
270b57cec5SDimitry Andric class ConstantInt;
280b57cec5SDimitry Andric class MachineRegisterInfo;
290b57cec5SDimitry Andric class MachineBasicBlock;
300b57cec5SDimitry Andric class MachineFunction;
310b57cec5SDimitry Andric class raw_ostream;
320b57cec5SDimitry Andric class TargetRegisterClass;
330b57cec5SDimitry Andric class TargetRegisterInfo;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric struct BitTracker {
360b57cec5SDimitry Andric   struct BitRef;
370b57cec5SDimitry Andric   struct RegisterRef;
380b57cec5SDimitry Andric   struct BitValue;
390b57cec5SDimitry Andric   struct BitMask;
400b57cec5SDimitry Andric   struct RegisterCell;
410b57cec5SDimitry Andric   struct MachineEvaluator;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   using BranchTargetList = SetVector<const MachineBasicBlock *>;
440b57cec5SDimitry Andric   using CellMapType = std::map<unsigned, RegisterCell>;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   BitTracker(const MachineEvaluator &E, MachineFunction &F);
470b57cec5SDimitry Andric   ~BitTracker();
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   void run();
500b57cec5SDimitry Andric   void trace(bool On = false) { Trace = On; }
510b57cec5SDimitry Andric   bool has(unsigned Reg) const;
520b57cec5SDimitry Andric   const RegisterCell &lookup(unsigned Reg) const;
530b57cec5SDimitry Andric   RegisterCell get(RegisterRef RR) const;
540b57cec5SDimitry Andric   void put(RegisterRef RR, const RegisterCell &RC);
550b57cec5SDimitry Andric   void subst(RegisterRef OldRR, RegisterRef NewRR);
560b57cec5SDimitry Andric   bool reached(const MachineBasicBlock *B) const;
570b57cec5SDimitry Andric   void visit(const MachineInstr &MI);
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   void print_cells(raw_ostream &OS) const;
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric private:
620b57cec5SDimitry Andric   void visitPHI(const MachineInstr &PI);
630b57cec5SDimitry Andric   void visitNonBranch(const MachineInstr &MI);
640b57cec5SDimitry Andric   void visitBranchesFrom(const MachineInstr &BI);
65*e8d8bef9SDimitry Andric   void visitUsesOf(Register Reg);
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   using CFGEdge = std::pair<int, int>;
680b57cec5SDimitry Andric   using EdgeSetType = std::set<CFGEdge>;
690b57cec5SDimitry Andric   using InstrSetType = std::set<const MachineInstr *>;
700b57cec5SDimitry Andric   using EdgeQueueType = std::queue<CFGEdge>;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   // Priority queue of instructions using modified registers, ordered by
730b57cec5SDimitry Andric   // their relative position in a basic block.
740b57cec5SDimitry Andric   struct UseQueueType {
UseQueueTypeBitTracker::UseQueueType750b57cec5SDimitry Andric     UseQueueType() : Uses(Dist) {}
760b57cec5SDimitry Andric 
sizeBitTracker::UseQueueType770b57cec5SDimitry Andric     unsigned size() const {
780b57cec5SDimitry Andric       return Uses.size();
790b57cec5SDimitry Andric     }
emptyBitTracker::UseQueueType800b57cec5SDimitry Andric     bool empty() const {
810b57cec5SDimitry Andric       return size() == 0;
820b57cec5SDimitry Andric     }
frontBitTracker::UseQueueType830b57cec5SDimitry Andric     MachineInstr *front() const {
840b57cec5SDimitry Andric       return Uses.top();
850b57cec5SDimitry Andric     }
pushBitTracker::UseQueueType860b57cec5SDimitry Andric     void push(MachineInstr *MI) {
870b57cec5SDimitry Andric       if (Set.insert(MI).second)
880b57cec5SDimitry Andric         Uses.push(MI);
890b57cec5SDimitry Andric     }
popBitTracker::UseQueueType900b57cec5SDimitry Andric     void pop() {
910b57cec5SDimitry Andric       Set.erase(front());
920b57cec5SDimitry Andric       Uses.pop();
930b57cec5SDimitry Andric     }
resetBitTracker::UseQueueType940b57cec5SDimitry Andric     void reset() {
950b57cec5SDimitry Andric       Dist.clear();
960b57cec5SDimitry Andric     }
970b57cec5SDimitry Andric   private:
980b57cec5SDimitry Andric     struct Cmp {
CmpBitTracker::UseQueueType::Cmp990b57cec5SDimitry Andric       Cmp(DenseMap<const MachineInstr*,unsigned> &Map) : Dist(Map) {}
1000b57cec5SDimitry Andric       bool operator()(const MachineInstr *MI, const MachineInstr *MJ) const;
1010b57cec5SDimitry Andric       DenseMap<const MachineInstr*,unsigned> &Dist;
1020b57cec5SDimitry Andric     };
1030b57cec5SDimitry Andric     std::priority_queue<MachineInstr*, std::vector<MachineInstr*>, Cmp> Uses;
1040b57cec5SDimitry Andric     DenseSet<const MachineInstr*> Set; // Set to avoid adding duplicate entries.
1050b57cec5SDimitry Andric     DenseMap<const MachineInstr*,unsigned> Dist;
1060b57cec5SDimitry Andric   };
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   void reset();
1090b57cec5SDimitry Andric   void runEdgeQueue(BitVector &BlockScanned);
1100b57cec5SDimitry Andric   void runUseQueue();
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   const MachineEvaluator &ME;
1130b57cec5SDimitry Andric   MachineFunction &MF;
1140b57cec5SDimitry Andric   MachineRegisterInfo &MRI;
1150b57cec5SDimitry Andric   CellMapType &Map;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   EdgeSetType EdgeExec;         // Executable flow graph edges.
1180b57cec5SDimitry Andric   InstrSetType InstrExec;       // Executable instructions.
1190b57cec5SDimitry Andric   UseQueueType UseQ;            // Work queue of register uses.
1200b57cec5SDimitry Andric   EdgeQueueType FlowQ;          // Work queue of CFG edges.
1210b57cec5SDimitry Andric   DenseSet<unsigned> ReachedBB; // Cache of reached blocks.
1220b57cec5SDimitry Andric   bool Trace;                   // Enable tracing for debugging.
1230b57cec5SDimitry Andric };
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric // Abstraction of a reference to bit at position Pos from a register Reg.
1260b57cec5SDimitry Andric struct BitTracker::BitRef {
RegBitRef1270b57cec5SDimitry Andric   BitRef(unsigned R = 0, uint16_t P = 0) : Reg(R), Pos(P) {}
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   bool operator== (const BitRef &BR) const {
1300b57cec5SDimitry Andric     // If Reg is 0, disregard Pos.
1310b57cec5SDimitry Andric     return Reg == BR.Reg && (Reg == 0 || Pos == BR.Pos);
1320b57cec5SDimitry Andric   }
1330b57cec5SDimitry Andric 
134*e8d8bef9SDimitry Andric   Register Reg;
1350b57cec5SDimitry Andric   uint16_t Pos;
1360b57cec5SDimitry Andric };
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric // Abstraction of a register reference in MachineOperand.  It contains the
1390b57cec5SDimitry Andric // register number and the subregister index.
140*e8d8bef9SDimitry Andric // FIXME: Consolidate duplicate definitions of RegisterRef
1410b57cec5SDimitry Andric struct BitTracker::RegisterRef {
RegRegisterRef142*e8d8bef9SDimitry Andric   RegisterRef(Register R = 0, unsigned S = 0) : Reg(R), Sub(S) {}
RegisterRefRegisterRef1430b57cec5SDimitry Andric   RegisterRef(const MachineOperand &MO)
1440b57cec5SDimitry Andric       : Reg(MO.getReg()), Sub(MO.getSubReg()) {}
1450b57cec5SDimitry Andric 
146*e8d8bef9SDimitry Andric   Register Reg;
147*e8d8bef9SDimitry Andric   unsigned Sub;
1480b57cec5SDimitry Andric };
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric // Value that a single bit can take.  This is outside of the context of
1510b57cec5SDimitry Andric // any register, it is more of an abstraction of the two-element set of
1520b57cec5SDimitry Andric // possible bit values.  One extension here is the "Ref" type, which
1530b57cec5SDimitry Andric // indicates that this bit takes the same value as the bit described by
1540b57cec5SDimitry Andric // RefInfo.
1550b57cec5SDimitry Andric struct BitTracker::BitValue {
1560b57cec5SDimitry Andric   enum ValueType {
1570b57cec5SDimitry Andric     Top,    // Bit not yet defined.
1580b57cec5SDimitry Andric     Zero,   // Bit = 0.
1590b57cec5SDimitry Andric     One,    // Bit = 1.
1600b57cec5SDimitry Andric     Ref     // Bit value same as the one described in RefI.
1610b57cec5SDimitry Andric     // Conceptually, there is no explicit "bottom" value: the lattice's
1620b57cec5SDimitry Andric     // bottom will be expressed as a "ref to itself", which, in the context
1630b57cec5SDimitry Andric     // of registers, could be read as "this value of this bit is defined by
1640b57cec5SDimitry Andric     // this bit".
1650b57cec5SDimitry Andric     // The ordering is:
1660b57cec5SDimitry Andric     //   x <= Top,
1670b57cec5SDimitry Andric     //   Self <= x, where "Self" is "ref to itself".
1680b57cec5SDimitry Andric     // This makes the value lattice different for each virtual register
1690b57cec5SDimitry Andric     // (even for each bit in the same virtual register), since the "bottom"
1700b57cec5SDimitry Andric     // for one register will be a simple "ref" for another register.
1710b57cec5SDimitry Andric     // Since we do not store the "Self" bit and register number, the meet
1720b57cec5SDimitry Andric     // operation will need to take it as a parameter.
1730b57cec5SDimitry Andric     //
1740b57cec5SDimitry Andric     // In practice there is a special case for values that are not associa-
1750b57cec5SDimitry Andric     // ted with any specific virtual register. An example would be a value
1760b57cec5SDimitry Andric     // corresponding to a bit of a physical register, or an intermediate
1770b57cec5SDimitry Andric     // value obtained in some computation (such as instruction evaluation).
1780b57cec5SDimitry Andric     // Such cases are identical to the usual Ref type, but the register
1790b57cec5SDimitry Andric     // number is 0. In such case the Pos field of the reference is ignored.
1800b57cec5SDimitry Andric     //
1810b57cec5SDimitry Andric     // What is worthy of notice is that in value V (that is a "ref"), as long
1820b57cec5SDimitry Andric     // as the RefI.Reg is not 0, it may actually be the same register as the
1830b57cec5SDimitry Andric     // one in which V will be contained.  If the RefI.Pos refers to the posi-
1840b57cec5SDimitry Andric     // tion of V, then V is assumed to be "bottom" (as a "ref to itself"),
1850b57cec5SDimitry Andric     // otherwise V is taken to be identical to the referenced bit of the
1860b57cec5SDimitry Andric     // same register.
1870b57cec5SDimitry Andric     // If RefI.Reg is 0, however, such a reference to the same register is
1880b57cec5SDimitry Andric     // not possible.  Any value V that is a "ref", and whose RefI.Reg is 0
1890b57cec5SDimitry Andric     // is treated as "bottom".
1900b57cec5SDimitry Andric   };
1910b57cec5SDimitry Andric   ValueType Type;
1920b57cec5SDimitry Andric   BitRef RefI;
1930b57cec5SDimitry Andric 
TypeBitValue1940b57cec5SDimitry Andric   BitValue(ValueType T = Top) : Type(T) {}
BitValueBitValue1950b57cec5SDimitry Andric   BitValue(bool B) : Type(B ? One : Zero) {}
BitValueBitValue1960b57cec5SDimitry Andric   BitValue(unsigned Reg, uint16_t Pos) : Type(Ref), RefI(Reg, Pos) {}
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   bool operator== (const BitValue &V) const {
1990b57cec5SDimitry Andric     if (Type != V.Type)
2000b57cec5SDimitry Andric       return false;
2010b57cec5SDimitry Andric     if (Type == Ref && !(RefI == V.RefI))
2020b57cec5SDimitry Andric       return false;
2030b57cec5SDimitry Andric     return true;
2040b57cec5SDimitry Andric   }
2050b57cec5SDimitry Andric   bool operator!= (const BitValue &V) const {
2060b57cec5SDimitry Andric     return !operator==(V);
2070b57cec5SDimitry Andric   }
2080b57cec5SDimitry Andric 
isBitValue2090b57cec5SDimitry Andric   bool is(unsigned T) const {
2100b57cec5SDimitry Andric     assert(T == 0 || T == 1);
2110b57cec5SDimitry Andric     return T == 0 ? Type == Zero
2120b57cec5SDimitry Andric                   : (T == 1 ? Type == One : false);
2130b57cec5SDimitry Andric   }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   // The "meet" operation is the "." operation in a semilattice (L, ., T, B):
2160b57cec5SDimitry Andric   // (1)  x.x = x
2170b57cec5SDimitry Andric   // (2)  x.y = y.x
2180b57cec5SDimitry Andric   // (3)  x.(y.z) = (x.y).z
2190b57cec5SDimitry Andric   // (4)  x.T = x  (i.e. T = "top")
2200b57cec5SDimitry Andric   // (5)  x.B = B  (i.e. B = "bottom")
2210b57cec5SDimitry Andric   //
2220b57cec5SDimitry Andric   // This "meet" function will update the value of the "*this" object with
2230b57cec5SDimitry Andric   // the newly calculated one, and return "true" if the value of *this has
2240b57cec5SDimitry Andric   // changed, and "false" otherwise.
2250b57cec5SDimitry Andric   // To prove that it satisfies the conditions (1)-(5), it is sufficient
2260b57cec5SDimitry Andric   // to show that a relation
2270b57cec5SDimitry Andric   //   x <= y  <=>  x.y = x
2280b57cec5SDimitry Andric   // defines a partial order (i.e. that "meet" is same as "infimum").
meetBitValue2290b57cec5SDimitry Andric   bool meet(const BitValue &V, const BitRef &Self) {
2300b57cec5SDimitry Andric     // First, check the cases where there is nothing to be done.
2310b57cec5SDimitry Andric     if (Type == Ref && RefI == Self)    // Bottom.meet(V) = Bottom (i.e. This)
2320b57cec5SDimitry Andric       return false;
2330b57cec5SDimitry Andric     if (V.Type == Top)                  // This.meet(Top) = This
2340b57cec5SDimitry Andric       return false;
2350b57cec5SDimitry Andric     if (*this == V)                     // This.meet(This) = This
2360b57cec5SDimitry Andric       return false;
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric     // At this point, we know that the value of "this" will change.
2390b57cec5SDimitry Andric     // If it is Top, it will become the same as V, otherwise it will
2400b57cec5SDimitry Andric     // become "bottom" (i.e. Self).
2410b57cec5SDimitry Andric     if (Type == Top) {
2420b57cec5SDimitry Andric       Type = V.Type;
2430b57cec5SDimitry Andric       RefI = V.RefI;  // This may be irrelevant, but copy anyway.
2440b57cec5SDimitry Andric       return true;
2450b57cec5SDimitry Andric     }
2460b57cec5SDimitry Andric     // Become "bottom".
2470b57cec5SDimitry Andric     Type = Ref;
2480b57cec5SDimitry Andric     RefI = Self;
2490b57cec5SDimitry Andric     return true;
2500b57cec5SDimitry Andric   }
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   // Create a reference to the bit value V.
2530b57cec5SDimitry Andric   static BitValue ref(const BitValue &V);
2540b57cec5SDimitry Andric   // Create a "self".
2550b57cec5SDimitry Andric   static BitValue self(const BitRef &Self = BitRef());
2560b57cec5SDimitry Andric 
numBitValue2570b57cec5SDimitry Andric   bool num() const {
2580b57cec5SDimitry Andric     return Type == Zero || Type == One;
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   operator bool() const {
2620b57cec5SDimitry Andric     assert(Type == Zero || Type == One);
2630b57cec5SDimitry Andric     return Type == One;
2640b57cec5SDimitry Andric   }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   friend raw_ostream &operator<<(raw_ostream &OS, const BitValue &BV);
2670b57cec5SDimitry Andric };
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric // This operation must be idempotent, i.e. ref(ref(V)) == ref(V).
2700b57cec5SDimitry Andric inline BitTracker::BitValue
ref(const BitValue & V)2710b57cec5SDimitry Andric BitTracker::BitValue::ref(const BitValue &V) {
2720b57cec5SDimitry Andric   if (V.Type != Ref)
2730b57cec5SDimitry Andric     return BitValue(V.Type);
2740b57cec5SDimitry Andric   if (V.RefI.Reg != 0)
2750b57cec5SDimitry Andric     return BitValue(V.RefI.Reg, V.RefI.Pos);
2760b57cec5SDimitry Andric   return self();
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric inline BitTracker::BitValue
self(const BitRef & Self)2800b57cec5SDimitry Andric BitTracker::BitValue::self(const BitRef &Self) {
2810b57cec5SDimitry Andric   return BitValue(Self.Reg, Self.Pos);
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric // A sequence of bits starting from index B up to and including index E.
2850b57cec5SDimitry Andric // If E < B, the mask represents two sections: [0..E] and [B..W) where
2860b57cec5SDimitry Andric // W is the width of the register.
2870b57cec5SDimitry Andric struct BitTracker::BitMask {
2880b57cec5SDimitry Andric   BitMask() = default;
BitMaskBitMask2890b57cec5SDimitry Andric   BitMask(uint16_t b, uint16_t e) : B(b), E(e) {}
2900b57cec5SDimitry Andric 
firstBitMask2910b57cec5SDimitry Andric   uint16_t first() const { return B; }
lastBitMask2920b57cec5SDimitry Andric   uint16_t last() const { return E; }
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric private:
2950b57cec5SDimitry Andric   uint16_t B = 0;
2960b57cec5SDimitry Andric   uint16_t E = 0;
2970b57cec5SDimitry Andric };
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric // Representation of a register: a list of BitValues.
3000b57cec5SDimitry Andric struct BitTracker::RegisterCell {
BitsRegisterCell3010b57cec5SDimitry Andric   RegisterCell(uint16_t Width = DefaultBitN) : Bits(Width) {}
3020b57cec5SDimitry Andric 
widthRegisterCell3030b57cec5SDimitry Andric   uint16_t width() const {
3040b57cec5SDimitry Andric     return Bits.size();
3050b57cec5SDimitry Andric   }
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   const BitValue &operator[](uint16_t BitN) const {
3080b57cec5SDimitry Andric     assert(BitN < Bits.size());
3090b57cec5SDimitry Andric     return Bits[BitN];
3100b57cec5SDimitry Andric   }
3110b57cec5SDimitry Andric   BitValue &operator[](uint16_t BitN) {
3120b57cec5SDimitry Andric     assert(BitN < Bits.size());
3130b57cec5SDimitry Andric     return Bits[BitN];
3140b57cec5SDimitry Andric   }
3150b57cec5SDimitry Andric 
316*e8d8bef9SDimitry Andric   bool meet(const RegisterCell &RC, Register SelfR);
3170b57cec5SDimitry Andric   RegisterCell &insert(const RegisterCell &RC, const BitMask &M);
3180b57cec5SDimitry Andric   RegisterCell extract(const BitMask &M) const;  // Returns a new cell.
3190b57cec5SDimitry Andric   RegisterCell &rol(uint16_t Sh);    // Rotate left.
3200b57cec5SDimitry Andric   RegisterCell &fill(uint16_t B, uint16_t E, const BitValue &V);
3210b57cec5SDimitry Andric   RegisterCell &cat(const RegisterCell &RC);  // Concatenate.
3220b57cec5SDimitry Andric   uint16_t cl(bool B) const;
3230b57cec5SDimitry Andric   uint16_t ct(bool B) const;
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   bool operator== (const RegisterCell &RC) const;
3260b57cec5SDimitry Andric   bool operator!= (const RegisterCell &RC) const {
3270b57cec5SDimitry Andric     return !operator==(RC);
3280b57cec5SDimitry Andric   }
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   // Replace the ref-to-reg-0 bit values with the given register.
3310b57cec5SDimitry Andric   RegisterCell &regify(unsigned R);
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   // Generate a "ref" cell for the corresponding register. In the resulting
3340b57cec5SDimitry Andric   // cell each bit will be described as being the same as the corresponding
3350b57cec5SDimitry Andric   // bit in register Reg (i.e. the cell is "defined" by register Reg).
3360b57cec5SDimitry Andric   static RegisterCell self(unsigned Reg, uint16_t Width);
3370b57cec5SDimitry Andric   // Generate a "top" cell of given size.
3380b57cec5SDimitry Andric   static RegisterCell top(uint16_t Width);
3390b57cec5SDimitry Andric   // Generate a cell that is a "ref" to another cell.
3400b57cec5SDimitry Andric   static RegisterCell ref(const RegisterCell &C);
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric private:
3430b57cec5SDimitry Andric   // The DefaultBitN is here only to avoid frequent reallocation of the
3440b57cec5SDimitry Andric   // memory in the vector.
3450b57cec5SDimitry Andric   static const unsigned DefaultBitN = 32;
3460b57cec5SDimitry Andric   using BitValueList = SmallVector<BitValue, DefaultBitN>;
3470b57cec5SDimitry Andric   BitValueList Bits;
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   friend raw_ostream &operator<<(raw_ostream &OS, const RegisterCell &RC);
3500b57cec5SDimitry Andric };
3510b57cec5SDimitry Andric 
has(unsigned Reg)3520b57cec5SDimitry Andric inline bool BitTracker::has(unsigned Reg) const {
3530b57cec5SDimitry Andric   return Map.find(Reg) != Map.end();
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric inline const BitTracker::RegisterCell&
lookup(unsigned Reg)3570b57cec5SDimitry Andric BitTracker::lookup(unsigned Reg) const {
3580b57cec5SDimitry Andric   CellMapType::const_iterator F = Map.find(Reg);
3590b57cec5SDimitry Andric   assert(F != Map.end());
3600b57cec5SDimitry Andric   return F->second;
3610b57cec5SDimitry Andric }
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric inline BitTracker::RegisterCell
self(unsigned Reg,uint16_t Width)3640b57cec5SDimitry Andric BitTracker::RegisterCell::self(unsigned Reg, uint16_t Width) {
3650b57cec5SDimitry Andric   RegisterCell RC(Width);
3660b57cec5SDimitry Andric   for (uint16_t i = 0; i < Width; ++i)
3670b57cec5SDimitry Andric     RC.Bits[i] = BitValue::self(BitRef(Reg, i));
3680b57cec5SDimitry Andric   return RC;
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric inline BitTracker::RegisterCell
top(uint16_t Width)3720b57cec5SDimitry Andric BitTracker::RegisterCell::top(uint16_t Width) {
3730b57cec5SDimitry Andric   RegisterCell RC(Width);
3740b57cec5SDimitry Andric   for (uint16_t i = 0; i < Width; ++i)
3750b57cec5SDimitry Andric     RC.Bits[i] = BitValue(BitValue::Top);
3760b57cec5SDimitry Andric   return RC;
3770b57cec5SDimitry Andric }
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric inline BitTracker::RegisterCell
ref(const RegisterCell & C)3800b57cec5SDimitry Andric BitTracker::RegisterCell::ref(const RegisterCell &C) {
3810b57cec5SDimitry Andric   uint16_t W = C.width();
3820b57cec5SDimitry Andric   RegisterCell RC(W);
3830b57cec5SDimitry Andric   for (unsigned i = 0; i < W; ++i)
3840b57cec5SDimitry Andric     RC[i] = BitValue::ref(C[i]);
3850b57cec5SDimitry Andric   return RC;
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric // A class to evaluate target's instructions and update the cell maps.
3890b57cec5SDimitry Andric // This is used internally by the bit tracker.  A target that wants to
3900b57cec5SDimitry Andric // utilize this should implement the evaluation functions (noted below)
3910b57cec5SDimitry Andric // in a subclass of this class.
3920b57cec5SDimitry Andric struct BitTracker::MachineEvaluator {
MachineEvaluatorMachineEvaluator3930b57cec5SDimitry Andric   MachineEvaluator(const TargetRegisterInfo &T, MachineRegisterInfo &M)
3940b57cec5SDimitry Andric       : TRI(T), MRI(M) {}
3950b57cec5SDimitry Andric   virtual ~MachineEvaluator() = default;
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   uint16_t getRegBitWidth(const RegisterRef &RR) const;
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric   RegisterCell getCell(const RegisterRef &RR, const CellMapType &M) const;
4000b57cec5SDimitry Andric   void putCell(const RegisterRef &RR, RegisterCell RC, CellMapType &M) const;
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric   // A result of any operation should use refs to the source cells, not
4030b57cec5SDimitry Andric   // the cells directly. This function is a convenience wrapper to quickly
4040b57cec5SDimitry Andric   // generate a ref for a cell corresponding to a register reference.
getRefMachineEvaluator4050b57cec5SDimitry Andric   RegisterCell getRef(const RegisterRef &RR, const CellMapType &M) const {
4060b57cec5SDimitry Andric     RegisterCell RC = getCell(RR, M);
4070b57cec5SDimitry Andric     return RegisterCell::ref(RC);
4080b57cec5SDimitry Andric   }
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   // Helper functions.
4110b57cec5SDimitry Andric   // Check if a cell is an immediate value (i.e. all bits are either 0 or 1).
4120b57cec5SDimitry Andric   bool isInt(const RegisterCell &A) const;
4130b57cec5SDimitry Andric   // Convert cell to an immediate value.
4140b57cec5SDimitry Andric   uint64_t toInt(const RegisterCell &A) const;
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   // Generate cell from an immediate value.
4170b57cec5SDimitry Andric   RegisterCell eIMM(int64_t V, uint16_t W) const;
4180b57cec5SDimitry Andric   RegisterCell eIMM(const ConstantInt *CI) const;
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   // Arithmetic.
4210b57cec5SDimitry Andric   RegisterCell eADD(const RegisterCell &A1, const RegisterCell &A2) const;
4220b57cec5SDimitry Andric   RegisterCell eSUB(const RegisterCell &A1, const RegisterCell &A2) const;
4230b57cec5SDimitry Andric   RegisterCell eMLS(const RegisterCell &A1, const RegisterCell &A2) const;
4240b57cec5SDimitry Andric   RegisterCell eMLU(const RegisterCell &A1, const RegisterCell &A2) const;
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   // Shifts.
4270b57cec5SDimitry Andric   RegisterCell eASL(const RegisterCell &A1, uint16_t Sh) const;
4280b57cec5SDimitry Andric   RegisterCell eLSR(const RegisterCell &A1, uint16_t Sh) const;
4290b57cec5SDimitry Andric   RegisterCell eASR(const RegisterCell &A1, uint16_t Sh) const;
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   // Logical.
4320b57cec5SDimitry Andric   RegisterCell eAND(const RegisterCell &A1, const RegisterCell &A2) const;
4330b57cec5SDimitry Andric   RegisterCell eORL(const RegisterCell &A1, const RegisterCell &A2) const;
4340b57cec5SDimitry Andric   RegisterCell eXOR(const RegisterCell &A1, const RegisterCell &A2) const;
4350b57cec5SDimitry Andric   RegisterCell eNOT(const RegisterCell &A1) const;
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   // Set bit, clear bit.
4380b57cec5SDimitry Andric   RegisterCell eSET(const RegisterCell &A1, uint16_t BitN) const;
4390b57cec5SDimitry Andric   RegisterCell eCLR(const RegisterCell &A1, uint16_t BitN) const;
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric   // Count leading/trailing bits (zeros/ones).
4420b57cec5SDimitry Andric   RegisterCell eCLB(const RegisterCell &A1, bool B, uint16_t W) const;
4430b57cec5SDimitry Andric   RegisterCell eCTB(const RegisterCell &A1, bool B, uint16_t W) const;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   // Sign/zero extension.
4460b57cec5SDimitry Andric   RegisterCell eSXT(const RegisterCell &A1, uint16_t FromN) const;
4470b57cec5SDimitry Andric   RegisterCell eZXT(const RegisterCell &A1, uint16_t FromN) const;
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   // Extract/insert
4500b57cec5SDimitry Andric   // XTR R,b,e:  extract bits from A1 starting at bit b, ending at e-1.
4510b57cec5SDimitry Andric   // INS R,S,b:  take R and replace bits starting from b with S.
4520b57cec5SDimitry Andric   RegisterCell eXTR(const RegisterCell &A1, uint16_t B, uint16_t E) const;
4530b57cec5SDimitry Andric   RegisterCell eINS(const RegisterCell &A1, const RegisterCell &A2,
4540b57cec5SDimitry Andric                     uint16_t AtN) const;
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric   // User-provided functions for individual targets:
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   // Return a sub-register mask that indicates which bits in Reg belong
4590b57cec5SDimitry Andric   // to the subregister Sub. These bits are assumed to be contiguous in
4600b57cec5SDimitry Andric   // the super-register, and have the same ordering in the sub-register
4610b57cec5SDimitry Andric   // as in the super-register. It is valid to call this function with
4620b57cec5SDimitry Andric   // Sub == 0, in this case, the function should return a mask that spans
4630b57cec5SDimitry Andric   // the entire register Reg (which is what the default implementation
4640b57cec5SDimitry Andric   // does).
465*e8d8bef9SDimitry Andric   virtual BitMask mask(Register Reg, unsigned Sub) const;
4660b57cec5SDimitry Andric   // Indicate whether a given register class should be tracked.
trackMachineEvaluator4670b57cec5SDimitry Andric   virtual bool track(const TargetRegisterClass *RC) const { return true; }
4680b57cec5SDimitry Andric   // Evaluate a non-branching machine instruction, given the cell map with
4690b57cec5SDimitry Andric   // the input values. Place the results in the Outputs map. Return "true"
4700b57cec5SDimitry Andric   // if evaluation succeeded, "false" otherwise.
4710b57cec5SDimitry Andric   virtual bool evaluate(const MachineInstr &MI, const CellMapType &Inputs,
4720b57cec5SDimitry Andric                         CellMapType &Outputs) const;
4730b57cec5SDimitry Andric   // Evaluate a branch, given the cell map with the input values. Fill out
4740b57cec5SDimitry Andric   // a list of all possible branch targets and indicate (through a flag)
4750b57cec5SDimitry Andric   // whether the branch could fall-through. Return "true" if this information
4760b57cec5SDimitry Andric   // has been successfully computed, "false" otherwise.
4770b57cec5SDimitry Andric   virtual bool evaluate(const MachineInstr &BI, const CellMapType &Inputs,
4780b57cec5SDimitry Andric                         BranchTargetList &Targets, bool &FallsThru) const = 0;
4790b57cec5SDimitry Andric   // Given a register class RC, return a register class that should be assumed
4800b57cec5SDimitry Andric   // when a register from class RC is used with a subregister of index Idx.
4810b57cec5SDimitry Andric   virtual const TargetRegisterClass&
composeWithSubRegIndexMachineEvaluator4820b57cec5SDimitry Andric   composeWithSubRegIndex(const TargetRegisterClass &RC, unsigned Idx) const {
4830b57cec5SDimitry Andric     if (Idx == 0)
4840b57cec5SDimitry Andric       return RC;
4850b57cec5SDimitry Andric     llvm_unreachable("Unimplemented composeWithSubRegIndex");
4860b57cec5SDimitry Andric   }
4870b57cec5SDimitry Andric   // Return the size in bits of the physical register Reg.
488*e8d8bef9SDimitry Andric   virtual uint16_t getPhysRegBitWidth(MCRegister Reg) const;
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   const TargetRegisterInfo &TRI;
4910b57cec5SDimitry Andric   MachineRegisterInfo &MRI;
4920b57cec5SDimitry Andric };
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric } // end namespace llvm
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_HEXAGON_BITTRACKER_H
497