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