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