10b57cec5SDimitry Andric //===- HexagonGenInsert.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/PostOrderIterator.h" 180b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 210b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 310b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 32480093f4SDimitry Andric #include "llvm/InitializePasses.h" 330b57cec5SDimitry Andric #include "llvm/Pass.h" 340b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 350b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 360b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 370b57cec5SDimitry Andric #include "llvm/Support/Timer.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 <utility> 440b57cec5SDimitry Andric #include <vector> 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric #define DEBUG_TYPE "hexinsert" 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric using namespace llvm; 490b57cec5SDimitry Andric 5081ad6265SDimitry Andric static cl::opt<unsigned> 5181ad6265SDimitry Andric VRegIndexCutoff("insert-vreg-cutoff", cl::init(~0U), cl::Hidden, 5281ad6265SDimitry Andric cl::desc("Vreg# cutoff for insert generation.")); 530b57cec5SDimitry Andric // The distance cutoff is selected based on the precheckin-perf results: 540b57cec5SDimitry Andric // cutoffs 20, 25, 35, and 40 are worse than 30. 5581ad6265SDimitry Andric static cl::opt<unsigned> 5681ad6265SDimitry Andric VRegDistCutoff("insert-dist-cutoff", cl::init(30U), cl::Hidden, 5781ad6265SDimitry Andric cl::desc("Vreg distance cutoff for insert " 580b57cec5SDimitry Andric "generation.")); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric // Limit the container sizes for extreme cases where we run out of memory. 6181ad6265SDimitry Andric static cl::opt<unsigned> 6281ad6265SDimitry Andric MaxORLSize("insert-max-orl", cl::init(4096), cl::Hidden, 6381ad6265SDimitry Andric cl::desc("Maximum size of OrderedRegisterList")); 640b57cec5SDimitry Andric static cl::opt<unsigned> MaxIFMSize("insert-max-ifmap", cl::init(1024), 6581ad6265SDimitry Andric cl::Hidden, 6681ad6265SDimitry Andric cl::desc("Maximum size of IFMap")); 670b57cec5SDimitry Andric 6881ad6265SDimitry Andric static cl::opt<bool> OptTiming("insert-timing", cl::Hidden, 6981ad6265SDimitry Andric cl::desc("Enable timing of insert generation")); 7081ad6265SDimitry Andric static cl::opt<bool> 7181ad6265SDimitry Andric OptTimingDetail("insert-timing-detail", cl::Hidden, 7281ad6265SDimitry Andric cl::desc("Enable detailed timing of insert " 730b57cec5SDimitry Andric "generation")); 740b57cec5SDimitry Andric 7581ad6265SDimitry Andric static cl::opt<bool> OptSelectAll0("insert-all0", cl::init(false), cl::Hidden); 7681ad6265SDimitry Andric static cl::opt<bool> OptSelectHas0("insert-has0", cl::init(false), cl::Hidden); 770b57cec5SDimitry Andric // Whether to construct constant values via "insert". Could eliminate constant 780b57cec5SDimitry Andric // extenders, but often not practical. 7981ad6265SDimitry Andric static cl::opt<bool> OptConst("insert-const", cl::init(false), cl::Hidden); 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric // The preprocessor gets confused when the DEBUG macro is passed larger 820b57cec5SDimitry Andric // chunks of code. Use this function to detect debugging. 830b57cec5SDimitry Andric inline static bool isDebug() { 840b57cec5SDimitry Andric #ifndef NDEBUG 850b57cec5SDimitry Andric return DebugFlag && isCurrentDebugType(DEBUG_TYPE); 860b57cec5SDimitry Andric #else 870b57cec5SDimitry Andric return false; 880b57cec5SDimitry Andric #endif 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric namespace { 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric // Set of virtual registers, based on BitVector. 940b57cec5SDimitry Andric struct RegisterSet : private BitVector { 950b57cec5SDimitry Andric RegisterSet() = default; 960b57cec5SDimitry Andric explicit RegisterSet(unsigned s, bool t = false) : BitVector(s, t) {} 9781ad6265SDimitry Andric RegisterSet(const RegisterSet &RS) = default; 9881ad6265SDimitry Andric RegisterSet &operator=(const RegisterSet &RS) = default; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric using BitVector::clear; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric unsigned find_first() const { 1030b57cec5SDimitry Andric int First = BitVector::find_first(); 1040b57cec5SDimitry Andric if (First < 0) 1050b57cec5SDimitry Andric return 0; 1060b57cec5SDimitry Andric return x2v(First); 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric unsigned find_next(unsigned Prev) const { 1100b57cec5SDimitry Andric int Next = BitVector::find_next(v2x(Prev)); 1110b57cec5SDimitry Andric if (Next < 0) 1120b57cec5SDimitry Andric return 0; 1130b57cec5SDimitry Andric return x2v(Next); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric RegisterSet &insert(unsigned R) { 1170b57cec5SDimitry Andric unsigned Idx = v2x(R); 1180b57cec5SDimitry Andric ensure(Idx); 1190b57cec5SDimitry Andric return static_cast<RegisterSet&>(BitVector::set(Idx)); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric RegisterSet &remove(unsigned R) { 1220b57cec5SDimitry Andric unsigned Idx = v2x(R); 1230b57cec5SDimitry Andric if (Idx >= size()) 1240b57cec5SDimitry Andric return *this; 1250b57cec5SDimitry Andric return static_cast<RegisterSet&>(BitVector::reset(Idx)); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric RegisterSet &insert(const RegisterSet &Rs) { 1290b57cec5SDimitry Andric return static_cast<RegisterSet&>(BitVector::operator|=(Rs)); 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric RegisterSet &remove(const RegisterSet &Rs) { 1320b57cec5SDimitry Andric return static_cast<RegisterSet&>(BitVector::reset(Rs)); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric reference operator[](unsigned R) { 1360b57cec5SDimitry Andric unsigned Idx = v2x(R); 1370b57cec5SDimitry Andric ensure(Idx); 1380b57cec5SDimitry Andric return BitVector::operator[](Idx); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric bool operator[](unsigned R) const { 1410b57cec5SDimitry Andric unsigned Idx = v2x(R); 1420b57cec5SDimitry Andric assert(Idx < size()); 1430b57cec5SDimitry Andric return BitVector::operator[](Idx); 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric bool has(unsigned R) const { 1460b57cec5SDimitry Andric unsigned Idx = v2x(R); 1470b57cec5SDimitry Andric if (Idx >= size()) 1480b57cec5SDimitry Andric return false; 1490b57cec5SDimitry Andric return BitVector::test(Idx); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric bool empty() const { 1530b57cec5SDimitry Andric return !BitVector::any(); 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric bool includes(const RegisterSet &Rs) const { 1560b57cec5SDimitry Andric // A.BitVector::test(B) <=> A-B != {} 1570b57cec5SDimitry Andric return !Rs.BitVector::test(*this); 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric bool intersects(const RegisterSet &Rs) const { 1600b57cec5SDimitry Andric return BitVector::anyCommon(Rs); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric private: 1640b57cec5SDimitry Andric void ensure(unsigned Idx) { 1650b57cec5SDimitry Andric if (size() <= Idx) 1660b57cec5SDimitry Andric resize(std::max(Idx+1, 32U)); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric static inline unsigned v2x(unsigned v) { 1708bcb0991SDimitry Andric return Register::virtReg2Index(v); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric static inline unsigned x2v(unsigned x) { 1748bcb0991SDimitry Andric return Register::index2VirtReg(x); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric }; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric struct PrintRegSet { 1790b57cec5SDimitry Andric PrintRegSet(const RegisterSet &S, const TargetRegisterInfo *RI) 1800b57cec5SDimitry Andric : RS(S), TRI(RI) {} 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric friend raw_ostream &operator<< (raw_ostream &OS, 1830b57cec5SDimitry Andric const PrintRegSet &P); 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric private: 1860b57cec5SDimitry Andric const RegisterSet &RS; 1870b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 1880b57cec5SDimitry Andric }; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric raw_ostream &operator<< (raw_ostream &OS, const PrintRegSet &P) { 1910b57cec5SDimitry Andric OS << '{'; 1920b57cec5SDimitry Andric for (unsigned R = P.RS.find_first(); R; R = P.RS.find_next(R)) 1930b57cec5SDimitry Andric OS << ' ' << printReg(R, P.TRI); 1940b57cec5SDimitry Andric OS << " }"; 1950b57cec5SDimitry Andric return OS; 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric // A convenience class to associate unsigned numbers (such as virtual 1990b57cec5SDimitry Andric // registers) with unsigned numbers. 2000b57cec5SDimitry Andric struct UnsignedMap : public DenseMap<unsigned,unsigned> { 2010b57cec5SDimitry Andric UnsignedMap() = default; 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric private: 2040b57cec5SDimitry Andric using BaseType = DenseMap<unsigned, unsigned>; 2050b57cec5SDimitry Andric }; 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric // A utility to establish an ordering between virtual registers: 2080b57cec5SDimitry Andric // VRegA < VRegB <=> RegisterOrdering[VRegA] < RegisterOrdering[VRegB] 2090b57cec5SDimitry Andric // This is meant as a cache for the ordering of virtual registers defined 2100b57cec5SDimitry Andric // by a potentially expensive comparison function, or obtained by a proce- 2110b57cec5SDimitry Andric // dure that should not be repeated each time two registers are compared. 2120b57cec5SDimitry Andric struct RegisterOrdering : public UnsignedMap { 2130b57cec5SDimitry Andric RegisterOrdering() = default; 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric unsigned operator[](unsigned VR) const { 2160b57cec5SDimitry Andric const_iterator F = find(VR); 2170b57cec5SDimitry Andric assert(F != end()); 2180b57cec5SDimitry Andric return F->second; 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric // Add operator(), so that objects of this class can be used as 2220b57cec5SDimitry Andric // comparators in std::sort et al. 2230b57cec5SDimitry Andric bool operator() (unsigned VR1, unsigned VR2) const { 2240b57cec5SDimitry Andric return operator[](VR1) < operator[](VR2); 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric }; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric // Ordering of bit values. This class does not have operator[], but 2290b57cec5SDimitry Andric // is supplies a comparison operator() for use in std:: algorithms. 2300b57cec5SDimitry Andric // The order is as follows: 2310b57cec5SDimitry Andric // - 0 < 1 < ref 2320b57cec5SDimitry Andric // - ref1 < ref2, if ord(ref1.Reg) < ord(ref2.Reg), 2330b57cec5SDimitry Andric // or ord(ref1.Reg) == ord(ref2.Reg), and ref1.Pos < ref2.Pos. 2340b57cec5SDimitry Andric struct BitValueOrdering { 2350b57cec5SDimitry Andric BitValueOrdering(const RegisterOrdering &RB) : BaseOrd(RB) {} 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric bool operator() (const BitTracker::BitValue &V1, 2380b57cec5SDimitry Andric const BitTracker::BitValue &V2) const; 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric const RegisterOrdering &BaseOrd; 2410b57cec5SDimitry Andric }; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric } // end anonymous namespace 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric bool BitValueOrdering::operator() (const BitTracker::BitValue &V1, 2460b57cec5SDimitry Andric const BitTracker::BitValue &V2) const { 2470b57cec5SDimitry Andric if (V1 == V2) 2480b57cec5SDimitry Andric return false; 2490b57cec5SDimitry Andric // V1==0 => true, V2==0 => false 2500b57cec5SDimitry Andric if (V1.is(0) || V2.is(0)) 2510b57cec5SDimitry Andric return V1.is(0); 2520b57cec5SDimitry Andric // Neither of V1,V2 is 0, and V1!=V2. 2530b57cec5SDimitry Andric // V2==1 => false, V1==1 => true 2540b57cec5SDimitry Andric if (V2.is(1) || V1.is(1)) 2550b57cec5SDimitry Andric return !V2.is(1); 2560b57cec5SDimitry Andric // Both V1,V2 are refs. 2570b57cec5SDimitry Andric unsigned Ind1 = BaseOrd[V1.RefI.Reg], Ind2 = BaseOrd[V2.RefI.Reg]; 2580b57cec5SDimitry Andric if (Ind1 != Ind2) 2590b57cec5SDimitry Andric return Ind1 < Ind2; 2600b57cec5SDimitry Andric // If V1.Pos==V2.Pos 2610b57cec5SDimitry Andric assert(V1.RefI.Pos != V2.RefI.Pos && "Bit values should be different"); 2620b57cec5SDimitry Andric return V1.RefI.Pos < V2.RefI.Pos; 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric namespace { 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric // Cache for the BitTracker's cell map. Map lookup has a logarithmic 2680b57cec5SDimitry Andric // complexity, this class will memoize the lookup results to reduce 2690b57cec5SDimitry Andric // the access time for repeated lookups of the same cell. 2700b57cec5SDimitry Andric struct CellMapShadow { 2710b57cec5SDimitry Andric CellMapShadow(const BitTracker &T) : BT(T) {} 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric const BitTracker::RegisterCell &lookup(unsigned VR) { 2748bcb0991SDimitry Andric unsigned RInd = Register::virtReg2Index(VR); 2750b57cec5SDimitry Andric // Grow the vector to at least 32 elements. 2760b57cec5SDimitry Andric if (RInd >= CVect.size()) 2770b57cec5SDimitry Andric CVect.resize(std::max(RInd+16, 32U), nullptr); 2780b57cec5SDimitry Andric const BitTracker::RegisterCell *CP = CVect[RInd]; 2790b57cec5SDimitry Andric if (CP == nullptr) 2800b57cec5SDimitry Andric CP = CVect[RInd] = &BT.lookup(VR); 2810b57cec5SDimitry Andric return *CP; 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric const BitTracker &BT; 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric private: 2870b57cec5SDimitry Andric using CellVectType = std::vector<const BitTracker::RegisterCell *>; 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric CellVectType CVect; 2900b57cec5SDimitry Andric }; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric // Comparator class for lexicographic ordering of virtual registers 2930b57cec5SDimitry Andric // according to the corresponding BitTracker::RegisterCell objects. 2940b57cec5SDimitry Andric struct RegisterCellLexCompare { 2950b57cec5SDimitry Andric RegisterCellLexCompare(const BitValueOrdering &BO, CellMapShadow &M) 2960b57cec5SDimitry Andric : BitOrd(BO), CM(M) {} 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric bool operator() (unsigned VR1, unsigned VR2) const; 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric private: 3010b57cec5SDimitry Andric const BitValueOrdering &BitOrd; 3020b57cec5SDimitry Andric CellMapShadow &CM; 3030b57cec5SDimitry Andric }; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric // Comparator class for lexicographic ordering of virtual registers 3060b57cec5SDimitry Andric // according to the specified bits of the corresponding BitTracker:: 3070b57cec5SDimitry Andric // RegisterCell objects. 3080b57cec5SDimitry Andric // Specifically, this class will be used to compare bit B of a register 3090b57cec5SDimitry Andric // cell for a selected virtual register R with bit N of any register 3100b57cec5SDimitry Andric // other than R. 3110b57cec5SDimitry Andric struct RegisterCellBitCompareSel { 3120b57cec5SDimitry Andric RegisterCellBitCompareSel(unsigned R, unsigned B, unsigned N, 3130b57cec5SDimitry Andric const BitValueOrdering &BO, CellMapShadow &M) 3140b57cec5SDimitry Andric : SelR(R), SelB(B), BitN(N), BitOrd(BO), CM(M) {} 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric bool operator() (unsigned VR1, unsigned VR2) const; 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric private: 3190b57cec5SDimitry Andric const unsigned SelR, SelB; 3200b57cec5SDimitry Andric const unsigned BitN; 3210b57cec5SDimitry Andric const BitValueOrdering &BitOrd; 3220b57cec5SDimitry Andric CellMapShadow &CM; 3230b57cec5SDimitry Andric }; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric } // end anonymous namespace 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric bool RegisterCellLexCompare::operator() (unsigned VR1, unsigned VR2) const { 3280b57cec5SDimitry Andric // Ordering of registers, made up from two given orderings: 3290b57cec5SDimitry Andric // - the ordering of the register numbers, and 3300b57cec5SDimitry Andric // - the ordering of register cells. 3310b57cec5SDimitry Andric // Def. R1 < R2 if: 3320b57cec5SDimitry Andric // - cell(R1) < cell(R2), or 3330b57cec5SDimitry Andric // - cell(R1) == cell(R2), and index(R1) < index(R2). 3340b57cec5SDimitry Andric // 3350b57cec5SDimitry Andric // For register cells, the ordering is lexicographic, with index 0 being 3360b57cec5SDimitry Andric // the most significant. 3370b57cec5SDimitry Andric if (VR1 == VR2) 3380b57cec5SDimitry Andric return false; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric const BitTracker::RegisterCell &RC1 = CM.lookup(VR1), &RC2 = CM.lookup(VR2); 3410b57cec5SDimitry Andric uint16_t W1 = RC1.width(), W2 = RC2.width(); 3420b57cec5SDimitry Andric for (uint16_t i = 0, w = std::min(W1, W2); i < w; ++i) { 3430b57cec5SDimitry Andric const BitTracker::BitValue &V1 = RC1[i], &V2 = RC2[i]; 3440b57cec5SDimitry Andric if (V1 != V2) 3450b57cec5SDimitry Andric return BitOrd(V1, V2); 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric // Cells are equal up until the common length. 3480b57cec5SDimitry Andric if (W1 != W2) 3490b57cec5SDimitry Andric return W1 < W2; 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric return BitOrd.BaseOrd[VR1] < BitOrd.BaseOrd[VR2]; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric bool RegisterCellBitCompareSel::operator() (unsigned VR1, unsigned VR2) const { 3550b57cec5SDimitry Andric if (VR1 == VR2) 3560b57cec5SDimitry Andric return false; 3570b57cec5SDimitry Andric const BitTracker::RegisterCell &RC1 = CM.lookup(VR1); 3580b57cec5SDimitry Andric const BitTracker::RegisterCell &RC2 = CM.lookup(VR2); 3590b57cec5SDimitry Andric uint16_t W1 = RC1.width(), W2 = RC2.width(); 3600b57cec5SDimitry Andric uint16_t Bit1 = (VR1 == SelR) ? SelB : BitN; 3610b57cec5SDimitry Andric uint16_t Bit2 = (VR2 == SelR) ? SelB : BitN; 3620b57cec5SDimitry Andric // If Bit1 exceeds the width of VR1, then: 3630b57cec5SDimitry Andric // - return false, if at the same time Bit2 exceeds VR2, or 3640b57cec5SDimitry Andric // - return true, otherwise. 3650b57cec5SDimitry Andric // (I.e. "a bit value that does not exist is less than any bit value 3660b57cec5SDimitry Andric // that does exist".) 3670b57cec5SDimitry Andric if (W1 <= Bit1) 3680b57cec5SDimitry Andric return Bit2 < W2; 3690b57cec5SDimitry Andric // If Bit1 is within VR1, but Bit2 is not within VR2, return false. 3700b57cec5SDimitry Andric if (W2 <= Bit2) 3710b57cec5SDimitry Andric return false; 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric const BitTracker::BitValue &V1 = RC1[Bit1], V2 = RC2[Bit2]; 3740b57cec5SDimitry Andric if (V1 != V2) 3750b57cec5SDimitry Andric return BitOrd(V1, V2); 3760b57cec5SDimitry Andric return false; 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric namespace { 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric class OrderedRegisterList { 3820b57cec5SDimitry Andric using ListType = std::vector<unsigned>; 3830b57cec5SDimitry Andric const unsigned MaxSize; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric public: 3860b57cec5SDimitry Andric OrderedRegisterList(const RegisterOrdering &RO) 3870b57cec5SDimitry Andric : MaxSize(MaxORLSize), Ord(RO) {} 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric void insert(unsigned VR); 3900b57cec5SDimitry Andric void remove(unsigned VR); 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric unsigned operator[](unsigned Idx) const { 3930b57cec5SDimitry Andric assert(Idx < Seq.size()); 3940b57cec5SDimitry Andric return Seq[Idx]; 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric unsigned size() const { 3980b57cec5SDimitry Andric return Seq.size(); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric using iterator = ListType::iterator; 4020b57cec5SDimitry Andric using const_iterator = ListType::const_iterator; 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric iterator begin() { return Seq.begin(); } 4050b57cec5SDimitry Andric iterator end() { return Seq.end(); } 4060b57cec5SDimitry Andric const_iterator begin() const { return Seq.begin(); } 4070b57cec5SDimitry Andric const_iterator end() const { return Seq.end(); } 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric // Convenience function to convert an iterator to the corresponding index. 4100b57cec5SDimitry Andric unsigned idx(iterator It) const { return It-begin(); } 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric private: 4130b57cec5SDimitry Andric ListType Seq; 4140b57cec5SDimitry Andric const RegisterOrdering &Ord; 4150b57cec5SDimitry Andric }; 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric struct PrintORL { 4180b57cec5SDimitry Andric PrintORL(const OrderedRegisterList &L, const TargetRegisterInfo *RI) 4190b57cec5SDimitry Andric : RL(L), TRI(RI) {} 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric friend raw_ostream &operator<< (raw_ostream &OS, const PrintORL &P); 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric private: 4240b57cec5SDimitry Andric const OrderedRegisterList &RL; 4250b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 4260b57cec5SDimitry Andric }; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric raw_ostream &operator<< (raw_ostream &OS, const PrintORL &P) { 4290b57cec5SDimitry Andric OS << '('; 4300b57cec5SDimitry Andric OrderedRegisterList::const_iterator B = P.RL.begin(), E = P.RL.end(); 4310b57cec5SDimitry Andric for (OrderedRegisterList::const_iterator I = B; I != E; ++I) { 4320b57cec5SDimitry Andric if (I != B) 4330b57cec5SDimitry Andric OS << ", "; 4340b57cec5SDimitry Andric OS << printReg(*I, P.TRI); 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric OS << ')'; 4370b57cec5SDimitry Andric return OS; 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric } // end anonymous namespace 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric void OrderedRegisterList::insert(unsigned VR) { 4430b57cec5SDimitry Andric iterator L = llvm::lower_bound(Seq, VR, Ord); 4440b57cec5SDimitry Andric if (L == Seq.end()) 4450b57cec5SDimitry Andric Seq.push_back(VR); 4460b57cec5SDimitry Andric else 4470b57cec5SDimitry Andric Seq.insert(L, VR); 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric unsigned S = Seq.size(); 4500b57cec5SDimitry Andric if (S > MaxSize) 4510b57cec5SDimitry Andric Seq.resize(MaxSize); 4520b57cec5SDimitry Andric assert(Seq.size() <= MaxSize); 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric void OrderedRegisterList::remove(unsigned VR) { 4560b57cec5SDimitry Andric iterator L = llvm::lower_bound(Seq, VR, Ord); 4570b57cec5SDimitry Andric if (L != Seq.end()) 4580b57cec5SDimitry Andric Seq.erase(L); 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric namespace { 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric // A record of the insert form. The fields correspond to the operands 4640b57cec5SDimitry Andric // of the "insert" instruction: 4650b57cec5SDimitry Andric // ... = insert(SrcR, InsR, #Wdh, #Off) 4660b57cec5SDimitry Andric struct IFRecord { 4670b57cec5SDimitry Andric IFRecord(unsigned SR = 0, unsigned IR = 0, uint16_t W = 0, uint16_t O = 0) 4680b57cec5SDimitry Andric : SrcR(SR), InsR(IR), Wdh(W), Off(O) {} 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric unsigned SrcR, InsR; 4710b57cec5SDimitry Andric uint16_t Wdh, Off; 4720b57cec5SDimitry Andric }; 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric struct PrintIFR { 4750b57cec5SDimitry Andric PrintIFR(const IFRecord &R, const TargetRegisterInfo *RI) 4760b57cec5SDimitry Andric : IFR(R), TRI(RI) {} 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric private: 4790b57cec5SDimitry Andric friend raw_ostream &operator<< (raw_ostream &OS, const PrintIFR &P); 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric const IFRecord &IFR; 4820b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 4830b57cec5SDimitry Andric }; 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric raw_ostream &operator<< (raw_ostream &OS, const PrintIFR &P) { 4860b57cec5SDimitry Andric unsigned SrcR = P.IFR.SrcR, InsR = P.IFR.InsR; 4870b57cec5SDimitry Andric OS << '(' << printReg(SrcR, P.TRI) << ',' << printReg(InsR, P.TRI) 4880b57cec5SDimitry Andric << ",#" << P.IFR.Wdh << ",#" << P.IFR.Off << ')'; 4890b57cec5SDimitry Andric return OS; 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric using IFRecordWithRegSet = std::pair<IFRecord, RegisterSet>; 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric } // end anonymous namespace 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric namespace llvm { 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric void initializeHexagonGenInsertPass(PassRegistry&); 4990b57cec5SDimitry Andric FunctionPass *createHexagonGenInsert(); 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric } // end namespace llvm 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric namespace { 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric class HexagonGenInsert : public MachineFunctionPass { 5060b57cec5SDimitry Andric public: 5070b57cec5SDimitry Andric static char ID; 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric HexagonGenInsert() : MachineFunctionPass(ID) { 5100b57cec5SDimitry Andric initializeHexagonGenInsertPass(*PassRegistry::getPassRegistry()); 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric StringRef getPassName() const override { 5140b57cec5SDimitry Andric return "Hexagon generate \"insert\" instructions"; 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 518*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>(); 519*0fca6ea1SDimitry Andric AU.addPreserved<MachineDominatorTreeWrapperPass>(); 5200b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric private: 5260b57cec5SDimitry Andric using PairMapType = DenseMap<std::pair<unsigned, unsigned>, unsigned>; 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric void buildOrderingMF(RegisterOrdering &RO) const; 5290b57cec5SDimitry Andric void buildOrderingBT(RegisterOrdering &RB, RegisterOrdering &RO) const; 5300b57cec5SDimitry Andric bool isIntClass(const TargetRegisterClass *RC) const; 5310b57cec5SDimitry Andric bool isConstant(unsigned VR) const; 5320b57cec5SDimitry Andric bool isSmallConstant(unsigned VR) const; 5330b57cec5SDimitry Andric bool isValidInsertForm(unsigned DstR, unsigned SrcR, unsigned InsR, 5340b57cec5SDimitry Andric uint16_t L, uint16_t S) const; 5350b57cec5SDimitry Andric bool findSelfReference(unsigned VR) const; 5360b57cec5SDimitry Andric bool findNonSelfReference(unsigned VR) const; 5370b57cec5SDimitry Andric void getInstrDefs(const MachineInstr *MI, RegisterSet &Defs) const; 5380b57cec5SDimitry Andric void getInstrUses(const MachineInstr *MI, RegisterSet &Uses) const; 5390b57cec5SDimitry Andric unsigned distance(const MachineBasicBlock *FromB, 5400b57cec5SDimitry Andric const MachineBasicBlock *ToB, const UnsignedMap &RPO, 5410b57cec5SDimitry Andric PairMapType &M) const; 5420b57cec5SDimitry Andric unsigned distance(MachineBasicBlock::const_iterator FromI, 5430b57cec5SDimitry Andric MachineBasicBlock::const_iterator ToI, const UnsignedMap &RPO, 5440b57cec5SDimitry Andric PairMapType &M) const; 5450b57cec5SDimitry Andric bool findRecordInsertForms(unsigned VR, OrderedRegisterList &AVs); 5460b57cec5SDimitry Andric void collectInBlock(MachineBasicBlock *B, OrderedRegisterList &AVs); 5470b57cec5SDimitry Andric void findRemovableRegisters(unsigned VR, IFRecord IF, 5480b57cec5SDimitry Andric RegisterSet &RMs) const; 5490b57cec5SDimitry Andric void computeRemovableRegisters(); 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric void pruneEmptyLists(); 5520b57cec5SDimitry Andric void pruneCoveredSets(unsigned VR); 5530b57cec5SDimitry Andric void pruneUsesTooFar(unsigned VR, const UnsignedMap &RPO, PairMapType &M); 5540b57cec5SDimitry Andric void pruneRegCopies(unsigned VR); 5550b57cec5SDimitry Andric void pruneCandidates(); 5560b57cec5SDimitry Andric void selectCandidates(); 5570b57cec5SDimitry Andric bool generateInserts(); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric bool removeDeadCode(MachineDomTreeNode *N); 5600b57cec5SDimitry Andric 5610b57cec5SDimitry Andric // IFRecord coupled with a set of potentially removable registers: 5620b57cec5SDimitry Andric using IFListType = std::vector<IFRecordWithRegSet>; 5630b57cec5SDimitry Andric using IFMapType = DenseMap<unsigned, IFListType>; // vreg -> IFListType 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric void dump_map() const; 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric const HexagonInstrInfo *HII = nullptr; 5680b57cec5SDimitry Andric const HexagonRegisterInfo *HRI = nullptr; 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric MachineFunction *MFN; 5710b57cec5SDimitry Andric MachineRegisterInfo *MRI; 5720b57cec5SDimitry Andric MachineDominatorTree *MDT; 5730b57cec5SDimitry Andric CellMapShadow *CMS; 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric RegisterOrdering BaseOrd; 5760b57cec5SDimitry Andric RegisterOrdering CellOrd; 5770b57cec5SDimitry Andric IFMapType IFMap; 5780b57cec5SDimitry Andric }; 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric } // end anonymous namespace 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric char HexagonGenInsert::ID = 0; 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric void HexagonGenInsert::dump_map() const { 58504eeddc0SDimitry Andric for (const auto &I : IFMap) { 58604eeddc0SDimitry Andric dbgs() << " " << printReg(I.first, HRI) << ":\n"; 58704eeddc0SDimitry Andric const IFListType &LL = I.second; 58804eeddc0SDimitry Andric for (const auto &J : LL) 58904eeddc0SDimitry Andric dbgs() << " " << PrintIFR(J.first, HRI) << ", " 59004eeddc0SDimitry Andric << PrintRegSet(J.second, HRI) << '\n'; 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric void HexagonGenInsert::buildOrderingMF(RegisterOrdering &RO) const { 5950b57cec5SDimitry Andric unsigned Index = 0; 5960b57cec5SDimitry Andric 5974824e7fdSDimitry Andric for (const MachineBasicBlock &B : *MFN) { 5980b57cec5SDimitry Andric if (!CMS->BT.reached(&B)) 5990b57cec5SDimitry Andric continue; 6000b57cec5SDimitry Andric 6014824e7fdSDimitry Andric for (const MachineInstr &MI : B) { 6024824e7fdSDimitry Andric for (const MachineOperand &MO : MI.operands()) { 6030b57cec5SDimitry Andric if (MO.isReg() && MO.isDef()) { 6048bcb0991SDimitry Andric Register R = MO.getReg(); 6050b57cec5SDimitry Andric assert(MO.getSubReg() == 0 && "Unexpected subregister in definition"); 606e8d8bef9SDimitry Andric if (R.isVirtual()) 6070b57cec5SDimitry Andric RO.insert(std::make_pair(R, Index++)); 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric // Since some virtual registers may have had their def and uses eliminated, 6130b57cec5SDimitry Andric // they are no longer referenced in the code, and so they will not appear 6140b57cec5SDimitry Andric // in the map. 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric void HexagonGenInsert::buildOrderingBT(RegisterOrdering &RB, 6180b57cec5SDimitry Andric RegisterOrdering &RO) const { 6190b57cec5SDimitry Andric // Create a vector of all virtual registers (collect them from the base 6200b57cec5SDimitry Andric // ordering RB), and then sort it using the RegisterCell comparator. 6210b57cec5SDimitry Andric BitValueOrdering BVO(RB); 6220b57cec5SDimitry Andric RegisterCellLexCompare LexCmp(BVO, *CMS); 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric using SortableVectorType = std::vector<unsigned>; 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric SortableVectorType VRs; 62704eeddc0SDimitry Andric for (auto &I : RB) 62804eeddc0SDimitry Andric VRs.push_back(I.first); 6290b57cec5SDimitry Andric llvm::sort(VRs, LexCmp); 6300b57cec5SDimitry Andric // Transfer the results to the outgoing register ordering. 6310b57cec5SDimitry Andric for (unsigned i = 0, n = VRs.size(); i < n; ++i) 6320b57cec5SDimitry Andric RO.insert(std::make_pair(VRs[i], i)); 6330b57cec5SDimitry Andric } 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric inline bool HexagonGenInsert::isIntClass(const TargetRegisterClass *RC) const { 6360b57cec5SDimitry Andric return RC == &Hexagon::IntRegsRegClass || RC == &Hexagon::DoubleRegsRegClass; 6370b57cec5SDimitry Andric } 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric bool HexagonGenInsert::isConstant(unsigned VR) const { 6400b57cec5SDimitry Andric const BitTracker::RegisterCell &RC = CMS->lookup(VR); 6410b57cec5SDimitry Andric uint16_t W = RC.width(); 6420b57cec5SDimitry Andric for (uint16_t i = 0; i < W; ++i) { 6430b57cec5SDimitry Andric const BitTracker::BitValue &BV = RC[i]; 6440b57cec5SDimitry Andric if (BV.is(0) || BV.is(1)) 6450b57cec5SDimitry Andric continue; 6460b57cec5SDimitry Andric return false; 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric return true; 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric bool HexagonGenInsert::isSmallConstant(unsigned VR) const { 6520b57cec5SDimitry Andric const BitTracker::RegisterCell &RC = CMS->lookup(VR); 6530b57cec5SDimitry Andric uint16_t W = RC.width(); 6540b57cec5SDimitry Andric if (W > 64) 6550b57cec5SDimitry Andric return false; 6560b57cec5SDimitry Andric uint64_t V = 0, B = 1; 6570b57cec5SDimitry Andric for (uint16_t i = 0; i < W; ++i) { 6580b57cec5SDimitry Andric const BitTracker::BitValue &BV = RC[i]; 6590b57cec5SDimitry Andric if (BV.is(1)) 6600b57cec5SDimitry Andric V |= B; 6610b57cec5SDimitry Andric else if (!BV.is(0)) 6620b57cec5SDimitry Andric return false; 6630b57cec5SDimitry Andric B <<= 1; 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric // For 32-bit registers, consider: Rd = #s16. 6670b57cec5SDimitry Andric if (W == 32) 6680b57cec5SDimitry Andric return isInt<16>(V); 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric // For 64-bit registers, it's Rdd = #s8 or Rdd = combine(#s8,#s8) 6710b57cec5SDimitry Andric return isInt<8>(Lo_32(V)) && isInt<8>(Hi_32(V)); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric bool HexagonGenInsert::isValidInsertForm(unsigned DstR, unsigned SrcR, 6750b57cec5SDimitry Andric unsigned InsR, uint16_t L, uint16_t S) const { 6760b57cec5SDimitry Andric const TargetRegisterClass *DstRC = MRI->getRegClass(DstR); 6770b57cec5SDimitry Andric const TargetRegisterClass *SrcRC = MRI->getRegClass(SrcR); 6780b57cec5SDimitry Andric const TargetRegisterClass *InsRC = MRI->getRegClass(InsR); 6790b57cec5SDimitry Andric // Only integet (32-/64-bit) register classes. 6800b57cec5SDimitry Andric if (!isIntClass(DstRC) || !isIntClass(SrcRC) || !isIntClass(InsRC)) 6810b57cec5SDimitry Andric return false; 6820b57cec5SDimitry Andric // The "source" register must be of the same class as DstR. 6830b57cec5SDimitry Andric if (DstRC != SrcRC) 6840b57cec5SDimitry Andric return false; 6850b57cec5SDimitry Andric if (DstRC == InsRC) 6860b57cec5SDimitry Andric return true; 6870b57cec5SDimitry Andric // A 64-bit register can only be generated from other 64-bit registers. 6880b57cec5SDimitry Andric if (DstRC == &Hexagon::DoubleRegsRegClass) 6890b57cec5SDimitry Andric return false; 6900b57cec5SDimitry Andric // Otherwise, the L and S cannot span 32-bit word boundary. 6910b57cec5SDimitry Andric if (S < 32 && S+L > 32) 6920b57cec5SDimitry Andric return false; 6930b57cec5SDimitry Andric return true; 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric bool HexagonGenInsert::findSelfReference(unsigned VR) const { 6970b57cec5SDimitry Andric const BitTracker::RegisterCell &RC = CMS->lookup(VR); 6980b57cec5SDimitry Andric for (uint16_t i = 0, w = RC.width(); i < w; ++i) { 6990b57cec5SDimitry Andric const BitTracker::BitValue &V = RC[i]; 7000b57cec5SDimitry Andric if (V.Type == BitTracker::BitValue::Ref && V.RefI.Reg == VR) 7010b57cec5SDimitry Andric return true; 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric return false; 7040b57cec5SDimitry Andric } 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric bool HexagonGenInsert::findNonSelfReference(unsigned VR) const { 7070b57cec5SDimitry Andric BitTracker::RegisterCell RC = CMS->lookup(VR); 7080b57cec5SDimitry Andric for (uint16_t i = 0, w = RC.width(); i < w; ++i) { 7090b57cec5SDimitry Andric const BitTracker::BitValue &V = RC[i]; 7100b57cec5SDimitry Andric if (V.Type == BitTracker::BitValue::Ref && V.RefI.Reg != VR) 7110b57cec5SDimitry Andric return true; 7120b57cec5SDimitry Andric } 7130b57cec5SDimitry Andric return false; 7140b57cec5SDimitry Andric } 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric void HexagonGenInsert::getInstrDefs(const MachineInstr *MI, 7170b57cec5SDimitry Andric RegisterSet &Defs) const { 7184824e7fdSDimitry Andric for (const MachineOperand &MO : MI->operands()) { 7190b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef()) 7200b57cec5SDimitry Andric continue; 7218bcb0991SDimitry Andric Register R = MO.getReg(); 722e8d8bef9SDimitry Andric if (!R.isVirtual()) 7230b57cec5SDimitry Andric continue; 7240b57cec5SDimitry Andric Defs.insert(R); 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric void HexagonGenInsert::getInstrUses(const MachineInstr *MI, 7290b57cec5SDimitry Andric RegisterSet &Uses) const { 7304824e7fdSDimitry Andric for (const MachineOperand &MO : MI->operands()) { 7310b57cec5SDimitry Andric if (!MO.isReg() || !MO.isUse()) 7320b57cec5SDimitry Andric continue; 7338bcb0991SDimitry Andric Register R = MO.getReg(); 734e8d8bef9SDimitry Andric if (!R.isVirtual()) 7350b57cec5SDimitry Andric continue; 7360b57cec5SDimitry Andric Uses.insert(R); 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric unsigned HexagonGenInsert::distance(const MachineBasicBlock *FromB, 7410b57cec5SDimitry Andric const MachineBasicBlock *ToB, const UnsignedMap &RPO, 7420b57cec5SDimitry Andric PairMapType &M) const { 7430b57cec5SDimitry Andric // Forward distance from the end of a block to the beginning of it does 7440b57cec5SDimitry Andric // not make sense. This function should not be called with FromB == ToB. 7450b57cec5SDimitry Andric assert(FromB != ToB); 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric unsigned FromN = FromB->getNumber(), ToN = ToB->getNumber(); 7480b57cec5SDimitry Andric // If we have already computed it, return the cached result. 7490b57cec5SDimitry Andric PairMapType::iterator F = M.find(std::make_pair(FromN, ToN)); 7500b57cec5SDimitry Andric if (F != M.end()) 7510b57cec5SDimitry Andric return F->second; 7520b57cec5SDimitry Andric unsigned ToRPO = RPO.lookup(ToN); 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric unsigned MaxD = 0; 7550b57cec5SDimitry Andric 756349cc55cSDimitry Andric for (const MachineBasicBlock *PB : ToB->predecessors()) { 7570b57cec5SDimitry Andric // Skip back edges. Also, if FromB is a predecessor of ToB, the distance 7580b57cec5SDimitry Andric // along that path will be 0, and we don't need to do any calculations 7590b57cec5SDimitry Andric // on it. 7600b57cec5SDimitry Andric if (PB == FromB || RPO.lookup(PB->getNumber()) >= ToRPO) 7610b57cec5SDimitry Andric continue; 7620b57cec5SDimitry Andric unsigned D = PB->size() + distance(FromB, PB, RPO, M); 7630b57cec5SDimitry Andric if (D > MaxD) 7640b57cec5SDimitry Andric MaxD = D; 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric // Memoize the result for later lookup. 7680b57cec5SDimitry Andric M.insert(std::make_pair(std::make_pair(FromN, ToN), MaxD)); 7690b57cec5SDimitry Andric return MaxD; 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric unsigned HexagonGenInsert::distance(MachineBasicBlock::const_iterator FromI, 7730b57cec5SDimitry Andric MachineBasicBlock::const_iterator ToI, const UnsignedMap &RPO, 7740b57cec5SDimitry Andric PairMapType &M) const { 7750b57cec5SDimitry Andric const MachineBasicBlock *FB = FromI->getParent(), *TB = ToI->getParent(); 7760b57cec5SDimitry Andric if (FB == TB) 7770b57cec5SDimitry Andric return std::distance(FromI, ToI); 7780b57cec5SDimitry Andric unsigned D1 = std::distance(TB->begin(), ToI); 7790b57cec5SDimitry Andric unsigned D2 = distance(FB, TB, RPO, M); 7800b57cec5SDimitry Andric unsigned D3 = std::distance(FromI, FB->end()); 7810b57cec5SDimitry Andric return D1+D2+D3; 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric bool HexagonGenInsert::findRecordInsertForms(unsigned VR, 7850b57cec5SDimitry Andric OrderedRegisterList &AVs) { 7860b57cec5SDimitry Andric if (isDebug()) { 7870b57cec5SDimitry Andric dbgs() << __func__ << ": " << printReg(VR, HRI) 7880b57cec5SDimitry Andric << " AVs: " << PrintORL(AVs, HRI) << "\n"; 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric if (AVs.size() == 0) 7910b57cec5SDimitry Andric return false; 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric using iterator = OrderedRegisterList::iterator; 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric BitValueOrdering BVO(BaseOrd); 7960b57cec5SDimitry Andric const BitTracker::RegisterCell &RC = CMS->lookup(VR); 7970b57cec5SDimitry Andric uint16_t W = RC.width(); 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric using RSRecord = std::pair<unsigned, uint16_t>; // (reg,shift) 8000b57cec5SDimitry Andric using RSListType = std::vector<RSRecord>; 8010b57cec5SDimitry Andric // Have a map, with key being the matching prefix length, and the value 8020b57cec5SDimitry Andric // being the list of pairs (R,S), where R's prefix matches VR at S. 8030b57cec5SDimitry Andric // (DenseMap<uint16_t,RSListType> fails to instantiate.) 8040b57cec5SDimitry Andric using LRSMapType = DenseMap<unsigned, RSListType>; 8050b57cec5SDimitry Andric LRSMapType LM; 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric // Conceptually, rotate the cell RC right (i.e. towards the LSB) by S, 8080b57cec5SDimitry Andric // and find matching prefixes from AVs with the rotated RC. Such a prefix 8090b57cec5SDimitry Andric // would match a string of bits (of length L) in RC starting at S. 8100b57cec5SDimitry Andric for (uint16_t S = 0; S < W; ++S) { 8110b57cec5SDimitry Andric iterator B = AVs.begin(), E = AVs.end(); 8120b57cec5SDimitry Andric // The registers in AVs are ordered according to the lexical order of 8130b57cec5SDimitry Andric // the corresponding register cells. This means that the range of regis- 8140b57cec5SDimitry Andric // ters in AVs that match a prefix of length L+1 will be contained in 8150b57cec5SDimitry Andric // the range that matches a prefix of length L. This means that we can 8160b57cec5SDimitry Andric // keep narrowing the search space as the prefix length goes up. This 8170b57cec5SDimitry Andric // helps reduce the overall complexity of the search. 8180b57cec5SDimitry Andric uint16_t L; 8190b57cec5SDimitry Andric for (L = 0; L < W-S; ++L) { 8200b57cec5SDimitry Andric // Compare against VR's bits starting at S, which emulates rotation 8210b57cec5SDimitry Andric // of VR by S. 8220b57cec5SDimitry Andric RegisterCellBitCompareSel RCB(VR, S+L, L, BVO, *CMS); 8230b57cec5SDimitry Andric iterator NewB = std::lower_bound(B, E, VR, RCB); 8240b57cec5SDimitry Andric iterator NewE = std::upper_bound(NewB, E, VR, RCB); 8250b57cec5SDimitry Andric // For the registers that are eliminated from the next range, L is 8260b57cec5SDimitry Andric // the longest prefix matching VR at position S (their prefixes 8270b57cec5SDimitry Andric // differ from VR at S+L). If L>0, record this information for later 8280b57cec5SDimitry Andric // use. 8290b57cec5SDimitry Andric if (L > 0) { 8300b57cec5SDimitry Andric for (iterator I = B; I != NewB; ++I) 8310b57cec5SDimitry Andric LM[L].push_back(std::make_pair(*I, S)); 8320b57cec5SDimitry Andric for (iterator I = NewE; I != E; ++I) 8330b57cec5SDimitry Andric LM[L].push_back(std::make_pair(*I, S)); 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric B = NewB, E = NewE; 8360b57cec5SDimitry Andric if (B == E) 8370b57cec5SDimitry Andric break; 8380b57cec5SDimitry Andric } 8390b57cec5SDimitry Andric // Record the final register range. If this range is non-empty, then 8400b57cec5SDimitry Andric // L=W-S. 8410b57cec5SDimitry Andric assert(B == E || L == W-S); 8420b57cec5SDimitry Andric if (B != E) { 8430b57cec5SDimitry Andric for (iterator I = B; I != E; ++I) 8440b57cec5SDimitry Andric LM[L].push_back(std::make_pair(*I, S)); 8450b57cec5SDimitry Andric // If B!=E, then we found a range of registers whose prefixes cover the 8460b57cec5SDimitry Andric // rest of VR from position S. There is no need to further advance S. 8470b57cec5SDimitry Andric break; 8480b57cec5SDimitry Andric } 8490b57cec5SDimitry Andric } 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric if (isDebug()) { 8520b57cec5SDimitry Andric dbgs() << "Prefixes matching register " << printReg(VR, HRI) << "\n"; 85304eeddc0SDimitry Andric for (const auto &I : LM) { 85404eeddc0SDimitry Andric dbgs() << " L=" << I.first << ':'; 85504eeddc0SDimitry Andric const RSListType &LL = I.second; 85604eeddc0SDimitry Andric for (const auto &J : LL) 85704eeddc0SDimitry Andric dbgs() << " (" << printReg(J.first, HRI) << ",@" << J.second << ')'; 8580b57cec5SDimitry Andric dbgs() << '\n'; 8590b57cec5SDimitry Andric } 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric bool Recorded = false; 8630b57cec5SDimitry Andric 86404eeddc0SDimitry Andric for (unsigned SrcR : AVs) { 8650b57cec5SDimitry Andric int FDi = -1, LDi = -1; // First/last different bit. 8660b57cec5SDimitry Andric const BitTracker::RegisterCell &AC = CMS->lookup(SrcR); 8670b57cec5SDimitry Andric uint16_t AW = AC.width(); 8680b57cec5SDimitry Andric for (uint16_t i = 0, w = std::min(W, AW); i < w; ++i) { 8690b57cec5SDimitry Andric if (RC[i] == AC[i]) 8700b57cec5SDimitry Andric continue; 8710b57cec5SDimitry Andric if (FDi == -1) 8720b57cec5SDimitry Andric FDi = i; 8730b57cec5SDimitry Andric LDi = i; 8740b57cec5SDimitry Andric } 8750b57cec5SDimitry Andric if (FDi == -1) 8760b57cec5SDimitry Andric continue; // TODO (future): Record identical registers. 8770b57cec5SDimitry Andric // Look for a register whose prefix could patch the range [FD..LD] 8780b57cec5SDimitry Andric // where VR and SrcR differ. 8790b57cec5SDimitry Andric uint16_t FD = FDi, LD = LDi; // Switch to unsigned type. 8800b57cec5SDimitry Andric uint16_t MinL = LD-FD+1; 8810b57cec5SDimitry Andric for (uint16_t L = MinL; L < W; ++L) { 8820b57cec5SDimitry Andric LRSMapType::iterator F = LM.find(L); 8830b57cec5SDimitry Andric if (F == LM.end()) 8840b57cec5SDimitry Andric continue; 8850b57cec5SDimitry Andric RSListType &LL = F->second; 88604eeddc0SDimitry Andric for (const auto &I : LL) { 88704eeddc0SDimitry Andric uint16_t S = I.second; 8880b57cec5SDimitry Andric // MinL is the minimum length of the prefix. Any length above MinL 8890b57cec5SDimitry Andric // allows some flexibility as to where the prefix can start: 8900b57cec5SDimitry Andric // given the extra length EL=L-MinL, the prefix must start between 8910b57cec5SDimitry Andric // max(0,FD-EL) and FD. 8920b57cec5SDimitry Andric if (S > FD) // Starts too late. 8930b57cec5SDimitry Andric continue; 8940b57cec5SDimitry Andric uint16_t EL = L-MinL; 8950b57cec5SDimitry Andric uint16_t LowS = (EL < FD) ? FD-EL : 0; 8960b57cec5SDimitry Andric if (S < LowS) // Starts too early. 8970b57cec5SDimitry Andric continue; 89804eeddc0SDimitry Andric unsigned InsR = I.first; 8990b57cec5SDimitry Andric if (!isValidInsertForm(VR, SrcR, InsR, L, S)) 9000b57cec5SDimitry Andric continue; 9010b57cec5SDimitry Andric if (isDebug()) { 9020b57cec5SDimitry Andric dbgs() << printReg(VR, HRI) << " = insert(" << printReg(SrcR, HRI) 9030b57cec5SDimitry Andric << ',' << printReg(InsR, HRI) << ",#" << L << ",#" 9040b57cec5SDimitry Andric << S << ")\n"; 9050b57cec5SDimitry Andric } 9060b57cec5SDimitry Andric IFRecordWithRegSet RR(IFRecord(SrcR, InsR, L, S), RegisterSet()); 9070b57cec5SDimitry Andric IFMap[VR].push_back(RR); 9080b57cec5SDimitry Andric Recorded = true; 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric } 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric return Recorded; 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric void HexagonGenInsert::collectInBlock(MachineBasicBlock *B, 9170b57cec5SDimitry Andric OrderedRegisterList &AVs) { 9180b57cec5SDimitry Andric if (isDebug()) 9190b57cec5SDimitry Andric dbgs() << "visiting block " << printMBBReference(*B) << "\n"; 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric // First, check if this block is reachable at all. If not, the bit tracker 9220b57cec5SDimitry Andric // will not have any information about registers in it. 9230b57cec5SDimitry Andric if (!CMS->BT.reached(B)) 9240b57cec5SDimitry Andric return; 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric bool DoConst = OptConst; 9270b57cec5SDimitry Andric // Keep a separate set of registers defined in this block, so that we 9280b57cec5SDimitry Andric // can remove them from the list of available registers once all DT 9290b57cec5SDimitry Andric // successors have been processed. 9300b57cec5SDimitry Andric RegisterSet BlockDefs, InsDefs; 9314824e7fdSDimitry Andric for (MachineInstr &MI : *B) { 9320b57cec5SDimitry Andric InsDefs.clear(); 9334824e7fdSDimitry Andric getInstrDefs(&MI, InsDefs); 9340b57cec5SDimitry Andric // Leave those alone. They are more transparent than "insert". 9354824e7fdSDimitry Andric bool Skip = MI.isCopy() || MI.isRegSequence(); 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric if (!Skip) { 9380b57cec5SDimitry Andric // Visit all defined registers, and attempt to find the corresponding 9390b57cec5SDimitry Andric // "insert" representations. 9400b57cec5SDimitry Andric for (unsigned VR = InsDefs.find_first(); VR; VR = InsDefs.find_next(VR)) { 9410b57cec5SDimitry Andric // Do not collect registers that are known to be compile-time cons- 9420b57cec5SDimitry Andric // tants, unless requested. 9430b57cec5SDimitry Andric if (!DoConst && isConstant(VR)) 9440b57cec5SDimitry Andric continue; 9450b57cec5SDimitry Andric // If VR's cell contains a reference to VR, then VR cannot be defined 9460b57cec5SDimitry Andric // via "insert". If VR is a constant that can be generated in a single 9470b57cec5SDimitry Andric // instruction (without constant extenders), generating it via insert 9480b57cec5SDimitry Andric // makes no sense. 9490b57cec5SDimitry Andric if (findSelfReference(VR) || isSmallConstant(VR)) 9500b57cec5SDimitry Andric continue; 9510b57cec5SDimitry Andric 9520b57cec5SDimitry Andric findRecordInsertForms(VR, AVs); 9530b57cec5SDimitry Andric // Stop if the map size is too large. 9540b57cec5SDimitry Andric if (IFMap.size() > MaxIFMSize) 9550b57cec5SDimitry Andric return; 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric 9590b57cec5SDimitry Andric // Insert the defined registers into the list of available registers 9600b57cec5SDimitry Andric // after they have been processed. 9610b57cec5SDimitry Andric for (unsigned VR = InsDefs.find_first(); VR; VR = InsDefs.find_next(VR)) 9620b57cec5SDimitry Andric AVs.insert(VR); 9630b57cec5SDimitry Andric BlockDefs.insert(InsDefs); 9640b57cec5SDimitry Andric } 9650b57cec5SDimitry Andric 9660b57cec5SDimitry Andric for (auto *DTN : children<MachineDomTreeNode*>(MDT->getNode(B))) { 9670b57cec5SDimitry Andric MachineBasicBlock *SB = DTN->getBlock(); 9680b57cec5SDimitry Andric collectInBlock(SB, AVs); 9690b57cec5SDimitry Andric } 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric for (unsigned VR = BlockDefs.find_first(); VR; VR = BlockDefs.find_next(VR)) 9720b57cec5SDimitry Andric AVs.remove(VR); 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric void HexagonGenInsert::findRemovableRegisters(unsigned VR, IFRecord IF, 9760b57cec5SDimitry Andric RegisterSet &RMs) const { 9770b57cec5SDimitry Andric // For a given register VR and a insert form, find the registers that are 9780b57cec5SDimitry Andric // used by the current definition of VR, and which would no longer be 9790b57cec5SDimitry Andric // needed for it after the definition of VR is replaced with the insert 9800b57cec5SDimitry Andric // form. These are the registers that could potentially become dead. 9810b57cec5SDimitry Andric RegisterSet Regs[2]; 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric unsigned S = 0; // Register set selector. 9840b57cec5SDimitry Andric Regs[S].insert(VR); 9850b57cec5SDimitry Andric 9860b57cec5SDimitry Andric while (!Regs[S].empty()) { 9870b57cec5SDimitry Andric // Breadth-first search. 9880b57cec5SDimitry Andric unsigned OtherS = 1-S; 9890b57cec5SDimitry Andric Regs[OtherS].clear(); 9900b57cec5SDimitry Andric for (unsigned R = Regs[S].find_first(); R; R = Regs[S].find_next(R)) { 9910b57cec5SDimitry Andric Regs[S].remove(R); 9920b57cec5SDimitry Andric if (R == IF.SrcR || R == IF.InsR) 9930b57cec5SDimitry Andric continue; 9940b57cec5SDimitry Andric // Check if a given register has bits that are references to any other 9950b57cec5SDimitry Andric // registers. This is to detect situations where the instruction that 9960b57cec5SDimitry Andric // defines register R takes register Q as an operand, but R itself does 9970b57cec5SDimitry Andric // not contain any bits from Q. Loads are examples of how this could 9980b57cec5SDimitry Andric // happen: 9990b57cec5SDimitry Andric // R = load Q 10000b57cec5SDimitry Andric // In this case (assuming we do not have any knowledge about the loaded 10010b57cec5SDimitry Andric // value), we must not treat R as a "conveyance" of the bits from Q. 10020b57cec5SDimitry Andric // (The information in BT about R's bits would have them as constants, 10030b57cec5SDimitry Andric // in case of zero-extending loads, or refs to R.) 10040b57cec5SDimitry Andric if (!findNonSelfReference(R)) 10050b57cec5SDimitry Andric continue; 10060b57cec5SDimitry Andric RMs.insert(R); 10070b57cec5SDimitry Andric const MachineInstr *DefI = MRI->getVRegDef(R); 10080b57cec5SDimitry Andric assert(DefI); 10090b57cec5SDimitry Andric // Do not iterate past PHI nodes to avoid infinite loops. This can 10100b57cec5SDimitry Andric // make the final set a bit less accurate, but the removable register 10110b57cec5SDimitry Andric // sets are an approximation anyway. 10120b57cec5SDimitry Andric if (DefI->isPHI()) 10130b57cec5SDimitry Andric continue; 10140b57cec5SDimitry Andric getInstrUses(DefI, Regs[OtherS]); 10150b57cec5SDimitry Andric } 10160b57cec5SDimitry Andric S = OtherS; 10170b57cec5SDimitry Andric } 10180b57cec5SDimitry Andric // The register VR is added to the list as a side-effect of the algorithm, 10190b57cec5SDimitry Andric // but it is not "potentially removable". A potentially removable register 10200b57cec5SDimitry Andric // is one that may become unused (dead) after conversion to the insert form 10210b57cec5SDimitry Andric // IF, and obviously VR (or its replacement) will not become dead by apply- 10220b57cec5SDimitry Andric // ing IF. 10230b57cec5SDimitry Andric RMs.remove(VR); 10240b57cec5SDimitry Andric } 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric void HexagonGenInsert::computeRemovableRegisters() { 102704eeddc0SDimitry Andric for (auto &I : IFMap) { 102804eeddc0SDimitry Andric IFListType &LL = I.second; 102904eeddc0SDimitry Andric for (auto &J : LL) 103004eeddc0SDimitry Andric findRemovableRegisters(I.first, J.first, J.second); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric } 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric void HexagonGenInsert::pruneEmptyLists() { 10350b57cec5SDimitry Andric // Remove all entries from the map, where the register has no insert forms 10360b57cec5SDimitry Andric // associated with it. 10370b57cec5SDimitry Andric using IterListType = SmallVector<IFMapType::iterator, 16>; 10380b57cec5SDimitry Andric IterListType Prune; 10390b57cec5SDimitry Andric for (IFMapType::iterator I = IFMap.begin(), E = IFMap.end(); I != E; ++I) { 10400b57cec5SDimitry Andric if (I->second.empty()) 10410b57cec5SDimitry Andric Prune.push_back(I); 10420b57cec5SDimitry Andric } 1043*0fca6ea1SDimitry Andric for (const auto &It : Prune) 1044*0fca6ea1SDimitry Andric IFMap.erase(It); 10450b57cec5SDimitry Andric } 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric void HexagonGenInsert::pruneCoveredSets(unsigned VR) { 10480b57cec5SDimitry Andric IFMapType::iterator F = IFMap.find(VR); 10490b57cec5SDimitry Andric assert(F != IFMap.end()); 10500b57cec5SDimitry Andric IFListType &LL = F->second; 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric // First, examine the IF candidates for register VR whose removable-regis- 10530b57cec5SDimitry Andric // ter sets are empty. This means that a given candidate will not help eli- 10540b57cec5SDimitry Andric // minate any registers, but since "insert" is not a constant-extendable 10550b57cec5SDimitry Andric // instruction, using such a candidate may reduce code size if the defini- 10560b57cec5SDimitry Andric // tion of VR is constant-extended. 10570b57cec5SDimitry Andric // If there exists a candidate with a non-empty set, the ones with empty 10580b57cec5SDimitry Andric // sets will not be used and can be removed. 10590b57cec5SDimitry Andric MachineInstr *DefVR = MRI->getVRegDef(VR); 10600b57cec5SDimitry Andric bool DefEx = HII->isConstExtended(*DefVR); 10610b57cec5SDimitry Andric bool HasNE = false; 106204eeddc0SDimitry Andric for (const auto &I : LL) { 106304eeddc0SDimitry Andric if (I.second.empty()) 10640b57cec5SDimitry Andric continue; 10650b57cec5SDimitry Andric HasNE = true; 10660b57cec5SDimitry Andric break; 10670b57cec5SDimitry Andric } 10680b57cec5SDimitry Andric if (!DefEx || HasNE) { 10690b57cec5SDimitry Andric // The definition of VR is not constant-extended, or there is a candidate 10700b57cec5SDimitry Andric // with a non-empty set. Remove all candidates with empty sets. 10710b57cec5SDimitry Andric auto IsEmpty = [] (const IFRecordWithRegSet &IR) -> bool { 10720b57cec5SDimitry Andric return IR.second.empty(); 10730b57cec5SDimitry Andric }; 1074e8d8bef9SDimitry Andric llvm::erase_if(LL, IsEmpty); 10750b57cec5SDimitry Andric } else { 10760b57cec5SDimitry Andric // The definition of VR is constant-extended, and all candidates have 10770b57cec5SDimitry Andric // empty removable-register sets. Pick the maximum candidate, and remove 10780b57cec5SDimitry Andric // all others. The "maximum" does not have any special meaning here, it 10790b57cec5SDimitry Andric // is only so that the candidate that will remain on the list is selec- 10800b57cec5SDimitry Andric // ted deterministically. 10810b57cec5SDimitry Andric IFRecord MaxIF = LL[0].first; 10820b57cec5SDimitry Andric for (unsigned i = 1, n = LL.size(); i < n; ++i) { 10830b57cec5SDimitry Andric // If LL[MaxI] < LL[i], then MaxI = i. 10840b57cec5SDimitry Andric const IFRecord &IF = LL[i].first; 10850b57cec5SDimitry Andric unsigned M0 = BaseOrd[MaxIF.SrcR], M1 = BaseOrd[MaxIF.InsR]; 10860b57cec5SDimitry Andric unsigned R0 = BaseOrd[IF.SrcR], R1 = BaseOrd[IF.InsR]; 10870b57cec5SDimitry Andric if (M0 > R0) 10880b57cec5SDimitry Andric continue; 10890b57cec5SDimitry Andric if (M0 == R0) { 10900b57cec5SDimitry Andric if (M1 > R1) 10910b57cec5SDimitry Andric continue; 10920b57cec5SDimitry Andric if (M1 == R1) { 10930b57cec5SDimitry Andric if (MaxIF.Wdh > IF.Wdh) 10940b57cec5SDimitry Andric continue; 10950b57cec5SDimitry Andric if (MaxIF.Wdh == IF.Wdh && MaxIF.Off >= IF.Off) 10960b57cec5SDimitry Andric continue; 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric } 10990b57cec5SDimitry Andric // MaxIF < IF. 11000b57cec5SDimitry Andric MaxIF = IF; 11010b57cec5SDimitry Andric } 11020b57cec5SDimitry Andric // Remove everything except the maximum candidate. All register sets 11030b57cec5SDimitry Andric // are empty, so no need to preserve anything. 11040b57cec5SDimitry Andric LL.clear(); 11050b57cec5SDimitry Andric LL.push_back(std::make_pair(MaxIF, RegisterSet())); 11060b57cec5SDimitry Andric } 11070b57cec5SDimitry Andric 11080b57cec5SDimitry Andric // Now, remove those whose sets of potentially removable registers are 11090b57cec5SDimitry Andric // contained in another IF candidate for VR. For example, given these 11100b57cec5SDimitry Andric // candidates for %45, 11110b57cec5SDimitry Andric // %45: 11120b57cec5SDimitry Andric // (%44,%41,#9,#8), { %42 } 11130b57cec5SDimitry Andric // (%43,%41,#9,#8), { %42 %44 } 11140b57cec5SDimitry Andric // remove the first one, since it is contained in the second one. 11150b57cec5SDimitry Andric for (unsigned i = 0, n = LL.size(); i < n; ) { 11160b57cec5SDimitry Andric const RegisterSet &RMi = LL[i].second; 11170b57cec5SDimitry Andric unsigned j = 0; 11180b57cec5SDimitry Andric while (j < n) { 11190b57cec5SDimitry Andric if (j != i && LL[j].second.includes(RMi)) 11200b57cec5SDimitry Andric break; 11210b57cec5SDimitry Andric j++; 11220b57cec5SDimitry Andric } 11230b57cec5SDimitry Andric if (j == n) { // RMi not contained in anything else. 11240b57cec5SDimitry Andric i++; 11250b57cec5SDimitry Andric continue; 11260b57cec5SDimitry Andric } 11270b57cec5SDimitry Andric LL.erase(LL.begin()+i); 11280b57cec5SDimitry Andric n = LL.size(); 11290b57cec5SDimitry Andric } 11300b57cec5SDimitry Andric } 11310b57cec5SDimitry Andric 11320b57cec5SDimitry Andric void HexagonGenInsert::pruneUsesTooFar(unsigned VR, const UnsignedMap &RPO, 11330b57cec5SDimitry Andric PairMapType &M) { 11340b57cec5SDimitry Andric IFMapType::iterator F = IFMap.find(VR); 11350b57cec5SDimitry Andric assert(F != IFMap.end()); 11360b57cec5SDimitry Andric IFListType &LL = F->second; 11370b57cec5SDimitry Andric unsigned Cutoff = VRegDistCutoff; 11380b57cec5SDimitry Andric const MachineInstr *DefV = MRI->getVRegDef(VR); 11390b57cec5SDimitry Andric 11400b57cec5SDimitry Andric for (unsigned i = LL.size(); i > 0; --i) { 11410b57cec5SDimitry Andric unsigned SR = LL[i-1].first.SrcR, IR = LL[i-1].first.InsR; 11420b57cec5SDimitry Andric const MachineInstr *DefS = MRI->getVRegDef(SR); 11430b57cec5SDimitry Andric const MachineInstr *DefI = MRI->getVRegDef(IR); 11440b57cec5SDimitry Andric unsigned DSV = distance(DefS, DefV, RPO, M); 11450b57cec5SDimitry Andric if (DSV < Cutoff) { 11460b57cec5SDimitry Andric unsigned DIV = distance(DefI, DefV, RPO, M); 11470b57cec5SDimitry Andric if (DIV < Cutoff) 11480b57cec5SDimitry Andric continue; 11490b57cec5SDimitry Andric } 11500b57cec5SDimitry Andric LL.erase(LL.begin()+(i-1)); 11510b57cec5SDimitry Andric } 11520b57cec5SDimitry Andric } 11530b57cec5SDimitry Andric 11540b57cec5SDimitry Andric void HexagonGenInsert::pruneRegCopies(unsigned VR) { 11550b57cec5SDimitry Andric IFMapType::iterator F = IFMap.find(VR); 11560b57cec5SDimitry Andric assert(F != IFMap.end()); 11570b57cec5SDimitry Andric IFListType &LL = F->second; 11580b57cec5SDimitry Andric 11590b57cec5SDimitry Andric auto IsCopy = [] (const IFRecordWithRegSet &IR) -> bool { 11600b57cec5SDimitry Andric return IR.first.Wdh == 32 && (IR.first.Off == 0 || IR.first.Off == 32); 11610b57cec5SDimitry Andric }; 1162e8d8bef9SDimitry Andric llvm::erase_if(LL, IsCopy); 11630b57cec5SDimitry Andric } 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric void HexagonGenInsert::pruneCandidates() { 11660b57cec5SDimitry Andric // Remove candidates that are not beneficial, regardless of the final 11670b57cec5SDimitry Andric // selection method. 11680b57cec5SDimitry Andric // First, remove candidates whose potentially removable set is a subset 11690b57cec5SDimitry Andric // of another candidate's set. 117004eeddc0SDimitry Andric for (const auto &I : IFMap) 117104eeddc0SDimitry Andric pruneCoveredSets(I.first); 11720b57cec5SDimitry Andric 11730b57cec5SDimitry Andric UnsignedMap RPO; 11740b57cec5SDimitry Andric 11750b57cec5SDimitry Andric using RPOTType = ReversePostOrderTraversal<const MachineFunction *>; 11760b57cec5SDimitry Andric 11770b57cec5SDimitry Andric RPOTType RPOT(MFN); 11780b57cec5SDimitry Andric unsigned RPON = 0; 117904eeddc0SDimitry Andric for (const auto &I : RPOT) 118004eeddc0SDimitry Andric RPO[I->getNumber()] = RPON++; 11810b57cec5SDimitry Andric 11820b57cec5SDimitry Andric PairMapType Memo; // Memoization map for distance calculation. 11830b57cec5SDimitry Andric // Remove candidates that would use registers defined too far away. 118404eeddc0SDimitry Andric for (const auto &I : IFMap) 118504eeddc0SDimitry Andric pruneUsesTooFar(I.first, RPO, Memo); 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric pruneEmptyLists(); 11880b57cec5SDimitry Andric 118904eeddc0SDimitry Andric for (const auto &I : IFMap) 119004eeddc0SDimitry Andric pruneRegCopies(I.first); 11910b57cec5SDimitry Andric } 11920b57cec5SDimitry Andric 11930b57cec5SDimitry Andric namespace { 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric // Class for comparing IF candidates for registers that have multiple of 11960b57cec5SDimitry Andric // them. The smaller the candidate, according to this ordering, the better. 11970b57cec5SDimitry Andric // First, compare the number of zeros in the associated potentially remova- 11980b57cec5SDimitry Andric // ble register sets. "Zero" indicates that the register is very likely to 11990b57cec5SDimitry Andric // become dead after this transformation. 12000b57cec5SDimitry Andric // Second, compare "averages", i.e. use-count per size. The lower wins. 12010b57cec5SDimitry Andric // After that, it does not really matter which one is smaller. Resolve 12020b57cec5SDimitry Andric // the tie in some deterministic way. 12030b57cec5SDimitry Andric struct IFOrdering { 12040b57cec5SDimitry Andric IFOrdering(const UnsignedMap &UC, const RegisterOrdering &BO) 12050b57cec5SDimitry Andric : UseC(UC), BaseOrd(BO) {} 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric bool operator() (const IFRecordWithRegSet &A, 12080b57cec5SDimitry Andric const IFRecordWithRegSet &B) const; 12090b57cec5SDimitry Andric 12100b57cec5SDimitry Andric private: 12110b57cec5SDimitry Andric void stats(const RegisterSet &Rs, unsigned &Size, unsigned &Zero, 12120b57cec5SDimitry Andric unsigned &Sum) const; 12130b57cec5SDimitry Andric 12140b57cec5SDimitry Andric const UnsignedMap &UseC; 12150b57cec5SDimitry Andric const RegisterOrdering &BaseOrd; 12160b57cec5SDimitry Andric }; 12170b57cec5SDimitry Andric 12180b57cec5SDimitry Andric } // end anonymous namespace 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andric bool IFOrdering::operator() (const IFRecordWithRegSet &A, 12210b57cec5SDimitry Andric const IFRecordWithRegSet &B) const { 12220b57cec5SDimitry Andric unsigned SizeA = 0, ZeroA = 0, SumA = 0; 12230b57cec5SDimitry Andric unsigned SizeB = 0, ZeroB = 0, SumB = 0; 12240b57cec5SDimitry Andric stats(A.second, SizeA, ZeroA, SumA); 12250b57cec5SDimitry Andric stats(B.second, SizeB, ZeroB, SumB); 12260b57cec5SDimitry Andric 12270b57cec5SDimitry Andric // We will pick the minimum element. The more zeros, the better. 12280b57cec5SDimitry Andric if (ZeroA != ZeroB) 12290b57cec5SDimitry Andric return ZeroA > ZeroB; 12300b57cec5SDimitry Andric // Compare SumA/SizeA with SumB/SizeB, lower is better. 12310b57cec5SDimitry Andric uint64_t AvgA = SumA*SizeB, AvgB = SumB*SizeA; 12320b57cec5SDimitry Andric if (AvgA != AvgB) 12330b57cec5SDimitry Andric return AvgA < AvgB; 12340b57cec5SDimitry Andric 12350b57cec5SDimitry Andric // The sets compare identical so far. Resort to comparing the IF records. 12360b57cec5SDimitry Andric // The actual values don't matter, this is only for determinism. 12370b57cec5SDimitry Andric unsigned OSA = BaseOrd[A.first.SrcR], OSB = BaseOrd[B.first.SrcR]; 12380b57cec5SDimitry Andric if (OSA != OSB) 12390b57cec5SDimitry Andric return OSA < OSB; 12400b57cec5SDimitry Andric unsigned OIA = BaseOrd[A.first.InsR], OIB = BaseOrd[B.first.InsR]; 12410b57cec5SDimitry Andric if (OIA != OIB) 12420b57cec5SDimitry Andric return OIA < OIB; 12430b57cec5SDimitry Andric if (A.first.Wdh != B.first.Wdh) 12440b57cec5SDimitry Andric return A.first.Wdh < B.first.Wdh; 12450b57cec5SDimitry Andric return A.first.Off < B.first.Off; 12460b57cec5SDimitry Andric } 12470b57cec5SDimitry Andric 12480b57cec5SDimitry Andric void IFOrdering::stats(const RegisterSet &Rs, unsigned &Size, unsigned &Zero, 12490b57cec5SDimitry Andric unsigned &Sum) const { 12500b57cec5SDimitry Andric for (unsigned R = Rs.find_first(); R; R = Rs.find_next(R)) { 12510b57cec5SDimitry Andric UnsignedMap::const_iterator F = UseC.find(R); 12520b57cec5SDimitry Andric assert(F != UseC.end()); 12530b57cec5SDimitry Andric unsigned UC = F->second; 12540b57cec5SDimitry Andric if (UC == 0) 12550b57cec5SDimitry Andric Zero++; 12560b57cec5SDimitry Andric Sum += UC; 12570b57cec5SDimitry Andric Size++; 12580b57cec5SDimitry Andric } 12590b57cec5SDimitry Andric } 12600b57cec5SDimitry Andric 12610b57cec5SDimitry Andric void HexagonGenInsert::selectCandidates() { 12620b57cec5SDimitry Andric // Some registers may have multiple valid candidates. Pick the best one 12630b57cec5SDimitry Andric // (or decide not to use any). 12640b57cec5SDimitry Andric 12650b57cec5SDimitry Andric // Compute the "removability" measure of R: 12660b57cec5SDimitry Andric // For each potentially removable register R, record the number of regis- 12670b57cec5SDimitry Andric // ters with IF candidates, where R appears in at least one set. 12680b57cec5SDimitry Andric RegisterSet AllRMs; 12690b57cec5SDimitry Andric UnsignedMap UseC, RemC; 12700b57cec5SDimitry Andric IFMapType::iterator End = IFMap.end(); 12710b57cec5SDimitry Andric 12720b57cec5SDimitry Andric for (IFMapType::iterator I = IFMap.begin(); I != End; ++I) { 12730b57cec5SDimitry Andric const IFListType &LL = I->second; 12740b57cec5SDimitry Andric RegisterSet TT; 127504eeddc0SDimitry Andric for (const auto &J : LL) 127604eeddc0SDimitry Andric TT.insert(J.second); 12770b57cec5SDimitry Andric for (unsigned R = TT.find_first(); R; R = TT.find_next(R)) 12780b57cec5SDimitry Andric RemC[R]++; 12790b57cec5SDimitry Andric AllRMs.insert(TT); 12800b57cec5SDimitry Andric } 12810b57cec5SDimitry Andric 12820b57cec5SDimitry Andric for (unsigned R = AllRMs.find_first(); R; R = AllRMs.find_next(R)) { 12830b57cec5SDimitry Andric using use_iterator = MachineRegisterInfo::use_nodbg_iterator; 12840b57cec5SDimitry Andric using InstrSet = SmallSet<const MachineInstr *, 16>; 12850b57cec5SDimitry Andric 12860b57cec5SDimitry Andric InstrSet UIs; 12870b57cec5SDimitry Andric // Count as the number of instructions in which R is used, not the 12880b57cec5SDimitry Andric // number of operands. 12890b57cec5SDimitry Andric use_iterator E = MRI->use_nodbg_end(); 12900b57cec5SDimitry Andric for (use_iterator I = MRI->use_nodbg_begin(R); I != E; ++I) 12910b57cec5SDimitry Andric UIs.insert(I->getParent()); 12920b57cec5SDimitry Andric unsigned C = UIs.size(); 12930b57cec5SDimitry Andric // Calculate a measure, which is the number of instructions using R, 12940b57cec5SDimitry Andric // minus the "removability" count computed earlier. 12950b57cec5SDimitry Andric unsigned D = RemC[R]; 12960b57cec5SDimitry Andric UseC[R] = (C > D) ? C-D : 0; // doz 12970b57cec5SDimitry Andric } 12980b57cec5SDimitry Andric 12990b57cec5SDimitry Andric bool SelectAll0 = OptSelectAll0, SelectHas0 = OptSelectHas0; 13000b57cec5SDimitry Andric if (!SelectAll0 && !SelectHas0) 13010b57cec5SDimitry Andric SelectAll0 = true; 13020b57cec5SDimitry Andric 13030b57cec5SDimitry Andric // The smaller the number UseC for a given register R, the "less used" 13040b57cec5SDimitry Andric // R is aside from the opportunities for removal offered by generating 13050b57cec5SDimitry Andric // "insert" instructions. 13060b57cec5SDimitry Andric // Iterate over the IF map, and for those registers that have multiple 13070b57cec5SDimitry Andric // candidates, pick the minimum one according to IFOrdering. 13080b57cec5SDimitry Andric IFOrdering IFO(UseC, BaseOrd); 13090b57cec5SDimitry Andric for (IFMapType::iterator I = IFMap.begin(); I != End; ++I) { 13100b57cec5SDimitry Andric IFListType &LL = I->second; 13110b57cec5SDimitry Andric if (LL.empty()) 13120b57cec5SDimitry Andric continue; 13130b57cec5SDimitry Andric // Get the minimum element, remember it and clear the list. If the 13140b57cec5SDimitry Andric // element found is adequate, we will put it back on the list, other- 13150b57cec5SDimitry Andric // wise the list will remain empty, and the entry for this register 13160b57cec5SDimitry Andric // will be removed (i.e. this register will not be replaced by insert). 1317*0fca6ea1SDimitry Andric IFListType::iterator MinI = llvm::min_element(LL, IFO); 13180b57cec5SDimitry Andric assert(MinI != LL.end()); 13190b57cec5SDimitry Andric IFRecordWithRegSet M = *MinI; 13200b57cec5SDimitry Andric LL.clear(); 13210b57cec5SDimitry Andric 13220b57cec5SDimitry Andric // We want to make sure that this replacement will have a chance to be 13230b57cec5SDimitry Andric // beneficial, and that means that we want to have indication that some 13240b57cec5SDimitry Andric // register will be removed. The most likely registers to be eliminated 13250b57cec5SDimitry Andric // are the use operands in the definition of I->first. Accept/reject a 13260b57cec5SDimitry Andric // candidate based on how many of its uses it can potentially eliminate. 13270b57cec5SDimitry Andric 13280b57cec5SDimitry Andric RegisterSet Us; 13290b57cec5SDimitry Andric const MachineInstr *DefI = MRI->getVRegDef(I->first); 13300b57cec5SDimitry Andric getInstrUses(DefI, Us); 13310b57cec5SDimitry Andric bool Accept = false; 13320b57cec5SDimitry Andric 13330b57cec5SDimitry Andric if (SelectAll0) { 13340b57cec5SDimitry Andric bool All0 = true; 13350b57cec5SDimitry Andric for (unsigned R = Us.find_first(); R; R = Us.find_next(R)) { 13360b57cec5SDimitry Andric if (UseC[R] == 0) 13370b57cec5SDimitry Andric continue; 13380b57cec5SDimitry Andric All0 = false; 13390b57cec5SDimitry Andric break; 13400b57cec5SDimitry Andric } 13410b57cec5SDimitry Andric Accept = All0; 13420b57cec5SDimitry Andric } else if (SelectHas0) { 13430b57cec5SDimitry Andric bool Has0 = false; 13440b57cec5SDimitry Andric for (unsigned R = Us.find_first(); R; R = Us.find_next(R)) { 13450b57cec5SDimitry Andric if (UseC[R] != 0) 13460b57cec5SDimitry Andric continue; 13470b57cec5SDimitry Andric Has0 = true; 13480b57cec5SDimitry Andric break; 13490b57cec5SDimitry Andric } 13500b57cec5SDimitry Andric Accept = Has0; 13510b57cec5SDimitry Andric } 13520b57cec5SDimitry Andric if (Accept) 13530b57cec5SDimitry Andric LL.push_back(M); 13540b57cec5SDimitry Andric } 13550b57cec5SDimitry Andric 13560b57cec5SDimitry Andric // Remove candidates that add uses of removable registers, unless the 13570b57cec5SDimitry Andric // removable registers are among replacement candidates. 13580b57cec5SDimitry Andric // Recompute the removable registers, since some candidates may have 13590b57cec5SDimitry Andric // been eliminated. 13600b57cec5SDimitry Andric AllRMs.clear(); 13610b57cec5SDimitry Andric for (IFMapType::iterator I = IFMap.begin(); I != End; ++I) { 13620b57cec5SDimitry Andric const IFListType &LL = I->second; 13630b57cec5SDimitry Andric if (!LL.empty()) 13640b57cec5SDimitry Andric AllRMs.insert(LL[0].second); 13650b57cec5SDimitry Andric } 13660b57cec5SDimitry Andric for (IFMapType::iterator I = IFMap.begin(); I != End; ++I) { 13670b57cec5SDimitry Andric IFListType &LL = I->second; 13680b57cec5SDimitry Andric if (LL.empty()) 13690b57cec5SDimitry Andric continue; 13700b57cec5SDimitry Andric unsigned SR = LL[0].first.SrcR, IR = LL[0].first.InsR; 13710b57cec5SDimitry Andric if (AllRMs[SR] || AllRMs[IR]) 13720b57cec5SDimitry Andric LL.clear(); 13730b57cec5SDimitry Andric } 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andric pruneEmptyLists(); 13760b57cec5SDimitry Andric } 13770b57cec5SDimitry Andric 13780b57cec5SDimitry Andric bool HexagonGenInsert::generateInserts() { 13790b57cec5SDimitry Andric // Create a new register for each one from IFMap, and store them in the 13800b57cec5SDimitry Andric // map. 13810b57cec5SDimitry Andric UnsignedMap RegMap; 138204eeddc0SDimitry Andric for (auto &I : IFMap) { 138304eeddc0SDimitry Andric unsigned VR = I.first; 13840b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(VR); 13858bcb0991SDimitry Andric Register NewVR = MRI->createVirtualRegister(RC); 13860b57cec5SDimitry Andric RegMap[VR] = NewVR; 13870b57cec5SDimitry Andric } 13880b57cec5SDimitry Andric 13890b57cec5SDimitry Andric // We can generate the "insert" instructions using potentially stale re- 13900b57cec5SDimitry Andric // gisters: SrcR and InsR for a given VR may be among other registers that 13910b57cec5SDimitry Andric // are also replaced. This is fine, we will do the mass "rauw" a bit later. 139204eeddc0SDimitry Andric for (auto &I : IFMap) { 139304eeddc0SDimitry Andric MachineInstr *MI = MRI->getVRegDef(I.first); 13940b57cec5SDimitry Andric MachineBasicBlock &B = *MI->getParent(); 13950b57cec5SDimitry Andric DebugLoc DL = MI->getDebugLoc(); 139604eeddc0SDimitry Andric unsigned NewR = RegMap[I.first]; 13970b57cec5SDimitry Andric bool R32 = MRI->getRegClass(NewR) == &Hexagon::IntRegsRegClass; 13980b57cec5SDimitry Andric const MCInstrDesc &D = R32 ? HII->get(Hexagon::S2_insert) 13990b57cec5SDimitry Andric : HII->get(Hexagon::S2_insertp); 140004eeddc0SDimitry Andric IFRecord IF = I.second[0].first; 14010b57cec5SDimitry Andric unsigned Wdh = IF.Wdh, Off = IF.Off; 14020b57cec5SDimitry Andric unsigned InsS = 0; 14030b57cec5SDimitry Andric if (R32 && MRI->getRegClass(IF.InsR) == &Hexagon::DoubleRegsRegClass) { 14040b57cec5SDimitry Andric InsS = Hexagon::isub_lo; 14050b57cec5SDimitry Andric if (Off >= 32) { 14060b57cec5SDimitry Andric InsS = Hexagon::isub_hi; 14070b57cec5SDimitry Andric Off -= 32; 14080b57cec5SDimitry Andric } 14090b57cec5SDimitry Andric } 14100b57cec5SDimitry Andric // Advance to the proper location for inserting instructions. This could 14110b57cec5SDimitry Andric // be B.end(). 14120b57cec5SDimitry Andric MachineBasicBlock::iterator At = MI; 14130b57cec5SDimitry Andric if (MI->isPHI()) 14140b57cec5SDimitry Andric At = B.getFirstNonPHI(); 14150b57cec5SDimitry Andric 14160b57cec5SDimitry Andric BuildMI(B, At, DL, D, NewR) 14170b57cec5SDimitry Andric .addReg(IF.SrcR) 14180b57cec5SDimitry Andric .addReg(IF.InsR, 0, InsS) 14190b57cec5SDimitry Andric .addImm(Wdh) 14200b57cec5SDimitry Andric .addImm(Off); 14210b57cec5SDimitry Andric 14220b57cec5SDimitry Andric MRI->clearKillFlags(IF.SrcR); 14230b57cec5SDimitry Andric MRI->clearKillFlags(IF.InsR); 14240b57cec5SDimitry Andric } 14250b57cec5SDimitry Andric 142604eeddc0SDimitry Andric for (const auto &I : IFMap) { 142704eeddc0SDimitry Andric MachineInstr *DefI = MRI->getVRegDef(I.first); 142804eeddc0SDimitry Andric MRI->replaceRegWith(I.first, RegMap[I.first]); 14290b57cec5SDimitry Andric DefI->eraseFromParent(); 14300b57cec5SDimitry Andric } 14310b57cec5SDimitry Andric 14320b57cec5SDimitry Andric return true; 14330b57cec5SDimitry Andric } 14340b57cec5SDimitry Andric 14350b57cec5SDimitry Andric bool HexagonGenInsert::removeDeadCode(MachineDomTreeNode *N) { 14360b57cec5SDimitry Andric bool Changed = false; 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric for (auto *DTN : children<MachineDomTreeNode*>(N)) 14390b57cec5SDimitry Andric Changed |= removeDeadCode(DTN); 14400b57cec5SDimitry Andric 14410b57cec5SDimitry Andric MachineBasicBlock *B = N->getBlock(); 14420b57cec5SDimitry Andric std::vector<MachineInstr*> Instrs; 14430eae32dcSDimitry Andric for (MachineInstr &MI : llvm::reverse(*B)) 14440eae32dcSDimitry Andric Instrs.push_back(&MI); 14450b57cec5SDimitry Andric 14464824e7fdSDimitry Andric for (MachineInstr *MI : Instrs) { 14470b57cec5SDimitry Andric unsigned Opc = MI->getOpcode(); 14480b57cec5SDimitry Andric // Do not touch lifetime markers. This is why the target-independent DCE 14490b57cec5SDimitry Andric // cannot be used. 14500b57cec5SDimitry Andric if (Opc == TargetOpcode::LIFETIME_START || 14510b57cec5SDimitry Andric Opc == TargetOpcode::LIFETIME_END) 14520b57cec5SDimitry Andric continue; 14530b57cec5SDimitry Andric bool Store = false; 14540b57cec5SDimitry Andric if (MI->isInlineAsm() || !MI->isSafeToMove(nullptr, Store)) 14550b57cec5SDimitry Andric continue; 14560b57cec5SDimitry Andric 14570b57cec5SDimitry Andric bool AllDead = true; 14580b57cec5SDimitry Andric SmallVector<unsigned,2> Regs; 14590b57cec5SDimitry Andric for (const MachineOperand &MO : MI->operands()) { 14600b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef()) 14610b57cec5SDimitry Andric continue; 14628bcb0991SDimitry Andric Register R = MO.getReg(); 1463e8d8bef9SDimitry Andric if (!R.isVirtual() || !MRI->use_nodbg_empty(R)) { 14640b57cec5SDimitry Andric AllDead = false; 14650b57cec5SDimitry Andric break; 14660b57cec5SDimitry Andric } 14670b57cec5SDimitry Andric Regs.push_back(R); 14680b57cec5SDimitry Andric } 14690b57cec5SDimitry Andric if (!AllDead) 14700b57cec5SDimitry Andric continue; 14710b57cec5SDimitry Andric 14720b57cec5SDimitry Andric B->erase(MI); 1473*0fca6ea1SDimitry Andric for (unsigned Reg : Regs) 1474*0fca6ea1SDimitry Andric MRI->markUsesInDebugValueAsUndef(Reg); 14750b57cec5SDimitry Andric Changed = true; 14760b57cec5SDimitry Andric } 14770b57cec5SDimitry Andric 14780b57cec5SDimitry Andric return Changed; 14790b57cec5SDimitry Andric } 14800b57cec5SDimitry Andric 14810b57cec5SDimitry Andric bool HexagonGenInsert::runOnMachineFunction(MachineFunction &MF) { 14820b57cec5SDimitry Andric if (skipFunction(MF.getFunction())) 14830b57cec5SDimitry Andric return false; 14840b57cec5SDimitry Andric 14850b57cec5SDimitry Andric bool Timing = OptTiming, TimingDetail = Timing && OptTimingDetail; 14860b57cec5SDimitry Andric bool Changed = false; 14870b57cec5SDimitry Andric 14884824e7fdSDimitry Andric // Verify: one, but not both. 14890b57cec5SDimitry Andric assert(!OptSelectAll0 || !OptSelectHas0); 14900b57cec5SDimitry Andric 14910b57cec5SDimitry Andric IFMap.clear(); 14920b57cec5SDimitry Andric BaseOrd.clear(); 14930b57cec5SDimitry Andric CellOrd.clear(); 14940b57cec5SDimitry Andric 14950b57cec5SDimitry Andric const auto &ST = MF.getSubtarget<HexagonSubtarget>(); 14960b57cec5SDimitry Andric HII = ST.getInstrInfo(); 14970b57cec5SDimitry Andric HRI = ST.getRegisterInfo(); 14980b57cec5SDimitry Andric MFN = &MF; 14990b57cec5SDimitry Andric MRI = &MF.getRegInfo(); 1500*0fca6ea1SDimitry Andric MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(); 15010b57cec5SDimitry Andric 15020b57cec5SDimitry Andric // Clean up before any further processing, so that dead code does not 15030b57cec5SDimitry Andric // get used in a newly generated "insert" instruction. Have a custom 15040b57cec5SDimitry Andric // version of DCE that preserves lifetime markers. Without it, merging 15050b57cec5SDimitry Andric // of stack objects can fail to recognize and merge disjoint objects 15060b57cec5SDimitry Andric // leading to unnecessary stack growth. 15070b57cec5SDimitry Andric Changed = removeDeadCode(MDT->getRootNode()); 15080b57cec5SDimitry Andric 15090b57cec5SDimitry Andric const HexagonEvaluator HE(*HRI, *MRI, *HII, MF); 15100b57cec5SDimitry Andric BitTracker BTLoc(HE, MF); 15110b57cec5SDimitry Andric BTLoc.trace(isDebug()); 15120b57cec5SDimitry Andric BTLoc.run(); 15130b57cec5SDimitry Andric CellMapShadow MS(BTLoc); 15140b57cec5SDimitry Andric CMS = &MS; 15150b57cec5SDimitry Andric 15160b57cec5SDimitry Andric buildOrderingMF(BaseOrd); 15170b57cec5SDimitry Andric buildOrderingBT(BaseOrd, CellOrd); 15180b57cec5SDimitry Andric 15190b57cec5SDimitry Andric if (isDebug()) { 15200b57cec5SDimitry Andric dbgs() << "Cell ordering:\n"; 152104eeddc0SDimitry Andric for (const auto &I : CellOrd) { 152204eeddc0SDimitry Andric unsigned VR = I.first, Pos = I.second; 15230b57cec5SDimitry Andric dbgs() << printReg(VR, HRI) << " -> " << Pos << "\n"; 15240b57cec5SDimitry Andric } 15250b57cec5SDimitry Andric } 15260b57cec5SDimitry Andric 15270b57cec5SDimitry Andric // Collect candidates for conversion into the insert forms. 15280b57cec5SDimitry Andric MachineBasicBlock *RootB = MDT->getRoot(); 15290b57cec5SDimitry Andric OrderedRegisterList AvailR(CellOrd); 15300b57cec5SDimitry Andric 15310b57cec5SDimitry Andric const char *const TGName = "hexinsert"; 15320b57cec5SDimitry Andric const char *const TGDesc = "Generate Insert Instructions"; 15330b57cec5SDimitry Andric 15340b57cec5SDimitry Andric { 15350b57cec5SDimitry Andric NamedRegionTimer _T("collection", "collection", TGName, TGDesc, 15360b57cec5SDimitry Andric TimingDetail); 15370b57cec5SDimitry Andric collectInBlock(RootB, AvailR); 15380b57cec5SDimitry Andric // Complete the information gathered in IFMap. 15390b57cec5SDimitry Andric computeRemovableRegisters(); 15400b57cec5SDimitry Andric } 15410b57cec5SDimitry Andric 15420b57cec5SDimitry Andric if (isDebug()) { 15430b57cec5SDimitry Andric dbgs() << "Candidates after collection:\n"; 15440b57cec5SDimitry Andric dump_map(); 15450b57cec5SDimitry Andric } 15460b57cec5SDimitry Andric 15470b57cec5SDimitry Andric if (IFMap.empty()) 15480b57cec5SDimitry Andric return Changed; 15490b57cec5SDimitry Andric 15500b57cec5SDimitry Andric { 15510b57cec5SDimitry Andric NamedRegionTimer _T("pruning", "pruning", TGName, TGDesc, TimingDetail); 15520b57cec5SDimitry Andric pruneCandidates(); 15530b57cec5SDimitry Andric } 15540b57cec5SDimitry Andric 15550b57cec5SDimitry Andric if (isDebug()) { 15560b57cec5SDimitry Andric dbgs() << "Candidates after pruning:\n"; 15570b57cec5SDimitry Andric dump_map(); 15580b57cec5SDimitry Andric } 15590b57cec5SDimitry Andric 15600b57cec5SDimitry Andric if (IFMap.empty()) 15610b57cec5SDimitry Andric return Changed; 15620b57cec5SDimitry Andric 15630b57cec5SDimitry Andric { 15640b57cec5SDimitry Andric NamedRegionTimer _T("selection", "selection", TGName, TGDesc, TimingDetail); 15650b57cec5SDimitry Andric selectCandidates(); 15660b57cec5SDimitry Andric } 15670b57cec5SDimitry Andric 15680b57cec5SDimitry Andric if (isDebug()) { 15690b57cec5SDimitry Andric dbgs() << "Candidates after selection:\n"; 15700b57cec5SDimitry Andric dump_map(); 15710b57cec5SDimitry Andric } 15720b57cec5SDimitry Andric 15730b57cec5SDimitry Andric // Filter out vregs beyond the cutoff. 15740b57cec5SDimitry Andric if (VRegIndexCutoff.getPosition()) { 15750b57cec5SDimitry Andric unsigned Cutoff = VRegIndexCutoff; 15760b57cec5SDimitry Andric 15770b57cec5SDimitry Andric using IterListType = SmallVector<IFMapType::iterator, 16>; 15780b57cec5SDimitry Andric 15790b57cec5SDimitry Andric IterListType Out; 15800b57cec5SDimitry Andric for (IFMapType::iterator I = IFMap.begin(), E = IFMap.end(); I != E; ++I) { 15818bcb0991SDimitry Andric unsigned Idx = Register::virtReg2Index(I->first); 15820b57cec5SDimitry Andric if (Idx >= Cutoff) 15830b57cec5SDimitry Andric Out.push_back(I); 15840b57cec5SDimitry Andric } 1585*0fca6ea1SDimitry Andric for (const auto &It : Out) 1586*0fca6ea1SDimitry Andric IFMap.erase(It); 15870b57cec5SDimitry Andric } 15880b57cec5SDimitry Andric if (IFMap.empty()) 15890b57cec5SDimitry Andric return Changed; 15900b57cec5SDimitry Andric 15910b57cec5SDimitry Andric { 15920b57cec5SDimitry Andric NamedRegionTimer _T("generation", "generation", TGName, TGDesc, 15930b57cec5SDimitry Andric TimingDetail); 15940b57cec5SDimitry Andric generateInserts(); 15950b57cec5SDimitry Andric } 15960b57cec5SDimitry Andric 15970b57cec5SDimitry Andric return true; 15980b57cec5SDimitry Andric } 15990b57cec5SDimitry Andric 16000b57cec5SDimitry Andric FunctionPass *llvm::createHexagonGenInsert() { 16010b57cec5SDimitry Andric return new HexagonGenInsert(); 16020b57cec5SDimitry Andric } 16030b57cec5SDimitry Andric 16040b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 16050b57cec5SDimitry Andric // Public Constructor Functions 16060b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 16070b57cec5SDimitry Andric 16080b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(HexagonGenInsert, "hexinsert", 16090b57cec5SDimitry Andric "Hexagon generate \"insert\" instructions", false, false) 1610*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) 16110b57cec5SDimitry Andric INITIALIZE_PASS_END(HexagonGenInsert, "hexinsert", 16120b57cec5SDimitry Andric "Hexagon generate \"insert\" instructions", false, false) 1613