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