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