1*0fca6ea1SDimitry Andric //===--- InfoByHwMode.cpp -------------------------------------------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // Classes that implement data parameterized by HW modes for instruction 9*0fca6ea1SDimitry Andric // selection. Currently it is ValueTypeByHwMode (parameterized ValueType), 10*0fca6ea1SDimitry Andric // and RegSizeInfoByHwMode (parameterized register/spill size and alignment 11*0fca6ea1SDimitry Andric // data). 12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 13*0fca6ea1SDimitry Andric 14*0fca6ea1SDimitry Andric #include "InfoByHwMode.h" 15*0fca6ea1SDimitry Andric #include "CodeGenTarget.h" 16*0fca6ea1SDimitry Andric #include "llvm/ADT/STLExtras.h" 17*0fca6ea1SDimitry Andric #include "llvm/ADT/Twine.h" 18*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h" 19*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h" 20*0fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h" 21*0fca6ea1SDimitry Andric #include <string> 22*0fca6ea1SDimitry Andric 23*0fca6ea1SDimitry Andric using namespace llvm; 24*0fca6ea1SDimitry Andric 25*0fca6ea1SDimitry Andric std::string llvm::getModeName(unsigned Mode) { 26*0fca6ea1SDimitry Andric if (Mode == DefaultMode) 27*0fca6ea1SDimitry Andric return "*"; 28*0fca6ea1SDimitry Andric return (Twine('m') + Twine(Mode)).str(); 29*0fca6ea1SDimitry Andric } 30*0fca6ea1SDimitry Andric 31*0fca6ea1SDimitry Andric ValueTypeByHwMode::ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH) { 32*0fca6ea1SDimitry Andric const HwModeSelect &MS = CGH.getHwModeSelect(R); 33*0fca6ea1SDimitry Andric for (const HwModeSelect::PairType &P : MS.Items) { 34*0fca6ea1SDimitry Andric auto I = Map.insert({P.first, MVT(llvm::getValueType(P.second))}); 35*0fca6ea1SDimitry Andric assert(I.second && "Duplicate entry?"); 36*0fca6ea1SDimitry Andric (void)I; 37*0fca6ea1SDimitry Andric } 38*0fca6ea1SDimitry Andric if (R->isSubClassOf("PtrValueType")) 39*0fca6ea1SDimitry Andric PtrAddrSpace = R->getValueAsInt("AddrSpace"); 40*0fca6ea1SDimitry Andric } 41*0fca6ea1SDimitry Andric 42*0fca6ea1SDimitry Andric ValueTypeByHwMode::ValueTypeByHwMode(Record *R, MVT T) : ValueTypeByHwMode(T) { 43*0fca6ea1SDimitry Andric if (R->isSubClassOf("PtrValueType")) 44*0fca6ea1SDimitry Andric PtrAddrSpace = R->getValueAsInt("AddrSpace"); 45*0fca6ea1SDimitry Andric } 46*0fca6ea1SDimitry Andric 47*0fca6ea1SDimitry Andric bool ValueTypeByHwMode::operator==(const ValueTypeByHwMode &T) const { 48*0fca6ea1SDimitry Andric assert(isValid() && T.isValid() && "Invalid type in assignment"); 49*0fca6ea1SDimitry Andric bool Simple = isSimple(); 50*0fca6ea1SDimitry Andric if (Simple != T.isSimple()) 51*0fca6ea1SDimitry Andric return false; 52*0fca6ea1SDimitry Andric if (Simple) 53*0fca6ea1SDimitry Andric return getSimple() == T.getSimple(); 54*0fca6ea1SDimitry Andric 55*0fca6ea1SDimitry Andric return Map == T.Map; 56*0fca6ea1SDimitry Andric } 57*0fca6ea1SDimitry Andric 58*0fca6ea1SDimitry Andric bool ValueTypeByHwMode::operator<(const ValueTypeByHwMode &T) const { 59*0fca6ea1SDimitry Andric assert(isValid() && T.isValid() && "Invalid type in comparison"); 60*0fca6ea1SDimitry Andric // Default order for maps. 61*0fca6ea1SDimitry Andric return Map < T.Map; 62*0fca6ea1SDimitry Andric } 63*0fca6ea1SDimitry Andric 64*0fca6ea1SDimitry Andric MVT &ValueTypeByHwMode::getOrCreateTypeForMode(unsigned Mode, MVT Type) { 65*0fca6ea1SDimitry Andric auto F = Map.find(Mode); 66*0fca6ea1SDimitry Andric if (F != Map.end()) 67*0fca6ea1SDimitry Andric return F->second; 68*0fca6ea1SDimitry Andric // If Mode is not in the map, look up the default mode. If it exists, 69*0fca6ea1SDimitry Andric // make a copy of it for Mode and return it. 70*0fca6ea1SDimitry Andric auto D = Map.begin(); 71*0fca6ea1SDimitry Andric if (D != Map.end() && D->first == DefaultMode) 72*0fca6ea1SDimitry Andric return Map.insert(std::pair(Mode, D->second)).first->second; 73*0fca6ea1SDimitry Andric // If default mode is not present either, use provided Type. 74*0fca6ea1SDimitry Andric return Map.insert(std::pair(Mode, Type)).first->second; 75*0fca6ea1SDimitry Andric } 76*0fca6ea1SDimitry Andric 77*0fca6ea1SDimitry Andric StringRef ValueTypeByHwMode::getMVTName(MVT T) { 78*0fca6ea1SDimitry Andric StringRef N = llvm::getEnumName(T.SimpleTy); 79*0fca6ea1SDimitry Andric N.consume_front("MVT::"); 80*0fca6ea1SDimitry Andric return N; 81*0fca6ea1SDimitry Andric } 82*0fca6ea1SDimitry Andric 83*0fca6ea1SDimitry Andric void ValueTypeByHwMode::writeToStream(raw_ostream &OS) const { 84*0fca6ea1SDimitry Andric if (isSimple()) { 85*0fca6ea1SDimitry Andric OS << getMVTName(getSimple()); 86*0fca6ea1SDimitry Andric return; 87*0fca6ea1SDimitry Andric } 88*0fca6ea1SDimitry Andric 89*0fca6ea1SDimitry Andric std::vector<const PairType *> Pairs; 90*0fca6ea1SDimitry Andric for (const auto &P : Map) 91*0fca6ea1SDimitry Andric Pairs.push_back(&P); 92*0fca6ea1SDimitry Andric llvm::sort(Pairs, deref<std::less<PairType>>()); 93*0fca6ea1SDimitry Andric 94*0fca6ea1SDimitry Andric OS << '{'; 95*0fca6ea1SDimitry Andric ListSeparator LS(","); 96*0fca6ea1SDimitry Andric for (const PairType *P : Pairs) 97*0fca6ea1SDimitry Andric OS << LS << '(' << getModeName(P->first) << ':' 98*0fca6ea1SDimitry Andric << getMVTName(P->second).str() << ')'; 99*0fca6ea1SDimitry Andric OS << '}'; 100*0fca6ea1SDimitry Andric } 101*0fca6ea1SDimitry Andric 102*0fca6ea1SDimitry Andric LLVM_DUMP_METHOD 103*0fca6ea1SDimitry Andric void ValueTypeByHwMode::dump() const { dbgs() << *this << '\n'; } 104*0fca6ea1SDimitry Andric 105*0fca6ea1SDimitry Andric ValueTypeByHwMode llvm::getValueTypeByHwMode(Record *Rec, 106*0fca6ea1SDimitry Andric const CodeGenHwModes &CGH) { 107*0fca6ea1SDimitry Andric #ifndef NDEBUG 108*0fca6ea1SDimitry Andric if (!Rec->isSubClassOf("ValueType")) 109*0fca6ea1SDimitry Andric Rec->dump(); 110*0fca6ea1SDimitry Andric #endif 111*0fca6ea1SDimitry Andric assert(Rec->isSubClassOf("ValueType") && 112*0fca6ea1SDimitry Andric "Record must be derived from ValueType"); 113*0fca6ea1SDimitry Andric if (Rec->isSubClassOf("HwModeSelect")) 114*0fca6ea1SDimitry Andric return ValueTypeByHwMode(Rec, CGH); 115*0fca6ea1SDimitry Andric return ValueTypeByHwMode(Rec, llvm::getValueType(Rec)); 116*0fca6ea1SDimitry Andric } 117*0fca6ea1SDimitry Andric 118*0fca6ea1SDimitry Andric RegSizeInfo::RegSizeInfo(Record *R) { 119*0fca6ea1SDimitry Andric RegSize = R->getValueAsInt("RegSize"); 120*0fca6ea1SDimitry Andric SpillSize = R->getValueAsInt("SpillSize"); 121*0fca6ea1SDimitry Andric SpillAlignment = R->getValueAsInt("SpillAlignment"); 122*0fca6ea1SDimitry Andric } 123*0fca6ea1SDimitry Andric 124*0fca6ea1SDimitry Andric bool RegSizeInfo::operator<(const RegSizeInfo &I) const { 125*0fca6ea1SDimitry Andric return std::tie(RegSize, SpillSize, SpillAlignment) < 126*0fca6ea1SDimitry Andric std::tie(I.RegSize, I.SpillSize, I.SpillAlignment); 127*0fca6ea1SDimitry Andric } 128*0fca6ea1SDimitry Andric 129*0fca6ea1SDimitry Andric bool RegSizeInfo::isSubClassOf(const RegSizeInfo &I) const { 130*0fca6ea1SDimitry Andric return RegSize <= I.RegSize && SpillAlignment && 131*0fca6ea1SDimitry Andric I.SpillAlignment % SpillAlignment == 0 && SpillSize <= I.SpillSize; 132*0fca6ea1SDimitry Andric } 133*0fca6ea1SDimitry Andric 134*0fca6ea1SDimitry Andric void RegSizeInfo::writeToStream(raw_ostream &OS) const { 135*0fca6ea1SDimitry Andric OS << "[R=" << RegSize << ",S=" << SpillSize << ",A=" << SpillAlignment 136*0fca6ea1SDimitry Andric << ']'; 137*0fca6ea1SDimitry Andric } 138*0fca6ea1SDimitry Andric 139*0fca6ea1SDimitry Andric RegSizeInfoByHwMode::RegSizeInfoByHwMode(Record *R, const CodeGenHwModes &CGH) { 140*0fca6ea1SDimitry Andric const HwModeSelect &MS = CGH.getHwModeSelect(R); 141*0fca6ea1SDimitry Andric for (const HwModeSelect::PairType &P : MS.Items) { 142*0fca6ea1SDimitry Andric auto I = Map.insert({P.first, RegSizeInfo(P.second)}); 143*0fca6ea1SDimitry Andric assert(I.second && "Duplicate entry?"); 144*0fca6ea1SDimitry Andric (void)I; 145*0fca6ea1SDimitry Andric } 146*0fca6ea1SDimitry Andric } 147*0fca6ea1SDimitry Andric 148*0fca6ea1SDimitry Andric bool RegSizeInfoByHwMode::operator<(const RegSizeInfoByHwMode &I) const { 149*0fca6ea1SDimitry Andric unsigned M0 = Map.begin()->first; 150*0fca6ea1SDimitry Andric return get(M0) < I.get(M0); 151*0fca6ea1SDimitry Andric } 152*0fca6ea1SDimitry Andric 153*0fca6ea1SDimitry Andric bool RegSizeInfoByHwMode::operator==(const RegSizeInfoByHwMode &I) const { 154*0fca6ea1SDimitry Andric unsigned M0 = Map.begin()->first; 155*0fca6ea1SDimitry Andric return get(M0) == I.get(M0); 156*0fca6ea1SDimitry Andric } 157*0fca6ea1SDimitry Andric 158*0fca6ea1SDimitry Andric bool RegSizeInfoByHwMode::isSubClassOf(const RegSizeInfoByHwMode &I) const { 159*0fca6ea1SDimitry Andric unsigned M0 = Map.begin()->first; 160*0fca6ea1SDimitry Andric return get(M0).isSubClassOf(I.get(M0)); 161*0fca6ea1SDimitry Andric } 162*0fca6ea1SDimitry Andric 163*0fca6ea1SDimitry Andric bool RegSizeInfoByHwMode::hasStricterSpillThan( 164*0fca6ea1SDimitry Andric const RegSizeInfoByHwMode &I) const { 165*0fca6ea1SDimitry Andric unsigned M0 = Map.begin()->first; 166*0fca6ea1SDimitry Andric const RegSizeInfo &A0 = get(M0); 167*0fca6ea1SDimitry Andric const RegSizeInfo &B0 = I.get(M0); 168*0fca6ea1SDimitry Andric return std::tie(A0.SpillSize, A0.SpillAlignment) > 169*0fca6ea1SDimitry Andric std::tie(B0.SpillSize, B0.SpillAlignment); 170*0fca6ea1SDimitry Andric } 171*0fca6ea1SDimitry Andric 172*0fca6ea1SDimitry Andric void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const { 173*0fca6ea1SDimitry Andric typedef typename decltype(Map)::value_type PairType; 174*0fca6ea1SDimitry Andric std::vector<const PairType *> Pairs; 175*0fca6ea1SDimitry Andric for (const auto &P : Map) 176*0fca6ea1SDimitry Andric Pairs.push_back(&P); 177*0fca6ea1SDimitry Andric llvm::sort(Pairs, deref<std::less<PairType>>()); 178*0fca6ea1SDimitry Andric 179*0fca6ea1SDimitry Andric OS << '{'; 180*0fca6ea1SDimitry Andric ListSeparator LS(","); 181*0fca6ea1SDimitry Andric for (const PairType *P : Pairs) 182*0fca6ea1SDimitry Andric OS << LS << '(' << getModeName(P->first) << ':' << P->second << ')'; 183*0fca6ea1SDimitry Andric OS << '}'; 184*0fca6ea1SDimitry Andric } 185*0fca6ea1SDimitry Andric 186*0fca6ea1SDimitry Andric SubRegRange::SubRegRange(Record *R) { 187*0fca6ea1SDimitry Andric Size = R->getValueAsInt("Size"); 188*0fca6ea1SDimitry Andric Offset = R->getValueAsInt("Offset"); 189*0fca6ea1SDimitry Andric } 190*0fca6ea1SDimitry Andric 191*0fca6ea1SDimitry Andric SubRegRangeByHwMode::SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH) { 192*0fca6ea1SDimitry Andric const HwModeSelect &MS = CGH.getHwModeSelect(R); 193*0fca6ea1SDimitry Andric for (const HwModeSelect::PairType &P : MS.Items) { 194*0fca6ea1SDimitry Andric auto I = Map.insert({P.first, SubRegRange(P.second)}); 195*0fca6ea1SDimitry Andric assert(I.second && "Duplicate entry?"); 196*0fca6ea1SDimitry Andric (void)I; 197*0fca6ea1SDimitry Andric } 198*0fca6ea1SDimitry Andric } 199*0fca6ea1SDimitry Andric 200*0fca6ea1SDimitry Andric EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R, 201*0fca6ea1SDimitry Andric const CodeGenHwModes &CGH) { 202*0fca6ea1SDimitry Andric const HwModeSelect &MS = CGH.getHwModeSelect(R); 203*0fca6ea1SDimitry Andric for (const HwModeSelect::PairType &P : MS.Items) { 204*0fca6ea1SDimitry Andric assert(P.second && P.second->isSubClassOf("InstructionEncoding") && 205*0fca6ea1SDimitry Andric "Encoding must subclass InstructionEncoding"); 206*0fca6ea1SDimitry Andric auto I = Map.insert({P.first, P.second}); 207*0fca6ea1SDimitry Andric assert(I.second && "Duplicate entry?"); 208*0fca6ea1SDimitry Andric (void)I; 209*0fca6ea1SDimitry Andric } 210*0fca6ea1SDimitry Andric } 211*0fca6ea1SDimitry Andric 212*0fca6ea1SDimitry Andric namespace llvm { 213*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T) { 214*0fca6ea1SDimitry Andric T.writeToStream(OS); 215*0fca6ea1SDimitry Andric return OS; 216*0fca6ea1SDimitry Andric } 217*0fca6ea1SDimitry Andric 218*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T) { 219*0fca6ea1SDimitry Andric T.writeToStream(OS); 220*0fca6ea1SDimitry Andric return OS; 221*0fca6ea1SDimitry Andric } 222*0fca6ea1SDimitry Andric 223*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T) { 224*0fca6ea1SDimitry Andric T.writeToStream(OS); 225*0fca6ea1SDimitry Andric return OS; 226*0fca6ea1SDimitry Andric } 227*0fca6ea1SDimitry Andric } // namespace llvm 228