10b57cec5SDimitry Andric //===- BitTracker.cpp -----------------------------------------------------===//
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 // SSA-based bit propagation.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric // The purpose of this code is, for a given virtual register, to provide
120b57cec5SDimitry Andric // information about the value of each bit in the register. The values
130b57cec5SDimitry Andric // of bits are represented by the class BitValue, and take one of four
140b57cec5SDimitry Andric // cases: 0, 1, "ref" and "bottom". The 0 and 1 are rather clear, the
150b57cec5SDimitry Andric // "ref" value means that the bit is a copy of another bit (which itself
160b57cec5SDimitry Andric // cannot be a copy of yet another bit---such chains are not allowed).
170b57cec5SDimitry Andric // A "ref" value is associated with a BitRef structure, which indicates
180b57cec5SDimitry Andric // which virtual register, and which bit in that register is the origin
190b57cec5SDimitry Andric // of the value. For example, given an instruction
200b57cec5SDimitry Andric // %2 = ASL %1, 1
210b57cec5SDimitry Andric // assuming that nothing is known about bits of %1, bit 1 of %2
220b57cec5SDimitry Andric // will be a "ref" to (%1, 0). If there is a subsequent instruction
230b57cec5SDimitry Andric // %3 = ASL %2, 2
240b57cec5SDimitry Andric // then bit 3 of %3 will be a "ref" to (%1, 0) as well.
250b57cec5SDimitry Andric // The "bottom" case means that the bit's value cannot be determined,
260b57cec5SDimitry Andric // and that this virtual register actually defines it. The "bottom" case
270b57cec5SDimitry Andric // is discussed in detail in BitTracker.h. In fact, "bottom" is a "ref
280b57cec5SDimitry Andric // to self", so for the %1 above, the bit 0 of it will be a "ref" to
290b57cec5SDimitry Andric // (%1, 0), bit 1 will be a "ref" to (%1, 1), etc.
300b57cec5SDimitry Andric //
310b57cec5SDimitry Andric // The tracker implements the Wegman-Zadeck algorithm, originally developed
320b57cec5SDimitry Andric // for SSA-based constant propagation. Each register is represented as
330b57cec5SDimitry Andric // a sequence of bits, with the convention that bit 0 is the least signi-
340b57cec5SDimitry Andric // ficant bit. Each bit is propagated individually. The class RegisterCell
350b57cec5SDimitry Andric // implements the register's representation, and is also the subject of
360b57cec5SDimitry Andric // the lattice operations in the tracker.
370b57cec5SDimitry Andric //
380b57cec5SDimitry Andric // The intended usage of the bit tracker is to create a target-specific
390b57cec5SDimitry Andric // machine instruction evaluator, pass the evaluator to the BitTracker
400b57cec5SDimitry Andric // object, and run the tracker. The tracker will then collect the bit
410b57cec5SDimitry Andric // value information for a given machine function. After that, it can be
420b57cec5SDimitry Andric // queried for the cells for each virtual register.
430b57cec5SDimitry Andric // Sample code:
440b57cec5SDimitry Andric // const TargetSpecificEvaluator TSE(TRI, MRI);
450b57cec5SDimitry Andric // BitTracker BT(TSE, MF);
460b57cec5SDimitry Andric // BT.run();
470b57cec5SDimitry Andric // ...
480b57cec5SDimitry Andric // unsigned Reg = interestingRegister();
490b57cec5SDimitry Andric // RegisterCell RC = BT.get(Reg);
500b57cec5SDimitry Andric // if (RC[3].is(1))
510b57cec5SDimitry Andric // Reg0bit3 = 1;
520b57cec5SDimitry Andric //
530b57cec5SDimitry Andric // The code below is intended to be fully target-independent.
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric #include "BitTracker.h"
560b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
570b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
580b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
590b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
600b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
610b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
620b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
630b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
640b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
650b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
660b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
670b57cec5SDimitry Andric #include <cassert>
680b57cec5SDimitry Andric #include <cstdint>
690b57cec5SDimitry Andric #include <iterator>
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric using namespace llvm;
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric using BT = BitTracker;
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric namespace {
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric // Local trickery to pretty print a register (without the whole "%number"
780b57cec5SDimitry Andric // business).
790b57cec5SDimitry Andric struct printv {
printv__anon9cb3ed6a0111::printv800b57cec5SDimitry Andric printv(unsigned r) : R(r) {}
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric unsigned R;
830b57cec5SDimitry Andric };
840b57cec5SDimitry Andric
operator <<(raw_ostream & OS,const printv & PV)850b57cec5SDimitry Andric raw_ostream &operator<< (raw_ostream &OS, const printv &PV) {
860b57cec5SDimitry Andric if (PV.R)
878bcb0991SDimitry Andric OS << 'v' << Register::virtReg2Index(PV.R);
880b57cec5SDimitry Andric else
890b57cec5SDimitry Andric OS << 's';
900b57cec5SDimitry Andric return OS;
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric } // end anonymous namespace
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric namespace llvm {
960b57cec5SDimitry Andric
operator <<(raw_ostream & OS,const BT::BitValue & BV)970b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const BT::BitValue &BV) {
980b57cec5SDimitry Andric switch (BV.Type) {
990b57cec5SDimitry Andric case BT::BitValue::Top:
1000b57cec5SDimitry Andric OS << 'T';
1010b57cec5SDimitry Andric break;
1020b57cec5SDimitry Andric case BT::BitValue::Zero:
1030b57cec5SDimitry Andric OS << '0';
1040b57cec5SDimitry Andric break;
1050b57cec5SDimitry Andric case BT::BitValue::One:
1060b57cec5SDimitry Andric OS << '1';
1070b57cec5SDimitry Andric break;
1080b57cec5SDimitry Andric case BT::BitValue::Ref:
1090b57cec5SDimitry Andric OS << printv(BV.RefI.Reg) << '[' << BV.RefI.Pos << ']';
1100b57cec5SDimitry Andric break;
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric return OS;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
operator <<(raw_ostream & OS,const BT::RegisterCell & RC)1150b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const BT::RegisterCell &RC) {
1160b57cec5SDimitry Andric unsigned n = RC.Bits.size();
1170b57cec5SDimitry Andric OS << "{ w:" << n;
1180b57cec5SDimitry Andric // Instead of printing each bit value individually, try to group them
1190b57cec5SDimitry Andric // into logical segments, such as sequences of 0 or 1 bits or references
1200b57cec5SDimitry Andric // to consecutive bits (e.g. "bits 3-5 are same as bits 7-9 of reg xyz").
1210b57cec5SDimitry Andric // "Start" will be the index of the beginning of the most recent segment.
1220b57cec5SDimitry Andric unsigned Start = 0;
1230b57cec5SDimitry Andric bool SeqRef = false; // A sequence of refs to consecutive bits.
1240b57cec5SDimitry Andric bool ConstRef = false; // A sequence of refs to the same bit.
1250b57cec5SDimitry Andric
1260b57cec5SDimitry Andric for (unsigned i = 1, n = RC.Bits.size(); i < n; ++i) {
1270b57cec5SDimitry Andric const BT::BitValue &V = RC[i];
1280b57cec5SDimitry Andric const BT::BitValue &SV = RC[Start];
1290b57cec5SDimitry Andric bool IsRef = (V.Type == BT::BitValue::Ref);
1300b57cec5SDimitry Andric // If the current value is the same as Start, skip to the next one.
1310b57cec5SDimitry Andric if (!IsRef && V == SV)
1320b57cec5SDimitry Andric continue;
1330b57cec5SDimitry Andric if (IsRef && SV.Type == BT::BitValue::Ref && V.RefI.Reg == SV.RefI.Reg) {
1340b57cec5SDimitry Andric if (Start+1 == i) {
1350b57cec5SDimitry Andric SeqRef = (V.RefI.Pos == SV.RefI.Pos+1);
1360b57cec5SDimitry Andric ConstRef = (V.RefI.Pos == SV.RefI.Pos);
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric if (SeqRef && V.RefI.Pos == SV.RefI.Pos+(i-Start))
1390b57cec5SDimitry Andric continue;
1400b57cec5SDimitry Andric if (ConstRef && V.RefI.Pos == SV.RefI.Pos)
1410b57cec5SDimitry Andric continue;
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric // The current value is different. Print the previous one and reset
1450b57cec5SDimitry Andric // the Start.
1460b57cec5SDimitry Andric OS << " [" << Start;
1470b57cec5SDimitry Andric unsigned Count = i - Start;
1480b57cec5SDimitry Andric if (Count == 1) {
1490b57cec5SDimitry Andric OS << "]:" << SV;
1500b57cec5SDimitry Andric } else {
1510b57cec5SDimitry Andric OS << '-' << i-1 << "]:";
1520b57cec5SDimitry Andric if (SV.Type == BT::BitValue::Ref && SeqRef)
1530b57cec5SDimitry Andric OS << printv(SV.RefI.Reg) << '[' << SV.RefI.Pos << '-'
1540b57cec5SDimitry Andric << SV.RefI.Pos+(Count-1) << ']';
1550b57cec5SDimitry Andric else
1560b57cec5SDimitry Andric OS << SV;
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric Start = i;
1590b57cec5SDimitry Andric SeqRef = ConstRef = false;
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric OS << " [" << Start;
1630b57cec5SDimitry Andric unsigned Count = n - Start;
1640b57cec5SDimitry Andric if (n-Start == 1) {
1650b57cec5SDimitry Andric OS << "]:" << RC[Start];
1660b57cec5SDimitry Andric } else {
1670b57cec5SDimitry Andric OS << '-' << n-1 << "]:";
1680b57cec5SDimitry Andric const BT::BitValue &SV = RC[Start];
1690b57cec5SDimitry Andric if (SV.Type == BT::BitValue::Ref && SeqRef)
1700b57cec5SDimitry Andric OS << printv(SV.RefI.Reg) << '[' << SV.RefI.Pos << '-'
1710b57cec5SDimitry Andric << SV.RefI.Pos+(Count-1) << ']';
1720b57cec5SDimitry Andric else
1730b57cec5SDimitry Andric OS << SV;
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric OS << " }";
1760b57cec5SDimitry Andric
1770b57cec5SDimitry Andric return OS;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andric } // end namespace llvm
1810b57cec5SDimitry Andric
print_cells(raw_ostream & OS) const1820b57cec5SDimitry Andric void BitTracker::print_cells(raw_ostream &OS) const {
1830b57cec5SDimitry Andric for (const std::pair<unsigned, RegisterCell> P : Map)
1840b57cec5SDimitry Andric dbgs() << printReg(P.first, &ME.TRI) << " -> " << P.second << "\n";
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
BitTracker(const MachineEvaluator & E,MachineFunction & F)1870b57cec5SDimitry Andric BitTracker::BitTracker(const MachineEvaluator &E, MachineFunction &F)
1880b57cec5SDimitry Andric : ME(E), MF(F), MRI(F.getRegInfo()), Map(*new CellMapType), Trace(false) {
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric
~BitTracker()1910b57cec5SDimitry Andric BitTracker::~BitTracker() {
1920b57cec5SDimitry Andric delete ⤅
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric
1950b57cec5SDimitry Andric // If we were allowed to update a cell for a part of a register, the meet
1960b57cec5SDimitry Andric // operation would need to be parametrized by the register number and the
1970b57cec5SDimitry Andric // exact part of the register, so that the computer BitRefs correspond to
1980b57cec5SDimitry Andric // the actual bits of the "self" register.
1990b57cec5SDimitry Andric // While this cannot happen in the current implementation, I'm not sure
2000b57cec5SDimitry Andric // if this should be ruled out in the future.
meet(const RegisterCell & RC,Register SelfR)201e8d8bef9SDimitry Andric bool BT::RegisterCell::meet(const RegisterCell &RC, Register SelfR) {
2020b57cec5SDimitry Andric // An example when "meet" can be invoked with SelfR == 0 is a phi node
2030b57cec5SDimitry Andric // with a physical register as an operand.
204e8d8bef9SDimitry Andric assert(SelfR == 0 || SelfR.isVirtual());
2050b57cec5SDimitry Andric bool Changed = false;
2060b57cec5SDimitry Andric for (uint16_t i = 0, n = Bits.size(); i < n; ++i) {
2070b57cec5SDimitry Andric const BitValue &RCV = RC[i];
2080b57cec5SDimitry Andric Changed |= Bits[i].meet(RCV, BitRef(SelfR, i));
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric return Changed;
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andric // Insert the entire cell RC into the current cell at position given by M.
insert(const BT::RegisterCell & RC,const BitMask & M)2140b57cec5SDimitry Andric BT::RegisterCell &BT::RegisterCell::insert(const BT::RegisterCell &RC,
2150b57cec5SDimitry Andric const BitMask &M) {
2160b57cec5SDimitry Andric uint16_t B = M.first(), E = M.last(), W = width();
2174824e7fdSDimitry Andric // M must be a valid mask for *this.
2180b57cec5SDimitry Andric assert(B < W && E < W);
2194824e7fdSDimitry Andric // The masked part of *this must have the same number of bits
2200b57cec5SDimitry Andric // as the source.
2210b57cec5SDimitry Andric assert(B > E || E-B+1 == RC.width()); // B <= E => E-B+1 = |RC|.
2220b57cec5SDimitry Andric assert(B <= E || E+(W-B)+1 == RC.width()); // E < B => E+(W-B)+1 = |RC|.
2230b57cec5SDimitry Andric if (B <= E) {
2240b57cec5SDimitry Andric for (uint16_t i = 0; i <= E-B; ++i)
2250b57cec5SDimitry Andric Bits[i+B] = RC[i];
2260b57cec5SDimitry Andric } else {
2270b57cec5SDimitry Andric for (uint16_t i = 0; i < W-B; ++i)
2280b57cec5SDimitry Andric Bits[i+B] = RC[i];
2290b57cec5SDimitry Andric for (uint16_t i = 0; i <= E; ++i)
2300b57cec5SDimitry Andric Bits[i] = RC[i+(W-B)];
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric return *this;
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric
extract(const BitMask & M) const2350b57cec5SDimitry Andric BT::RegisterCell BT::RegisterCell::extract(const BitMask &M) const {
2360b57cec5SDimitry Andric uint16_t B = M.first(), E = M.last(), W = width();
2370b57cec5SDimitry Andric assert(B < W && E < W);
2380b57cec5SDimitry Andric if (B <= E) {
2390b57cec5SDimitry Andric RegisterCell RC(E-B+1);
2400b57cec5SDimitry Andric for (uint16_t i = B; i <= E; ++i)
2410b57cec5SDimitry Andric RC.Bits[i-B] = Bits[i];
2420b57cec5SDimitry Andric return RC;
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric RegisterCell RC(E+(W-B)+1);
2460b57cec5SDimitry Andric for (uint16_t i = 0; i < W-B; ++i)
2470b57cec5SDimitry Andric RC.Bits[i] = Bits[i+B];
2480b57cec5SDimitry Andric for (uint16_t i = 0; i <= E; ++i)
2490b57cec5SDimitry Andric RC.Bits[i+(W-B)] = Bits[i];
2500b57cec5SDimitry Andric return RC;
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric
rol(uint16_t Sh)2530b57cec5SDimitry Andric BT::RegisterCell &BT::RegisterCell::rol(uint16_t Sh) {
2540b57cec5SDimitry Andric // Rotate left (i.e. towards increasing bit indices).
2550b57cec5SDimitry Andric // Swap the two parts: [0..W-Sh-1] [W-Sh..W-1]
2560b57cec5SDimitry Andric uint16_t W = width();
2570b57cec5SDimitry Andric Sh = Sh % W;
2580b57cec5SDimitry Andric if (Sh == 0)
2590b57cec5SDimitry Andric return *this;
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric RegisterCell Tmp(W-Sh);
2620b57cec5SDimitry Andric // Tmp = [0..W-Sh-1].
2630b57cec5SDimitry Andric for (uint16_t i = 0; i < W-Sh; ++i)
2640b57cec5SDimitry Andric Tmp[i] = Bits[i];
2650b57cec5SDimitry Andric // Shift [W-Sh..W-1] to [0..Sh-1].
2660b57cec5SDimitry Andric for (uint16_t i = 0; i < Sh; ++i)
2670b57cec5SDimitry Andric Bits[i] = Bits[W-Sh+i];
2680b57cec5SDimitry Andric // Copy Tmp to [Sh..W-1].
2690b57cec5SDimitry Andric for (uint16_t i = 0; i < W-Sh; ++i)
2700b57cec5SDimitry Andric Bits[i+Sh] = Tmp.Bits[i];
2710b57cec5SDimitry Andric return *this;
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric
fill(uint16_t B,uint16_t E,const BitValue & V)2740b57cec5SDimitry Andric BT::RegisterCell &BT::RegisterCell::fill(uint16_t B, uint16_t E,
2750b57cec5SDimitry Andric const BitValue &V) {
2760b57cec5SDimitry Andric assert(B <= E);
2770b57cec5SDimitry Andric while (B < E)
2780b57cec5SDimitry Andric Bits[B++] = V;
2790b57cec5SDimitry Andric return *this;
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric
cat(const RegisterCell & RC)2820b57cec5SDimitry Andric BT::RegisterCell &BT::RegisterCell::cat(const RegisterCell &RC) {
2830b57cec5SDimitry Andric // Append the cell given as the argument to the "this" cell.
2840b57cec5SDimitry Andric // Bit 0 of RC becomes bit W of the result, where W is this->width().
2850b57cec5SDimitry Andric uint16_t W = width(), WRC = RC.width();
2860b57cec5SDimitry Andric Bits.resize(W+WRC);
2870b57cec5SDimitry Andric for (uint16_t i = 0; i < WRC; ++i)
2880b57cec5SDimitry Andric Bits[i+W] = RC.Bits[i];
2890b57cec5SDimitry Andric return *this;
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric
ct(bool B) const2920b57cec5SDimitry Andric uint16_t BT::RegisterCell::ct(bool B) const {
2930b57cec5SDimitry Andric uint16_t W = width();
2940b57cec5SDimitry Andric uint16_t C = 0;
2950b57cec5SDimitry Andric BitValue V = B;
2960b57cec5SDimitry Andric while (C < W && Bits[C] == V)
2970b57cec5SDimitry Andric C++;
2980b57cec5SDimitry Andric return C;
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric
cl(bool B) const3010b57cec5SDimitry Andric uint16_t BT::RegisterCell::cl(bool B) const {
3020b57cec5SDimitry Andric uint16_t W = width();
3030b57cec5SDimitry Andric uint16_t C = 0;
3040b57cec5SDimitry Andric BitValue V = B;
3050b57cec5SDimitry Andric while (C < W && Bits[W-(C+1)] == V)
3060b57cec5SDimitry Andric C++;
3070b57cec5SDimitry Andric return C;
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric
operator ==(const RegisterCell & RC) const3100b57cec5SDimitry Andric bool BT::RegisterCell::operator== (const RegisterCell &RC) const {
3110b57cec5SDimitry Andric uint16_t W = Bits.size();
3120b57cec5SDimitry Andric if (RC.Bits.size() != W)
3130b57cec5SDimitry Andric return false;
3140b57cec5SDimitry Andric for (uint16_t i = 0; i < W; ++i)
3150b57cec5SDimitry Andric if (Bits[i] != RC[i])
3160b57cec5SDimitry Andric return false;
3170b57cec5SDimitry Andric return true;
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric
regify(unsigned R)3200b57cec5SDimitry Andric BT::RegisterCell &BT::RegisterCell::regify(unsigned R) {
3210b57cec5SDimitry Andric for (unsigned i = 0, n = width(); i < n; ++i) {
3220b57cec5SDimitry Andric const BitValue &V = Bits[i];
3230b57cec5SDimitry Andric if (V.Type == BitValue::Ref && V.RefI.Reg == 0)
3240b57cec5SDimitry Andric Bits[i].RefI = BitRef(R, i);
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric return *this;
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric
getRegBitWidth(const RegisterRef & RR) const3290b57cec5SDimitry Andric uint16_t BT::MachineEvaluator::getRegBitWidth(const RegisterRef &RR) const {
3300b57cec5SDimitry Andric // The general problem is with finding a register class that corresponds
3310b57cec5SDimitry Andric // to a given reference reg:sub. There can be several such classes, and
3320b57cec5SDimitry Andric // since we only care about the register size, it does not matter which
3330b57cec5SDimitry Andric // such class we would find.
3340b57cec5SDimitry Andric // The easiest way to accomplish what we want is to
3350b57cec5SDimitry Andric // 1. find a physical register PhysR from the same class as RR.Reg,
3360b57cec5SDimitry Andric // 2. find a physical register PhysS that corresponds to PhysR:RR.Sub,
3370b57cec5SDimitry Andric // 3. find a register class that contains PhysS.
338e8d8bef9SDimitry Andric if (RR.Reg.isVirtual()) {
3390b57cec5SDimitry Andric const auto &VC = composeWithSubRegIndex(*MRI.getRegClass(RR.Reg), RR.Sub);
3400b57cec5SDimitry Andric return TRI.getRegSizeInBits(VC);
3410b57cec5SDimitry Andric }
342e8d8bef9SDimitry Andric assert(RR.Reg.isPhysical());
343e8d8bef9SDimitry Andric MCRegister PhysR =
344e8d8bef9SDimitry Andric (RR.Sub == 0) ? RR.Reg.asMCReg() : TRI.getSubReg(RR.Reg, RR.Sub);
3450b57cec5SDimitry Andric return getPhysRegBitWidth(PhysR);
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric
getCell(const RegisterRef & RR,const CellMapType & M) const3480b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::getCell(const RegisterRef &RR,
3490b57cec5SDimitry Andric const CellMapType &M) const {
3500b57cec5SDimitry Andric uint16_t BW = getRegBitWidth(RR);
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric // Physical registers are assumed to be present in the map with an unknown
3530b57cec5SDimitry Andric // value. Don't actually insert anything in the map, just return the cell.
354e8d8bef9SDimitry Andric if (RR.Reg.isPhysical())
3550b57cec5SDimitry Andric return RegisterCell::self(0, BW);
3560b57cec5SDimitry Andric
357e8d8bef9SDimitry Andric assert(RR.Reg.isVirtual());
3580b57cec5SDimitry Andric // For virtual registers that belong to a class that is not tracked,
3590b57cec5SDimitry Andric // generate an "unknown" value as well.
3600b57cec5SDimitry Andric const TargetRegisterClass *C = MRI.getRegClass(RR.Reg);
3610b57cec5SDimitry Andric if (!track(C))
3620b57cec5SDimitry Andric return RegisterCell::self(0, BW);
3630b57cec5SDimitry Andric
3640b57cec5SDimitry Andric CellMapType::const_iterator F = M.find(RR.Reg);
3650b57cec5SDimitry Andric if (F != M.end()) {
3660b57cec5SDimitry Andric if (!RR.Sub)
3670b57cec5SDimitry Andric return F->second;
3680b57cec5SDimitry Andric BitMask M = mask(RR.Reg, RR.Sub);
3690b57cec5SDimitry Andric return F->second.extract(M);
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric // If not found, create a "top" entry, but do not insert it in the map.
3720b57cec5SDimitry Andric return RegisterCell::top(BW);
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric
putCell(const RegisterRef & RR,RegisterCell RC,CellMapType & M) const3750b57cec5SDimitry Andric void BT::MachineEvaluator::putCell(const RegisterRef &RR, RegisterCell RC,
3760b57cec5SDimitry Andric CellMapType &M) const {
3770b57cec5SDimitry Andric // While updating the cell map can be done in a meaningful way for
3780b57cec5SDimitry Andric // a part of a register, it makes little sense to implement it as the
3790b57cec5SDimitry Andric // SSA representation would never contain such "partial definitions".
380e8d8bef9SDimitry Andric if (!RR.Reg.isVirtual())
3810b57cec5SDimitry Andric return;
3820b57cec5SDimitry Andric assert(RR.Sub == 0 && "Unexpected sub-register in definition");
3830b57cec5SDimitry Andric // Eliminate all ref-to-reg-0 bit values: replace them with "self".
3840b57cec5SDimitry Andric M[RR.Reg] = RC.regify(RR.Reg);
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric
3870b57cec5SDimitry Andric // Check if the cell represents a compile-time integer value.
isInt(const RegisterCell & A) const3880b57cec5SDimitry Andric bool BT::MachineEvaluator::isInt(const RegisterCell &A) const {
3890b57cec5SDimitry Andric uint16_t W = A.width();
3900b57cec5SDimitry Andric for (uint16_t i = 0; i < W; ++i)
3910b57cec5SDimitry Andric if (!A[i].is(0) && !A[i].is(1))
3920b57cec5SDimitry Andric return false;
3930b57cec5SDimitry Andric return true;
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric
3960b57cec5SDimitry Andric // Convert a cell to the integer value. The result must fit in uint64_t.
toInt(const RegisterCell & A) const3970b57cec5SDimitry Andric uint64_t BT::MachineEvaluator::toInt(const RegisterCell &A) const {
3980b57cec5SDimitry Andric assert(isInt(A));
3990b57cec5SDimitry Andric uint64_t Val = 0;
4000b57cec5SDimitry Andric uint16_t W = A.width();
4010b57cec5SDimitry Andric for (uint16_t i = 0; i < W; ++i) {
4020b57cec5SDimitry Andric Val <<= 1;
4030b57cec5SDimitry Andric Val |= A[i].is(1);
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric return Val;
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric
4080b57cec5SDimitry Andric // Evaluator helper functions. These implement some common operation on
4090b57cec5SDimitry Andric // register cells that can be used to implement target-specific instructions
4100b57cec5SDimitry Andric // in a target-specific evaluator.
4110b57cec5SDimitry Andric
eIMM(int64_t V,uint16_t W) const4120b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eIMM(int64_t V, uint16_t W) const {
4130b57cec5SDimitry Andric RegisterCell Res(W);
4140b57cec5SDimitry Andric // For bits beyond the 63rd, this will generate the sign bit of V.
4150b57cec5SDimitry Andric for (uint16_t i = 0; i < W; ++i) {
4160b57cec5SDimitry Andric Res[i] = BitValue(V & 1);
4170b57cec5SDimitry Andric V >>= 1;
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric return Res;
4200b57cec5SDimitry Andric }
4210b57cec5SDimitry Andric
eIMM(const ConstantInt * CI) const4220b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eIMM(const ConstantInt *CI) const {
4230b57cec5SDimitry Andric const APInt &A = CI->getValue();
4240b57cec5SDimitry Andric uint16_t BW = A.getBitWidth();
4250b57cec5SDimitry Andric assert((unsigned)BW == A.getBitWidth() && "BitWidth overflow");
4260b57cec5SDimitry Andric RegisterCell Res(BW);
4270b57cec5SDimitry Andric for (uint16_t i = 0; i < BW; ++i)
4280b57cec5SDimitry Andric Res[i] = A[i];
4290b57cec5SDimitry Andric return Res;
4300b57cec5SDimitry Andric }
4310b57cec5SDimitry Andric
eADD(const RegisterCell & A1,const RegisterCell & A2) const4320b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eADD(const RegisterCell &A1,
4330b57cec5SDimitry Andric const RegisterCell &A2) const {
4340b57cec5SDimitry Andric uint16_t W = A1.width();
4350b57cec5SDimitry Andric assert(W == A2.width());
4360b57cec5SDimitry Andric RegisterCell Res(W);
4370b57cec5SDimitry Andric bool Carry = false;
4380b57cec5SDimitry Andric uint16_t I;
4390b57cec5SDimitry Andric for (I = 0; I < W; ++I) {
4400b57cec5SDimitry Andric const BitValue &V1 = A1[I];
4410b57cec5SDimitry Andric const BitValue &V2 = A2[I];
4420b57cec5SDimitry Andric if (!V1.num() || !V2.num())
4430b57cec5SDimitry Andric break;
4440b57cec5SDimitry Andric unsigned S = bool(V1) + bool(V2) + Carry;
4450b57cec5SDimitry Andric Res[I] = BitValue(S & 1);
4460b57cec5SDimitry Andric Carry = (S > 1);
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric for (; I < W; ++I) {
4490b57cec5SDimitry Andric const BitValue &V1 = A1[I];
4500b57cec5SDimitry Andric const BitValue &V2 = A2[I];
4510b57cec5SDimitry Andric // If the next bit is same as Carry, the result will be 0 plus the
4520b57cec5SDimitry Andric // other bit. The Carry bit will remain unchanged.
4530b57cec5SDimitry Andric if (V1.is(Carry))
4540b57cec5SDimitry Andric Res[I] = BitValue::ref(V2);
4550b57cec5SDimitry Andric else if (V2.is(Carry))
4560b57cec5SDimitry Andric Res[I] = BitValue::ref(V1);
4570b57cec5SDimitry Andric else
4580b57cec5SDimitry Andric break;
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric for (; I < W; ++I)
4610b57cec5SDimitry Andric Res[I] = BitValue::self();
4620b57cec5SDimitry Andric return Res;
4630b57cec5SDimitry Andric }
4640b57cec5SDimitry Andric
eSUB(const RegisterCell & A1,const RegisterCell & A2) const4650b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eSUB(const RegisterCell &A1,
4660b57cec5SDimitry Andric const RegisterCell &A2) const {
4670b57cec5SDimitry Andric uint16_t W = A1.width();
4680b57cec5SDimitry Andric assert(W == A2.width());
4690b57cec5SDimitry Andric RegisterCell Res(W);
4700b57cec5SDimitry Andric bool Borrow = false;
4710b57cec5SDimitry Andric uint16_t I;
4720b57cec5SDimitry Andric for (I = 0; I < W; ++I) {
4730b57cec5SDimitry Andric const BitValue &V1 = A1[I];
4740b57cec5SDimitry Andric const BitValue &V2 = A2[I];
4750b57cec5SDimitry Andric if (!V1.num() || !V2.num())
4760b57cec5SDimitry Andric break;
4770b57cec5SDimitry Andric unsigned S = bool(V1) - bool(V2) - Borrow;
4780b57cec5SDimitry Andric Res[I] = BitValue(S & 1);
4790b57cec5SDimitry Andric Borrow = (S > 1);
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric for (; I < W; ++I) {
4820b57cec5SDimitry Andric const BitValue &V1 = A1[I];
4830b57cec5SDimitry Andric const BitValue &V2 = A2[I];
4840b57cec5SDimitry Andric if (V1.is(Borrow)) {
4850b57cec5SDimitry Andric Res[I] = BitValue::ref(V2);
4860b57cec5SDimitry Andric break;
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric if (V2.is(Borrow))
4890b57cec5SDimitry Andric Res[I] = BitValue::ref(V1);
4900b57cec5SDimitry Andric else
4910b57cec5SDimitry Andric break;
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric for (; I < W; ++I)
4940b57cec5SDimitry Andric Res[I] = BitValue::self();
4950b57cec5SDimitry Andric return Res;
4960b57cec5SDimitry Andric }
4970b57cec5SDimitry Andric
eMLS(const RegisterCell & A1,const RegisterCell & A2) const4980b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eMLS(const RegisterCell &A1,
4990b57cec5SDimitry Andric const RegisterCell &A2) const {
5000b57cec5SDimitry Andric uint16_t W = A1.width() + A2.width();
5010b57cec5SDimitry Andric uint16_t Z = A1.ct(false) + A2.ct(false);
5020b57cec5SDimitry Andric RegisterCell Res(W);
5030b57cec5SDimitry Andric Res.fill(0, Z, BitValue::Zero);
5040b57cec5SDimitry Andric Res.fill(Z, W, BitValue::self());
5050b57cec5SDimitry Andric return Res;
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric
eMLU(const RegisterCell & A1,const RegisterCell & A2) const5080b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eMLU(const RegisterCell &A1,
5090b57cec5SDimitry Andric const RegisterCell &A2) const {
5100b57cec5SDimitry Andric uint16_t W = A1.width() + A2.width();
5110b57cec5SDimitry Andric uint16_t Z = A1.ct(false) + A2.ct(false);
5120b57cec5SDimitry Andric RegisterCell Res(W);
5130b57cec5SDimitry Andric Res.fill(0, Z, BitValue::Zero);
5140b57cec5SDimitry Andric Res.fill(Z, W, BitValue::self());
5150b57cec5SDimitry Andric return Res;
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric
eASL(const RegisterCell & A1,uint16_t Sh) const5180b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eASL(const RegisterCell &A1,
5190b57cec5SDimitry Andric uint16_t Sh) const {
5200b57cec5SDimitry Andric assert(Sh <= A1.width());
5210b57cec5SDimitry Andric RegisterCell Res = RegisterCell::ref(A1);
5220b57cec5SDimitry Andric Res.rol(Sh);
5230b57cec5SDimitry Andric Res.fill(0, Sh, BitValue::Zero);
5240b57cec5SDimitry Andric return Res;
5250b57cec5SDimitry Andric }
5260b57cec5SDimitry Andric
eLSR(const RegisterCell & A1,uint16_t Sh) const5270b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eLSR(const RegisterCell &A1,
5280b57cec5SDimitry Andric uint16_t Sh) const {
5290b57cec5SDimitry Andric uint16_t W = A1.width();
5300b57cec5SDimitry Andric assert(Sh <= W);
5310b57cec5SDimitry Andric RegisterCell Res = RegisterCell::ref(A1);
5320b57cec5SDimitry Andric Res.rol(W-Sh);
5330b57cec5SDimitry Andric Res.fill(W-Sh, W, BitValue::Zero);
5340b57cec5SDimitry Andric return Res;
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric
eASR(const RegisterCell & A1,uint16_t Sh) const5370b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eASR(const RegisterCell &A1,
5380b57cec5SDimitry Andric uint16_t Sh) const {
5390b57cec5SDimitry Andric uint16_t W = A1.width();
5400b57cec5SDimitry Andric assert(Sh <= W);
5410b57cec5SDimitry Andric RegisterCell Res = RegisterCell::ref(A1);
5420b57cec5SDimitry Andric BitValue Sign = Res[W-1];
5430b57cec5SDimitry Andric Res.rol(W-Sh);
5440b57cec5SDimitry Andric Res.fill(W-Sh, W, Sign);
5450b57cec5SDimitry Andric return Res;
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric
eAND(const RegisterCell & A1,const RegisterCell & A2) const5480b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eAND(const RegisterCell &A1,
5490b57cec5SDimitry Andric const RegisterCell &A2) const {
5500b57cec5SDimitry Andric uint16_t W = A1.width();
5510b57cec5SDimitry Andric assert(W == A2.width());
5520b57cec5SDimitry Andric RegisterCell Res(W);
5530b57cec5SDimitry Andric for (uint16_t i = 0; i < W; ++i) {
5540b57cec5SDimitry Andric const BitValue &V1 = A1[i];
5550b57cec5SDimitry Andric const BitValue &V2 = A2[i];
5560b57cec5SDimitry Andric if (V1.is(1))
5570b57cec5SDimitry Andric Res[i] = BitValue::ref(V2);
5580b57cec5SDimitry Andric else if (V2.is(1))
5590b57cec5SDimitry Andric Res[i] = BitValue::ref(V1);
5600b57cec5SDimitry Andric else if (V1.is(0) || V2.is(0))
5610b57cec5SDimitry Andric Res[i] = BitValue::Zero;
5620b57cec5SDimitry Andric else if (V1 == V2)
5630b57cec5SDimitry Andric Res[i] = V1;
5640b57cec5SDimitry Andric else
5650b57cec5SDimitry Andric Res[i] = BitValue::self();
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric return Res;
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric
eORL(const RegisterCell & A1,const RegisterCell & A2) const5700b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eORL(const RegisterCell &A1,
5710b57cec5SDimitry Andric const RegisterCell &A2) const {
5720b57cec5SDimitry Andric uint16_t W = A1.width();
5730b57cec5SDimitry Andric assert(W == A2.width());
5740b57cec5SDimitry Andric RegisterCell Res(W);
5750b57cec5SDimitry Andric for (uint16_t i = 0; i < W; ++i) {
5760b57cec5SDimitry Andric const BitValue &V1 = A1[i];
5770b57cec5SDimitry Andric const BitValue &V2 = A2[i];
5780b57cec5SDimitry Andric if (V1.is(1) || V2.is(1))
5790b57cec5SDimitry Andric Res[i] = BitValue::One;
5800b57cec5SDimitry Andric else if (V1.is(0))
5810b57cec5SDimitry Andric Res[i] = BitValue::ref(V2);
5820b57cec5SDimitry Andric else if (V2.is(0))
5830b57cec5SDimitry Andric Res[i] = BitValue::ref(V1);
5840b57cec5SDimitry Andric else if (V1 == V2)
5850b57cec5SDimitry Andric Res[i] = V1;
5860b57cec5SDimitry Andric else
5870b57cec5SDimitry Andric Res[i] = BitValue::self();
5880b57cec5SDimitry Andric }
5890b57cec5SDimitry Andric return Res;
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric
eXOR(const RegisterCell & A1,const RegisterCell & A2) const5920b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eXOR(const RegisterCell &A1,
5930b57cec5SDimitry Andric const RegisterCell &A2) const {
5940b57cec5SDimitry Andric uint16_t W = A1.width();
5950b57cec5SDimitry Andric assert(W == A2.width());
5960b57cec5SDimitry Andric RegisterCell Res(W);
5970b57cec5SDimitry Andric for (uint16_t i = 0; i < W; ++i) {
5980b57cec5SDimitry Andric const BitValue &V1 = A1[i];
5990b57cec5SDimitry Andric const BitValue &V2 = A2[i];
6000b57cec5SDimitry Andric if (V1.is(0))
6010b57cec5SDimitry Andric Res[i] = BitValue::ref(V2);
6020b57cec5SDimitry Andric else if (V2.is(0))
6030b57cec5SDimitry Andric Res[i] = BitValue::ref(V1);
6040b57cec5SDimitry Andric else if (V1 == V2)
6050b57cec5SDimitry Andric Res[i] = BitValue::Zero;
6060b57cec5SDimitry Andric else
6070b57cec5SDimitry Andric Res[i] = BitValue::self();
6080b57cec5SDimitry Andric }
6090b57cec5SDimitry Andric return Res;
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric
eNOT(const RegisterCell & A1) const6120b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eNOT(const RegisterCell &A1) const {
6130b57cec5SDimitry Andric uint16_t W = A1.width();
6140b57cec5SDimitry Andric RegisterCell Res(W);
6150b57cec5SDimitry Andric for (uint16_t i = 0; i < W; ++i) {
6160b57cec5SDimitry Andric const BitValue &V = A1[i];
6170b57cec5SDimitry Andric if (V.is(0))
6180b57cec5SDimitry Andric Res[i] = BitValue::One;
6190b57cec5SDimitry Andric else if (V.is(1))
6200b57cec5SDimitry Andric Res[i] = BitValue::Zero;
6210b57cec5SDimitry Andric else
6220b57cec5SDimitry Andric Res[i] = BitValue::self();
6230b57cec5SDimitry Andric }
6240b57cec5SDimitry Andric return Res;
6250b57cec5SDimitry Andric }
6260b57cec5SDimitry Andric
eSET(const RegisterCell & A1,uint16_t BitN) const6270b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eSET(const RegisterCell &A1,
6280b57cec5SDimitry Andric uint16_t BitN) const {
6290b57cec5SDimitry Andric assert(BitN < A1.width());
6300b57cec5SDimitry Andric RegisterCell Res = RegisterCell::ref(A1);
6310b57cec5SDimitry Andric Res[BitN] = BitValue::One;
6320b57cec5SDimitry Andric return Res;
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric
eCLR(const RegisterCell & A1,uint16_t BitN) const6350b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eCLR(const RegisterCell &A1,
6360b57cec5SDimitry Andric uint16_t BitN) const {
6370b57cec5SDimitry Andric assert(BitN < A1.width());
6380b57cec5SDimitry Andric RegisterCell Res = RegisterCell::ref(A1);
6390b57cec5SDimitry Andric Res[BitN] = BitValue::Zero;
6400b57cec5SDimitry Andric return Res;
6410b57cec5SDimitry Andric }
6420b57cec5SDimitry Andric
eCLB(const RegisterCell & A1,bool B,uint16_t W) const6430b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eCLB(const RegisterCell &A1, bool B,
6440b57cec5SDimitry Andric uint16_t W) const {
6450b57cec5SDimitry Andric uint16_t C = A1.cl(B), AW = A1.width();
6460b57cec5SDimitry Andric // If the last leading non-B bit is not a constant, then we don't know
6470b57cec5SDimitry Andric // the real count.
6480b57cec5SDimitry Andric if ((C < AW && A1[AW-1-C].num()) || C == AW)
6490b57cec5SDimitry Andric return eIMM(C, W);
6500b57cec5SDimitry Andric return RegisterCell::self(0, W);
6510b57cec5SDimitry Andric }
6520b57cec5SDimitry Andric
eCTB(const RegisterCell & A1,bool B,uint16_t W) const6530b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eCTB(const RegisterCell &A1, bool B,
6540b57cec5SDimitry Andric uint16_t W) const {
6550b57cec5SDimitry Andric uint16_t C = A1.ct(B), AW = A1.width();
6560b57cec5SDimitry Andric // If the last trailing non-B bit is not a constant, then we don't know
6570b57cec5SDimitry Andric // the real count.
6580b57cec5SDimitry Andric if ((C < AW && A1[C].num()) || C == AW)
6590b57cec5SDimitry Andric return eIMM(C, W);
6600b57cec5SDimitry Andric return RegisterCell::self(0, W);
6610b57cec5SDimitry Andric }
6620b57cec5SDimitry Andric
eSXT(const RegisterCell & A1,uint16_t FromN) const6630b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eSXT(const RegisterCell &A1,
6640b57cec5SDimitry Andric uint16_t FromN) const {
6650b57cec5SDimitry Andric uint16_t W = A1.width();
6660b57cec5SDimitry Andric assert(FromN <= W);
6670b57cec5SDimitry Andric RegisterCell Res = RegisterCell::ref(A1);
6680b57cec5SDimitry Andric BitValue Sign = Res[FromN-1];
6690b57cec5SDimitry Andric // Sign-extend "inreg".
6700b57cec5SDimitry Andric Res.fill(FromN, W, Sign);
6710b57cec5SDimitry Andric return Res;
6720b57cec5SDimitry Andric }
6730b57cec5SDimitry Andric
eZXT(const RegisterCell & A1,uint16_t FromN) const6740b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eZXT(const RegisterCell &A1,
6750b57cec5SDimitry Andric uint16_t FromN) const {
6760b57cec5SDimitry Andric uint16_t W = A1.width();
6770b57cec5SDimitry Andric assert(FromN <= W);
6780b57cec5SDimitry Andric RegisterCell Res = RegisterCell::ref(A1);
6790b57cec5SDimitry Andric Res.fill(FromN, W, BitValue::Zero);
6800b57cec5SDimitry Andric return Res;
6810b57cec5SDimitry Andric }
6820b57cec5SDimitry Andric
eXTR(const RegisterCell & A1,uint16_t B,uint16_t E) const6830b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eXTR(const RegisterCell &A1,
6840b57cec5SDimitry Andric uint16_t B, uint16_t E) const {
6850b57cec5SDimitry Andric uint16_t W = A1.width();
6860b57cec5SDimitry Andric assert(B < W && E <= W);
6870b57cec5SDimitry Andric if (B == E)
6880b57cec5SDimitry Andric return RegisterCell(0);
6890b57cec5SDimitry Andric uint16_t Last = (E > 0) ? E-1 : W-1;
6900b57cec5SDimitry Andric RegisterCell Res = RegisterCell::ref(A1).extract(BT::BitMask(B, Last));
6910b57cec5SDimitry Andric // Return shorter cell.
6920b57cec5SDimitry Andric return Res;
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric
eINS(const RegisterCell & A1,const RegisterCell & A2,uint16_t AtN) const6950b57cec5SDimitry Andric BT::RegisterCell BT::MachineEvaluator::eINS(const RegisterCell &A1,
6960b57cec5SDimitry Andric const RegisterCell &A2, uint16_t AtN) const {
6970b57cec5SDimitry Andric uint16_t W1 = A1.width(), W2 = A2.width();
6980b57cec5SDimitry Andric (void)W1;
6990b57cec5SDimitry Andric assert(AtN < W1 && AtN+W2 <= W1);
7000b57cec5SDimitry Andric // Copy bits from A1, insert A2 at position AtN.
7010b57cec5SDimitry Andric RegisterCell Res = RegisterCell::ref(A1);
7020b57cec5SDimitry Andric if (W2 > 0)
7030b57cec5SDimitry Andric Res.insert(RegisterCell::ref(A2), BT::BitMask(AtN, AtN+W2-1));
7040b57cec5SDimitry Andric return Res;
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric
mask(Register Reg,unsigned Sub) const707e8d8bef9SDimitry Andric BT::BitMask BT::MachineEvaluator::mask(Register Reg, unsigned Sub) const {
7080b57cec5SDimitry Andric assert(Sub == 0 && "Generic BitTracker::mask called for Sub != 0");
7090b57cec5SDimitry Andric uint16_t W = getRegBitWidth(Reg);
7100b57cec5SDimitry Andric assert(W > 0 && "Cannot generate mask for empty register");
7110b57cec5SDimitry Andric return BitMask(0, W-1);
7120b57cec5SDimitry Andric }
7130b57cec5SDimitry Andric
getPhysRegBitWidth(MCRegister Reg) const714e8d8bef9SDimitry Andric uint16_t BT::MachineEvaluator::getPhysRegBitWidth(MCRegister Reg) const {
7150b57cec5SDimitry Andric const TargetRegisterClass &PC = *TRI.getMinimalPhysRegClass(Reg);
7160b57cec5SDimitry Andric return TRI.getRegSizeInBits(PC);
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric
evaluate(const MachineInstr & MI,const CellMapType & Inputs,CellMapType & Outputs) const7190b57cec5SDimitry Andric bool BT::MachineEvaluator::evaluate(const MachineInstr &MI,
7200b57cec5SDimitry Andric const CellMapType &Inputs,
7210b57cec5SDimitry Andric CellMapType &Outputs) const {
7220b57cec5SDimitry Andric unsigned Opc = MI.getOpcode();
7230b57cec5SDimitry Andric switch (Opc) {
7240b57cec5SDimitry Andric case TargetOpcode::REG_SEQUENCE: {
7250b57cec5SDimitry Andric RegisterRef RD = MI.getOperand(0);
7260b57cec5SDimitry Andric assert(RD.Sub == 0);
7270b57cec5SDimitry Andric RegisterRef RS = MI.getOperand(1);
7280b57cec5SDimitry Andric unsigned SS = MI.getOperand(2).getImm();
7290b57cec5SDimitry Andric RegisterRef RT = MI.getOperand(3);
7300b57cec5SDimitry Andric unsigned ST = MI.getOperand(4).getImm();
7310b57cec5SDimitry Andric assert(SS != ST);
7320b57cec5SDimitry Andric
7330b57cec5SDimitry Andric uint16_t W = getRegBitWidth(RD);
7340b57cec5SDimitry Andric RegisterCell Res(W);
7350b57cec5SDimitry Andric Res.insert(RegisterCell::ref(getCell(RS, Inputs)), mask(RD.Reg, SS));
7360b57cec5SDimitry Andric Res.insert(RegisterCell::ref(getCell(RT, Inputs)), mask(RD.Reg, ST));
7370b57cec5SDimitry Andric putCell(RD, Res, Outputs);
7380b57cec5SDimitry Andric break;
7390b57cec5SDimitry Andric }
7400b57cec5SDimitry Andric
7410b57cec5SDimitry Andric case TargetOpcode::COPY: {
7420b57cec5SDimitry Andric // COPY can transfer a smaller register into a wider one.
7430b57cec5SDimitry Andric // If that is the case, fill the remaining high bits with 0.
7440b57cec5SDimitry Andric RegisterRef RD = MI.getOperand(0);
7450b57cec5SDimitry Andric RegisterRef RS = MI.getOperand(1);
7460b57cec5SDimitry Andric assert(RD.Sub == 0);
7470b57cec5SDimitry Andric uint16_t WD = getRegBitWidth(RD);
7480b57cec5SDimitry Andric uint16_t WS = getRegBitWidth(RS);
7490b57cec5SDimitry Andric assert(WD >= WS);
7500b57cec5SDimitry Andric RegisterCell Src = getCell(RS, Inputs);
7510b57cec5SDimitry Andric RegisterCell Res(WD);
7520b57cec5SDimitry Andric Res.insert(Src, BitMask(0, WS-1));
7530b57cec5SDimitry Andric Res.fill(WS, WD, BitValue::Zero);
7540b57cec5SDimitry Andric putCell(RD, Res, Outputs);
7550b57cec5SDimitry Andric break;
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric
7580b57cec5SDimitry Andric default:
7590b57cec5SDimitry Andric return false;
7600b57cec5SDimitry Andric }
7610b57cec5SDimitry Andric
7620b57cec5SDimitry Andric return true;
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric
operator ()(const MachineInstr * InstA,const MachineInstr * InstB) const7650b57cec5SDimitry Andric bool BT::UseQueueType::Cmp::operator()(const MachineInstr *InstA,
7660b57cec5SDimitry Andric const MachineInstr *InstB) const {
7670b57cec5SDimitry Andric // This is a comparison function for a priority queue: give higher priority
7680b57cec5SDimitry Andric // to earlier instructions.
7690b57cec5SDimitry Andric // This operator is used as "less", so returning "true" gives InstB higher
7700b57cec5SDimitry Andric // priority (because then InstA < InstB).
7710b57cec5SDimitry Andric if (InstA == InstB)
7720b57cec5SDimitry Andric return false;
7730b57cec5SDimitry Andric const MachineBasicBlock *BA = InstA->getParent();
7740b57cec5SDimitry Andric const MachineBasicBlock *BB = InstB->getParent();
7750b57cec5SDimitry Andric if (BA != BB) {
7760b57cec5SDimitry Andric // If the blocks are different, ideally the dominating block would
7770b57cec5SDimitry Andric // have a higher priority, but it may be too expensive to check.
7780b57cec5SDimitry Andric return BA->getNumber() > BB->getNumber();
7790b57cec5SDimitry Andric }
7800b57cec5SDimitry Andric
7810b57cec5SDimitry Andric auto getDist = [this] (const MachineInstr *MI) {
7820b57cec5SDimitry Andric auto F = Dist.find(MI);
7830b57cec5SDimitry Andric if (F != Dist.end())
7840b57cec5SDimitry Andric return F->second;
7850b57cec5SDimitry Andric MachineBasicBlock::const_iterator I = MI->getParent()->begin();
7860b57cec5SDimitry Andric MachineBasicBlock::const_iterator E = MI->getIterator();
7870b57cec5SDimitry Andric unsigned D = std::distance(I, E);
7880b57cec5SDimitry Andric Dist.insert(std::make_pair(MI, D));
7890b57cec5SDimitry Andric return D;
7900b57cec5SDimitry Andric };
7910b57cec5SDimitry Andric
7920b57cec5SDimitry Andric return getDist(InstA) > getDist(InstB);
7930b57cec5SDimitry Andric }
7940b57cec5SDimitry Andric
7950b57cec5SDimitry Andric // Main W-Z implementation.
7960b57cec5SDimitry Andric
visitPHI(const MachineInstr & PI)7970b57cec5SDimitry Andric void BT::visitPHI(const MachineInstr &PI) {
7980b57cec5SDimitry Andric int ThisN = PI.getParent()->getNumber();
7990b57cec5SDimitry Andric if (Trace)
8000b57cec5SDimitry Andric dbgs() << "Visit FI(" << printMBBReference(*PI.getParent()) << "): " << PI;
8010b57cec5SDimitry Andric
8020b57cec5SDimitry Andric const MachineOperand &MD = PI.getOperand(0);
8030b57cec5SDimitry Andric assert(MD.getSubReg() == 0 && "Unexpected sub-register in definition");
8040b57cec5SDimitry Andric RegisterRef DefRR(MD);
8050b57cec5SDimitry Andric uint16_t DefBW = ME.getRegBitWidth(DefRR);
8060b57cec5SDimitry Andric
8070b57cec5SDimitry Andric RegisterCell DefC = ME.getCell(DefRR, Map);
8080b57cec5SDimitry Andric if (DefC == RegisterCell::self(DefRR.Reg, DefBW)) // XXX slow
8090b57cec5SDimitry Andric return;
8100b57cec5SDimitry Andric
8110b57cec5SDimitry Andric bool Changed = false;
8120b57cec5SDimitry Andric
8130b57cec5SDimitry Andric for (unsigned i = 1, n = PI.getNumOperands(); i < n; i += 2) {
8140b57cec5SDimitry Andric const MachineBasicBlock *PB = PI.getOperand(i + 1).getMBB();
8150b57cec5SDimitry Andric int PredN = PB->getNumber();
8160b57cec5SDimitry Andric if (Trace)
8170b57cec5SDimitry Andric dbgs() << " edge " << printMBBReference(*PB) << "->"
8180b57cec5SDimitry Andric << printMBBReference(*PI.getParent());
8190b57cec5SDimitry Andric if (!EdgeExec.count(CFGEdge(PredN, ThisN))) {
8200b57cec5SDimitry Andric if (Trace)
8210b57cec5SDimitry Andric dbgs() << " not executable\n";
8220b57cec5SDimitry Andric continue;
8230b57cec5SDimitry Andric }
8240b57cec5SDimitry Andric
8250b57cec5SDimitry Andric RegisterRef RU = PI.getOperand(i);
8260b57cec5SDimitry Andric RegisterCell ResC = ME.getCell(RU, Map);
8270b57cec5SDimitry Andric if (Trace)
8280b57cec5SDimitry Andric dbgs() << " input reg: " << printReg(RU.Reg, &ME.TRI, RU.Sub)
8290b57cec5SDimitry Andric << " cell: " << ResC << "\n";
8300b57cec5SDimitry Andric Changed |= DefC.meet(ResC, DefRR.Reg);
8310b57cec5SDimitry Andric }
8320b57cec5SDimitry Andric
8330b57cec5SDimitry Andric if (Changed) {
8340b57cec5SDimitry Andric if (Trace)
8350b57cec5SDimitry Andric dbgs() << "Output: " << printReg(DefRR.Reg, &ME.TRI, DefRR.Sub)
8360b57cec5SDimitry Andric << " cell: " << DefC << "\n";
8370b57cec5SDimitry Andric ME.putCell(DefRR, DefC, Map);
8380b57cec5SDimitry Andric visitUsesOf(DefRR.Reg);
8390b57cec5SDimitry Andric }
8400b57cec5SDimitry Andric }
8410b57cec5SDimitry Andric
visitNonBranch(const MachineInstr & MI)8420b57cec5SDimitry Andric void BT::visitNonBranch(const MachineInstr &MI) {
8430b57cec5SDimitry Andric if (Trace)
8440b57cec5SDimitry Andric dbgs() << "Visit MI(" << printMBBReference(*MI.getParent()) << "): " << MI;
8450b57cec5SDimitry Andric if (MI.isDebugInstr())
8460b57cec5SDimitry Andric return;
8470b57cec5SDimitry Andric assert(!MI.isBranch() && "Unexpected branch instruction");
8480b57cec5SDimitry Andric
8490b57cec5SDimitry Andric CellMapType ResMap;
8500b57cec5SDimitry Andric bool Eval = ME.evaluate(MI, Map, ResMap);
8510b57cec5SDimitry Andric
8520b57cec5SDimitry Andric if (Trace && Eval) {
8534824e7fdSDimitry Andric for (const MachineOperand &MO : MI.operands()) {
8540b57cec5SDimitry Andric if (!MO.isReg() || !MO.isUse())
8550b57cec5SDimitry Andric continue;
8560b57cec5SDimitry Andric RegisterRef RU(MO);
8570b57cec5SDimitry Andric dbgs() << " input reg: " << printReg(RU.Reg, &ME.TRI, RU.Sub)
8580b57cec5SDimitry Andric << " cell: " << ME.getCell(RU, Map) << "\n";
8590b57cec5SDimitry Andric }
8600b57cec5SDimitry Andric dbgs() << "Outputs:\n";
861480093f4SDimitry Andric for (const std::pair<const unsigned, RegisterCell> &P : ResMap) {
8620b57cec5SDimitry Andric RegisterRef RD(P.first);
8630b57cec5SDimitry Andric dbgs() << " " << printReg(P.first, &ME.TRI) << " cell: "
8640b57cec5SDimitry Andric << ME.getCell(RD, ResMap) << "\n";
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric
8680b57cec5SDimitry Andric // Iterate over all definitions of the instruction, and update the
8690b57cec5SDimitry Andric // cells accordingly.
8700b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) {
8710b57cec5SDimitry Andric // Visit register defs only.
8720b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef())
8730b57cec5SDimitry Andric continue;
8740b57cec5SDimitry Andric RegisterRef RD(MO);
8750b57cec5SDimitry Andric assert(RD.Sub == 0 && "Unexpected sub-register in definition");
876e8d8bef9SDimitry Andric if (!RD.Reg.isVirtual())
8770b57cec5SDimitry Andric continue;
8780b57cec5SDimitry Andric
8790b57cec5SDimitry Andric bool Changed = false;
8800b57cec5SDimitry Andric if (!Eval || ResMap.count(RD.Reg) == 0) {
8810b57cec5SDimitry Andric // Set to "ref" (aka "bottom").
8820b57cec5SDimitry Andric uint16_t DefBW = ME.getRegBitWidth(RD);
8830b57cec5SDimitry Andric RegisterCell RefC = RegisterCell::self(RD.Reg, DefBW);
8840b57cec5SDimitry Andric if (RefC != ME.getCell(RD, Map)) {
8850b57cec5SDimitry Andric ME.putCell(RD, RefC, Map);
8860b57cec5SDimitry Andric Changed = true;
8870b57cec5SDimitry Andric }
8880b57cec5SDimitry Andric } else {
8890b57cec5SDimitry Andric RegisterCell DefC = ME.getCell(RD, Map);
8900b57cec5SDimitry Andric RegisterCell ResC = ME.getCell(RD, ResMap);
8910b57cec5SDimitry Andric // This is a non-phi instruction, so the values of the inputs come
8920b57cec5SDimitry Andric // from the same registers each time this instruction is evaluated.
8930b57cec5SDimitry Andric // During the propagation, the values of the inputs can become lowered
8940b57cec5SDimitry Andric // in the sense of the lattice operation, which may cause different
8950b57cec5SDimitry Andric // results to be calculated in subsequent evaluations. This should
8960b57cec5SDimitry Andric // not cause the bottoming of the result in the map, since the new
8970b57cec5SDimitry Andric // result is already reflecting the lowered inputs.
8980b57cec5SDimitry Andric for (uint16_t i = 0, w = DefC.width(); i < w; ++i) {
8990b57cec5SDimitry Andric BitValue &V = DefC[i];
9000b57cec5SDimitry Andric // Bits that are already "bottom" should not be updated.
9010b57cec5SDimitry Andric if (V.Type == BitValue::Ref && V.RefI.Reg == RD.Reg)
9020b57cec5SDimitry Andric continue;
9030b57cec5SDimitry Andric // Same for those that are identical in DefC and ResC.
9040b57cec5SDimitry Andric if (V == ResC[i])
9050b57cec5SDimitry Andric continue;
9060b57cec5SDimitry Andric V = ResC[i];
9070b57cec5SDimitry Andric Changed = true;
9080b57cec5SDimitry Andric }
9090b57cec5SDimitry Andric if (Changed)
9100b57cec5SDimitry Andric ME.putCell(RD, DefC, Map);
9110b57cec5SDimitry Andric }
9120b57cec5SDimitry Andric if (Changed)
9130b57cec5SDimitry Andric visitUsesOf(RD.Reg);
9140b57cec5SDimitry Andric }
9150b57cec5SDimitry Andric }
9160b57cec5SDimitry Andric
visitBranchesFrom(const MachineInstr & BI)9170b57cec5SDimitry Andric void BT::visitBranchesFrom(const MachineInstr &BI) {
9180b57cec5SDimitry Andric const MachineBasicBlock &B = *BI.getParent();
9190b57cec5SDimitry Andric MachineBasicBlock::const_iterator It = BI, End = B.end();
9200b57cec5SDimitry Andric BranchTargetList Targets, BTs;
9210b57cec5SDimitry Andric bool FallsThrough = true, DefaultToAll = false;
9220b57cec5SDimitry Andric int ThisN = B.getNumber();
9230b57cec5SDimitry Andric
9240b57cec5SDimitry Andric do {
9250b57cec5SDimitry Andric BTs.clear();
9260b57cec5SDimitry Andric const MachineInstr &MI = *It;
9270b57cec5SDimitry Andric if (Trace)
9280b57cec5SDimitry Andric dbgs() << "Visit BR(" << printMBBReference(B) << "): " << MI;
9290b57cec5SDimitry Andric assert(MI.isBranch() && "Expecting branch instruction");
9300b57cec5SDimitry Andric InstrExec.insert(&MI);
9310b57cec5SDimitry Andric bool Eval = ME.evaluate(MI, Map, BTs, FallsThrough);
9320b57cec5SDimitry Andric if (!Eval) {
9330b57cec5SDimitry Andric // If the evaluation failed, we will add all targets. Keep going in
9340b57cec5SDimitry Andric // the loop to mark all executable branches as such.
9350b57cec5SDimitry Andric DefaultToAll = true;
9360b57cec5SDimitry Andric FallsThrough = true;
9370b57cec5SDimitry Andric if (Trace)
9380b57cec5SDimitry Andric dbgs() << " failed to evaluate: will add all CFG successors\n";
9390b57cec5SDimitry Andric } else if (!DefaultToAll) {
9400b57cec5SDimitry Andric // If evaluated successfully add the targets to the cumulative list.
9410b57cec5SDimitry Andric if (Trace) {
9420b57cec5SDimitry Andric dbgs() << " adding targets:";
94304eeddc0SDimitry Andric for (const MachineBasicBlock *BT : BTs)
94404eeddc0SDimitry Andric dbgs() << " " << printMBBReference(*BT);
9450b57cec5SDimitry Andric if (FallsThrough)
9460b57cec5SDimitry Andric dbgs() << "\n falls through\n";
9470b57cec5SDimitry Andric else
9480b57cec5SDimitry Andric dbgs() << "\n does not fall through\n";
9490b57cec5SDimitry Andric }
9500b57cec5SDimitry Andric Targets.insert(BTs.begin(), BTs.end());
9510b57cec5SDimitry Andric }
9520b57cec5SDimitry Andric ++It;
9530b57cec5SDimitry Andric } while (FallsThrough && It != End);
9540b57cec5SDimitry Andric
9555ffd83dbSDimitry Andric if (B.mayHaveInlineAsmBr())
9565ffd83dbSDimitry Andric DefaultToAll = true;
9575ffd83dbSDimitry Andric
9580b57cec5SDimitry Andric if (!DefaultToAll) {
9590b57cec5SDimitry Andric // Need to add all CFG successors that lead to EH landing pads.
9600b57cec5SDimitry Andric // There won't be explicit branches to these blocks, but they must
9610b57cec5SDimitry Andric // be processed.
9620b57cec5SDimitry Andric for (const MachineBasicBlock *SB : B.successors()) {
9630b57cec5SDimitry Andric if (SB->isEHPad())
9640b57cec5SDimitry Andric Targets.insert(SB);
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric if (FallsThrough) {
9670b57cec5SDimitry Andric MachineFunction::const_iterator BIt = B.getIterator();
9680b57cec5SDimitry Andric MachineFunction::const_iterator Next = std::next(BIt);
9690b57cec5SDimitry Andric if (Next != MF.end())
9700b57cec5SDimitry Andric Targets.insert(&*Next);
9710b57cec5SDimitry Andric }
9720b57cec5SDimitry Andric } else {
9730b57cec5SDimitry Andric for (const MachineBasicBlock *SB : B.successors())
9740b57cec5SDimitry Andric Targets.insert(SB);
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric
9770b57cec5SDimitry Andric for (const MachineBasicBlock *TB : Targets)
9780b57cec5SDimitry Andric FlowQ.push(CFGEdge(ThisN, TB->getNumber()));
9790b57cec5SDimitry Andric }
9800b57cec5SDimitry Andric
visitUsesOf(Register Reg)981e8d8bef9SDimitry Andric void BT::visitUsesOf(Register Reg) {
9820b57cec5SDimitry Andric if (Trace)
9830b57cec5SDimitry Andric dbgs() << "queuing uses of modified reg " << printReg(Reg, &ME.TRI)
9840b57cec5SDimitry Andric << " cell: " << ME.getCell(Reg, Map) << '\n';
9850b57cec5SDimitry Andric
9860b57cec5SDimitry Andric for (MachineInstr &UseI : MRI.use_nodbg_instructions(Reg))
9870b57cec5SDimitry Andric UseQ.push(&UseI);
9880b57cec5SDimitry Andric }
9890b57cec5SDimitry Andric
get(RegisterRef RR) const9900b57cec5SDimitry Andric BT::RegisterCell BT::get(RegisterRef RR) const {
9910b57cec5SDimitry Andric return ME.getCell(RR, Map);
9920b57cec5SDimitry Andric }
9930b57cec5SDimitry Andric
put(RegisterRef RR,const RegisterCell & RC)9940b57cec5SDimitry Andric void BT::put(RegisterRef RR, const RegisterCell &RC) {
9950b57cec5SDimitry Andric ME.putCell(RR, RC, Map);
9960b57cec5SDimitry Andric }
9970b57cec5SDimitry Andric
9980b57cec5SDimitry Andric // Replace all references to bits from OldRR with the corresponding bits
9990b57cec5SDimitry Andric // in NewRR.
subst(RegisterRef OldRR,RegisterRef NewRR)10000b57cec5SDimitry Andric void BT::subst(RegisterRef OldRR, RegisterRef NewRR) {
10010b57cec5SDimitry Andric assert(Map.count(OldRR.Reg) > 0 && "OldRR not present in map");
10020b57cec5SDimitry Andric BitMask OM = ME.mask(OldRR.Reg, OldRR.Sub);
10030b57cec5SDimitry Andric BitMask NM = ME.mask(NewRR.Reg, NewRR.Sub);
10040b57cec5SDimitry Andric uint16_t OMB = OM.first(), OME = OM.last();
10050b57cec5SDimitry Andric uint16_t NMB = NM.first(), NME = NM.last();
10060b57cec5SDimitry Andric (void)NME;
10070b57cec5SDimitry Andric assert((OME-OMB == NME-NMB) &&
10080b57cec5SDimitry Andric "Substituting registers of different lengths");
10090b57cec5SDimitry Andric for (std::pair<const unsigned, RegisterCell> &P : Map) {
10100b57cec5SDimitry Andric RegisterCell &RC = P.second;
10110b57cec5SDimitry Andric for (uint16_t i = 0, w = RC.width(); i < w; ++i) {
10120b57cec5SDimitry Andric BitValue &V = RC[i];
10130b57cec5SDimitry Andric if (V.Type != BitValue::Ref || V.RefI.Reg != OldRR.Reg)
10140b57cec5SDimitry Andric continue;
10150b57cec5SDimitry Andric if (V.RefI.Pos < OMB || V.RefI.Pos > OME)
10160b57cec5SDimitry Andric continue;
10170b57cec5SDimitry Andric V.RefI.Reg = NewRR.Reg;
10180b57cec5SDimitry Andric V.RefI.Pos += NMB-OMB;
10190b57cec5SDimitry Andric }
10200b57cec5SDimitry Andric }
10210b57cec5SDimitry Andric }
10220b57cec5SDimitry Andric
10230b57cec5SDimitry Andric // Check if the block has been "executed" during propagation. (If not, the
10240b57cec5SDimitry Andric // block is dead, but it may still appear to be reachable.)
reached(const MachineBasicBlock * B) const10250b57cec5SDimitry Andric bool BT::reached(const MachineBasicBlock *B) const {
10260b57cec5SDimitry Andric int BN = B->getNumber();
10270b57cec5SDimitry Andric assert(BN >= 0);
10280b57cec5SDimitry Andric return ReachedBB.count(BN);
10290b57cec5SDimitry Andric }
10300b57cec5SDimitry Andric
10310b57cec5SDimitry Andric // Visit an individual instruction. This could be a newly added instruction,
10320b57cec5SDimitry Andric // or one that has been modified by an optimization.
visit(const MachineInstr & MI)10330b57cec5SDimitry Andric void BT::visit(const MachineInstr &MI) {
10340b57cec5SDimitry Andric assert(!MI.isBranch() && "Only non-branches are allowed");
10350b57cec5SDimitry Andric InstrExec.insert(&MI);
10360b57cec5SDimitry Andric visitNonBranch(MI);
10370b57cec5SDimitry Andric // Make sure to flush all the pending use updates.
10380b57cec5SDimitry Andric runUseQueue();
10390b57cec5SDimitry Andric // The call to visitNonBranch could propagate the changes until a branch
10400b57cec5SDimitry Andric // is actually visited. This could result in adding CFG edges to the flow
10410b57cec5SDimitry Andric // queue. Since the queue won't be processed, clear it.
10420b57cec5SDimitry Andric while (!FlowQ.empty())
10430b57cec5SDimitry Andric FlowQ.pop();
10440b57cec5SDimitry Andric }
10450b57cec5SDimitry Andric
reset()10460b57cec5SDimitry Andric void BT::reset() {
10470b57cec5SDimitry Andric EdgeExec.clear();
10480b57cec5SDimitry Andric InstrExec.clear();
10490b57cec5SDimitry Andric Map.clear();
10500b57cec5SDimitry Andric ReachedBB.clear();
10510b57cec5SDimitry Andric ReachedBB.reserve(MF.size());
10520b57cec5SDimitry Andric }
10530b57cec5SDimitry Andric
runEdgeQueue(BitVector & BlockScanned)10540b57cec5SDimitry Andric void BT::runEdgeQueue(BitVector &BlockScanned) {
10550b57cec5SDimitry Andric while (!FlowQ.empty()) {
10560b57cec5SDimitry Andric CFGEdge Edge = FlowQ.front();
10570b57cec5SDimitry Andric FlowQ.pop();
10580b57cec5SDimitry Andric
1059*81ad6265SDimitry Andric if (!EdgeExec.insert(Edge).second)
10600b57cec5SDimitry Andric return;
10610b57cec5SDimitry Andric ReachedBB.insert(Edge.second);
10620b57cec5SDimitry Andric
10630b57cec5SDimitry Andric const MachineBasicBlock &B = *MF.getBlockNumbered(Edge.second);
10640b57cec5SDimitry Andric MachineBasicBlock::const_iterator It = B.begin(), End = B.end();
10650b57cec5SDimitry Andric // Visit PHI nodes first.
10660b57cec5SDimitry Andric while (It != End && It->isPHI()) {
10670b57cec5SDimitry Andric const MachineInstr &PI = *It++;
10680b57cec5SDimitry Andric InstrExec.insert(&PI);
10690b57cec5SDimitry Andric visitPHI(PI);
10700b57cec5SDimitry Andric }
10710b57cec5SDimitry Andric
10720b57cec5SDimitry Andric // If this block has already been visited through a flow graph edge,
10730b57cec5SDimitry Andric // then the instructions have already been processed. Any updates to
10740b57cec5SDimitry Andric // the cells would now only happen through visitUsesOf...
10750b57cec5SDimitry Andric if (BlockScanned[Edge.second])
10760b57cec5SDimitry Andric return;
10770b57cec5SDimitry Andric BlockScanned[Edge.second] = true;
10780b57cec5SDimitry Andric
10790b57cec5SDimitry Andric // Visit non-branch instructions.
10800b57cec5SDimitry Andric while (It != End && !It->isBranch()) {
10810b57cec5SDimitry Andric const MachineInstr &MI = *It++;
10820b57cec5SDimitry Andric InstrExec.insert(&MI);
10830b57cec5SDimitry Andric visitNonBranch(MI);
10840b57cec5SDimitry Andric }
10850b57cec5SDimitry Andric // If block end has been reached, add the fall-through edge to the queue.
10860b57cec5SDimitry Andric if (It == End) {
10870b57cec5SDimitry Andric MachineFunction::const_iterator BIt = B.getIterator();
10880b57cec5SDimitry Andric MachineFunction::const_iterator Next = std::next(BIt);
10890b57cec5SDimitry Andric if (Next != MF.end() && B.isSuccessor(&*Next)) {
10900b57cec5SDimitry Andric int ThisN = B.getNumber();
10910b57cec5SDimitry Andric int NextN = Next->getNumber();
10920b57cec5SDimitry Andric FlowQ.push(CFGEdge(ThisN, NextN));
10930b57cec5SDimitry Andric }
10940b57cec5SDimitry Andric } else {
10950b57cec5SDimitry Andric // Handle the remaining sequence of branches. This function will update
10960b57cec5SDimitry Andric // the work queue.
10970b57cec5SDimitry Andric visitBranchesFrom(*It);
10980b57cec5SDimitry Andric }
10990b57cec5SDimitry Andric } // while (!FlowQ->empty())
11000b57cec5SDimitry Andric }
11010b57cec5SDimitry Andric
runUseQueue()11020b57cec5SDimitry Andric void BT::runUseQueue() {
11030b57cec5SDimitry Andric while (!UseQ.empty()) {
11040b57cec5SDimitry Andric MachineInstr &UseI = *UseQ.front();
11050b57cec5SDimitry Andric UseQ.pop();
11060b57cec5SDimitry Andric
11070b57cec5SDimitry Andric if (!InstrExec.count(&UseI))
11080b57cec5SDimitry Andric continue;
11090b57cec5SDimitry Andric if (UseI.isPHI())
11100b57cec5SDimitry Andric visitPHI(UseI);
11110b57cec5SDimitry Andric else if (!UseI.isBranch())
11120b57cec5SDimitry Andric visitNonBranch(UseI);
11130b57cec5SDimitry Andric else
11140b57cec5SDimitry Andric visitBranchesFrom(UseI);
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric }
11170b57cec5SDimitry Andric
run()11180b57cec5SDimitry Andric void BT::run() {
11190b57cec5SDimitry Andric reset();
11200b57cec5SDimitry Andric assert(FlowQ.empty());
11210b57cec5SDimitry Andric
11220b57cec5SDimitry Andric using MachineFlowGraphTraits = GraphTraits<const MachineFunction*>;
11230b57cec5SDimitry Andric const MachineBasicBlock *Entry = MachineFlowGraphTraits::getEntryNode(&MF);
11240b57cec5SDimitry Andric
11250b57cec5SDimitry Andric unsigned MaxBN = 0;
11260b57cec5SDimitry Andric for (const MachineBasicBlock &B : MF) {
11270b57cec5SDimitry Andric assert(B.getNumber() >= 0 && "Disconnected block");
11280b57cec5SDimitry Andric unsigned BN = B.getNumber();
11290b57cec5SDimitry Andric if (BN > MaxBN)
11300b57cec5SDimitry Andric MaxBN = BN;
11310b57cec5SDimitry Andric }
11320b57cec5SDimitry Andric
11330b57cec5SDimitry Andric // Keep track of visited blocks.
11340b57cec5SDimitry Andric BitVector BlockScanned(MaxBN+1);
11350b57cec5SDimitry Andric
11360b57cec5SDimitry Andric int EntryN = Entry->getNumber();
11370b57cec5SDimitry Andric // Generate a fake edge to get something to start with.
11380b57cec5SDimitry Andric FlowQ.push(CFGEdge(-1, EntryN));
11390b57cec5SDimitry Andric
11400b57cec5SDimitry Andric while (!FlowQ.empty() || !UseQ.empty()) {
11410b57cec5SDimitry Andric runEdgeQueue(BlockScanned);
11420b57cec5SDimitry Andric runUseQueue();
11430b57cec5SDimitry Andric }
11440b57cec5SDimitry Andric UseQ.reset();
11450b57cec5SDimitry Andric
11460b57cec5SDimitry Andric if (Trace)
11470b57cec5SDimitry Andric print_cells(dbgs() << "Cells after propagation:\n");
11480b57cec5SDimitry Andric }
1149