xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonBitSimplify.cpp (revision 8bcb0991864975618c09697b1aca10683346d9f0)
10b57cec5SDimitry Andric //===- HexagonBitSimplify.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 #include "BitTracker.h"
100b57cec5SDimitry Andric #include "HexagonBitTracker.h"
110b57cec5SDimitry Andric #include "HexagonInstrInfo.h"
120b57cec5SDimitry Andric #include "HexagonRegisterInfo.h"
130b57cec5SDimitry Andric #include "HexagonSubtarget.h"
140b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
150b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
160b57cec5SDimitry Andric #include "llvm/ADT/GraphTraits.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
290b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
310b57cec5SDimitry Andric #include "llvm/Pass.h"
320b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
330b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
340b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
350b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
360b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
370b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
380b57cec5SDimitry Andric #include <algorithm>
390b57cec5SDimitry Andric #include <cassert>
400b57cec5SDimitry Andric #include <cstdint>
410b57cec5SDimitry Andric #include <iterator>
420b57cec5SDimitry Andric #include <limits>
430b57cec5SDimitry Andric #include <utility>
440b57cec5SDimitry Andric #include <vector>
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric #define DEBUG_TYPE "hexbit"
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric using namespace llvm;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric static cl::opt<bool> PreserveTiedOps("hexbit-keep-tied", cl::Hidden,
510b57cec5SDimitry Andric   cl::init(true), cl::desc("Preserve subregisters in tied operands"));
520b57cec5SDimitry Andric static cl::opt<bool> GenExtract("hexbit-extract", cl::Hidden,
530b57cec5SDimitry Andric   cl::init(true), cl::desc("Generate extract instructions"));
540b57cec5SDimitry Andric static cl::opt<bool> GenBitSplit("hexbit-bitsplit", cl::Hidden,
550b57cec5SDimitry Andric   cl::init(true), cl::desc("Generate bitsplit instructions"));
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric static cl::opt<unsigned> MaxExtract("hexbit-max-extract", cl::Hidden,
580b57cec5SDimitry Andric   cl::init(std::numeric_limits<unsigned>::max()));
590b57cec5SDimitry Andric static unsigned CountExtract = 0;
600b57cec5SDimitry Andric static cl::opt<unsigned> MaxBitSplit("hexbit-max-bitsplit", cl::Hidden,
610b57cec5SDimitry Andric   cl::init(std::numeric_limits<unsigned>::max()));
620b57cec5SDimitry Andric static unsigned CountBitSplit = 0;
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric namespace llvm {
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   void initializeHexagonBitSimplifyPass(PassRegistry& Registry);
670b57cec5SDimitry Andric   FunctionPass *createHexagonBitSimplify();
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric } // end namespace llvm
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric namespace {
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   // Set of virtual registers, based on BitVector.
740b57cec5SDimitry Andric   struct RegisterSet : private BitVector {
750b57cec5SDimitry Andric     RegisterSet() = default;
760b57cec5SDimitry Andric     explicit RegisterSet(unsigned s, bool t = false) : BitVector(s, t) {}
770b57cec5SDimitry Andric     RegisterSet(const RegisterSet &RS) = default;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric     using BitVector::clear;
800b57cec5SDimitry Andric     using BitVector::count;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric     unsigned find_first() const {
830b57cec5SDimitry Andric       int First = BitVector::find_first();
840b57cec5SDimitry Andric       if (First < 0)
850b57cec5SDimitry Andric         return 0;
860b57cec5SDimitry Andric       return x2v(First);
870b57cec5SDimitry Andric     }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric     unsigned find_next(unsigned Prev) const {
900b57cec5SDimitry Andric       int Next = BitVector::find_next(v2x(Prev));
910b57cec5SDimitry Andric       if (Next < 0)
920b57cec5SDimitry Andric         return 0;
930b57cec5SDimitry Andric       return x2v(Next);
940b57cec5SDimitry Andric     }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric     RegisterSet &insert(unsigned R) {
970b57cec5SDimitry Andric       unsigned Idx = v2x(R);
980b57cec5SDimitry Andric       ensure(Idx);
990b57cec5SDimitry Andric       return static_cast<RegisterSet&>(BitVector::set(Idx));
1000b57cec5SDimitry Andric     }
1010b57cec5SDimitry Andric     RegisterSet &remove(unsigned R) {
1020b57cec5SDimitry Andric       unsigned Idx = v2x(R);
1030b57cec5SDimitry Andric       if (Idx >= size())
1040b57cec5SDimitry Andric         return *this;
1050b57cec5SDimitry Andric       return static_cast<RegisterSet&>(BitVector::reset(Idx));
1060b57cec5SDimitry Andric     }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric     RegisterSet &insert(const RegisterSet &Rs) {
1090b57cec5SDimitry Andric       return static_cast<RegisterSet&>(BitVector::operator|=(Rs));
1100b57cec5SDimitry Andric     }
1110b57cec5SDimitry Andric     RegisterSet &remove(const RegisterSet &Rs) {
1120b57cec5SDimitry Andric       return static_cast<RegisterSet&>(BitVector::reset(Rs));
1130b57cec5SDimitry Andric     }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     reference operator[](unsigned R) {
1160b57cec5SDimitry Andric       unsigned Idx = v2x(R);
1170b57cec5SDimitry Andric       ensure(Idx);
1180b57cec5SDimitry Andric       return BitVector::operator[](Idx);
1190b57cec5SDimitry Andric     }
1200b57cec5SDimitry Andric     bool operator[](unsigned R) const {
1210b57cec5SDimitry Andric       unsigned Idx = v2x(R);
1220b57cec5SDimitry Andric       assert(Idx < size());
1230b57cec5SDimitry Andric       return BitVector::operator[](Idx);
1240b57cec5SDimitry Andric     }
1250b57cec5SDimitry Andric     bool has(unsigned R) const {
1260b57cec5SDimitry Andric       unsigned Idx = v2x(R);
1270b57cec5SDimitry Andric       if (Idx >= size())
1280b57cec5SDimitry Andric         return false;
1290b57cec5SDimitry Andric       return BitVector::test(Idx);
1300b57cec5SDimitry Andric     }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric     bool empty() const {
1330b57cec5SDimitry Andric       return !BitVector::any();
1340b57cec5SDimitry Andric     }
1350b57cec5SDimitry Andric     bool includes(const RegisterSet &Rs) const {
1360b57cec5SDimitry Andric       // A.BitVector::test(B)  <=>  A-B != {}
1370b57cec5SDimitry Andric       return !Rs.BitVector::test(*this);
1380b57cec5SDimitry Andric     }
1390b57cec5SDimitry Andric     bool intersects(const RegisterSet &Rs) const {
1400b57cec5SDimitry Andric       return BitVector::anyCommon(Rs);
1410b57cec5SDimitry Andric     }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   private:
1440b57cec5SDimitry Andric     void ensure(unsigned Idx) {
1450b57cec5SDimitry Andric       if (size() <= Idx)
1460b57cec5SDimitry Andric         resize(std::max(Idx+1, 32U));
1470b57cec5SDimitry Andric     }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric     static inline unsigned v2x(unsigned v) {
150*8bcb0991SDimitry Andric       return Register::virtReg2Index(v);
1510b57cec5SDimitry Andric     }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric     static inline unsigned x2v(unsigned x) {
154*8bcb0991SDimitry Andric       return Register::index2VirtReg(x);
1550b57cec5SDimitry Andric     }
1560b57cec5SDimitry Andric   };
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   struct PrintRegSet {
1590b57cec5SDimitry Andric     PrintRegSet(const RegisterSet &S, const TargetRegisterInfo *RI)
1600b57cec5SDimitry Andric       : RS(S), TRI(RI) {}
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS,
1630b57cec5SDimitry Andric           const PrintRegSet &P);
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   private:
1660b57cec5SDimitry Andric     const RegisterSet &RS;
1670b57cec5SDimitry Andric     const TargetRegisterInfo *TRI;
1680b57cec5SDimitry Andric   };
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintRegSet &P)
1710b57cec5SDimitry Andric     LLVM_ATTRIBUTE_UNUSED;
1720b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintRegSet &P) {
1730b57cec5SDimitry Andric     OS << '{';
1740b57cec5SDimitry Andric     for (unsigned R = P.RS.find_first(); R; R = P.RS.find_next(R))
1750b57cec5SDimitry Andric       OS << ' ' << printReg(R, P.TRI);
1760b57cec5SDimitry Andric     OS << " }";
1770b57cec5SDimitry Andric     return OS;
1780b57cec5SDimitry Andric   }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   class Transformation;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   class HexagonBitSimplify : public MachineFunctionPass {
1830b57cec5SDimitry Andric   public:
1840b57cec5SDimitry Andric     static char ID;
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric     HexagonBitSimplify() : MachineFunctionPass(ID) {}
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric     StringRef getPassName() const override {
1890b57cec5SDimitry Andric       return "Hexagon bit simplification";
1900b57cec5SDimitry Andric     }
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
1930b57cec5SDimitry Andric       AU.addRequired<MachineDominatorTree>();
1940b57cec5SDimitry Andric       AU.addPreserved<MachineDominatorTree>();
1950b57cec5SDimitry Andric       MachineFunctionPass::getAnalysisUsage(AU);
1960b57cec5SDimitry Andric     }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric     static void getInstrDefs(const MachineInstr &MI, RegisterSet &Defs);
2010b57cec5SDimitry Andric     static void getInstrUses(const MachineInstr &MI, RegisterSet &Uses);
2020b57cec5SDimitry Andric     static bool isEqual(const BitTracker::RegisterCell &RC1, uint16_t B1,
2030b57cec5SDimitry Andric         const BitTracker::RegisterCell &RC2, uint16_t B2, uint16_t W);
2040b57cec5SDimitry Andric     static bool isZero(const BitTracker::RegisterCell &RC, uint16_t B,
2050b57cec5SDimitry Andric         uint16_t W);
2060b57cec5SDimitry Andric     static bool getConst(const BitTracker::RegisterCell &RC, uint16_t B,
2070b57cec5SDimitry Andric         uint16_t W, uint64_t &U);
2080b57cec5SDimitry Andric     static bool replaceReg(unsigned OldR, unsigned NewR,
2090b57cec5SDimitry Andric         MachineRegisterInfo &MRI);
2100b57cec5SDimitry Andric     static bool getSubregMask(const BitTracker::RegisterRef &RR,
2110b57cec5SDimitry Andric         unsigned &Begin, unsigned &Width, MachineRegisterInfo &MRI);
2120b57cec5SDimitry Andric     static bool replaceRegWithSub(unsigned OldR, unsigned NewR,
2130b57cec5SDimitry Andric         unsigned NewSR, MachineRegisterInfo &MRI);
2140b57cec5SDimitry Andric     static bool replaceSubWithSub(unsigned OldR, unsigned OldSR,
2150b57cec5SDimitry Andric         unsigned NewR, unsigned NewSR, MachineRegisterInfo &MRI);
2160b57cec5SDimitry Andric     static bool parseRegSequence(const MachineInstr &I,
2170b57cec5SDimitry Andric         BitTracker::RegisterRef &SL, BitTracker::RegisterRef &SH,
2180b57cec5SDimitry Andric         const MachineRegisterInfo &MRI);
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric     static bool getUsedBitsInStore(unsigned Opc, BitVector &Bits,
2210b57cec5SDimitry Andric         uint16_t Begin);
2220b57cec5SDimitry Andric     static bool getUsedBits(unsigned Opc, unsigned OpN, BitVector &Bits,
2230b57cec5SDimitry Andric         uint16_t Begin, const HexagonInstrInfo &HII);
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric     static const TargetRegisterClass *getFinalVRegClass(
2260b57cec5SDimitry Andric         const BitTracker::RegisterRef &RR, MachineRegisterInfo &MRI);
2270b57cec5SDimitry Andric     static bool isTransparentCopy(const BitTracker::RegisterRef &RD,
2280b57cec5SDimitry Andric         const BitTracker::RegisterRef &RS, MachineRegisterInfo &MRI);
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   private:
2310b57cec5SDimitry Andric     MachineDominatorTree *MDT = nullptr;
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric     bool visitBlock(MachineBasicBlock &B, Transformation &T, RegisterSet &AVs);
2340b57cec5SDimitry Andric     static bool hasTiedUse(unsigned Reg, MachineRegisterInfo &MRI,
2350b57cec5SDimitry Andric         unsigned NewSub = Hexagon::NoSubRegister);
2360b57cec5SDimitry Andric   };
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   using HBS = HexagonBitSimplify;
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   // The purpose of this class is to provide a common facility to traverse
2410b57cec5SDimitry Andric   // the function top-down or bottom-up via the dominator tree, and keep
2420b57cec5SDimitry Andric   // track of the available registers.
2430b57cec5SDimitry Andric   class Transformation {
2440b57cec5SDimitry Andric   public:
2450b57cec5SDimitry Andric     bool TopDown;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric     Transformation(bool TD) : TopDown(TD) {}
2480b57cec5SDimitry Andric     virtual ~Transformation() = default;
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric     virtual bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) = 0;
2510b57cec5SDimitry Andric   };
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric } // end anonymous namespace
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric char HexagonBitSimplify::ID = 0;
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(HexagonBitSimplify, "hexagon-bit-simplify",
2580b57cec5SDimitry Andric       "Hexagon bit simplification", false, false)
2590b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
2600b57cec5SDimitry Andric INITIALIZE_PASS_END(HexagonBitSimplify, "hexagon-bit-simplify",
2610b57cec5SDimitry Andric       "Hexagon bit simplification", false, false)
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric bool HexagonBitSimplify::visitBlock(MachineBasicBlock &B, Transformation &T,
2640b57cec5SDimitry Andric       RegisterSet &AVs) {
2650b57cec5SDimitry Andric   bool Changed = false;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   if (T.TopDown)
2680b57cec5SDimitry Andric     Changed = T.processBlock(B, AVs);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   RegisterSet Defs;
2710b57cec5SDimitry Andric   for (auto &I : B)
2720b57cec5SDimitry Andric     getInstrDefs(I, Defs);
2730b57cec5SDimitry Andric   RegisterSet NewAVs = AVs;
2740b57cec5SDimitry Andric   NewAVs.insert(Defs);
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   for (auto *DTN : children<MachineDomTreeNode*>(MDT->getNode(&B)))
2770b57cec5SDimitry Andric     Changed |= visitBlock(*(DTN->getBlock()), T, NewAVs);
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   if (!T.TopDown)
2800b57cec5SDimitry Andric     Changed |= T.processBlock(B, AVs);
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   return Changed;
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric //
2860b57cec5SDimitry Andric // Utility functions:
2870b57cec5SDimitry Andric //
2880b57cec5SDimitry Andric void HexagonBitSimplify::getInstrDefs(const MachineInstr &MI,
2890b57cec5SDimitry Andric       RegisterSet &Defs) {
2900b57cec5SDimitry Andric   for (auto &Op : MI.operands()) {
2910b57cec5SDimitry Andric     if (!Op.isReg() || !Op.isDef())
2920b57cec5SDimitry Andric       continue;
293*8bcb0991SDimitry Andric     Register R = Op.getReg();
294*8bcb0991SDimitry Andric     if (!Register::isVirtualRegister(R))
2950b57cec5SDimitry Andric       continue;
2960b57cec5SDimitry Andric     Defs.insert(R);
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric void HexagonBitSimplify::getInstrUses(const MachineInstr &MI,
3010b57cec5SDimitry Andric       RegisterSet &Uses) {
3020b57cec5SDimitry Andric   for (auto &Op : MI.operands()) {
3030b57cec5SDimitry Andric     if (!Op.isReg() || !Op.isUse())
3040b57cec5SDimitry Andric       continue;
305*8bcb0991SDimitry Andric     Register R = Op.getReg();
306*8bcb0991SDimitry Andric     if (!Register::isVirtualRegister(R))
3070b57cec5SDimitry Andric       continue;
3080b57cec5SDimitry Andric     Uses.insert(R);
3090b57cec5SDimitry Andric   }
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric // Check if all the bits in range [B, E) in both cells are equal.
3130b57cec5SDimitry Andric bool HexagonBitSimplify::isEqual(const BitTracker::RegisterCell &RC1,
3140b57cec5SDimitry Andric       uint16_t B1, const BitTracker::RegisterCell &RC2, uint16_t B2,
3150b57cec5SDimitry Andric       uint16_t W) {
3160b57cec5SDimitry Andric   for (uint16_t i = 0; i < W; ++i) {
3170b57cec5SDimitry Andric     // If RC1[i] is "bottom", it cannot be proven equal to RC2[i].
3180b57cec5SDimitry Andric     if (RC1[B1+i].Type == BitTracker::BitValue::Ref && RC1[B1+i].RefI.Reg == 0)
3190b57cec5SDimitry Andric       return false;
3200b57cec5SDimitry Andric     // Same for RC2[i].
3210b57cec5SDimitry Andric     if (RC2[B2+i].Type == BitTracker::BitValue::Ref && RC2[B2+i].RefI.Reg == 0)
3220b57cec5SDimitry Andric       return false;
3230b57cec5SDimitry Andric     if (RC1[B1+i] != RC2[B2+i])
3240b57cec5SDimitry Andric       return false;
3250b57cec5SDimitry Andric   }
3260b57cec5SDimitry Andric   return true;
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric bool HexagonBitSimplify::isZero(const BitTracker::RegisterCell &RC,
3300b57cec5SDimitry Andric       uint16_t B, uint16_t W) {
3310b57cec5SDimitry Andric   assert(B < RC.width() && B+W <= RC.width());
3320b57cec5SDimitry Andric   for (uint16_t i = B; i < B+W; ++i)
3330b57cec5SDimitry Andric     if (!RC[i].is(0))
3340b57cec5SDimitry Andric       return false;
3350b57cec5SDimitry Andric   return true;
3360b57cec5SDimitry Andric }
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric bool HexagonBitSimplify::getConst(const BitTracker::RegisterCell &RC,
3390b57cec5SDimitry Andric         uint16_t B, uint16_t W, uint64_t &U) {
3400b57cec5SDimitry Andric   assert(B < RC.width() && B+W <= RC.width());
3410b57cec5SDimitry Andric   int64_t T = 0;
3420b57cec5SDimitry Andric   for (uint16_t i = B+W; i > B; --i) {
3430b57cec5SDimitry Andric     const BitTracker::BitValue &BV = RC[i-1];
3440b57cec5SDimitry Andric     T <<= 1;
3450b57cec5SDimitry Andric     if (BV.is(1))
3460b57cec5SDimitry Andric       T |= 1;
3470b57cec5SDimitry Andric     else if (!BV.is(0))
3480b57cec5SDimitry Andric       return false;
3490b57cec5SDimitry Andric   }
3500b57cec5SDimitry Andric   U = T;
3510b57cec5SDimitry Andric   return true;
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric bool HexagonBitSimplify::replaceReg(unsigned OldR, unsigned NewR,
3550b57cec5SDimitry Andric       MachineRegisterInfo &MRI) {
356*8bcb0991SDimitry Andric   if (!Register::isVirtualRegister(OldR) || !Register::isVirtualRegister(NewR))
3570b57cec5SDimitry Andric     return false;
3580b57cec5SDimitry Andric   auto Begin = MRI.use_begin(OldR), End = MRI.use_end();
3590b57cec5SDimitry Andric   decltype(End) NextI;
3600b57cec5SDimitry Andric   for (auto I = Begin; I != End; I = NextI) {
3610b57cec5SDimitry Andric     NextI = std::next(I);
3620b57cec5SDimitry Andric     I->setReg(NewR);
3630b57cec5SDimitry Andric   }
3640b57cec5SDimitry Andric   return Begin != End;
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric bool HexagonBitSimplify::replaceRegWithSub(unsigned OldR, unsigned NewR,
3680b57cec5SDimitry Andric       unsigned NewSR, MachineRegisterInfo &MRI) {
369*8bcb0991SDimitry Andric   if (!Register::isVirtualRegister(OldR) || !Register::isVirtualRegister(NewR))
3700b57cec5SDimitry Andric     return false;
3710b57cec5SDimitry Andric   if (hasTiedUse(OldR, MRI, NewSR))
3720b57cec5SDimitry Andric     return false;
3730b57cec5SDimitry Andric   auto Begin = MRI.use_begin(OldR), End = MRI.use_end();
3740b57cec5SDimitry Andric   decltype(End) NextI;
3750b57cec5SDimitry Andric   for (auto I = Begin; I != End; I = NextI) {
3760b57cec5SDimitry Andric     NextI = std::next(I);
3770b57cec5SDimitry Andric     I->setReg(NewR);
3780b57cec5SDimitry Andric     I->setSubReg(NewSR);
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric   return Begin != End;
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric bool HexagonBitSimplify::replaceSubWithSub(unsigned OldR, unsigned OldSR,
3840b57cec5SDimitry Andric       unsigned NewR, unsigned NewSR, MachineRegisterInfo &MRI) {
385*8bcb0991SDimitry Andric   if (!Register::isVirtualRegister(OldR) || !Register::isVirtualRegister(NewR))
3860b57cec5SDimitry Andric     return false;
3870b57cec5SDimitry Andric   if (OldSR != NewSR && hasTiedUse(OldR, MRI, NewSR))
3880b57cec5SDimitry Andric     return false;
3890b57cec5SDimitry Andric   auto Begin = MRI.use_begin(OldR), End = MRI.use_end();
3900b57cec5SDimitry Andric   decltype(End) NextI;
3910b57cec5SDimitry Andric   for (auto I = Begin; I != End; I = NextI) {
3920b57cec5SDimitry Andric     NextI = std::next(I);
3930b57cec5SDimitry Andric     if (I->getSubReg() != OldSR)
3940b57cec5SDimitry Andric       continue;
3950b57cec5SDimitry Andric     I->setReg(NewR);
3960b57cec5SDimitry Andric     I->setSubReg(NewSR);
3970b57cec5SDimitry Andric   }
3980b57cec5SDimitry Andric   return Begin != End;
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric // For a register ref (pair Reg:Sub), set Begin to the position of the LSB
4020b57cec5SDimitry Andric // of Sub in Reg, and set Width to the size of Sub in bits. Return true,
4030b57cec5SDimitry Andric // if this succeeded, otherwise return false.
4040b57cec5SDimitry Andric bool HexagonBitSimplify::getSubregMask(const BitTracker::RegisterRef &RR,
4050b57cec5SDimitry Andric       unsigned &Begin, unsigned &Width, MachineRegisterInfo &MRI) {
4060b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI.getRegClass(RR.Reg);
4070b57cec5SDimitry Andric   if (RR.Sub == 0) {
4080b57cec5SDimitry Andric     Begin = 0;
4090b57cec5SDimitry Andric     Width = MRI.getTargetRegisterInfo()->getRegSizeInBits(*RC);
4100b57cec5SDimitry Andric     return true;
4110b57cec5SDimitry Andric   }
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   Begin = 0;
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric   switch (RC->getID()) {
4160b57cec5SDimitry Andric     case Hexagon::DoubleRegsRegClassID:
4170b57cec5SDimitry Andric     case Hexagon::HvxWRRegClassID:
4180b57cec5SDimitry Andric       Width = MRI.getTargetRegisterInfo()->getRegSizeInBits(*RC) / 2;
4190b57cec5SDimitry Andric       if (RR.Sub == Hexagon::isub_hi || RR.Sub == Hexagon::vsub_hi)
4200b57cec5SDimitry Andric         Begin = Width;
4210b57cec5SDimitry Andric       break;
4220b57cec5SDimitry Andric     default:
4230b57cec5SDimitry Andric       return false;
4240b57cec5SDimitry Andric   }
4250b57cec5SDimitry Andric   return true;
4260b57cec5SDimitry Andric }
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric // For a REG_SEQUENCE, set SL to the low subregister and SH to the high
4300b57cec5SDimitry Andric // subregister.
4310b57cec5SDimitry Andric bool HexagonBitSimplify::parseRegSequence(const MachineInstr &I,
4320b57cec5SDimitry Andric       BitTracker::RegisterRef &SL, BitTracker::RegisterRef &SH,
4330b57cec5SDimitry Andric       const MachineRegisterInfo &MRI) {
4340b57cec5SDimitry Andric   assert(I.getOpcode() == TargetOpcode::REG_SEQUENCE);
4350b57cec5SDimitry Andric   unsigned Sub1 = I.getOperand(2).getImm(), Sub2 = I.getOperand(4).getImm();
4360b57cec5SDimitry Andric   auto &DstRC = *MRI.getRegClass(I.getOperand(0).getReg());
4370b57cec5SDimitry Andric   auto &HRI = static_cast<const HexagonRegisterInfo&>(
4380b57cec5SDimitry Andric                   *MRI.getTargetRegisterInfo());
4390b57cec5SDimitry Andric   unsigned SubLo = HRI.getHexagonSubRegIndex(DstRC, Hexagon::ps_sub_lo);
4400b57cec5SDimitry Andric   unsigned SubHi = HRI.getHexagonSubRegIndex(DstRC, Hexagon::ps_sub_hi);
4410b57cec5SDimitry Andric   assert((Sub1 == SubLo && Sub2 == SubHi) || (Sub1 == SubHi && Sub2 == SubLo));
4420b57cec5SDimitry Andric   if (Sub1 == SubLo && Sub2 == SubHi) {
4430b57cec5SDimitry Andric     SL = I.getOperand(1);
4440b57cec5SDimitry Andric     SH = I.getOperand(3);
4450b57cec5SDimitry Andric     return true;
4460b57cec5SDimitry Andric   }
4470b57cec5SDimitry Andric   if (Sub1 == SubHi && Sub2 == SubLo) {
4480b57cec5SDimitry Andric     SH = I.getOperand(1);
4490b57cec5SDimitry Andric     SL = I.getOperand(3);
4500b57cec5SDimitry Andric     return true;
4510b57cec5SDimitry Andric   }
4520b57cec5SDimitry Andric   return false;
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric // All stores (except 64-bit stores) take a 32-bit register as the source
4560b57cec5SDimitry Andric // of the value to be stored. If the instruction stores into a location
4570b57cec5SDimitry Andric // that is shorter than 32 bits, some bits of the source register are not
4580b57cec5SDimitry Andric // used. For each store instruction, calculate the set of used bits in
4590b57cec5SDimitry Andric // the source register, and set appropriate bits in Bits. Return true if
4600b57cec5SDimitry Andric // the bits are calculated, false otherwise.
4610b57cec5SDimitry Andric bool HexagonBitSimplify::getUsedBitsInStore(unsigned Opc, BitVector &Bits,
4620b57cec5SDimitry Andric       uint16_t Begin) {
4630b57cec5SDimitry Andric   using namespace Hexagon;
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric   switch (Opc) {
4660b57cec5SDimitry Andric     // Store byte
4670b57cec5SDimitry Andric     case S2_storerb_io:           // memb(Rs32+#s11:0)=Rt32
4680b57cec5SDimitry Andric     case S2_storerbnew_io:        // memb(Rs32+#s11:0)=Nt8.new
4690b57cec5SDimitry Andric     case S2_pstorerbt_io:         // if (Pv4) memb(Rs32+#u6:0)=Rt32
4700b57cec5SDimitry Andric     case S2_pstorerbf_io:         // if (!Pv4) memb(Rs32+#u6:0)=Rt32
4710b57cec5SDimitry Andric     case S4_pstorerbtnew_io:      // if (Pv4.new) memb(Rs32+#u6:0)=Rt32
4720b57cec5SDimitry Andric     case S4_pstorerbfnew_io:      // if (!Pv4.new) memb(Rs32+#u6:0)=Rt32
4730b57cec5SDimitry Andric     case S2_pstorerbnewt_io:      // if (Pv4) memb(Rs32+#u6:0)=Nt8.new
4740b57cec5SDimitry Andric     case S2_pstorerbnewf_io:      // if (!Pv4) memb(Rs32+#u6:0)=Nt8.new
4750b57cec5SDimitry Andric     case S4_pstorerbnewtnew_io:   // if (Pv4.new) memb(Rs32+#u6:0)=Nt8.new
4760b57cec5SDimitry Andric     case S4_pstorerbnewfnew_io:   // if (!Pv4.new) memb(Rs32+#u6:0)=Nt8.new
4770b57cec5SDimitry Andric     case S2_storerb_pi:           // memb(Rx32++#s4:0)=Rt32
4780b57cec5SDimitry Andric     case S2_storerbnew_pi:        // memb(Rx32++#s4:0)=Nt8.new
4790b57cec5SDimitry Andric     case S2_pstorerbt_pi:         // if (Pv4) memb(Rx32++#s4:0)=Rt32
4800b57cec5SDimitry Andric     case S2_pstorerbf_pi:         // if (!Pv4) memb(Rx32++#s4:0)=Rt32
4810b57cec5SDimitry Andric     case S2_pstorerbtnew_pi:      // if (Pv4.new) memb(Rx32++#s4:0)=Rt32
4820b57cec5SDimitry Andric     case S2_pstorerbfnew_pi:      // if (!Pv4.new) memb(Rx32++#s4:0)=Rt32
4830b57cec5SDimitry Andric     case S2_pstorerbnewt_pi:      // if (Pv4) memb(Rx32++#s4:0)=Nt8.new
4840b57cec5SDimitry Andric     case S2_pstorerbnewf_pi:      // if (!Pv4) memb(Rx32++#s4:0)=Nt8.new
4850b57cec5SDimitry Andric     case S2_pstorerbnewtnew_pi:   // if (Pv4.new) memb(Rx32++#s4:0)=Nt8.new
4860b57cec5SDimitry Andric     case S2_pstorerbnewfnew_pi:   // if (!Pv4.new) memb(Rx32++#s4:0)=Nt8.new
4870b57cec5SDimitry Andric     case S4_storerb_ap:           // memb(Re32=#U6)=Rt32
4880b57cec5SDimitry Andric     case S4_storerbnew_ap:        // memb(Re32=#U6)=Nt8.new
4890b57cec5SDimitry Andric     case S2_storerb_pr:           // memb(Rx32++Mu2)=Rt32
4900b57cec5SDimitry Andric     case S2_storerbnew_pr:        // memb(Rx32++Mu2)=Nt8.new
4910b57cec5SDimitry Andric     case S4_storerb_ur:           // memb(Ru32<<#u2+#U6)=Rt32
4920b57cec5SDimitry Andric     case S4_storerbnew_ur:        // memb(Ru32<<#u2+#U6)=Nt8.new
4930b57cec5SDimitry Andric     case S2_storerb_pbr:          // memb(Rx32++Mu2:brev)=Rt32
4940b57cec5SDimitry Andric     case S2_storerbnew_pbr:       // memb(Rx32++Mu2:brev)=Nt8.new
4950b57cec5SDimitry Andric     case S2_storerb_pci:          // memb(Rx32++#s4:0:circ(Mu2))=Rt32
4960b57cec5SDimitry Andric     case S2_storerbnew_pci:       // memb(Rx32++#s4:0:circ(Mu2))=Nt8.new
4970b57cec5SDimitry Andric     case S2_storerb_pcr:          // memb(Rx32++I:circ(Mu2))=Rt32
4980b57cec5SDimitry Andric     case S2_storerbnew_pcr:       // memb(Rx32++I:circ(Mu2))=Nt8.new
4990b57cec5SDimitry Andric     case S4_storerb_rr:           // memb(Rs32+Ru32<<#u2)=Rt32
5000b57cec5SDimitry Andric     case S4_storerbnew_rr:        // memb(Rs32+Ru32<<#u2)=Nt8.new
5010b57cec5SDimitry Andric     case S4_pstorerbt_rr:         // if (Pv4) memb(Rs32+Ru32<<#u2)=Rt32
5020b57cec5SDimitry Andric     case S4_pstorerbf_rr:         // if (!Pv4) memb(Rs32+Ru32<<#u2)=Rt32
5030b57cec5SDimitry Andric     case S4_pstorerbtnew_rr:      // if (Pv4.new) memb(Rs32+Ru32<<#u2)=Rt32
5040b57cec5SDimitry Andric     case S4_pstorerbfnew_rr:      // if (!Pv4.new) memb(Rs32+Ru32<<#u2)=Rt32
5050b57cec5SDimitry Andric     case S4_pstorerbnewt_rr:      // if (Pv4) memb(Rs32+Ru32<<#u2)=Nt8.new
5060b57cec5SDimitry Andric     case S4_pstorerbnewf_rr:      // if (!Pv4) memb(Rs32+Ru32<<#u2)=Nt8.new
5070b57cec5SDimitry Andric     case S4_pstorerbnewtnew_rr:   // if (Pv4.new) memb(Rs32+Ru32<<#u2)=Nt8.new
5080b57cec5SDimitry Andric     case S4_pstorerbnewfnew_rr:   // if (!Pv4.new) memb(Rs32+Ru32<<#u2)=Nt8.new
5090b57cec5SDimitry Andric     case S2_storerbgp:            // memb(gp+#u16:0)=Rt32
5100b57cec5SDimitry Andric     case S2_storerbnewgp:         // memb(gp+#u16:0)=Nt8.new
5110b57cec5SDimitry Andric     case S4_pstorerbt_abs:        // if (Pv4) memb(#u6)=Rt32
5120b57cec5SDimitry Andric     case S4_pstorerbf_abs:        // if (!Pv4) memb(#u6)=Rt32
5130b57cec5SDimitry Andric     case S4_pstorerbtnew_abs:     // if (Pv4.new) memb(#u6)=Rt32
5140b57cec5SDimitry Andric     case S4_pstorerbfnew_abs:     // if (!Pv4.new) memb(#u6)=Rt32
5150b57cec5SDimitry Andric     case S4_pstorerbnewt_abs:     // if (Pv4) memb(#u6)=Nt8.new
5160b57cec5SDimitry Andric     case S4_pstorerbnewf_abs:     // if (!Pv4) memb(#u6)=Nt8.new
5170b57cec5SDimitry Andric     case S4_pstorerbnewtnew_abs:  // if (Pv4.new) memb(#u6)=Nt8.new
5180b57cec5SDimitry Andric     case S4_pstorerbnewfnew_abs:  // if (!Pv4.new) memb(#u6)=Nt8.new
5190b57cec5SDimitry Andric       Bits.set(Begin, Begin+8);
5200b57cec5SDimitry Andric       return true;
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric     // Store low half
5230b57cec5SDimitry Andric     case S2_storerh_io:           // memh(Rs32+#s11:1)=Rt32
5240b57cec5SDimitry Andric     case S2_storerhnew_io:        // memh(Rs32+#s11:1)=Nt8.new
5250b57cec5SDimitry Andric     case S2_pstorerht_io:         // if (Pv4) memh(Rs32+#u6:1)=Rt32
5260b57cec5SDimitry Andric     case S2_pstorerhf_io:         // if (!Pv4) memh(Rs32+#u6:1)=Rt32
5270b57cec5SDimitry Andric     case S4_pstorerhtnew_io:      // if (Pv4.new) memh(Rs32+#u6:1)=Rt32
5280b57cec5SDimitry Andric     case S4_pstorerhfnew_io:      // if (!Pv4.new) memh(Rs32+#u6:1)=Rt32
5290b57cec5SDimitry Andric     case S2_pstorerhnewt_io:      // if (Pv4) memh(Rs32+#u6:1)=Nt8.new
5300b57cec5SDimitry Andric     case S2_pstorerhnewf_io:      // if (!Pv4) memh(Rs32+#u6:1)=Nt8.new
5310b57cec5SDimitry Andric     case S4_pstorerhnewtnew_io:   // if (Pv4.new) memh(Rs32+#u6:1)=Nt8.new
5320b57cec5SDimitry Andric     case S4_pstorerhnewfnew_io:   // if (!Pv4.new) memh(Rs32+#u6:1)=Nt8.new
5330b57cec5SDimitry Andric     case S2_storerh_pi:           // memh(Rx32++#s4:1)=Rt32
5340b57cec5SDimitry Andric     case S2_storerhnew_pi:        // memh(Rx32++#s4:1)=Nt8.new
5350b57cec5SDimitry Andric     case S2_pstorerht_pi:         // if (Pv4) memh(Rx32++#s4:1)=Rt32
5360b57cec5SDimitry Andric     case S2_pstorerhf_pi:         // if (!Pv4) memh(Rx32++#s4:1)=Rt32
5370b57cec5SDimitry Andric     case S2_pstorerhtnew_pi:      // if (Pv4.new) memh(Rx32++#s4:1)=Rt32
5380b57cec5SDimitry Andric     case S2_pstorerhfnew_pi:      // if (!Pv4.new) memh(Rx32++#s4:1)=Rt32
5390b57cec5SDimitry Andric     case S2_pstorerhnewt_pi:      // if (Pv4) memh(Rx32++#s4:1)=Nt8.new
5400b57cec5SDimitry Andric     case S2_pstorerhnewf_pi:      // if (!Pv4) memh(Rx32++#s4:1)=Nt8.new
5410b57cec5SDimitry Andric     case S2_pstorerhnewtnew_pi:   // if (Pv4.new) memh(Rx32++#s4:1)=Nt8.new
5420b57cec5SDimitry Andric     case S2_pstorerhnewfnew_pi:   // if (!Pv4.new) memh(Rx32++#s4:1)=Nt8.new
5430b57cec5SDimitry Andric     case S4_storerh_ap:           // memh(Re32=#U6)=Rt32
5440b57cec5SDimitry Andric     case S4_storerhnew_ap:        // memh(Re32=#U6)=Nt8.new
5450b57cec5SDimitry Andric     case S2_storerh_pr:           // memh(Rx32++Mu2)=Rt32
5460b57cec5SDimitry Andric     case S2_storerhnew_pr:        // memh(Rx32++Mu2)=Nt8.new
5470b57cec5SDimitry Andric     case S4_storerh_ur:           // memh(Ru32<<#u2+#U6)=Rt32
5480b57cec5SDimitry Andric     case S4_storerhnew_ur:        // memh(Ru32<<#u2+#U6)=Nt8.new
5490b57cec5SDimitry Andric     case S2_storerh_pbr:          // memh(Rx32++Mu2:brev)=Rt32
5500b57cec5SDimitry Andric     case S2_storerhnew_pbr:       // memh(Rx32++Mu2:brev)=Nt8.new
5510b57cec5SDimitry Andric     case S2_storerh_pci:          // memh(Rx32++#s4:1:circ(Mu2))=Rt32
5520b57cec5SDimitry Andric     case S2_storerhnew_pci:       // memh(Rx32++#s4:1:circ(Mu2))=Nt8.new
5530b57cec5SDimitry Andric     case S2_storerh_pcr:          // memh(Rx32++I:circ(Mu2))=Rt32
5540b57cec5SDimitry Andric     case S2_storerhnew_pcr:       // memh(Rx32++I:circ(Mu2))=Nt8.new
5550b57cec5SDimitry Andric     case S4_storerh_rr:           // memh(Rs32+Ru32<<#u2)=Rt32
5560b57cec5SDimitry Andric     case S4_pstorerht_rr:         // if (Pv4) memh(Rs32+Ru32<<#u2)=Rt32
5570b57cec5SDimitry Andric     case S4_pstorerhf_rr:         // if (!Pv4) memh(Rs32+Ru32<<#u2)=Rt32
5580b57cec5SDimitry Andric     case S4_pstorerhtnew_rr:      // if (Pv4.new) memh(Rs32+Ru32<<#u2)=Rt32
5590b57cec5SDimitry Andric     case S4_pstorerhfnew_rr:      // if (!Pv4.new) memh(Rs32+Ru32<<#u2)=Rt32
5600b57cec5SDimitry Andric     case S4_storerhnew_rr:        // memh(Rs32+Ru32<<#u2)=Nt8.new
5610b57cec5SDimitry Andric     case S4_pstorerhnewt_rr:      // if (Pv4) memh(Rs32+Ru32<<#u2)=Nt8.new
5620b57cec5SDimitry Andric     case S4_pstorerhnewf_rr:      // if (!Pv4) memh(Rs32+Ru32<<#u2)=Nt8.new
5630b57cec5SDimitry Andric     case S4_pstorerhnewtnew_rr:   // if (Pv4.new) memh(Rs32+Ru32<<#u2)=Nt8.new
5640b57cec5SDimitry Andric     case S4_pstorerhnewfnew_rr:   // if (!Pv4.new) memh(Rs32+Ru32<<#u2)=Nt8.new
5650b57cec5SDimitry Andric     case S2_storerhgp:            // memh(gp+#u16:1)=Rt32
5660b57cec5SDimitry Andric     case S2_storerhnewgp:         // memh(gp+#u16:1)=Nt8.new
5670b57cec5SDimitry Andric     case S4_pstorerht_abs:        // if (Pv4) memh(#u6)=Rt32
5680b57cec5SDimitry Andric     case S4_pstorerhf_abs:        // if (!Pv4) memh(#u6)=Rt32
5690b57cec5SDimitry Andric     case S4_pstorerhtnew_abs:     // if (Pv4.new) memh(#u6)=Rt32
5700b57cec5SDimitry Andric     case S4_pstorerhfnew_abs:     // if (!Pv4.new) memh(#u6)=Rt32
5710b57cec5SDimitry Andric     case S4_pstorerhnewt_abs:     // if (Pv4) memh(#u6)=Nt8.new
5720b57cec5SDimitry Andric     case S4_pstorerhnewf_abs:     // if (!Pv4) memh(#u6)=Nt8.new
5730b57cec5SDimitry Andric     case S4_pstorerhnewtnew_abs:  // if (Pv4.new) memh(#u6)=Nt8.new
5740b57cec5SDimitry Andric     case S4_pstorerhnewfnew_abs:  // if (!Pv4.new) memh(#u6)=Nt8.new
5750b57cec5SDimitry Andric       Bits.set(Begin, Begin+16);
5760b57cec5SDimitry Andric       return true;
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric     // Store high half
5790b57cec5SDimitry Andric     case S2_storerf_io:           // memh(Rs32+#s11:1)=Rt.H32
5800b57cec5SDimitry Andric     case S2_pstorerft_io:         // if (Pv4) memh(Rs32+#u6:1)=Rt.H32
5810b57cec5SDimitry Andric     case S2_pstorerff_io:         // if (!Pv4) memh(Rs32+#u6:1)=Rt.H32
5820b57cec5SDimitry Andric     case S4_pstorerftnew_io:      // if (Pv4.new) memh(Rs32+#u6:1)=Rt.H32
5830b57cec5SDimitry Andric     case S4_pstorerffnew_io:      // if (!Pv4.new) memh(Rs32+#u6:1)=Rt.H32
5840b57cec5SDimitry Andric     case S2_storerf_pi:           // memh(Rx32++#s4:1)=Rt.H32
5850b57cec5SDimitry Andric     case S2_pstorerft_pi:         // if (Pv4) memh(Rx32++#s4:1)=Rt.H32
5860b57cec5SDimitry Andric     case S2_pstorerff_pi:         // if (!Pv4) memh(Rx32++#s4:1)=Rt.H32
5870b57cec5SDimitry Andric     case S2_pstorerftnew_pi:      // if (Pv4.new) memh(Rx32++#s4:1)=Rt.H32
5880b57cec5SDimitry Andric     case S2_pstorerffnew_pi:      // if (!Pv4.new) memh(Rx32++#s4:1)=Rt.H32
5890b57cec5SDimitry Andric     case S4_storerf_ap:           // memh(Re32=#U6)=Rt.H32
5900b57cec5SDimitry Andric     case S2_storerf_pr:           // memh(Rx32++Mu2)=Rt.H32
5910b57cec5SDimitry Andric     case S4_storerf_ur:           // memh(Ru32<<#u2+#U6)=Rt.H32
5920b57cec5SDimitry Andric     case S2_storerf_pbr:          // memh(Rx32++Mu2:brev)=Rt.H32
5930b57cec5SDimitry Andric     case S2_storerf_pci:          // memh(Rx32++#s4:1:circ(Mu2))=Rt.H32
5940b57cec5SDimitry Andric     case S2_storerf_pcr:          // memh(Rx32++I:circ(Mu2))=Rt.H32
5950b57cec5SDimitry Andric     case S4_storerf_rr:           // memh(Rs32+Ru32<<#u2)=Rt.H32
5960b57cec5SDimitry Andric     case S4_pstorerft_rr:         // if (Pv4) memh(Rs32+Ru32<<#u2)=Rt.H32
5970b57cec5SDimitry Andric     case S4_pstorerff_rr:         // if (!Pv4) memh(Rs32+Ru32<<#u2)=Rt.H32
5980b57cec5SDimitry Andric     case S4_pstorerftnew_rr:      // if (Pv4.new) memh(Rs32+Ru32<<#u2)=Rt.H32
5990b57cec5SDimitry Andric     case S4_pstorerffnew_rr:      // if (!Pv4.new) memh(Rs32+Ru32<<#u2)=Rt.H32
6000b57cec5SDimitry Andric     case S2_storerfgp:            // memh(gp+#u16:1)=Rt.H32
6010b57cec5SDimitry Andric     case S4_pstorerft_abs:        // if (Pv4) memh(#u6)=Rt.H32
6020b57cec5SDimitry Andric     case S4_pstorerff_abs:        // if (!Pv4) memh(#u6)=Rt.H32
6030b57cec5SDimitry Andric     case S4_pstorerftnew_abs:     // if (Pv4.new) memh(#u6)=Rt.H32
6040b57cec5SDimitry Andric     case S4_pstorerffnew_abs:     // if (!Pv4.new) memh(#u6)=Rt.H32
6050b57cec5SDimitry Andric       Bits.set(Begin+16, Begin+32);
6060b57cec5SDimitry Andric       return true;
6070b57cec5SDimitry Andric   }
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric   return false;
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric // For an instruction with opcode Opc, calculate the set of bits that it
6130b57cec5SDimitry Andric // uses in a register in operand OpN. This only calculates the set of used
6140b57cec5SDimitry Andric // bits for cases where it does not depend on any operands (as is the case
6150b57cec5SDimitry Andric // in shifts, for example). For concrete instructions from a program, the
6160b57cec5SDimitry Andric // operand may be a subregister of a larger register, while Bits would
6170b57cec5SDimitry Andric // correspond to the larger register in its entirety. Because of that,
6180b57cec5SDimitry Andric // the parameter Begin can be used to indicate which bit of Bits should be
6190b57cec5SDimitry Andric // considered the LSB of the operand.
6200b57cec5SDimitry Andric bool HexagonBitSimplify::getUsedBits(unsigned Opc, unsigned OpN,
6210b57cec5SDimitry Andric       BitVector &Bits, uint16_t Begin, const HexagonInstrInfo &HII) {
6220b57cec5SDimitry Andric   using namespace Hexagon;
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric   const MCInstrDesc &D = HII.get(Opc);
6250b57cec5SDimitry Andric   if (D.mayStore()) {
6260b57cec5SDimitry Andric     if (OpN == D.getNumOperands()-1)
6270b57cec5SDimitry Andric       return getUsedBitsInStore(Opc, Bits, Begin);
6280b57cec5SDimitry Andric     return false;
6290b57cec5SDimitry Andric   }
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric   switch (Opc) {
6320b57cec5SDimitry Andric     // One register source. Used bits: R1[0-7].
6330b57cec5SDimitry Andric     case A2_sxtb:
6340b57cec5SDimitry Andric     case A2_zxtb:
6350b57cec5SDimitry Andric     case A4_cmpbeqi:
6360b57cec5SDimitry Andric     case A4_cmpbgti:
6370b57cec5SDimitry Andric     case A4_cmpbgtui:
6380b57cec5SDimitry Andric       if (OpN == 1) {
6390b57cec5SDimitry Andric         Bits.set(Begin, Begin+8);
6400b57cec5SDimitry Andric         return true;
6410b57cec5SDimitry Andric       }
6420b57cec5SDimitry Andric       break;
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric     // One register source. Used bits: R1[0-15].
6450b57cec5SDimitry Andric     case A2_aslh:
6460b57cec5SDimitry Andric     case A2_sxth:
6470b57cec5SDimitry Andric     case A2_zxth:
6480b57cec5SDimitry Andric     case A4_cmpheqi:
6490b57cec5SDimitry Andric     case A4_cmphgti:
6500b57cec5SDimitry Andric     case A4_cmphgtui:
6510b57cec5SDimitry Andric       if (OpN == 1) {
6520b57cec5SDimitry Andric         Bits.set(Begin, Begin+16);
6530b57cec5SDimitry Andric         return true;
6540b57cec5SDimitry Andric       }
6550b57cec5SDimitry Andric       break;
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric     // One register source. Used bits: R1[16-31].
6580b57cec5SDimitry Andric     case A2_asrh:
6590b57cec5SDimitry Andric       if (OpN == 1) {
6600b57cec5SDimitry Andric         Bits.set(Begin+16, Begin+32);
6610b57cec5SDimitry Andric         return true;
6620b57cec5SDimitry Andric       }
6630b57cec5SDimitry Andric       break;
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric     // Two register sources. Used bits: R1[0-7], R2[0-7].
6660b57cec5SDimitry Andric     case A4_cmpbeq:
6670b57cec5SDimitry Andric     case A4_cmpbgt:
6680b57cec5SDimitry Andric     case A4_cmpbgtu:
6690b57cec5SDimitry Andric       if (OpN == 1) {
6700b57cec5SDimitry Andric         Bits.set(Begin, Begin+8);
6710b57cec5SDimitry Andric         return true;
6720b57cec5SDimitry Andric       }
6730b57cec5SDimitry Andric       break;
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric     // Two register sources. Used bits: R1[0-15], R2[0-15].
6760b57cec5SDimitry Andric     case A4_cmpheq:
6770b57cec5SDimitry Andric     case A4_cmphgt:
6780b57cec5SDimitry Andric     case A4_cmphgtu:
6790b57cec5SDimitry Andric     case A2_addh_h16_ll:
6800b57cec5SDimitry Andric     case A2_addh_h16_sat_ll:
6810b57cec5SDimitry Andric     case A2_addh_l16_ll:
6820b57cec5SDimitry Andric     case A2_addh_l16_sat_ll:
6830b57cec5SDimitry Andric     case A2_combine_ll:
6840b57cec5SDimitry Andric     case A2_subh_h16_ll:
6850b57cec5SDimitry Andric     case A2_subh_h16_sat_ll:
6860b57cec5SDimitry Andric     case A2_subh_l16_ll:
6870b57cec5SDimitry Andric     case A2_subh_l16_sat_ll:
6880b57cec5SDimitry Andric     case M2_mpy_acc_ll_s0:
6890b57cec5SDimitry Andric     case M2_mpy_acc_ll_s1:
6900b57cec5SDimitry Andric     case M2_mpy_acc_sat_ll_s0:
6910b57cec5SDimitry Andric     case M2_mpy_acc_sat_ll_s1:
6920b57cec5SDimitry Andric     case M2_mpy_ll_s0:
6930b57cec5SDimitry Andric     case M2_mpy_ll_s1:
6940b57cec5SDimitry Andric     case M2_mpy_nac_ll_s0:
6950b57cec5SDimitry Andric     case M2_mpy_nac_ll_s1:
6960b57cec5SDimitry Andric     case M2_mpy_nac_sat_ll_s0:
6970b57cec5SDimitry Andric     case M2_mpy_nac_sat_ll_s1:
6980b57cec5SDimitry Andric     case M2_mpy_rnd_ll_s0:
6990b57cec5SDimitry Andric     case M2_mpy_rnd_ll_s1:
7000b57cec5SDimitry Andric     case M2_mpy_sat_ll_s0:
7010b57cec5SDimitry Andric     case M2_mpy_sat_ll_s1:
7020b57cec5SDimitry Andric     case M2_mpy_sat_rnd_ll_s0:
7030b57cec5SDimitry Andric     case M2_mpy_sat_rnd_ll_s1:
7040b57cec5SDimitry Andric     case M2_mpyd_acc_ll_s0:
7050b57cec5SDimitry Andric     case M2_mpyd_acc_ll_s1:
7060b57cec5SDimitry Andric     case M2_mpyd_ll_s0:
7070b57cec5SDimitry Andric     case M2_mpyd_ll_s1:
7080b57cec5SDimitry Andric     case M2_mpyd_nac_ll_s0:
7090b57cec5SDimitry Andric     case M2_mpyd_nac_ll_s1:
7100b57cec5SDimitry Andric     case M2_mpyd_rnd_ll_s0:
7110b57cec5SDimitry Andric     case M2_mpyd_rnd_ll_s1:
7120b57cec5SDimitry Andric     case M2_mpyu_acc_ll_s0:
7130b57cec5SDimitry Andric     case M2_mpyu_acc_ll_s1:
7140b57cec5SDimitry Andric     case M2_mpyu_ll_s0:
7150b57cec5SDimitry Andric     case M2_mpyu_ll_s1:
7160b57cec5SDimitry Andric     case M2_mpyu_nac_ll_s0:
7170b57cec5SDimitry Andric     case M2_mpyu_nac_ll_s1:
7180b57cec5SDimitry Andric     case M2_mpyud_acc_ll_s0:
7190b57cec5SDimitry Andric     case M2_mpyud_acc_ll_s1:
7200b57cec5SDimitry Andric     case M2_mpyud_ll_s0:
7210b57cec5SDimitry Andric     case M2_mpyud_ll_s1:
7220b57cec5SDimitry Andric     case M2_mpyud_nac_ll_s0:
7230b57cec5SDimitry Andric     case M2_mpyud_nac_ll_s1:
7240b57cec5SDimitry Andric       if (OpN == 1 || OpN == 2) {
7250b57cec5SDimitry Andric         Bits.set(Begin, Begin+16);
7260b57cec5SDimitry Andric         return true;
7270b57cec5SDimitry Andric       }
7280b57cec5SDimitry Andric       break;
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric     // Two register sources. Used bits: R1[0-15], R2[16-31].
7310b57cec5SDimitry Andric     case A2_addh_h16_lh:
7320b57cec5SDimitry Andric     case A2_addh_h16_sat_lh:
7330b57cec5SDimitry Andric     case A2_combine_lh:
7340b57cec5SDimitry Andric     case A2_subh_h16_lh:
7350b57cec5SDimitry Andric     case A2_subh_h16_sat_lh:
7360b57cec5SDimitry Andric     case M2_mpy_acc_lh_s0:
7370b57cec5SDimitry Andric     case M2_mpy_acc_lh_s1:
7380b57cec5SDimitry Andric     case M2_mpy_acc_sat_lh_s0:
7390b57cec5SDimitry Andric     case M2_mpy_acc_sat_lh_s1:
7400b57cec5SDimitry Andric     case M2_mpy_lh_s0:
7410b57cec5SDimitry Andric     case M2_mpy_lh_s1:
7420b57cec5SDimitry Andric     case M2_mpy_nac_lh_s0:
7430b57cec5SDimitry Andric     case M2_mpy_nac_lh_s1:
7440b57cec5SDimitry Andric     case M2_mpy_nac_sat_lh_s0:
7450b57cec5SDimitry Andric     case M2_mpy_nac_sat_lh_s1:
7460b57cec5SDimitry Andric     case M2_mpy_rnd_lh_s0:
7470b57cec5SDimitry Andric     case M2_mpy_rnd_lh_s1:
7480b57cec5SDimitry Andric     case M2_mpy_sat_lh_s0:
7490b57cec5SDimitry Andric     case M2_mpy_sat_lh_s1:
7500b57cec5SDimitry Andric     case M2_mpy_sat_rnd_lh_s0:
7510b57cec5SDimitry Andric     case M2_mpy_sat_rnd_lh_s1:
7520b57cec5SDimitry Andric     case M2_mpyd_acc_lh_s0:
7530b57cec5SDimitry Andric     case M2_mpyd_acc_lh_s1:
7540b57cec5SDimitry Andric     case M2_mpyd_lh_s0:
7550b57cec5SDimitry Andric     case M2_mpyd_lh_s1:
7560b57cec5SDimitry Andric     case M2_mpyd_nac_lh_s0:
7570b57cec5SDimitry Andric     case M2_mpyd_nac_lh_s1:
7580b57cec5SDimitry Andric     case M2_mpyd_rnd_lh_s0:
7590b57cec5SDimitry Andric     case M2_mpyd_rnd_lh_s1:
7600b57cec5SDimitry Andric     case M2_mpyu_acc_lh_s0:
7610b57cec5SDimitry Andric     case M2_mpyu_acc_lh_s1:
7620b57cec5SDimitry Andric     case M2_mpyu_lh_s0:
7630b57cec5SDimitry Andric     case M2_mpyu_lh_s1:
7640b57cec5SDimitry Andric     case M2_mpyu_nac_lh_s0:
7650b57cec5SDimitry Andric     case M2_mpyu_nac_lh_s1:
7660b57cec5SDimitry Andric     case M2_mpyud_acc_lh_s0:
7670b57cec5SDimitry Andric     case M2_mpyud_acc_lh_s1:
7680b57cec5SDimitry Andric     case M2_mpyud_lh_s0:
7690b57cec5SDimitry Andric     case M2_mpyud_lh_s1:
7700b57cec5SDimitry Andric     case M2_mpyud_nac_lh_s0:
7710b57cec5SDimitry Andric     case M2_mpyud_nac_lh_s1:
7720b57cec5SDimitry Andric     // These four are actually LH.
7730b57cec5SDimitry Andric     case A2_addh_l16_hl:
7740b57cec5SDimitry Andric     case A2_addh_l16_sat_hl:
7750b57cec5SDimitry Andric     case A2_subh_l16_hl:
7760b57cec5SDimitry Andric     case A2_subh_l16_sat_hl:
7770b57cec5SDimitry Andric       if (OpN == 1) {
7780b57cec5SDimitry Andric         Bits.set(Begin, Begin+16);
7790b57cec5SDimitry Andric         return true;
7800b57cec5SDimitry Andric       }
7810b57cec5SDimitry Andric       if (OpN == 2) {
7820b57cec5SDimitry Andric         Bits.set(Begin+16, Begin+32);
7830b57cec5SDimitry Andric         return true;
7840b57cec5SDimitry Andric       }
7850b57cec5SDimitry Andric       break;
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric     // Two register sources, used bits: R1[16-31], R2[0-15].
7880b57cec5SDimitry Andric     case A2_addh_h16_hl:
7890b57cec5SDimitry Andric     case A2_addh_h16_sat_hl:
7900b57cec5SDimitry Andric     case A2_combine_hl:
7910b57cec5SDimitry Andric     case A2_subh_h16_hl:
7920b57cec5SDimitry Andric     case A2_subh_h16_sat_hl:
7930b57cec5SDimitry Andric     case M2_mpy_acc_hl_s0:
7940b57cec5SDimitry Andric     case M2_mpy_acc_hl_s1:
7950b57cec5SDimitry Andric     case M2_mpy_acc_sat_hl_s0:
7960b57cec5SDimitry Andric     case M2_mpy_acc_sat_hl_s1:
7970b57cec5SDimitry Andric     case M2_mpy_hl_s0:
7980b57cec5SDimitry Andric     case M2_mpy_hl_s1:
7990b57cec5SDimitry Andric     case M2_mpy_nac_hl_s0:
8000b57cec5SDimitry Andric     case M2_mpy_nac_hl_s1:
8010b57cec5SDimitry Andric     case M2_mpy_nac_sat_hl_s0:
8020b57cec5SDimitry Andric     case M2_mpy_nac_sat_hl_s1:
8030b57cec5SDimitry Andric     case M2_mpy_rnd_hl_s0:
8040b57cec5SDimitry Andric     case M2_mpy_rnd_hl_s1:
8050b57cec5SDimitry Andric     case M2_mpy_sat_hl_s0:
8060b57cec5SDimitry Andric     case M2_mpy_sat_hl_s1:
8070b57cec5SDimitry Andric     case M2_mpy_sat_rnd_hl_s0:
8080b57cec5SDimitry Andric     case M2_mpy_sat_rnd_hl_s1:
8090b57cec5SDimitry Andric     case M2_mpyd_acc_hl_s0:
8100b57cec5SDimitry Andric     case M2_mpyd_acc_hl_s1:
8110b57cec5SDimitry Andric     case M2_mpyd_hl_s0:
8120b57cec5SDimitry Andric     case M2_mpyd_hl_s1:
8130b57cec5SDimitry Andric     case M2_mpyd_nac_hl_s0:
8140b57cec5SDimitry Andric     case M2_mpyd_nac_hl_s1:
8150b57cec5SDimitry Andric     case M2_mpyd_rnd_hl_s0:
8160b57cec5SDimitry Andric     case M2_mpyd_rnd_hl_s1:
8170b57cec5SDimitry Andric     case M2_mpyu_acc_hl_s0:
8180b57cec5SDimitry Andric     case M2_mpyu_acc_hl_s1:
8190b57cec5SDimitry Andric     case M2_mpyu_hl_s0:
8200b57cec5SDimitry Andric     case M2_mpyu_hl_s1:
8210b57cec5SDimitry Andric     case M2_mpyu_nac_hl_s0:
8220b57cec5SDimitry Andric     case M2_mpyu_nac_hl_s1:
8230b57cec5SDimitry Andric     case M2_mpyud_acc_hl_s0:
8240b57cec5SDimitry Andric     case M2_mpyud_acc_hl_s1:
8250b57cec5SDimitry Andric     case M2_mpyud_hl_s0:
8260b57cec5SDimitry Andric     case M2_mpyud_hl_s1:
8270b57cec5SDimitry Andric     case M2_mpyud_nac_hl_s0:
8280b57cec5SDimitry Andric     case M2_mpyud_nac_hl_s1:
8290b57cec5SDimitry Andric       if (OpN == 1) {
8300b57cec5SDimitry Andric         Bits.set(Begin+16, Begin+32);
8310b57cec5SDimitry Andric         return true;
8320b57cec5SDimitry Andric       }
8330b57cec5SDimitry Andric       if (OpN == 2) {
8340b57cec5SDimitry Andric         Bits.set(Begin, Begin+16);
8350b57cec5SDimitry Andric         return true;
8360b57cec5SDimitry Andric       }
8370b57cec5SDimitry Andric       break;
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric     // Two register sources, used bits: R1[16-31], R2[16-31].
8400b57cec5SDimitry Andric     case A2_addh_h16_hh:
8410b57cec5SDimitry Andric     case A2_addh_h16_sat_hh:
8420b57cec5SDimitry Andric     case A2_combine_hh:
8430b57cec5SDimitry Andric     case A2_subh_h16_hh:
8440b57cec5SDimitry Andric     case A2_subh_h16_sat_hh:
8450b57cec5SDimitry Andric     case M2_mpy_acc_hh_s0:
8460b57cec5SDimitry Andric     case M2_mpy_acc_hh_s1:
8470b57cec5SDimitry Andric     case M2_mpy_acc_sat_hh_s0:
8480b57cec5SDimitry Andric     case M2_mpy_acc_sat_hh_s1:
8490b57cec5SDimitry Andric     case M2_mpy_hh_s0:
8500b57cec5SDimitry Andric     case M2_mpy_hh_s1:
8510b57cec5SDimitry Andric     case M2_mpy_nac_hh_s0:
8520b57cec5SDimitry Andric     case M2_mpy_nac_hh_s1:
8530b57cec5SDimitry Andric     case M2_mpy_nac_sat_hh_s0:
8540b57cec5SDimitry Andric     case M2_mpy_nac_sat_hh_s1:
8550b57cec5SDimitry Andric     case M2_mpy_rnd_hh_s0:
8560b57cec5SDimitry Andric     case M2_mpy_rnd_hh_s1:
8570b57cec5SDimitry Andric     case M2_mpy_sat_hh_s0:
8580b57cec5SDimitry Andric     case M2_mpy_sat_hh_s1:
8590b57cec5SDimitry Andric     case M2_mpy_sat_rnd_hh_s0:
8600b57cec5SDimitry Andric     case M2_mpy_sat_rnd_hh_s1:
8610b57cec5SDimitry Andric     case M2_mpyd_acc_hh_s0:
8620b57cec5SDimitry Andric     case M2_mpyd_acc_hh_s1:
8630b57cec5SDimitry Andric     case M2_mpyd_hh_s0:
8640b57cec5SDimitry Andric     case M2_mpyd_hh_s1:
8650b57cec5SDimitry Andric     case M2_mpyd_nac_hh_s0:
8660b57cec5SDimitry Andric     case M2_mpyd_nac_hh_s1:
8670b57cec5SDimitry Andric     case M2_mpyd_rnd_hh_s0:
8680b57cec5SDimitry Andric     case M2_mpyd_rnd_hh_s1:
8690b57cec5SDimitry Andric     case M2_mpyu_acc_hh_s0:
8700b57cec5SDimitry Andric     case M2_mpyu_acc_hh_s1:
8710b57cec5SDimitry Andric     case M2_mpyu_hh_s0:
8720b57cec5SDimitry Andric     case M2_mpyu_hh_s1:
8730b57cec5SDimitry Andric     case M2_mpyu_nac_hh_s0:
8740b57cec5SDimitry Andric     case M2_mpyu_nac_hh_s1:
8750b57cec5SDimitry Andric     case M2_mpyud_acc_hh_s0:
8760b57cec5SDimitry Andric     case M2_mpyud_acc_hh_s1:
8770b57cec5SDimitry Andric     case M2_mpyud_hh_s0:
8780b57cec5SDimitry Andric     case M2_mpyud_hh_s1:
8790b57cec5SDimitry Andric     case M2_mpyud_nac_hh_s0:
8800b57cec5SDimitry Andric     case M2_mpyud_nac_hh_s1:
8810b57cec5SDimitry Andric       if (OpN == 1 || OpN == 2) {
8820b57cec5SDimitry Andric         Bits.set(Begin+16, Begin+32);
8830b57cec5SDimitry Andric         return true;
8840b57cec5SDimitry Andric       }
8850b57cec5SDimitry Andric       break;
8860b57cec5SDimitry Andric   }
8870b57cec5SDimitry Andric 
8880b57cec5SDimitry Andric   return false;
8890b57cec5SDimitry Andric }
8900b57cec5SDimitry Andric 
8910b57cec5SDimitry Andric // Calculate the register class that matches Reg:Sub. For example, if
8920b57cec5SDimitry Andric // %1 is a double register, then %1:isub_hi would match the "int"
8930b57cec5SDimitry Andric // register class.
8940b57cec5SDimitry Andric const TargetRegisterClass *HexagonBitSimplify::getFinalVRegClass(
8950b57cec5SDimitry Andric       const BitTracker::RegisterRef &RR, MachineRegisterInfo &MRI) {
896*8bcb0991SDimitry Andric   if (!Register::isVirtualRegister(RR.Reg))
8970b57cec5SDimitry Andric     return nullptr;
8980b57cec5SDimitry Andric   auto *RC = MRI.getRegClass(RR.Reg);
8990b57cec5SDimitry Andric   if (RR.Sub == 0)
9000b57cec5SDimitry Andric     return RC;
9010b57cec5SDimitry Andric   auto &HRI = static_cast<const HexagonRegisterInfo&>(
9020b57cec5SDimitry Andric                   *MRI.getTargetRegisterInfo());
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric   auto VerifySR = [&HRI] (const TargetRegisterClass *RC, unsigned Sub) -> void {
9050b57cec5SDimitry Andric     (void)HRI;
9060b57cec5SDimitry Andric     assert(Sub == HRI.getHexagonSubRegIndex(*RC, Hexagon::ps_sub_lo) ||
9070b57cec5SDimitry Andric            Sub == HRI.getHexagonSubRegIndex(*RC, Hexagon::ps_sub_hi));
9080b57cec5SDimitry Andric   };
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric   switch (RC->getID()) {
9110b57cec5SDimitry Andric     case Hexagon::DoubleRegsRegClassID:
9120b57cec5SDimitry Andric       VerifySR(RC, RR.Sub);
9130b57cec5SDimitry Andric       return &Hexagon::IntRegsRegClass;
9140b57cec5SDimitry Andric     case Hexagon::HvxWRRegClassID:
9150b57cec5SDimitry Andric       VerifySR(RC, RR.Sub);
9160b57cec5SDimitry Andric       return &Hexagon::HvxVRRegClass;
9170b57cec5SDimitry Andric   }
9180b57cec5SDimitry Andric   return nullptr;
9190b57cec5SDimitry Andric }
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric // Check if RD could be replaced with RS at any possible use of RD.
9220b57cec5SDimitry Andric // For example a predicate register cannot be replaced with a integer
9230b57cec5SDimitry Andric // register, but a 64-bit register with a subregister can be replaced
9240b57cec5SDimitry Andric // with a 32-bit register.
9250b57cec5SDimitry Andric bool HexagonBitSimplify::isTransparentCopy(const BitTracker::RegisterRef &RD,
9260b57cec5SDimitry Andric       const BitTracker::RegisterRef &RS, MachineRegisterInfo &MRI) {
927*8bcb0991SDimitry Andric   if (!Register::isVirtualRegister(RD.Reg) ||
928*8bcb0991SDimitry Andric       !Register::isVirtualRegister(RS.Reg))
9290b57cec5SDimitry Andric     return false;
9300b57cec5SDimitry Andric   // Return false if one (or both) classes are nullptr.
9310b57cec5SDimitry Andric   auto *DRC = getFinalVRegClass(RD, MRI);
9320b57cec5SDimitry Andric   if (!DRC)
9330b57cec5SDimitry Andric     return false;
9340b57cec5SDimitry Andric 
9350b57cec5SDimitry Andric   return DRC == getFinalVRegClass(RS, MRI);
9360b57cec5SDimitry Andric }
9370b57cec5SDimitry Andric 
9380b57cec5SDimitry Andric bool HexagonBitSimplify::hasTiedUse(unsigned Reg, MachineRegisterInfo &MRI,
9390b57cec5SDimitry Andric       unsigned NewSub) {
9400b57cec5SDimitry Andric   if (!PreserveTiedOps)
9410b57cec5SDimitry Andric     return false;
9420b57cec5SDimitry Andric   return llvm::any_of(MRI.use_operands(Reg),
9430b57cec5SDimitry Andric                       [NewSub] (const MachineOperand &Op) -> bool {
9440b57cec5SDimitry Andric                         return Op.getSubReg() != NewSub && Op.isTied();
9450b57cec5SDimitry Andric                       });
9460b57cec5SDimitry Andric }
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric namespace {
9490b57cec5SDimitry Andric 
9500b57cec5SDimitry Andric   class DeadCodeElimination {
9510b57cec5SDimitry Andric   public:
9520b57cec5SDimitry Andric     DeadCodeElimination(MachineFunction &mf, MachineDominatorTree &mdt)
9530b57cec5SDimitry Andric       : MF(mf), HII(*MF.getSubtarget<HexagonSubtarget>().getInstrInfo()),
9540b57cec5SDimitry Andric         MDT(mdt), MRI(mf.getRegInfo()) {}
9550b57cec5SDimitry Andric 
9560b57cec5SDimitry Andric     bool run() {
9570b57cec5SDimitry Andric       return runOnNode(MDT.getRootNode());
9580b57cec5SDimitry Andric     }
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   private:
9610b57cec5SDimitry Andric     bool isDead(unsigned R) const;
9620b57cec5SDimitry Andric     bool runOnNode(MachineDomTreeNode *N);
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric     MachineFunction &MF;
9650b57cec5SDimitry Andric     const HexagonInstrInfo &HII;
9660b57cec5SDimitry Andric     MachineDominatorTree &MDT;
9670b57cec5SDimitry Andric     MachineRegisterInfo &MRI;
9680b57cec5SDimitry Andric   };
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric } // end anonymous namespace
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric bool DeadCodeElimination::isDead(unsigned R) const {
9730b57cec5SDimitry Andric   for (auto I = MRI.use_begin(R), E = MRI.use_end(); I != E; ++I) {
9740b57cec5SDimitry Andric     MachineInstr *UseI = I->getParent();
9750b57cec5SDimitry Andric     if (UseI->isDebugValue())
9760b57cec5SDimitry Andric       continue;
9770b57cec5SDimitry Andric     if (UseI->isPHI()) {
9780b57cec5SDimitry Andric       assert(!UseI->getOperand(0).getSubReg());
979*8bcb0991SDimitry Andric       Register DR = UseI->getOperand(0).getReg();
9800b57cec5SDimitry Andric       if (DR == R)
9810b57cec5SDimitry Andric         continue;
9820b57cec5SDimitry Andric     }
9830b57cec5SDimitry Andric     return false;
9840b57cec5SDimitry Andric   }
9850b57cec5SDimitry Andric   return true;
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric bool DeadCodeElimination::runOnNode(MachineDomTreeNode *N) {
9890b57cec5SDimitry Andric   bool Changed = false;
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric   for (auto *DTN : children<MachineDomTreeNode*>(N))
9920b57cec5SDimitry Andric     Changed |= runOnNode(DTN);
9930b57cec5SDimitry Andric 
9940b57cec5SDimitry Andric   MachineBasicBlock *B = N->getBlock();
9950b57cec5SDimitry Andric   std::vector<MachineInstr*> Instrs;
9960b57cec5SDimitry Andric   for (auto I = B->rbegin(), E = B->rend(); I != E; ++I)
9970b57cec5SDimitry Andric     Instrs.push_back(&*I);
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric   for (auto MI : Instrs) {
10000b57cec5SDimitry Andric     unsigned Opc = MI->getOpcode();
10010b57cec5SDimitry Andric     // Do not touch lifetime markers. This is why the target-independent DCE
10020b57cec5SDimitry Andric     // cannot be used.
10030b57cec5SDimitry Andric     if (Opc == TargetOpcode::LIFETIME_START ||
10040b57cec5SDimitry Andric         Opc == TargetOpcode::LIFETIME_END)
10050b57cec5SDimitry Andric       continue;
10060b57cec5SDimitry Andric     bool Store = false;
10070b57cec5SDimitry Andric     if (MI->isInlineAsm())
10080b57cec5SDimitry Andric       continue;
10090b57cec5SDimitry Andric     // Delete PHIs if possible.
10100b57cec5SDimitry Andric     if (!MI->isPHI() && !MI->isSafeToMove(nullptr, Store))
10110b57cec5SDimitry Andric       continue;
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric     bool AllDead = true;
10140b57cec5SDimitry Andric     SmallVector<unsigned,2> Regs;
10150b57cec5SDimitry Andric     for (auto &Op : MI->operands()) {
10160b57cec5SDimitry Andric       if (!Op.isReg() || !Op.isDef())
10170b57cec5SDimitry Andric         continue;
1018*8bcb0991SDimitry Andric       Register R = Op.getReg();
1019*8bcb0991SDimitry Andric       if (!Register::isVirtualRegister(R) || !isDead(R)) {
10200b57cec5SDimitry Andric         AllDead = false;
10210b57cec5SDimitry Andric         break;
10220b57cec5SDimitry Andric       }
10230b57cec5SDimitry Andric       Regs.push_back(R);
10240b57cec5SDimitry Andric     }
10250b57cec5SDimitry Andric     if (!AllDead)
10260b57cec5SDimitry Andric       continue;
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric     B->erase(MI);
10290b57cec5SDimitry Andric     for (unsigned i = 0, n = Regs.size(); i != n; ++i)
10300b57cec5SDimitry Andric       MRI.markUsesInDebugValueAsUndef(Regs[i]);
10310b57cec5SDimitry Andric     Changed = true;
10320b57cec5SDimitry Andric   }
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric   return Changed;
10350b57cec5SDimitry Andric }
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric namespace {
10380b57cec5SDimitry Andric 
10390b57cec5SDimitry Andric // Eliminate redundant instructions
10400b57cec5SDimitry Andric //
10410b57cec5SDimitry Andric // This transformation will identify instructions where the output register
10420b57cec5SDimitry Andric // is the same as one of its input registers. This only works on instructions
10430b57cec5SDimitry Andric // that define a single register (unlike post-increment loads, for example).
10440b57cec5SDimitry Andric // The equality check is actually more detailed: the code calculates which
10450b57cec5SDimitry Andric // bits of the output are used, and only compares these bits with the input
10460b57cec5SDimitry Andric // registers.
10470b57cec5SDimitry Andric // If the output matches an input, the instruction is replaced with COPY.
10480b57cec5SDimitry Andric // The copies will be removed by another transformation.
10490b57cec5SDimitry Andric   class RedundantInstrElimination : public Transformation {
10500b57cec5SDimitry Andric   public:
10510b57cec5SDimitry Andric     RedundantInstrElimination(BitTracker &bt, const HexagonInstrInfo &hii,
10520b57cec5SDimitry Andric           const HexagonRegisterInfo &hri, MachineRegisterInfo &mri)
10530b57cec5SDimitry Andric         : Transformation(true), HII(hii), HRI(hri), MRI(mri), BT(bt) {}
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric     bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric   private:
10580b57cec5SDimitry Andric     bool isLossyShiftLeft(const MachineInstr &MI, unsigned OpN,
10590b57cec5SDimitry Andric           unsigned &LostB, unsigned &LostE);
10600b57cec5SDimitry Andric     bool isLossyShiftRight(const MachineInstr &MI, unsigned OpN,
10610b57cec5SDimitry Andric           unsigned &LostB, unsigned &LostE);
10620b57cec5SDimitry Andric     bool computeUsedBits(unsigned Reg, BitVector &Bits);
10630b57cec5SDimitry Andric     bool computeUsedBits(const MachineInstr &MI, unsigned OpN, BitVector &Bits,
10640b57cec5SDimitry Andric           uint16_t Begin);
10650b57cec5SDimitry Andric     bool usedBitsEqual(BitTracker::RegisterRef RD, BitTracker::RegisterRef RS);
10660b57cec5SDimitry Andric 
10670b57cec5SDimitry Andric     const HexagonInstrInfo &HII;
10680b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
10690b57cec5SDimitry Andric     MachineRegisterInfo &MRI;
10700b57cec5SDimitry Andric     BitTracker &BT;
10710b57cec5SDimitry Andric   };
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric } // end anonymous namespace
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric // Check if the instruction is a lossy shift left, where the input being
10760b57cec5SDimitry Andric // shifted is the operand OpN of MI. If true, [LostB, LostE) is the range
10770b57cec5SDimitry Andric // of bit indices that are lost.
10780b57cec5SDimitry Andric bool RedundantInstrElimination::isLossyShiftLeft(const MachineInstr &MI,
10790b57cec5SDimitry Andric       unsigned OpN, unsigned &LostB, unsigned &LostE) {
10800b57cec5SDimitry Andric   using namespace Hexagon;
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
10830b57cec5SDimitry Andric   unsigned ImN, RegN, Width;
10840b57cec5SDimitry Andric   switch (Opc) {
10850b57cec5SDimitry Andric     case S2_asl_i_p:
10860b57cec5SDimitry Andric       ImN = 2;
10870b57cec5SDimitry Andric       RegN = 1;
10880b57cec5SDimitry Andric       Width = 64;
10890b57cec5SDimitry Andric       break;
10900b57cec5SDimitry Andric     case S2_asl_i_p_acc:
10910b57cec5SDimitry Andric     case S2_asl_i_p_and:
10920b57cec5SDimitry Andric     case S2_asl_i_p_nac:
10930b57cec5SDimitry Andric     case S2_asl_i_p_or:
10940b57cec5SDimitry Andric     case S2_asl_i_p_xacc:
10950b57cec5SDimitry Andric       ImN = 3;
10960b57cec5SDimitry Andric       RegN = 2;
10970b57cec5SDimitry Andric       Width = 64;
10980b57cec5SDimitry Andric       break;
10990b57cec5SDimitry Andric     case S2_asl_i_r:
11000b57cec5SDimitry Andric       ImN = 2;
11010b57cec5SDimitry Andric       RegN = 1;
11020b57cec5SDimitry Andric       Width = 32;
11030b57cec5SDimitry Andric       break;
11040b57cec5SDimitry Andric     case S2_addasl_rrri:
11050b57cec5SDimitry Andric     case S4_andi_asl_ri:
11060b57cec5SDimitry Andric     case S4_ori_asl_ri:
11070b57cec5SDimitry Andric     case S4_addi_asl_ri:
11080b57cec5SDimitry Andric     case S4_subi_asl_ri:
11090b57cec5SDimitry Andric     case S2_asl_i_r_acc:
11100b57cec5SDimitry Andric     case S2_asl_i_r_and:
11110b57cec5SDimitry Andric     case S2_asl_i_r_nac:
11120b57cec5SDimitry Andric     case S2_asl_i_r_or:
11130b57cec5SDimitry Andric     case S2_asl_i_r_sat:
11140b57cec5SDimitry Andric     case S2_asl_i_r_xacc:
11150b57cec5SDimitry Andric       ImN = 3;
11160b57cec5SDimitry Andric       RegN = 2;
11170b57cec5SDimitry Andric       Width = 32;
11180b57cec5SDimitry Andric       break;
11190b57cec5SDimitry Andric     default:
11200b57cec5SDimitry Andric       return false;
11210b57cec5SDimitry Andric   }
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric   if (RegN != OpN)
11240b57cec5SDimitry Andric     return false;
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric   assert(MI.getOperand(ImN).isImm());
11270b57cec5SDimitry Andric   unsigned S = MI.getOperand(ImN).getImm();
11280b57cec5SDimitry Andric   if (S == 0)
11290b57cec5SDimitry Andric     return false;
11300b57cec5SDimitry Andric   LostB = Width-S;
11310b57cec5SDimitry Andric   LostE = Width;
11320b57cec5SDimitry Andric   return true;
11330b57cec5SDimitry Andric }
11340b57cec5SDimitry Andric 
11350b57cec5SDimitry Andric // Check if the instruction is a lossy shift right, where the input being
11360b57cec5SDimitry Andric // shifted is the operand OpN of MI. If true, [LostB, LostE) is the range
11370b57cec5SDimitry Andric // of bit indices that are lost.
11380b57cec5SDimitry Andric bool RedundantInstrElimination::isLossyShiftRight(const MachineInstr &MI,
11390b57cec5SDimitry Andric       unsigned OpN, unsigned &LostB, unsigned &LostE) {
11400b57cec5SDimitry Andric   using namespace Hexagon;
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
11430b57cec5SDimitry Andric   unsigned ImN, RegN;
11440b57cec5SDimitry Andric   switch (Opc) {
11450b57cec5SDimitry Andric     case S2_asr_i_p:
11460b57cec5SDimitry Andric     case S2_lsr_i_p:
11470b57cec5SDimitry Andric       ImN = 2;
11480b57cec5SDimitry Andric       RegN = 1;
11490b57cec5SDimitry Andric       break;
11500b57cec5SDimitry Andric     case S2_asr_i_p_acc:
11510b57cec5SDimitry Andric     case S2_asr_i_p_and:
11520b57cec5SDimitry Andric     case S2_asr_i_p_nac:
11530b57cec5SDimitry Andric     case S2_asr_i_p_or:
11540b57cec5SDimitry Andric     case S2_lsr_i_p_acc:
11550b57cec5SDimitry Andric     case S2_lsr_i_p_and:
11560b57cec5SDimitry Andric     case S2_lsr_i_p_nac:
11570b57cec5SDimitry Andric     case S2_lsr_i_p_or:
11580b57cec5SDimitry Andric     case S2_lsr_i_p_xacc:
11590b57cec5SDimitry Andric       ImN = 3;
11600b57cec5SDimitry Andric       RegN = 2;
11610b57cec5SDimitry Andric       break;
11620b57cec5SDimitry Andric     case S2_asr_i_r:
11630b57cec5SDimitry Andric     case S2_lsr_i_r:
11640b57cec5SDimitry Andric       ImN = 2;
11650b57cec5SDimitry Andric       RegN = 1;
11660b57cec5SDimitry Andric       break;
11670b57cec5SDimitry Andric     case S4_andi_lsr_ri:
11680b57cec5SDimitry Andric     case S4_ori_lsr_ri:
11690b57cec5SDimitry Andric     case S4_addi_lsr_ri:
11700b57cec5SDimitry Andric     case S4_subi_lsr_ri:
11710b57cec5SDimitry Andric     case S2_asr_i_r_acc:
11720b57cec5SDimitry Andric     case S2_asr_i_r_and:
11730b57cec5SDimitry Andric     case S2_asr_i_r_nac:
11740b57cec5SDimitry Andric     case S2_asr_i_r_or:
11750b57cec5SDimitry Andric     case S2_lsr_i_r_acc:
11760b57cec5SDimitry Andric     case S2_lsr_i_r_and:
11770b57cec5SDimitry Andric     case S2_lsr_i_r_nac:
11780b57cec5SDimitry Andric     case S2_lsr_i_r_or:
11790b57cec5SDimitry Andric     case S2_lsr_i_r_xacc:
11800b57cec5SDimitry Andric       ImN = 3;
11810b57cec5SDimitry Andric       RegN = 2;
11820b57cec5SDimitry Andric       break;
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric     default:
11850b57cec5SDimitry Andric       return false;
11860b57cec5SDimitry Andric   }
11870b57cec5SDimitry Andric 
11880b57cec5SDimitry Andric   if (RegN != OpN)
11890b57cec5SDimitry Andric     return false;
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric   assert(MI.getOperand(ImN).isImm());
11920b57cec5SDimitry Andric   unsigned S = MI.getOperand(ImN).getImm();
11930b57cec5SDimitry Andric   LostB = 0;
11940b57cec5SDimitry Andric   LostE = S;
11950b57cec5SDimitry Andric   return true;
11960b57cec5SDimitry Andric }
11970b57cec5SDimitry Andric 
11980b57cec5SDimitry Andric // Calculate the bit vector that corresponds to the used bits of register Reg.
11990b57cec5SDimitry Andric // The vector Bits has the same size, as the size of Reg in bits. If the cal-
12000b57cec5SDimitry Andric // culation fails (i.e. the used bits are unknown), it returns false. Other-
12010b57cec5SDimitry Andric // wise, it returns true and sets the corresponding bits in Bits.
12020b57cec5SDimitry Andric bool RedundantInstrElimination::computeUsedBits(unsigned Reg, BitVector &Bits) {
12030b57cec5SDimitry Andric   BitVector Used(Bits.size());
12040b57cec5SDimitry Andric   RegisterSet Visited;
12050b57cec5SDimitry Andric   std::vector<unsigned> Pending;
12060b57cec5SDimitry Andric   Pending.push_back(Reg);
12070b57cec5SDimitry Andric 
12080b57cec5SDimitry Andric   for (unsigned i = 0; i < Pending.size(); ++i) {
12090b57cec5SDimitry Andric     unsigned R = Pending[i];
12100b57cec5SDimitry Andric     if (Visited.has(R))
12110b57cec5SDimitry Andric       continue;
12120b57cec5SDimitry Andric     Visited.insert(R);
12130b57cec5SDimitry Andric     for (auto I = MRI.use_begin(R), E = MRI.use_end(); I != E; ++I) {
12140b57cec5SDimitry Andric       BitTracker::RegisterRef UR = *I;
12150b57cec5SDimitry Andric       unsigned B, W;
12160b57cec5SDimitry Andric       if (!HBS::getSubregMask(UR, B, W, MRI))
12170b57cec5SDimitry Andric         return false;
12180b57cec5SDimitry Andric       MachineInstr &UseI = *I->getParent();
12190b57cec5SDimitry Andric       if (UseI.isPHI() || UseI.isCopy()) {
1220*8bcb0991SDimitry Andric         Register DefR = UseI.getOperand(0).getReg();
1221*8bcb0991SDimitry Andric         if (!Register::isVirtualRegister(DefR))
12220b57cec5SDimitry Andric           return false;
12230b57cec5SDimitry Andric         Pending.push_back(DefR);
12240b57cec5SDimitry Andric       } else {
12250b57cec5SDimitry Andric         if (!computeUsedBits(UseI, I.getOperandNo(), Used, B))
12260b57cec5SDimitry Andric           return false;
12270b57cec5SDimitry Andric       }
12280b57cec5SDimitry Andric     }
12290b57cec5SDimitry Andric   }
12300b57cec5SDimitry Andric   Bits |= Used;
12310b57cec5SDimitry Andric   return true;
12320b57cec5SDimitry Andric }
12330b57cec5SDimitry Andric 
12340b57cec5SDimitry Andric // Calculate the bits used by instruction MI in a register in operand OpN.
12350b57cec5SDimitry Andric // Return true/false if the calculation succeeds/fails. If is succeeds, set
12360b57cec5SDimitry Andric // used bits in Bits. This function does not reset any bits in Bits, so
12370b57cec5SDimitry Andric // subsequent calls over different instructions will result in the union
12380b57cec5SDimitry Andric // of the used bits in all these instructions.
12390b57cec5SDimitry Andric // The register in question may be used with a sub-register, whereas Bits
12400b57cec5SDimitry Andric // holds the bits for the entire register. To keep track of that, the
12410b57cec5SDimitry Andric // argument Begin indicates where in Bits is the lowest-significant bit
12420b57cec5SDimitry Andric // of the register used in operand OpN. For example, in instruction:
12430b57cec5SDimitry Andric //   %1 = S2_lsr_i_r %2:isub_hi, 10
12440b57cec5SDimitry Andric // the operand 1 is a 32-bit register, which happens to be a subregister
12450b57cec5SDimitry Andric // of the 64-bit register %2, and that subregister starts at position 32.
12460b57cec5SDimitry Andric // In this case Begin=32, since Bits[32] would be the lowest-significant bit
12470b57cec5SDimitry Andric // of %2:isub_hi.
12480b57cec5SDimitry Andric bool RedundantInstrElimination::computeUsedBits(const MachineInstr &MI,
12490b57cec5SDimitry Andric       unsigned OpN, BitVector &Bits, uint16_t Begin) {
12500b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
12510b57cec5SDimitry Andric   BitVector T(Bits.size());
12520b57cec5SDimitry Andric   bool GotBits = HBS::getUsedBits(Opc, OpN, T, Begin, HII);
12530b57cec5SDimitry Andric   // Even if we don't have bits yet, we could still provide some information
12540b57cec5SDimitry Andric   // if the instruction is a lossy shift: the lost bits will be marked as
12550b57cec5SDimitry Andric   // not used.
12560b57cec5SDimitry Andric   unsigned LB, LE;
12570b57cec5SDimitry Andric   if (isLossyShiftLeft(MI, OpN, LB, LE) || isLossyShiftRight(MI, OpN, LB, LE)) {
12580b57cec5SDimitry Andric     assert(MI.getOperand(OpN).isReg());
12590b57cec5SDimitry Andric     BitTracker::RegisterRef RR = MI.getOperand(OpN);
12600b57cec5SDimitry Andric     const TargetRegisterClass *RC = HBS::getFinalVRegClass(RR, MRI);
12610b57cec5SDimitry Andric     uint16_t Width = HRI.getRegSizeInBits(*RC);
12620b57cec5SDimitry Andric 
12630b57cec5SDimitry Andric     if (!GotBits)
12640b57cec5SDimitry Andric       T.set(Begin, Begin+Width);
12650b57cec5SDimitry Andric     assert(LB <= LE && LB < Width && LE <= Width);
12660b57cec5SDimitry Andric     T.reset(Begin+LB, Begin+LE);
12670b57cec5SDimitry Andric     GotBits = true;
12680b57cec5SDimitry Andric   }
12690b57cec5SDimitry Andric   if (GotBits)
12700b57cec5SDimitry Andric     Bits |= T;
12710b57cec5SDimitry Andric   return GotBits;
12720b57cec5SDimitry Andric }
12730b57cec5SDimitry Andric 
12740b57cec5SDimitry Andric // Calculates the used bits in RD ("defined register"), and checks if these
12750b57cec5SDimitry Andric // bits in RS ("used register") and RD are identical.
12760b57cec5SDimitry Andric bool RedundantInstrElimination::usedBitsEqual(BitTracker::RegisterRef RD,
12770b57cec5SDimitry Andric       BitTracker::RegisterRef RS) {
12780b57cec5SDimitry Andric   const BitTracker::RegisterCell &DC = BT.lookup(RD.Reg);
12790b57cec5SDimitry Andric   const BitTracker::RegisterCell &SC = BT.lookup(RS.Reg);
12800b57cec5SDimitry Andric 
12810b57cec5SDimitry Andric   unsigned DB, DW;
12820b57cec5SDimitry Andric   if (!HBS::getSubregMask(RD, DB, DW, MRI))
12830b57cec5SDimitry Andric     return false;
12840b57cec5SDimitry Andric   unsigned SB, SW;
12850b57cec5SDimitry Andric   if (!HBS::getSubregMask(RS, SB, SW, MRI))
12860b57cec5SDimitry Andric     return false;
12870b57cec5SDimitry Andric   if (SW != DW)
12880b57cec5SDimitry Andric     return false;
12890b57cec5SDimitry Andric 
12900b57cec5SDimitry Andric   BitVector Used(DC.width());
12910b57cec5SDimitry Andric   if (!computeUsedBits(RD.Reg, Used))
12920b57cec5SDimitry Andric     return false;
12930b57cec5SDimitry Andric 
12940b57cec5SDimitry Andric   for (unsigned i = 0; i != DW; ++i)
12950b57cec5SDimitry Andric     if (Used[i+DB] && DC[DB+i] != SC[SB+i])
12960b57cec5SDimitry Andric       return false;
12970b57cec5SDimitry Andric   return true;
12980b57cec5SDimitry Andric }
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric bool RedundantInstrElimination::processBlock(MachineBasicBlock &B,
13010b57cec5SDimitry Andric       const RegisterSet&) {
13020b57cec5SDimitry Andric   if (!BT.reached(&B))
13030b57cec5SDimitry Andric     return false;
13040b57cec5SDimitry Andric   bool Changed = false;
13050b57cec5SDimitry Andric 
13060b57cec5SDimitry Andric   for (auto I = B.begin(), E = B.end(), NextI = I; I != E; ++I) {
13070b57cec5SDimitry Andric     NextI = std::next(I);
13080b57cec5SDimitry Andric     MachineInstr *MI = &*I;
13090b57cec5SDimitry Andric 
13100b57cec5SDimitry Andric     if (MI->getOpcode() == TargetOpcode::COPY)
13110b57cec5SDimitry Andric       continue;
13120b57cec5SDimitry Andric     if (MI->isPHI() || MI->hasUnmodeledSideEffects() || MI->isInlineAsm())
13130b57cec5SDimitry Andric       continue;
13140b57cec5SDimitry Andric     unsigned NumD = MI->getDesc().getNumDefs();
13150b57cec5SDimitry Andric     if (NumD != 1)
13160b57cec5SDimitry Andric       continue;
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric     BitTracker::RegisterRef RD = MI->getOperand(0);
13190b57cec5SDimitry Andric     if (!BT.has(RD.Reg))
13200b57cec5SDimitry Andric       continue;
13210b57cec5SDimitry Andric     const BitTracker::RegisterCell &DC = BT.lookup(RD.Reg);
13220b57cec5SDimitry Andric     auto At = MachineBasicBlock::iterator(MI);
13230b57cec5SDimitry Andric 
13240b57cec5SDimitry Andric     // Find a source operand that is equal to the result.
13250b57cec5SDimitry Andric     for (auto &Op : MI->uses()) {
13260b57cec5SDimitry Andric       if (!Op.isReg())
13270b57cec5SDimitry Andric         continue;
13280b57cec5SDimitry Andric       BitTracker::RegisterRef RS = Op;
13290b57cec5SDimitry Andric       if (!BT.has(RS.Reg))
13300b57cec5SDimitry Andric         continue;
13310b57cec5SDimitry Andric       if (!HBS::isTransparentCopy(RD, RS, MRI))
13320b57cec5SDimitry Andric         continue;
13330b57cec5SDimitry Andric 
13340b57cec5SDimitry Andric       unsigned BN, BW;
13350b57cec5SDimitry Andric       if (!HBS::getSubregMask(RS, BN, BW, MRI))
13360b57cec5SDimitry Andric         continue;
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric       const BitTracker::RegisterCell &SC = BT.lookup(RS.Reg);
13390b57cec5SDimitry Andric       if (!usedBitsEqual(RD, RS) && !HBS::isEqual(DC, 0, SC, BN, BW))
13400b57cec5SDimitry Andric         continue;
13410b57cec5SDimitry Andric 
13420b57cec5SDimitry Andric       // If found, replace the instruction with a COPY.
13430b57cec5SDimitry Andric       const DebugLoc &DL = MI->getDebugLoc();
13440b57cec5SDimitry Andric       const TargetRegisterClass *FRC = HBS::getFinalVRegClass(RD, MRI);
1345*8bcb0991SDimitry Andric       Register NewR = MRI.createVirtualRegister(FRC);
13460b57cec5SDimitry Andric       MachineInstr *CopyI =
13470b57cec5SDimitry Andric           BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)
13480b57cec5SDimitry Andric             .addReg(RS.Reg, 0, RS.Sub);
13490b57cec5SDimitry Andric       HBS::replaceSubWithSub(RD.Reg, RD.Sub, NewR, 0, MRI);
13500b57cec5SDimitry Andric       // This pass can create copies between registers that don't have the
13510b57cec5SDimitry Andric       // exact same values. Updating the tracker has to involve updating
13520b57cec5SDimitry Andric       // all dependent cells. Example:
13530b57cec5SDimitry Andric       //   %1  = inst %2     ; %1 != %2, but used bits are equal
13540b57cec5SDimitry Andric       //
13550b57cec5SDimitry Andric       //   %3  = copy %2     ; <- inserted
13560b57cec5SDimitry Andric       //   ... = %3          ; <- replaced from %2
13570b57cec5SDimitry Andric       // Indirectly, we can create a "copy" between %1 and %2 even
13580b57cec5SDimitry Andric       // though their exact values do not match.
13590b57cec5SDimitry Andric       BT.visit(*CopyI);
13600b57cec5SDimitry Andric       Changed = true;
13610b57cec5SDimitry Andric       break;
13620b57cec5SDimitry Andric     }
13630b57cec5SDimitry Andric   }
13640b57cec5SDimitry Andric 
13650b57cec5SDimitry Andric   return Changed;
13660b57cec5SDimitry Andric }
13670b57cec5SDimitry Andric 
13680b57cec5SDimitry Andric namespace {
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric // Recognize instructions that produce constant values known at compile-time.
13710b57cec5SDimitry Andric // Replace them with register definitions that load these constants directly.
13720b57cec5SDimitry Andric   class ConstGeneration : public Transformation {
13730b57cec5SDimitry Andric   public:
13740b57cec5SDimitry Andric     ConstGeneration(BitTracker &bt, const HexagonInstrInfo &hii,
13750b57cec5SDimitry Andric         MachineRegisterInfo &mri)
13760b57cec5SDimitry Andric       : Transformation(true), HII(hii), MRI(mri), BT(bt) {}
13770b57cec5SDimitry Andric 
13780b57cec5SDimitry Andric     bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
13790b57cec5SDimitry Andric     static bool isTfrConst(const MachineInstr &MI);
13800b57cec5SDimitry Andric 
13810b57cec5SDimitry Andric   private:
13820b57cec5SDimitry Andric     unsigned genTfrConst(const TargetRegisterClass *RC, int64_t C,
13830b57cec5SDimitry Andric         MachineBasicBlock &B, MachineBasicBlock::iterator At, DebugLoc &DL);
13840b57cec5SDimitry Andric 
13850b57cec5SDimitry Andric     const HexagonInstrInfo &HII;
13860b57cec5SDimitry Andric     MachineRegisterInfo &MRI;
13870b57cec5SDimitry Andric     BitTracker &BT;
13880b57cec5SDimitry Andric   };
13890b57cec5SDimitry Andric 
13900b57cec5SDimitry Andric } // end anonymous namespace
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric bool ConstGeneration::isTfrConst(const MachineInstr &MI) {
13930b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
13940b57cec5SDimitry Andric   switch (Opc) {
13950b57cec5SDimitry Andric     case Hexagon::A2_combineii:
13960b57cec5SDimitry Andric     case Hexagon::A4_combineii:
13970b57cec5SDimitry Andric     case Hexagon::A2_tfrsi:
13980b57cec5SDimitry Andric     case Hexagon::A2_tfrpi:
13990b57cec5SDimitry Andric     case Hexagon::PS_true:
14000b57cec5SDimitry Andric     case Hexagon::PS_false:
14010b57cec5SDimitry Andric     case Hexagon::CONST32:
14020b57cec5SDimitry Andric     case Hexagon::CONST64:
14030b57cec5SDimitry Andric       return true;
14040b57cec5SDimitry Andric   }
14050b57cec5SDimitry Andric   return false;
14060b57cec5SDimitry Andric }
14070b57cec5SDimitry Andric 
14080b57cec5SDimitry Andric // Generate a transfer-immediate instruction that is appropriate for the
14090b57cec5SDimitry Andric // register class and the actual value being transferred.
14100b57cec5SDimitry Andric unsigned ConstGeneration::genTfrConst(const TargetRegisterClass *RC, int64_t C,
14110b57cec5SDimitry Andric       MachineBasicBlock &B, MachineBasicBlock::iterator At, DebugLoc &DL) {
1412*8bcb0991SDimitry Andric   Register Reg = MRI.createVirtualRegister(RC);
14130b57cec5SDimitry Andric   if (RC == &Hexagon::IntRegsRegClass) {
14140b57cec5SDimitry Andric     BuildMI(B, At, DL, HII.get(Hexagon::A2_tfrsi), Reg)
14150b57cec5SDimitry Andric         .addImm(int32_t(C));
14160b57cec5SDimitry Andric     return Reg;
14170b57cec5SDimitry Andric   }
14180b57cec5SDimitry Andric 
14190b57cec5SDimitry Andric   if (RC == &Hexagon::DoubleRegsRegClass) {
14200b57cec5SDimitry Andric     if (isInt<8>(C)) {
14210b57cec5SDimitry Andric       BuildMI(B, At, DL, HII.get(Hexagon::A2_tfrpi), Reg)
14220b57cec5SDimitry Andric           .addImm(C);
14230b57cec5SDimitry Andric       return Reg;
14240b57cec5SDimitry Andric     }
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric     unsigned Lo = Lo_32(C), Hi = Hi_32(C);
14270b57cec5SDimitry Andric     if (isInt<8>(Lo) || isInt<8>(Hi)) {
14280b57cec5SDimitry Andric       unsigned Opc = isInt<8>(Lo) ? Hexagon::A2_combineii
14290b57cec5SDimitry Andric                                   : Hexagon::A4_combineii;
14300b57cec5SDimitry Andric       BuildMI(B, At, DL, HII.get(Opc), Reg)
14310b57cec5SDimitry Andric           .addImm(int32_t(Hi))
14320b57cec5SDimitry Andric           .addImm(int32_t(Lo));
14330b57cec5SDimitry Andric       return Reg;
14340b57cec5SDimitry Andric     }
14350b57cec5SDimitry Andric 
14360b57cec5SDimitry Andric     BuildMI(B, At, DL, HII.get(Hexagon::CONST64), Reg)
14370b57cec5SDimitry Andric         .addImm(C);
14380b57cec5SDimitry Andric     return Reg;
14390b57cec5SDimitry Andric   }
14400b57cec5SDimitry Andric 
14410b57cec5SDimitry Andric   if (RC == &Hexagon::PredRegsRegClass) {
14420b57cec5SDimitry Andric     unsigned Opc;
14430b57cec5SDimitry Andric     if (C == 0)
14440b57cec5SDimitry Andric       Opc = Hexagon::PS_false;
14450b57cec5SDimitry Andric     else if ((C & 0xFF) == 0xFF)
14460b57cec5SDimitry Andric       Opc = Hexagon::PS_true;
14470b57cec5SDimitry Andric     else
14480b57cec5SDimitry Andric       return 0;
14490b57cec5SDimitry Andric     BuildMI(B, At, DL, HII.get(Opc), Reg);
14500b57cec5SDimitry Andric     return Reg;
14510b57cec5SDimitry Andric   }
14520b57cec5SDimitry Andric 
14530b57cec5SDimitry Andric   return 0;
14540b57cec5SDimitry Andric }
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric bool ConstGeneration::processBlock(MachineBasicBlock &B, const RegisterSet&) {
14570b57cec5SDimitry Andric   if (!BT.reached(&B))
14580b57cec5SDimitry Andric     return false;
14590b57cec5SDimitry Andric   bool Changed = false;
14600b57cec5SDimitry Andric   RegisterSet Defs;
14610b57cec5SDimitry Andric 
14620b57cec5SDimitry Andric   for (auto I = B.begin(), E = B.end(); I != E; ++I) {
14630b57cec5SDimitry Andric     if (isTfrConst(*I))
14640b57cec5SDimitry Andric       continue;
14650b57cec5SDimitry Andric     Defs.clear();
14660b57cec5SDimitry Andric     HBS::getInstrDefs(*I, Defs);
14670b57cec5SDimitry Andric     if (Defs.count() != 1)
14680b57cec5SDimitry Andric       continue;
14690b57cec5SDimitry Andric     unsigned DR = Defs.find_first();
1470*8bcb0991SDimitry Andric     if (!Register::isVirtualRegister(DR))
14710b57cec5SDimitry Andric       continue;
14720b57cec5SDimitry Andric     uint64_t U;
14730b57cec5SDimitry Andric     const BitTracker::RegisterCell &DRC = BT.lookup(DR);
14740b57cec5SDimitry Andric     if (HBS::getConst(DRC, 0, DRC.width(), U)) {
14750b57cec5SDimitry Andric       int64_t C = U;
14760b57cec5SDimitry Andric       DebugLoc DL = I->getDebugLoc();
14770b57cec5SDimitry Andric       auto At = I->isPHI() ? B.getFirstNonPHI() : I;
14780b57cec5SDimitry Andric       unsigned ImmReg = genTfrConst(MRI.getRegClass(DR), C, B, At, DL);
14790b57cec5SDimitry Andric       if (ImmReg) {
14800b57cec5SDimitry Andric         HBS::replaceReg(DR, ImmReg, MRI);
14810b57cec5SDimitry Andric         BT.put(ImmReg, DRC);
14820b57cec5SDimitry Andric         Changed = true;
14830b57cec5SDimitry Andric       }
14840b57cec5SDimitry Andric     }
14850b57cec5SDimitry Andric   }
14860b57cec5SDimitry Andric   return Changed;
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric namespace {
14900b57cec5SDimitry Andric 
14910b57cec5SDimitry Andric // Identify pairs of available registers which hold identical values.
14920b57cec5SDimitry Andric // In such cases, only one of them needs to be calculated, the other one
14930b57cec5SDimitry Andric // will be defined as a copy of the first.
14940b57cec5SDimitry Andric   class CopyGeneration : public Transformation {
14950b57cec5SDimitry Andric   public:
14960b57cec5SDimitry Andric     CopyGeneration(BitTracker &bt, const HexagonInstrInfo &hii,
14970b57cec5SDimitry Andric         const HexagonRegisterInfo &hri, MachineRegisterInfo &mri)
14980b57cec5SDimitry Andric       : Transformation(true), HII(hii), HRI(hri), MRI(mri), BT(bt) {}
14990b57cec5SDimitry Andric 
15000b57cec5SDimitry Andric     bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
15010b57cec5SDimitry Andric 
15020b57cec5SDimitry Andric   private:
15030b57cec5SDimitry Andric     bool findMatch(const BitTracker::RegisterRef &Inp,
15040b57cec5SDimitry Andric         BitTracker::RegisterRef &Out, const RegisterSet &AVs);
15050b57cec5SDimitry Andric 
15060b57cec5SDimitry Andric     const HexagonInstrInfo &HII;
15070b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
15080b57cec5SDimitry Andric     MachineRegisterInfo &MRI;
15090b57cec5SDimitry Andric     BitTracker &BT;
15100b57cec5SDimitry Andric     RegisterSet Forbidden;
15110b57cec5SDimitry Andric   };
15120b57cec5SDimitry Andric 
15130b57cec5SDimitry Andric // Eliminate register copies RD = RS, by replacing the uses of RD with
15140b57cec5SDimitry Andric // with uses of RS.
15150b57cec5SDimitry Andric   class CopyPropagation : public Transformation {
15160b57cec5SDimitry Andric   public:
15170b57cec5SDimitry Andric     CopyPropagation(const HexagonRegisterInfo &hri, MachineRegisterInfo &mri)
15180b57cec5SDimitry Andric         : Transformation(false), HRI(hri), MRI(mri) {}
15190b57cec5SDimitry Andric 
15200b57cec5SDimitry Andric     bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
15210b57cec5SDimitry Andric 
15220b57cec5SDimitry Andric     static bool isCopyReg(unsigned Opc, bool NoConv);
15230b57cec5SDimitry Andric 
15240b57cec5SDimitry Andric   private:
15250b57cec5SDimitry Andric     bool propagateRegCopy(MachineInstr &MI);
15260b57cec5SDimitry Andric 
15270b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
15280b57cec5SDimitry Andric     MachineRegisterInfo &MRI;
15290b57cec5SDimitry Andric   };
15300b57cec5SDimitry Andric 
15310b57cec5SDimitry Andric } // end anonymous namespace
15320b57cec5SDimitry Andric 
15330b57cec5SDimitry Andric /// Check if there is a register in AVs that is identical to Inp. If so,
15340b57cec5SDimitry Andric /// set Out to the found register. The output may be a pair Reg:Sub.
15350b57cec5SDimitry Andric bool CopyGeneration::findMatch(const BitTracker::RegisterRef &Inp,
15360b57cec5SDimitry Andric       BitTracker::RegisterRef &Out, const RegisterSet &AVs) {
15370b57cec5SDimitry Andric   if (!BT.has(Inp.Reg))
15380b57cec5SDimitry Andric     return false;
15390b57cec5SDimitry Andric   const BitTracker::RegisterCell &InpRC = BT.lookup(Inp.Reg);
15400b57cec5SDimitry Andric   auto *FRC = HBS::getFinalVRegClass(Inp, MRI);
15410b57cec5SDimitry Andric   unsigned B, W;
15420b57cec5SDimitry Andric   if (!HBS::getSubregMask(Inp, B, W, MRI))
15430b57cec5SDimitry Andric     return false;
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric   for (unsigned R = AVs.find_first(); R; R = AVs.find_next(R)) {
15460b57cec5SDimitry Andric     if (!BT.has(R) || Forbidden[R])
15470b57cec5SDimitry Andric       continue;
15480b57cec5SDimitry Andric     const BitTracker::RegisterCell &RC = BT.lookup(R);
15490b57cec5SDimitry Andric     unsigned RW = RC.width();
15500b57cec5SDimitry Andric     if (W == RW) {
15510b57cec5SDimitry Andric       if (FRC != MRI.getRegClass(R))
15520b57cec5SDimitry Andric         continue;
15530b57cec5SDimitry Andric       if (!HBS::isTransparentCopy(R, Inp, MRI))
15540b57cec5SDimitry Andric         continue;
15550b57cec5SDimitry Andric       if (!HBS::isEqual(InpRC, B, RC, 0, W))
15560b57cec5SDimitry Andric         continue;
15570b57cec5SDimitry Andric       Out.Reg = R;
15580b57cec5SDimitry Andric       Out.Sub = 0;
15590b57cec5SDimitry Andric       return true;
15600b57cec5SDimitry Andric     }
15610b57cec5SDimitry Andric     // Check if there is a super-register, whose part (with a subregister)
15620b57cec5SDimitry Andric     // is equal to the input.
15630b57cec5SDimitry Andric     // Only do double registers for now.
15640b57cec5SDimitry Andric     if (W*2 != RW)
15650b57cec5SDimitry Andric       continue;
15660b57cec5SDimitry Andric     if (MRI.getRegClass(R) != &Hexagon::DoubleRegsRegClass)
15670b57cec5SDimitry Andric       continue;
15680b57cec5SDimitry Andric 
15690b57cec5SDimitry Andric     if (HBS::isEqual(InpRC, B, RC, 0, W))
15700b57cec5SDimitry Andric       Out.Sub = Hexagon::isub_lo;
15710b57cec5SDimitry Andric     else if (HBS::isEqual(InpRC, B, RC, W, W))
15720b57cec5SDimitry Andric       Out.Sub = Hexagon::isub_hi;
15730b57cec5SDimitry Andric     else
15740b57cec5SDimitry Andric       continue;
15750b57cec5SDimitry Andric     Out.Reg = R;
15760b57cec5SDimitry Andric     if (HBS::isTransparentCopy(Out, Inp, MRI))
15770b57cec5SDimitry Andric       return true;
15780b57cec5SDimitry Andric   }
15790b57cec5SDimitry Andric   return false;
15800b57cec5SDimitry Andric }
15810b57cec5SDimitry Andric 
15820b57cec5SDimitry Andric bool CopyGeneration::processBlock(MachineBasicBlock &B,
15830b57cec5SDimitry Andric       const RegisterSet &AVs) {
15840b57cec5SDimitry Andric   if (!BT.reached(&B))
15850b57cec5SDimitry Andric     return false;
15860b57cec5SDimitry Andric   RegisterSet AVB(AVs);
15870b57cec5SDimitry Andric   bool Changed = false;
15880b57cec5SDimitry Andric   RegisterSet Defs;
15890b57cec5SDimitry Andric 
15900b57cec5SDimitry Andric   for (auto I = B.begin(), E = B.end(), NextI = I; I != E;
15910b57cec5SDimitry Andric        ++I, AVB.insert(Defs)) {
15920b57cec5SDimitry Andric     NextI = std::next(I);
15930b57cec5SDimitry Andric     Defs.clear();
15940b57cec5SDimitry Andric     HBS::getInstrDefs(*I, Defs);
15950b57cec5SDimitry Andric 
15960b57cec5SDimitry Andric     unsigned Opc = I->getOpcode();
15970b57cec5SDimitry Andric     if (CopyPropagation::isCopyReg(Opc, false) ||
15980b57cec5SDimitry Andric         ConstGeneration::isTfrConst(*I))
15990b57cec5SDimitry Andric       continue;
16000b57cec5SDimitry Andric 
16010b57cec5SDimitry Andric     DebugLoc DL = I->getDebugLoc();
16020b57cec5SDimitry Andric     auto At = I->isPHI() ? B.getFirstNonPHI() : I;
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric     for (unsigned R = Defs.find_first(); R; R = Defs.find_next(R)) {
16050b57cec5SDimitry Andric       BitTracker::RegisterRef MR;
16060b57cec5SDimitry Andric       auto *FRC = HBS::getFinalVRegClass(R, MRI);
16070b57cec5SDimitry Andric 
16080b57cec5SDimitry Andric       if (findMatch(R, MR, AVB)) {
1609*8bcb0991SDimitry Andric         Register NewR = MRI.createVirtualRegister(FRC);
16100b57cec5SDimitry Andric         BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)
16110b57cec5SDimitry Andric           .addReg(MR.Reg, 0, MR.Sub);
16120b57cec5SDimitry Andric         BT.put(BitTracker::RegisterRef(NewR), BT.get(MR));
16130b57cec5SDimitry Andric         HBS::replaceReg(R, NewR, MRI);
16140b57cec5SDimitry Andric         Forbidden.insert(R);
16150b57cec5SDimitry Andric         continue;
16160b57cec5SDimitry Andric       }
16170b57cec5SDimitry Andric 
16180b57cec5SDimitry Andric       if (FRC == &Hexagon::DoubleRegsRegClass ||
16190b57cec5SDimitry Andric           FRC == &Hexagon::HvxWRRegClass) {
16200b57cec5SDimitry Andric         // Try to generate REG_SEQUENCE.
16210b57cec5SDimitry Andric         unsigned SubLo = HRI.getHexagonSubRegIndex(*FRC, Hexagon::ps_sub_lo);
16220b57cec5SDimitry Andric         unsigned SubHi = HRI.getHexagonSubRegIndex(*FRC, Hexagon::ps_sub_hi);
16230b57cec5SDimitry Andric         BitTracker::RegisterRef TL = { R, SubLo };
16240b57cec5SDimitry Andric         BitTracker::RegisterRef TH = { R, SubHi };
16250b57cec5SDimitry Andric         BitTracker::RegisterRef ML, MH;
16260b57cec5SDimitry Andric         if (findMatch(TL, ML, AVB) && findMatch(TH, MH, AVB)) {
16270b57cec5SDimitry Andric           auto *FRC = HBS::getFinalVRegClass(R, MRI);
1628*8bcb0991SDimitry Andric           Register NewR = MRI.createVirtualRegister(FRC);
16290b57cec5SDimitry Andric           BuildMI(B, At, DL, HII.get(TargetOpcode::REG_SEQUENCE), NewR)
16300b57cec5SDimitry Andric             .addReg(ML.Reg, 0, ML.Sub)
16310b57cec5SDimitry Andric             .addImm(SubLo)
16320b57cec5SDimitry Andric             .addReg(MH.Reg, 0, MH.Sub)
16330b57cec5SDimitry Andric             .addImm(SubHi);
16340b57cec5SDimitry Andric           BT.put(BitTracker::RegisterRef(NewR), BT.get(R));
16350b57cec5SDimitry Andric           HBS::replaceReg(R, NewR, MRI);
16360b57cec5SDimitry Andric           Forbidden.insert(R);
16370b57cec5SDimitry Andric         }
16380b57cec5SDimitry Andric       }
16390b57cec5SDimitry Andric     }
16400b57cec5SDimitry Andric   }
16410b57cec5SDimitry Andric 
16420b57cec5SDimitry Andric   return Changed;
16430b57cec5SDimitry Andric }
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric bool CopyPropagation::isCopyReg(unsigned Opc, bool NoConv) {
16460b57cec5SDimitry Andric   switch (Opc) {
16470b57cec5SDimitry Andric     case TargetOpcode::COPY:
16480b57cec5SDimitry Andric     case TargetOpcode::REG_SEQUENCE:
16490b57cec5SDimitry Andric     case Hexagon::A4_combineir:
16500b57cec5SDimitry Andric     case Hexagon::A4_combineri:
16510b57cec5SDimitry Andric       return true;
16520b57cec5SDimitry Andric     case Hexagon::A2_tfr:
16530b57cec5SDimitry Andric     case Hexagon::A2_tfrp:
16540b57cec5SDimitry Andric     case Hexagon::A2_combinew:
16550b57cec5SDimitry Andric     case Hexagon::V6_vcombine:
16560b57cec5SDimitry Andric       return NoConv;
16570b57cec5SDimitry Andric     default:
16580b57cec5SDimitry Andric       break;
16590b57cec5SDimitry Andric   }
16600b57cec5SDimitry Andric   return false;
16610b57cec5SDimitry Andric }
16620b57cec5SDimitry Andric 
16630b57cec5SDimitry Andric bool CopyPropagation::propagateRegCopy(MachineInstr &MI) {
16640b57cec5SDimitry Andric   bool Changed = false;
16650b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
16660b57cec5SDimitry Andric   BitTracker::RegisterRef RD = MI.getOperand(0);
16670b57cec5SDimitry Andric   assert(MI.getOperand(0).getSubReg() == 0);
16680b57cec5SDimitry Andric 
16690b57cec5SDimitry Andric   switch (Opc) {
16700b57cec5SDimitry Andric     case TargetOpcode::COPY:
16710b57cec5SDimitry Andric     case Hexagon::A2_tfr:
16720b57cec5SDimitry Andric     case Hexagon::A2_tfrp: {
16730b57cec5SDimitry Andric       BitTracker::RegisterRef RS = MI.getOperand(1);
16740b57cec5SDimitry Andric       if (!HBS::isTransparentCopy(RD, RS, MRI))
16750b57cec5SDimitry Andric         break;
16760b57cec5SDimitry Andric       if (RS.Sub != 0)
16770b57cec5SDimitry Andric         Changed = HBS::replaceRegWithSub(RD.Reg, RS.Reg, RS.Sub, MRI);
16780b57cec5SDimitry Andric       else
16790b57cec5SDimitry Andric         Changed = HBS::replaceReg(RD.Reg, RS.Reg, MRI);
16800b57cec5SDimitry Andric       break;
16810b57cec5SDimitry Andric     }
16820b57cec5SDimitry Andric     case TargetOpcode::REG_SEQUENCE: {
16830b57cec5SDimitry Andric       BitTracker::RegisterRef SL, SH;
16840b57cec5SDimitry Andric       if (HBS::parseRegSequence(MI, SL, SH, MRI)) {
16850b57cec5SDimitry Andric         const TargetRegisterClass &RC = *MRI.getRegClass(RD.Reg);
16860b57cec5SDimitry Andric         unsigned SubLo = HRI.getHexagonSubRegIndex(RC, Hexagon::ps_sub_lo);
16870b57cec5SDimitry Andric         unsigned SubHi = HRI.getHexagonSubRegIndex(RC, Hexagon::ps_sub_hi);
16880b57cec5SDimitry Andric         Changed  = HBS::replaceSubWithSub(RD.Reg, SubLo, SL.Reg, SL.Sub, MRI);
16890b57cec5SDimitry Andric         Changed |= HBS::replaceSubWithSub(RD.Reg, SubHi, SH.Reg, SH.Sub, MRI);
16900b57cec5SDimitry Andric       }
16910b57cec5SDimitry Andric       break;
16920b57cec5SDimitry Andric     }
16930b57cec5SDimitry Andric     case Hexagon::A2_combinew:
16940b57cec5SDimitry Andric     case Hexagon::V6_vcombine: {
16950b57cec5SDimitry Andric       const TargetRegisterClass &RC = *MRI.getRegClass(RD.Reg);
16960b57cec5SDimitry Andric       unsigned SubLo = HRI.getHexagonSubRegIndex(RC, Hexagon::ps_sub_lo);
16970b57cec5SDimitry Andric       unsigned SubHi = HRI.getHexagonSubRegIndex(RC, Hexagon::ps_sub_hi);
16980b57cec5SDimitry Andric       BitTracker::RegisterRef RH = MI.getOperand(1), RL = MI.getOperand(2);
16990b57cec5SDimitry Andric       Changed  = HBS::replaceSubWithSub(RD.Reg, SubLo, RL.Reg, RL.Sub, MRI);
17000b57cec5SDimitry Andric       Changed |= HBS::replaceSubWithSub(RD.Reg, SubHi, RH.Reg, RH.Sub, MRI);
17010b57cec5SDimitry Andric       break;
17020b57cec5SDimitry Andric     }
17030b57cec5SDimitry Andric     case Hexagon::A4_combineir:
17040b57cec5SDimitry Andric     case Hexagon::A4_combineri: {
17050b57cec5SDimitry Andric       unsigned SrcX = (Opc == Hexagon::A4_combineir) ? 2 : 1;
17060b57cec5SDimitry Andric       unsigned Sub = (Opc == Hexagon::A4_combineir) ? Hexagon::isub_lo
17070b57cec5SDimitry Andric                                                     : Hexagon::isub_hi;
17080b57cec5SDimitry Andric       BitTracker::RegisterRef RS = MI.getOperand(SrcX);
17090b57cec5SDimitry Andric       Changed = HBS::replaceSubWithSub(RD.Reg, Sub, RS.Reg, RS.Sub, MRI);
17100b57cec5SDimitry Andric       break;
17110b57cec5SDimitry Andric     }
17120b57cec5SDimitry Andric   }
17130b57cec5SDimitry Andric   return Changed;
17140b57cec5SDimitry Andric }
17150b57cec5SDimitry Andric 
17160b57cec5SDimitry Andric bool CopyPropagation::processBlock(MachineBasicBlock &B, const RegisterSet&) {
17170b57cec5SDimitry Andric   std::vector<MachineInstr*> Instrs;
17180b57cec5SDimitry Andric   for (auto I = B.rbegin(), E = B.rend(); I != E; ++I)
17190b57cec5SDimitry Andric     Instrs.push_back(&*I);
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric   bool Changed = false;
17220b57cec5SDimitry Andric   for (auto I : Instrs) {
17230b57cec5SDimitry Andric     unsigned Opc = I->getOpcode();
17240b57cec5SDimitry Andric     if (!CopyPropagation::isCopyReg(Opc, true))
17250b57cec5SDimitry Andric       continue;
17260b57cec5SDimitry Andric     Changed |= propagateRegCopy(*I);
17270b57cec5SDimitry Andric   }
17280b57cec5SDimitry Andric 
17290b57cec5SDimitry Andric   return Changed;
17300b57cec5SDimitry Andric }
17310b57cec5SDimitry Andric 
17320b57cec5SDimitry Andric namespace {
17330b57cec5SDimitry Andric 
17340b57cec5SDimitry Andric // Recognize patterns that can be simplified and replace them with the
17350b57cec5SDimitry Andric // simpler forms.
17360b57cec5SDimitry Andric // This is by no means complete
17370b57cec5SDimitry Andric   class BitSimplification : public Transformation {
17380b57cec5SDimitry Andric   public:
17390b57cec5SDimitry Andric     BitSimplification(BitTracker &bt, const MachineDominatorTree &mdt,
17400b57cec5SDimitry Andric         const HexagonInstrInfo &hii, const HexagonRegisterInfo &hri,
17410b57cec5SDimitry Andric         MachineRegisterInfo &mri, MachineFunction &mf)
17420b57cec5SDimitry Andric       : Transformation(true), MDT(mdt), HII(hii), HRI(hri), MRI(mri),
17430b57cec5SDimitry Andric         MF(mf), BT(bt) {}
17440b57cec5SDimitry Andric 
17450b57cec5SDimitry Andric     bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
17460b57cec5SDimitry Andric 
17470b57cec5SDimitry Andric   private:
17480b57cec5SDimitry Andric     struct RegHalf : public BitTracker::RegisterRef {
17490b57cec5SDimitry Andric       bool Low;  // Low/High halfword.
17500b57cec5SDimitry Andric     };
17510b57cec5SDimitry Andric 
17520b57cec5SDimitry Andric     bool matchHalf(unsigned SelfR, const BitTracker::RegisterCell &RC,
17530b57cec5SDimitry Andric           unsigned B, RegHalf &RH);
17540b57cec5SDimitry Andric     bool validateReg(BitTracker::RegisterRef R, unsigned Opc, unsigned OpNum);
17550b57cec5SDimitry Andric 
17560b57cec5SDimitry Andric     bool matchPackhl(unsigned SelfR, const BitTracker::RegisterCell &RC,
17570b57cec5SDimitry Andric           BitTracker::RegisterRef &Rs, BitTracker::RegisterRef &Rt);
17580b57cec5SDimitry Andric     unsigned getCombineOpcode(bool HLow, bool LLow);
17590b57cec5SDimitry Andric 
17600b57cec5SDimitry Andric     bool genStoreUpperHalf(MachineInstr *MI);
17610b57cec5SDimitry Andric     bool genStoreImmediate(MachineInstr *MI);
17620b57cec5SDimitry Andric     bool genPackhl(MachineInstr *MI, BitTracker::RegisterRef RD,
17630b57cec5SDimitry Andric           const BitTracker::RegisterCell &RC);
17640b57cec5SDimitry Andric     bool genExtractHalf(MachineInstr *MI, BitTracker::RegisterRef RD,
17650b57cec5SDimitry Andric           const BitTracker::RegisterCell &RC);
17660b57cec5SDimitry Andric     bool genCombineHalf(MachineInstr *MI, BitTracker::RegisterRef RD,
17670b57cec5SDimitry Andric           const BitTracker::RegisterCell &RC);
17680b57cec5SDimitry Andric     bool genExtractLow(MachineInstr *MI, BitTracker::RegisterRef RD,
17690b57cec5SDimitry Andric           const BitTracker::RegisterCell &RC);
17700b57cec5SDimitry Andric     bool genBitSplit(MachineInstr *MI, BitTracker::RegisterRef RD,
17710b57cec5SDimitry Andric           const BitTracker::RegisterCell &RC, const RegisterSet &AVs);
17720b57cec5SDimitry Andric     bool simplifyTstbit(MachineInstr *MI, BitTracker::RegisterRef RD,
17730b57cec5SDimitry Andric           const BitTracker::RegisterCell &RC);
17740b57cec5SDimitry Andric     bool simplifyExtractLow(MachineInstr *MI, BitTracker::RegisterRef RD,
17750b57cec5SDimitry Andric           const BitTracker::RegisterCell &RC, const RegisterSet &AVs);
17760b57cec5SDimitry Andric     bool simplifyRCmp0(MachineInstr *MI, BitTracker::RegisterRef RD);
17770b57cec5SDimitry Andric 
17780b57cec5SDimitry Andric     // Cache of created instructions to avoid creating duplicates.
17790b57cec5SDimitry Andric     // XXX Currently only used by genBitSplit.
17800b57cec5SDimitry Andric     std::vector<MachineInstr*> NewMIs;
17810b57cec5SDimitry Andric 
17820b57cec5SDimitry Andric     const MachineDominatorTree &MDT;
17830b57cec5SDimitry Andric     const HexagonInstrInfo &HII;
17840b57cec5SDimitry Andric     const HexagonRegisterInfo &HRI;
17850b57cec5SDimitry Andric     MachineRegisterInfo &MRI;
17860b57cec5SDimitry Andric     MachineFunction &MF;
17870b57cec5SDimitry Andric     BitTracker &BT;
17880b57cec5SDimitry Andric   };
17890b57cec5SDimitry Andric 
17900b57cec5SDimitry Andric } // end anonymous namespace
17910b57cec5SDimitry Andric 
17920b57cec5SDimitry Andric // Check if the bits [B..B+16) in register cell RC form a valid halfword,
17930b57cec5SDimitry Andric // i.e. [0..16), [16..32), etc. of some register. If so, return true and
17940b57cec5SDimitry Andric // set the information about the found register in RH.
17950b57cec5SDimitry Andric bool BitSimplification::matchHalf(unsigned SelfR,
17960b57cec5SDimitry Andric       const BitTracker::RegisterCell &RC, unsigned B, RegHalf &RH) {
17970b57cec5SDimitry Andric   // XXX This could be searching in the set of available registers, in case
17980b57cec5SDimitry Andric   // the match is not exact.
17990b57cec5SDimitry Andric 
18000b57cec5SDimitry Andric   // Match 16-bit chunks, where the RC[B..B+15] references exactly one
18010b57cec5SDimitry Andric   // register and all the bits B..B+15 match between RC and the register.
18020b57cec5SDimitry Andric   // This is meant to match "v1[0-15]", where v1 = { [0]:0 [1-15]:v1... },
18030b57cec5SDimitry Andric   // and RC = { [0]:0 [1-15]:v1[1-15]... }.
18040b57cec5SDimitry Andric   bool Low = false;
18050b57cec5SDimitry Andric   unsigned I = B;
18060b57cec5SDimitry Andric   while (I < B+16 && RC[I].num())
18070b57cec5SDimitry Andric     I++;
18080b57cec5SDimitry Andric   if (I == B+16)
18090b57cec5SDimitry Andric     return false;
18100b57cec5SDimitry Andric 
18110b57cec5SDimitry Andric   unsigned Reg = RC[I].RefI.Reg;
18120b57cec5SDimitry Andric   unsigned P = RC[I].RefI.Pos;    // The RefI.Pos will be advanced by I-B.
18130b57cec5SDimitry Andric   if (P < I-B)
18140b57cec5SDimitry Andric     return false;
18150b57cec5SDimitry Andric   unsigned Pos = P - (I-B);
18160b57cec5SDimitry Andric 
18170b57cec5SDimitry Andric   if (Reg == 0 || Reg == SelfR)    // Don't match "self".
18180b57cec5SDimitry Andric     return false;
1819*8bcb0991SDimitry Andric   if (!Register::isVirtualRegister(Reg))
18200b57cec5SDimitry Andric     return false;
18210b57cec5SDimitry Andric   if (!BT.has(Reg))
18220b57cec5SDimitry Andric     return false;
18230b57cec5SDimitry Andric 
18240b57cec5SDimitry Andric   const BitTracker::RegisterCell &SC = BT.lookup(Reg);
18250b57cec5SDimitry Andric   if (Pos+16 > SC.width())
18260b57cec5SDimitry Andric     return false;
18270b57cec5SDimitry Andric 
18280b57cec5SDimitry Andric   for (unsigned i = 0; i < 16; ++i) {
18290b57cec5SDimitry Andric     const BitTracker::BitValue &RV = RC[i+B];
18300b57cec5SDimitry Andric     if (RV.Type == BitTracker::BitValue::Ref) {
18310b57cec5SDimitry Andric       if (RV.RefI.Reg != Reg)
18320b57cec5SDimitry Andric         return false;
18330b57cec5SDimitry Andric       if (RV.RefI.Pos != i+Pos)
18340b57cec5SDimitry Andric         return false;
18350b57cec5SDimitry Andric       continue;
18360b57cec5SDimitry Andric     }
18370b57cec5SDimitry Andric     if (RC[i+B] != SC[i+Pos])
18380b57cec5SDimitry Andric       return false;
18390b57cec5SDimitry Andric   }
18400b57cec5SDimitry Andric 
18410b57cec5SDimitry Andric   unsigned Sub = 0;
18420b57cec5SDimitry Andric   switch (Pos) {
18430b57cec5SDimitry Andric     case 0:
18440b57cec5SDimitry Andric       Sub = Hexagon::isub_lo;
18450b57cec5SDimitry Andric       Low = true;
18460b57cec5SDimitry Andric       break;
18470b57cec5SDimitry Andric     case 16:
18480b57cec5SDimitry Andric       Sub = Hexagon::isub_lo;
18490b57cec5SDimitry Andric       Low = false;
18500b57cec5SDimitry Andric       break;
18510b57cec5SDimitry Andric     case 32:
18520b57cec5SDimitry Andric       Sub = Hexagon::isub_hi;
18530b57cec5SDimitry Andric       Low = true;
18540b57cec5SDimitry Andric       break;
18550b57cec5SDimitry Andric     case 48:
18560b57cec5SDimitry Andric       Sub = Hexagon::isub_hi;
18570b57cec5SDimitry Andric       Low = false;
18580b57cec5SDimitry Andric       break;
18590b57cec5SDimitry Andric     default:
18600b57cec5SDimitry Andric       return false;
18610b57cec5SDimitry Andric   }
18620b57cec5SDimitry Andric 
18630b57cec5SDimitry Andric   RH.Reg = Reg;
18640b57cec5SDimitry Andric   RH.Sub = Sub;
18650b57cec5SDimitry Andric   RH.Low = Low;
18660b57cec5SDimitry Andric   // If the subregister is not valid with the register, set it to 0.
18670b57cec5SDimitry Andric   if (!HBS::getFinalVRegClass(RH, MRI))
18680b57cec5SDimitry Andric     RH.Sub = 0;
18690b57cec5SDimitry Andric 
18700b57cec5SDimitry Andric   return true;
18710b57cec5SDimitry Andric }
18720b57cec5SDimitry Andric 
18730b57cec5SDimitry Andric bool BitSimplification::validateReg(BitTracker::RegisterRef R, unsigned Opc,
18740b57cec5SDimitry Andric       unsigned OpNum) {
18750b57cec5SDimitry Andric   auto *OpRC = HII.getRegClass(HII.get(Opc), OpNum, &HRI, MF);
18760b57cec5SDimitry Andric   auto *RRC = HBS::getFinalVRegClass(R, MRI);
18770b57cec5SDimitry Andric   return OpRC->hasSubClassEq(RRC);
18780b57cec5SDimitry Andric }
18790b57cec5SDimitry Andric 
18800b57cec5SDimitry Andric // Check if RC matches the pattern of a S2_packhl. If so, return true and
18810b57cec5SDimitry Andric // set the inputs Rs and Rt.
18820b57cec5SDimitry Andric bool BitSimplification::matchPackhl(unsigned SelfR,
18830b57cec5SDimitry Andric       const BitTracker::RegisterCell &RC, BitTracker::RegisterRef &Rs,
18840b57cec5SDimitry Andric       BitTracker::RegisterRef &Rt) {
18850b57cec5SDimitry Andric   RegHalf L1, H1, L2, H2;
18860b57cec5SDimitry Andric 
18870b57cec5SDimitry Andric   if (!matchHalf(SelfR, RC, 0, L2)  || !matchHalf(SelfR, RC, 16, L1))
18880b57cec5SDimitry Andric     return false;
18890b57cec5SDimitry Andric   if (!matchHalf(SelfR, RC, 32, H2) || !matchHalf(SelfR, RC, 48, H1))
18900b57cec5SDimitry Andric     return false;
18910b57cec5SDimitry Andric 
18920b57cec5SDimitry Andric   // Rs = H1.L1, Rt = H2.L2
18930b57cec5SDimitry Andric   if (H1.Reg != L1.Reg || H1.Sub != L1.Sub || H1.Low || !L1.Low)
18940b57cec5SDimitry Andric     return false;
18950b57cec5SDimitry Andric   if (H2.Reg != L2.Reg || H2.Sub != L2.Sub || H2.Low || !L2.Low)
18960b57cec5SDimitry Andric     return false;
18970b57cec5SDimitry Andric 
18980b57cec5SDimitry Andric   Rs = H1;
18990b57cec5SDimitry Andric   Rt = H2;
19000b57cec5SDimitry Andric   return true;
19010b57cec5SDimitry Andric }
19020b57cec5SDimitry Andric 
19030b57cec5SDimitry Andric unsigned BitSimplification::getCombineOpcode(bool HLow, bool LLow) {
19040b57cec5SDimitry Andric   return HLow ? LLow ? Hexagon::A2_combine_ll
19050b57cec5SDimitry Andric                      : Hexagon::A2_combine_lh
19060b57cec5SDimitry Andric               : LLow ? Hexagon::A2_combine_hl
19070b57cec5SDimitry Andric                      : Hexagon::A2_combine_hh;
19080b57cec5SDimitry Andric }
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric // If MI stores the upper halfword of a register (potentially obtained via
19110b57cec5SDimitry Andric // shifts or extracts), replace it with a storerf instruction. This could
19120b57cec5SDimitry Andric // cause the "extraction" code to become dead.
19130b57cec5SDimitry Andric bool BitSimplification::genStoreUpperHalf(MachineInstr *MI) {
19140b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
19150b57cec5SDimitry Andric   if (Opc != Hexagon::S2_storerh_io)
19160b57cec5SDimitry Andric     return false;
19170b57cec5SDimitry Andric 
19180b57cec5SDimitry Andric   MachineOperand &ValOp = MI->getOperand(2);
19190b57cec5SDimitry Andric   BitTracker::RegisterRef RS = ValOp;
19200b57cec5SDimitry Andric   if (!BT.has(RS.Reg))
19210b57cec5SDimitry Andric     return false;
19220b57cec5SDimitry Andric   const BitTracker::RegisterCell &RC = BT.lookup(RS.Reg);
19230b57cec5SDimitry Andric   RegHalf H;
19240b57cec5SDimitry Andric   if (!matchHalf(0, RC, 0, H))
19250b57cec5SDimitry Andric     return false;
19260b57cec5SDimitry Andric   if (H.Low)
19270b57cec5SDimitry Andric     return false;
19280b57cec5SDimitry Andric   MI->setDesc(HII.get(Hexagon::S2_storerf_io));
19290b57cec5SDimitry Andric   ValOp.setReg(H.Reg);
19300b57cec5SDimitry Andric   ValOp.setSubReg(H.Sub);
19310b57cec5SDimitry Andric   return true;
19320b57cec5SDimitry Andric }
19330b57cec5SDimitry Andric 
19340b57cec5SDimitry Andric // If MI stores a value known at compile-time, and the value is within a range
19350b57cec5SDimitry Andric // that avoids using constant-extenders, replace it with a store-immediate.
19360b57cec5SDimitry Andric bool BitSimplification::genStoreImmediate(MachineInstr *MI) {
19370b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
19380b57cec5SDimitry Andric   unsigned Align = 0;
19390b57cec5SDimitry Andric   switch (Opc) {
19400b57cec5SDimitry Andric     case Hexagon::S2_storeri_io:
19410b57cec5SDimitry Andric       Align++;
19420b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
19430b57cec5SDimitry Andric     case Hexagon::S2_storerh_io:
19440b57cec5SDimitry Andric       Align++;
19450b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
19460b57cec5SDimitry Andric     case Hexagon::S2_storerb_io:
19470b57cec5SDimitry Andric       break;
19480b57cec5SDimitry Andric     default:
19490b57cec5SDimitry Andric       return false;
19500b57cec5SDimitry Andric   }
19510b57cec5SDimitry Andric 
19520b57cec5SDimitry Andric   // Avoid stores to frame-indices (due to an unknown offset).
19530b57cec5SDimitry Andric   if (!MI->getOperand(0).isReg())
19540b57cec5SDimitry Andric     return false;
19550b57cec5SDimitry Andric   MachineOperand &OffOp = MI->getOperand(1);
19560b57cec5SDimitry Andric   if (!OffOp.isImm())
19570b57cec5SDimitry Andric     return false;
19580b57cec5SDimitry Andric 
19590b57cec5SDimitry Andric   int64_t Off = OffOp.getImm();
19600b57cec5SDimitry Andric   // Offset is u6:a. Sadly, there is no isShiftedUInt(n,x).
19610b57cec5SDimitry Andric   if (!isUIntN(6+Align, Off) || (Off & ((1<<Align)-1)))
19620b57cec5SDimitry Andric     return false;
19630b57cec5SDimitry Andric   // Source register:
19640b57cec5SDimitry Andric   BitTracker::RegisterRef RS = MI->getOperand(2);
19650b57cec5SDimitry Andric   if (!BT.has(RS.Reg))
19660b57cec5SDimitry Andric     return false;
19670b57cec5SDimitry Andric   const BitTracker::RegisterCell &RC = BT.lookup(RS.Reg);
19680b57cec5SDimitry Andric   uint64_t U;
19690b57cec5SDimitry Andric   if (!HBS::getConst(RC, 0, RC.width(), U))
19700b57cec5SDimitry Andric     return false;
19710b57cec5SDimitry Andric 
19720b57cec5SDimitry Andric   // Only consider 8-bit values to avoid constant-extenders.
19730b57cec5SDimitry Andric   int V;
19740b57cec5SDimitry Andric   switch (Opc) {
19750b57cec5SDimitry Andric     case Hexagon::S2_storerb_io:
19760b57cec5SDimitry Andric       V = int8_t(U);
19770b57cec5SDimitry Andric       break;
19780b57cec5SDimitry Andric     case Hexagon::S2_storerh_io:
19790b57cec5SDimitry Andric       V = int16_t(U);
19800b57cec5SDimitry Andric       break;
19810b57cec5SDimitry Andric     case Hexagon::S2_storeri_io:
19820b57cec5SDimitry Andric       V = int32_t(U);
19830b57cec5SDimitry Andric       break;
19840b57cec5SDimitry Andric     default:
19850b57cec5SDimitry Andric       // Opc is already checked above to be one of the three store instructions.
19860b57cec5SDimitry Andric       // This silences a -Wuninitialized false positive on GCC 5.4.
19870b57cec5SDimitry Andric       llvm_unreachable("Unexpected store opcode");
19880b57cec5SDimitry Andric   }
19890b57cec5SDimitry Andric   if (!isInt<8>(V))
19900b57cec5SDimitry Andric     return false;
19910b57cec5SDimitry Andric 
19920b57cec5SDimitry Andric   MI->RemoveOperand(2);
19930b57cec5SDimitry Andric   switch (Opc) {
19940b57cec5SDimitry Andric     case Hexagon::S2_storerb_io:
19950b57cec5SDimitry Andric       MI->setDesc(HII.get(Hexagon::S4_storeirb_io));
19960b57cec5SDimitry Andric       break;
19970b57cec5SDimitry Andric     case Hexagon::S2_storerh_io:
19980b57cec5SDimitry Andric       MI->setDesc(HII.get(Hexagon::S4_storeirh_io));
19990b57cec5SDimitry Andric       break;
20000b57cec5SDimitry Andric     case Hexagon::S2_storeri_io:
20010b57cec5SDimitry Andric       MI->setDesc(HII.get(Hexagon::S4_storeiri_io));
20020b57cec5SDimitry Andric       break;
20030b57cec5SDimitry Andric   }
20040b57cec5SDimitry Andric   MI->addOperand(MachineOperand::CreateImm(V));
20050b57cec5SDimitry Andric   return true;
20060b57cec5SDimitry Andric }
20070b57cec5SDimitry Andric 
20080b57cec5SDimitry Andric // If MI is equivalent o S2_packhl, generate the S2_packhl. MI could be the
20090b57cec5SDimitry Andric // last instruction in a sequence that results in something equivalent to
20100b57cec5SDimitry Andric // the pack-halfwords. The intent is to cause the entire sequence to become
20110b57cec5SDimitry Andric // dead.
20120b57cec5SDimitry Andric bool BitSimplification::genPackhl(MachineInstr *MI,
20130b57cec5SDimitry Andric       BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC) {
20140b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
20150b57cec5SDimitry Andric   if (Opc == Hexagon::S2_packhl)
20160b57cec5SDimitry Andric     return false;
20170b57cec5SDimitry Andric   BitTracker::RegisterRef Rs, Rt;
20180b57cec5SDimitry Andric   if (!matchPackhl(RD.Reg, RC, Rs, Rt))
20190b57cec5SDimitry Andric     return false;
20200b57cec5SDimitry Andric   if (!validateReg(Rs, Hexagon::S2_packhl, 1) ||
20210b57cec5SDimitry Andric       !validateReg(Rt, Hexagon::S2_packhl, 2))
20220b57cec5SDimitry Andric     return false;
20230b57cec5SDimitry Andric 
20240b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
2025*8bcb0991SDimitry Andric   Register NewR = MRI.createVirtualRegister(&Hexagon::DoubleRegsRegClass);
20260b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
20270b57cec5SDimitry Andric   auto At = MI->isPHI() ? B.getFirstNonPHI()
20280b57cec5SDimitry Andric                         : MachineBasicBlock::iterator(MI);
20290b57cec5SDimitry Andric   BuildMI(B, At, DL, HII.get(Hexagon::S2_packhl), NewR)
20300b57cec5SDimitry Andric       .addReg(Rs.Reg, 0, Rs.Sub)
20310b57cec5SDimitry Andric       .addReg(Rt.Reg, 0, Rt.Sub);
20320b57cec5SDimitry Andric   HBS::replaceSubWithSub(RD.Reg, RD.Sub, NewR, 0, MRI);
20330b57cec5SDimitry Andric   BT.put(BitTracker::RegisterRef(NewR), RC);
20340b57cec5SDimitry Andric   return true;
20350b57cec5SDimitry Andric }
20360b57cec5SDimitry Andric 
20370b57cec5SDimitry Andric // If MI produces halfword of the input in the low half of the output,
20380b57cec5SDimitry Andric // replace it with zero-extend or extractu.
20390b57cec5SDimitry Andric bool BitSimplification::genExtractHalf(MachineInstr *MI,
20400b57cec5SDimitry Andric       BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC) {
20410b57cec5SDimitry Andric   RegHalf L;
20420b57cec5SDimitry Andric   // Check for halfword in low 16 bits, zeros elsewhere.
20430b57cec5SDimitry Andric   if (!matchHalf(RD.Reg, RC, 0, L) || !HBS::isZero(RC, 16, 16))
20440b57cec5SDimitry Andric     return false;
20450b57cec5SDimitry Andric 
20460b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
20470b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
20480b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
20490b57cec5SDimitry Andric 
20500b57cec5SDimitry Andric   // Prefer zxth, since zxth can go in any slot, while extractu only in
20510b57cec5SDimitry Andric   // slots 2 and 3.
20520b57cec5SDimitry Andric   unsigned NewR = 0;
20530b57cec5SDimitry Andric   auto At = MI->isPHI() ? B.getFirstNonPHI()
20540b57cec5SDimitry Andric                         : MachineBasicBlock::iterator(MI);
20550b57cec5SDimitry Andric   if (L.Low && Opc != Hexagon::A2_zxth) {
20560b57cec5SDimitry Andric     if (validateReg(L, Hexagon::A2_zxth, 1)) {
20570b57cec5SDimitry Andric       NewR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
20580b57cec5SDimitry Andric       BuildMI(B, At, DL, HII.get(Hexagon::A2_zxth), NewR)
20590b57cec5SDimitry Andric           .addReg(L.Reg, 0, L.Sub);
20600b57cec5SDimitry Andric     }
20610b57cec5SDimitry Andric   } else if (!L.Low && Opc != Hexagon::S2_lsr_i_r) {
20620b57cec5SDimitry Andric     if (validateReg(L, Hexagon::S2_lsr_i_r, 1)) {
20630b57cec5SDimitry Andric       NewR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
20640b57cec5SDimitry Andric       BuildMI(B, MI, DL, HII.get(Hexagon::S2_lsr_i_r), NewR)
20650b57cec5SDimitry Andric           .addReg(L.Reg, 0, L.Sub)
20660b57cec5SDimitry Andric           .addImm(16);
20670b57cec5SDimitry Andric     }
20680b57cec5SDimitry Andric   }
20690b57cec5SDimitry Andric   if (NewR == 0)
20700b57cec5SDimitry Andric     return false;
20710b57cec5SDimitry Andric   HBS::replaceSubWithSub(RD.Reg, RD.Sub, NewR, 0, MRI);
20720b57cec5SDimitry Andric   BT.put(BitTracker::RegisterRef(NewR), RC);
20730b57cec5SDimitry Andric   return true;
20740b57cec5SDimitry Andric }
20750b57cec5SDimitry Andric 
20760b57cec5SDimitry Andric // If MI is equivalent to a combine(.L/.H, .L/.H) replace with with the
20770b57cec5SDimitry Andric // combine.
20780b57cec5SDimitry Andric bool BitSimplification::genCombineHalf(MachineInstr *MI,
20790b57cec5SDimitry Andric       BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC) {
20800b57cec5SDimitry Andric   RegHalf L, H;
20810b57cec5SDimitry Andric   // Check for combine h/l
20820b57cec5SDimitry Andric   if (!matchHalf(RD.Reg, RC, 0, L) || !matchHalf(RD.Reg, RC, 16, H))
20830b57cec5SDimitry Andric     return false;
20840b57cec5SDimitry Andric   // Do nothing if this is just a reg copy.
20850b57cec5SDimitry Andric   if (L.Reg == H.Reg && L.Sub == H.Sub && !H.Low && L.Low)
20860b57cec5SDimitry Andric     return false;
20870b57cec5SDimitry Andric 
20880b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
20890b57cec5SDimitry Andric   unsigned COpc = getCombineOpcode(H.Low, L.Low);
20900b57cec5SDimitry Andric   if (COpc == Opc)
20910b57cec5SDimitry Andric     return false;
20920b57cec5SDimitry Andric   if (!validateReg(H, COpc, 1) || !validateReg(L, COpc, 2))
20930b57cec5SDimitry Andric     return false;
20940b57cec5SDimitry Andric 
20950b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
20960b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
2097*8bcb0991SDimitry Andric   Register NewR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
20980b57cec5SDimitry Andric   auto At = MI->isPHI() ? B.getFirstNonPHI()
20990b57cec5SDimitry Andric                         : MachineBasicBlock::iterator(MI);
21000b57cec5SDimitry Andric   BuildMI(B, At, DL, HII.get(COpc), NewR)
21010b57cec5SDimitry Andric       .addReg(H.Reg, 0, H.Sub)
21020b57cec5SDimitry Andric       .addReg(L.Reg, 0, L.Sub);
21030b57cec5SDimitry Andric   HBS::replaceSubWithSub(RD.Reg, RD.Sub, NewR, 0, MRI);
21040b57cec5SDimitry Andric   BT.put(BitTracker::RegisterRef(NewR), RC);
21050b57cec5SDimitry Andric   return true;
21060b57cec5SDimitry Andric }
21070b57cec5SDimitry Andric 
21080b57cec5SDimitry Andric // If MI resets high bits of a register and keeps the lower ones, replace it
21090b57cec5SDimitry Andric // with zero-extend byte/half, and-immediate, or extractu, as appropriate.
21100b57cec5SDimitry Andric bool BitSimplification::genExtractLow(MachineInstr *MI,
21110b57cec5SDimitry Andric       BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC) {
21120b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
21130b57cec5SDimitry Andric   switch (Opc) {
21140b57cec5SDimitry Andric     case Hexagon::A2_zxtb:
21150b57cec5SDimitry Andric     case Hexagon::A2_zxth:
21160b57cec5SDimitry Andric     case Hexagon::S2_extractu:
21170b57cec5SDimitry Andric       return false;
21180b57cec5SDimitry Andric   }
21190b57cec5SDimitry Andric   if (Opc == Hexagon::A2_andir && MI->getOperand(2).isImm()) {
21200b57cec5SDimitry Andric     int32_t Imm = MI->getOperand(2).getImm();
21210b57cec5SDimitry Andric     if (isInt<10>(Imm))
21220b57cec5SDimitry Andric       return false;
21230b57cec5SDimitry Andric   }
21240b57cec5SDimitry Andric 
21250b57cec5SDimitry Andric   if (MI->hasUnmodeledSideEffects() || MI->isInlineAsm())
21260b57cec5SDimitry Andric     return false;
21270b57cec5SDimitry Andric   unsigned W = RC.width();
21280b57cec5SDimitry Andric   while (W > 0 && RC[W-1].is(0))
21290b57cec5SDimitry Andric     W--;
21300b57cec5SDimitry Andric   if (W == 0 || W == RC.width())
21310b57cec5SDimitry Andric     return false;
21320b57cec5SDimitry Andric   unsigned NewOpc = (W == 8)  ? Hexagon::A2_zxtb
21330b57cec5SDimitry Andric                   : (W == 16) ? Hexagon::A2_zxth
21340b57cec5SDimitry Andric                   : (W < 10)  ? Hexagon::A2_andir
21350b57cec5SDimitry Andric                   : Hexagon::S2_extractu;
21360b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
21370b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
21380b57cec5SDimitry Andric 
21390b57cec5SDimitry Andric   for (auto &Op : MI->uses()) {
21400b57cec5SDimitry Andric     if (!Op.isReg())
21410b57cec5SDimitry Andric       continue;
21420b57cec5SDimitry Andric     BitTracker::RegisterRef RS = Op;
21430b57cec5SDimitry Andric     if (!BT.has(RS.Reg))
21440b57cec5SDimitry Andric       continue;
21450b57cec5SDimitry Andric     const BitTracker::RegisterCell &SC = BT.lookup(RS.Reg);
21460b57cec5SDimitry Andric     unsigned BN, BW;
21470b57cec5SDimitry Andric     if (!HBS::getSubregMask(RS, BN, BW, MRI))
21480b57cec5SDimitry Andric       continue;
21490b57cec5SDimitry Andric     if (BW < W || !HBS::isEqual(RC, 0, SC, BN, W))
21500b57cec5SDimitry Andric       continue;
21510b57cec5SDimitry Andric     if (!validateReg(RS, NewOpc, 1))
21520b57cec5SDimitry Andric       continue;
21530b57cec5SDimitry Andric 
2154*8bcb0991SDimitry Andric     Register NewR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
21550b57cec5SDimitry Andric     auto At = MI->isPHI() ? B.getFirstNonPHI()
21560b57cec5SDimitry Andric                           : MachineBasicBlock::iterator(MI);
21570b57cec5SDimitry Andric     auto MIB = BuildMI(B, At, DL, HII.get(NewOpc), NewR)
21580b57cec5SDimitry Andric                   .addReg(RS.Reg, 0, RS.Sub);
21590b57cec5SDimitry Andric     if (NewOpc == Hexagon::A2_andir)
21600b57cec5SDimitry Andric       MIB.addImm((1 << W) - 1);
21610b57cec5SDimitry Andric     else if (NewOpc == Hexagon::S2_extractu)
21620b57cec5SDimitry Andric       MIB.addImm(W).addImm(0);
21630b57cec5SDimitry Andric     HBS::replaceSubWithSub(RD.Reg, RD.Sub, NewR, 0, MRI);
21640b57cec5SDimitry Andric     BT.put(BitTracker::RegisterRef(NewR), RC);
21650b57cec5SDimitry Andric     return true;
21660b57cec5SDimitry Andric   }
21670b57cec5SDimitry Andric   return false;
21680b57cec5SDimitry Andric }
21690b57cec5SDimitry Andric 
21700b57cec5SDimitry Andric bool BitSimplification::genBitSplit(MachineInstr *MI,
21710b57cec5SDimitry Andric       BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC,
21720b57cec5SDimitry Andric       const RegisterSet &AVs) {
21730b57cec5SDimitry Andric   if (!GenBitSplit)
21740b57cec5SDimitry Andric     return false;
21750b57cec5SDimitry Andric   if (MaxBitSplit.getNumOccurrences()) {
21760b57cec5SDimitry Andric     if (CountBitSplit >= MaxBitSplit)
21770b57cec5SDimitry Andric       return false;
21780b57cec5SDimitry Andric   }
21790b57cec5SDimitry Andric 
21800b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
21810b57cec5SDimitry Andric   switch (Opc) {
21820b57cec5SDimitry Andric     case Hexagon::A4_bitsplit:
21830b57cec5SDimitry Andric     case Hexagon::A4_bitspliti:
21840b57cec5SDimitry Andric       return false;
21850b57cec5SDimitry Andric   }
21860b57cec5SDimitry Andric 
21870b57cec5SDimitry Andric   unsigned W = RC.width();
21880b57cec5SDimitry Andric   if (W != 32)
21890b57cec5SDimitry Andric     return false;
21900b57cec5SDimitry Andric 
21910b57cec5SDimitry Andric   auto ctlz = [] (const BitTracker::RegisterCell &C) -> unsigned {
21920b57cec5SDimitry Andric     unsigned Z = C.width();
21930b57cec5SDimitry Andric     while (Z > 0 && C[Z-1].is(0))
21940b57cec5SDimitry Andric       --Z;
21950b57cec5SDimitry Andric     return C.width() - Z;
21960b57cec5SDimitry Andric   };
21970b57cec5SDimitry Andric 
21980b57cec5SDimitry Andric   // Count the number of leading zeros in the target RC.
21990b57cec5SDimitry Andric   unsigned Z = ctlz(RC);
22000b57cec5SDimitry Andric   if (Z == 0 || Z == W)
22010b57cec5SDimitry Andric     return false;
22020b57cec5SDimitry Andric 
22030b57cec5SDimitry Andric   // A simplistic analysis: assume the source register (the one being split)
22040b57cec5SDimitry Andric   // is fully unknown, and that all its bits are self-references.
22050b57cec5SDimitry Andric   const BitTracker::BitValue &B0 = RC[0];
22060b57cec5SDimitry Andric   if (B0.Type != BitTracker::BitValue::Ref)
22070b57cec5SDimitry Andric     return false;
22080b57cec5SDimitry Andric 
22090b57cec5SDimitry Andric   unsigned SrcR = B0.RefI.Reg;
22100b57cec5SDimitry Andric   unsigned SrcSR = 0;
22110b57cec5SDimitry Andric   unsigned Pos = B0.RefI.Pos;
22120b57cec5SDimitry Andric 
22130b57cec5SDimitry Andric   // All the non-zero bits should be consecutive bits from the same register.
22140b57cec5SDimitry Andric   for (unsigned i = 1; i < W-Z; ++i) {
22150b57cec5SDimitry Andric     const BitTracker::BitValue &V = RC[i];
22160b57cec5SDimitry Andric     if (V.Type != BitTracker::BitValue::Ref)
22170b57cec5SDimitry Andric       return false;
22180b57cec5SDimitry Andric     if (V.RefI.Reg != SrcR || V.RefI.Pos != Pos+i)
22190b57cec5SDimitry Andric       return false;
22200b57cec5SDimitry Andric   }
22210b57cec5SDimitry Andric 
22220b57cec5SDimitry Andric   // Now, find the other bitfield among AVs.
22230b57cec5SDimitry Andric   for (unsigned S = AVs.find_first(); S; S = AVs.find_next(S)) {
22240b57cec5SDimitry Andric     // The number of leading zeros here should be the number of trailing
22250b57cec5SDimitry Andric     // non-zeros in RC.
22260b57cec5SDimitry Andric     unsigned SRC = MRI.getRegClass(S)->getID();
22270b57cec5SDimitry Andric     if (SRC != Hexagon::IntRegsRegClassID &&
22280b57cec5SDimitry Andric         SRC != Hexagon::DoubleRegsRegClassID)
22290b57cec5SDimitry Andric       continue;
22300b57cec5SDimitry Andric     if (!BT.has(S))
22310b57cec5SDimitry Andric       continue;
22320b57cec5SDimitry Andric     const BitTracker::RegisterCell &SC = BT.lookup(S);
22330b57cec5SDimitry Andric     if (SC.width() != W || ctlz(SC) != W-Z)
22340b57cec5SDimitry Andric       continue;
22350b57cec5SDimitry Andric     // The Z lower bits should now match SrcR.
22360b57cec5SDimitry Andric     const BitTracker::BitValue &S0 = SC[0];
22370b57cec5SDimitry Andric     if (S0.Type != BitTracker::BitValue::Ref || S0.RefI.Reg != SrcR)
22380b57cec5SDimitry Andric       continue;
22390b57cec5SDimitry Andric     unsigned P = S0.RefI.Pos;
22400b57cec5SDimitry Andric 
22410b57cec5SDimitry Andric     if (Pos <= P && (Pos + W-Z) != P)
22420b57cec5SDimitry Andric       continue;
22430b57cec5SDimitry Andric     if (P < Pos && (P + Z) != Pos)
22440b57cec5SDimitry Andric       continue;
22450b57cec5SDimitry Andric     // The starting bitfield position must be at a subregister boundary.
22460b57cec5SDimitry Andric     if (std::min(P, Pos) != 0 && std::min(P, Pos) != 32)
22470b57cec5SDimitry Andric       continue;
22480b57cec5SDimitry Andric 
22490b57cec5SDimitry Andric     unsigned I;
22500b57cec5SDimitry Andric     for (I = 1; I < Z; ++I) {
22510b57cec5SDimitry Andric       const BitTracker::BitValue &V = SC[I];
22520b57cec5SDimitry Andric       if (V.Type != BitTracker::BitValue::Ref)
22530b57cec5SDimitry Andric         break;
22540b57cec5SDimitry Andric       if (V.RefI.Reg != SrcR || V.RefI.Pos != P+I)
22550b57cec5SDimitry Andric         break;
22560b57cec5SDimitry Andric     }
22570b57cec5SDimitry Andric     if (I != Z)
22580b57cec5SDimitry Andric       continue;
22590b57cec5SDimitry Andric 
22600b57cec5SDimitry Andric     // Generate bitsplit where S is defined.
22610b57cec5SDimitry Andric     if (MaxBitSplit.getNumOccurrences())
22620b57cec5SDimitry Andric       CountBitSplit++;
22630b57cec5SDimitry Andric     MachineInstr *DefS = MRI.getVRegDef(S);
22640b57cec5SDimitry Andric     assert(DefS != nullptr);
22650b57cec5SDimitry Andric     DebugLoc DL = DefS->getDebugLoc();
22660b57cec5SDimitry Andric     MachineBasicBlock &B = *DefS->getParent();
22670b57cec5SDimitry Andric     auto At = DefS->isPHI() ? B.getFirstNonPHI()
22680b57cec5SDimitry Andric                             : MachineBasicBlock::iterator(DefS);
22690b57cec5SDimitry Andric     if (MRI.getRegClass(SrcR)->getID() == Hexagon::DoubleRegsRegClassID)
22700b57cec5SDimitry Andric       SrcSR = (std::min(Pos, P) == 32) ? Hexagon::isub_hi : Hexagon::isub_lo;
22710b57cec5SDimitry Andric     if (!validateReg({SrcR,SrcSR}, Hexagon::A4_bitspliti, 1))
22720b57cec5SDimitry Andric       continue;
22730b57cec5SDimitry Andric     unsigned ImmOp = Pos <= P ? W-Z : Z;
22740b57cec5SDimitry Andric 
22750b57cec5SDimitry Andric     // Find an existing bitsplit instruction if one already exists.
22760b57cec5SDimitry Andric     unsigned NewR = 0;
22770b57cec5SDimitry Andric     for (MachineInstr *In : NewMIs) {
22780b57cec5SDimitry Andric       if (In->getOpcode() != Hexagon::A4_bitspliti)
22790b57cec5SDimitry Andric         continue;
22800b57cec5SDimitry Andric       MachineOperand &Op1 = In->getOperand(1);
22810b57cec5SDimitry Andric       if (Op1.getReg() != SrcR || Op1.getSubReg() != SrcSR)
22820b57cec5SDimitry Andric         continue;
22830b57cec5SDimitry Andric       if (In->getOperand(2).getImm() != ImmOp)
22840b57cec5SDimitry Andric         continue;
22850b57cec5SDimitry Andric       // Check if the target register is available here.
22860b57cec5SDimitry Andric       MachineOperand &Op0 = In->getOperand(0);
22870b57cec5SDimitry Andric       MachineInstr *DefI = MRI.getVRegDef(Op0.getReg());
22880b57cec5SDimitry Andric       assert(DefI != nullptr);
22890b57cec5SDimitry Andric       if (!MDT.dominates(DefI, &*At))
22900b57cec5SDimitry Andric         continue;
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric       // Found one that can be reused.
22930b57cec5SDimitry Andric       assert(Op0.getSubReg() == 0);
22940b57cec5SDimitry Andric       NewR = Op0.getReg();
22950b57cec5SDimitry Andric       break;
22960b57cec5SDimitry Andric     }
22970b57cec5SDimitry Andric     if (!NewR) {
22980b57cec5SDimitry Andric       NewR = MRI.createVirtualRegister(&Hexagon::DoubleRegsRegClass);
22990b57cec5SDimitry Andric       auto NewBS = BuildMI(B, At, DL, HII.get(Hexagon::A4_bitspliti), NewR)
23000b57cec5SDimitry Andric                       .addReg(SrcR, 0, SrcSR)
23010b57cec5SDimitry Andric                       .addImm(ImmOp);
23020b57cec5SDimitry Andric       NewMIs.push_back(NewBS);
23030b57cec5SDimitry Andric     }
23040b57cec5SDimitry Andric     if (Pos <= P) {
23050b57cec5SDimitry Andric       HBS::replaceRegWithSub(RD.Reg, NewR, Hexagon::isub_lo, MRI);
23060b57cec5SDimitry Andric       HBS::replaceRegWithSub(S,      NewR, Hexagon::isub_hi, MRI);
23070b57cec5SDimitry Andric     } else {
23080b57cec5SDimitry Andric       HBS::replaceRegWithSub(S,      NewR, Hexagon::isub_lo, MRI);
23090b57cec5SDimitry Andric       HBS::replaceRegWithSub(RD.Reg, NewR, Hexagon::isub_hi, MRI);
23100b57cec5SDimitry Andric     }
23110b57cec5SDimitry Andric     return true;
23120b57cec5SDimitry Andric   }
23130b57cec5SDimitry Andric 
23140b57cec5SDimitry Andric   return false;
23150b57cec5SDimitry Andric }
23160b57cec5SDimitry Andric 
23170b57cec5SDimitry Andric // Check for tstbit simplification opportunity, where the bit being checked
23180b57cec5SDimitry Andric // can be tracked back to another register. For example:
23190b57cec5SDimitry Andric //   %2 = S2_lsr_i_r  %1, 5
23200b57cec5SDimitry Andric //   %3 = S2_tstbit_i %2, 0
23210b57cec5SDimitry Andric // =>
23220b57cec5SDimitry Andric //   %3 = S2_tstbit_i %1, 5
23230b57cec5SDimitry Andric bool BitSimplification::simplifyTstbit(MachineInstr *MI,
23240b57cec5SDimitry Andric       BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC) {
23250b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
23260b57cec5SDimitry Andric   if (Opc != Hexagon::S2_tstbit_i)
23270b57cec5SDimitry Andric     return false;
23280b57cec5SDimitry Andric 
23290b57cec5SDimitry Andric   unsigned BN = MI->getOperand(2).getImm();
23300b57cec5SDimitry Andric   BitTracker::RegisterRef RS = MI->getOperand(1);
23310b57cec5SDimitry Andric   unsigned F, W;
23320b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
23330b57cec5SDimitry Andric   if (!BT.has(RS.Reg) || !HBS::getSubregMask(RS, F, W, MRI))
23340b57cec5SDimitry Andric     return false;
23350b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
23360b57cec5SDimitry Andric   auto At = MI->isPHI() ? B.getFirstNonPHI()
23370b57cec5SDimitry Andric                         : MachineBasicBlock::iterator(MI);
23380b57cec5SDimitry Andric 
23390b57cec5SDimitry Andric   const BitTracker::RegisterCell &SC = BT.lookup(RS.Reg);
23400b57cec5SDimitry Andric   const BitTracker::BitValue &V = SC[F+BN];
23410b57cec5SDimitry Andric   if (V.Type == BitTracker::BitValue::Ref && V.RefI.Reg != RS.Reg) {
23420b57cec5SDimitry Andric     const TargetRegisterClass *TC = MRI.getRegClass(V.RefI.Reg);
23430b57cec5SDimitry Andric     // Need to map V.RefI.Reg to a 32-bit register, i.e. if it is
23440b57cec5SDimitry Andric     // a double register, need to use a subregister and adjust bit
23450b57cec5SDimitry Andric     // number.
23460b57cec5SDimitry Andric     unsigned P = std::numeric_limits<unsigned>::max();
23470b57cec5SDimitry Andric     BitTracker::RegisterRef RR(V.RefI.Reg, 0);
23480b57cec5SDimitry Andric     if (TC == &Hexagon::DoubleRegsRegClass) {
23490b57cec5SDimitry Andric       P = V.RefI.Pos;
23500b57cec5SDimitry Andric       RR.Sub = Hexagon::isub_lo;
23510b57cec5SDimitry Andric       if (P >= 32) {
23520b57cec5SDimitry Andric         P -= 32;
23530b57cec5SDimitry Andric         RR.Sub = Hexagon::isub_hi;
23540b57cec5SDimitry Andric       }
23550b57cec5SDimitry Andric     } else if (TC == &Hexagon::IntRegsRegClass) {
23560b57cec5SDimitry Andric       P = V.RefI.Pos;
23570b57cec5SDimitry Andric     }
23580b57cec5SDimitry Andric     if (P != std::numeric_limits<unsigned>::max()) {
23590b57cec5SDimitry Andric       unsigned NewR = MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);
23600b57cec5SDimitry Andric       BuildMI(B, At, DL, HII.get(Hexagon::S2_tstbit_i), NewR)
23610b57cec5SDimitry Andric           .addReg(RR.Reg, 0, RR.Sub)
23620b57cec5SDimitry Andric           .addImm(P);
23630b57cec5SDimitry Andric       HBS::replaceReg(RD.Reg, NewR, MRI);
23640b57cec5SDimitry Andric       BT.put(NewR, RC);
23650b57cec5SDimitry Andric       return true;
23660b57cec5SDimitry Andric     }
23670b57cec5SDimitry Andric   } else if (V.is(0) || V.is(1)) {
2368*8bcb0991SDimitry Andric     Register NewR = MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);
23690b57cec5SDimitry Andric     unsigned NewOpc = V.is(0) ? Hexagon::PS_false : Hexagon::PS_true;
23700b57cec5SDimitry Andric     BuildMI(B, At, DL, HII.get(NewOpc), NewR);
23710b57cec5SDimitry Andric     HBS::replaceReg(RD.Reg, NewR, MRI);
23720b57cec5SDimitry Andric     return true;
23730b57cec5SDimitry Andric   }
23740b57cec5SDimitry Andric 
23750b57cec5SDimitry Andric   return false;
23760b57cec5SDimitry Andric }
23770b57cec5SDimitry Andric 
23780b57cec5SDimitry Andric // Detect whether RD is a bitfield extract (sign- or zero-extended) of
23790b57cec5SDimitry Andric // some register from the AVs set. Create a new corresponding instruction
23800b57cec5SDimitry Andric // at the location of MI. The intent is to recognize situations where
23810b57cec5SDimitry Andric // a sequence of instructions performs an operation that is equivalent to
23820b57cec5SDimitry Andric // an extract operation, such as a shift left followed by a shift right.
23830b57cec5SDimitry Andric bool BitSimplification::simplifyExtractLow(MachineInstr *MI,
23840b57cec5SDimitry Andric       BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC,
23850b57cec5SDimitry Andric       const RegisterSet &AVs) {
23860b57cec5SDimitry Andric   if (!GenExtract)
23870b57cec5SDimitry Andric     return false;
23880b57cec5SDimitry Andric   if (MaxExtract.getNumOccurrences()) {
23890b57cec5SDimitry Andric     if (CountExtract >= MaxExtract)
23900b57cec5SDimitry Andric       return false;
23910b57cec5SDimitry Andric     CountExtract++;
23920b57cec5SDimitry Andric   }
23930b57cec5SDimitry Andric 
23940b57cec5SDimitry Andric   unsigned W = RC.width();
23950b57cec5SDimitry Andric   unsigned RW = W;
23960b57cec5SDimitry Andric   unsigned Len;
23970b57cec5SDimitry Andric   bool Signed;
23980b57cec5SDimitry Andric 
23990b57cec5SDimitry Andric   // The code is mostly class-independent, except for the part that generates
24000b57cec5SDimitry Andric   // the extract instruction, and establishes the source register (in case it
24010b57cec5SDimitry Andric   // needs to use a subregister).
24020b57cec5SDimitry Andric   const TargetRegisterClass *FRC = HBS::getFinalVRegClass(RD, MRI);
24030b57cec5SDimitry Andric   if (FRC != &Hexagon::IntRegsRegClass && FRC != &Hexagon::DoubleRegsRegClass)
24040b57cec5SDimitry Andric     return false;
24050b57cec5SDimitry Andric   assert(RD.Sub == 0);
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric   // Observation:
24080b57cec5SDimitry Andric   // If the cell has a form of 00..0xx..x with k zeros and n remaining
24090b57cec5SDimitry Andric   // bits, this could be an extractu of the n bits, but it could also be
24100b57cec5SDimitry Andric   // an extractu of a longer field which happens to have 0s in the top
24110b57cec5SDimitry Andric   // bit positions.
24120b57cec5SDimitry Andric   // The same logic applies to sign-extended fields.
24130b57cec5SDimitry Andric   //
24140b57cec5SDimitry Andric   // Do not check for the extended extracts, since it would expand the
24150b57cec5SDimitry Andric   // search space quite a bit. The search may be expensive as it is.
24160b57cec5SDimitry Andric 
24170b57cec5SDimitry Andric   const BitTracker::BitValue &TopV = RC[W-1];
24180b57cec5SDimitry Andric 
24190b57cec5SDimitry Andric   // Eliminate candidates that have self-referential bits, since they
24200b57cec5SDimitry Andric   // cannot be extracts from other registers. Also, skip registers that
24210b57cec5SDimitry Andric   // have compile-time constant values.
24220b57cec5SDimitry Andric   bool IsConst = true;
24230b57cec5SDimitry Andric   for (unsigned I = 0; I != W; ++I) {
24240b57cec5SDimitry Andric     const BitTracker::BitValue &V = RC[I];
24250b57cec5SDimitry Andric     if (V.Type == BitTracker::BitValue::Ref && V.RefI.Reg == RD.Reg)
24260b57cec5SDimitry Andric       return false;
24270b57cec5SDimitry Andric     IsConst = IsConst && (V.is(0) || V.is(1));
24280b57cec5SDimitry Andric   }
24290b57cec5SDimitry Andric   if (IsConst)
24300b57cec5SDimitry Andric     return false;
24310b57cec5SDimitry Andric 
24320b57cec5SDimitry Andric   if (TopV.is(0) || TopV.is(1)) {
24330b57cec5SDimitry Andric     bool S = TopV.is(1);
24340b57cec5SDimitry Andric     for (--W; W > 0 && RC[W-1].is(S); --W)
24350b57cec5SDimitry Andric       ;
24360b57cec5SDimitry Andric     Len = W;
24370b57cec5SDimitry Andric     Signed = S;
24380b57cec5SDimitry Andric     // The sign bit must be a part of the field being extended.
24390b57cec5SDimitry Andric     if (Signed)
24400b57cec5SDimitry Andric       ++Len;
24410b57cec5SDimitry Andric   } else {
24420b57cec5SDimitry Andric     // This could still be a sign-extended extract.
24430b57cec5SDimitry Andric     assert(TopV.Type == BitTracker::BitValue::Ref);
24440b57cec5SDimitry Andric     if (TopV.RefI.Reg == RD.Reg || TopV.RefI.Pos == W-1)
24450b57cec5SDimitry Andric       return false;
24460b57cec5SDimitry Andric     for (--W; W > 0 && RC[W-1] == TopV; --W)
24470b57cec5SDimitry Andric       ;
24480b57cec5SDimitry Andric     // The top bits of RC are copies of TopV. One occurrence of TopV will
24490b57cec5SDimitry Andric     // be a part of the field.
24500b57cec5SDimitry Andric     Len = W + 1;
24510b57cec5SDimitry Andric     Signed = true;
24520b57cec5SDimitry Andric   }
24530b57cec5SDimitry Andric 
24540b57cec5SDimitry Andric   // This would be just a copy. It should be handled elsewhere.
24550b57cec5SDimitry Andric   if (Len == RW)
24560b57cec5SDimitry Andric     return false;
24570b57cec5SDimitry Andric 
24580b57cec5SDimitry Andric   LLVM_DEBUG({
24590b57cec5SDimitry Andric     dbgs() << __func__ << " on reg: " << printReg(RD.Reg, &HRI, RD.Sub)
24600b57cec5SDimitry Andric            << ", MI: " << *MI;
24610b57cec5SDimitry Andric     dbgs() << "Cell: " << RC << '\n';
24620b57cec5SDimitry Andric     dbgs() << "Expected bitfield size: " << Len << " bits, "
24630b57cec5SDimitry Andric            << (Signed ? "sign" : "zero") << "-extended\n";
24640b57cec5SDimitry Andric   });
24650b57cec5SDimitry Andric 
24660b57cec5SDimitry Andric   bool Changed = false;
24670b57cec5SDimitry Andric 
24680b57cec5SDimitry Andric   for (unsigned R = AVs.find_first(); R != 0; R = AVs.find_next(R)) {
24690b57cec5SDimitry Andric     if (!BT.has(R))
24700b57cec5SDimitry Andric       continue;
24710b57cec5SDimitry Andric     const BitTracker::RegisterCell &SC = BT.lookup(R);
24720b57cec5SDimitry Andric     unsigned SW = SC.width();
24730b57cec5SDimitry Andric 
24740b57cec5SDimitry Andric     // The source can be longer than the destination, as long as its size is
24750b57cec5SDimitry Andric     // a multiple of the size of the destination. Also, we would need to be
24760b57cec5SDimitry Andric     // able to refer to the subregister in the source that would be of the
24770b57cec5SDimitry Andric     // same size as the destination, but only check the sizes here.
24780b57cec5SDimitry Andric     if (SW < RW || (SW % RW) != 0)
24790b57cec5SDimitry Andric       continue;
24800b57cec5SDimitry Andric 
24810b57cec5SDimitry Andric     // The field can start at any offset in SC as long as it contains Len
24820b57cec5SDimitry Andric     // bits and does not cross subregister boundary (if the source register
24830b57cec5SDimitry Andric     // is longer than the destination).
24840b57cec5SDimitry Andric     unsigned Off = 0;
24850b57cec5SDimitry Andric     while (Off <= SW-Len) {
24860b57cec5SDimitry Andric       unsigned OE = (Off+Len)/RW;
24870b57cec5SDimitry Andric       if (OE != Off/RW) {
24880b57cec5SDimitry Andric         // The assumption here is that if the source (R) is longer than the
24890b57cec5SDimitry Andric         // destination, then the destination is a sequence of words of
24900b57cec5SDimitry Andric         // size RW, and each such word in R can be accessed via a subregister.
24910b57cec5SDimitry Andric         //
24920b57cec5SDimitry Andric         // If the beginning and the end of the field cross the subregister
24930b57cec5SDimitry Andric         // boundary, advance to the next subregister.
24940b57cec5SDimitry Andric         Off = OE*RW;
24950b57cec5SDimitry Andric         continue;
24960b57cec5SDimitry Andric       }
24970b57cec5SDimitry Andric       if (HBS::isEqual(RC, 0, SC, Off, Len))
24980b57cec5SDimitry Andric         break;
24990b57cec5SDimitry Andric       ++Off;
25000b57cec5SDimitry Andric     }
25010b57cec5SDimitry Andric 
25020b57cec5SDimitry Andric     if (Off > SW-Len)
25030b57cec5SDimitry Andric       continue;
25040b57cec5SDimitry Andric 
25050b57cec5SDimitry Andric     // Found match.
25060b57cec5SDimitry Andric     unsigned ExtOpc = 0;
25070b57cec5SDimitry Andric     if (Off == 0) {
25080b57cec5SDimitry Andric       if (Len == 8)
25090b57cec5SDimitry Andric         ExtOpc = Signed ? Hexagon::A2_sxtb : Hexagon::A2_zxtb;
25100b57cec5SDimitry Andric       else if (Len == 16)
25110b57cec5SDimitry Andric         ExtOpc = Signed ? Hexagon::A2_sxth : Hexagon::A2_zxth;
25120b57cec5SDimitry Andric       else if (Len < 10 && !Signed)
25130b57cec5SDimitry Andric         ExtOpc = Hexagon::A2_andir;
25140b57cec5SDimitry Andric     }
25150b57cec5SDimitry Andric     if (ExtOpc == 0) {
25160b57cec5SDimitry Andric       ExtOpc =
25170b57cec5SDimitry Andric           Signed ? (RW == 32 ? Hexagon::S4_extract  : Hexagon::S4_extractp)
25180b57cec5SDimitry Andric                  : (RW == 32 ? Hexagon::S2_extractu : Hexagon::S2_extractup);
25190b57cec5SDimitry Andric     }
25200b57cec5SDimitry Andric     unsigned SR = 0;
25210b57cec5SDimitry Andric     // This only recognizes isub_lo and isub_hi.
25220b57cec5SDimitry Andric     if (RW != SW && RW*2 != SW)
25230b57cec5SDimitry Andric       continue;
25240b57cec5SDimitry Andric     if (RW != SW)
25250b57cec5SDimitry Andric       SR = (Off/RW == 0) ? Hexagon::isub_lo : Hexagon::isub_hi;
25260b57cec5SDimitry Andric     Off = Off % RW;
25270b57cec5SDimitry Andric 
25280b57cec5SDimitry Andric     if (!validateReg({R,SR}, ExtOpc, 1))
25290b57cec5SDimitry Andric       continue;
25300b57cec5SDimitry Andric 
25310b57cec5SDimitry Andric     // Don't generate the same instruction as the one being optimized.
25320b57cec5SDimitry Andric     if (MI->getOpcode() == ExtOpc) {
25330b57cec5SDimitry Andric       // All possible ExtOpc's have the source in operand(1).
25340b57cec5SDimitry Andric       const MachineOperand &SrcOp = MI->getOperand(1);
25350b57cec5SDimitry Andric       if (SrcOp.getReg() == R)
25360b57cec5SDimitry Andric         continue;
25370b57cec5SDimitry Andric     }
25380b57cec5SDimitry Andric 
25390b57cec5SDimitry Andric     DebugLoc DL = MI->getDebugLoc();
25400b57cec5SDimitry Andric     MachineBasicBlock &B = *MI->getParent();
2541*8bcb0991SDimitry Andric     Register NewR = MRI.createVirtualRegister(FRC);
25420b57cec5SDimitry Andric     auto At = MI->isPHI() ? B.getFirstNonPHI()
25430b57cec5SDimitry Andric                           : MachineBasicBlock::iterator(MI);
25440b57cec5SDimitry Andric     auto MIB = BuildMI(B, At, DL, HII.get(ExtOpc), NewR)
25450b57cec5SDimitry Andric                   .addReg(R, 0, SR);
25460b57cec5SDimitry Andric     switch (ExtOpc) {
25470b57cec5SDimitry Andric       case Hexagon::A2_sxtb:
25480b57cec5SDimitry Andric       case Hexagon::A2_zxtb:
25490b57cec5SDimitry Andric       case Hexagon::A2_sxth:
25500b57cec5SDimitry Andric       case Hexagon::A2_zxth:
25510b57cec5SDimitry Andric         break;
25520b57cec5SDimitry Andric       case Hexagon::A2_andir:
25530b57cec5SDimitry Andric         MIB.addImm((1u << Len) - 1);
25540b57cec5SDimitry Andric         break;
25550b57cec5SDimitry Andric       case Hexagon::S4_extract:
25560b57cec5SDimitry Andric       case Hexagon::S2_extractu:
25570b57cec5SDimitry Andric       case Hexagon::S4_extractp:
25580b57cec5SDimitry Andric       case Hexagon::S2_extractup:
25590b57cec5SDimitry Andric         MIB.addImm(Len)
25600b57cec5SDimitry Andric            .addImm(Off);
25610b57cec5SDimitry Andric         break;
25620b57cec5SDimitry Andric       default:
25630b57cec5SDimitry Andric         llvm_unreachable("Unexpected opcode");
25640b57cec5SDimitry Andric     }
25650b57cec5SDimitry Andric 
25660b57cec5SDimitry Andric     HBS::replaceReg(RD.Reg, NewR, MRI);
25670b57cec5SDimitry Andric     BT.put(BitTracker::RegisterRef(NewR), RC);
25680b57cec5SDimitry Andric     Changed = true;
25690b57cec5SDimitry Andric     break;
25700b57cec5SDimitry Andric   }
25710b57cec5SDimitry Andric 
25720b57cec5SDimitry Andric   return Changed;
25730b57cec5SDimitry Andric }
25740b57cec5SDimitry Andric 
25750b57cec5SDimitry Andric bool BitSimplification::simplifyRCmp0(MachineInstr *MI,
25760b57cec5SDimitry Andric       BitTracker::RegisterRef RD) {
25770b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
25780b57cec5SDimitry Andric   if (Opc != Hexagon::A4_rcmpeqi && Opc != Hexagon::A4_rcmpneqi)
25790b57cec5SDimitry Andric     return false;
25800b57cec5SDimitry Andric   MachineOperand &CmpOp = MI->getOperand(2);
25810b57cec5SDimitry Andric   if (!CmpOp.isImm() || CmpOp.getImm() != 0)
25820b57cec5SDimitry Andric     return false;
25830b57cec5SDimitry Andric 
25840b57cec5SDimitry Andric   const TargetRegisterClass *FRC = HBS::getFinalVRegClass(RD, MRI);
25850b57cec5SDimitry Andric   if (FRC != &Hexagon::IntRegsRegClass && FRC != &Hexagon::DoubleRegsRegClass)
25860b57cec5SDimitry Andric     return false;
25870b57cec5SDimitry Andric   assert(RD.Sub == 0);
25880b57cec5SDimitry Andric 
25890b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
25900b57cec5SDimitry Andric   const DebugLoc &DL = MI->getDebugLoc();
25910b57cec5SDimitry Andric   auto At = MI->isPHI() ? B.getFirstNonPHI()
25920b57cec5SDimitry Andric                         : MachineBasicBlock::iterator(MI);
25930b57cec5SDimitry Andric   bool KnownZ = true;
25940b57cec5SDimitry Andric   bool KnownNZ = false;
25950b57cec5SDimitry Andric 
25960b57cec5SDimitry Andric   BitTracker::RegisterRef SR = MI->getOperand(1);
25970b57cec5SDimitry Andric   if (!BT.has(SR.Reg))
25980b57cec5SDimitry Andric     return false;
25990b57cec5SDimitry Andric   const BitTracker::RegisterCell &SC = BT.lookup(SR.Reg);
26000b57cec5SDimitry Andric   unsigned F, W;
26010b57cec5SDimitry Andric   if (!HBS::getSubregMask(SR, F, W, MRI))
26020b57cec5SDimitry Andric     return false;
26030b57cec5SDimitry Andric 
26040b57cec5SDimitry Andric   for (uint16_t I = F; I != F+W; ++I) {
26050b57cec5SDimitry Andric     const BitTracker::BitValue &V = SC[I];
26060b57cec5SDimitry Andric     if (!V.is(0))
26070b57cec5SDimitry Andric       KnownZ = false;
26080b57cec5SDimitry Andric     if (V.is(1))
26090b57cec5SDimitry Andric       KnownNZ = true;
26100b57cec5SDimitry Andric   }
26110b57cec5SDimitry Andric 
26120b57cec5SDimitry Andric   auto ReplaceWithConst = [&](int C) {
2613*8bcb0991SDimitry Andric     Register NewR = MRI.createVirtualRegister(FRC);
26140b57cec5SDimitry Andric     BuildMI(B, At, DL, HII.get(Hexagon::A2_tfrsi), NewR)
26150b57cec5SDimitry Andric       .addImm(C);
26160b57cec5SDimitry Andric     HBS::replaceReg(RD.Reg, NewR, MRI);
26170b57cec5SDimitry Andric     BitTracker::RegisterCell NewRC(W);
26180b57cec5SDimitry Andric     for (uint16_t I = 0; I != W; ++I) {
26190b57cec5SDimitry Andric       NewRC[I] = BitTracker::BitValue(C & 1);
26200b57cec5SDimitry Andric       C = unsigned(C) >> 1;
26210b57cec5SDimitry Andric     }
26220b57cec5SDimitry Andric     BT.put(BitTracker::RegisterRef(NewR), NewRC);
26230b57cec5SDimitry Andric     return true;
26240b57cec5SDimitry Andric   };
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric   auto IsNonZero = [] (const MachineOperand &Op) {
26270b57cec5SDimitry Andric     if (Op.isGlobal() || Op.isBlockAddress())
26280b57cec5SDimitry Andric       return true;
26290b57cec5SDimitry Andric     if (Op.isImm())
26300b57cec5SDimitry Andric       return Op.getImm() != 0;
26310b57cec5SDimitry Andric     if (Op.isCImm())
26320b57cec5SDimitry Andric       return !Op.getCImm()->isZero();
26330b57cec5SDimitry Andric     if (Op.isFPImm())
26340b57cec5SDimitry Andric       return !Op.getFPImm()->isZero();
26350b57cec5SDimitry Andric     return false;
26360b57cec5SDimitry Andric   };
26370b57cec5SDimitry Andric 
26380b57cec5SDimitry Andric   auto IsZero = [] (const MachineOperand &Op) {
26390b57cec5SDimitry Andric     if (Op.isGlobal() || Op.isBlockAddress())
26400b57cec5SDimitry Andric       return false;
26410b57cec5SDimitry Andric     if (Op.isImm())
26420b57cec5SDimitry Andric       return Op.getImm() == 0;
26430b57cec5SDimitry Andric     if (Op.isCImm())
26440b57cec5SDimitry Andric       return Op.getCImm()->isZero();
26450b57cec5SDimitry Andric     if (Op.isFPImm())
26460b57cec5SDimitry Andric       return Op.getFPImm()->isZero();
26470b57cec5SDimitry Andric     return false;
26480b57cec5SDimitry Andric   };
26490b57cec5SDimitry Andric 
26500b57cec5SDimitry Andric   // If the source register is known to be 0 or non-0, the comparison can
26510b57cec5SDimitry Andric   // be folded to a load of a constant.
26520b57cec5SDimitry Andric   if (KnownZ || KnownNZ) {
26530b57cec5SDimitry Andric     assert(KnownZ != KnownNZ && "Register cannot be both 0 and non-0");
26540b57cec5SDimitry Andric     return ReplaceWithConst(KnownZ == (Opc == Hexagon::A4_rcmpeqi));
26550b57cec5SDimitry Andric   }
26560b57cec5SDimitry Andric 
26570b57cec5SDimitry Andric   // Special case: if the compare comes from a C2_muxii, then we know the
26580b57cec5SDimitry Andric   // two possible constants that can be the source value.
26590b57cec5SDimitry Andric   MachineInstr *InpDef = MRI.getVRegDef(SR.Reg);
26600b57cec5SDimitry Andric   if (!InpDef)
26610b57cec5SDimitry Andric     return false;
26620b57cec5SDimitry Andric   if (SR.Sub == 0 && InpDef->getOpcode() == Hexagon::C2_muxii) {
26630b57cec5SDimitry Andric     MachineOperand &Src1 = InpDef->getOperand(2);
26640b57cec5SDimitry Andric     MachineOperand &Src2 = InpDef->getOperand(3);
26650b57cec5SDimitry Andric     // Check if both are non-zero.
26660b57cec5SDimitry Andric     bool KnownNZ1 = IsNonZero(Src1), KnownNZ2 = IsNonZero(Src2);
26670b57cec5SDimitry Andric     if (KnownNZ1 && KnownNZ2)
26680b57cec5SDimitry Andric       return ReplaceWithConst(Opc == Hexagon::A4_rcmpneqi);
26690b57cec5SDimitry Andric     // Check if both are zero.
26700b57cec5SDimitry Andric     bool KnownZ1 = IsZero(Src1), KnownZ2 = IsZero(Src2);
26710b57cec5SDimitry Andric     if (KnownZ1 && KnownZ2)
26720b57cec5SDimitry Andric       return ReplaceWithConst(Opc == Hexagon::A4_rcmpeqi);
26730b57cec5SDimitry Andric 
26740b57cec5SDimitry Andric     // If for both operands we know that they are either 0 or non-0,
26750b57cec5SDimitry Andric     // replace the comparison with a C2_muxii, using the same predicate
26760b57cec5SDimitry Andric     // register, but with operands substituted with 0/1 accordingly.
26770b57cec5SDimitry Andric     if ((KnownZ1 || KnownNZ1) && (KnownZ2 || KnownNZ2)) {
2678*8bcb0991SDimitry Andric       Register NewR = MRI.createVirtualRegister(FRC);
26790b57cec5SDimitry Andric       BuildMI(B, At, DL, HII.get(Hexagon::C2_muxii), NewR)
26800b57cec5SDimitry Andric         .addReg(InpDef->getOperand(1).getReg())
26810b57cec5SDimitry Andric         .addImm(KnownZ1 == (Opc == Hexagon::A4_rcmpeqi))
26820b57cec5SDimitry Andric         .addImm(KnownZ2 == (Opc == Hexagon::A4_rcmpeqi));
26830b57cec5SDimitry Andric       HBS::replaceReg(RD.Reg, NewR, MRI);
26840b57cec5SDimitry Andric       // Create a new cell with only the least significant bit unknown.
26850b57cec5SDimitry Andric       BitTracker::RegisterCell NewRC(W);
26860b57cec5SDimitry Andric       NewRC[0] = BitTracker::BitValue::self();
26870b57cec5SDimitry Andric       NewRC.fill(1, W, BitTracker::BitValue::Zero);
26880b57cec5SDimitry Andric       BT.put(BitTracker::RegisterRef(NewR), NewRC);
26890b57cec5SDimitry Andric       return true;
26900b57cec5SDimitry Andric     }
26910b57cec5SDimitry Andric   }
26920b57cec5SDimitry Andric 
26930b57cec5SDimitry Andric   return false;
26940b57cec5SDimitry Andric }
26950b57cec5SDimitry Andric 
26960b57cec5SDimitry Andric bool BitSimplification::processBlock(MachineBasicBlock &B,
26970b57cec5SDimitry Andric       const RegisterSet &AVs) {
26980b57cec5SDimitry Andric   if (!BT.reached(&B))
26990b57cec5SDimitry Andric     return false;
27000b57cec5SDimitry Andric   bool Changed = false;
27010b57cec5SDimitry Andric   RegisterSet AVB = AVs;
27020b57cec5SDimitry Andric   RegisterSet Defs;
27030b57cec5SDimitry Andric 
27040b57cec5SDimitry Andric   for (auto I = B.begin(), E = B.end(); I != E; ++I, AVB.insert(Defs)) {
27050b57cec5SDimitry Andric     MachineInstr *MI = &*I;
27060b57cec5SDimitry Andric     Defs.clear();
27070b57cec5SDimitry Andric     HBS::getInstrDefs(*MI, Defs);
27080b57cec5SDimitry Andric 
27090b57cec5SDimitry Andric     unsigned Opc = MI->getOpcode();
27100b57cec5SDimitry Andric     if (Opc == TargetOpcode::COPY || Opc == TargetOpcode::REG_SEQUENCE)
27110b57cec5SDimitry Andric       continue;
27120b57cec5SDimitry Andric 
27130b57cec5SDimitry Andric     if (MI->mayStore()) {
27140b57cec5SDimitry Andric       bool T = genStoreUpperHalf(MI);
27150b57cec5SDimitry Andric       T = T || genStoreImmediate(MI);
27160b57cec5SDimitry Andric       Changed |= T;
27170b57cec5SDimitry Andric       continue;
27180b57cec5SDimitry Andric     }
27190b57cec5SDimitry Andric 
27200b57cec5SDimitry Andric     if (Defs.count() != 1)
27210b57cec5SDimitry Andric       continue;
27220b57cec5SDimitry Andric     const MachineOperand &Op0 = MI->getOperand(0);
27230b57cec5SDimitry Andric     if (!Op0.isReg() || !Op0.isDef())
27240b57cec5SDimitry Andric       continue;
27250b57cec5SDimitry Andric     BitTracker::RegisterRef RD = Op0;
27260b57cec5SDimitry Andric     if (!BT.has(RD.Reg))
27270b57cec5SDimitry Andric       continue;
27280b57cec5SDimitry Andric     const TargetRegisterClass *FRC = HBS::getFinalVRegClass(RD, MRI);
27290b57cec5SDimitry Andric     const BitTracker::RegisterCell &RC = BT.lookup(RD.Reg);
27300b57cec5SDimitry Andric 
27310b57cec5SDimitry Andric     if (FRC->getID() == Hexagon::DoubleRegsRegClassID) {
27320b57cec5SDimitry Andric       bool T = genPackhl(MI, RD, RC);
27330b57cec5SDimitry Andric       T = T || simplifyExtractLow(MI, RD, RC, AVB);
27340b57cec5SDimitry Andric       Changed |= T;
27350b57cec5SDimitry Andric       continue;
27360b57cec5SDimitry Andric     }
27370b57cec5SDimitry Andric 
27380b57cec5SDimitry Andric     if (FRC->getID() == Hexagon::IntRegsRegClassID) {
27390b57cec5SDimitry Andric       bool T = genBitSplit(MI, RD, RC, AVB);
27400b57cec5SDimitry Andric       T = T || simplifyExtractLow(MI, RD, RC, AVB);
27410b57cec5SDimitry Andric       T = T || genExtractHalf(MI, RD, RC);
27420b57cec5SDimitry Andric       T = T || genCombineHalf(MI, RD, RC);
27430b57cec5SDimitry Andric       T = T || genExtractLow(MI, RD, RC);
27440b57cec5SDimitry Andric       T = T || simplifyRCmp0(MI, RD);
27450b57cec5SDimitry Andric       Changed |= T;
27460b57cec5SDimitry Andric       continue;
27470b57cec5SDimitry Andric     }
27480b57cec5SDimitry Andric 
27490b57cec5SDimitry Andric     if (FRC->getID() == Hexagon::PredRegsRegClassID) {
27500b57cec5SDimitry Andric       bool T = simplifyTstbit(MI, RD, RC);
27510b57cec5SDimitry Andric       Changed |= T;
27520b57cec5SDimitry Andric       continue;
27530b57cec5SDimitry Andric     }
27540b57cec5SDimitry Andric   }
27550b57cec5SDimitry Andric   return Changed;
27560b57cec5SDimitry Andric }
27570b57cec5SDimitry Andric 
27580b57cec5SDimitry Andric bool HexagonBitSimplify::runOnMachineFunction(MachineFunction &MF) {
27590b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
27600b57cec5SDimitry Andric     return false;
27610b57cec5SDimitry Andric 
27620b57cec5SDimitry Andric   auto &HST = MF.getSubtarget<HexagonSubtarget>();
27630b57cec5SDimitry Andric   auto &HRI = *HST.getRegisterInfo();
27640b57cec5SDimitry Andric   auto &HII = *HST.getInstrInfo();
27650b57cec5SDimitry Andric 
27660b57cec5SDimitry Andric   MDT = &getAnalysis<MachineDominatorTree>();
27670b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
27680b57cec5SDimitry Andric   bool Changed;
27690b57cec5SDimitry Andric 
27700b57cec5SDimitry Andric   Changed = DeadCodeElimination(MF, *MDT).run();
27710b57cec5SDimitry Andric 
27720b57cec5SDimitry Andric   const HexagonEvaluator HE(HRI, MRI, HII, MF);
27730b57cec5SDimitry Andric   BitTracker BT(HE, MF);
27740b57cec5SDimitry Andric   LLVM_DEBUG(BT.trace(true));
27750b57cec5SDimitry Andric   BT.run();
27760b57cec5SDimitry Andric 
27770b57cec5SDimitry Andric   MachineBasicBlock &Entry = MF.front();
27780b57cec5SDimitry Andric 
27790b57cec5SDimitry Andric   RegisterSet AIG;  // Available registers for IG.
27800b57cec5SDimitry Andric   ConstGeneration ImmG(BT, HII, MRI);
27810b57cec5SDimitry Andric   Changed |= visitBlock(Entry, ImmG, AIG);
27820b57cec5SDimitry Andric 
27830b57cec5SDimitry Andric   RegisterSet ARE;  // Available registers for RIE.
27840b57cec5SDimitry Andric   RedundantInstrElimination RIE(BT, HII, HRI, MRI);
27850b57cec5SDimitry Andric   bool Ried = visitBlock(Entry, RIE, ARE);
27860b57cec5SDimitry Andric   if (Ried) {
27870b57cec5SDimitry Andric     Changed = true;
27880b57cec5SDimitry Andric     BT.run();
27890b57cec5SDimitry Andric   }
27900b57cec5SDimitry Andric 
27910b57cec5SDimitry Andric   RegisterSet ACG;  // Available registers for CG.
27920b57cec5SDimitry Andric   CopyGeneration CopyG(BT, HII, HRI, MRI);
27930b57cec5SDimitry Andric   Changed |= visitBlock(Entry, CopyG, ACG);
27940b57cec5SDimitry Andric 
27950b57cec5SDimitry Andric   RegisterSet ACP;  // Available registers for CP.
27960b57cec5SDimitry Andric   CopyPropagation CopyP(HRI, MRI);
27970b57cec5SDimitry Andric   Changed |= visitBlock(Entry, CopyP, ACP);
27980b57cec5SDimitry Andric 
27990b57cec5SDimitry Andric   Changed = DeadCodeElimination(MF, *MDT).run() || Changed;
28000b57cec5SDimitry Andric 
28010b57cec5SDimitry Andric   BT.run();
28020b57cec5SDimitry Andric   RegisterSet ABS;  // Available registers for BS.
28030b57cec5SDimitry Andric   BitSimplification BitS(BT, *MDT, HII, HRI, MRI, MF);
28040b57cec5SDimitry Andric   Changed |= visitBlock(Entry, BitS, ABS);
28050b57cec5SDimitry Andric 
28060b57cec5SDimitry Andric   Changed = DeadCodeElimination(MF, *MDT).run() || Changed;
28070b57cec5SDimitry Andric 
28080b57cec5SDimitry Andric   if (Changed) {
28090b57cec5SDimitry Andric     for (auto &B : MF)
28100b57cec5SDimitry Andric       for (auto &I : B)
28110b57cec5SDimitry Andric         I.clearKillInfo();
28120b57cec5SDimitry Andric     DeadCodeElimination(MF, *MDT).run();
28130b57cec5SDimitry Andric   }
28140b57cec5SDimitry Andric   return Changed;
28150b57cec5SDimitry Andric }
28160b57cec5SDimitry Andric 
28170b57cec5SDimitry Andric // Recognize loops where the code at the end of the loop matches the code
28180b57cec5SDimitry Andric // before the entry of the loop, and the matching code is such that is can
28190b57cec5SDimitry Andric // be simplified. This pass relies on the bit simplification above and only
28200b57cec5SDimitry Andric // prepares code in a way that can be handled by the bit simplifcation.
28210b57cec5SDimitry Andric //
28220b57cec5SDimitry Andric // This is the motivating testcase (and explanation):
28230b57cec5SDimitry Andric //
28240b57cec5SDimitry Andric // {
28250b57cec5SDimitry Andric //   loop0(.LBB0_2, r1)      // %for.body.preheader
28260b57cec5SDimitry Andric //   r5:4 = memd(r0++#8)
28270b57cec5SDimitry Andric // }
28280b57cec5SDimitry Andric // {
28290b57cec5SDimitry Andric //   r3 = lsr(r4, #16)
28300b57cec5SDimitry Andric //   r7:6 = combine(r5, r5)
28310b57cec5SDimitry Andric // }
28320b57cec5SDimitry Andric // {
28330b57cec5SDimitry Andric //   r3 = insert(r5, #16, #16)
28340b57cec5SDimitry Andric //   r7:6 = vlsrw(r7:6, #16)
28350b57cec5SDimitry Andric // }
28360b57cec5SDimitry Andric // .LBB0_2:
28370b57cec5SDimitry Andric // {
28380b57cec5SDimitry Andric //   memh(r2+#4) = r5
28390b57cec5SDimitry Andric //   memh(r2+#6) = r6            # R6 is really R5.H
28400b57cec5SDimitry Andric // }
28410b57cec5SDimitry Andric // {
28420b57cec5SDimitry Andric //   r2 = add(r2, #8)
28430b57cec5SDimitry Andric //   memh(r2+#0) = r4
28440b57cec5SDimitry Andric //   memh(r2+#2) = r3            # R3 is really R4.H
28450b57cec5SDimitry Andric // }
28460b57cec5SDimitry Andric // {
28470b57cec5SDimitry Andric //   r5:4 = memd(r0++#8)
28480b57cec5SDimitry Andric // }
28490b57cec5SDimitry Andric // {                             # "Shuffling" code that sets up R3 and R6
28500b57cec5SDimitry Andric //   r3 = lsr(r4, #16)           # so that their halves can be stored in the
28510b57cec5SDimitry Andric //   r7:6 = combine(r5, r5)      # next iteration. This could be folded into
28520b57cec5SDimitry Andric // }                             # the stores if the code was at the beginning
28530b57cec5SDimitry Andric // {                             # of the loop iteration. Since the same code
28540b57cec5SDimitry Andric //   r3 = insert(r5, #16, #16)   # precedes the loop, it can actually be moved
28550b57cec5SDimitry Andric //   r7:6 = vlsrw(r7:6, #16)     # there.
28560b57cec5SDimitry Andric // }:endloop0
28570b57cec5SDimitry Andric //
28580b57cec5SDimitry Andric //
28590b57cec5SDimitry Andric // The outcome:
28600b57cec5SDimitry Andric //
28610b57cec5SDimitry Andric // {
28620b57cec5SDimitry Andric //   loop0(.LBB0_2, r1)
28630b57cec5SDimitry Andric //   r5:4 = memd(r0++#8)
28640b57cec5SDimitry Andric // }
28650b57cec5SDimitry Andric // .LBB0_2:
28660b57cec5SDimitry Andric // {
28670b57cec5SDimitry Andric //   memh(r2+#4) = r5
28680b57cec5SDimitry Andric //   memh(r2+#6) = r5.h
28690b57cec5SDimitry Andric // }
28700b57cec5SDimitry Andric // {
28710b57cec5SDimitry Andric //   r2 = add(r2, #8)
28720b57cec5SDimitry Andric //   memh(r2+#0) = r4
28730b57cec5SDimitry Andric //   memh(r2+#2) = r4.h
28740b57cec5SDimitry Andric // }
28750b57cec5SDimitry Andric // {
28760b57cec5SDimitry Andric //   r5:4 = memd(r0++#8)
28770b57cec5SDimitry Andric // }:endloop0
28780b57cec5SDimitry Andric 
28790b57cec5SDimitry Andric namespace llvm {
28800b57cec5SDimitry Andric 
28810b57cec5SDimitry Andric   FunctionPass *createHexagonLoopRescheduling();
28820b57cec5SDimitry Andric   void initializeHexagonLoopReschedulingPass(PassRegistry&);
28830b57cec5SDimitry Andric 
28840b57cec5SDimitry Andric } // end namespace llvm
28850b57cec5SDimitry Andric 
28860b57cec5SDimitry Andric namespace {
28870b57cec5SDimitry Andric 
28880b57cec5SDimitry Andric   class HexagonLoopRescheduling : public MachineFunctionPass {
28890b57cec5SDimitry Andric   public:
28900b57cec5SDimitry Andric     static char ID;
28910b57cec5SDimitry Andric 
28920b57cec5SDimitry Andric     HexagonLoopRescheduling() : MachineFunctionPass(ID) {
28930b57cec5SDimitry Andric       initializeHexagonLoopReschedulingPass(*PassRegistry::getPassRegistry());
28940b57cec5SDimitry Andric     }
28950b57cec5SDimitry Andric 
28960b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
28970b57cec5SDimitry Andric 
28980b57cec5SDimitry Andric   private:
28990b57cec5SDimitry Andric     const HexagonInstrInfo *HII = nullptr;
29000b57cec5SDimitry Andric     const HexagonRegisterInfo *HRI = nullptr;
29010b57cec5SDimitry Andric     MachineRegisterInfo *MRI = nullptr;
29020b57cec5SDimitry Andric     BitTracker *BTP = nullptr;
29030b57cec5SDimitry Andric 
29040b57cec5SDimitry Andric     struct LoopCand {
29050b57cec5SDimitry Andric       LoopCand(MachineBasicBlock *lb, MachineBasicBlock *pb,
29060b57cec5SDimitry Andric             MachineBasicBlock *eb) : LB(lb), PB(pb), EB(eb) {}
29070b57cec5SDimitry Andric 
29080b57cec5SDimitry Andric       MachineBasicBlock *LB, *PB, *EB;
29090b57cec5SDimitry Andric     };
29100b57cec5SDimitry Andric     using InstrList = std::vector<MachineInstr *>;
29110b57cec5SDimitry Andric     struct InstrGroup {
29120b57cec5SDimitry Andric       BitTracker::RegisterRef Inp, Out;
29130b57cec5SDimitry Andric       InstrList Ins;
29140b57cec5SDimitry Andric     };
29150b57cec5SDimitry Andric     struct PhiInfo {
29160b57cec5SDimitry Andric       PhiInfo(MachineInstr &P, MachineBasicBlock &B);
29170b57cec5SDimitry Andric 
29180b57cec5SDimitry Andric       unsigned DefR;
29190b57cec5SDimitry Andric       BitTracker::RegisterRef LR, PR; // Loop Register, Preheader Register
29200b57cec5SDimitry Andric       MachineBasicBlock *LB, *PB;     // Loop Block, Preheader Block
29210b57cec5SDimitry Andric     };
29220b57cec5SDimitry Andric 
29230b57cec5SDimitry Andric     static unsigned getDefReg(const MachineInstr *MI);
29240b57cec5SDimitry Andric     bool isConst(unsigned Reg) const;
29250b57cec5SDimitry Andric     bool isBitShuffle(const MachineInstr *MI, unsigned DefR) const;
29260b57cec5SDimitry Andric     bool isStoreInput(const MachineInstr *MI, unsigned DefR) const;
29270b57cec5SDimitry Andric     bool isShuffleOf(unsigned OutR, unsigned InpR) const;
29280b57cec5SDimitry Andric     bool isSameShuffle(unsigned OutR1, unsigned InpR1, unsigned OutR2,
29290b57cec5SDimitry Andric         unsigned &InpR2) const;
29300b57cec5SDimitry Andric     void moveGroup(InstrGroup &G, MachineBasicBlock &LB, MachineBasicBlock &PB,
29310b57cec5SDimitry Andric         MachineBasicBlock::iterator At, unsigned OldPhiR, unsigned NewPredR);
29320b57cec5SDimitry Andric     bool processLoop(LoopCand &C);
29330b57cec5SDimitry Andric   };
29340b57cec5SDimitry Andric 
29350b57cec5SDimitry Andric } // end anonymous namespace
29360b57cec5SDimitry Andric 
29370b57cec5SDimitry Andric char HexagonLoopRescheduling::ID = 0;
29380b57cec5SDimitry Andric 
29390b57cec5SDimitry Andric INITIALIZE_PASS(HexagonLoopRescheduling, "hexagon-loop-resched",
29400b57cec5SDimitry Andric   "Hexagon Loop Rescheduling", false, false)
29410b57cec5SDimitry Andric 
29420b57cec5SDimitry Andric HexagonLoopRescheduling::PhiInfo::PhiInfo(MachineInstr &P,
29430b57cec5SDimitry Andric       MachineBasicBlock &B) {
29440b57cec5SDimitry Andric   DefR = HexagonLoopRescheduling::getDefReg(&P);
29450b57cec5SDimitry Andric   LB = &B;
29460b57cec5SDimitry Andric   PB = nullptr;
29470b57cec5SDimitry Andric   for (unsigned i = 1, n = P.getNumOperands(); i < n; i += 2) {
29480b57cec5SDimitry Andric     const MachineOperand &OpB = P.getOperand(i+1);
29490b57cec5SDimitry Andric     if (OpB.getMBB() == &B) {
29500b57cec5SDimitry Andric       LR = P.getOperand(i);
29510b57cec5SDimitry Andric       continue;
29520b57cec5SDimitry Andric     }
29530b57cec5SDimitry Andric     PB = OpB.getMBB();
29540b57cec5SDimitry Andric     PR = P.getOperand(i);
29550b57cec5SDimitry Andric   }
29560b57cec5SDimitry Andric }
29570b57cec5SDimitry Andric 
29580b57cec5SDimitry Andric unsigned HexagonLoopRescheduling::getDefReg(const MachineInstr *MI) {
29590b57cec5SDimitry Andric   RegisterSet Defs;
29600b57cec5SDimitry Andric   HBS::getInstrDefs(*MI, Defs);
29610b57cec5SDimitry Andric   if (Defs.count() != 1)
29620b57cec5SDimitry Andric     return 0;
29630b57cec5SDimitry Andric   return Defs.find_first();
29640b57cec5SDimitry Andric }
29650b57cec5SDimitry Andric 
29660b57cec5SDimitry Andric bool HexagonLoopRescheduling::isConst(unsigned Reg) const {
29670b57cec5SDimitry Andric   if (!BTP->has(Reg))
29680b57cec5SDimitry Andric     return false;
29690b57cec5SDimitry Andric   const BitTracker::RegisterCell &RC = BTP->lookup(Reg);
29700b57cec5SDimitry Andric   for (unsigned i = 0, w = RC.width(); i < w; ++i) {
29710b57cec5SDimitry Andric     const BitTracker::BitValue &V = RC[i];
29720b57cec5SDimitry Andric     if (!V.is(0) && !V.is(1))
29730b57cec5SDimitry Andric       return false;
29740b57cec5SDimitry Andric   }
29750b57cec5SDimitry Andric   return true;
29760b57cec5SDimitry Andric }
29770b57cec5SDimitry Andric 
29780b57cec5SDimitry Andric bool HexagonLoopRescheduling::isBitShuffle(const MachineInstr *MI,
29790b57cec5SDimitry Andric       unsigned DefR) const {
29800b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
29810b57cec5SDimitry Andric   switch (Opc) {
29820b57cec5SDimitry Andric     case TargetOpcode::COPY:
29830b57cec5SDimitry Andric     case Hexagon::S2_lsr_i_r:
29840b57cec5SDimitry Andric     case Hexagon::S2_asr_i_r:
29850b57cec5SDimitry Andric     case Hexagon::S2_asl_i_r:
29860b57cec5SDimitry Andric     case Hexagon::S2_lsr_i_p:
29870b57cec5SDimitry Andric     case Hexagon::S2_asr_i_p:
29880b57cec5SDimitry Andric     case Hexagon::S2_asl_i_p:
29890b57cec5SDimitry Andric     case Hexagon::S2_insert:
29900b57cec5SDimitry Andric     case Hexagon::A2_or:
29910b57cec5SDimitry Andric     case Hexagon::A2_orp:
29920b57cec5SDimitry Andric     case Hexagon::A2_and:
29930b57cec5SDimitry Andric     case Hexagon::A2_andp:
29940b57cec5SDimitry Andric     case Hexagon::A2_combinew:
29950b57cec5SDimitry Andric     case Hexagon::A4_combineri:
29960b57cec5SDimitry Andric     case Hexagon::A4_combineir:
29970b57cec5SDimitry Andric     case Hexagon::A2_combineii:
29980b57cec5SDimitry Andric     case Hexagon::A4_combineii:
29990b57cec5SDimitry Andric     case Hexagon::A2_combine_ll:
30000b57cec5SDimitry Andric     case Hexagon::A2_combine_lh:
30010b57cec5SDimitry Andric     case Hexagon::A2_combine_hl:
30020b57cec5SDimitry Andric     case Hexagon::A2_combine_hh:
30030b57cec5SDimitry Andric       return true;
30040b57cec5SDimitry Andric   }
30050b57cec5SDimitry Andric   return false;
30060b57cec5SDimitry Andric }
30070b57cec5SDimitry Andric 
30080b57cec5SDimitry Andric bool HexagonLoopRescheduling::isStoreInput(const MachineInstr *MI,
30090b57cec5SDimitry Andric       unsigned InpR) const {
30100b57cec5SDimitry Andric   for (unsigned i = 0, n = MI->getNumOperands(); i < n; ++i) {
30110b57cec5SDimitry Andric     const MachineOperand &Op = MI->getOperand(i);
30120b57cec5SDimitry Andric     if (!Op.isReg())
30130b57cec5SDimitry Andric       continue;
30140b57cec5SDimitry Andric     if (Op.getReg() == InpR)
30150b57cec5SDimitry Andric       return i == n-1;
30160b57cec5SDimitry Andric   }
30170b57cec5SDimitry Andric   return false;
30180b57cec5SDimitry Andric }
30190b57cec5SDimitry Andric 
30200b57cec5SDimitry Andric bool HexagonLoopRescheduling::isShuffleOf(unsigned OutR, unsigned InpR) const {
30210b57cec5SDimitry Andric   if (!BTP->has(OutR) || !BTP->has(InpR))
30220b57cec5SDimitry Andric     return false;
30230b57cec5SDimitry Andric   const BitTracker::RegisterCell &OutC = BTP->lookup(OutR);
30240b57cec5SDimitry Andric   for (unsigned i = 0, w = OutC.width(); i < w; ++i) {
30250b57cec5SDimitry Andric     const BitTracker::BitValue &V = OutC[i];
30260b57cec5SDimitry Andric     if (V.Type != BitTracker::BitValue::Ref)
30270b57cec5SDimitry Andric       continue;
30280b57cec5SDimitry Andric     if (V.RefI.Reg != InpR)
30290b57cec5SDimitry Andric       return false;
30300b57cec5SDimitry Andric   }
30310b57cec5SDimitry Andric   return true;
30320b57cec5SDimitry Andric }
30330b57cec5SDimitry Andric 
30340b57cec5SDimitry Andric bool HexagonLoopRescheduling::isSameShuffle(unsigned OutR1, unsigned InpR1,
30350b57cec5SDimitry Andric       unsigned OutR2, unsigned &InpR2) const {
30360b57cec5SDimitry Andric   if (!BTP->has(OutR1) || !BTP->has(InpR1) || !BTP->has(OutR2))
30370b57cec5SDimitry Andric     return false;
30380b57cec5SDimitry Andric   const BitTracker::RegisterCell &OutC1 = BTP->lookup(OutR1);
30390b57cec5SDimitry Andric   const BitTracker::RegisterCell &OutC2 = BTP->lookup(OutR2);
30400b57cec5SDimitry Andric   unsigned W = OutC1.width();
30410b57cec5SDimitry Andric   unsigned MatchR = 0;
30420b57cec5SDimitry Andric   if (W != OutC2.width())
30430b57cec5SDimitry Andric     return false;
30440b57cec5SDimitry Andric   for (unsigned i = 0; i < W; ++i) {
30450b57cec5SDimitry Andric     const BitTracker::BitValue &V1 = OutC1[i], &V2 = OutC2[i];
30460b57cec5SDimitry Andric     if (V1.Type != V2.Type || V1.Type == BitTracker::BitValue::One)
30470b57cec5SDimitry Andric       return false;
30480b57cec5SDimitry Andric     if (V1.Type != BitTracker::BitValue::Ref)
30490b57cec5SDimitry Andric       continue;
30500b57cec5SDimitry Andric     if (V1.RefI.Pos != V2.RefI.Pos)
30510b57cec5SDimitry Andric       return false;
30520b57cec5SDimitry Andric     if (V1.RefI.Reg != InpR1)
30530b57cec5SDimitry Andric       return false;
30540b57cec5SDimitry Andric     if (V2.RefI.Reg == 0 || V2.RefI.Reg == OutR2)
30550b57cec5SDimitry Andric       return false;
30560b57cec5SDimitry Andric     if (!MatchR)
30570b57cec5SDimitry Andric       MatchR = V2.RefI.Reg;
30580b57cec5SDimitry Andric     else if (V2.RefI.Reg != MatchR)
30590b57cec5SDimitry Andric       return false;
30600b57cec5SDimitry Andric   }
30610b57cec5SDimitry Andric   InpR2 = MatchR;
30620b57cec5SDimitry Andric   return true;
30630b57cec5SDimitry Andric }
30640b57cec5SDimitry Andric 
30650b57cec5SDimitry Andric void HexagonLoopRescheduling::moveGroup(InstrGroup &G, MachineBasicBlock &LB,
30660b57cec5SDimitry Andric       MachineBasicBlock &PB, MachineBasicBlock::iterator At, unsigned OldPhiR,
30670b57cec5SDimitry Andric       unsigned NewPredR) {
30680b57cec5SDimitry Andric   DenseMap<unsigned,unsigned> RegMap;
30690b57cec5SDimitry Andric 
30700b57cec5SDimitry Andric   const TargetRegisterClass *PhiRC = MRI->getRegClass(NewPredR);
3071*8bcb0991SDimitry Andric   Register PhiR = MRI->createVirtualRegister(PhiRC);
30720b57cec5SDimitry Andric   BuildMI(LB, At, At->getDebugLoc(), HII->get(TargetOpcode::PHI), PhiR)
30730b57cec5SDimitry Andric     .addReg(NewPredR)
30740b57cec5SDimitry Andric     .addMBB(&PB)
30750b57cec5SDimitry Andric     .addReg(G.Inp.Reg)
30760b57cec5SDimitry Andric     .addMBB(&LB);
30770b57cec5SDimitry Andric   RegMap.insert(std::make_pair(G.Inp.Reg, PhiR));
30780b57cec5SDimitry Andric 
30790b57cec5SDimitry Andric   for (unsigned i = G.Ins.size(); i > 0; --i) {
30800b57cec5SDimitry Andric     const MachineInstr *SI = G.Ins[i-1];
30810b57cec5SDimitry Andric     unsigned DR = getDefReg(SI);
30820b57cec5SDimitry Andric     const TargetRegisterClass *RC = MRI->getRegClass(DR);
3083*8bcb0991SDimitry Andric     Register NewDR = MRI->createVirtualRegister(RC);
30840b57cec5SDimitry Andric     DebugLoc DL = SI->getDebugLoc();
30850b57cec5SDimitry Andric 
30860b57cec5SDimitry Andric     auto MIB = BuildMI(LB, At, DL, HII->get(SI->getOpcode()), NewDR);
30870b57cec5SDimitry Andric     for (unsigned j = 0, m = SI->getNumOperands(); j < m; ++j) {
30880b57cec5SDimitry Andric       const MachineOperand &Op = SI->getOperand(j);
30890b57cec5SDimitry Andric       if (!Op.isReg()) {
30900b57cec5SDimitry Andric         MIB.add(Op);
30910b57cec5SDimitry Andric         continue;
30920b57cec5SDimitry Andric       }
30930b57cec5SDimitry Andric       if (!Op.isUse())
30940b57cec5SDimitry Andric         continue;
30950b57cec5SDimitry Andric       unsigned UseR = RegMap[Op.getReg()];
30960b57cec5SDimitry Andric       MIB.addReg(UseR, 0, Op.getSubReg());
30970b57cec5SDimitry Andric     }
30980b57cec5SDimitry Andric     RegMap.insert(std::make_pair(DR, NewDR));
30990b57cec5SDimitry Andric   }
31000b57cec5SDimitry Andric 
31010b57cec5SDimitry Andric   HBS::replaceReg(OldPhiR, RegMap[G.Out.Reg], *MRI);
31020b57cec5SDimitry Andric }
31030b57cec5SDimitry Andric 
31040b57cec5SDimitry Andric bool HexagonLoopRescheduling::processLoop(LoopCand &C) {
31050b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Processing loop in " << printMBBReference(*C.LB)
31060b57cec5SDimitry Andric                     << "\n");
31070b57cec5SDimitry Andric   std::vector<PhiInfo> Phis;
31080b57cec5SDimitry Andric   for (auto &I : *C.LB) {
31090b57cec5SDimitry Andric     if (!I.isPHI())
31100b57cec5SDimitry Andric       break;
31110b57cec5SDimitry Andric     unsigned PR = getDefReg(&I);
31120b57cec5SDimitry Andric     if (isConst(PR))
31130b57cec5SDimitry Andric       continue;
31140b57cec5SDimitry Andric     bool BadUse = false, GoodUse = false;
31150b57cec5SDimitry Andric     for (auto UI = MRI->use_begin(PR), UE = MRI->use_end(); UI != UE; ++UI) {
31160b57cec5SDimitry Andric       MachineInstr *UseI = UI->getParent();
31170b57cec5SDimitry Andric       if (UseI->getParent() != C.LB) {
31180b57cec5SDimitry Andric         BadUse = true;
31190b57cec5SDimitry Andric         break;
31200b57cec5SDimitry Andric       }
31210b57cec5SDimitry Andric       if (isBitShuffle(UseI, PR) || isStoreInput(UseI, PR))
31220b57cec5SDimitry Andric         GoodUse = true;
31230b57cec5SDimitry Andric     }
31240b57cec5SDimitry Andric     if (BadUse || !GoodUse)
31250b57cec5SDimitry Andric       continue;
31260b57cec5SDimitry Andric 
31270b57cec5SDimitry Andric     Phis.push_back(PhiInfo(I, *C.LB));
31280b57cec5SDimitry Andric   }
31290b57cec5SDimitry Andric 
31300b57cec5SDimitry Andric   LLVM_DEBUG({
31310b57cec5SDimitry Andric     dbgs() << "Phis: {";
31320b57cec5SDimitry Andric     for (auto &I : Phis) {
31330b57cec5SDimitry Andric       dbgs() << ' ' << printReg(I.DefR, HRI) << "=phi("
31340b57cec5SDimitry Andric              << printReg(I.PR.Reg, HRI, I.PR.Sub) << ":b" << I.PB->getNumber()
31350b57cec5SDimitry Andric              << ',' << printReg(I.LR.Reg, HRI, I.LR.Sub) << ":b"
31360b57cec5SDimitry Andric              << I.LB->getNumber() << ')';
31370b57cec5SDimitry Andric     }
31380b57cec5SDimitry Andric     dbgs() << " }\n";
31390b57cec5SDimitry Andric   });
31400b57cec5SDimitry Andric 
31410b57cec5SDimitry Andric   if (Phis.empty())
31420b57cec5SDimitry Andric     return false;
31430b57cec5SDimitry Andric 
31440b57cec5SDimitry Andric   bool Changed = false;
31450b57cec5SDimitry Andric   InstrList ShufIns;
31460b57cec5SDimitry Andric 
31470b57cec5SDimitry Andric   // Go backwards in the block: for each bit shuffling instruction, check
31480b57cec5SDimitry Andric   // if that instruction could potentially be moved to the front of the loop:
31490b57cec5SDimitry Andric   // the output of the loop cannot be used in a non-shuffling instruction
31500b57cec5SDimitry Andric   // in this loop.
31510b57cec5SDimitry Andric   for (auto I = C.LB->rbegin(), E = C.LB->rend(); I != E; ++I) {
31520b57cec5SDimitry Andric     if (I->isTerminator())
31530b57cec5SDimitry Andric       continue;
31540b57cec5SDimitry Andric     if (I->isPHI())
31550b57cec5SDimitry Andric       break;
31560b57cec5SDimitry Andric 
31570b57cec5SDimitry Andric     RegisterSet Defs;
31580b57cec5SDimitry Andric     HBS::getInstrDefs(*I, Defs);
31590b57cec5SDimitry Andric     if (Defs.count() != 1)
31600b57cec5SDimitry Andric       continue;
31610b57cec5SDimitry Andric     unsigned DefR = Defs.find_first();
3162*8bcb0991SDimitry Andric     if (!Register::isVirtualRegister(DefR))
31630b57cec5SDimitry Andric       continue;
31640b57cec5SDimitry Andric     if (!isBitShuffle(&*I, DefR))
31650b57cec5SDimitry Andric       continue;
31660b57cec5SDimitry Andric 
31670b57cec5SDimitry Andric     bool BadUse = false;
31680b57cec5SDimitry Andric     for (auto UI = MRI->use_begin(DefR), UE = MRI->use_end(); UI != UE; ++UI) {
31690b57cec5SDimitry Andric       MachineInstr *UseI = UI->getParent();
31700b57cec5SDimitry Andric       if (UseI->getParent() == C.LB) {
31710b57cec5SDimitry Andric         if (UseI->isPHI()) {
31720b57cec5SDimitry Andric           // If the use is in a phi node in this loop, then it should be
31730b57cec5SDimitry Andric           // the value corresponding to the back edge.
31740b57cec5SDimitry Andric           unsigned Idx = UI.getOperandNo();
31750b57cec5SDimitry Andric           if (UseI->getOperand(Idx+1).getMBB() != C.LB)
31760b57cec5SDimitry Andric             BadUse = true;
31770b57cec5SDimitry Andric         } else {
31780b57cec5SDimitry Andric           auto F = find(ShufIns, UseI);
31790b57cec5SDimitry Andric           if (F == ShufIns.end())
31800b57cec5SDimitry Andric             BadUse = true;
31810b57cec5SDimitry Andric         }
31820b57cec5SDimitry Andric       } else {
31830b57cec5SDimitry Andric         // There is a use outside of the loop, but there is no epilog block
31840b57cec5SDimitry Andric         // suitable for a copy-out.
31850b57cec5SDimitry Andric         if (C.EB == nullptr)
31860b57cec5SDimitry Andric           BadUse = true;
31870b57cec5SDimitry Andric       }
31880b57cec5SDimitry Andric       if (BadUse)
31890b57cec5SDimitry Andric         break;
31900b57cec5SDimitry Andric     }
31910b57cec5SDimitry Andric 
31920b57cec5SDimitry Andric     if (BadUse)
31930b57cec5SDimitry Andric       continue;
31940b57cec5SDimitry Andric     ShufIns.push_back(&*I);
31950b57cec5SDimitry Andric   }
31960b57cec5SDimitry Andric 
31970b57cec5SDimitry Andric   // Partition the list of shuffling instructions into instruction groups,
31980b57cec5SDimitry Andric   // where each group has to be moved as a whole (i.e. a group is a chain of
31990b57cec5SDimitry Andric   // dependent instructions). A group produces a single live output register,
32000b57cec5SDimitry Andric   // which is meant to be the input of the loop phi node (although this is
32010b57cec5SDimitry Andric   // not checked here yet). It also uses a single register as its input,
32020b57cec5SDimitry Andric   // which is some value produced in the loop body. After moving the group
32030b57cec5SDimitry Andric   // to the beginning of the loop, that input register would need to be
32040b57cec5SDimitry Andric   // the loop-carried register (through a phi node) instead of the (currently
32050b57cec5SDimitry Andric   // loop-carried) output register.
32060b57cec5SDimitry Andric   using InstrGroupList = std::vector<InstrGroup>;
32070b57cec5SDimitry Andric   InstrGroupList Groups;
32080b57cec5SDimitry Andric 
32090b57cec5SDimitry Andric   for (unsigned i = 0, n = ShufIns.size(); i < n; ++i) {
32100b57cec5SDimitry Andric     MachineInstr *SI = ShufIns[i];
32110b57cec5SDimitry Andric     if (SI == nullptr)
32120b57cec5SDimitry Andric       continue;
32130b57cec5SDimitry Andric 
32140b57cec5SDimitry Andric     InstrGroup G;
32150b57cec5SDimitry Andric     G.Ins.push_back(SI);
32160b57cec5SDimitry Andric     G.Out.Reg = getDefReg(SI);
32170b57cec5SDimitry Andric     RegisterSet Inputs;
32180b57cec5SDimitry Andric     HBS::getInstrUses(*SI, Inputs);
32190b57cec5SDimitry Andric 
32200b57cec5SDimitry Andric     for (unsigned j = i+1; j < n; ++j) {
32210b57cec5SDimitry Andric       MachineInstr *MI = ShufIns[j];
32220b57cec5SDimitry Andric       if (MI == nullptr)
32230b57cec5SDimitry Andric         continue;
32240b57cec5SDimitry Andric       RegisterSet Defs;
32250b57cec5SDimitry Andric       HBS::getInstrDefs(*MI, Defs);
32260b57cec5SDimitry Andric       // If this instruction does not define any pending inputs, skip it.
32270b57cec5SDimitry Andric       if (!Defs.intersects(Inputs))
32280b57cec5SDimitry Andric         continue;
32290b57cec5SDimitry Andric       // Otherwise, add it to the current group and remove the inputs that
32300b57cec5SDimitry Andric       // are defined by MI.
32310b57cec5SDimitry Andric       G.Ins.push_back(MI);
32320b57cec5SDimitry Andric       Inputs.remove(Defs);
32330b57cec5SDimitry Andric       // Then add all registers used by MI.
32340b57cec5SDimitry Andric       HBS::getInstrUses(*MI, Inputs);
32350b57cec5SDimitry Andric       ShufIns[j] = nullptr;
32360b57cec5SDimitry Andric     }
32370b57cec5SDimitry Andric 
32380b57cec5SDimitry Andric     // Only add a group if it requires at most one register.
32390b57cec5SDimitry Andric     if (Inputs.count() > 1)
32400b57cec5SDimitry Andric       continue;
32410b57cec5SDimitry Andric     auto LoopInpEq = [G] (const PhiInfo &P) -> bool {
32420b57cec5SDimitry Andric       return G.Out.Reg == P.LR.Reg;
32430b57cec5SDimitry Andric     };
32440b57cec5SDimitry Andric     if (llvm::find_if(Phis, LoopInpEq) == Phis.end())
32450b57cec5SDimitry Andric       continue;
32460b57cec5SDimitry Andric 
32470b57cec5SDimitry Andric     G.Inp.Reg = Inputs.find_first();
32480b57cec5SDimitry Andric     Groups.push_back(G);
32490b57cec5SDimitry Andric   }
32500b57cec5SDimitry Andric 
32510b57cec5SDimitry Andric   LLVM_DEBUG({
32520b57cec5SDimitry Andric     for (unsigned i = 0, n = Groups.size(); i < n; ++i) {
32530b57cec5SDimitry Andric       InstrGroup &G = Groups[i];
32540b57cec5SDimitry Andric       dbgs() << "Group[" << i << "] inp: "
32550b57cec5SDimitry Andric              << printReg(G.Inp.Reg, HRI, G.Inp.Sub)
32560b57cec5SDimitry Andric              << "  out: " << printReg(G.Out.Reg, HRI, G.Out.Sub) << "\n";
32570b57cec5SDimitry Andric       for (unsigned j = 0, m = G.Ins.size(); j < m; ++j)
32580b57cec5SDimitry Andric         dbgs() << "  " << *G.Ins[j];
32590b57cec5SDimitry Andric     }
32600b57cec5SDimitry Andric   });
32610b57cec5SDimitry Andric 
32620b57cec5SDimitry Andric   for (unsigned i = 0, n = Groups.size(); i < n; ++i) {
32630b57cec5SDimitry Andric     InstrGroup &G = Groups[i];
32640b57cec5SDimitry Andric     if (!isShuffleOf(G.Out.Reg, G.Inp.Reg))
32650b57cec5SDimitry Andric       continue;
32660b57cec5SDimitry Andric     auto LoopInpEq = [G] (const PhiInfo &P) -> bool {
32670b57cec5SDimitry Andric       return G.Out.Reg == P.LR.Reg;
32680b57cec5SDimitry Andric     };
32690b57cec5SDimitry Andric     auto F = llvm::find_if(Phis, LoopInpEq);
32700b57cec5SDimitry Andric     if (F == Phis.end())
32710b57cec5SDimitry Andric       continue;
32720b57cec5SDimitry Andric     unsigned PrehR = 0;
32730b57cec5SDimitry Andric     if (!isSameShuffle(G.Out.Reg, G.Inp.Reg, F->PR.Reg, PrehR)) {
32740b57cec5SDimitry Andric       const MachineInstr *DefPrehR = MRI->getVRegDef(F->PR.Reg);
32750b57cec5SDimitry Andric       unsigned Opc = DefPrehR->getOpcode();
32760b57cec5SDimitry Andric       if (Opc != Hexagon::A2_tfrsi && Opc != Hexagon::A2_tfrpi)
32770b57cec5SDimitry Andric         continue;
32780b57cec5SDimitry Andric       if (!DefPrehR->getOperand(1).isImm())
32790b57cec5SDimitry Andric         continue;
32800b57cec5SDimitry Andric       if (DefPrehR->getOperand(1).getImm() != 0)
32810b57cec5SDimitry Andric         continue;
32820b57cec5SDimitry Andric       const TargetRegisterClass *RC = MRI->getRegClass(G.Inp.Reg);
32830b57cec5SDimitry Andric       if (RC != MRI->getRegClass(F->PR.Reg)) {
32840b57cec5SDimitry Andric         PrehR = MRI->createVirtualRegister(RC);
32850b57cec5SDimitry Andric         unsigned TfrI = (RC == &Hexagon::IntRegsRegClass) ? Hexagon::A2_tfrsi
32860b57cec5SDimitry Andric                                                           : Hexagon::A2_tfrpi;
32870b57cec5SDimitry Andric         auto T = C.PB->getFirstTerminator();
32880b57cec5SDimitry Andric         DebugLoc DL = (T != C.PB->end()) ? T->getDebugLoc() : DebugLoc();
32890b57cec5SDimitry Andric         BuildMI(*C.PB, T, DL, HII->get(TfrI), PrehR)
32900b57cec5SDimitry Andric           .addImm(0);
32910b57cec5SDimitry Andric       } else {
32920b57cec5SDimitry Andric         PrehR = F->PR.Reg;
32930b57cec5SDimitry Andric       }
32940b57cec5SDimitry Andric     }
32950b57cec5SDimitry Andric     // isSameShuffle could match with PrehR being of a wider class than
32960b57cec5SDimitry Andric     // G.Inp.Reg, for example if G shuffles the low 32 bits of its input,
32970b57cec5SDimitry Andric     // it would match for the input being a 32-bit register, and PrehR
32980b57cec5SDimitry Andric     // being a 64-bit register (where the low 32 bits match). This could
32990b57cec5SDimitry Andric     // be handled, but for now skip these cases.
33000b57cec5SDimitry Andric     if (MRI->getRegClass(PrehR) != MRI->getRegClass(G.Inp.Reg))
33010b57cec5SDimitry Andric       continue;
33020b57cec5SDimitry Andric     moveGroup(G, *F->LB, *F->PB, F->LB->getFirstNonPHI(), F->DefR, PrehR);
33030b57cec5SDimitry Andric     Changed = true;
33040b57cec5SDimitry Andric   }
33050b57cec5SDimitry Andric 
33060b57cec5SDimitry Andric   return Changed;
33070b57cec5SDimitry Andric }
33080b57cec5SDimitry Andric 
33090b57cec5SDimitry Andric bool HexagonLoopRescheduling::runOnMachineFunction(MachineFunction &MF) {
33100b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
33110b57cec5SDimitry Andric     return false;
33120b57cec5SDimitry Andric 
33130b57cec5SDimitry Andric   auto &HST = MF.getSubtarget<HexagonSubtarget>();
33140b57cec5SDimitry Andric   HII = HST.getInstrInfo();
33150b57cec5SDimitry Andric   HRI = HST.getRegisterInfo();
33160b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
33170b57cec5SDimitry Andric   const HexagonEvaluator HE(*HRI, *MRI, *HII, MF);
33180b57cec5SDimitry Andric   BitTracker BT(HE, MF);
33190b57cec5SDimitry Andric   LLVM_DEBUG(BT.trace(true));
33200b57cec5SDimitry Andric   BT.run();
33210b57cec5SDimitry Andric   BTP = &BT;
33220b57cec5SDimitry Andric 
33230b57cec5SDimitry Andric   std::vector<LoopCand> Cand;
33240b57cec5SDimitry Andric 
33250b57cec5SDimitry Andric   for (auto &B : MF) {
33260b57cec5SDimitry Andric     if (B.pred_size() != 2 || B.succ_size() != 2)
33270b57cec5SDimitry Andric       continue;
33280b57cec5SDimitry Andric     MachineBasicBlock *PB = nullptr;
33290b57cec5SDimitry Andric     bool IsLoop = false;
33300b57cec5SDimitry Andric     for (auto PI = B.pred_begin(), PE = B.pred_end(); PI != PE; ++PI) {
33310b57cec5SDimitry Andric       if (*PI != &B)
33320b57cec5SDimitry Andric         PB = *PI;
33330b57cec5SDimitry Andric       else
33340b57cec5SDimitry Andric         IsLoop = true;
33350b57cec5SDimitry Andric     }
33360b57cec5SDimitry Andric     if (!IsLoop)
33370b57cec5SDimitry Andric       continue;
33380b57cec5SDimitry Andric 
33390b57cec5SDimitry Andric     MachineBasicBlock *EB = nullptr;
33400b57cec5SDimitry Andric     for (auto SI = B.succ_begin(), SE = B.succ_end(); SI != SE; ++SI) {
33410b57cec5SDimitry Andric       if (*SI == &B)
33420b57cec5SDimitry Andric         continue;
33430b57cec5SDimitry Andric       // Set EP to the epilog block, if it has only 1 predecessor (i.e. the
33440b57cec5SDimitry Andric       // edge from B to EP is non-critical.
33450b57cec5SDimitry Andric       if ((*SI)->pred_size() == 1)
33460b57cec5SDimitry Andric         EB = *SI;
33470b57cec5SDimitry Andric       break;
33480b57cec5SDimitry Andric     }
33490b57cec5SDimitry Andric 
33500b57cec5SDimitry Andric     Cand.push_back(LoopCand(&B, PB, EB));
33510b57cec5SDimitry Andric   }
33520b57cec5SDimitry Andric 
33530b57cec5SDimitry Andric   bool Changed = false;
33540b57cec5SDimitry Andric   for (auto &C : Cand)
33550b57cec5SDimitry Andric     Changed |= processLoop(C);
33560b57cec5SDimitry Andric 
33570b57cec5SDimitry Andric   return Changed;
33580b57cec5SDimitry Andric }
33590b57cec5SDimitry Andric 
33600b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
33610b57cec5SDimitry Andric //                         Public Constructor Functions
33620b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
33630b57cec5SDimitry Andric 
33640b57cec5SDimitry Andric FunctionPass *llvm::createHexagonLoopRescheduling() {
33650b57cec5SDimitry Andric   return new HexagonLoopRescheduling();
33660b57cec5SDimitry Andric }
33670b57cec5SDimitry Andric 
33680b57cec5SDimitry Andric FunctionPass *llvm::createHexagonBitSimplify() {
33690b57cec5SDimitry Andric   return new HexagonBitSimplify();
33700b57cec5SDimitry Andric }
3371