1*0fca6ea1SDimitry Andric //===- CodeGenDAGPatterns.cpp - Read DAG patterns from .td file -----------===// 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 // 9*0fca6ea1SDimitry Andric // This file implements the CodeGenDAGPatterns class, which is used to read and 10*0fca6ea1SDimitry Andric // represent the patterns present in a .td file for instructions. 11*0fca6ea1SDimitry Andric // 12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 13*0fca6ea1SDimitry Andric 14*0fca6ea1SDimitry Andric #include "CodeGenDAGPatterns.h" 15*0fca6ea1SDimitry Andric #include "CodeGenInstruction.h" 16*0fca6ea1SDimitry Andric #include "CodeGenRegisters.h" 17*0fca6ea1SDimitry Andric #include "llvm/ADT/DenseSet.h" 18*0fca6ea1SDimitry Andric #include "llvm/ADT/MapVector.h" 19*0fca6ea1SDimitry Andric #include "llvm/ADT/STLExtras.h" 20*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallSet.h" 21*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallString.h" 22*0fca6ea1SDimitry Andric #include "llvm/ADT/StringExtras.h" 23*0fca6ea1SDimitry Andric #include "llvm/ADT/StringMap.h" 24*0fca6ea1SDimitry Andric #include "llvm/ADT/Twine.h" 25*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h" 26*0fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h" 27*0fca6ea1SDimitry Andric #include "llvm/Support/TypeSize.h" 28*0fca6ea1SDimitry Andric #include "llvm/TableGen/Error.h" 29*0fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h" 30*0fca6ea1SDimitry Andric #include <algorithm> 31*0fca6ea1SDimitry Andric #include <cstdio> 32*0fca6ea1SDimitry Andric #include <iterator> 33*0fca6ea1SDimitry Andric #include <set> 34*0fca6ea1SDimitry Andric using namespace llvm; 35*0fca6ea1SDimitry Andric 36*0fca6ea1SDimitry Andric #define DEBUG_TYPE "dag-patterns" 37*0fca6ea1SDimitry Andric 38*0fca6ea1SDimitry Andric static inline bool isIntegerOrPtr(MVT VT) { 39*0fca6ea1SDimitry Andric return VT.isInteger() || VT == MVT::iPTR; 40*0fca6ea1SDimitry Andric } 41*0fca6ea1SDimitry Andric static inline bool isFloatingPoint(MVT VT) { return VT.isFloatingPoint(); } 42*0fca6ea1SDimitry Andric static inline bool isVector(MVT VT) { return VT.isVector(); } 43*0fca6ea1SDimitry Andric static inline bool isScalar(MVT VT) { return !VT.isVector(); } 44*0fca6ea1SDimitry Andric 45*0fca6ea1SDimitry Andric template <typename Predicate> 46*0fca6ea1SDimitry Andric static bool berase_if(MachineValueTypeSet &S, Predicate P) { 47*0fca6ea1SDimitry Andric bool Erased = false; 48*0fca6ea1SDimitry Andric // It is ok to iterate over MachineValueTypeSet and remove elements from it 49*0fca6ea1SDimitry Andric // at the same time. 50*0fca6ea1SDimitry Andric for (MVT T : S) { 51*0fca6ea1SDimitry Andric if (!P(T)) 52*0fca6ea1SDimitry Andric continue; 53*0fca6ea1SDimitry Andric Erased = true; 54*0fca6ea1SDimitry Andric S.erase(T); 55*0fca6ea1SDimitry Andric } 56*0fca6ea1SDimitry Andric return Erased; 57*0fca6ea1SDimitry Andric } 58*0fca6ea1SDimitry Andric 59*0fca6ea1SDimitry Andric void MachineValueTypeSet::writeToStream(raw_ostream &OS) const { 60*0fca6ea1SDimitry Andric SmallVector<MVT, 4> Types(begin(), end()); 61*0fca6ea1SDimitry Andric array_pod_sort(Types.begin(), Types.end()); 62*0fca6ea1SDimitry Andric 63*0fca6ea1SDimitry Andric OS << '['; 64*0fca6ea1SDimitry Andric ListSeparator LS(" "); 65*0fca6ea1SDimitry Andric for (const MVT &T : Types) 66*0fca6ea1SDimitry Andric OS << LS << ValueTypeByHwMode::getMVTName(T); 67*0fca6ea1SDimitry Andric OS << ']'; 68*0fca6ea1SDimitry Andric } 69*0fca6ea1SDimitry Andric 70*0fca6ea1SDimitry Andric // --- TypeSetByHwMode 71*0fca6ea1SDimitry Andric 72*0fca6ea1SDimitry Andric // This is a parameterized type-set class. For each mode there is a list 73*0fca6ea1SDimitry Andric // of types that are currently possible for a given tree node. Type 74*0fca6ea1SDimitry Andric // inference will apply to each mode separately. 75*0fca6ea1SDimitry Andric 76*0fca6ea1SDimitry Andric TypeSetByHwMode::TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList) { 77*0fca6ea1SDimitry Andric // Take the address space from the first type in the list. 78*0fca6ea1SDimitry Andric if (!VTList.empty()) 79*0fca6ea1SDimitry Andric AddrSpace = VTList[0].PtrAddrSpace; 80*0fca6ea1SDimitry Andric 81*0fca6ea1SDimitry Andric for (const ValueTypeByHwMode &VVT : VTList) 82*0fca6ea1SDimitry Andric insert(VVT); 83*0fca6ea1SDimitry Andric } 84*0fca6ea1SDimitry Andric 85*0fca6ea1SDimitry Andric bool TypeSetByHwMode::isValueTypeByHwMode(bool AllowEmpty) const { 86*0fca6ea1SDimitry Andric for (const auto &I : *this) { 87*0fca6ea1SDimitry Andric if (I.second.size() > 1) 88*0fca6ea1SDimitry Andric return false; 89*0fca6ea1SDimitry Andric if (!AllowEmpty && I.second.empty()) 90*0fca6ea1SDimitry Andric return false; 91*0fca6ea1SDimitry Andric } 92*0fca6ea1SDimitry Andric return true; 93*0fca6ea1SDimitry Andric } 94*0fca6ea1SDimitry Andric 95*0fca6ea1SDimitry Andric ValueTypeByHwMode TypeSetByHwMode::getValueTypeByHwMode() const { 96*0fca6ea1SDimitry Andric assert(isValueTypeByHwMode(true) && 97*0fca6ea1SDimitry Andric "The type set has multiple types for at least one HW mode"); 98*0fca6ea1SDimitry Andric ValueTypeByHwMode VVT; 99*0fca6ea1SDimitry Andric VVT.PtrAddrSpace = AddrSpace; 100*0fca6ea1SDimitry Andric 101*0fca6ea1SDimitry Andric for (const auto &I : *this) { 102*0fca6ea1SDimitry Andric MVT T = I.second.empty() ? MVT::Other : *I.second.begin(); 103*0fca6ea1SDimitry Andric VVT.getOrCreateTypeForMode(I.first, T); 104*0fca6ea1SDimitry Andric } 105*0fca6ea1SDimitry Andric return VVT; 106*0fca6ea1SDimitry Andric } 107*0fca6ea1SDimitry Andric 108*0fca6ea1SDimitry Andric bool TypeSetByHwMode::isPossible() const { 109*0fca6ea1SDimitry Andric for (const auto &I : *this) 110*0fca6ea1SDimitry Andric if (!I.second.empty()) 111*0fca6ea1SDimitry Andric return true; 112*0fca6ea1SDimitry Andric return false; 113*0fca6ea1SDimitry Andric } 114*0fca6ea1SDimitry Andric 115*0fca6ea1SDimitry Andric bool TypeSetByHwMode::insert(const ValueTypeByHwMode &VVT) { 116*0fca6ea1SDimitry Andric bool Changed = false; 117*0fca6ea1SDimitry Andric bool ContainsDefault = false; 118*0fca6ea1SDimitry Andric MVT DT = MVT::Other; 119*0fca6ea1SDimitry Andric 120*0fca6ea1SDimitry Andric for (const auto &P : VVT) { 121*0fca6ea1SDimitry Andric unsigned M = P.first; 122*0fca6ea1SDimitry Andric // Make sure there exists a set for each specific mode from VVT. 123*0fca6ea1SDimitry Andric Changed |= getOrCreate(M).insert(P.second).second; 124*0fca6ea1SDimitry Andric // Cache VVT's default mode. 125*0fca6ea1SDimitry Andric if (DefaultMode == M) { 126*0fca6ea1SDimitry Andric ContainsDefault = true; 127*0fca6ea1SDimitry Andric DT = P.second; 128*0fca6ea1SDimitry Andric } 129*0fca6ea1SDimitry Andric } 130*0fca6ea1SDimitry Andric 131*0fca6ea1SDimitry Andric // If VVT has a default mode, add the corresponding type to all 132*0fca6ea1SDimitry Andric // modes in "this" that do not exist in VVT. 133*0fca6ea1SDimitry Andric if (ContainsDefault) 134*0fca6ea1SDimitry Andric for (auto &I : *this) 135*0fca6ea1SDimitry Andric if (!VVT.hasMode(I.first)) 136*0fca6ea1SDimitry Andric Changed |= I.second.insert(DT).second; 137*0fca6ea1SDimitry Andric 138*0fca6ea1SDimitry Andric return Changed; 139*0fca6ea1SDimitry Andric } 140*0fca6ea1SDimitry Andric 141*0fca6ea1SDimitry Andric // Constrain the type set to be the intersection with VTS. 142*0fca6ea1SDimitry Andric bool TypeSetByHwMode::constrain(const TypeSetByHwMode &VTS) { 143*0fca6ea1SDimitry Andric bool Changed = false; 144*0fca6ea1SDimitry Andric if (hasDefault()) { 145*0fca6ea1SDimitry Andric for (const auto &I : VTS) { 146*0fca6ea1SDimitry Andric unsigned M = I.first; 147*0fca6ea1SDimitry Andric if (M == DefaultMode || hasMode(M)) 148*0fca6ea1SDimitry Andric continue; 149*0fca6ea1SDimitry Andric Map.insert({M, Map.at(DefaultMode)}); 150*0fca6ea1SDimitry Andric Changed = true; 151*0fca6ea1SDimitry Andric } 152*0fca6ea1SDimitry Andric } 153*0fca6ea1SDimitry Andric 154*0fca6ea1SDimitry Andric for (auto &I : *this) { 155*0fca6ea1SDimitry Andric unsigned M = I.first; 156*0fca6ea1SDimitry Andric SetType &S = I.second; 157*0fca6ea1SDimitry Andric if (VTS.hasMode(M) || VTS.hasDefault()) { 158*0fca6ea1SDimitry Andric Changed |= intersect(I.second, VTS.get(M)); 159*0fca6ea1SDimitry Andric } else if (!S.empty()) { 160*0fca6ea1SDimitry Andric S.clear(); 161*0fca6ea1SDimitry Andric Changed = true; 162*0fca6ea1SDimitry Andric } 163*0fca6ea1SDimitry Andric } 164*0fca6ea1SDimitry Andric return Changed; 165*0fca6ea1SDimitry Andric } 166*0fca6ea1SDimitry Andric 167*0fca6ea1SDimitry Andric template <typename Predicate> bool TypeSetByHwMode::constrain(Predicate P) { 168*0fca6ea1SDimitry Andric bool Changed = false; 169*0fca6ea1SDimitry Andric for (auto &I : *this) 170*0fca6ea1SDimitry Andric Changed |= berase_if(I.second, [&P](MVT VT) { return !P(VT); }); 171*0fca6ea1SDimitry Andric return Changed; 172*0fca6ea1SDimitry Andric } 173*0fca6ea1SDimitry Andric 174*0fca6ea1SDimitry Andric template <typename Predicate> 175*0fca6ea1SDimitry Andric bool TypeSetByHwMode::assign_if(const TypeSetByHwMode &VTS, Predicate P) { 176*0fca6ea1SDimitry Andric assert(empty()); 177*0fca6ea1SDimitry Andric for (const auto &I : VTS) { 178*0fca6ea1SDimitry Andric SetType &S = getOrCreate(I.first); 179*0fca6ea1SDimitry Andric for (auto J : I.second) 180*0fca6ea1SDimitry Andric if (P(J)) 181*0fca6ea1SDimitry Andric S.insert(J); 182*0fca6ea1SDimitry Andric } 183*0fca6ea1SDimitry Andric return !empty(); 184*0fca6ea1SDimitry Andric } 185*0fca6ea1SDimitry Andric 186*0fca6ea1SDimitry Andric void TypeSetByHwMode::writeToStream(raw_ostream &OS) const { 187*0fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 188*0fca6ea1SDimitry Andric Modes.reserve(Map.size()); 189*0fca6ea1SDimitry Andric 190*0fca6ea1SDimitry Andric for (const auto &I : *this) 191*0fca6ea1SDimitry Andric Modes.push_back(I.first); 192*0fca6ea1SDimitry Andric if (Modes.empty()) { 193*0fca6ea1SDimitry Andric OS << "{}"; 194*0fca6ea1SDimitry Andric return; 195*0fca6ea1SDimitry Andric } 196*0fca6ea1SDimitry Andric array_pod_sort(Modes.begin(), Modes.end()); 197*0fca6ea1SDimitry Andric 198*0fca6ea1SDimitry Andric OS << '{'; 199*0fca6ea1SDimitry Andric for (unsigned M : Modes) { 200*0fca6ea1SDimitry Andric OS << ' ' << getModeName(M) << ':'; 201*0fca6ea1SDimitry Andric get(M).writeToStream(OS); 202*0fca6ea1SDimitry Andric } 203*0fca6ea1SDimitry Andric OS << " }"; 204*0fca6ea1SDimitry Andric } 205*0fca6ea1SDimitry Andric 206*0fca6ea1SDimitry Andric bool TypeSetByHwMode::operator==(const TypeSetByHwMode &VTS) const { 207*0fca6ea1SDimitry Andric // The isSimple call is much quicker than hasDefault - check this first. 208*0fca6ea1SDimitry Andric bool IsSimple = isSimple(); 209*0fca6ea1SDimitry Andric bool VTSIsSimple = VTS.isSimple(); 210*0fca6ea1SDimitry Andric if (IsSimple && VTSIsSimple) 211*0fca6ea1SDimitry Andric return getSimple() == VTS.getSimple(); 212*0fca6ea1SDimitry Andric 213*0fca6ea1SDimitry Andric // Speedup: We have a default if the set is simple. 214*0fca6ea1SDimitry Andric bool HaveDefault = IsSimple || hasDefault(); 215*0fca6ea1SDimitry Andric bool VTSHaveDefault = VTSIsSimple || VTS.hasDefault(); 216*0fca6ea1SDimitry Andric if (HaveDefault != VTSHaveDefault) 217*0fca6ea1SDimitry Andric return false; 218*0fca6ea1SDimitry Andric 219*0fca6ea1SDimitry Andric SmallSet<unsigned, 4> Modes; 220*0fca6ea1SDimitry Andric for (auto &I : *this) 221*0fca6ea1SDimitry Andric Modes.insert(I.first); 222*0fca6ea1SDimitry Andric for (const auto &I : VTS) 223*0fca6ea1SDimitry Andric Modes.insert(I.first); 224*0fca6ea1SDimitry Andric 225*0fca6ea1SDimitry Andric if (HaveDefault) { 226*0fca6ea1SDimitry Andric // Both sets have default mode. 227*0fca6ea1SDimitry Andric for (unsigned M : Modes) { 228*0fca6ea1SDimitry Andric if (get(M) != VTS.get(M)) 229*0fca6ea1SDimitry Andric return false; 230*0fca6ea1SDimitry Andric } 231*0fca6ea1SDimitry Andric } else { 232*0fca6ea1SDimitry Andric // Neither set has default mode. 233*0fca6ea1SDimitry Andric for (unsigned M : Modes) { 234*0fca6ea1SDimitry Andric // If there is no default mode, an empty set is equivalent to not having 235*0fca6ea1SDimitry Andric // the corresponding mode. 236*0fca6ea1SDimitry Andric bool NoModeThis = !hasMode(M) || get(M).empty(); 237*0fca6ea1SDimitry Andric bool NoModeVTS = !VTS.hasMode(M) || VTS.get(M).empty(); 238*0fca6ea1SDimitry Andric if (NoModeThis != NoModeVTS) 239*0fca6ea1SDimitry Andric return false; 240*0fca6ea1SDimitry Andric if (!NoModeThis) 241*0fca6ea1SDimitry Andric if (get(M) != VTS.get(M)) 242*0fca6ea1SDimitry Andric return false; 243*0fca6ea1SDimitry Andric } 244*0fca6ea1SDimitry Andric } 245*0fca6ea1SDimitry Andric 246*0fca6ea1SDimitry Andric return true; 247*0fca6ea1SDimitry Andric } 248*0fca6ea1SDimitry Andric 249*0fca6ea1SDimitry Andric namespace llvm { 250*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const MachineValueTypeSet &T) { 251*0fca6ea1SDimitry Andric T.writeToStream(OS); 252*0fca6ea1SDimitry Andric return OS; 253*0fca6ea1SDimitry Andric } 254*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const TypeSetByHwMode &T) { 255*0fca6ea1SDimitry Andric T.writeToStream(OS); 256*0fca6ea1SDimitry Andric return OS; 257*0fca6ea1SDimitry Andric } 258*0fca6ea1SDimitry Andric } // namespace llvm 259*0fca6ea1SDimitry Andric 260*0fca6ea1SDimitry Andric LLVM_DUMP_METHOD 261*0fca6ea1SDimitry Andric void TypeSetByHwMode::dump() const { dbgs() << *this << '\n'; } 262*0fca6ea1SDimitry Andric 263*0fca6ea1SDimitry Andric bool TypeSetByHwMode::intersect(SetType &Out, const SetType &In) { 264*0fca6ea1SDimitry Andric auto IntersectP = [&](std::optional<MVT> WildVT, function_ref<bool(MVT)> P) { 265*0fca6ea1SDimitry Andric // Complement of In within this partition. 266*0fca6ea1SDimitry Andric auto CompIn = [&](MVT T) -> bool { return !In.count(T) && P(T); }; 267*0fca6ea1SDimitry Andric 268*0fca6ea1SDimitry Andric if (!WildVT) 269*0fca6ea1SDimitry Andric return berase_if(Out, CompIn); 270*0fca6ea1SDimitry Andric 271*0fca6ea1SDimitry Andric bool OutW = Out.count(*WildVT), InW = In.count(*WildVT); 272*0fca6ea1SDimitry Andric if (OutW == InW) 273*0fca6ea1SDimitry Andric return berase_if(Out, CompIn); 274*0fca6ea1SDimitry Andric 275*0fca6ea1SDimitry Andric // Compute the intersection of scalars separately to account for only one 276*0fca6ea1SDimitry Andric // set containing WildVT. 277*0fca6ea1SDimitry Andric // The intersection of WildVT with a set of corresponding types that does 278*0fca6ea1SDimitry Andric // not include WildVT will result in the most specific type: 279*0fca6ea1SDimitry Andric // - WildVT is more specific than any set with two elements or more 280*0fca6ea1SDimitry Andric // - WildVT is less specific than any single type. 281*0fca6ea1SDimitry Andric // For example, for iPTR and scalar integer types 282*0fca6ea1SDimitry Andric // { iPTR } * { i32 } -> { i32 } 283*0fca6ea1SDimitry Andric // { iPTR } * { i32 i64 } -> { iPTR } 284*0fca6ea1SDimitry Andric // and 285*0fca6ea1SDimitry Andric // { iPTR i32 } * { i32 } -> { i32 } 286*0fca6ea1SDimitry Andric // { iPTR i32 } * { i32 i64 } -> { i32 i64 } 287*0fca6ea1SDimitry Andric // { iPTR i32 } * { i32 i64 i128 } -> { iPTR i32 } 288*0fca6ea1SDimitry Andric 289*0fca6ea1SDimitry Andric // Looking at just this partition, let In' = elements only in In, 290*0fca6ea1SDimitry Andric // Out' = elements only in Out, and IO = elements common to both. Normally 291*0fca6ea1SDimitry Andric // IO would be returned as the result of the intersection, but we need to 292*0fca6ea1SDimitry Andric // account for WildVT being a "wildcard" of sorts. Since elements in IO are 293*0fca6ea1SDimitry Andric // those that match both sets exactly, they will all belong to the output. 294*0fca6ea1SDimitry Andric // If any of the "leftovers" (i.e. In' or Out') contain WildVT, it means 295*0fca6ea1SDimitry Andric // that the other set doesn't have it, but it could have (1) a more 296*0fca6ea1SDimitry Andric // specific type, or (2) a set of types that is less specific. The 297*0fca6ea1SDimitry Andric // "leftovers" from the other set is what we want to examine more closely. 298*0fca6ea1SDimitry Andric 299*0fca6ea1SDimitry Andric auto Leftovers = [&](const SetType &A, const SetType &B) { 300*0fca6ea1SDimitry Andric SetType Diff = A; 301*0fca6ea1SDimitry Andric berase_if(Diff, [&](MVT T) { return B.count(T) || !P(T); }); 302*0fca6ea1SDimitry Andric return Diff; 303*0fca6ea1SDimitry Andric }; 304*0fca6ea1SDimitry Andric 305*0fca6ea1SDimitry Andric if (InW) { 306*0fca6ea1SDimitry Andric SetType OutLeftovers = Leftovers(Out, In); 307*0fca6ea1SDimitry Andric if (OutLeftovers.size() < 2) { 308*0fca6ea1SDimitry Andric // WildVT not added to Out. Keep the possible single leftover. 309*0fca6ea1SDimitry Andric return false; 310*0fca6ea1SDimitry Andric } 311*0fca6ea1SDimitry Andric // WildVT replaces the leftovers. 312*0fca6ea1SDimitry Andric berase_if(Out, CompIn); 313*0fca6ea1SDimitry Andric Out.insert(*WildVT); 314*0fca6ea1SDimitry Andric return true; 315*0fca6ea1SDimitry Andric } 316*0fca6ea1SDimitry Andric 317*0fca6ea1SDimitry Andric // OutW == true 318*0fca6ea1SDimitry Andric SetType InLeftovers = Leftovers(In, Out); 319*0fca6ea1SDimitry Andric unsigned SizeOut = Out.size(); 320*0fca6ea1SDimitry Andric berase_if(Out, CompIn); // This will remove at least the WildVT. 321*0fca6ea1SDimitry Andric if (InLeftovers.size() < 2) { 322*0fca6ea1SDimitry Andric // WildVT deleted from Out. Add back the possible single leftover. 323*0fca6ea1SDimitry Andric Out.insert(InLeftovers); 324*0fca6ea1SDimitry Andric return true; 325*0fca6ea1SDimitry Andric } 326*0fca6ea1SDimitry Andric 327*0fca6ea1SDimitry Andric // Keep the WildVT in Out. 328*0fca6ea1SDimitry Andric Out.insert(*WildVT); 329*0fca6ea1SDimitry Andric // If WildVT was the only element initially removed from Out, then Out 330*0fca6ea1SDimitry Andric // has not changed. 331*0fca6ea1SDimitry Andric return SizeOut != Out.size(); 332*0fca6ea1SDimitry Andric }; 333*0fca6ea1SDimitry Andric 334*0fca6ea1SDimitry Andric // Note: must be non-overlapping 335*0fca6ea1SDimitry Andric using WildPartT = std::pair<MVT, std::function<bool(MVT)>>; 336*0fca6ea1SDimitry Andric static const WildPartT WildParts[] = { 337*0fca6ea1SDimitry Andric {MVT::iPTR, [](MVT T) { return T.isScalarInteger() || T == MVT::iPTR; }}, 338*0fca6ea1SDimitry Andric }; 339*0fca6ea1SDimitry Andric 340*0fca6ea1SDimitry Andric bool Changed = false; 341*0fca6ea1SDimitry Andric for (const auto &I : WildParts) 342*0fca6ea1SDimitry Andric Changed |= IntersectP(I.first, I.second); 343*0fca6ea1SDimitry Andric 344*0fca6ea1SDimitry Andric Changed |= IntersectP(std::nullopt, [&](MVT T) { 345*0fca6ea1SDimitry Andric return !any_of(WildParts, [=](const WildPartT &I) { return I.second(T); }); 346*0fca6ea1SDimitry Andric }); 347*0fca6ea1SDimitry Andric 348*0fca6ea1SDimitry Andric return Changed; 349*0fca6ea1SDimitry Andric } 350*0fca6ea1SDimitry Andric 351*0fca6ea1SDimitry Andric bool TypeSetByHwMode::validate() const { 352*0fca6ea1SDimitry Andric if (empty()) 353*0fca6ea1SDimitry Andric return true; 354*0fca6ea1SDimitry Andric bool AllEmpty = true; 355*0fca6ea1SDimitry Andric for (const auto &I : *this) 356*0fca6ea1SDimitry Andric AllEmpty &= I.second.empty(); 357*0fca6ea1SDimitry Andric return !AllEmpty; 358*0fca6ea1SDimitry Andric } 359*0fca6ea1SDimitry Andric 360*0fca6ea1SDimitry Andric // --- TypeInfer 361*0fca6ea1SDimitry Andric 362*0fca6ea1SDimitry Andric bool TypeInfer::MergeInTypeInfo(TypeSetByHwMode &Out, 363*0fca6ea1SDimitry Andric const TypeSetByHwMode &In) const { 364*0fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 365*0fca6ea1SDimitry Andric In.validate(); 366*0fca6ea1SDimitry Andric if (In.empty() || Out == In || TP.hasError()) 367*0fca6ea1SDimitry Andric return false; 368*0fca6ea1SDimitry Andric if (Out.empty()) { 369*0fca6ea1SDimitry Andric Out = In; 370*0fca6ea1SDimitry Andric return true; 371*0fca6ea1SDimitry Andric } 372*0fca6ea1SDimitry Andric 373*0fca6ea1SDimitry Andric bool Changed = Out.constrain(In); 374*0fca6ea1SDimitry Andric if (Changed && Out.empty()) 375*0fca6ea1SDimitry Andric TP.error("Type contradiction"); 376*0fca6ea1SDimitry Andric 377*0fca6ea1SDimitry Andric return Changed; 378*0fca6ea1SDimitry Andric } 379*0fca6ea1SDimitry Andric 380*0fca6ea1SDimitry Andric bool TypeInfer::forceArbitrary(TypeSetByHwMode &Out) { 381*0fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 382*0fca6ea1SDimitry Andric if (TP.hasError()) 383*0fca6ea1SDimitry Andric return false; 384*0fca6ea1SDimitry Andric assert(!Out.empty() && "cannot pick from an empty set"); 385*0fca6ea1SDimitry Andric 386*0fca6ea1SDimitry Andric bool Changed = false; 387*0fca6ea1SDimitry Andric for (auto &I : Out) { 388*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &S = I.second; 389*0fca6ea1SDimitry Andric if (S.size() <= 1) 390*0fca6ea1SDimitry Andric continue; 391*0fca6ea1SDimitry Andric MVT T = *S.begin(); // Pick the first element. 392*0fca6ea1SDimitry Andric S.clear(); 393*0fca6ea1SDimitry Andric S.insert(T); 394*0fca6ea1SDimitry Andric Changed = true; 395*0fca6ea1SDimitry Andric } 396*0fca6ea1SDimitry Andric return Changed; 397*0fca6ea1SDimitry Andric } 398*0fca6ea1SDimitry Andric 399*0fca6ea1SDimitry Andric bool TypeInfer::EnforceInteger(TypeSetByHwMode &Out) { 400*0fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 401*0fca6ea1SDimitry Andric if (TP.hasError()) 402*0fca6ea1SDimitry Andric return false; 403*0fca6ea1SDimitry Andric if (!Out.empty()) 404*0fca6ea1SDimitry Andric return Out.constrain(isIntegerOrPtr); 405*0fca6ea1SDimitry Andric 406*0fca6ea1SDimitry Andric return Out.assign_if(getLegalTypes(), isIntegerOrPtr); 407*0fca6ea1SDimitry Andric } 408*0fca6ea1SDimitry Andric 409*0fca6ea1SDimitry Andric bool TypeInfer::EnforceFloatingPoint(TypeSetByHwMode &Out) { 410*0fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 411*0fca6ea1SDimitry Andric if (TP.hasError()) 412*0fca6ea1SDimitry Andric return false; 413*0fca6ea1SDimitry Andric if (!Out.empty()) 414*0fca6ea1SDimitry Andric return Out.constrain(isFloatingPoint); 415*0fca6ea1SDimitry Andric 416*0fca6ea1SDimitry Andric return Out.assign_if(getLegalTypes(), isFloatingPoint); 417*0fca6ea1SDimitry Andric } 418*0fca6ea1SDimitry Andric 419*0fca6ea1SDimitry Andric bool TypeInfer::EnforceScalar(TypeSetByHwMode &Out) { 420*0fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 421*0fca6ea1SDimitry Andric if (TP.hasError()) 422*0fca6ea1SDimitry Andric return false; 423*0fca6ea1SDimitry Andric if (!Out.empty()) 424*0fca6ea1SDimitry Andric return Out.constrain(isScalar); 425*0fca6ea1SDimitry Andric 426*0fca6ea1SDimitry Andric return Out.assign_if(getLegalTypes(), isScalar); 427*0fca6ea1SDimitry Andric } 428*0fca6ea1SDimitry Andric 429*0fca6ea1SDimitry Andric bool TypeInfer::EnforceVector(TypeSetByHwMode &Out) { 430*0fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 431*0fca6ea1SDimitry Andric if (TP.hasError()) 432*0fca6ea1SDimitry Andric return false; 433*0fca6ea1SDimitry Andric if (!Out.empty()) 434*0fca6ea1SDimitry Andric return Out.constrain(isVector); 435*0fca6ea1SDimitry Andric 436*0fca6ea1SDimitry Andric return Out.assign_if(getLegalTypes(), isVector); 437*0fca6ea1SDimitry Andric } 438*0fca6ea1SDimitry Andric 439*0fca6ea1SDimitry Andric bool TypeInfer::EnforceAny(TypeSetByHwMode &Out) { 440*0fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 441*0fca6ea1SDimitry Andric if (TP.hasError() || !Out.empty()) 442*0fca6ea1SDimitry Andric return false; 443*0fca6ea1SDimitry Andric 444*0fca6ea1SDimitry Andric Out = getLegalTypes(); 445*0fca6ea1SDimitry Andric return true; 446*0fca6ea1SDimitry Andric } 447*0fca6ea1SDimitry Andric 448*0fca6ea1SDimitry Andric template <typename Iter, typename Pred, typename Less> 449*0fca6ea1SDimitry Andric static Iter min_if(Iter B, Iter E, Pred P, Less L) { 450*0fca6ea1SDimitry Andric if (B == E) 451*0fca6ea1SDimitry Andric return E; 452*0fca6ea1SDimitry Andric Iter Min = E; 453*0fca6ea1SDimitry Andric for (Iter I = B; I != E; ++I) { 454*0fca6ea1SDimitry Andric if (!P(*I)) 455*0fca6ea1SDimitry Andric continue; 456*0fca6ea1SDimitry Andric if (Min == E || L(*I, *Min)) 457*0fca6ea1SDimitry Andric Min = I; 458*0fca6ea1SDimitry Andric } 459*0fca6ea1SDimitry Andric return Min; 460*0fca6ea1SDimitry Andric } 461*0fca6ea1SDimitry Andric 462*0fca6ea1SDimitry Andric template <typename Iter, typename Pred, typename Less> 463*0fca6ea1SDimitry Andric static Iter max_if(Iter B, Iter E, Pred P, Less L) { 464*0fca6ea1SDimitry Andric if (B == E) 465*0fca6ea1SDimitry Andric return E; 466*0fca6ea1SDimitry Andric Iter Max = E; 467*0fca6ea1SDimitry Andric for (Iter I = B; I != E; ++I) { 468*0fca6ea1SDimitry Andric if (!P(*I)) 469*0fca6ea1SDimitry Andric continue; 470*0fca6ea1SDimitry Andric if (Max == E || L(*Max, *I)) 471*0fca6ea1SDimitry Andric Max = I; 472*0fca6ea1SDimitry Andric } 473*0fca6ea1SDimitry Andric return Max; 474*0fca6ea1SDimitry Andric } 475*0fca6ea1SDimitry Andric 476*0fca6ea1SDimitry Andric /// Make sure that for each type in Small, there exists a larger type in Big. 477*0fca6ea1SDimitry Andric bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small, TypeSetByHwMode &Big, 478*0fca6ea1SDimitry Andric bool SmallIsVT) { 479*0fca6ea1SDimitry Andric ValidateOnExit _1(Small, *this), _2(Big, *this); 480*0fca6ea1SDimitry Andric if (TP.hasError()) 481*0fca6ea1SDimitry Andric return false; 482*0fca6ea1SDimitry Andric bool Changed = false; 483*0fca6ea1SDimitry Andric 484*0fca6ea1SDimitry Andric assert((!SmallIsVT || !Small.empty()) && 485*0fca6ea1SDimitry Andric "Small should not be empty for SDTCisVTSmallerThanOp"); 486*0fca6ea1SDimitry Andric 487*0fca6ea1SDimitry Andric if (Small.empty()) 488*0fca6ea1SDimitry Andric Changed |= EnforceAny(Small); 489*0fca6ea1SDimitry Andric if (Big.empty()) 490*0fca6ea1SDimitry Andric Changed |= EnforceAny(Big); 491*0fca6ea1SDimitry Andric 492*0fca6ea1SDimitry Andric assert(Small.hasDefault() && Big.hasDefault()); 493*0fca6ea1SDimitry Andric 494*0fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 495*0fca6ea1SDimitry Andric union_modes(Small, Big, Modes); 496*0fca6ea1SDimitry Andric 497*0fca6ea1SDimitry Andric // 1. Only allow integer or floating point types and make sure that 498*0fca6ea1SDimitry Andric // both sides are both integer or both floating point. 499*0fca6ea1SDimitry Andric // 2. Make sure that either both sides have vector types, or neither 500*0fca6ea1SDimitry Andric // of them does. 501*0fca6ea1SDimitry Andric for (unsigned M : Modes) { 502*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &S = Small.get(M); 503*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &B = Big.get(M); 504*0fca6ea1SDimitry Andric 505*0fca6ea1SDimitry Andric assert((!SmallIsVT || !S.empty()) && "Expected non-empty type"); 506*0fca6ea1SDimitry Andric 507*0fca6ea1SDimitry Andric if (any_of(S, isIntegerOrPtr) && any_of(B, isIntegerOrPtr)) { 508*0fca6ea1SDimitry Andric auto NotInt = [](MVT VT) { return !isIntegerOrPtr(VT); }; 509*0fca6ea1SDimitry Andric Changed |= berase_if(S, NotInt); 510*0fca6ea1SDimitry Andric Changed |= berase_if(B, NotInt); 511*0fca6ea1SDimitry Andric } else if (any_of(S, isFloatingPoint) && any_of(B, isFloatingPoint)) { 512*0fca6ea1SDimitry Andric auto NotFP = [](MVT VT) { return !isFloatingPoint(VT); }; 513*0fca6ea1SDimitry Andric Changed |= berase_if(S, NotFP); 514*0fca6ea1SDimitry Andric Changed |= berase_if(B, NotFP); 515*0fca6ea1SDimitry Andric } else if (SmallIsVT && B.empty()) { 516*0fca6ea1SDimitry Andric // B is empty and since S is a specific VT, it will never be empty. Don't 517*0fca6ea1SDimitry Andric // report this as a change, just clear S and continue. This prevents an 518*0fca6ea1SDimitry Andric // infinite loop. 519*0fca6ea1SDimitry Andric S.clear(); 520*0fca6ea1SDimitry Andric } else if (S.empty() || B.empty()) { 521*0fca6ea1SDimitry Andric Changed = !S.empty() || !B.empty(); 522*0fca6ea1SDimitry Andric S.clear(); 523*0fca6ea1SDimitry Andric B.clear(); 524*0fca6ea1SDimitry Andric } else { 525*0fca6ea1SDimitry Andric TP.error("Incompatible types"); 526*0fca6ea1SDimitry Andric return Changed; 527*0fca6ea1SDimitry Andric } 528*0fca6ea1SDimitry Andric 529*0fca6ea1SDimitry Andric if (none_of(S, isVector) || none_of(B, isVector)) { 530*0fca6ea1SDimitry Andric Changed |= berase_if(S, isVector); 531*0fca6ea1SDimitry Andric Changed |= berase_if(B, isVector); 532*0fca6ea1SDimitry Andric } 533*0fca6ea1SDimitry Andric } 534*0fca6ea1SDimitry Andric 535*0fca6ea1SDimitry Andric auto LT = [](MVT A, MVT B) -> bool { 536*0fca6ea1SDimitry Andric // Always treat non-scalable MVTs as smaller than scalable MVTs for the 537*0fca6ea1SDimitry Andric // purposes of ordering. 538*0fca6ea1SDimitry Andric auto ASize = std::tuple(A.isScalableVector(), A.getScalarSizeInBits(), 539*0fca6ea1SDimitry Andric A.getSizeInBits().getKnownMinValue()); 540*0fca6ea1SDimitry Andric auto BSize = std::tuple(B.isScalableVector(), B.getScalarSizeInBits(), 541*0fca6ea1SDimitry Andric B.getSizeInBits().getKnownMinValue()); 542*0fca6ea1SDimitry Andric return ASize < BSize; 543*0fca6ea1SDimitry Andric }; 544*0fca6ea1SDimitry Andric auto SameKindLE = [](MVT A, MVT B) -> bool { 545*0fca6ea1SDimitry Andric // This function is used when removing elements: when a vector is compared 546*0fca6ea1SDimitry Andric // to a non-vector or a scalable vector to any non-scalable MVT, it should 547*0fca6ea1SDimitry Andric // return false (to avoid removal). 548*0fca6ea1SDimitry Andric if (std::tuple(A.isVector(), A.isScalableVector()) != 549*0fca6ea1SDimitry Andric std::tuple(B.isVector(), B.isScalableVector())) 550*0fca6ea1SDimitry Andric return false; 551*0fca6ea1SDimitry Andric 552*0fca6ea1SDimitry Andric return std::tuple(A.getScalarSizeInBits(), 553*0fca6ea1SDimitry Andric A.getSizeInBits().getKnownMinValue()) <= 554*0fca6ea1SDimitry Andric std::tuple(B.getScalarSizeInBits(), 555*0fca6ea1SDimitry Andric B.getSizeInBits().getKnownMinValue()); 556*0fca6ea1SDimitry Andric }; 557*0fca6ea1SDimitry Andric 558*0fca6ea1SDimitry Andric for (unsigned M : Modes) { 559*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &S = Small.get(M); 560*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &B = Big.get(M); 561*0fca6ea1SDimitry Andric // MinS = min scalar in Small, remove all scalars from Big that are 562*0fca6ea1SDimitry Andric // smaller-or-equal than MinS. 563*0fca6ea1SDimitry Andric auto MinS = min_if(S.begin(), S.end(), isScalar, LT); 564*0fca6ea1SDimitry Andric if (MinS != S.end()) 565*0fca6ea1SDimitry Andric Changed |= 566*0fca6ea1SDimitry Andric berase_if(B, std::bind(SameKindLE, std::placeholders::_1, *MinS)); 567*0fca6ea1SDimitry Andric 568*0fca6ea1SDimitry Andric // MaxS = max scalar in Big, remove all scalars from Small that are 569*0fca6ea1SDimitry Andric // larger than MaxS. 570*0fca6ea1SDimitry Andric auto MaxS = max_if(B.begin(), B.end(), isScalar, LT); 571*0fca6ea1SDimitry Andric if (MaxS != B.end()) 572*0fca6ea1SDimitry Andric Changed |= 573*0fca6ea1SDimitry Andric berase_if(S, std::bind(SameKindLE, *MaxS, std::placeholders::_1)); 574*0fca6ea1SDimitry Andric 575*0fca6ea1SDimitry Andric // MinV = min vector in Small, remove all vectors from Big that are 576*0fca6ea1SDimitry Andric // smaller-or-equal than MinV. 577*0fca6ea1SDimitry Andric auto MinV = min_if(S.begin(), S.end(), isVector, LT); 578*0fca6ea1SDimitry Andric if (MinV != S.end()) 579*0fca6ea1SDimitry Andric Changed |= 580*0fca6ea1SDimitry Andric berase_if(B, std::bind(SameKindLE, std::placeholders::_1, *MinV)); 581*0fca6ea1SDimitry Andric 582*0fca6ea1SDimitry Andric // MaxV = max vector in Big, remove all vectors from Small that are 583*0fca6ea1SDimitry Andric // larger than MaxV. 584*0fca6ea1SDimitry Andric auto MaxV = max_if(B.begin(), B.end(), isVector, LT); 585*0fca6ea1SDimitry Andric if (MaxV != B.end()) 586*0fca6ea1SDimitry Andric Changed |= 587*0fca6ea1SDimitry Andric berase_if(S, std::bind(SameKindLE, *MaxV, std::placeholders::_1)); 588*0fca6ea1SDimitry Andric } 589*0fca6ea1SDimitry Andric 590*0fca6ea1SDimitry Andric return Changed; 591*0fca6ea1SDimitry Andric } 592*0fca6ea1SDimitry Andric 593*0fca6ea1SDimitry Andric /// 1. Ensure that for each type T in Vec, T is a vector type, and that 594*0fca6ea1SDimitry Andric /// for each type U in Elem, U is a scalar type. 595*0fca6ea1SDimitry Andric /// 2. Ensure that for each (scalar) type U in Elem, there exists a (vector) 596*0fca6ea1SDimitry Andric /// type T in Vec, such that U is the element type of T. 597*0fca6ea1SDimitry Andric bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec, 598*0fca6ea1SDimitry Andric TypeSetByHwMode &Elem) { 599*0fca6ea1SDimitry Andric ValidateOnExit _1(Vec, *this), _2(Elem, *this); 600*0fca6ea1SDimitry Andric if (TP.hasError()) 601*0fca6ea1SDimitry Andric return false; 602*0fca6ea1SDimitry Andric bool Changed = false; 603*0fca6ea1SDimitry Andric 604*0fca6ea1SDimitry Andric if (Vec.empty()) 605*0fca6ea1SDimitry Andric Changed |= EnforceVector(Vec); 606*0fca6ea1SDimitry Andric if (Elem.empty()) 607*0fca6ea1SDimitry Andric Changed |= EnforceScalar(Elem); 608*0fca6ea1SDimitry Andric 609*0fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 610*0fca6ea1SDimitry Andric union_modes(Vec, Elem, Modes); 611*0fca6ea1SDimitry Andric for (unsigned M : Modes) { 612*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &V = Vec.get(M); 613*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &E = Elem.get(M); 614*0fca6ea1SDimitry Andric 615*0fca6ea1SDimitry Andric Changed |= berase_if(V, isScalar); // Scalar = !vector 616*0fca6ea1SDimitry Andric Changed |= berase_if(E, isVector); // Vector = !scalar 617*0fca6ea1SDimitry Andric assert(!V.empty() && !E.empty()); 618*0fca6ea1SDimitry Andric 619*0fca6ea1SDimitry Andric MachineValueTypeSet VT, ST; 620*0fca6ea1SDimitry Andric // Collect element types from the "vector" set. 621*0fca6ea1SDimitry Andric for (MVT T : V) 622*0fca6ea1SDimitry Andric VT.insert(T.getVectorElementType()); 623*0fca6ea1SDimitry Andric // Collect scalar types from the "element" set. 624*0fca6ea1SDimitry Andric for (MVT T : E) 625*0fca6ea1SDimitry Andric ST.insert(T); 626*0fca6ea1SDimitry Andric 627*0fca6ea1SDimitry Andric // Remove from V all (vector) types whose element type is not in S. 628*0fca6ea1SDimitry Andric Changed |= berase_if(V, [&ST](MVT T) -> bool { 629*0fca6ea1SDimitry Andric return !ST.count(T.getVectorElementType()); 630*0fca6ea1SDimitry Andric }); 631*0fca6ea1SDimitry Andric // Remove from E all (scalar) types, for which there is no corresponding 632*0fca6ea1SDimitry Andric // type in V. 633*0fca6ea1SDimitry Andric Changed |= berase_if(E, [&VT](MVT T) -> bool { return !VT.count(T); }); 634*0fca6ea1SDimitry Andric } 635*0fca6ea1SDimitry Andric 636*0fca6ea1SDimitry Andric return Changed; 637*0fca6ea1SDimitry Andric } 638*0fca6ea1SDimitry Andric 639*0fca6ea1SDimitry Andric bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec, 640*0fca6ea1SDimitry Andric const ValueTypeByHwMode &VVT) { 641*0fca6ea1SDimitry Andric TypeSetByHwMode Tmp(VVT); 642*0fca6ea1SDimitry Andric ValidateOnExit _1(Vec, *this), _2(Tmp, *this); 643*0fca6ea1SDimitry Andric return EnforceVectorEltTypeIs(Vec, Tmp); 644*0fca6ea1SDimitry Andric } 645*0fca6ea1SDimitry Andric 646*0fca6ea1SDimitry Andric /// Ensure that for each type T in Sub, T is a vector type, and there 647*0fca6ea1SDimitry Andric /// exists a type U in Vec such that U is a vector type with the same 648*0fca6ea1SDimitry Andric /// element type as T and at least as many elements as T. 649*0fca6ea1SDimitry Andric bool TypeInfer::EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec, 650*0fca6ea1SDimitry Andric TypeSetByHwMode &Sub) { 651*0fca6ea1SDimitry Andric ValidateOnExit _1(Vec, *this), _2(Sub, *this); 652*0fca6ea1SDimitry Andric if (TP.hasError()) 653*0fca6ea1SDimitry Andric return false; 654*0fca6ea1SDimitry Andric 655*0fca6ea1SDimitry Andric /// Return true if B is a suB-vector of P, i.e. P is a suPer-vector of B. 656*0fca6ea1SDimitry Andric auto IsSubVec = [](MVT B, MVT P) -> bool { 657*0fca6ea1SDimitry Andric if (!B.isVector() || !P.isVector()) 658*0fca6ea1SDimitry Andric return false; 659*0fca6ea1SDimitry Andric // Logically a <4 x i32> is a valid subvector of <n x 4 x i32> 660*0fca6ea1SDimitry Andric // but until there are obvious use-cases for this, keep the 661*0fca6ea1SDimitry Andric // types separate. 662*0fca6ea1SDimitry Andric if (B.isScalableVector() != P.isScalableVector()) 663*0fca6ea1SDimitry Andric return false; 664*0fca6ea1SDimitry Andric if (B.getVectorElementType() != P.getVectorElementType()) 665*0fca6ea1SDimitry Andric return false; 666*0fca6ea1SDimitry Andric return B.getVectorMinNumElements() < P.getVectorMinNumElements(); 667*0fca6ea1SDimitry Andric }; 668*0fca6ea1SDimitry Andric 669*0fca6ea1SDimitry Andric /// Return true if S has no element (vector type) that T is a sub-vector of, 670*0fca6ea1SDimitry Andric /// i.e. has the same element type as T and more elements. 671*0fca6ea1SDimitry Andric auto NoSubV = [&IsSubVec](const TypeSetByHwMode::SetType &S, MVT T) -> bool { 672*0fca6ea1SDimitry Andric for (auto I : S) 673*0fca6ea1SDimitry Andric if (IsSubVec(T, I)) 674*0fca6ea1SDimitry Andric return false; 675*0fca6ea1SDimitry Andric return true; 676*0fca6ea1SDimitry Andric }; 677*0fca6ea1SDimitry Andric 678*0fca6ea1SDimitry Andric /// Return true if S has no element (vector type) that T is a super-vector 679*0fca6ea1SDimitry Andric /// of, i.e. has the same element type as T and fewer elements. 680*0fca6ea1SDimitry Andric auto NoSupV = [&IsSubVec](const TypeSetByHwMode::SetType &S, MVT T) -> bool { 681*0fca6ea1SDimitry Andric for (auto I : S) 682*0fca6ea1SDimitry Andric if (IsSubVec(I, T)) 683*0fca6ea1SDimitry Andric return false; 684*0fca6ea1SDimitry Andric return true; 685*0fca6ea1SDimitry Andric }; 686*0fca6ea1SDimitry Andric 687*0fca6ea1SDimitry Andric bool Changed = false; 688*0fca6ea1SDimitry Andric 689*0fca6ea1SDimitry Andric if (Vec.empty()) 690*0fca6ea1SDimitry Andric Changed |= EnforceVector(Vec); 691*0fca6ea1SDimitry Andric if (Sub.empty()) 692*0fca6ea1SDimitry Andric Changed |= EnforceVector(Sub); 693*0fca6ea1SDimitry Andric 694*0fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 695*0fca6ea1SDimitry Andric union_modes(Vec, Sub, Modes); 696*0fca6ea1SDimitry Andric for (unsigned M : Modes) { 697*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &S = Sub.get(M); 698*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &V = Vec.get(M); 699*0fca6ea1SDimitry Andric 700*0fca6ea1SDimitry Andric Changed |= berase_if(S, isScalar); 701*0fca6ea1SDimitry Andric 702*0fca6ea1SDimitry Andric // Erase all types from S that are not sub-vectors of a type in V. 703*0fca6ea1SDimitry Andric Changed |= berase_if(S, std::bind(NoSubV, V, std::placeholders::_1)); 704*0fca6ea1SDimitry Andric 705*0fca6ea1SDimitry Andric // Erase all types from V that are not super-vectors of a type in S. 706*0fca6ea1SDimitry Andric Changed |= berase_if(V, std::bind(NoSupV, S, std::placeholders::_1)); 707*0fca6ea1SDimitry Andric } 708*0fca6ea1SDimitry Andric 709*0fca6ea1SDimitry Andric return Changed; 710*0fca6ea1SDimitry Andric } 711*0fca6ea1SDimitry Andric 712*0fca6ea1SDimitry Andric /// 1. Ensure that V has a scalar type iff W has a scalar type. 713*0fca6ea1SDimitry Andric /// 2. Ensure that for each vector type T in V, there exists a vector 714*0fca6ea1SDimitry Andric /// type U in W, such that T and U have the same number of elements. 715*0fca6ea1SDimitry Andric /// 3. Ensure that for each vector type U in W, there exists a vector 716*0fca6ea1SDimitry Andric /// type T in V, such that T and U have the same number of elements 717*0fca6ea1SDimitry Andric /// (reverse of 2). 718*0fca6ea1SDimitry Andric bool TypeInfer::EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W) { 719*0fca6ea1SDimitry Andric ValidateOnExit _1(V, *this), _2(W, *this); 720*0fca6ea1SDimitry Andric if (TP.hasError()) 721*0fca6ea1SDimitry Andric return false; 722*0fca6ea1SDimitry Andric 723*0fca6ea1SDimitry Andric bool Changed = false; 724*0fca6ea1SDimitry Andric if (V.empty()) 725*0fca6ea1SDimitry Andric Changed |= EnforceAny(V); 726*0fca6ea1SDimitry Andric if (W.empty()) 727*0fca6ea1SDimitry Andric Changed |= EnforceAny(W); 728*0fca6ea1SDimitry Andric 729*0fca6ea1SDimitry Andric // An actual vector type cannot have 0 elements, so we can treat scalars 730*0fca6ea1SDimitry Andric // as zero-length vectors. This way both vectors and scalars can be 731*0fca6ea1SDimitry Andric // processed identically. 732*0fca6ea1SDimitry Andric auto NoLength = [](const SmallDenseSet<ElementCount> &Lengths, 733*0fca6ea1SDimitry Andric MVT T) -> bool { 734*0fca6ea1SDimitry Andric return !Lengths.count(T.isVector() ? T.getVectorElementCount() 735*0fca6ea1SDimitry Andric : ElementCount()); 736*0fca6ea1SDimitry Andric }; 737*0fca6ea1SDimitry Andric 738*0fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 739*0fca6ea1SDimitry Andric union_modes(V, W, Modes); 740*0fca6ea1SDimitry Andric for (unsigned M : Modes) { 741*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &VS = V.get(M); 742*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &WS = W.get(M); 743*0fca6ea1SDimitry Andric 744*0fca6ea1SDimitry Andric SmallDenseSet<ElementCount> VN, WN; 745*0fca6ea1SDimitry Andric for (MVT T : VS) 746*0fca6ea1SDimitry Andric VN.insert(T.isVector() ? T.getVectorElementCount() : ElementCount()); 747*0fca6ea1SDimitry Andric for (MVT T : WS) 748*0fca6ea1SDimitry Andric WN.insert(T.isVector() ? T.getVectorElementCount() : ElementCount()); 749*0fca6ea1SDimitry Andric 750*0fca6ea1SDimitry Andric Changed |= berase_if(VS, std::bind(NoLength, WN, std::placeholders::_1)); 751*0fca6ea1SDimitry Andric Changed |= berase_if(WS, std::bind(NoLength, VN, std::placeholders::_1)); 752*0fca6ea1SDimitry Andric } 753*0fca6ea1SDimitry Andric return Changed; 754*0fca6ea1SDimitry Andric } 755*0fca6ea1SDimitry Andric 756*0fca6ea1SDimitry Andric namespace { 757*0fca6ea1SDimitry Andric struct TypeSizeComparator { 758*0fca6ea1SDimitry Andric bool operator()(const TypeSize &LHS, const TypeSize &RHS) const { 759*0fca6ea1SDimitry Andric return std::tuple(LHS.isScalable(), LHS.getKnownMinValue()) < 760*0fca6ea1SDimitry Andric std::tuple(RHS.isScalable(), RHS.getKnownMinValue()); 761*0fca6ea1SDimitry Andric } 762*0fca6ea1SDimitry Andric }; 763*0fca6ea1SDimitry Andric } // end anonymous namespace 764*0fca6ea1SDimitry Andric 765*0fca6ea1SDimitry Andric /// 1. Ensure that for each type T in A, there exists a type U in B, 766*0fca6ea1SDimitry Andric /// such that T and U have equal size in bits. 767*0fca6ea1SDimitry Andric /// 2. Ensure that for each type U in B, there exists a type T in A 768*0fca6ea1SDimitry Andric /// such that T and U have equal size in bits (reverse of 1). 769*0fca6ea1SDimitry Andric bool TypeInfer::EnforceSameSize(TypeSetByHwMode &A, TypeSetByHwMode &B) { 770*0fca6ea1SDimitry Andric ValidateOnExit _1(A, *this), _2(B, *this); 771*0fca6ea1SDimitry Andric if (TP.hasError()) 772*0fca6ea1SDimitry Andric return false; 773*0fca6ea1SDimitry Andric bool Changed = false; 774*0fca6ea1SDimitry Andric if (A.empty()) 775*0fca6ea1SDimitry Andric Changed |= EnforceAny(A); 776*0fca6ea1SDimitry Andric if (B.empty()) 777*0fca6ea1SDimitry Andric Changed |= EnforceAny(B); 778*0fca6ea1SDimitry Andric 779*0fca6ea1SDimitry Andric typedef SmallSet<TypeSize, 2, TypeSizeComparator> TypeSizeSet; 780*0fca6ea1SDimitry Andric 781*0fca6ea1SDimitry Andric auto NoSize = [](const TypeSizeSet &Sizes, MVT T) -> bool { 782*0fca6ea1SDimitry Andric return !Sizes.count(T.getSizeInBits()); 783*0fca6ea1SDimitry Andric }; 784*0fca6ea1SDimitry Andric 785*0fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 786*0fca6ea1SDimitry Andric union_modes(A, B, Modes); 787*0fca6ea1SDimitry Andric for (unsigned M : Modes) { 788*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &AS = A.get(M); 789*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &BS = B.get(M); 790*0fca6ea1SDimitry Andric TypeSizeSet AN, BN; 791*0fca6ea1SDimitry Andric 792*0fca6ea1SDimitry Andric for (MVT T : AS) 793*0fca6ea1SDimitry Andric AN.insert(T.getSizeInBits()); 794*0fca6ea1SDimitry Andric for (MVT T : BS) 795*0fca6ea1SDimitry Andric BN.insert(T.getSizeInBits()); 796*0fca6ea1SDimitry Andric 797*0fca6ea1SDimitry Andric Changed |= berase_if(AS, std::bind(NoSize, BN, std::placeholders::_1)); 798*0fca6ea1SDimitry Andric Changed |= berase_if(BS, std::bind(NoSize, AN, std::placeholders::_1)); 799*0fca6ea1SDimitry Andric } 800*0fca6ea1SDimitry Andric 801*0fca6ea1SDimitry Andric return Changed; 802*0fca6ea1SDimitry Andric } 803*0fca6ea1SDimitry Andric 804*0fca6ea1SDimitry Andric void TypeInfer::expandOverloads(TypeSetByHwMode &VTS) const { 805*0fca6ea1SDimitry Andric ValidateOnExit _1(VTS, *this); 806*0fca6ea1SDimitry Andric const TypeSetByHwMode &Legal = getLegalTypes(); 807*0fca6ea1SDimitry Andric assert(Legal.isSimple() && "Default-mode only expected"); 808*0fca6ea1SDimitry Andric const TypeSetByHwMode::SetType &LegalTypes = Legal.getSimple(); 809*0fca6ea1SDimitry Andric 810*0fca6ea1SDimitry Andric for (auto &I : VTS) 811*0fca6ea1SDimitry Andric expandOverloads(I.second, LegalTypes); 812*0fca6ea1SDimitry Andric } 813*0fca6ea1SDimitry Andric 814*0fca6ea1SDimitry Andric void TypeInfer::expandOverloads(TypeSetByHwMode::SetType &Out, 815*0fca6ea1SDimitry Andric const TypeSetByHwMode::SetType &Legal) const { 816*0fca6ea1SDimitry Andric if (Out.count(MVT::iPTRAny)) { 817*0fca6ea1SDimitry Andric Out.erase(MVT::iPTRAny); 818*0fca6ea1SDimitry Andric Out.insert(MVT::iPTR); 819*0fca6ea1SDimitry Andric } else if (Out.count(MVT::iAny)) { 820*0fca6ea1SDimitry Andric Out.erase(MVT::iAny); 821*0fca6ea1SDimitry Andric for (MVT T : MVT::integer_valuetypes()) 822*0fca6ea1SDimitry Andric if (Legal.count(T)) 823*0fca6ea1SDimitry Andric Out.insert(T); 824*0fca6ea1SDimitry Andric for (MVT T : MVT::integer_fixedlen_vector_valuetypes()) 825*0fca6ea1SDimitry Andric if (Legal.count(T)) 826*0fca6ea1SDimitry Andric Out.insert(T); 827*0fca6ea1SDimitry Andric for (MVT T : MVT::integer_scalable_vector_valuetypes()) 828*0fca6ea1SDimitry Andric if (Legal.count(T)) 829*0fca6ea1SDimitry Andric Out.insert(T); 830*0fca6ea1SDimitry Andric } else if (Out.count(MVT::fAny)) { 831*0fca6ea1SDimitry Andric Out.erase(MVT::fAny); 832*0fca6ea1SDimitry Andric for (MVT T : MVT::fp_valuetypes()) 833*0fca6ea1SDimitry Andric if (Legal.count(T)) 834*0fca6ea1SDimitry Andric Out.insert(T); 835*0fca6ea1SDimitry Andric for (MVT T : MVT::fp_fixedlen_vector_valuetypes()) 836*0fca6ea1SDimitry Andric if (Legal.count(T)) 837*0fca6ea1SDimitry Andric Out.insert(T); 838*0fca6ea1SDimitry Andric for (MVT T : MVT::fp_scalable_vector_valuetypes()) 839*0fca6ea1SDimitry Andric if (Legal.count(T)) 840*0fca6ea1SDimitry Andric Out.insert(T); 841*0fca6ea1SDimitry Andric } else if (Out.count(MVT::vAny)) { 842*0fca6ea1SDimitry Andric Out.erase(MVT::vAny); 843*0fca6ea1SDimitry Andric for (MVT T : MVT::vector_valuetypes()) 844*0fca6ea1SDimitry Andric if (Legal.count(T)) 845*0fca6ea1SDimitry Andric Out.insert(T); 846*0fca6ea1SDimitry Andric } else if (Out.count(MVT::Any)) { 847*0fca6ea1SDimitry Andric Out.erase(MVT::Any); 848*0fca6ea1SDimitry Andric for (MVT T : MVT::all_valuetypes()) 849*0fca6ea1SDimitry Andric if (Legal.count(T)) 850*0fca6ea1SDimitry Andric Out.insert(T); 851*0fca6ea1SDimitry Andric } 852*0fca6ea1SDimitry Andric } 853*0fca6ea1SDimitry Andric 854*0fca6ea1SDimitry Andric const TypeSetByHwMode &TypeInfer::getLegalTypes() const { 855*0fca6ea1SDimitry Andric if (!LegalTypesCached) { 856*0fca6ea1SDimitry Andric TypeSetByHwMode::SetType &LegalTypes = LegalCache.getOrCreate(DefaultMode); 857*0fca6ea1SDimitry Andric // Stuff all types from all modes into the default mode. 858*0fca6ea1SDimitry Andric const TypeSetByHwMode <S = TP.getDAGPatterns().getLegalTypes(); 859*0fca6ea1SDimitry Andric for (const auto &I : LTS) 860*0fca6ea1SDimitry Andric LegalTypes.insert(I.second); 861*0fca6ea1SDimitry Andric LegalTypesCached = true; 862*0fca6ea1SDimitry Andric } 863*0fca6ea1SDimitry Andric assert(LegalCache.isSimple() && "Default-mode only expected"); 864*0fca6ea1SDimitry Andric return LegalCache; 865*0fca6ea1SDimitry Andric } 866*0fca6ea1SDimitry Andric 867*0fca6ea1SDimitry Andric TypeInfer::ValidateOnExit::~ValidateOnExit() { 868*0fca6ea1SDimitry Andric if (Infer.Validate && !VTS.validate()) { 869*0fca6ea1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 870*0fca6ea1SDimitry Andric errs() << "Type set is empty for each HW mode:\n" 871*0fca6ea1SDimitry Andric "possible type contradiction in the pattern below " 872*0fca6ea1SDimitry Andric "(use -print-records with llvm-tblgen to see all " 873*0fca6ea1SDimitry Andric "expanded records).\n"; 874*0fca6ea1SDimitry Andric Infer.TP.dump(); 875*0fca6ea1SDimitry Andric errs() << "Generated from record:\n"; 876*0fca6ea1SDimitry Andric Infer.TP.getRecord()->dump(); 877*0fca6ea1SDimitry Andric #endif 878*0fca6ea1SDimitry Andric PrintFatalError(Infer.TP.getRecord()->getLoc(), 879*0fca6ea1SDimitry Andric "Type set is empty for each HW mode in '" + 880*0fca6ea1SDimitry Andric Infer.TP.getRecord()->getName() + "'"); 881*0fca6ea1SDimitry Andric } 882*0fca6ea1SDimitry Andric } 883*0fca6ea1SDimitry Andric 884*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 885*0fca6ea1SDimitry Andric // ScopedName Implementation 886*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 887*0fca6ea1SDimitry Andric 888*0fca6ea1SDimitry Andric bool ScopedName::operator==(const ScopedName &o) const { 889*0fca6ea1SDimitry Andric return Scope == o.Scope && Identifier == o.Identifier; 890*0fca6ea1SDimitry Andric } 891*0fca6ea1SDimitry Andric 892*0fca6ea1SDimitry Andric bool ScopedName::operator!=(const ScopedName &o) const { return !(*this == o); } 893*0fca6ea1SDimitry Andric 894*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 895*0fca6ea1SDimitry Andric // TreePredicateFn Implementation 896*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 897*0fca6ea1SDimitry Andric 898*0fca6ea1SDimitry Andric /// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag. 899*0fca6ea1SDimitry Andric TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) { 900*0fca6ea1SDimitry Andric assert( 901*0fca6ea1SDimitry Andric (!hasPredCode() || !hasImmCode()) && 902*0fca6ea1SDimitry Andric ".td file corrupt: can't have a node predicate *and* an imm predicate"); 903*0fca6ea1SDimitry Andric } 904*0fca6ea1SDimitry Andric 905*0fca6ea1SDimitry Andric bool TreePredicateFn::hasPredCode() const { 906*0fca6ea1SDimitry Andric return isLoad() || isStore() || isAtomic() || hasNoUse() || hasOneUse() || 907*0fca6ea1SDimitry Andric !PatFragRec->getRecord()->getValueAsString("PredicateCode").empty(); 908*0fca6ea1SDimitry Andric } 909*0fca6ea1SDimitry Andric 910*0fca6ea1SDimitry Andric std::string TreePredicateFn::getPredCode() const { 911*0fca6ea1SDimitry Andric std::string Code; 912*0fca6ea1SDimitry Andric 913*0fca6ea1SDimitry Andric if (!isLoad() && !isStore() && !isAtomic()) { 914*0fca6ea1SDimitry Andric Record *MemoryVT = getMemoryVT(); 915*0fca6ea1SDimitry Andric 916*0fca6ea1SDimitry Andric if (MemoryVT) 917*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 918*0fca6ea1SDimitry Andric "MemoryVT requires IsLoad or IsStore"); 919*0fca6ea1SDimitry Andric } 920*0fca6ea1SDimitry Andric 921*0fca6ea1SDimitry Andric if (!isLoad() && !isStore()) { 922*0fca6ea1SDimitry Andric if (isUnindexed()) 923*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 924*0fca6ea1SDimitry Andric "IsUnindexed requires IsLoad or IsStore"); 925*0fca6ea1SDimitry Andric 926*0fca6ea1SDimitry Andric Record *ScalarMemoryVT = getScalarMemoryVT(); 927*0fca6ea1SDimitry Andric 928*0fca6ea1SDimitry Andric if (ScalarMemoryVT) 929*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 930*0fca6ea1SDimitry Andric "ScalarMemoryVT requires IsLoad or IsStore"); 931*0fca6ea1SDimitry Andric } 932*0fca6ea1SDimitry Andric 933*0fca6ea1SDimitry Andric if (isLoad() + isStore() + isAtomic() > 1) 934*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 935*0fca6ea1SDimitry Andric "IsLoad, IsStore, and IsAtomic are mutually exclusive"); 936*0fca6ea1SDimitry Andric 937*0fca6ea1SDimitry Andric if (isLoad()) { 938*0fca6ea1SDimitry Andric if (!isUnindexed() && !isNonExtLoad() && !isAnyExtLoad() && 939*0fca6ea1SDimitry Andric !isSignExtLoad() && !isZeroExtLoad() && getMemoryVT() == nullptr && 940*0fca6ea1SDimitry Andric getScalarMemoryVT() == nullptr && getAddressSpaces() == nullptr && 941*0fca6ea1SDimitry Andric getMinAlignment() < 1) 942*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 943*0fca6ea1SDimitry Andric "IsLoad cannot be used by itself"); 944*0fca6ea1SDimitry Andric } else { 945*0fca6ea1SDimitry Andric if (isNonExtLoad()) 946*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 947*0fca6ea1SDimitry Andric "IsNonExtLoad requires IsLoad"); 948*0fca6ea1SDimitry Andric if (isAnyExtLoad()) 949*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 950*0fca6ea1SDimitry Andric "IsAnyExtLoad requires IsLoad"); 951*0fca6ea1SDimitry Andric 952*0fca6ea1SDimitry Andric if (!isAtomic()) { 953*0fca6ea1SDimitry Andric if (isSignExtLoad()) 954*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 955*0fca6ea1SDimitry Andric "IsSignExtLoad requires IsLoad or IsAtomic"); 956*0fca6ea1SDimitry Andric if (isZeroExtLoad()) 957*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 958*0fca6ea1SDimitry Andric "IsZeroExtLoad requires IsLoad or IsAtomic"); 959*0fca6ea1SDimitry Andric } 960*0fca6ea1SDimitry Andric } 961*0fca6ea1SDimitry Andric 962*0fca6ea1SDimitry Andric if (isStore()) { 963*0fca6ea1SDimitry Andric if (!isUnindexed() && !isTruncStore() && !isNonTruncStore() && 964*0fca6ea1SDimitry Andric getMemoryVT() == nullptr && getScalarMemoryVT() == nullptr && 965*0fca6ea1SDimitry Andric getAddressSpaces() == nullptr && getMinAlignment() < 1) 966*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 967*0fca6ea1SDimitry Andric "IsStore cannot be used by itself"); 968*0fca6ea1SDimitry Andric } else { 969*0fca6ea1SDimitry Andric if (isNonTruncStore()) 970*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 971*0fca6ea1SDimitry Andric "IsNonTruncStore requires IsStore"); 972*0fca6ea1SDimitry Andric if (isTruncStore()) 973*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 974*0fca6ea1SDimitry Andric "IsTruncStore requires IsStore"); 975*0fca6ea1SDimitry Andric } 976*0fca6ea1SDimitry Andric 977*0fca6ea1SDimitry Andric if (isAtomic()) { 978*0fca6ea1SDimitry Andric if (getMemoryVT() == nullptr && !isAtomicOrderingMonotonic() && 979*0fca6ea1SDimitry Andric getAddressSpaces() == nullptr && 980*0fca6ea1SDimitry Andric // FIXME: Should atomic loads be IsLoad, IsAtomic, or both? 981*0fca6ea1SDimitry Andric !isZeroExtLoad() && !isSignExtLoad() && !isAtomicOrderingAcquire() && 982*0fca6ea1SDimitry Andric !isAtomicOrderingRelease() && !isAtomicOrderingAcquireRelease() && 983*0fca6ea1SDimitry Andric !isAtomicOrderingSequentiallyConsistent() && 984*0fca6ea1SDimitry Andric !isAtomicOrderingAcquireOrStronger() && 985*0fca6ea1SDimitry Andric !isAtomicOrderingReleaseOrStronger() && 986*0fca6ea1SDimitry Andric !isAtomicOrderingWeakerThanAcquire() && 987*0fca6ea1SDimitry Andric !isAtomicOrderingWeakerThanRelease()) 988*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 989*0fca6ea1SDimitry Andric "IsAtomic cannot be used by itself"); 990*0fca6ea1SDimitry Andric } else { 991*0fca6ea1SDimitry Andric if (isAtomicOrderingMonotonic()) 992*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 993*0fca6ea1SDimitry Andric "IsAtomicOrderingMonotonic requires IsAtomic"); 994*0fca6ea1SDimitry Andric if (isAtomicOrderingAcquire()) 995*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 996*0fca6ea1SDimitry Andric "IsAtomicOrderingAcquire requires IsAtomic"); 997*0fca6ea1SDimitry Andric if (isAtomicOrderingRelease()) 998*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 999*0fca6ea1SDimitry Andric "IsAtomicOrderingRelease requires IsAtomic"); 1000*0fca6ea1SDimitry Andric if (isAtomicOrderingAcquireRelease()) 1001*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 1002*0fca6ea1SDimitry Andric "IsAtomicOrderingAcquireRelease requires IsAtomic"); 1003*0fca6ea1SDimitry Andric if (isAtomicOrderingSequentiallyConsistent()) 1004*0fca6ea1SDimitry Andric PrintFatalError( 1005*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 1006*0fca6ea1SDimitry Andric "IsAtomicOrderingSequentiallyConsistent requires IsAtomic"); 1007*0fca6ea1SDimitry Andric if (isAtomicOrderingAcquireOrStronger()) 1008*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 1009*0fca6ea1SDimitry Andric "IsAtomicOrderingAcquireOrStronger requires IsAtomic"); 1010*0fca6ea1SDimitry Andric if (isAtomicOrderingReleaseOrStronger()) 1011*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 1012*0fca6ea1SDimitry Andric "IsAtomicOrderingReleaseOrStronger requires IsAtomic"); 1013*0fca6ea1SDimitry Andric if (isAtomicOrderingWeakerThanAcquire()) 1014*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 1015*0fca6ea1SDimitry Andric "IsAtomicOrderingWeakerThanAcquire requires IsAtomic"); 1016*0fca6ea1SDimitry Andric } 1017*0fca6ea1SDimitry Andric 1018*0fca6ea1SDimitry Andric if (isLoad() || isStore() || isAtomic()) { 1019*0fca6ea1SDimitry Andric if (ListInit *AddressSpaces = getAddressSpaces()) { 1020*0fca6ea1SDimitry Andric Code += "unsigned AddrSpace = cast<MemSDNode>(N)->getAddressSpace();\n" 1021*0fca6ea1SDimitry Andric " if ("; 1022*0fca6ea1SDimitry Andric 1023*0fca6ea1SDimitry Andric ListSeparator LS(" && "); 1024*0fca6ea1SDimitry Andric for (Init *Val : AddressSpaces->getValues()) { 1025*0fca6ea1SDimitry Andric Code += LS; 1026*0fca6ea1SDimitry Andric 1027*0fca6ea1SDimitry Andric IntInit *IntVal = dyn_cast<IntInit>(Val); 1028*0fca6ea1SDimitry Andric if (!IntVal) { 1029*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 1030*0fca6ea1SDimitry Andric "AddressSpaces element must be integer"); 1031*0fca6ea1SDimitry Andric } 1032*0fca6ea1SDimitry Andric 1033*0fca6ea1SDimitry Andric Code += "AddrSpace != " + utostr(IntVal->getValue()); 1034*0fca6ea1SDimitry Andric } 1035*0fca6ea1SDimitry Andric 1036*0fca6ea1SDimitry Andric Code += ")\nreturn false;\n"; 1037*0fca6ea1SDimitry Andric } 1038*0fca6ea1SDimitry Andric 1039*0fca6ea1SDimitry Andric int64_t MinAlign = getMinAlignment(); 1040*0fca6ea1SDimitry Andric if (MinAlign > 0) { 1041*0fca6ea1SDimitry Andric Code += "if (cast<MemSDNode>(N)->getAlign() < Align("; 1042*0fca6ea1SDimitry Andric Code += utostr(MinAlign); 1043*0fca6ea1SDimitry Andric Code += "))\nreturn false;\n"; 1044*0fca6ea1SDimitry Andric } 1045*0fca6ea1SDimitry Andric 1046*0fca6ea1SDimitry Andric Record *MemoryVT = getMemoryVT(); 1047*0fca6ea1SDimitry Andric 1048*0fca6ea1SDimitry Andric if (MemoryVT) 1049*0fca6ea1SDimitry Andric Code += ("if (cast<MemSDNode>(N)->getMemoryVT() != MVT::" + 1050*0fca6ea1SDimitry Andric MemoryVT->getName() + ") return false;\n") 1051*0fca6ea1SDimitry Andric .str(); 1052*0fca6ea1SDimitry Andric } 1053*0fca6ea1SDimitry Andric 1054*0fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingMonotonic()) 1055*0fca6ea1SDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != " 1056*0fca6ea1SDimitry Andric "AtomicOrdering::Monotonic) return false;\n"; 1057*0fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingAcquire()) 1058*0fca6ea1SDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != " 1059*0fca6ea1SDimitry Andric "AtomicOrdering::Acquire) return false;\n"; 1060*0fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingRelease()) 1061*0fca6ea1SDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != " 1062*0fca6ea1SDimitry Andric "AtomicOrdering::Release) return false;\n"; 1063*0fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingAcquireRelease()) 1064*0fca6ea1SDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != " 1065*0fca6ea1SDimitry Andric "AtomicOrdering::AcquireRelease) return false;\n"; 1066*0fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingSequentiallyConsistent()) 1067*0fca6ea1SDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != " 1068*0fca6ea1SDimitry Andric "AtomicOrdering::SequentiallyConsistent) return false;\n"; 1069*0fca6ea1SDimitry Andric 1070*0fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingAcquireOrStronger()) 1071*0fca6ea1SDimitry Andric Code += 1072*0fca6ea1SDimitry Andric "if (!isAcquireOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) " 1073*0fca6ea1SDimitry Andric "return false;\n"; 1074*0fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingWeakerThanAcquire()) 1075*0fca6ea1SDimitry Andric Code += 1076*0fca6ea1SDimitry Andric "if (isAcquireOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) " 1077*0fca6ea1SDimitry Andric "return false;\n"; 1078*0fca6ea1SDimitry Andric 1079*0fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingReleaseOrStronger()) 1080*0fca6ea1SDimitry Andric Code += 1081*0fca6ea1SDimitry Andric "if (!isReleaseOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) " 1082*0fca6ea1SDimitry Andric "return false;\n"; 1083*0fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingWeakerThanRelease()) 1084*0fca6ea1SDimitry Andric Code += 1085*0fca6ea1SDimitry Andric "if (isReleaseOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) " 1086*0fca6ea1SDimitry Andric "return false;\n"; 1087*0fca6ea1SDimitry Andric 1088*0fca6ea1SDimitry Andric // TODO: Handle atomic sextload/zextload normally when ATOMIC_LOAD is removed. 1089*0fca6ea1SDimitry Andric if (isAtomic() && (isZeroExtLoad() || isSignExtLoad())) 1090*0fca6ea1SDimitry Andric Code += "return false;\n"; 1091*0fca6ea1SDimitry Andric 1092*0fca6ea1SDimitry Andric if (isLoad() || isStore()) { 1093*0fca6ea1SDimitry Andric StringRef SDNodeName = isLoad() ? "LoadSDNode" : "StoreSDNode"; 1094*0fca6ea1SDimitry Andric 1095*0fca6ea1SDimitry Andric if (isUnindexed()) 1096*0fca6ea1SDimitry Andric Code += ("if (cast<" + SDNodeName + 1097*0fca6ea1SDimitry Andric ">(N)->getAddressingMode() != ISD::UNINDEXED) " 1098*0fca6ea1SDimitry Andric "return false;\n") 1099*0fca6ea1SDimitry Andric .str(); 1100*0fca6ea1SDimitry Andric 1101*0fca6ea1SDimitry Andric if (isLoad()) { 1102*0fca6ea1SDimitry Andric if ((isNonExtLoad() + isAnyExtLoad() + isSignExtLoad() + 1103*0fca6ea1SDimitry Andric isZeroExtLoad()) > 1) 1104*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 1105*0fca6ea1SDimitry Andric "IsNonExtLoad, IsAnyExtLoad, IsSignExtLoad, and " 1106*0fca6ea1SDimitry Andric "IsZeroExtLoad are mutually exclusive"); 1107*0fca6ea1SDimitry Andric if (isNonExtLoad()) 1108*0fca6ea1SDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != " 1109*0fca6ea1SDimitry Andric "ISD::NON_EXTLOAD) return false;\n"; 1110*0fca6ea1SDimitry Andric if (isAnyExtLoad()) 1111*0fca6ea1SDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::EXTLOAD) " 1112*0fca6ea1SDimitry Andric "return false;\n"; 1113*0fca6ea1SDimitry Andric if (isSignExtLoad()) 1114*0fca6ea1SDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::SEXTLOAD) " 1115*0fca6ea1SDimitry Andric "return false;\n"; 1116*0fca6ea1SDimitry Andric if (isZeroExtLoad()) 1117*0fca6ea1SDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::ZEXTLOAD) " 1118*0fca6ea1SDimitry Andric "return false;\n"; 1119*0fca6ea1SDimitry Andric } else { 1120*0fca6ea1SDimitry Andric if ((isNonTruncStore() + isTruncStore()) > 1) 1121*0fca6ea1SDimitry Andric PrintFatalError( 1122*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 1123*0fca6ea1SDimitry Andric "IsNonTruncStore, and IsTruncStore are mutually exclusive"); 1124*0fca6ea1SDimitry Andric if (isNonTruncStore()) 1125*0fca6ea1SDimitry Andric Code += 1126*0fca6ea1SDimitry Andric " if (cast<StoreSDNode>(N)->isTruncatingStore()) return false;\n"; 1127*0fca6ea1SDimitry Andric if (isTruncStore()) 1128*0fca6ea1SDimitry Andric Code += 1129*0fca6ea1SDimitry Andric " if (!cast<StoreSDNode>(N)->isTruncatingStore()) return false;\n"; 1130*0fca6ea1SDimitry Andric } 1131*0fca6ea1SDimitry Andric 1132*0fca6ea1SDimitry Andric Record *ScalarMemoryVT = getScalarMemoryVT(); 1133*0fca6ea1SDimitry Andric 1134*0fca6ea1SDimitry Andric if (ScalarMemoryVT) 1135*0fca6ea1SDimitry Andric Code += ("if (cast<" + SDNodeName + 1136*0fca6ea1SDimitry Andric ">(N)->getMemoryVT().getScalarType() != MVT::" + 1137*0fca6ea1SDimitry Andric ScalarMemoryVT->getName() + ") return false;\n") 1138*0fca6ea1SDimitry Andric .str(); 1139*0fca6ea1SDimitry Andric } 1140*0fca6ea1SDimitry Andric 1141*0fca6ea1SDimitry Andric if (hasNoUse()) 1142*0fca6ea1SDimitry Andric Code += "if (!SDValue(N, 0).use_empty()) return false;\n"; 1143*0fca6ea1SDimitry Andric if (hasOneUse()) 1144*0fca6ea1SDimitry Andric Code += "if (!SDValue(N, 0).hasOneUse()) return false;\n"; 1145*0fca6ea1SDimitry Andric 1146*0fca6ea1SDimitry Andric std::string PredicateCode = 1147*0fca6ea1SDimitry Andric std::string(PatFragRec->getRecord()->getValueAsString("PredicateCode")); 1148*0fca6ea1SDimitry Andric 1149*0fca6ea1SDimitry Andric Code += PredicateCode; 1150*0fca6ea1SDimitry Andric 1151*0fca6ea1SDimitry Andric if (PredicateCode.empty() && !Code.empty()) 1152*0fca6ea1SDimitry Andric Code += "return true;\n"; 1153*0fca6ea1SDimitry Andric 1154*0fca6ea1SDimitry Andric return Code; 1155*0fca6ea1SDimitry Andric } 1156*0fca6ea1SDimitry Andric 1157*0fca6ea1SDimitry Andric bool TreePredicateFn::hasImmCode() const { 1158*0fca6ea1SDimitry Andric return !PatFragRec->getRecord()->getValueAsString("ImmediateCode").empty(); 1159*0fca6ea1SDimitry Andric } 1160*0fca6ea1SDimitry Andric 1161*0fca6ea1SDimitry Andric std::string TreePredicateFn::getImmCode() const { 1162*0fca6ea1SDimitry Andric return std::string( 1163*0fca6ea1SDimitry Andric PatFragRec->getRecord()->getValueAsString("ImmediateCode")); 1164*0fca6ea1SDimitry Andric } 1165*0fca6ea1SDimitry Andric 1166*0fca6ea1SDimitry Andric bool TreePredicateFn::immCodeUsesAPInt() const { 1167*0fca6ea1SDimitry Andric return getOrigPatFragRecord()->getRecord()->getValueAsBit("IsAPInt"); 1168*0fca6ea1SDimitry Andric } 1169*0fca6ea1SDimitry Andric 1170*0fca6ea1SDimitry Andric bool TreePredicateFn::immCodeUsesAPFloat() const { 1171*0fca6ea1SDimitry Andric bool Unset; 1172*0fca6ea1SDimitry Andric // The return value will be false when IsAPFloat is unset. 1173*0fca6ea1SDimitry Andric return getOrigPatFragRecord()->getRecord()->getValueAsBitOrUnset("IsAPFloat", 1174*0fca6ea1SDimitry Andric Unset); 1175*0fca6ea1SDimitry Andric } 1176*0fca6ea1SDimitry Andric 1177*0fca6ea1SDimitry Andric bool TreePredicateFn::isPredefinedPredicateEqualTo(StringRef Field, 1178*0fca6ea1SDimitry Andric bool Value) const { 1179*0fca6ea1SDimitry Andric bool Unset; 1180*0fca6ea1SDimitry Andric bool Result = 1181*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getValueAsBitOrUnset(Field, Unset); 1182*0fca6ea1SDimitry Andric if (Unset) 1183*0fca6ea1SDimitry Andric return false; 1184*0fca6ea1SDimitry Andric return Result == Value; 1185*0fca6ea1SDimitry Andric } 1186*0fca6ea1SDimitry Andric bool TreePredicateFn::usesOperands() const { 1187*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("PredicateCodeUsesOperands", true); 1188*0fca6ea1SDimitry Andric } 1189*0fca6ea1SDimitry Andric bool TreePredicateFn::hasNoUse() const { 1190*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("HasNoUse", true); 1191*0fca6ea1SDimitry Andric } 1192*0fca6ea1SDimitry Andric bool TreePredicateFn::hasOneUse() const { 1193*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("HasOneUse", true); 1194*0fca6ea1SDimitry Andric } 1195*0fca6ea1SDimitry Andric bool TreePredicateFn::isLoad() const { 1196*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsLoad", true); 1197*0fca6ea1SDimitry Andric } 1198*0fca6ea1SDimitry Andric bool TreePredicateFn::isStore() const { 1199*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsStore", true); 1200*0fca6ea1SDimitry Andric } 1201*0fca6ea1SDimitry Andric bool TreePredicateFn::isAtomic() const { 1202*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomic", true); 1203*0fca6ea1SDimitry Andric } 1204*0fca6ea1SDimitry Andric bool TreePredicateFn::isUnindexed() const { 1205*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsUnindexed", true); 1206*0fca6ea1SDimitry Andric } 1207*0fca6ea1SDimitry Andric bool TreePredicateFn::isNonExtLoad() const { 1208*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsNonExtLoad", true); 1209*0fca6ea1SDimitry Andric } 1210*0fca6ea1SDimitry Andric bool TreePredicateFn::isAnyExtLoad() const { 1211*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAnyExtLoad", true); 1212*0fca6ea1SDimitry Andric } 1213*0fca6ea1SDimitry Andric bool TreePredicateFn::isSignExtLoad() const { 1214*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsSignExtLoad", true); 1215*0fca6ea1SDimitry Andric } 1216*0fca6ea1SDimitry Andric bool TreePredicateFn::isZeroExtLoad() const { 1217*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsZeroExtLoad", true); 1218*0fca6ea1SDimitry Andric } 1219*0fca6ea1SDimitry Andric bool TreePredicateFn::isNonTruncStore() const { 1220*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsTruncStore", false); 1221*0fca6ea1SDimitry Andric } 1222*0fca6ea1SDimitry Andric bool TreePredicateFn::isTruncStore() const { 1223*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsTruncStore", true); 1224*0fca6ea1SDimitry Andric } 1225*0fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingMonotonic() const { 1226*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingMonotonic", true); 1227*0fca6ea1SDimitry Andric } 1228*0fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingAcquire() const { 1229*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquire", true); 1230*0fca6ea1SDimitry Andric } 1231*0fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingRelease() const { 1232*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingRelease", true); 1233*0fca6ea1SDimitry Andric } 1234*0fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingAcquireRelease() const { 1235*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireRelease", true); 1236*0fca6ea1SDimitry Andric } 1237*0fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingSequentiallyConsistent() const { 1238*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingSequentiallyConsistent", 1239*0fca6ea1SDimitry Andric true); 1240*0fca6ea1SDimitry Andric } 1241*0fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingAcquireOrStronger() const { 1242*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireOrStronger", 1243*0fca6ea1SDimitry Andric true); 1244*0fca6ea1SDimitry Andric } 1245*0fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingWeakerThanAcquire() const { 1246*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireOrStronger", 1247*0fca6ea1SDimitry Andric false); 1248*0fca6ea1SDimitry Andric } 1249*0fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingReleaseOrStronger() const { 1250*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingReleaseOrStronger", 1251*0fca6ea1SDimitry Andric true); 1252*0fca6ea1SDimitry Andric } 1253*0fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingWeakerThanRelease() const { 1254*0fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingReleaseOrStronger", 1255*0fca6ea1SDimitry Andric false); 1256*0fca6ea1SDimitry Andric } 1257*0fca6ea1SDimitry Andric Record *TreePredicateFn::getMemoryVT() const { 1258*0fca6ea1SDimitry Andric Record *R = getOrigPatFragRecord()->getRecord(); 1259*0fca6ea1SDimitry Andric if (R->isValueUnset("MemoryVT")) 1260*0fca6ea1SDimitry Andric return nullptr; 1261*0fca6ea1SDimitry Andric return R->getValueAsDef("MemoryVT"); 1262*0fca6ea1SDimitry Andric } 1263*0fca6ea1SDimitry Andric 1264*0fca6ea1SDimitry Andric ListInit *TreePredicateFn::getAddressSpaces() const { 1265*0fca6ea1SDimitry Andric Record *R = getOrigPatFragRecord()->getRecord(); 1266*0fca6ea1SDimitry Andric if (R->isValueUnset("AddressSpaces")) 1267*0fca6ea1SDimitry Andric return nullptr; 1268*0fca6ea1SDimitry Andric return R->getValueAsListInit("AddressSpaces"); 1269*0fca6ea1SDimitry Andric } 1270*0fca6ea1SDimitry Andric 1271*0fca6ea1SDimitry Andric int64_t TreePredicateFn::getMinAlignment() const { 1272*0fca6ea1SDimitry Andric Record *R = getOrigPatFragRecord()->getRecord(); 1273*0fca6ea1SDimitry Andric if (R->isValueUnset("MinAlignment")) 1274*0fca6ea1SDimitry Andric return 0; 1275*0fca6ea1SDimitry Andric return R->getValueAsInt("MinAlignment"); 1276*0fca6ea1SDimitry Andric } 1277*0fca6ea1SDimitry Andric 1278*0fca6ea1SDimitry Andric Record *TreePredicateFn::getScalarMemoryVT() const { 1279*0fca6ea1SDimitry Andric Record *R = getOrigPatFragRecord()->getRecord(); 1280*0fca6ea1SDimitry Andric if (R->isValueUnset("ScalarMemoryVT")) 1281*0fca6ea1SDimitry Andric return nullptr; 1282*0fca6ea1SDimitry Andric return R->getValueAsDef("ScalarMemoryVT"); 1283*0fca6ea1SDimitry Andric } 1284*0fca6ea1SDimitry Andric bool TreePredicateFn::hasGISelPredicateCode() const { 1285*0fca6ea1SDimitry Andric return !PatFragRec->getRecord() 1286*0fca6ea1SDimitry Andric ->getValueAsString("GISelPredicateCode") 1287*0fca6ea1SDimitry Andric .empty(); 1288*0fca6ea1SDimitry Andric } 1289*0fca6ea1SDimitry Andric std::string TreePredicateFn::getGISelPredicateCode() const { 1290*0fca6ea1SDimitry Andric return std::string( 1291*0fca6ea1SDimitry Andric PatFragRec->getRecord()->getValueAsString("GISelPredicateCode")); 1292*0fca6ea1SDimitry Andric } 1293*0fca6ea1SDimitry Andric 1294*0fca6ea1SDimitry Andric StringRef TreePredicateFn::getImmType() const { 1295*0fca6ea1SDimitry Andric if (immCodeUsesAPInt()) 1296*0fca6ea1SDimitry Andric return "const APInt &"; 1297*0fca6ea1SDimitry Andric if (immCodeUsesAPFloat()) 1298*0fca6ea1SDimitry Andric return "const APFloat &"; 1299*0fca6ea1SDimitry Andric return "int64_t"; 1300*0fca6ea1SDimitry Andric } 1301*0fca6ea1SDimitry Andric 1302*0fca6ea1SDimitry Andric StringRef TreePredicateFn::getImmTypeIdentifier() const { 1303*0fca6ea1SDimitry Andric if (immCodeUsesAPInt()) 1304*0fca6ea1SDimitry Andric return "APInt"; 1305*0fca6ea1SDimitry Andric if (immCodeUsesAPFloat()) 1306*0fca6ea1SDimitry Andric return "APFloat"; 1307*0fca6ea1SDimitry Andric return "I64"; 1308*0fca6ea1SDimitry Andric } 1309*0fca6ea1SDimitry Andric 1310*0fca6ea1SDimitry Andric /// isAlwaysTrue - Return true if this is a noop predicate. 1311*0fca6ea1SDimitry Andric bool TreePredicateFn::isAlwaysTrue() const { 1312*0fca6ea1SDimitry Andric return !hasPredCode() && !hasImmCode(); 1313*0fca6ea1SDimitry Andric } 1314*0fca6ea1SDimitry Andric 1315*0fca6ea1SDimitry Andric /// Return the name to use in the generated code to reference this, this is 1316*0fca6ea1SDimitry Andric /// "Predicate_foo" if from a pattern fragment "foo". 1317*0fca6ea1SDimitry Andric std::string TreePredicateFn::getFnName() const { 1318*0fca6ea1SDimitry Andric return "Predicate_" + PatFragRec->getRecord()->getName().str(); 1319*0fca6ea1SDimitry Andric } 1320*0fca6ea1SDimitry Andric 1321*0fca6ea1SDimitry Andric /// getCodeToRunOnSDNode - Return the code for the function body that 1322*0fca6ea1SDimitry Andric /// evaluates this predicate. The argument is expected to be in "Node", 1323*0fca6ea1SDimitry Andric /// not N. This handles casting and conversion to a concrete node type as 1324*0fca6ea1SDimitry Andric /// appropriate. 1325*0fca6ea1SDimitry Andric std::string TreePredicateFn::getCodeToRunOnSDNode() const { 1326*0fca6ea1SDimitry Andric // Handle immediate predicates first. 1327*0fca6ea1SDimitry Andric std::string ImmCode = getImmCode(); 1328*0fca6ea1SDimitry Andric if (!ImmCode.empty()) { 1329*0fca6ea1SDimitry Andric if (isLoad()) 1330*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 1331*0fca6ea1SDimitry Andric "IsLoad cannot be used with ImmLeaf or its subclasses"); 1332*0fca6ea1SDimitry Andric if (isStore()) 1333*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 1334*0fca6ea1SDimitry Andric "IsStore cannot be used with ImmLeaf or its subclasses"); 1335*0fca6ea1SDimitry Andric if (isUnindexed()) 1336*0fca6ea1SDimitry Andric PrintFatalError( 1337*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 1338*0fca6ea1SDimitry Andric "IsUnindexed cannot be used with ImmLeaf or its subclasses"); 1339*0fca6ea1SDimitry Andric if (isNonExtLoad()) 1340*0fca6ea1SDimitry Andric PrintFatalError( 1341*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 1342*0fca6ea1SDimitry Andric "IsNonExtLoad cannot be used with ImmLeaf or its subclasses"); 1343*0fca6ea1SDimitry Andric if (isAnyExtLoad()) 1344*0fca6ea1SDimitry Andric PrintFatalError( 1345*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 1346*0fca6ea1SDimitry Andric "IsAnyExtLoad cannot be used with ImmLeaf or its subclasses"); 1347*0fca6ea1SDimitry Andric if (isSignExtLoad()) 1348*0fca6ea1SDimitry Andric PrintFatalError( 1349*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 1350*0fca6ea1SDimitry Andric "IsSignExtLoad cannot be used with ImmLeaf or its subclasses"); 1351*0fca6ea1SDimitry Andric if (isZeroExtLoad()) 1352*0fca6ea1SDimitry Andric PrintFatalError( 1353*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 1354*0fca6ea1SDimitry Andric "IsZeroExtLoad cannot be used with ImmLeaf or its subclasses"); 1355*0fca6ea1SDimitry Andric if (isNonTruncStore()) 1356*0fca6ea1SDimitry Andric PrintFatalError( 1357*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 1358*0fca6ea1SDimitry Andric "IsNonTruncStore cannot be used with ImmLeaf or its subclasses"); 1359*0fca6ea1SDimitry Andric if (isTruncStore()) 1360*0fca6ea1SDimitry Andric PrintFatalError( 1361*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 1362*0fca6ea1SDimitry Andric "IsTruncStore cannot be used with ImmLeaf or its subclasses"); 1363*0fca6ea1SDimitry Andric if (getMemoryVT()) 1364*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 1365*0fca6ea1SDimitry Andric "MemoryVT cannot be used with ImmLeaf or its subclasses"); 1366*0fca6ea1SDimitry Andric if (getScalarMemoryVT()) 1367*0fca6ea1SDimitry Andric PrintFatalError( 1368*0fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 1369*0fca6ea1SDimitry Andric "ScalarMemoryVT cannot be used with ImmLeaf or its subclasses"); 1370*0fca6ea1SDimitry Andric 1371*0fca6ea1SDimitry Andric std::string Result = (" " + getImmType() + " Imm = ").str(); 1372*0fca6ea1SDimitry Andric if (immCodeUsesAPFloat()) 1373*0fca6ea1SDimitry Andric Result += "cast<ConstantFPSDNode>(Node)->getValueAPF();\n"; 1374*0fca6ea1SDimitry Andric else if (immCodeUsesAPInt()) 1375*0fca6ea1SDimitry Andric Result += "Node->getAsAPIntVal();\n"; 1376*0fca6ea1SDimitry Andric else 1377*0fca6ea1SDimitry Andric Result += "cast<ConstantSDNode>(Node)->getSExtValue();\n"; 1378*0fca6ea1SDimitry Andric return Result + ImmCode; 1379*0fca6ea1SDimitry Andric } 1380*0fca6ea1SDimitry Andric 1381*0fca6ea1SDimitry Andric // Handle arbitrary node predicates. 1382*0fca6ea1SDimitry Andric assert(hasPredCode() && "Don't have any predicate code!"); 1383*0fca6ea1SDimitry Andric 1384*0fca6ea1SDimitry Andric // If this is using PatFrags, there are multiple trees to search. They should 1385*0fca6ea1SDimitry Andric // all have the same class. FIXME: Is there a way to find a common 1386*0fca6ea1SDimitry Andric // superclass? 1387*0fca6ea1SDimitry Andric StringRef ClassName; 1388*0fca6ea1SDimitry Andric for (const auto &Tree : PatFragRec->getTrees()) { 1389*0fca6ea1SDimitry Andric StringRef TreeClassName; 1390*0fca6ea1SDimitry Andric if (Tree->isLeaf()) 1391*0fca6ea1SDimitry Andric TreeClassName = "SDNode"; 1392*0fca6ea1SDimitry Andric else { 1393*0fca6ea1SDimitry Andric Record *Op = Tree->getOperator(); 1394*0fca6ea1SDimitry Andric const SDNodeInfo &Info = PatFragRec->getDAGPatterns().getSDNodeInfo(Op); 1395*0fca6ea1SDimitry Andric TreeClassName = Info.getSDClassName(); 1396*0fca6ea1SDimitry Andric } 1397*0fca6ea1SDimitry Andric 1398*0fca6ea1SDimitry Andric if (ClassName.empty()) 1399*0fca6ea1SDimitry Andric ClassName = TreeClassName; 1400*0fca6ea1SDimitry Andric else if (ClassName != TreeClassName) { 1401*0fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 1402*0fca6ea1SDimitry Andric "PatFrags trees do not have consistent class"); 1403*0fca6ea1SDimitry Andric } 1404*0fca6ea1SDimitry Andric } 1405*0fca6ea1SDimitry Andric 1406*0fca6ea1SDimitry Andric std::string Result; 1407*0fca6ea1SDimitry Andric if (ClassName == "SDNode") 1408*0fca6ea1SDimitry Andric Result = " SDNode *N = Node;\n"; 1409*0fca6ea1SDimitry Andric else 1410*0fca6ea1SDimitry Andric Result = " auto *N = cast<" + ClassName.str() + ">(Node);\n"; 1411*0fca6ea1SDimitry Andric 1412*0fca6ea1SDimitry Andric return (Twine(Result) + " (void)N;\n" + getPredCode()).str(); 1413*0fca6ea1SDimitry Andric } 1414*0fca6ea1SDimitry Andric 1415*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 1416*0fca6ea1SDimitry Andric // PatternToMatch implementation 1417*0fca6ea1SDimitry Andric // 1418*0fca6ea1SDimitry Andric 1419*0fca6ea1SDimitry Andric static bool isImmAllOnesAllZerosMatch(const TreePatternNode &P) { 1420*0fca6ea1SDimitry Andric if (!P.isLeaf()) 1421*0fca6ea1SDimitry Andric return false; 1422*0fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(P.getLeafValue()); 1423*0fca6ea1SDimitry Andric if (!DI) 1424*0fca6ea1SDimitry Andric return false; 1425*0fca6ea1SDimitry Andric 1426*0fca6ea1SDimitry Andric Record *R = DI->getDef(); 1427*0fca6ea1SDimitry Andric return R->getName() == "immAllOnesV" || R->getName() == "immAllZerosV"; 1428*0fca6ea1SDimitry Andric } 1429*0fca6ea1SDimitry Andric 1430*0fca6ea1SDimitry Andric /// getPatternSize - Return the 'size' of this pattern. We want to match large 1431*0fca6ea1SDimitry Andric /// patterns before small ones. This is used to determine the size of a 1432*0fca6ea1SDimitry Andric /// pattern. 1433*0fca6ea1SDimitry Andric static unsigned getPatternSize(const TreePatternNode &P, 1434*0fca6ea1SDimitry Andric const CodeGenDAGPatterns &CGP) { 1435*0fca6ea1SDimitry Andric unsigned Size = 3; // The node itself. 1436*0fca6ea1SDimitry Andric // If the root node is a ConstantSDNode, increases its size. 1437*0fca6ea1SDimitry Andric // e.g. (set R32:$dst, 0). 1438*0fca6ea1SDimitry Andric if (P.isLeaf() && isa<IntInit>(P.getLeafValue())) 1439*0fca6ea1SDimitry Andric Size += 2; 1440*0fca6ea1SDimitry Andric 1441*0fca6ea1SDimitry Andric if (const ComplexPattern *AM = P.getComplexPatternInfo(CGP)) { 1442*0fca6ea1SDimitry Andric Size += AM->getComplexity(); 1443*0fca6ea1SDimitry Andric // We don't want to count any children twice, so return early. 1444*0fca6ea1SDimitry Andric return Size; 1445*0fca6ea1SDimitry Andric } 1446*0fca6ea1SDimitry Andric 1447*0fca6ea1SDimitry Andric // If this node has some predicate function that must match, it adds to the 1448*0fca6ea1SDimitry Andric // complexity of this node. 1449*0fca6ea1SDimitry Andric if (!P.getPredicateCalls().empty()) 1450*0fca6ea1SDimitry Andric ++Size; 1451*0fca6ea1SDimitry Andric 1452*0fca6ea1SDimitry Andric // Count children in the count if they are also nodes. 1453*0fca6ea1SDimitry Andric for (unsigned i = 0, e = P.getNumChildren(); i != e; ++i) { 1454*0fca6ea1SDimitry Andric const TreePatternNode &Child = P.getChild(i); 1455*0fca6ea1SDimitry Andric if (!Child.isLeaf() && Child.getNumTypes()) { 1456*0fca6ea1SDimitry Andric const TypeSetByHwMode &T0 = Child.getExtType(0); 1457*0fca6ea1SDimitry Andric // At this point, all variable type sets should be simple, i.e. only 1458*0fca6ea1SDimitry Andric // have a default mode. 1459*0fca6ea1SDimitry Andric if (T0.getMachineValueType() != MVT::Other) { 1460*0fca6ea1SDimitry Andric Size += getPatternSize(Child, CGP); 1461*0fca6ea1SDimitry Andric continue; 1462*0fca6ea1SDimitry Andric } 1463*0fca6ea1SDimitry Andric } 1464*0fca6ea1SDimitry Andric if (Child.isLeaf()) { 1465*0fca6ea1SDimitry Andric if (isa<IntInit>(Child.getLeafValue())) 1466*0fca6ea1SDimitry Andric Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). 1467*0fca6ea1SDimitry Andric else if (Child.getComplexPatternInfo(CGP)) 1468*0fca6ea1SDimitry Andric Size += getPatternSize(Child, CGP); 1469*0fca6ea1SDimitry Andric else if (isImmAllOnesAllZerosMatch(Child)) 1470*0fca6ea1SDimitry Andric Size += 4; // Matches a build_vector(+3) and a predicate (+1). 1471*0fca6ea1SDimitry Andric else if (!Child.getPredicateCalls().empty()) 1472*0fca6ea1SDimitry Andric ++Size; 1473*0fca6ea1SDimitry Andric } 1474*0fca6ea1SDimitry Andric } 1475*0fca6ea1SDimitry Andric 1476*0fca6ea1SDimitry Andric return Size; 1477*0fca6ea1SDimitry Andric } 1478*0fca6ea1SDimitry Andric 1479*0fca6ea1SDimitry Andric /// Compute the complexity metric for the input pattern. This roughly 1480*0fca6ea1SDimitry Andric /// corresponds to the number of nodes that are covered. 1481*0fca6ea1SDimitry Andric int PatternToMatch::getPatternComplexity(const CodeGenDAGPatterns &CGP) const { 1482*0fca6ea1SDimitry Andric return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity(); 1483*0fca6ea1SDimitry Andric } 1484*0fca6ea1SDimitry Andric 1485*0fca6ea1SDimitry Andric void PatternToMatch::getPredicateRecords( 1486*0fca6ea1SDimitry Andric SmallVectorImpl<Record *> &PredicateRecs) const { 1487*0fca6ea1SDimitry Andric for (Init *I : Predicates->getValues()) { 1488*0fca6ea1SDimitry Andric if (DefInit *Pred = dyn_cast<DefInit>(I)) { 1489*0fca6ea1SDimitry Andric Record *Def = Pred->getDef(); 1490*0fca6ea1SDimitry Andric if (!Def->isSubClassOf("Predicate")) { 1491*0fca6ea1SDimitry Andric #ifndef NDEBUG 1492*0fca6ea1SDimitry Andric Def->dump(); 1493*0fca6ea1SDimitry Andric #endif 1494*0fca6ea1SDimitry Andric llvm_unreachable("Unknown predicate type!"); 1495*0fca6ea1SDimitry Andric } 1496*0fca6ea1SDimitry Andric PredicateRecs.push_back(Def); 1497*0fca6ea1SDimitry Andric } 1498*0fca6ea1SDimitry Andric } 1499*0fca6ea1SDimitry Andric // Sort so that different orders get canonicalized to the same string. 1500*0fca6ea1SDimitry Andric llvm::sort(PredicateRecs, LessRecord()); 1501*0fca6ea1SDimitry Andric // Remove duplicate predicates. 1502*0fca6ea1SDimitry Andric PredicateRecs.erase(llvm::unique(PredicateRecs), PredicateRecs.end()); 1503*0fca6ea1SDimitry Andric } 1504*0fca6ea1SDimitry Andric 1505*0fca6ea1SDimitry Andric /// getPredicateCheck - Return a single string containing all of this 1506*0fca6ea1SDimitry Andric /// pattern's predicates concatenated with "&&" operators. 1507*0fca6ea1SDimitry Andric /// 1508*0fca6ea1SDimitry Andric std::string PatternToMatch::getPredicateCheck() const { 1509*0fca6ea1SDimitry Andric SmallVector<Record *, 4> PredicateRecs; 1510*0fca6ea1SDimitry Andric getPredicateRecords(PredicateRecs); 1511*0fca6ea1SDimitry Andric 1512*0fca6ea1SDimitry Andric SmallString<128> PredicateCheck; 1513*0fca6ea1SDimitry Andric raw_svector_ostream OS(PredicateCheck); 1514*0fca6ea1SDimitry Andric ListSeparator LS(" && "); 1515*0fca6ea1SDimitry Andric for (Record *Pred : PredicateRecs) { 1516*0fca6ea1SDimitry Andric StringRef CondString = Pred->getValueAsString("CondString"); 1517*0fca6ea1SDimitry Andric if (CondString.empty()) 1518*0fca6ea1SDimitry Andric continue; 1519*0fca6ea1SDimitry Andric OS << LS << '(' << CondString << ')'; 1520*0fca6ea1SDimitry Andric } 1521*0fca6ea1SDimitry Andric 1522*0fca6ea1SDimitry Andric if (!HwModeFeatures.empty()) 1523*0fca6ea1SDimitry Andric OS << LS << HwModeFeatures; 1524*0fca6ea1SDimitry Andric 1525*0fca6ea1SDimitry Andric return std::string(PredicateCheck); 1526*0fca6ea1SDimitry Andric } 1527*0fca6ea1SDimitry Andric 1528*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 1529*0fca6ea1SDimitry Andric // SDTypeConstraint implementation 1530*0fca6ea1SDimitry Andric // 1531*0fca6ea1SDimitry Andric 1532*0fca6ea1SDimitry Andric SDTypeConstraint::SDTypeConstraint(Record *R, const CodeGenHwModes &CGH) { 1533*0fca6ea1SDimitry Andric OperandNo = R->getValueAsInt("OperandNum"); 1534*0fca6ea1SDimitry Andric 1535*0fca6ea1SDimitry Andric if (R->isSubClassOf("SDTCisVT")) { 1536*0fca6ea1SDimitry Andric ConstraintType = SDTCisVT; 1537*0fca6ea1SDimitry Andric VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH); 1538*0fca6ea1SDimitry Andric for (const auto &P : VVT) 1539*0fca6ea1SDimitry Andric if (P.second == MVT::isVoid) 1540*0fca6ea1SDimitry Andric PrintFatalError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT"); 1541*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisPtrTy")) { 1542*0fca6ea1SDimitry Andric ConstraintType = SDTCisPtrTy; 1543*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisInt")) { 1544*0fca6ea1SDimitry Andric ConstraintType = SDTCisInt; 1545*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisFP")) { 1546*0fca6ea1SDimitry Andric ConstraintType = SDTCisFP; 1547*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisVec")) { 1548*0fca6ea1SDimitry Andric ConstraintType = SDTCisVec; 1549*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisSameAs")) { 1550*0fca6ea1SDimitry Andric ConstraintType = SDTCisSameAs; 1551*0fca6ea1SDimitry Andric x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum"); 1552*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) { 1553*0fca6ea1SDimitry Andric ConstraintType = SDTCisVTSmallerThanOp; 1554*0fca6ea1SDimitry Andric x.SDTCisVTSmallerThanOp_Info.OtherOperandNum = 1555*0fca6ea1SDimitry Andric R->getValueAsInt("OtherOperandNum"); 1556*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) { 1557*0fca6ea1SDimitry Andric ConstraintType = SDTCisOpSmallerThanOp; 1558*0fca6ea1SDimitry Andric x.SDTCisOpSmallerThanOp_Info.BigOperandNum = 1559*0fca6ea1SDimitry Andric R->getValueAsInt("BigOperandNum"); 1560*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisEltOfVec")) { 1561*0fca6ea1SDimitry Andric ConstraintType = SDTCisEltOfVec; 1562*0fca6ea1SDimitry Andric x.SDTCisEltOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum"); 1563*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisSubVecOfVec")) { 1564*0fca6ea1SDimitry Andric ConstraintType = SDTCisSubVecOfVec; 1565*0fca6ea1SDimitry Andric x.SDTCisSubVecOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum"); 1566*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCVecEltisVT")) { 1567*0fca6ea1SDimitry Andric ConstraintType = SDTCVecEltisVT; 1568*0fca6ea1SDimitry Andric VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH); 1569*0fca6ea1SDimitry Andric for (const auto &P : VVT) { 1570*0fca6ea1SDimitry Andric MVT T = P.second; 1571*0fca6ea1SDimitry Andric if (T.isVector()) 1572*0fca6ea1SDimitry Andric PrintFatalError(R->getLoc(), 1573*0fca6ea1SDimitry Andric "Cannot use vector type as SDTCVecEltisVT"); 1574*0fca6ea1SDimitry Andric if (!T.isInteger() && !T.isFloatingPoint()) 1575*0fca6ea1SDimitry Andric PrintFatalError(R->getLoc(), "Must use integer or floating point type " 1576*0fca6ea1SDimitry Andric "as SDTCVecEltisVT"); 1577*0fca6ea1SDimitry Andric } 1578*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) { 1579*0fca6ea1SDimitry Andric ConstraintType = SDTCisSameNumEltsAs; 1580*0fca6ea1SDimitry Andric x.SDTCisSameNumEltsAs_Info.OtherOperandNum = 1581*0fca6ea1SDimitry Andric R->getValueAsInt("OtherOperandNum"); 1582*0fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisSameSizeAs")) { 1583*0fca6ea1SDimitry Andric ConstraintType = SDTCisSameSizeAs; 1584*0fca6ea1SDimitry Andric x.SDTCisSameSizeAs_Info.OtherOperandNum = 1585*0fca6ea1SDimitry Andric R->getValueAsInt("OtherOperandNum"); 1586*0fca6ea1SDimitry Andric } else { 1587*0fca6ea1SDimitry Andric PrintFatalError(R->getLoc(), 1588*0fca6ea1SDimitry Andric "Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); 1589*0fca6ea1SDimitry Andric } 1590*0fca6ea1SDimitry Andric } 1591*0fca6ea1SDimitry Andric 1592*0fca6ea1SDimitry Andric /// getOperandNum - Return the node corresponding to operand #OpNo in tree 1593*0fca6ea1SDimitry Andric /// N, and the result number in ResNo. 1594*0fca6ea1SDimitry Andric static TreePatternNode &getOperandNum(unsigned OpNo, TreePatternNode &N, 1595*0fca6ea1SDimitry Andric const SDNodeInfo &NodeInfo, 1596*0fca6ea1SDimitry Andric unsigned &ResNo) { 1597*0fca6ea1SDimitry Andric unsigned NumResults = NodeInfo.getNumResults(); 1598*0fca6ea1SDimitry Andric if (OpNo < NumResults) { 1599*0fca6ea1SDimitry Andric ResNo = OpNo; 1600*0fca6ea1SDimitry Andric return N; 1601*0fca6ea1SDimitry Andric } 1602*0fca6ea1SDimitry Andric 1603*0fca6ea1SDimitry Andric OpNo -= NumResults; 1604*0fca6ea1SDimitry Andric 1605*0fca6ea1SDimitry Andric if (OpNo >= N.getNumChildren()) { 1606*0fca6ea1SDimitry Andric std::string S; 1607*0fca6ea1SDimitry Andric raw_string_ostream OS(S); 1608*0fca6ea1SDimitry Andric OS << "Invalid operand number in type constraint " << (OpNo + NumResults) 1609*0fca6ea1SDimitry Andric << " "; 1610*0fca6ea1SDimitry Andric N.print(OS); 1611*0fca6ea1SDimitry Andric PrintFatalError(S); 1612*0fca6ea1SDimitry Andric } 1613*0fca6ea1SDimitry Andric 1614*0fca6ea1SDimitry Andric return N.getChild(OpNo); 1615*0fca6ea1SDimitry Andric } 1616*0fca6ea1SDimitry Andric 1617*0fca6ea1SDimitry Andric /// ApplyTypeConstraint - Given a node in a pattern, apply this type 1618*0fca6ea1SDimitry Andric /// constraint to the nodes operands. This returns true if it makes a 1619*0fca6ea1SDimitry Andric /// change, false otherwise. If a type contradiction is found, flag an error. 1620*0fca6ea1SDimitry Andric bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode &N, 1621*0fca6ea1SDimitry Andric const SDNodeInfo &NodeInfo, 1622*0fca6ea1SDimitry Andric TreePattern &TP) const { 1623*0fca6ea1SDimitry Andric if (TP.hasError()) 1624*0fca6ea1SDimitry Andric return false; 1625*0fca6ea1SDimitry Andric 1626*0fca6ea1SDimitry Andric unsigned ResNo = 0; // The result number being referenced. 1627*0fca6ea1SDimitry Andric TreePatternNode &NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); 1628*0fca6ea1SDimitry Andric TypeInfer &TI = TP.getInfer(); 1629*0fca6ea1SDimitry Andric 1630*0fca6ea1SDimitry Andric switch (ConstraintType) { 1631*0fca6ea1SDimitry Andric case SDTCisVT: 1632*0fca6ea1SDimitry Andric // Operand must be a particular type. 1633*0fca6ea1SDimitry Andric return NodeToApply.UpdateNodeType(ResNo, VVT, TP); 1634*0fca6ea1SDimitry Andric case SDTCisPtrTy: 1635*0fca6ea1SDimitry Andric // Operand must be same as target pointer type. 1636*0fca6ea1SDimitry Andric return NodeToApply.UpdateNodeType(ResNo, MVT::iPTR, TP); 1637*0fca6ea1SDimitry Andric case SDTCisInt: 1638*0fca6ea1SDimitry Andric // Require it to be one of the legal integer VTs. 1639*0fca6ea1SDimitry Andric return TI.EnforceInteger(NodeToApply.getExtType(ResNo)); 1640*0fca6ea1SDimitry Andric case SDTCisFP: 1641*0fca6ea1SDimitry Andric // Require it to be one of the legal fp VTs. 1642*0fca6ea1SDimitry Andric return TI.EnforceFloatingPoint(NodeToApply.getExtType(ResNo)); 1643*0fca6ea1SDimitry Andric case SDTCisVec: 1644*0fca6ea1SDimitry Andric // Require it to be one of the legal vector VTs. 1645*0fca6ea1SDimitry Andric return TI.EnforceVector(NodeToApply.getExtType(ResNo)); 1646*0fca6ea1SDimitry Andric case SDTCisSameAs: { 1647*0fca6ea1SDimitry Andric unsigned OResNo = 0; 1648*0fca6ea1SDimitry Andric TreePatternNode &OtherNode = 1649*0fca6ea1SDimitry Andric getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo); 1650*0fca6ea1SDimitry Andric return (int)NodeToApply.UpdateNodeType(ResNo, OtherNode.getExtType(OResNo), 1651*0fca6ea1SDimitry Andric TP) | 1652*0fca6ea1SDimitry Andric (int)OtherNode.UpdateNodeType(OResNo, NodeToApply.getExtType(ResNo), 1653*0fca6ea1SDimitry Andric TP); 1654*0fca6ea1SDimitry Andric } 1655*0fca6ea1SDimitry Andric case SDTCisVTSmallerThanOp: { 1656*0fca6ea1SDimitry Andric // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must 1657*0fca6ea1SDimitry Andric // have an integer type that is smaller than the VT. 1658*0fca6ea1SDimitry Andric if (!NodeToApply.isLeaf() || !isa<DefInit>(NodeToApply.getLeafValue()) || 1659*0fca6ea1SDimitry Andric !cast<DefInit>(NodeToApply.getLeafValue()) 1660*0fca6ea1SDimitry Andric ->getDef() 1661*0fca6ea1SDimitry Andric ->isSubClassOf("ValueType")) { 1662*0fca6ea1SDimitry Andric TP.error(N.getOperator()->getName() + " expects a VT operand!"); 1663*0fca6ea1SDimitry Andric return false; 1664*0fca6ea1SDimitry Andric } 1665*0fca6ea1SDimitry Andric DefInit *DI = cast<DefInit>(NodeToApply.getLeafValue()); 1666*0fca6ea1SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 1667*0fca6ea1SDimitry Andric auto VVT = getValueTypeByHwMode(DI->getDef(), T.getHwModes()); 1668*0fca6ea1SDimitry Andric TypeSetByHwMode TypeListTmp(VVT); 1669*0fca6ea1SDimitry Andric 1670*0fca6ea1SDimitry Andric unsigned OResNo = 0; 1671*0fca6ea1SDimitry Andric TreePatternNode &OtherNode = getOperandNum( 1672*0fca6ea1SDimitry Andric x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo, OResNo); 1673*0fca6ea1SDimitry Andric 1674*0fca6ea1SDimitry Andric return TI.EnforceSmallerThan(TypeListTmp, OtherNode.getExtType(OResNo), 1675*0fca6ea1SDimitry Andric /*SmallIsVT*/ true); 1676*0fca6ea1SDimitry Andric } 1677*0fca6ea1SDimitry Andric case SDTCisOpSmallerThanOp: { 1678*0fca6ea1SDimitry Andric unsigned BResNo = 0; 1679*0fca6ea1SDimitry Andric TreePatternNode &BigOperand = getOperandNum( 1680*0fca6ea1SDimitry Andric x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NodeInfo, BResNo); 1681*0fca6ea1SDimitry Andric return TI.EnforceSmallerThan(NodeToApply.getExtType(ResNo), 1682*0fca6ea1SDimitry Andric BigOperand.getExtType(BResNo)); 1683*0fca6ea1SDimitry Andric } 1684*0fca6ea1SDimitry Andric case SDTCisEltOfVec: { 1685*0fca6ea1SDimitry Andric unsigned VResNo = 0; 1686*0fca6ea1SDimitry Andric TreePatternNode &VecOperand = getOperandNum( 1687*0fca6ea1SDimitry Andric x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo, VResNo); 1688*0fca6ea1SDimitry Andric // Filter vector types out of VecOperand that don't have the right element 1689*0fca6ea1SDimitry Andric // type. 1690*0fca6ea1SDimitry Andric return TI.EnforceVectorEltTypeIs(VecOperand.getExtType(VResNo), 1691*0fca6ea1SDimitry Andric NodeToApply.getExtType(ResNo)); 1692*0fca6ea1SDimitry Andric } 1693*0fca6ea1SDimitry Andric case SDTCisSubVecOfVec: { 1694*0fca6ea1SDimitry Andric unsigned VResNo = 0; 1695*0fca6ea1SDimitry Andric TreePatternNode &BigVecOperand = getOperandNum( 1696*0fca6ea1SDimitry Andric x.SDTCisSubVecOfVec_Info.OtherOperandNum, N, NodeInfo, VResNo); 1697*0fca6ea1SDimitry Andric 1698*0fca6ea1SDimitry Andric // Filter vector types out of BigVecOperand that don't have the 1699*0fca6ea1SDimitry Andric // right subvector type. 1700*0fca6ea1SDimitry Andric return TI.EnforceVectorSubVectorTypeIs(BigVecOperand.getExtType(VResNo), 1701*0fca6ea1SDimitry Andric NodeToApply.getExtType(ResNo)); 1702*0fca6ea1SDimitry Andric } 1703*0fca6ea1SDimitry Andric case SDTCVecEltisVT: { 1704*0fca6ea1SDimitry Andric return TI.EnforceVectorEltTypeIs(NodeToApply.getExtType(ResNo), VVT); 1705*0fca6ea1SDimitry Andric } 1706*0fca6ea1SDimitry Andric case SDTCisSameNumEltsAs: { 1707*0fca6ea1SDimitry Andric unsigned OResNo = 0; 1708*0fca6ea1SDimitry Andric TreePatternNode &OtherNode = getOperandNum( 1709*0fca6ea1SDimitry Andric x.SDTCisSameNumEltsAs_Info.OtherOperandNum, N, NodeInfo, OResNo); 1710*0fca6ea1SDimitry Andric return TI.EnforceSameNumElts(OtherNode.getExtType(OResNo), 1711*0fca6ea1SDimitry Andric NodeToApply.getExtType(ResNo)); 1712*0fca6ea1SDimitry Andric } 1713*0fca6ea1SDimitry Andric case SDTCisSameSizeAs: { 1714*0fca6ea1SDimitry Andric unsigned OResNo = 0; 1715*0fca6ea1SDimitry Andric TreePatternNode &OtherNode = getOperandNum( 1716*0fca6ea1SDimitry Andric x.SDTCisSameSizeAs_Info.OtherOperandNum, N, NodeInfo, OResNo); 1717*0fca6ea1SDimitry Andric return TI.EnforceSameSize(OtherNode.getExtType(OResNo), 1718*0fca6ea1SDimitry Andric NodeToApply.getExtType(ResNo)); 1719*0fca6ea1SDimitry Andric } 1720*0fca6ea1SDimitry Andric } 1721*0fca6ea1SDimitry Andric llvm_unreachable("Invalid ConstraintType!"); 1722*0fca6ea1SDimitry Andric } 1723*0fca6ea1SDimitry Andric 1724*0fca6ea1SDimitry Andric // Update the node type to match an instruction operand or result as specified 1725*0fca6ea1SDimitry Andric // in the ins or outs lists on the instruction definition. Return true if the 1726*0fca6ea1SDimitry Andric // type was actually changed. 1727*0fca6ea1SDimitry Andric bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo, Record *Operand, 1728*0fca6ea1SDimitry Andric TreePattern &TP) { 1729*0fca6ea1SDimitry Andric // The 'unknown' operand indicates that types should be inferred from the 1730*0fca6ea1SDimitry Andric // context. 1731*0fca6ea1SDimitry Andric if (Operand->isSubClassOf("unknown_class")) 1732*0fca6ea1SDimitry Andric return false; 1733*0fca6ea1SDimitry Andric 1734*0fca6ea1SDimitry Andric // The Operand class specifies a type directly. 1735*0fca6ea1SDimitry Andric if (Operand->isSubClassOf("Operand")) { 1736*0fca6ea1SDimitry Andric Record *R = Operand->getValueAsDef("Type"); 1737*0fca6ea1SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 1738*0fca6ea1SDimitry Andric return UpdateNodeType(ResNo, getValueTypeByHwMode(R, T.getHwModes()), TP); 1739*0fca6ea1SDimitry Andric } 1740*0fca6ea1SDimitry Andric 1741*0fca6ea1SDimitry Andric // PointerLikeRegClass has a type that is determined at runtime. 1742*0fca6ea1SDimitry Andric if (Operand->isSubClassOf("PointerLikeRegClass")) 1743*0fca6ea1SDimitry Andric return UpdateNodeType(ResNo, MVT::iPTR, TP); 1744*0fca6ea1SDimitry Andric 1745*0fca6ea1SDimitry Andric // Both RegisterClass and RegisterOperand operands derive their types from a 1746*0fca6ea1SDimitry Andric // register class def. 1747*0fca6ea1SDimitry Andric Record *RC = nullptr; 1748*0fca6ea1SDimitry Andric if (Operand->isSubClassOf("RegisterClass")) 1749*0fca6ea1SDimitry Andric RC = Operand; 1750*0fca6ea1SDimitry Andric else if (Operand->isSubClassOf("RegisterOperand")) 1751*0fca6ea1SDimitry Andric RC = Operand->getValueAsDef("RegClass"); 1752*0fca6ea1SDimitry Andric 1753*0fca6ea1SDimitry Andric assert(RC && "Unknown operand type"); 1754*0fca6ea1SDimitry Andric CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo(); 1755*0fca6ea1SDimitry Andric return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP); 1756*0fca6ea1SDimitry Andric } 1757*0fca6ea1SDimitry Andric 1758*0fca6ea1SDimitry Andric bool TreePatternNode::ContainsUnresolvedType(TreePattern &TP) const { 1759*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Types.size(); i != e; ++i) 1760*0fca6ea1SDimitry Andric if (!TP.getInfer().isConcrete(Types[i], true)) 1761*0fca6ea1SDimitry Andric return true; 1762*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 1763*0fca6ea1SDimitry Andric if (getChild(i).ContainsUnresolvedType(TP)) 1764*0fca6ea1SDimitry Andric return true; 1765*0fca6ea1SDimitry Andric return false; 1766*0fca6ea1SDimitry Andric } 1767*0fca6ea1SDimitry Andric 1768*0fca6ea1SDimitry Andric bool TreePatternNode::hasProperTypeByHwMode() const { 1769*0fca6ea1SDimitry Andric for (const TypeSetByHwMode &S : Types) 1770*0fca6ea1SDimitry Andric if (!S.isSimple()) 1771*0fca6ea1SDimitry Andric return true; 1772*0fca6ea1SDimitry Andric for (const TreePatternNodePtr &C : Children) 1773*0fca6ea1SDimitry Andric if (C->hasProperTypeByHwMode()) 1774*0fca6ea1SDimitry Andric return true; 1775*0fca6ea1SDimitry Andric return false; 1776*0fca6ea1SDimitry Andric } 1777*0fca6ea1SDimitry Andric 1778*0fca6ea1SDimitry Andric bool TreePatternNode::hasPossibleType() const { 1779*0fca6ea1SDimitry Andric for (const TypeSetByHwMode &S : Types) 1780*0fca6ea1SDimitry Andric if (!S.isPossible()) 1781*0fca6ea1SDimitry Andric return false; 1782*0fca6ea1SDimitry Andric for (const TreePatternNodePtr &C : Children) 1783*0fca6ea1SDimitry Andric if (!C->hasPossibleType()) 1784*0fca6ea1SDimitry Andric return false; 1785*0fca6ea1SDimitry Andric return true; 1786*0fca6ea1SDimitry Andric } 1787*0fca6ea1SDimitry Andric 1788*0fca6ea1SDimitry Andric bool TreePatternNode::setDefaultMode(unsigned Mode) { 1789*0fca6ea1SDimitry Andric for (TypeSetByHwMode &S : Types) { 1790*0fca6ea1SDimitry Andric S.makeSimple(Mode); 1791*0fca6ea1SDimitry Andric // Check if the selected mode had a type conflict. 1792*0fca6ea1SDimitry Andric if (S.get(DefaultMode).empty()) 1793*0fca6ea1SDimitry Andric return false; 1794*0fca6ea1SDimitry Andric } 1795*0fca6ea1SDimitry Andric for (const TreePatternNodePtr &C : Children) 1796*0fca6ea1SDimitry Andric if (!C->setDefaultMode(Mode)) 1797*0fca6ea1SDimitry Andric return false; 1798*0fca6ea1SDimitry Andric return true; 1799*0fca6ea1SDimitry Andric } 1800*0fca6ea1SDimitry Andric 1801*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 1802*0fca6ea1SDimitry Andric // SDNodeInfo implementation 1803*0fca6ea1SDimitry Andric // 1804*0fca6ea1SDimitry Andric SDNodeInfo::SDNodeInfo(Record *R, const CodeGenHwModes &CGH) : Def(R) { 1805*0fca6ea1SDimitry Andric EnumName = R->getValueAsString("Opcode"); 1806*0fca6ea1SDimitry Andric SDClassName = R->getValueAsString("SDClass"); 1807*0fca6ea1SDimitry Andric Record *TypeProfile = R->getValueAsDef("TypeProfile"); 1808*0fca6ea1SDimitry Andric NumResults = TypeProfile->getValueAsInt("NumResults"); 1809*0fca6ea1SDimitry Andric NumOperands = TypeProfile->getValueAsInt("NumOperands"); 1810*0fca6ea1SDimitry Andric 1811*0fca6ea1SDimitry Andric // Parse the properties. 1812*0fca6ea1SDimitry Andric Properties = parseSDPatternOperatorProperties(R); 1813*0fca6ea1SDimitry Andric 1814*0fca6ea1SDimitry Andric // Parse the type constraints. 1815*0fca6ea1SDimitry Andric std::vector<Record *> ConstraintList = 1816*0fca6ea1SDimitry Andric TypeProfile->getValueAsListOfDefs("Constraints"); 1817*0fca6ea1SDimitry Andric for (Record *R : ConstraintList) 1818*0fca6ea1SDimitry Andric TypeConstraints.emplace_back(R, CGH); 1819*0fca6ea1SDimitry Andric } 1820*0fca6ea1SDimitry Andric 1821*0fca6ea1SDimitry Andric /// getKnownType - If the type constraints on this node imply a fixed type 1822*0fca6ea1SDimitry Andric /// (e.g. all stores return void, etc), then return it as an 1823*0fca6ea1SDimitry Andric /// MVT::SimpleValueType. Otherwise, return EEVT::Other. 1824*0fca6ea1SDimitry Andric MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const { 1825*0fca6ea1SDimitry Andric unsigned NumResults = getNumResults(); 1826*0fca6ea1SDimitry Andric assert(NumResults <= 1 && 1827*0fca6ea1SDimitry Andric "We only work with nodes with zero or one result so far!"); 1828*0fca6ea1SDimitry Andric assert(ResNo == 0 && "Only handles single result nodes so far"); 1829*0fca6ea1SDimitry Andric 1830*0fca6ea1SDimitry Andric for (const SDTypeConstraint &Constraint : TypeConstraints) { 1831*0fca6ea1SDimitry Andric // Make sure that this applies to the correct node result. 1832*0fca6ea1SDimitry Andric if (Constraint.OperandNo >= NumResults) // FIXME: need value # 1833*0fca6ea1SDimitry Andric continue; 1834*0fca6ea1SDimitry Andric 1835*0fca6ea1SDimitry Andric switch (Constraint.ConstraintType) { 1836*0fca6ea1SDimitry Andric default: 1837*0fca6ea1SDimitry Andric break; 1838*0fca6ea1SDimitry Andric case SDTypeConstraint::SDTCisVT: 1839*0fca6ea1SDimitry Andric if (Constraint.VVT.isSimple()) 1840*0fca6ea1SDimitry Andric return Constraint.VVT.getSimple().SimpleTy; 1841*0fca6ea1SDimitry Andric break; 1842*0fca6ea1SDimitry Andric case SDTypeConstraint::SDTCisPtrTy: 1843*0fca6ea1SDimitry Andric return MVT::iPTR; 1844*0fca6ea1SDimitry Andric } 1845*0fca6ea1SDimitry Andric } 1846*0fca6ea1SDimitry Andric return MVT::Other; 1847*0fca6ea1SDimitry Andric } 1848*0fca6ea1SDimitry Andric 1849*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 1850*0fca6ea1SDimitry Andric // TreePatternNode implementation 1851*0fca6ea1SDimitry Andric // 1852*0fca6ea1SDimitry Andric 1853*0fca6ea1SDimitry Andric static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { 1854*0fca6ea1SDimitry Andric if (Operator->getName() == "set" || Operator->getName() == "implicit") 1855*0fca6ea1SDimitry Andric return 0; // All return nothing. 1856*0fca6ea1SDimitry Andric 1857*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("Intrinsic")) 1858*0fca6ea1SDimitry Andric return CDP.getIntrinsic(Operator).IS.RetTys.size(); 1859*0fca6ea1SDimitry Andric 1860*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("SDNode")) 1861*0fca6ea1SDimitry Andric return CDP.getSDNodeInfo(Operator).getNumResults(); 1862*0fca6ea1SDimitry Andric 1863*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("PatFrags")) { 1864*0fca6ea1SDimitry Andric // If we've already parsed this pattern fragment, get it. Otherwise, handle 1865*0fca6ea1SDimitry Andric // the forward reference case where one pattern fragment references another 1866*0fca6ea1SDimitry Andric // before it is processed. 1867*0fca6ea1SDimitry Andric if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator)) { 1868*0fca6ea1SDimitry Andric // The number of results of a fragment with alternative records is the 1869*0fca6ea1SDimitry Andric // maximum number of results across all alternatives. 1870*0fca6ea1SDimitry Andric unsigned NumResults = 0; 1871*0fca6ea1SDimitry Andric for (const auto &T : PFRec->getTrees()) 1872*0fca6ea1SDimitry Andric NumResults = std::max(NumResults, T->getNumTypes()); 1873*0fca6ea1SDimitry Andric return NumResults; 1874*0fca6ea1SDimitry Andric } 1875*0fca6ea1SDimitry Andric 1876*0fca6ea1SDimitry Andric ListInit *LI = Operator->getValueAsListInit("Fragments"); 1877*0fca6ea1SDimitry Andric assert(LI && "Invalid Fragment"); 1878*0fca6ea1SDimitry Andric unsigned NumResults = 0; 1879*0fca6ea1SDimitry Andric for (Init *I : LI->getValues()) { 1880*0fca6ea1SDimitry Andric Record *Op = nullptr; 1881*0fca6ea1SDimitry Andric if (DagInit *Dag = dyn_cast<DagInit>(I)) 1882*0fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(Dag->getOperator())) 1883*0fca6ea1SDimitry Andric Op = DI->getDef(); 1884*0fca6ea1SDimitry Andric assert(Op && "Invalid Fragment"); 1885*0fca6ea1SDimitry Andric NumResults = std::max(NumResults, GetNumNodeResults(Op, CDP)); 1886*0fca6ea1SDimitry Andric } 1887*0fca6ea1SDimitry Andric return NumResults; 1888*0fca6ea1SDimitry Andric } 1889*0fca6ea1SDimitry Andric 1890*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("Instruction")) { 1891*0fca6ea1SDimitry Andric CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); 1892*0fca6ea1SDimitry Andric 1893*0fca6ea1SDimitry Andric unsigned NumDefsToAdd = InstInfo.Operands.NumDefs; 1894*0fca6ea1SDimitry Andric 1895*0fca6ea1SDimitry Andric // Subtract any defaulted outputs. 1896*0fca6ea1SDimitry Andric for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) { 1897*0fca6ea1SDimitry Andric Record *OperandNode = InstInfo.Operands[i].Rec; 1898*0fca6ea1SDimitry Andric 1899*0fca6ea1SDimitry Andric if (OperandNode->isSubClassOf("OperandWithDefaultOps") && 1900*0fca6ea1SDimitry Andric !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) 1901*0fca6ea1SDimitry Andric --NumDefsToAdd; 1902*0fca6ea1SDimitry Andric } 1903*0fca6ea1SDimitry Andric 1904*0fca6ea1SDimitry Andric // Add on one implicit def if it has a resolvable type. 1905*0fca6ea1SDimitry Andric if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) != 1906*0fca6ea1SDimitry Andric MVT::Other) 1907*0fca6ea1SDimitry Andric ++NumDefsToAdd; 1908*0fca6ea1SDimitry Andric return NumDefsToAdd; 1909*0fca6ea1SDimitry Andric } 1910*0fca6ea1SDimitry Andric 1911*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("SDNodeXForm")) 1912*0fca6ea1SDimitry Andric return 1; // FIXME: Generalize SDNodeXForm 1913*0fca6ea1SDimitry Andric 1914*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("ValueType")) 1915*0fca6ea1SDimitry Andric return 1; // A type-cast of one result. 1916*0fca6ea1SDimitry Andric 1917*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("ComplexPattern")) 1918*0fca6ea1SDimitry Andric return 1; 1919*0fca6ea1SDimitry Andric 1920*0fca6ea1SDimitry Andric errs() << *Operator; 1921*0fca6ea1SDimitry Andric PrintFatalError("Unhandled node in GetNumNodeResults"); 1922*0fca6ea1SDimitry Andric } 1923*0fca6ea1SDimitry Andric 1924*0fca6ea1SDimitry Andric void TreePatternNode::print(raw_ostream &OS) const { 1925*0fca6ea1SDimitry Andric if (isLeaf()) 1926*0fca6ea1SDimitry Andric OS << *getLeafValue(); 1927*0fca6ea1SDimitry Andric else 1928*0fca6ea1SDimitry Andric OS << '(' << getOperator()->getName(); 1929*0fca6ea1SDimitry Andric 1930*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Types.size(); i != e; ++i) { 1931*0fca6ea1SDimitry Andric OS << ':'; 1932*0fca6ea1SDimitry Andric getExtType(i).writeToStream(OS); 1933*0fca6ea1SDimitry Andric } 1934*0fca6ea1SDimitry Andric 1935*0fca6ea1SDimitry Andric if (!isLeaf()) { 1936*0fca6ea1SDimitry Andric if (getNumChildren() != 0) { 1937*0fca6ea1SDimitry Andric OS << " "; 1938*0fca6ea1SDimitry Andric ListSeparator LS; 1939*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { 1940*0fca6ea1SDimitry Andric OS << LS; 1941*0fca6ea1SDimitry Andric getChild(i).print(OS); 1942*0fca6ea1SDimitry Andric } 1943*0fca6ea1SDimitry Andric } 1944*0fca6ea1SDimitry Andric OS << ")"; 1945*0fca6ea1SDimitry Andric } 1946*0fca6ea1SDimitry Andric 1947*0fca6ea1SDimitry Andric for (const TreePredicateCall &Pred : PredicateCalls) { 1948*0fca6ea1SDimitry Andric OS << "<<P:"; 1949*0fca6ea1SDimitry Andric if (Pred.Scope) 1950*0fca6ea1SDimitry Andric OS << Pred.Scope << ":"; 1951*0fca6ea1SDimitry Andric OS << Pred.Fn.getFnName() << ">>"; 1952*0fca6ea1SDimitry Andric } 1953*0fca6ea1SDimitry Andric if (TransformFn) 1954*0fca6ea1SDimitry Andric OS << "<<X:" << TransformFn->getName() << ">>"; 1955*0fca6ea1SDimitry Andric if (!getName().empty()) 1956*0fca6ea1SDimitry Andric OS << ":$" << getName(); 1957*0fca6ea1SDimitry Andric 1958*0fca6ea1SDimitry Andric for (const ScopedName &Name : NamesAsPredicateArg) 1959*0fca6ea1SDimitry Andric OS << ":$pred:" << Name.getScope() << ":" << Name.getIdentifier(); 1960*0fca6ea1SDimitry Andric } 1961*0fca6ea1SDimitry Andric void TreePatternNode::dump() const { print(errs()); } 1962*0fca6ea1SDimitry Andric 1963*0fca6ea1SDimitry Andric /// isIsomorphicTo - Return true if this node is recursively 1964*0fca6ea1SDimitry Andric /// isomorphic to the specified node. For this comparison, the node's 1965*0fca6ea1SDimitry Andric /// entire state is considered. The assigned name is ignored, since 1966*0fca6ea1SDimitry Andric /// nodes with differing names are considered isomorphic. However, if 1967*0fca6ea1SDimitry Andric /// the assigned name is present in the dependent variable set, then 1968*0fca6ea1SDimitry Andric /// the assigned name is considered significant and the node is 1969*0fca6ea1SDimitry Andric /// isomorphic if the names match. 1970*0fca6ea1SDimitry Andric bool TreePatternNode::isIsomorphicTo(const TreePatternNode &N, 1971*0fca6ea1SDimitry Andric const MultipleUseVarSet &DepVars) const { 1972*0fca6ea1SDimitry Andric if (&N == this) 1973*0fca6ea1SDimitry Andric return true; 1974*0fca6ea1SDimitry Andric if (N.isLeaf() != isLeaf()) 1975*0fca6ea1SDimitry Andric return false; 1976*0fca6ea1SDimitry Andric 1977*0fca6ea1SDimitry Andric // Check operator of non-leaves early since it can be cheaper than checking 1978*0fca6ea1SDimitry Andric // types. 1979*0fca6ea1SDimitry Andric if (!isLeaf()) 1980*0fca6ea1SDimitry Andric if (N.getOperator() != getOperator() || 1981*0fca6ea1SDimitry Andric N.getNumChildren() != getNumChildren()) 1982*0fca6ea1SDimitry Andric return false; 1983*0fca6ea1SDimitry Andric 1984*0fca6ea1SDimitry Andric if (getExtTypes() != N.getExtTypes() || 1985*0fca6ea1SDimitry Andric getPredicateCalls() != N.getPredicateCalls() || 1986*0fca6ea1SDimitry Andric getTransformFn() != N.getTransformFn()) 1987*0fca6ea1SDimitry Andric return false; 1988*0fca6ea1SDimitry Andric 1989*0fca6ea1SDimitry Andric if (isLeaf()) { 1990*0fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) { 1991*0fca6ea1SDimitry Andric if (DefInit *NDI = dyn_cast<DefInit>(N.getLeafValue())) { 1992*0fca6ea1SDimitry Andric return ((DI->getDef() == NDI->getDef()) && 1993*0fca6ea1SDimitry Andric (!DepVars.contains(getName()) || getName() == N.getName())); 1994*0fca6ea1SDimitry Andric } 1995*0fca6ea1SDimitry Andric } 1996*0fca6ea1SDimitry Andric return getLeafValue() == N.getLeafValue(); 1997*0fca6ea1SDimitry Andric } 1998*0fca6ea1SDimitry Andric 1999*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2000*0fca6ea1SDimitry Andric if (!getChild(i).isIsomorphicTo(N.getChild(i), DepVars)) 2001*0fca6ea1SDimitry Andric return false; 2002*0fca6ea1SDimitry Andric return true; 2003*0fca6ea1SDimitry Andric } 2004*0fca6ea1SDimitry Andric 2005*0fca6ea1SDimitry Andric /// clone - Make a copy of this tree and all of its children. 2006*0fca6ea1SDimitry Andric /// 2007*0fca6ea1SDimitry Andric TreePatternNodePtr TreePatternNode::clone() const { 2008*0fca6ea1SDimitry Andric TreePatternNodePtr New; 2009*0fca6ea1SDimitry Andric if (isLeaf()) { 2010*0fca6ea1SDimitry Andric New = makeIntrusiveRefCnt<TreePatternNode>(getLeafValue(), getNumTypes()); 2011*0fca6ea1SDimitry Andric } else { 2012*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> CChildren; 2013*0fca6ea1SDimitry Andric CChildren.reserve(Children.size()); 2014*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2015*0fca6ea1SDimitry Andric CChildren.push_back(getChild(i).clone()); 2016*0fca6ea1SDimitry Andric New = makeIntrusiveRefCnt<TreePatternNode>( 2017*0fca6ea1SDimitry Andric getOperator(), std::move(CChildren), getNumTypes()); 2018*0fca6ea1SDimitry Andric } 2019*0fca6ea1SDimitry Andric New->setName(getName()); 2020*0fca6ea1SDimitry Andric New->setNamesAsPredicateArg(getNamesAsPredicateArg()); 2021*0fca6ea1SDimitry Andric New->Types = Types; 2022*0fca6ea1SDimitry Andric New->setPredicateCalls(getPredicateCalls()); 2023*0fca6ea1SDimitry Andric New->setGISelFlagsRecord(getGISelFlagsRecord()); 2024*0fca6ea1SDimitry Andric New->setTransformFn(getTransformFn()); 2025*0fca6ea1SDimitry Andric return New; 2026*0fca6ea1SDimitry Andric } 2027*0fca6ea1SDimitry Andric 2028*0fca6ea1SDimitry Andric /// RemoveAllTypes - Recursively strip all the types of this tree. 2029*0fca6ea1SDimitry Andric void TreePatternNode::RemoveAllTypes() { 2030*0fca6ea1SDimitry Andric // Reset to unknown type. 2031*0fca6ea1SDimitry Andric std::fill(Types.begin(), Types.end(), TypeSetByHwMode()); 2032*0fca6ea1SDimitry Andric if (isLeaf()) 2033*0fca6ea1SDimitry Andric return; 2034*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2035*0fca6ea1SDimitry Andric getChild(i).RemoveAllTypes(); 2036*0fca6ea1SDimitry Andric } 2037*0fca6ea1SDimitry Andric 2038*0fca6ea1SDimitry Andric /// SubstituteFormalArguments - Replace the formal arguments in this tree 2039*0fca6ea1SDimitry Andric /// with actual values specified by ArgMap. 2040*0fca6ea1SDimitry Andric void TreePatternNode::SubstituteFormalArguments( 2041*0fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> &ArgMap) { 2042*0fca6ea1SDimitry Andric if (isLeaf()) 2043*0fca6ea1SDimitry Andric return; 2044*0fca6ea1SDimitry Andric 2045*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { 2046*0fca6ea1SDimitry Andric TreePatternNode &Child = getChild(i); 2047*0fca6ea1SDimitry Andric if (Child.isLeaf()) { 2048*0fca6ea1SDimitry Andric Init *Val = Child.getLeafValue(); 2049*0fca6ea1SDimitry Andric // Note that, when substituting into an output pattern, Val might be an 2050*0fca6ea1SDimitry Andric // UnsetInit. 2051*0fca6ea1SDimitry Andric if (isa<UnsetInit>(Val) || 2052*0fca6ea1SDimitry Andric (isa<DefInit>(Val) && 2053*0fca6ea1SDimitry Andric cast<DefInit>(Val)->getDef()->getName() == "node")) { 2054*0fca6ea1SDimitry Andric // We found a use of a formal argument, replace it with its value. 2055*0fca6ea1SDimitry Andric TreePatternNodePtr NewChild = ArgMap[Child.getName()]; 2056*0fca6ea1SDimitry Andric assert(NewChild && "Couldn't find formal argument!"); 2057*0fca6ea1SDimitry Andric assert((Child.getPredicateCalls().empty() || 2058*0fca6ea1SDimitry Andric NewChild->getPredicateCalls() == Child.getPredicateCalls()) && 2059*0fca6ea1SDimitry Andric "Non-empty child predicate clobbered!"); 2060*0fca6ea1SDimitry Andric setChild(i, std::move(NewChild)); 2061*0fca6ea1SDimitry Andric } 2062*0fca6ea1SDimitry Andric } else { 2063*0fca6ea1SDimitry Andric getChild(i).SubstituteFormalArguments(ArgMap); 2064*0fca6ea1SDimitry Andric } 2065*0fca6ea1SDimitry Andric } 2066*0fca6ea1SDimitry Andric } 2067*0fca6ea1SDimitry Andric 2068*0fca6ea1SDimitry Andric /// InlinePatternFragments - If this pattern refers to any pattern 2069*0fca6ea1SDimitry Andric /// fragments, return the set of inlined versions (this can be more than 2070*0fca6ea1SDimitry Andric /// one if a PatFrags record has multiple alternatives). 2071*0fca6ea1SDimitry Andric void TreePatternNode::InlinePatternFragments( 2072*0fca6ea1SDimitry Andric TreePattern &TP, std::vector<TreePatternNodePtr> &OutAlternatives) { 2073*0fca6ea1SDimitry Andric 2074*0fca6ea1SDimitry Andric if (TP.hasError()) 2075*0fca6ea1SDimitry Andric return; 2076*0fca6ea1SDimitry Andric 2077*0fca6ea1SDimitry Andric if (isLeaf()) { 2078*0fca6ea1SDimitry Andric OutAlternatives.push_back(this); // nothing to do. 2079*0fca6ea1SDimitry Andric return; 2080*0fca6ea1SDimitry Andric } 2081*0fca6ea1SDimitry Andric 2082*0fca6ea1SDimitry Andric Record *Op = getOperator(); 2083*0fca6ea1SDimitry Andric 2084*0fca6ea1SDimitry Andric if (!Op->isSubClassOf("PatFrags")) { 2085*0fca6ea1SDimitry Andric if (getNumChildren() == 0) { 2086*0fca6ea1SDimitry Andric OutAlternatives.push_back(this); 2087*0fca6ea1SDimitry Andric return; 2088*0fca6ea1SDimitry Andric } 2089*0fca6ea1SDimitry Andric 2090*0fca6ea1SDimitry Andric // Recursively inline children nodes. 2091*0fca6ea1SDimitry Andric std::vector<std::vector<TreePatternNodePtr>> ChildAlternatives( 2092*0fca6ea1SDimitry Andric getNumChildren()); 2093*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { 2094*0fca6ea1SDimitry Andric TreePatternNodePtr Child = getChildShared(i); 2095*0fca6ea1SDimitry Andric Child->InlinePatternFragments(TP, ChildAlternatives[i]); 2096*0fca6ea1SDimitry Andric // If there are no alternatives for any child, there are no 2097*0fca6ea1SDimitry Andric // alternatives for this expression as whole. 2098*0fca6ea1SDimitry Andric if (ChildAlternatives[i].empty()) 2099*0fca6ea1SDimitry Andric return; 2100*0fca6ea1SDimitry Andric 2101*0fca6ea1SDimitry Andric assert((Child->getPredicateCalls().empty() || 2102*0fca6ea1SDimitry Andric llvm::all_of(ChildAlternatives[i], 2103*0fca6ea1SDimitry Andric [&](const TreePatternNodePtr &NewChild) { 2104*0fca6ea1SDimitry Andric return NewChild->getPredicateCalls() == 2105*0fca6ea1SDimitry Andric Child->getPredicateCalls(); 2106*0fca6ea1SDimitry Andric })) && 2107*0fca6ea1SDimitry Andric "Non-empty child predicate clobbered!"); 2108*0fca6ea1SDimitry Andric } 2109*0fca6ea1SDimitry Andric 2110*0fca6ea1SDimitry Andric // The end result is an all-pairs construction of the resultant pattern. 2111*0fca6ea1SDimitry Andric std::vector<unsigned> Idxs(ChildAlternatives.size()); 2112*0fca6ea1SDimitry Andric bool NotDone; 2113*0fca6ea1SDimitry Andric do { 2114*0fca6ea1SDimitry Andric // Create the variant and add it to the output list. 2115*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> NewChildren; 2116*0fca6ea1SDimitry Andric NewChildren.reserve(ChildAlternatives.size()); 2117*0fca6ea1SDimitry Andric for (unsigned i = 0, e = ChildAlternatives.size(); i != e; ++i) 2118*0fca6ea1SDimitry Andric NewChildren.push_back(ChildAlternatives[i][Idxs[i]]); 2119*0fca6ea1SDimitry Andric TreePatternNodePtr R = makeIntrusiveRefCnt<TreePatternNode>( 2120*0fca6ea1SDimitry Andric getOperator(), std::move(NewChildren), getNumTypes()); 2121*0fca6ea1SDimitry Andric 2122*0fca6ea1SDimitry Andric // Copy over properties. 2123*0fca6ea1SDimitry Andric R->setName(getName()); 2124*0fca6ea1SDimitry Andric R->setNamesAsPredicateArg(getNamesAsPredicateArg()); 2125*0fca6ea1SDimitry Andric R->setPredicateCalls(getPredicateCalls()); 2126*0fca6ea1SDimitry Andric R->setGISelFlagsRecord(getGISelFlagsRecord()); 2127*0fca6ea1SDimitry Andric R->setTransformFn(getTransformFn()); 2128*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumTypes(); i != e; ++i) 2129*0fca6ea1SDimitry Andric R->setType(i, getExtType(i)); 2130*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumResults(); i != e; ++i) 2131*0fca6ea1SDimitry Andric R->setResultIndex(i, getResultIndex(i)); 2132*0fca6ea1SDimitry Andric 2133*0fca6ea1SDimitry Andric // Register alternative. 2134*0fca6ea1SDimitry Andric OutAlternatives.push_back(R); 2135*0fca6ea1SDimitry Andric 2136*0fca6ea1SDimitry Andric // Increment indices to the next permutation by incrementing the 2137*0fca6ea1SDimitry Andric // indices from last index backward, e.g., generate the sequence 2138*0fca6ea1SDimitry Andric // [0, 0], [0, 1], [1, 0], [1, 1]. 2139*0fca6ea1SDimitry Andric int IdxsIdx; 2140*0fca6ea1SDimitry Andric for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) { 2141*0fca6ea1SDimitry Andric if (++Idxs[IdxsIdx] == ChildAlternatives[IdxsIdx].size()) 2142*0fca6ea1SDimitry Andric Idxs[IdxsIdx] = 0; 2143*0fca6ea1SDimitry Andric else 2144*0fca6ea1SDimitry Andric break; 2145*0fca6ea1SDimitry Andric } 2146*0fca6ea1SDimitry Andric NotDone = (IdxsIdx >= 0); 2147*0fca6ea1SDimitry Andric } while (NotDone); 2148*0fca6ea1SDimitry Andric 2149*0fca6ea1SDimitry Andric return; 2150*0fca6ea1SDimitry Andric } 2151*0fca6ea1SDimitry Andric 2152*0fca6ea1SDimitry Andric // Otherwise, we found a reference to a fragment. First, look up its 2153*0fca6ea1SDimitry Andric // TreePattern record. 2154*0fca6ea1SDimitry Andric TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op); 2155*0fca6ea1SDimitry Andric 2156*0fca6ea1SDimitry Andric // Verify that we are passing the right number of operands. 2157*0fca6ea1SDimitry Andric if (Frag->getNumArgs() != getNumChildren()) { 2158*0fca6ea1SDimitry Andric TP.error("'" + Op->getName() + "' fragment requires " + 2159*0fca6ea1SDimitry Andric Twine(Frag->getNumArgs()) + " operands!"); 2160*0fca6ea1SDimitry Andric return; 2161*0fca6ea1SDimitry Andric } 2162*0fca6ea1SDimitry Andric 2163*0fca6ea1SDimitry Andric TreePredicateFn PredFn(Frag); 2164*0fca6ea1SDimitry Andric unsigned Scope = 0; 2165*0fca6ea1SDimitry Andric if (TreePredicateFn(Frag).usesOperands()) 2166*0fca6ea1SDimitry Andric Scope = TP.getDAGPatterns().allocateScope(); 2167*0fca6ea1SDimitry Andric 2168*0fca6ea1SDimitry Andric // Compute the map of formal to actual arguments. 2169*0fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> ArgMap; 2170*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) { 2171*0fca6ea1SDimitry Andric TreePatternNodePtr Child = getChildShared(i); 2172*0fca6ea1SDimitry Andric if (Scope != 0) { 2173*0fca6ea1SDimitry Andric Child = Child->clone(); 2174*0fca6ea1SDimitry Andric Child->addNameAsPredicateArg(ScopedName(Scope, Frag->getArgName(i))); 2175*0fca6ea1SDimitry Andric } 2176*0fca6ea1SDimitry Andric ArgMap[Frag->getArgName(i)] = Child; 2177*0fca6ea1SDimitry Andric } 2178*0fca6ea1SDimitry Andric 2179*0fca6ea1SDimitry Andric // Loop over all fragment alternatives. 2180*0fca6ea1SDimitry Andric for (const auto &Alternative : Frag->getTrees()) { 2181*0fca6ea1SDimitry Andric TreePatternNodePtr FragTree = Alternative->clone(); 2182*0fca6ea1SDimitry Andric 2183*0fca6ea1SDimitry Andric if (!PredFn.isAlwaysTrue()) 2184*0fca6ea1SDimitry Andric FragTree->addPredicateCall(PredFn, Scope); 2185*0fca6ea1SDimitry Andric 2186*0fca6ea1SDimitry Andric // Resolve formal arguments to their actual value. 2187*0fca6ea1SDimitry Andric if (Frag->getNumArgs()) 2188*0fca6ea1SDimitry Andric FragTree->SubstituteFormalArguments(ArgMap); 2189*0fca6ea1SDimitry Andric 2190*0fca6ea1SDimitry Andric // Transfer types. Note that the resolved alternative may have fewer 2191*0fca6ea1SDimitry Andric // (but not more) results than the PatFrags node. 2192*0fca6ea1SDimitry Andric FragTree->setName(getName()); 2193*0fca6ea1SDimitry Andric for (unsigned i = 0, e = FragTree->getNumTypes(); i != e; ++i) 2194*0fca6ea1SDimitry Andric FragTree->UpdateNodeType(i, getExtType(i), TP); 2195*0fca6ea1SDimitry Andric 2196*0fca6ea1SDimitry Andric if (Op->isSubClassOf("GISelFlags")) 2197*0fca6ea1SDimitry Andric FragTree->setGISelFlagsRecord(Op); 2198*0fca6ea1SDimitry Andric 2199*0fca6ea1SDimitry Andric // Transfer in the old predicates. 2200*0fca6ea1SDimitry Andric for (const TreePredicateCall &Pred : getPredicateCalls()) 2201*0fca6ea1SDimitry Andric FragTree->addPredicateCall(Pred); 2202*0fca6ea1SDimitry Andric 2203*0fca6ea1SDimitry Andric // The fragment we inlined could have recursive inlining that is needed. See 2204*0fca6ea1SDimitry Andric // if there are any pattern fragments in it and inline them as needed. 2205*0fca6ea1SDimitry Andric FragTree->InlinePatternFragments(TP, OutAlternatives); 2206*0fca6ea1SDimitry Andric } 2207*0fca6ea1SDimitry Andric } 2208*0fca6ea1SDimitry Andric 2209*0fca6ea1SDimitry Andric /// getImplicitType - Check to see if the specified record has an implicit 2210*0fca6ea1SDimitry Andric /// type which should be applied to it. This will infer the type of register 2211*0fca6ea1SDimitry Andric /// references from the register file information, for example. 2212*0fca6ea1SDimitry Andric /// 2213*0fca6ea1SDimitry Andric /// When Unnamed is set, return the type of a DAG operand with no name, such as 2214*0fca6ea1SDimitry Andric /// the F8RC register class argument in: 2215*0fca6ea1SDimitry Andric /// 2216*0fca6ea1SDimitry Andric /// (COPY_TO_REGCLASS GPR:$src, F8RC) 2217*0fca6ea1SDimitry Andric /// 2218*0fca6ea1SDimitry Andric /// When Unnamed is false, return the type of a named DAG operand such as the 2219*0fca6ea1SDimitry Andric /// GPR:$src operand above. 2220*0fca6ea1SDimitry Andric /// 2221*0fca6ea1SDimitry Andric static TypeSetByHwMode getImplicitType(Record *R, unsigned ResNo, 2222*0fca6ea1SDimitry Andric bool NotRegisters, bool Unnamed, 2223*0fca6ea1SDimitry Andric TreePattern &TP) { 2224*0fca6ea1SDimitry Andric CodeGenDAGPatterns &CDP = TP.getDAGPatterns(); 2225*0fca6ea1SDimitry Andric 2226*0fca6ea1SDimitry Andric // Check to see if this is a register operand. 2227*0fca6ea1SDimitry Andric if (R->isSubClassOf("RegisterOperand")) { 2228*0fca6ea1SDimitry Andric assert(ResNo == 0 && "Regoperand ref only has one result!"); 2229*0fca6ea1SDimitry Andric if (NotRegisters) 2230*0fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 2231*0fca6ea1SDimitry Andric Record *RegClass = R->getValueAsDef("RegClass"); 2232*0fca6ea1SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 2233*0fca6ea1SDimitry Andric return TypeSetByHwMode(T.getRegisterClass(RegClass).getValueTypes()); 2234*0fca6ea1SDimitry Andric } 2235*0fca6ea1SDimitry Andric 2236*0fca6ea1SDimitry Andric // Check to see if this is a register or a register class. 2237*0fca6ea1SDimitry Andric if (R->isSubClassOf("RegisterClass")) { 2238*0fca6ea1SDimitry Andric assert(ResNo == 0 && "Regclass ref only has one result!"); 2239*0fca6ea1SDimitry Andric // An unnamed register class represents itself as an i32 immediate, for 2240*0fca6ea1SDimitry Andric // example on a COPY_TO_REGCLASS instruction. 2241*0fca6ea1SDimitry Andric if (Unnamed) 2242*0fca6ea1SDimitry Andric return TypeSetByHwMode(MVT::i32); 2243*0fca6ea1SDimitry Andric 2244*0fca6ea1SDimitry Andric // In a named operand, the register class provides the possible set of 2245*0fca6ea1SDimitry Andric // types. 2246*0fca6ea1SDimitry Andric if (NotRegisters) 2247*0fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 2248*0fca6ea1SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 2249*0fca6ea1SDimitry Andric return TypeSetByHwMode(T.getRegisterClass(R).getValueTypes()); 2250*0fca6ea1SDimitry Andric } 2251*0fca6ea1SDimitry Andric 2252*0fca6ea1SDimitry Andric if (R->isSubClassOf("PatFrags")) { 2253*0fca6ea1SDimitry Andric assert(ResNo == 0 && "FIXME: PatFrag with multiple results?"); 2254*0fca6ea1SDimitry Andric // Pattern fragment types will be resolved when they are inlined. 2255*0fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 2256*0fca6ea1SDimitry Andric } 2257*0fca6ea1SDimitry Andric 2258*0fca6ea1SDimitry Andric if (R->isSubClassOf("Register")) { 2259*0fca6ea1SDimitry Andric assert(ResNo == 0 && "Registers only produce one result!"); 2260*0fca6ea1SDimitry Andric if (NotRegisters) 2261*0fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 2262*0fca6ea1SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 2263*0fca6ea1SDimitry Andric return TypeSetByHwMode(T.getRegisterVTs(R)); 2264*0fca6ea1SDimitry Andric } 2265*0fca6ea1SDimitry Andric 2266*0fca6ea1SDimitry Andric if (R->isSubClassOf("SubRegIndex")) { 2267*0fca6ea1SDimitry Andric assert(ResNo == 0 && "SubRegisterIndices only produce one result!"); 2268*0fca6ea1SDimitry Andric return TypeSetByHwMode(MVT::i32); 2269*0fca6ea1SDimitry Andric } 2270*0fca6ea1SDimitry Andric 2271*0fca6ea1SDimitry Andric if (R->isSubClassOf("ValueType")) { 2272*0fca6ea1SDimitry Andric assert(ResNo == 0 && "This node only has one result!"); 2273*0fca6ea1SDimitry Andric // An unnamed VTSDNode represents itself as an MVT::Other immediate. 2274*0fca6ea1SDimitry Andric // 2275*0fca6ea1SDimitry Andric // (sext_inreg GPR:$src, i16) 2276*0fca6ea1SDimitry Andric // ~~~ 2277*0fca6ea1SDimitry Andric if (Unnamed) 2278*0fca6ea1SDimitry Andric return TypeSetByHwMode(MVT::Other); 2279*0fca6ea1SDimitry Andric // With a name, the ValueType simply provides the type of the named 2280*0fca6ea1SDimitry Andric // variable. 2281*0fca6ea1SDimitry Andric // 2282*0fca6ea1SDimitry Andric // (sext_inreg i32:$src, i16) 2283*0fca6ea1SDimitry Andric // ~~~~~~~~ 2284*0fca6ea1SDimitry Andric if (NotRegisters) 2285*0fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 2286*0fca6ea1SDimitry Andric const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); 2287*0fca6ea1SDimitry Andric return TypeSetByHwMode(getValueTypeByHwMode(R, CGH)); 2288*0fca6ea1SDimitry Andric } 2289*0fca6ea1SDimitry Andric 2290*0fca6ea1SDimitry Andric if (R->isSubClassOf("CondCode")) { 2291*0fca6ea1SDimitry Andric assert(ResNo == 0 && "This node only has one result!"); 2292*0fca6ea1SDimitry Andric // Using a CondCodeSDNode. 2293*0fca6ea1SDimitry Andric return TypeSetByHwMode(MVT::Other); 2294*0fca6ea1SDimitry Andric } 2295*0fca6ea1SDimitry Andric 2296*0fca6ea1SDimitry Andric if (R->isSubClassOf("ComplexPattern")) { 2297*0fca6ea1SDimitry Andric assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?"); 2298*0fca6ea1SDimitry Andric if (NotRegisters) 2299*0fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 2300*0fca6ea1SDimitry Andric Record *T = CDP.getComplexPattern(R).getValueType(); 2301*0fca6ea1SDimitry Andric const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); 2302*0fca6ea1SDimitry Andric return TypeSetByHwMode(getValueTypeByHwMode(T, CGH)); 2303*0fca6ea1SDimitry Andric } 2304*0fca6ea1SDimitry Andric if (R->isSubClassOf("PointerLikeRegClass")) { 2305*0fca6ea1SDimitry Andric assert(ResNo == 0 && "Regclass can only have one result!"); 2306*0fca6ea1SDimitry Andric TypeSetByHwMode VTS(MVT::iPTR); 2307*0fca6ea1SDimitry Andric TP.getInfer().expandOverloads(VTS); 2308*0fca6ea1SDimitry Andric return VTS; 2309*0fca6ea1SDimitry Andric } 2310*0fca6ea1SDimitry Andric 2311*0fca6ea1SDimitry Andric if (R->getName() == "node" || R->getName() == "srcvalue" || 2312*0fca6ea1SDimitry Andric R->getName() == "zero_reg" || R->getName() == "immAllOnesV" || 2313*0fca6ea1SDimitry Andric R->getName() == "immAllZerosV" || R->getName() == "undef_tied_input") { 2314*0fca6ea1SDimitry Andric // Placeholder. 2315*0fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 2316*0fca6ea1SDimitry Andric } 2317*0fca6ea1SDimitry Andric 2318*0fca6ea1SDimitry Andric if (R->isSubClassOf("Operand")) { 2319*0fca6ea1SDimitry Andric const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); 2320*0fca6ea1SDimitry Andric Record *T = R->getValueAsDef("Type"); 2321*0fca6ea1SDimitry Andric return TypeSetByHwMode(getValueTypeByHwMode(T, CGH)); 2322*0fca6ea1SDimitry Andric } 2323*0fca6ea1SDimitry Andric 2324*0fca6ea1SDimitry Andric TP.error("Unknown node flavor used in pattern: " + R->getName()); 2325*0fca6ea1SDimitry Andric return TypeSetByHwMode(MVT::Other); 2326*0fca6ea1SDimitry Andric } 2327*0fca6ea1SDimitry Andric 2328*0fca6ea1SDimitry Andric /// getIntrinsicInfo - If this node corresponds to an intrinsic, return the 2329*0fca6ea1SDimitry Andric /// CodeGenIntrinsic information for it, otherwise return a null pointer. 2330*0fca6ea1SDimitry Andric const CodeGenIntrinsic * 2331*0fca6ea1SDimitry Andric TreePatternNode::getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { 2332*0fca6ea1SDimitry Andric if (getOperator() != CDP.get_intrinsic_void_sdnode() && 2333*0fca6ea1SDimitry Andric getOperator() != CDP.get_intrinsic_w_chain_sdnode() && 2334*0fca6ea1SDimitry Andric getOperator() != CDP.get_intrinsic_wo_chain_sdnode()) 2335*0fca6ea1SDimitry Andric return nullptr; 2336*0fca6ea1SDimitry Andric 2337*0fca6ea1SDimitry Andric unsigned IID = cast<IntInit>(getChild(0).getLeafValue())->getValue(); 2338*0fca6ea1SDimitry Andric return &CDP.getIntrinsicInfo(IID); 2339*0fca6ea1SDimitry Andric } 2340*0fca6ea1SDimitry Andric 2341*0fca6ea1SDimitry Andric /// getComplexPatternInfo - If this node corresponds to a ComplexPattern, 2342*0fca6ea1SDimitry Andric /// return the ComplexPattern information, otherwise return null. 2343*0fca6ea1SDimitry Andric const ComplexPattern * 2344*0fca6ea1SDimitry Andric TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const { 2345*0fca6ea1SDimitry Andric Record *Rec; 2346*0fca6ea1SDimitry Andric if (isLeaf()) { 2347*0fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(getLeafValue()); 2348*0fca6ea1SDimitry Andric if (!DI) 2349*0fca6ea1SDimitry Andric return nullptr; 2350*0fca6ea1SDimitry Andric Rec = DI->getDef(); 2351*0fca6ea1SDimitry Andric } else 2352*0fca6ea1SDimitry Andric Rec = getOperator(); 2353*0fca6ea1SDimitry Andric 2354*0fca6ea1SDimitry Andric if (!Rec->isSubClassOf("ComplexPattern")) 2355*0fca6ea1SDimitry Andric return nullptr; 2356*0fca6ea1SDimitry Andric return &CGP.getComplexPattern(Rec); 2357*0fca6ea1SDimitry Andric } 2358*0fca6ea1SDimitry Andric 2359*0fca6ea1SDimitry Andric unsigned TreePatternNode::getNumMIResults(const CodeGenDAGPatterns &CGP) const { 2360*0fca6ea1SDimitry Andric // A ComplexPattern specifically declares how many results it fills in. 2361*0fca6ea1SDimitry Andric if (const ComplexPattern *CP = getComplexPatternInfo(CGP)) 2362*0fca6ea1SDimitry Andric return CP->getNumOperands(); 2363*0fca6ea1SDimitry Andric 2364*0fca6ea1SDimitry Andric // If MIOperandInfo is specified, that gives the count. 2365*0fca6ea1SDimitry Andric if (isLeaf()) { 2366*0fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(getLeafValue()); 2367*0fca6ea1SDimitry Andric if (DI && DI->getDef()->isSubClassOf("Operand")) { 2368*0fca6ea1SDimitry Andric DagInit *MIOps = DI->getDef()->getValueAsDag("MIOperandInfo"); 2369*0fca6ea1SDimitry Andric if (MIOps->getNumArgs()) 2370*0fca6ea1SDimitry Andric return MIOps->getNumArgs(); 2371*0fca6ea1SDimitry Andric } 2372*0fca6ea1SDimitry Andric } 2373*0fca6ea1SDimitry Andric 2374*0fca6ea1SDimitry Andric // Otherwise there is just one result. 2375*0fca6ea1SDimitry Andric return 1; 2376*0fca6ea1SDimitry Andric } 2377*0fca6ea1SDimitry Andric 2378*0fca6ea1SDimitry Andric /// NodeHasProperty - Return true if this node has the specified property. 2379*0fca6ea1SDimitry Andric bool TreePatternNode::NodeHasProperty(SDNP Property, 2380*0fca6ea1SDimitry Andric const CodeGenDAGPatterns &CGP) const { 2381*0fca6ea1SDimitry Andric if (isLeaf()) { 2382*0fca6ea1SDimitry Andric if (const ComplexPattern *CP = getComplexPatternInfo(CGP)) 2383*0fca6ea1SDimitry Andric return CP->hasProperty(Property); 2384*0fca6ea1SDimitry Andric 2385*0fca6ea1SDimitry Andric return false; 2386*0fca6ea1SDimitry Andric } 2387*0fca6ea1SDimitry Andric 2388*0fca6ea1SDimitry Andric if (Property != SDNPHasChain) { 2389*0fca6ea1SDimitry Andric // The chain proprety is already present on the different intrinsic node 2390*0fca6ea1SDimitry Andric // types (intrinsic_w_chain, intrinsic_void), and is not explicitly listed 2391*0fca6ea1SDimitry Andric // on the intrinsic. Anything else is specific to the individual intrinsic. 2392*0fca6ea1SDimitry Andric if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CGP)) 2393*0fca6ea1SDimitry Andric return Int->hasProperty(Property); 2394*0fca6ea1SDimitry Andric } 2395*0fca6ea1SDimitry Andric 2396*0fca6ea1SDimitry Andric if (!getOperator()->isSubClassOf("SDPatternOperator")) 2397*0fca6ea1SDimitry Andric return false; 2398*0fca6ea1SDimitry Andric 2399*0fca6ea1SDimitry Andric return CGP.getSDNodeInfo(getOperator()).hasProperty(Property); 2400*0fca6ea1SDimitry Andric } 2401*0fca6ea1SDimitry Andric 2402*0fca6ea1SDimitry Andric /// TreeHasProperty - Return true if any node in this tree has the specified 2403*0fca6ea1SDimitry Andric /// property. 2404*0fca6ea1SDimitry Andric bool TreePatternNode::TreeHasProperty(SDNP Property, 2405*0fca6ea1SDimitry Andric const CodeGenDAGPatterns &CGP) const { 2406*0fca6ea1SDimitry Andric if (NodeHasProperty(Property, CGP)) 2407*0fca6ea1SDimitry Andric return true; 2408*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2409*0fca6ea1SDimitry Andric if (getChild(i).TreeHasProperty(Property, CGP)) 2410*0fca6ea1SDimitry Andric return true; 2411*0fca6ea1SDimitry Andric return false; 2412*0fca6ea1SDimitry Andric } 2413*0fca6ea1SDimitry Andric 2414*0fca6ea1SDimitry Andric /// isCommutativeIntrinsic - Return true if the node corresponds to a 2415*0fca6ea1SDimitry Andric /// commutative intrinsic. 2416*0fca6ea1SDimitry Andric bool TreePatternNode::isCommutativeIntrinsic( 2417*0fca6ea1SDimitry Andric const CodeGenDAGPatterns &CDP) const { 2418*0fca6ea1SDimitry Andric if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) 2419*0fca6ea1SDimitry Andric return Int->isCommutative; 2420*0fca6ea1SDimitry Andric return false; 2421*0fca6ea1SDimitry Andric } 2422*0fca6ea1SDimitry Andric 2423*0fca6ea1SDimitry Andric static bool isOperandClass(const TreePatternNode &N, StringRef Class) { 2424*0fca6ea1SDimitry Andric if (!N.isLeaf()) 2425*0fca6ea1SDimitry Andric return N.getOperator()->isSubClassOf(Class); 2426*0fca6ea1SDimitry Andric 2427*0fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(N.getLeafValue()); 2428*0fca6ea1SDimitry Andric if (DI && DI->getDef()->isSubClassOf(Class)) 2429*0fca6ea1SDimitry Andric return true; 2430*0fca6ea1SDimitry Andric 2431*0fca6ea1SDimitry Andric return false; 2432*0fca6ea1SDimitry Andric } 2433*0fca6ea1SDimitry Andric 2434*0fca6ea1SDimitry Andric static void emitTooManyOperandsError(TreePattern &TP, StringRef InstName, 2435*0fca6ea1SDimitry Andric unsigned Expected, unsigned Actual) { 2436*0fca6ea1SDimitry Andric TP.error("Instruction '" + InstName + "' was provided " + Twine(Actual) + 2437*0fca6ea1SDimitry Andric " operands but expected only " + Twine(Expected) + "!"); 2438*0fca6ea1SDimitry Andric } 2439*0fca6ea1SDimitry Andric 2440*0fca6ea1SDimitry Andric static void emitTooFewOperandsError(TreePattern &TP, StringRef InstName, 2441*0fca6ea1SDimitry Andric unsigned Actual) { 2442*0fca6ea1SDimitry Andric TP.error("Instruction '" + InstName + "' expects more than the provided " + 2443*0fca6ea1SDimitry Andric Twine(Actual) + " operands!"); 2444*0fca6ea1SDimitry Andric } 2445*0fca6ea1SDimitry Andric 2446*0fca6ea1SDimitry Andric /// ApplyTypeConstraints - Apply all of the type constraints relevant to 2447*0fca6ea1SDimitry Andric /// this node and its children in the tree. This returns true if it makes a 2448*0fca6ea1SDimitry Andric /// change, false otherwise. If a type contradiction is found, flag an error. 2449*0fca6ea1SDimitry Andric bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { 2450*0fca6ea1SDimitry Andric if (TP.hasError()) 2451*0fca6ea1SDimitry Andric return false; 2452*0fca6ea1SDimitry Andric 2453*0fca6ea1SDimitry Andric CodeGenDAGPatterns &CDP = TP.getDAGPatterns(); 2454*0fca6ea1SDimitry Andric if (isLeaf()) { 2455*0fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) { 2456*0fca6ea1SDimitry Andric // If it's a regclass or something else known, include the type. 2457*0fca6ea1SDimitry Andric bool MadeChange = false; 2458*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Types.size(); i != e; ++i) 2459*0fca6ea1SDimitry Andric MadeChange |= UpdateNodeType( 2460*0fca6ea1SDimitry Andric i, getImplicitType(DI->getDef(), i, NotRegisters, !hasName(), TP), 2461*0fca6ea1SDimitry Andric TP); 2462*0fca6ea1SDimitry Andric return MadeChange; 2463*0fca6ea1SDimitry Andric } 2464*0fca6ea1SDimitry Andric 2465*0fca6ea1SDimitry Andric if (IntInit *II = dyn_cast<IntInit>(getLeafValue())) { 2466*0fca6ea1SDimitry Andric assert(Types.size() == 1 && "Invalid IntInit"); 2467*0fca6ea1SDimitry Andric 2468*0fca6ea1SDimitry Andric // Int inits are always integers. :) 2469*0fca6ea1SDimitry Andric bool MadeChange = TP.getInfer().EnforceInteger(Types[0]); 2470*0fca6ea1SDimitry Andric 2471*0fca6ea1SDimitry Andric if (!TP.getInfer().isConcrete(Types[0], false)) 2472*0fca6ea1SDimitry Andric return MadeChange; 2473*0fca6ea1SDimitry Andric 2474*0fca6ea1SDimitry Andric ValueTypeByHwMode VVT = TP.getInfer().getConcrete(Types[0], false); 2475*0fca6ea1SDimitry Andric for (auto &P : VVT) { 2476*0fca6ea1SDimitry Andric MVT::SimpleValueType VT = P.second.SimpleTy; 2477*0fca6ea1SDimitry Andric if (VT == MVT::iPTR || VT == MVT::iPTRAny) 2478*0fca6ea1SDimitry Andric continue; 2479*0fca6ea1SDimitry Andric unsigned Size = MVT(VT).getFixedSizeInBits(); 2480*0fca6ea1SDimitry Andric // Make sure that the value is representable for this type. 2481*0fca6ea1SDimitry Andric if (Size >= 32) 2482*0fca6ea1SDimitry Andric continue; 2483*0fca6ea1SDimitry Andric // Check that the value doesn't use more bits than we have. It must 2484*0fca6ea1SDimitry Andric // either be a sign- or zero-extended equivalent of the original. 2485*0fca6ea1SDimitry Andric int64_t SignBitAndAbove = II->getValue() >> (Size - 1); 2486*0fca6ea1SDimitry Andric if (SignBitAndAbove == -1 || SignBitAndAbove == 0 || 2487*0fca6ea1SDimitry Andric SignBitAndAbove == 1) 2488*0fca6ea1SDimitry Andric continue; 2489*0fca6ea1SDimitry Andric 2490*0fca6ea1SDimitry Andric TP.error("Integer value '" + Twine(II->getValue()) + 2491*0fca6ea1SDimitry Andric "' is out of range for type '" + getEnumName(VT) + "'!"); 2492*0fca6ea1SDimitry Andric break; 2493*0fca6ea1SDimitry Andric } 2494*0fca6ea1SDimitry Andric return MadeChange; 2495*0fca6ea1SDimitry Andric } 2496*0fca6ea1SDimitry Andric 2497*0fca6ea1SDimitry Andric return false; 2498*0fca6ea1SDimitry Andric } 2499*0fca6ea1SDimitry Andric 2500*0fca6ea1SDimitry Andric if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) { 2501*0fca6ea1SDimitry Andric bool MadeChange = false; 2502*0fca6ea1SDimitry Andric 2503*0fca6ea1SDimitry Andric // Apply the result type to the node. 2504*0fca6ea1SDimitry Andric unsigned NumRetVTs = Int->IS.RetTys.size(); 2505*0fca6ea1SDimitry Andric unsigned NumParamVTs = Int->IS.ParamTys.size(); 2506*0fca6ea1SDimitry Andric 2507*0fca6ea1SDimitry Andric for (unsigned i = 0, e = NumRetVTs; i != e; ++i) 2508*0fca6ea1SDimitry Andric MadeChange |= UpdateNodeType( 2509*0fca6ea1SDimitry Andric i, getValueType(Int->IS.RetTys[i]->getValueAsDef("VT")), TP); 2510*0fca6ea1SDimitry Andric 2511*0fca6ea1SDimitry Andric if (getNumChildren() != NumParamVTs + 1) { 2512*0fca6ea1SDimitry Andric TP.error("Intrinsic '" + Int->Name + "' expects " + Twine(NumParamVTs) + 2513*0fca6ea1SDimitry Andric " operands, not " + Twine(getNumChildren() - 1) + " operands!"); 2514*0fca6ea1SDimitry Andric return false; 2515*0fca6ea1SDimitry Andric } 2516*0fca6ea1SDimitry Andric 2517*0fca6ea1SDimitry Andric // Apply type info to the intrinsic ID. 2518*0fca6ea1SDimitry Andric MadeChange |= getChild(0).UpdateNodeType(0, MVT::iPTR, TP); 2519*0fca6ea1SDimitry Andric 2520*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren() - 1; i != e; ++i) { 2521*0fca6ea1SDimitry Andric MadeChange |= getChild(i + 1).ApplyTypeConstraints(TP, NotRegisters); 2522*0fca6ea1SDimitry Andric 2523*0fca6ea1SDimitry Andric MVT::SimpleValueType OpVT = 2524*0fca6ea1SDimitry Andric getValueType(Int->IS.ParamTys[i]->getValueAsDef("VT")); 2525*0fca6ea1SDimitry Andric assert(getChild(i + 1).getNumTypes() == 1 && "Unhandled case"); 2526*0fca6ea1SDimitry Andric MadeChange |= getChild(i + 1).UpdateNodeType(0, OpVT, TP); 2527*0fca6ea1SDimitry Andric } 2528*0fca6ea1SDimitry Andric return MadeChange; 2529*0fca6ea1SDimitry Andric } 2530*0fca6ea1SDimitry Andric 2531*0fca6ea1SDimitry Andric if (getOperator()->isSubClassOf("SDNode")) { 2532*0fca6ea1SDimitry Andric const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator()); 2533*0fca6ea1SDimitry Andric 2534*0fca6ea1SDimitry Andric // Check that the number of operands is sane. Negative operands -> varargs. 2535*0fca6ea1SDimitry Andric if (NI.getNumOperands() >= 0 && 2536*0fca6ea1SDimitry Andric getNumChildren() != (unsigned)NI.getNumOperands()) { 2537*0fca6ea1SDimitry Andric TP.error(getOperator()->getName() + " node requires exactly " + 2538*0fca6ea1SDimitry Andric Twine(NI.getNumOperands()) + " operands!"); 2539*0fca6ea1SDimitry Andric return false; 2540*0fca6ea1SDimitry Andric } 2541*0fca6ea1SDimitry Andric 2542*0fca6ea1SDimitry Andric bool MadeChange = false; 2543*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2544*0fca6ea1SDimitry Andric MadeChange |= getChild(i).ApplyTypeConstraints(TP, NotRegisters); 2545*0fca6ea1SDimitry Andric MadeChange |= NI.ApplyTypeConstraints(*this, TP); 2546*0fca6ea1SDimitry Andric return MadeChange; 2547*0fca6ea1SDimitry Andric } 2548*0fca6ea1SDimitry Andric 2549*0fca6ea1SDimitry Andric if (getOperator()->isSubClassOf("Instruction")) { 2550*0fca6ea1SDimitry Andric const DAGInstruction &Inst = CDP.getInstruction(getOperator()); 2551*0fca6ea1SDimitry Andric CodeGenInstruction &InstInfo = 2552*0fca6ea1SDimitry Andric CDP.getTargetInfo().getInstruction(getOperator()); 2553*0fca6ea1SDimitry Andric 2554*0fca6ea1SDimitry Andric bool MadeChange = false; 2555*0fca6ea1SDimitry Andric 2556*0fca6ea1SDimitry Andric // Apply the result types to the node, these come from the things in the 2557*0fca6ea1SDimitry Andric // (outs) list of the instruction. 2558*0fca6ea1SDimitry Andric unsigned NumResultsToAdd = 2559*0fca6ea1SDimitry Andric std::min(InstInfo.Operands.NumDefs, Inst.getNumResults()); 2560*0fca6ea1SDimitry Andric for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) 2561*0fca6ea1SDimitry Andric MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP); 2562*0fca6ea1SDimitry Andric 2563*0fca6ea1SDimitry Andric // If the instruction has implicit defs, we apply the first one as a result. 2564*0fca6ea1SDimitry Andric // FIXME: This sucks, it should apply all implicit defs. 2565*0fca6ea1SDimitry Andric if (!InstInfo.ImplicitDefs.empty()) { 2566*0fca6ea1SDimitry Andric unsigned ResNo = NumResultsToAdd; 2567*0fca6ea1SDimitry Andric 2568*0fca6ea1SDimitry Andric // FIXME: Generalize to multiple possible types and multiple possible 2569*0fca6ea1SDimitry Andric // ImplicitDefs. 2570*0fca6ea1SDimitry Andric MVT::SimpleValueType VT = 2571*0fca6ea1SDimitry Andric InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()); 2572*0fca6ea1SDimitry Andric 2573*0fca6ea1SDimitry Andric if (VT != MVT::Other) 2574*0fca6ea1SDimitry Andric MadeChange |= UpdateNodeType(ResNo, VT, TP); 2575*0fca6ea1SDimitry Andric } 2576*0fca6ea1SDimitry Andric 2577*0fca6ea1SDimitry Andric // If this is an INSERT_SUBREG, constrain the source and destination VTs to 2578*0fca6ea1SDimitry Andric // be the same. 2579*0fca6ea1SDimitry Andric if (getOperator()->getName() == "INSERT_SUBREG") { 2580*0fca6ea1SDimitry Andric assert(getChild(0).getNumTypes() == 1 && "FIXME: Unhandled"); 2581*0fca6ea1SDimitry Andric MadeChange |= UpdateNodeType(0, getChild(0).getExtType(0), TP); 2582*0fca6ea1SDimitry Andric MadeChange |= getChild(0).UpdateNodeType(0, getExtType(0), TP); 2583*0fca6ea1SDimitry Andric } else if (getOperator()->getName() == "REG_SEQUENCE") { 2584*0fca6ea1SDimitry Andric // We need to do extra, custom typechecking for REG_SEQUENCE since it is 2585*0fca6ea1SDimitry Andric // variadic. 2586*0fca6ea1SDimitry Andric 2587*0fca6ea1SDimitry Andric unsigned NChild = getNumChildren(); 2588*0fca6ea1SDimitry Andric if (NChild < 3) { 2589*0fca6ea1SDimitry Andric TP.error("REG_SEQUENCE requires at least 3 operands!"); 2590*0fca6ea1SDimitry Andric return false; 2591*0fca6ea1SDimitry Andric } 2592*0fca6ea1SDimitry Andric 2593*0fca6ea1SDimitry Andric if (NChild % 2 == 0) { 2594*0fca6ea1SDimitry Andric TP.error("REG_SEQUENCE requires an odd number of operands!"); 2595*0fca6ea1SDimitry Andric return false; 2596*0fca6ea1SDimitry Andric } 2597*0fca6ea1SDimitry Andric 2598*0fca6ea1SDimitry Andric if (!isOperandClass(getChild(0), "RegisterClass")) { 2599*0fca6ea1SDimitry Andric TP.error("REG_SEQUENCE requires a RegisterClass for first operand!"); 2600*0fca6ea1SDimitry Andric return false; 2601*0fca6ea1SDimitry Andric } 2602*0fca6ea1SDimitry Andric 2603*0fca6ea1SDimitry Andric for (unsigned I = 1; I < NChild; I += 2) { 2604*0fca6ea1SDimitry Andric TreePatternNode &SubIdxChild = getChild(I + 1); 2605*0fca6ea1SDimitry Andric if (!isOperandClass(SubIdxChild, "SubRegIndex")) { 2606*0fca6ea1SDimitry Andric TP.error("REG_SEQUENCE requires a SubRegIndex for operand " + 2607*0fca6ea1SDimitry Andric Twine(I + 1) + "!"); 2608*0fca6ea1SDimitry Andric return false; 2609*0fca6ea1SDimitry Andric } 2610*0fca6ea1SDimitry Andric } 2611*0fca6ea1SDimitry Andric } 2612*0fca6ea1SDimitry Andric 2613*0fca6ea1SDimitry Andric unsigned NumResults = Inst.getNumResults(); 2614*0fca6ea1SDimitry Andric unsigned NumFixedOperands = InstInfo.Operands.size(); 2615*0fca6ea1SDimitry Andric 2616*0fca6ea1SDimitry Andric // If one or more operands with a default value appear at the end of the 2617*0fca6ea1SDimitry Andric // formal operand list for an instruction, we allow them to be overridden 2618*0fca6ea1SDimitry Andric // by optional operands provided in the pattern. 2619*0fca6ea1SDimitry Andric // 2620*0fca6ea1SDimitry Andric // But if an operand B without a default appears at any point after an 2621*0fca6ea1SDimitry Andric // operand A with a default, then we don't allow A to be overridden, 2622*0fca6ea1SDimitry Andric // because there would be no way to specify whether the next operand in 2623*0fca6ea1SDimitry Andric // the pattern was intended to override A or skip it. 2624*0fca6ea1SDimitry Andric unsigned NonOverridableOperands = NumFixedOperands; 2625*0fca6ea1SDimitry Andric while (NonOverridableOperands > NumResults && 2626*0fca6ea1SDimitry Andric CDP.operandHasDefault( 2627*0fca6ea1SDimitry Andric InstInfo.Operands[NonOverridableOperands - 1].Rec)) 2628*0fca6ea1SDimitry Andric --NonOverridableOperands; 2629*0fca6ea1SDimitry Andric 2630*0fca6ea1SDimitry Andric unsigned ChildNo = 0; 2631*0fca6ea1SDimitry Andric assert(NumResults <= NumFixedOperands); 2632*0fca6ea1SDimitry Andric for (unsigned i = NumResults, e = NumFixedOperands; i != e; ++i) { 2633*0fca6ea1SDimitry Andric Record *OperandNode = InstInfo.Operands[i].Rec; 2634*0fca6ea1SDimitry Andric 2635*0fca6ea1SDimitry Andric // If the operand has a default value, do we use it? We must use the 2636*0fca6ea1SDimitry Andric // default if we've run out of children of the pattern DAG to consume, 2637*0fca6ea1SDimitry Andric // or if the operand is followed by a non-defaulted one. 2638*0fca6ea1SDimitry Andric if (CDP.operandHasDefault(OperandNode) && 2639*0fca6ea1SDimitry Andric (i < NonOverridableOperands || ChildNo >= getNumChildren())) 2640*0fca6ea1SDimitry Andric continue; 2641*0fca6ea1SDimitry Andric 2642*0fca6ea1SDimitry Andric // If we have run out of child nodes and there _isn't_ a default 2643*0fca6ea1SDimitry Andric // value we can use for the next operand, give an error. 2644*0fca6ea1SDimitry Andric if (ChildNo >= getNumChildren()) { 2645*0fca6ea1SDimitry Andric emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren()); 2646*0fca6ea1SDimitry Andric return false; 2647*0fca6ea1SDimitry Andric } 2648*0fca6ea1SDimitry Andric 2649*0fca6ea1SDimitry Andric TreePatternNode *Child = &getChild(ChildNo++); 2650*0fca6ea1SDimitry Andric unsigned ChildResNo = 0; // Instructions always use res #0 of their op. 2651*0fca6ea1SDimitry Andric 2652*0fca6ea1SDimitry Andric // If the operand has sub-operands, they may be provided by distinct 2653*0fca6ea1SDimitry Andric // child patterns, so attempt to match each sub-operand separately. 2654*0fca6ea1SDimitry Andric if (OperandNode->isSubClassOf("Operand")) { 2655*0fca6ea1SDimitry Andric DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo"); 2656*0fca6ea1SDimitry Andric if (unsigned NumArgs = MIOpInfo->getNumArgs()) { 2657*0fca6ea1SDimitry Andric // But don't do that if the whole operand is being provided by 2658*0fca6ea1SDimitry Andric // a single ComplexPattern-related Operand. 2659*0fca6ea1SDimitry Andric 2660*0fca6ea1SDimitry Andric if (Child->getNumMIResults(CDP) < NumArgs) { 2661*0fca6ea1SDimitry Andric // Match first sub-operand against the child we already have. 2662*0fca6ea1SDimitry Andric Record *SubRec = cast<DefInit>(MIOpInfo->getArg(0))->getDef(); 2663*0fca6ea1SDimitry Andric MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP); 2664*0fca6ea1SDimitry Andric 2665*0fca6ea1SDimitry Andric // And the remaining sub-operands against subsequent children. 2666*0fca6ea1SDimitry Andric for (unsigned Arg = 1; Arg < NumArgs; ++Arg) { 2667*0fca6ea1SDimitry Andric if (ChildNo >= getNumChildren()) { 2668*0fca6ea1SDimitry Andric emitTooFewOperandsError(TP, getOperator()->getName(), 2669*0fca6ea1SDimitry Andric getNumChildren()); 2670*0fca6ea1SDimitry Andric return false; 2671*0fca6ea1SDimitry Andric } 2672*0fca6ea1SDimitry Andric Child = &getChild(ChildNo++); 2673*0fca6ea1SDimitry Andric 2674*0fca6ea1SDimitry Andric SubRec = cast<DefInit>(MIOpInfo->getArg(Arg))->getDef(); 2675*0fca6ea1SDimitry Andric MadeChange |= 2676*0fca6ea1SDimitry Andric Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP); 2677*0fca6ea1SDimitry Andric } 2678*0fca6ea1SDimitry Andric continue; 2679*0fca6ea1SDimitry Andric } 2680*0fca6ea1SDimitry Andric } 2681*0fca6ea1SDimitry Andric } 2682*0fca6ea1SDimitry Andric 2683*0fca6ea1SDimitry Andric // If we didn't match by pieces above, attempt to match the whole 2684*0fca6ea1SDimitry Andric // operand now. 2685*0fca6ea1SDimitry Andric MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP); 2686*0fca6ea1SDimitry Andric } 2687*0fca6ea1SDimitry Andric 2688*0fca6ea1SDimitry Andric if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) { 2689*0fca6ea1SDimitry Andric emitTooManyOperandsError(TP, getOperator()->getName(), ChildNo, 2690*0fca6ea1SDimitry Andric getNumChildren()); 2691*0fca6ea1SDimitry Andric return false; 2692*0fca6ea1SDimitry Andric } 2693*0fca6ea1SDimitry Andric 2694*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2695*0fca6ea1SDimitry Andric MadeChange |= getChild(i).ApplyTypeConstraints(TP, NotRegisters); 2696*0fca6ea1SDimitry Andric return MadeChange; 2697*0fca6ea1SDimitry Andric } 2698*0fca6ea1SDimitry Andric 2699*0fca6ea1SDimitry Andric if (getOperator()->isSubClassOf("ComplexPattern")) { 2700*0fca6ea1SDimitry Andric bool MadeChange = false; 2701*0fca6ea1SDimitry Andric 2702*0fca6ea1SDimitry Andric if (!NotRegisters) { 2703*0fca6ea1SDimitry Andric assert(Types.size() == 1 && "ComplexPatterns only produce one result!"); 2704*0fca6ea1SDimitry Andric Record *T = CDP.getComplexPattern(getOperator()).getValueType(); 2705*0fca6ea1SDimitry Andric const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); 2706*0fca6ea1SDimitry Andric const ValueTypeByHwMode VVT = getValueTypeByHwMode(T, CGH); 2707*0fca6ea1SDimitry Andric // TODO: AArch64 and AMDGPU use ComplexPattern<untyped, ...> and then 2708*0fca6ea1SDimitry Andric // exclusively use those as non-leaf nodes with explicit type casts, so 2709*0fca6ea1SDimitry Andric // for backwards compatibility we do no inference in that case. This is 2710*0fca6ea1SDimitry Andric // not supported when the ComplexPattern is used as a leaf value, 2711*0fca6ea1SDimitry Andric // however; this inconsistency should be resolved, either by adding this 2712*0fca6ea1SDimitry Andric // case there or by altering the backends to not do this (e.g. using Any 2713*0fca6ea1SDimitry Andric // instead may work). 2714*0fca6ea1SDimitry Andric if (!VVT.isSimple() || VVT.getSimple() != MVT::Untyped) 2715*0fca6ea1SDimitry Andric MadeChange |= UpdateNodeType(0, VVT, TP); 2716*0fca6ea1SDimitry Andric } 2717*0fca6ea1SDimitry Andric 2718*0fca6ea1SDimitry Andric for (unsigned i = 0; i < getNumChildren(); ++i) 2719*0fca6ea1SDimitry Andric MadeChange |= getChild(i).ApplyTypeConstraints(TP, NotRegisters); 2720*0fca6ea1SDimitry Andric 2721*0fca6ea1SDimitry Andric return MadeChange; 2722*0fca6ea1SDimitry Andric } 2723*0fca6ea1SDimitry Andric 2724*0fca6ea1SDimitry Andric assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); 2725*0fca6ea1SDimitry Andric 2726*0fca6ea1SDimitry Andric // Node transforms always take one operand. 2727*0fca6ea1SDimitry Andric if (getNumChildren() != 1) { 2728*0fca6ea1SDimitry Andric TP.error("Node transform '" + getOperator()->getName() + 2729*0fca6ea1SDimitry Andric "' requires one operand!"); 2730*0fca6ea1SDimitry Andric return false; 2731*0fca6ea1SDimitry Andric } 2732*0fca6ea1SDimitry Andric 2733*0fca6ea1SDimitry Andric bool MadeChange = getChild(0).ApplyTypeConstraints(TP, NotRegisters); 2734*0fca6ea1SDimitry Andric return MadeChange; 2735*0fca6ea1SDimitry Andric } 2736*0fca6ea1SDimitry Andric 2737*0fca6ea1SDimitry Andric /// OnlyOnRHSOfCommutative - Return true if this value is only allowed on the 2738*0fca6ea1SDimitry Andric /// RHS of a commutative operation, not the on LHS. 2739*0fca6ea1SDimitry Andric static bool OnlyOnRHSOfCommutative(TreePatternNode &N) { 2740*0fca6ea1SDimitry Andric if (!N.isLeaf() && N.getOperator()->getName() == "imm") 2741*0fca6ea1SDimitry Andric return true; 2742*0fca6ea1SDimitry Andric if (N.isLeaf() && isa<IntInit>(N.getLeafValue())) 2743*0fca6ea1SDimitry Andric return true; 2744*0fca6ea1SDimitry Andric if (isImmAllOnesAllZerosMatch(N)) 2745*0fca6ea1SDimitry Andric return true; 2746*0fca6ea1SDimitry Andric return false; 2747*0fca6ea1SDimitry Andric } 2748*0fca6ea1SDimitry Andric 2749*0fca6ea1SDimitry Andric /// canPatternMatch - If it is impossible for this pattern to match on this 2750*0fca6ea1SDimitry Andric /// target, fill in Reason and return false. Otherwise, return true. This is 2751*0fca6ea1SDimitry Andric /// used as a sanity check for .td files (to prevent people from writing stuff 2752*0fca6ea1SDimitry Andric /// that can never possibly work), and to prevent the pattern permuter from 2753*0fca6ea1SDimitry Andric /// generating stuff that is useless. 2754*0fca6ea1SDimitry Andric bool TreePatternNode::canPatternMatch(std::string &Reason, 2755*0fca6ea1SDimitry Andric const CodeGenDAGPatterns &CDP) { 2756*0fca6ea1SDimitry Andric if (isLeaf()) 2757*0fca6ea1SDimitry Andric return true; 2758*0fca6ea1SDimitry Andric 2759*0fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2760*0fca6ea1SDimitry Andric if (!getChild(i).canPatternMatch(Reason, CDP)) 2761*0fca6ea1SDimitry Andric return false; 2762*0fca6ea1SDimitry Andric 2763*0fca6ea1SDimitry Andric // If this is an intrinsic, handle cases that would make it not match. For 2764*0fca6ea1SDimitry Andric // example, if an operand is required to be an immediate. 2765*0fca6ea1SDimitry Andric if (getOperator()->isSubClassOf("Intrinsic")) { 2766*0fca6ea1SDimitry Andric // TODO: 2767*0fca6ea1SDimitry Andric return true; 2768*0fca6ea1SDimitry Andric } 2769*0fca6ea1SDimitry Andric 2770*0fca6ea1SDimitry Andric if (getOperator()->isSubClassOf("ComplexPattern")) 2771*0fca6ea1SDimitry Andric return true; 2772*0fca6ea1SDimitry Andric 2773*0fca6ea1SDimitry Andric // If this node is a commutative operator, check that the LHS isn't an 2774*0fca6ea1SDimitry Andric // immediate. 2775*0fca6ea1SDimitry Andric const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator()); 2776*0fca6ea1SDimitry Andric bool isCommIntrinsic = isCommutativeIntrinsic(CDP); 2777*0fca6ea1SDimitry Andric if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) { 2778*0fca6ea1SDimitry Andric // Scan all of the operands of the node and make sure that only the last one 2779*0fca6ea1SDimitry Andric // is a constant node, unless the RHS also is. 2780*0fca6ea1SDimitry Andric if (!OnlyOnRHSOfCommutative(getChild(getNumChildren() - 1))) { 2781*0fca6ea1SDimitry Andric unsigned Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id. 2782*0fca6ea1SDimitry Andric for (unsigned i = Skip, e = getNumChildren() - 1; i != e; ++i) 2783*0fca6ea1SDimitry Andric if (OnlyOnRHSOfCommutative(getChild(i))) { 2784*0fca6ea1SDimitry Andric Reason = 2785*0fca6ea1SDimitry Andric "Immediate value must be on the RHS of commutative operators!"; 2786*0fca6ea1SDimitry Andric return false; 2787*0fca6ea1SDimitry Andric } 2788*0fca6ea1SDimitry Andric } 2789*0fca6ea1SDimitry Andric } 2790*0fca6ea1SDimitry Andric 2791*0fca6ea1SDimitry Andric return true; 2792*0fca6ea1SDimitry Andric } 2793*0fca6ea1SDimitry Andric 2794*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 2795*0fca6ea1SDimitry Andric // TreePattern implementation 2796*0fca6ea1SDimitry Andric // 2797*0fca6ea1SDimitry Andric 2798*0fca6ea1SDimitry Andric TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, 2799*0fca6ea1SDimitry Andric CodeGenDAGPatterns &cdp) 2800*0fca6ea1SDimitry Andric : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false), 2801*0fca6ea1SDimitry Andric Infer(*this) { 2802*0fca6ea1SDimitry Andric for (Init *I : RawPat->getValues()) 2803*0fca6ea1SDimitry Andric Trees.push_back(ParseTreePattern(I, "")); 2804*0fca6ea1SDimitry Andric } 2805*0fca6ea1SDimitry Andric 2806*0fca6ea1SDimitry Andric TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput, 2807*0fca6ea1SDimitry Andric CodeGenDAGPatterns &cdp) 2808*0fca6ea1SDimitry Andric : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false), 2809*0fca6ea1SDimitry Andric Infer(*this) { 2810*0fca6ea1SDimitry Andric Trees.push_back(ParseTreePattern(Pat, "")); 2811*0fca6ea1SDimitry Andric } 2812*0fca6ea1SDimitry Andric 2813*0fca6ea1SDimitry Andric TreePattern::TreePattern(Record *TheRec, TreePatternNodePtr Pat, bool isInput, 2814*0fca6ea1SDimitry Andric CodeGenDAGPatterns &cdp) 2815*0fca6ea1SDimitry Andric : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false), 2816*0fca6ea1SDimitry Andric Infer(*this) { 2817*0fca6ea1SDimitry Andric Trees.push_back(Pat); 2818*0fca6ea1SDimitry Andric } 2819*0fca6ea1SDimitry Andric 2820*0fca6ea1SDimitry Andric void TreePattern::error(const Twine &Msg) { 2821*0fca6ea1SDimitry Andric if (HasError) 2822*0fca6ea1SDimitry Andric return; 2823*0fca6ea1SDimitry Andric dump(); 2824*0fca6ea1SDimitry Andric PrintError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg); 2825*0fca6ea1SDimitry Andric HasError = true; 2826*0fca6ea1SDimitry Andric } 2827*0fca6ea1SDimitry Andric 2828*0fca6ea1SDimitry Andric void TreePattern::ComputeNamedNodes() { 2829*0fca6ea1SDimitry Andric for (TreePatternNodePtr &Tree : Trees) 2830*0fca6ea1SDimitry Andric ComputeNamedNodes(*Tree); 2831*0fca6ea1SDimitry Andric } 2832*0fca6ea1SDimitry Andric 2833*0fca6ea1SDimitry Andric void TreePattern::ComputeNamedNodes(TreePatternNode &N) { 2834*0fca6ea1SDimitry Andric if (!N.getName().empty()) 2835*0fca6ea1SDimitry Andric NamedNodes[N.getName()].push_back(&N); 2836*0fca6ea1SDimitry Andric 2837*0fca6ea1SDimitry Andric for (unsigned i = 0, e = N.getNumChildren(); i != e; ++i) 2838*0fca6ea1SDimitry Andric ComputeNamedNodes(N.getChild(i)); 2839*0fca6ea1SDimitry Andric } 2840*0fca6ea1SDimitry Andric 2841*0fca6ea1SDimitry Andric TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit, 2842*0fca6ea1SDimitry Andric StringRef OpName) { 2843*0fca6ea1SDimitry Andric RecordKeeper &RK = TheInit->getRecordKeeper(); 2844*0fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(TheInit)) { 2845*0fca6ea1SDimitry Andric Record *R = DI->getDef(); 2846*0fca6ea1SDimitry Andric 2847*0fca6ea1SDimitry Andric // Direct reference to a leaf DagNode or PatFrag? Turn it into a 2848*0fca6ea1SDimitry Andric // TreePatternNode of its own. For example: 2849*0fca6ea1SDimitry Andric /// (foo GPR, imm) -> (foo GPR, (imm)) 2850*0fca6ea1SDimitry Andric if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrags")) 2851*0fca6ea1SDimitry Andric return ParseTreePattern( 2852*0fca6ea1SDimitry Andric DagInit::get(DI, nullptr, 2853*0fca6ea1SDimitry Andric std::vector<std::pair<Init *, StringInit *>>()), 2854*0fca6ea1SDimitry Andric OpName); 2855*0fca6ea1SDimitry Andric 2856*0fca6ea1SDimitry Andric // Input argument? 2857*0fca6ea1SDimitry Andric TreePatternNodePtr Res = makeIntrusiveRefCnt<TreePatternNode>(DI, 1); 2858*0fca6ea1SDimitry Andric if (R->getName() == "node" && !OpName.empty()) { 2859*0fca6ea1SDimitry Andric if (OpName.empty()) 2860*0fca6ea1SDimitry Andric error("'node' argument requires a name to match with operand list"); 2861*0fca6ea1SDimitry Andric Args.push_back(std::string(OpName)); 2862*0fca6ea1SDimitry Andric } 2863*0fca6ea1SDimitry Andric 2864*0fca6ea1SDimitry Andric Res->setName(OpName); 2865*0fca6ea1SDimitry Andric return Res; 2866*0fca6ea1SDimitry Andric } 2867*0fca6ea1SDimitry Andric 2868*0fca6ea1SDimitry Andric // ?:$name or just $name. 2869*0fca6ea1SDimitry Andric if (isa<UnsetInit>(TheInit)) { 2870*0fca6ea1SDimitry Andric if (OpName.empty()) 2871*0fca6ea1SDimitry Andric error("'?' argument requires a name to match with operand list"); 2872*0fca6ea1SDimitry Andric TreePatternNodePtr Res = makeIntrusiveRefCnt<TreePatternNode>(TheInit, 1); 2873*0fca6ea1SDimitry Andric Args.push_back(std::string(OpName)); 2874*0fca6ea1SDimitry Andric Res->setName(OpName); 2875*0fca6ea1SDimitry Andric return Res; 2876*0fca6ea1SDimitry Andric } 2877*0fca6ea1SDimitry Andric 2878*0fca6ea1SDimitry Andric if (isa<IntInit>(TheInit) || isa<BitInit>(TheInit)) { 2879*0fca6ea1SDimitry Andric if (!OpName.empty()) 2880*0fca6ea1SDimitry Andric error("Constant int or bit argument should not have a name!"); 2881*0fca6ea1SDimitry Andric if (isa<BitInit>(TheInit)) 2882*0fca6ea1SDimitry Andric TheInit = TheInit->convertInitializerTo(IntRecTy::get(RK)); 2883*0fca6ea1SDimitry Andric return makeIntrusiveRefCnt<TreePatternNode>(TheInit, 1); 2884*0fca6ea1SDimitry Andric } 2885*0fca6ea1SDimitry Andric 2886*0fca6ea1SDimitry Andric if (BitsInit *BI = dyn_cast<BitsInit>(TheInit)) { 2887*0fca6ea1SDimitry Andric // Turn this into an IntInit. 2888*0fca6ea1SDimitry Andric Init *II = BI->convertInitializerTo(IntRecTy::get(RK)); 2889*0fca6ea1SDimitry Andric if (!II || !isa<IntInit>(II)) 2890*0fca6ea1SDimitry Andric error("Bits value must be constants!"); 2891*0fca6ea1SDimitry Andric return II ? ParseTreePattern(II, OpName) : nullptr; 2892*0fca6ea1SDimitry Andric } 2893*0fca6ea1SDimitry Andric 2894*0fca6ea1SDimitry Andric DagInit *Dag = dyn_cast<DagInit>(TheInit); 2895*0fca6ea1SDimitry Andric if (!Dag) { 2896*0fca6ea1SDimitry Andric TheInit->print(errs()); 2897*0fca6ea1SDimitry Andric error("Pattern has unexpected init kind!"); 2898*0fca6ea1SDimitry Andric return nullptr; 2899*0fca6ea1SDimitry Andric } 2900*0fca6ea1SDimitry Andric DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator()); 2901*0fca6ea1SDimitry Andric if (!OpDef) { 2902*0fca6ea1SDimitry Andric error("Pattern has unexpected operator type!"); 2903*0fca6ea1SDimitry Andric return nullptr; 2904*0fca6ea1SDimitry Andric } 2905*0fca6ea1SDimitry Andric Record *Operator = OpDef->getDef(); 2906*0fca6ea1SDimitry Andric 2907*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("ValueType")) { 2908*0fca6ea1SDimitry Andric // If the operator is a ValueType, then this must be "type cast" of a leaf 2909*0fca6ea1SDimitry Andric // node. 2910*0fca6ea1SDimitry Andric if (Dag->getNumArgs() != 1) 2911*0fca6ea1SDimitry Andric error("Type cast only takes one operand!"); 2912*0fca6ea1SDimitry Andric 2913*0fca6ea1SDimitry Andric TreePatternNodePtr New = 2914*0fca6ea1SDimitry Andric ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0)); 2915*0fca6ea1SDimitry Andric 2916*0fca6ea1SDimitry Andric // Apply the type cast. 2917*0fca6ea1SDimitry Andric if (New->getNumTypes() != 1) 2918*0fca6ea1SDimitry Andric error("Type cast can only have one type!"); 2919*0fca6ea1SDimitry Andric const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes(); 2920*0fca6ea1SDimitry Andric New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this); 2921*0fca6ea1SDimitry Andric 2922*0fca6ea1SDimitry Andric if (!OpName.empty()) 2923*0fca6ea1SDimitry Andric error("ValueType cast should not have a name!"); 2924*0fca6ea1SDimitry Andric return New; 2925*0fca6ea1SDimitry Andric } 2926*0fca6ea1SDimitry Andric 2927*0fca6ea1SDimitry Andric // Verify that this is something that makes sense for an operator. 2928*0fca6ea1SDimitry Andric if (!Operator->isSubClassOf("PatFrags") && 2929*0fca6ea1SDimitry Andric !Operator->isSubClassOf("SDNode") && 2930*0fca6ea1SDimitry Andric !Operator->isSubClassOf("Instruction") && 2931*0fca6ea1SDimitry Andric !Operator->isSubClassOf("SDNodeXForm") && 2932*0fca6ea1SDimitry Andric !Operator->isSubClassOf("Intrinsic") && 2933*0fca6ea1SDimitry Andric !Operator->isSubClassOf("ComplexPattern") && 2934*0fca6ea1SDimitry Andric Operator->getName() != "set" && Operator->getName() != "implicit") 2935*0fca6ea1SDimitry Andric error("Unrecognized node '" + Operator->getName() + "'!"); 2936*0fca6ea1SDimitry Andric 2937*0fca6ea1SDimitry Andric // Check to see if this is something that is illegal in an input pattern. 2938*0fca6ea1SDimitry Andric if (isInputPattern) { 2939*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("Instruction") || 2940*0fca6ea1SDimitry Andric Operator->isSubClassOf("SDNodeXForm")) 2941*0fca6ea1SDimitry Andric error("Cannot use '" + Operator->getName() + "' in an input pattern!"); 2942*0fca6ea1SDimitry Andric } else { 2943*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("Intrinsic")) 2944*0fca6ea1SDimitry Andric error("Cannot use '" + Operator->getName() + "' in an output pattern!"); 2945*0fca6ea1SDimitry Andric 2946*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("SDNode") && Operator->getName() != "imm" && 2947*0fca6ea1SDimitry Andric Operator->getName() != "timm" && Operator->getName() != "fpimm" && 2948*0fca6ea1SDimitry Andric Operator->getName() != "tglobaltlsaddr" && 2949*0fca6ea1SDimitry Andric Operator->getName() != "tconstpool" && 2950*0fca6ea1SDimitry Andric Operator->getName() != "tjumptable" && 2951*0fca6ea1SDimitry Andric Operator->getName() != "tframeindex" && 2952*0fca6ea1SDimitry Andric Operator->getName() != "texternalsym" && 2953*0fca6ea1SDimitry Andric Operator->getName() != "tblockaddress" && 2954*0fca6ea1SDimitry Andric Operator->getName() != "tglobaladdr" && Operator->getName() != "bb" && 2955*0fca6ea1SDimitry Andric Operator->getName() != "vt" && Operator->getName() != "mcsym") 2956*0fca6ea1SDimitry Andric error("Cannot use '" + Operator->getName() + "' in an output pattern!"); 2957*0fca6ea1SDimitry Andric } 2958*0fca6ea1SDimitry Andric 2959*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> Children; 2960*0fca6ea1SDimitry Andric 2961*0fca6ea1SDimitry Andric // Parse all the operands. 2962*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) 2963*0fca6ea1SDimitry Andric Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgNameStr(i))); 2964*0fca6ea1SDimitry Andric 2965*0fca6ea1SDimitry Andric // Get the actual number of results before Operator is converted to an 2966*0fca6ea1SDimitry Andric // intrinsic node (which is hard-coded to have either zero or one result). 2967*0fca6ea1SDimitry Andric unsigned NumResults = GetNumNodeResults(Operator, CDP); 2968*0fca6ea1SDimitry Andric 2969*0fca6ea1SDimitry Andric // If the operator is an intrinsic, then this is just syntactic sugar for 2970*0fca6ea1SDimitry Andric // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and 2971*0fca6ea1SDimitry Andric // convert the intrinsic name to a number. 2972*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("Intrinsic")) { 2973*0fca6ea1SDimitry Andric const CodeGenIntrinsic &Int = getDAGPatterns().getIntrinsic(Operator); 2974*0fca6ea1SDimitry Andric unsigned IID = getDAGPatterns().getIntrinsicID(Operator) + 1; 2975*0fca6ea1SDimitry Andric 2976*0fca6ea1SDimitry Andric // If this intrinsic returns void, it must have side-effects and thus a 2977*0fca6ea1SDimitry Andric // chain. 2978*0fca6ea1SDimitry Andric if (Int.IS.RetTys.empty()) 2979*0fca6ea1SDimitry Andric Operator = getDAGPatterns().get_intrinsic_void_sdnode(); 2980*0fca6ea1SDimitry Andric else if (!Int.ME.doesNotAccessMemory() || Int.hasSideEffects) 2981*0fca6ea1SDimitry Andric // Has side-effects, requires chain. 2982*0fca6ea1SDimitry Andric Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode(); 2983*0fca6ea1SDimitry Andric else // Otherwise, no chain. 2984*0fca6ea1SDimitry Andric Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode(); 2985*0fca6ea1SDimitry Andric 2986*0fca6ea1SDimitry Andric Children.insert(Children.begin(), makeIntrusiveRefCnt<TreePatternNode>( 2987*0fca6ea1SDimitry Andric IntInit::get(RK, IID), 1)); 2988*0fca6ea1SDimitry Andric } 2989*0fca6ea1SDimitry Andric 2990*0fca6ea1SDimitry Andric if (Operator->isSubClassOf("ComplexPattern")) { 2991*0fca6ea1SDimitry Andric for (unsigned i = 0; i < Children.size(); ++i) { 2992*0fca6ea1SDimitry Andric TreePatternNodePtr Child = Children[i]; 2993*0fca6ea1SDimitry Andric 2994*0fca6ea1SDimitry Andric if (Child->getName().empty()) 2995*0fca6ea1SDimitry Andric error("All arguments to a ComplexPattern must be named"); 2996*0fca6ea1SDimitry Andric 2997*0fca6ea1SDimitry Andric // Check that the ComplexPattern uses are consistent: "(MY_PAT $a, $b)" 2998*0fca6ea1SDimitry Andric // and "(MY_PAT $b, $a)" should not be allowed in the same pattern; 2999*0fca6ea1SDimitry Andric // neither should "(MY_PAT_1 $a, $b)" and "(MY_PAT_2 $a, $b)". 3000*0fca6ea1SDimitry Andric auto OperandId = std::pair(Operator, i); 3001*0fca6ea1SDimitry Andric auto PrevOp = ComplexPatternOperands.find(Child->getName()); 3002*0fca6ea1SDimitry Andric if (PrevOp != ComplexPatternOperands.end()) { 3003*0fca6ea1SDimitry Andric if (PrevOp->getValue() != OperandId) 3004*0fca6ea1SDimitry Andric error("All ComplexPattern operands must appear consistently: " 3005*0fca6ea1SDimitry Andric "in the same order in just one ComplexPattern instance."); 3006*0fca6ea1SDimitry Andric } else 3007*0fca6ea1SDimitry Andric ComplexPatternOperands[Child->getName()] = OperandId; 3008*0fca6ea1SDimitry Andric } 3009*0fca6ea1SDimitry Andric } 3010*0fca6ea1SDimitry Andric 3011*0fca6ea1SDimitry Andric TreePatternNodePtr Result = makeIntrusiveRefCnt<TreePatternNode>( 3012*0fca6ea1SDimitry Andric Operator, std::move(Children), NumResults); 3013*0fca6ea1SDimitry Andric Result->setName(OpName); 3014*0fca6ea1SDimitry Andric 3015*0fca6ea1SDimitry Andric if (Dag->getName()) { 3016*0fca6ea1SDimitry Andric assert(Result->getName().empty()); 3017*0fca6ea1SDimitry Andric Result->setName(Dag->getNameStr()); 3018*0fca6ea1SDimitry Andric } 3019*0fca6ea1SDimitry Andric return Result; 3020*0fca6ea1SDimitry Andric } 3021*0fca6ea1SDimitry Andric 3022*0fca6ea1SDimitry Andric /// SimplifyTree - See if we can simplify this tree to eliminate something that 3023*0fca6ea1SDimitry Andric /// will never match in favor of something obvious that will. This is here 3024*0fca6ea1SDimitry Andric /// strictly as a convenience to target authors because it allows them to write 3025*0fca6ea1SDimitry Andric /// more type generic things and have useless type casts fold away. 3026*0fca6ea1SDimitry Andric /// 3027*0fca6ea1SDimitry Andric /// This returns true if any change is made. 3028*0fca6ea1SDimitry Andric static bool SimplifyTree(TreePatternNodePtr &N) { 3029*0fca6ea1SDimitry Andric if (N->isLeaf()) 3030*0fca6ea1SDimitry Andric return false; 3031*0fca6ea1SDimitry Andric 3032*0fca6ea1SDimitry Andric // If we have a bitconvert with a resolved type and if the source and 3033*0fca6ea1SDimitry Andric // destination types are the same, then the bitconvert is useless, remove it. 3034*0fca6ea1SDimitry Andric // 3035*0fca6ea1SDimitry Andric // We make an exception if the types are completely empty. This can come up 3036*0fca6ea1SDimitry Andric // when the pattern being simplified is in the Fragments list of a PatFrags, 3037*0fca6ea1SDimitry Andric // so that the operand is just an untyped "node". In that situation we leave 3038*0fca6ea1SDimitry Andric // bitconverts unsimplified, and simplify them later once the fragment is 3039*0fca6ea1SDimitry Andric // expanded into its true context. 3040*0fca6ea1SDimitry Andric if (N->getOperator()->getName() == "bitconvert" && 3041*0fca6ea1SDimitry Andric N->getExtType(0).isValueTypeByHwMode(false) && 3042*0fca6ea1SDimitry Andric !N->getExtType(0).empty() && 3043*0fca6ea1SDimitry Andric N->getExtType(0) == N->getChild(0).getExtType(0) && 3044*0fca6ea1SDimitry Andric N->getName().empty()) { 3045*0fca6ea1SDimitry Andric N = N->getChildShared(0); 3046*0fca6ea1SDimitry Andric SimplifyTree(N); 3047*0fca6ea1SDimitry Andric return true; 3048*0fca6ea1SDimitry Andric } 3049*0fca6ea1SDimitry Andric 3050*0fca6ea1SDimitry Andric // Walk all children. 3051*0fca6ea1SDimitry Andric bool MadeChange = false; 3052*0fca6ea1SDimitry Andric for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) 3053*0fca6ea1SDimitry Andric MadeChange |= SimplifyTree(N->getChildSharedPtr(i)); 3054*0fca6ea1SDimitry Andric 3055*0fca6ea1SDimitry Andric return MadeChange; 3056*0fca6ea1SDimitry Andric } 3057*0fca6ea1SDimitry Andric 3058*0fca6ea1SDimitry Andric /// InferAllTypes - Infer/propagate as many types throughout the expression 3059*0fca6ea1SDimitry Andric /// patterns as possible. Return true if all types are inferred, false 3060*0fca6ea1SDimitry Andric /// otherwise. Flags an error if a type contradiction is found. 3061*0fca6ea1SDimitry Andric bool TreePattern::InferAllTypes( 3062*0fca6ea1SDimitry Andric const StringMap<SmallVector<TreePatternNode *, 1>> *InNamedTypes) { 3063*0fca6ea1SDimitry Andric if (NamedNodes.empty()) 3064*0fca6ea1SDimitry Andric ComputeNamedNodes(); 3065*0fca6ea1SDimitry Andric 3066*0fca6ea1SDimitry Andric bool MadeChange = true; 3067*0fca6ea1SDimitry Andric while (MadeChange) { 3068*0fca6ea1SDimitry Andric MadeChange = false; 3069*0fca6ea1SDimitry Andric for (TreePatternNodePtr &Tree : Trees) { 3070*0fca6ea1SDimitry Andric MadeChange |= Tree->ApplyTypeConstraints(*this, false); 3071*0fca6ea1SDimitry Andric MadeChange |= SimplifyTree(Tree); 3072*0fca6ea1SDimitry Andric } 3073*0fca6ea1SDimitry Andric 3074*0fca6ea1SDimitry Andric // If there are constraints on our named nodes, apply them. 3075*0fca6ea1SDimitry Andric for (auto &Entry : NamedNodes) { 3076*0fca6ea1SDimitry Andric SmallVectorImpl<TreePatternNode *> &Nodes = Entry.second; 3077*0fca6ea1SDimitry Andric 3078*0fca6ea1SDimitry Andric // If we have input named node types, propagate their types to the named 3079*0fca6ea1SDimitry Andric // values here. 3080*0fca6ea1SDimitry Andric if (InNamedTypes) { 3081*0fca6ea1SDimitry Andric if (!InNamedTypes->count(Entry.getKey())) { 3082*0fca6ea1SDimitry Andric error("Node '" + std::string(Entry.getKey()) + 3083*0fca6ea1SDimitry Andric "' in output pattern but not input pattern"); 3084*0fca6ea1SDimitry Andric return true; 3085*0fca6ea1SDimitry Andric } 3086*0fca6ea1SDimitry Andric 3087*0fca6ea1SDimitry Andric const SmallVectorImpl<TreePatternNode *> &InNodes = 3088*0fca6ea1SDimitry Andric InNamedTypes->find(Entry.getKey())->second; 3089*0fca6ea1SDimitry Andric 3090*0fca6ea1SDimitry Andric // The input types should be fully resolved by now. 3091*0fca6ea1SDimitry Andric for (TreePatternNode *Node : Nodes) { 3092*0fca6ea1SDimitry Andric // If this node is a register class, and it is the root of the pattern 3093*0fca6ea1SDimitry Andric // then we're mapping something onto an input register. We allow 3094*0fca6ea1SDimitry Andric // changing the type of the input register in this case. This allows 3095*0fca6ea1SDimitry Andric // us to match things like: 3096*0fca6ea1SDimitry Andric // def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>; 3097*0fca6ea1SDimitry Andric if (Node == Trees[0].get() && Node->isLeaf()) { 3098*0fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(Node->getLeafValue()); 3099*0fca6ea1SDimitry Andric if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || 3100*0fca6ea1SDimitry Andric DI->getDef()->isSubClassOf("RegisterOperand"))) 3101*0fca6ea1SDimitry Andric continue; 3102*0fca6ea1SDimitry Andric } 3103*0fca6ea1SDimitry Andric 3104*0fca6ea1SDimitry Andric assert(Node->getNumTypes() == 1 && InNodes[0]->getNumTypes() == 1 && 3105*0fca6ea1SDimitry Andric "FIXME: cannot name multiple result nodes yet"); 3106*0fca6ea1SDimitry Andric MadeChange |= 3107*0fca6ea1SDimitry Andric Node->UpdateNodeType(0, InNodes[0]->getExtType(0), *this); 3108*0fca6ea1SDimitry Andric } 3109*0fca6ea1SDimitry Andric } 3110*0fca6ea1SDimitry Andric 3111*0fca6ea1SDimitry Andric // If there are multiple nodes with the same name, they must all have the 3112*0fca6ea1SDimitry Andric // same type. 3113*0fca6ea1SDimitry Andric if (Entry.second.size() > 1) { 3114*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Nodes.size() - 1; i != e; ++i) { 3115*0fca6ea1SDimitry Andric TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i + 1]; 3116*0fca6ea1SDimitry Andric assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 && 3117*0fca6ea1SDimitry Andric "FIXME: cannot name multiple result nodes yet"); 3118*0fca6ea1SDimitry Andric 3119*0fca6ea1SDimitry Andric MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this); 3120*0fca6ea1SDimitry Andric MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this); 3121*0fca6ea1SDimitry Andric } 3122*0fca6ea1SDimitry Andric } 3123*0fca6ea1SDimitry Andric } 3124*0fca6ea1SDimitry Andric } 3125*0fca6ea1SDimitry Andric 3126*0fca6ea1SDimitry Andric bool HasUnresolvedTypes = false; 3127*0fca6ea1SDimitry Andric for (const TreePatternNodePtr &Tree : Trees) 3128*0fca6ea1SDimitry Andric HasUnresolvedTypes |= Tree->ContainsUnresolvedType(*this); 3129*0fca6ea1SDimitry Andric return !HasUnresolvedTypes; 3130*0fca6ea1SDimitry Andric } 3131*0fca6ea1SDimitry Andric 3132*0fca6ea1SDimitry Andric void TreePattern::print(raw_ostream &OS) const { 3133*0fca6ea1SDimitry Andric OS << getRecord()->getName(); 3134*0fca6ea1SDimitry Andric if (!Args.empty()) { 3135*0fca6ea1SDimitry Andric OS << "("; 3136*0fca6ea1SDimitry Andric ListSeparator LS; 3137*0fca6ea1SDimitry Andric for (const std::string &Arg : Args) 3138*0fca6ea1SDimitry Andric OS << LS << Arg; 3139*0fca6ea1SDimitry Andric OS << ")"; 3140*0fca6ea1SDimitry Andric } 3141*0fca6ea1SDimitry Andric OS << ": "; 3142*0fca6ea1SDimitry Andric 3143*0fca6ea1SDimitry Andric if (Trees.size() > 1) 3144*0fca6ea1SDimitry Andric OS << "[\n"; 3145*0fca6ea1SDimitry Andric for (const TreePatternNodePtr &Tree : Trees) { 3146*0fca6ea1SDimitry Andric OS << "\t"; 3147*0fca6ea1SDimitry Andric Tree->print(OS); 3148*0fca6ea1SDimitry Andric OS << "\n"; 3149*0fca6ea1SDimitry Andric } 3150*0fca6ea1SDimitry Andric 3151*0fca6ea1SDimitry Andric if (Trees.size() > 1) 3152*0fca6ea1SDimitry Andric OS << "]\n"; 3153*0fca6ea1SDimitry Andric } 3154*0fca6ea1SDimitry Andric 3155*0fca6ea1SDimitry Andric void TreePattern::dump() const { print(errs()); } 3156*0fca6ea1SDimitry Andric 3157*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 3158*0fca6ea1SDimitry Andric // CodeGenDAGPatterns implementation 3159*0fca6ea1SDimitry Andric // 3160*0fca6ea1SDimitry Andric 3161*0fca6ea1SDimitry Andric CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R, 3162*0fca6ea1SDimitry Andric PatternRewriterFn PatternRewriter) 3163*0fca6ea1SDimitry Andric : Records(R), Target(R), LegalVTS(Target.getLegalValueTypes()), 3164*0fca6ea1SDimitry Andric PatternRewriter(PatternRewriter) { 3165*0fca6ea1SDimitry Andric 3166*0fca6ea1SDimitry Andric Intrinsics = CodeGenIntrinsicTable(Records); 3167*0fca6ea1SDimitry Andric ParseNodeInfo(); 3168*0fca6ea1SDimitry Andric ParseNodeTransforms(); 3169*0fca6ea1SDimitry Andric ParseComplexPatterns(); 3170*0fca6ea1SDimitry Andric ParsePatternFragments(); 3171*0fca6ea1SDimitry Andric ParseDefaultOperands(); 3172*0fca6ea1SDimitry Andric ParseInstructions(); 3173*0fca6ea1SDimitry Andric ParsePatternFragments(/*OutFrags*/ true); 3174*0fca6ea1SDimitry Andric ParsePatterns(); 3175*0fca6ea1SDimitry Andric 3176*0fca6ea1SDimitry Andric // Generate variants. For example, commutative patterns can match 3177*0fca6ea1SDimitry Andric // multiple ways. Add them to PatternsToMatch as well. 3178*0fca6ea1SDimitry Andric GenerateVariants(); 3179*0fca6ea1SDimitry Andric 3180*0fca6ea1SDimitry Andric // Break patterns with parameterized types into a series of patterns, 3181*0fca6ea1SDimitry Andric // where each one has a fixed type and is predicated on the conditions 3182*0fca6ea1SDimitry Andric // of the associated HW mode. 3183*0fca6ea1SDimitry Andric ExpandHwModeBasedTypes(); 3184*0fca6ea1SDimitry Andric 3185*0fca6ea1SDimitry Andric // Infer instruction flags. For example, we can detect loads, 3186*0fca6ea1SDimitry Andric // stores, and side effects in many cases by examining an 3187*0fca6ea1SDimitry Andric // instruction's pattern. 3188*0fca6ea1SDimitry Andric InferInstructionFlags(); 3189*0fca6ea1SDimitry Andric 3190*0fca6ea1SDimitry Andric // Verify that instruction flags match the patterns. 3191*0fca6ea1SDimitry Andric VerifyInstructionFlags(); 3192*0fca6ea1SDimitry Andric } 3193*0fca6ea1SDimitry Andric 3194*0fca6ea1SDimitry Andric Record *CodeGenDAGPatterns::getSDNodeNamed(StringRef Name) const { 3195*0fca6ea1SDimitry Andric Record *N = Records.getDef(Name); 3196*0fca6ea1SDimitry Andric if (!N || !N->isSubClassOf("SDNode")) 3197*0fca6ea1SDimitry Andric PrintFatalError("Error getting SDNode '" + Name + "'!"); 3198*0fca6ea1SDimitry Andric 3199*0fca6ea1SDimitry Andric return N; 3200*0fca6ea1SDimitry Andric } 3201*0fca6ea1SDimitry Andric 3202*0fca6ea1SDimitry Andric // Parse all of the SDNode definitions for the target, populating SDNodes. 3203*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseNodeInfo() { 3204*0fca6ea1SDimitry Andric std::vector<Record *> Nodes = Records.getAllDerivedDefinitions("SDNode"); 3205*0fca6ea1SDimitry Andric const CodeGenHwModes &CGH = getTargetInfo().getHwModes(); 3206*0fca6ea1SDimitry Andric 3207*0fca6ea1SDimitry Andric while (!Nodes.empty()) { 3208*0fca6ea1SDimitry Andric Record *R = Nodes.back(); 3209*0fca6ea1SDimitry Andric SDNodes.insert(std::pair(R, SDNodeInfo(R, CGH))); 3210*0fca6ea1SDimitry Andric Nodes.pop_back(); 3211*0fca6ea1SDimitry Andric } 3212*0fca6ea1SDimitry Andric 3213*0fca6ea1SDimitry Andric // Get the builtin intrinsic nodes. 3214*0fca6ea1SDimitry Andric intrinsic_void_sdnode = getSDNodeNamed("intrinsic_void"); 3215*0fca6ea1SDimitry Andric intrinsic_w_chain_sdnode = getSDNodeNamed("intrinsic_w_chain"); 3216*0fca6ea1SDimitry Andric intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain"); 3217*0fca6ea1SDimitry Andric } 3218*0fca6ea1SDimitry Andric 3219*0fca6ea1SDimitry Andric /// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms 3220*0fca6ea1SDimitry Andric /// map, and emit them to the file as functions. 3221*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseNodeTransforms() { 3222*0fca6ea1SDimitry Andric std::vector<Record *> Xforms = 3223*0fca6ea1SDimitry Andric Records.getAllDerivedDefinitions("SDNodeXForm"); 3224*0fca6ea1SDimitry Andric while (!Xforms.empty()) { 3225*0fca6ea1SDimitry Andric Record *XFormNode = Xforms.back(); 3226*0fca6ea1SDimitry Andric Record *SDNode = XFormNode->getValueAsDef("Opcode"); 3227*0fca6ea1SDimitry Andric StringRef Code = XFormNode->getValueAsString("XFormFunction"); 3228*0fca6ea1SDimitry Andric SDNodeXForms.insert( 3229*0fca6ea1SDimitry Andric std::pair(XFormNode, NodeXForm(SDNode, std::string(Code)))); 3230*0fca6ea1SDimitry Andric 3231*0fca6ea1SDimitry Andric Xforms.pop_back(); 3232*0fca6ea1SDimitry Andric } 3233*0fca6ea1SDimitry Andric } 3234*0fca6ea1SDimitry Andric 3235*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseComplexPatterns() { 3236*0fca6ea1SDimitry Andric std::vector<Record *> AMs = 3237*0fca6ea1SDimitry Andric Records.getAllDerivedDefinitions("ComplexPattern"); 3238*0fca6ea1SDimitry Andric while (!AMs.empty()) { 3239*0fca6ea1SDimitry Andric ComplexPatterns.insert(std::pair(AMs.back(), AMs.back())); 3240*0fca6ea1SDimitry Andric AMs.pop_back(); 3241*0fca6ea1SDimitry Andric } 3242*0fca6ea1SDimitry Andric } 3243*0fca6ea1SDimitry Andric 3244*0fca6ea1SDimitry Andric /// ParsePatternFragments - Parse all of the PatFrag definitions in the .td 3245*0fca6ea1SDimitry Andric /// file, building up the PatternFragments map. After we've collected them all, 3246*0fca6ea1SDimitry Andric /// inline fragments together as necessary, so that there are no references left 3247*0fca6ea1SDimitry Andric /// inside a pattern fragment to a pattern fragment. 3248*0fca6ea1SDimitry Andric /// 3249*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { 3250*0fca6ea1SDimitry Andric std::vector<Record *> Fragments = 3251*0fca6ea1SDimitry Andric Records.getAllDerivedDefinitions("PatFrags"); 3252*0fca6ea1SDimitry Andric 3253*0fca6ea1SDimitry Andric // First step, parse all of the fragments. 3254*0fca6ea1SDimitry Andric for (Record *Frag : Fragments) { 3255*0fca6ea1SDimitry Andric if (OutFrags != Frag->isSubClassOf("OutPatFrag")) 3256*0fca6ea1SDimitry Andric continue; 3257*0fca6ea1SDimitry Andric 3258*0fca6ea1SDimitry Andric ListInit *LI = Frag->getValueAsListInit("Fragments"); 3259*0fca6ea1SDimitry Andric TreePattern *P = (PatternFragments[Frag] = std::make_unique<TreePattern>( 3260*0fca6ea1SDimitry Andric Frag, LI, !Frag->isSubClassOf("OutPatFrag"), *this)) 3261*0fca6ea1SDimitry Andric .get(); 3262*0fca6ea1SDimitry Andric 3263*0fca6ea1SDimitry Andric // Validate the argument list, converting it to set, to discard duplicates. 3264*0fca6ea1SDimitry Andric std::vector<std::string> &Args = P->getArgList(); 3265*0fca6ea1SDimitry Andric // Copy the args so we can take StringRefs to them. 3266*0fca6ea1SDimitry Andric auto ArgsCopy = Args; 3267*0fca6ea1SDimitry Andric SmallDenseSet<StringRef, 4> OperandsSet; 3268*0fca6ea1SDimitry Andric OperandsSet.insert(ArgsCopy.begin(), ArgsCopy.end()); 3269*0fca6ea1SDimitry Andric 3270*0fca6ea1SDimitry Andric if (OperandsSet.count("")) 3271*0fca6ea1SDimitry Andric P->error("Cannot have unnamed 'node' values in pattern fragment!"); 3272*0fca6ea1SDimitry Andric 3273*0fca6ea1SDimitry Andric // Parse the operands list. 3274*0fca6ea1SDimitry Andric DagInit *OpsList = Frag->getValueAsDag("Operands"); 3275*0fca6ea1SDimitry Andric DefInit *OpsOp = dyn_cast<DefInit>(OpsList->getOperator()); 3276*0fca6ea1SDimitry Andric // Special cases: ops == outs == ins. Different names are used to 3277*0fca6ea1SDimitry Andric // improve readability. 3278*0fca6ea1SDimitry Andric if (!OpsOp || (OpsOp->getDef()->getName() != "ops" && 3279*0fca6ea1SDimitry Andric OpsOp->getDef()->getName() != "outs" && 3280*0fca6ea1SDimitry Andric OpsOp->getDef()->getName() != "ins")) 3281*0fca6ea1SDimitry Andric P->error("Operands list should start with '(ops ... '!"); 3282*0fca6ea1SDimitry Andric 3283*0fca6ea1SDimitry Andric // Copy over the arguments. 3284*0fca6ea1SDimitry Andric Args.clear(); 3285*0fca6ea1SDimitry Andric for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) { 3286*0fca6ea1SDimitry Andric if (!isa<DefInit>(OpsList->getArg(j)) || 3287*0fca6ea1SDimitry Andric cast<DefInit>(OpsList->getArg(j))->getDef()->getName() != "node") 3288*0fca6ea1SDimitry Andric P->error("Operands list should all be 'node' values."); 3289*0fca6ea1SDimitry Andric if (!OpsList->getArgName(j)) 3290*0fca6ea1SDimitry Andric P->error("Operands list should have names for each operand!"); 3291*0fca6ea1SDimitry Andric StringRef ArgNameStr = OpsList->getArgNameStr(j); 3292*0fca6ea1SDimitry Andric if (!OperandsSet.count(ArgNameStr)) 3293*0fca6ea1SDimitry Andric P->error("'" + ArgNameStr + 3294*0fca6ea1SDimitry Andric "' does not occur in pattern or was multiply specified!"); 3295*0fca6ea1SDimitry Andric OperandsSet.erase(ArgNameStr); 3296*0fca6ea1SDimitry Andric Args.push_back(std::string(ArgNameStr)); 3297*0fca6ea1SDimitry Andric } 3298*0fca6ea1SDimitry Andric 3299*0fca6ea1SDimitry Andric if (!OperandsSet.empty()) 3300*0fca6ea1SDimitry Andric P->error("Operands list does not contain an entry for operand '" + 3301*0fca6ea1SDimitry Andric *OperandsSet.begin() + "'!"); 3302*0fca6ea1SDimitry Andric 3303*0fca6ea1SDimitry Andric // If there is a node transformation corresponding to this, keep track of 3304*0fca6ea1SDimitry Andric // it. 3305*0fca6ea1SDimitry Andric Record *Transform = Frag->getValueAsDef("OperandTransform"); 3306*0fca6ea1SDimitry Andric if (!getSDNodeTransform(Transform).second.empty()) // not noop xform? 3307*0fca6ea1SDimitry Andric for (const auto &T : P->getTrees()) 3308*0fca6ea1SDimitry Andric T->setTransformFn(Transform); 3309*0fca6ea1SDimitry Andric } 3310*0fca6ea1SDimitry Andric 3311*0fca6ea1SDimitry Andric // Now that we've parsed all of the tree fragments, do a closure on them so 3312*0fca6ea1SDimitry Andric // that there are not references to PatFrags left inside of them. 3313*0fca6ea1SDimitry Andric for (Record *Frag : Fragments) { 3314*0fca6ea1SDimitry Andric if (OutFrags != Frag->isSubClassOf("OutPatFrag")) 3315*0fca6ea1SDimitry Andric continue; 3316*0fca6ea1SDimitry Andric 3317*0fca6ea1SDimitry Andric TreePattern &ThePat = *PatternFragments[Frag]; 3318*0fca6ea1SDimitry Andric ThePat.InlinePatternFragments(); 3319*0fca6ea1SDimitry Andric 3320*0fca6ea1SDimitry Andric // Infer as many types as possible. Don't worry about it if we don't infer 3321*0fca6ea1SDimitry Andric // all of them, some may depend on the inputs of the pattern. Also, don't 3322*0fca6ea1SDimitry Andric // validate type sets; validation may cause spurious failures e.g. if a 3323*0fca6ea1SDimitry Andric // fragment needs floating-point types but the current target does not have 3324*0fca6ea1SDimitry Andric // any (this is only an error if that fragment is ever used!). 3325*0fca6ea1SDimitry Andric { 3326*0fca6ea1SDimitry Andric TypeInfer::SuppressValidation SV(ThePat.getInfer()); 3327*0fca6ea1SDimitry Andric ThePat.InferAllTypes(); 3328*0fca6ea1SDimitry Andric ThePat.resetError(); 3329*0fca6ea1SDimitry Andric } 3330*0fca6ea1SDimitry Andric 3331*0fca6ea1SDimitry Andric // If debugging, print out the pattern fragment result. 3332*0fca6ea1SDimitry Andric LLVM_DEBUG(ThePat.dump()); 3333*0fca6ea1SDimitry Andric } 3334*0fca6ea1SDimitry Andric } 3335*0fca6ea1SDimitry Andric 3336*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseDefaultOperands() { 3337*0fca6ea1SDimitry Andric std::vector<Record *> DefaultOps; 3338*0fca6ea1SDimitry Andric DefaultOps = Records.getAllDerivedDefinitions("OperandWithDefaultOps"); 3339*0fca6ea1SDimitry Andric 3340*0fca6ea1SDimitry Andric // Find some SDNode. 3341*0fca6ea1SDimitry Andric assert(!SDNodes.empty() && "No SDNodes parsed?"); 3342*0fca6ea1SDimitry Andric Init *SomeSDNode = DefInit::get(SDNodes.begin()->first); 3343*0fca6ea1SDimitry Andric 3344*0fca6ea1SDimitry Andric for (unsigned i = 0, e = DefaultOps.size(); i != e; ++i) { 3345*0fca6ea1SDimitry Andric DagInit *DefaultInfo = DefaultOps[i]->getValueAsDag("DefaultOps"); 3346*0fca6ea1SDimitry Andric 3347*0fca6ea1SDimitry Andric // Clone the DefaultInfo dag node, changing the operator from 'ops' to 3348*0fca6ea1SDimitry Andric // SomeSDnode so that we can parse this. 3349*0fca6ea1SDimitry Andric std::vector<std::pair<Init *, StringInit *>> Ops; 3350*0fca6ea1SDimitry Andric for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op) 3351*0fca6ea1SDimitry Andric Ops.push_back( 3352*0fca6ea1SDimitry Andric std::pair(DefaultInfo->getArg(op), DefaultInfo->getArgName(op))); 3353*0fca6ea1SDimitry Andric DagInit *DI = DagInit::get(SomeSDNode, nullptr, Ops); 3354*0fca6ea1SDimitry Andric 3355*0fca6ea1SDimitry Andric // Create a TreePattern to parse this. 3356*0fca6ea1SDimitry Andric TreePattern P(DefaultOps[i], DI, false, *this); 3357*0fca6ea1SDimitry Andric assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!"); 3358*0fca6ea1SDimitry Andric 3359*0fca6ea1SDimitry Andric // Copy the operands over into a DAGDefaultOperand. 3360*0fca6ea1SDimitry Andric DAGDefaultOperand DefaultOpInfo; 3361*0fca6ea1SDimitry Andric 3362*0fca6ea1SDimitry Andric const TreePatternNodePtr &T = P.getTree(0); 3363*0fca6ea1SDimitry Andric for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) { 3364*0fca6ea1SDimitry Andric TreePatternNodePtr TPN = T->getChildShared(op); 3365*0fca6ea1SDimitry Andric while (TPN->ApplyTypeConstraints(P, false)) 3366*0fca6ea1SDimitry Andric /* Resolve all types */; 3367*0fca6ea1SDimitry Andric 3368*0fca6ea1SDimitry Andric if (TPN->ContainsUnresolvedType(P)) { 3369*0fca6ea1SDimitry Andric PrintFatalError("Value #" + Twine(i) + " of OperandWithDefaultOps '" + 3370*0fca6ea1SDimitry Andric DefaultOps[i]->getName() + 3371*0fca6ea1SDimitry Andric "' doesn't have a concrete type!"); 3372*0fca6ea1SDimitry Andric } 3373*0fca6ea1SDimitry Andric DefaultOpInfo.DefaultOps.push_back(std::move(TPN)); 3374*0fca6ea1SDimitry Andric } 3375*0fca6ea1SDimitry Andric 3376*0fca6ea1SDimitry Andric // Insert it into the DefaultOperands map so we can find it later. 3377*0fca6ea1SDimitry Andric DefaultOperands[DefaultOps[i]] = DefaultOpInfo; 3378*0fca6ea1SDimitry Andric } 3379*0fca6ea1SDimitry Andric } 3380*0fca6ea1SDimitry Andric 3381*0fca6ea1SDimitry Andric /// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an 3382*0fca6ea1SDimitry Andric /// instruction input. Return true if this is a real use. 3383*0fca6ea1SDimitry Andric static bool HandleUse(TreePattern &I, TreePatternNodePtr Pat, 3384*0fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> &InstInputs) { 3385*0fca6ea1SDimitry Andric // No name -> not interesting. 3386*0fca6ea1SDimitry Andric if (Pat->getName().empty()) { 3387*0fca6ea1SDimitry Andric if (Pat->isLeaf()) { 3388*0fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue()); 3389*0fca6ea1SDimitry Andric if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || 3390*0fca6ea1SDimitry Andric DI->getDef()->isSubClassOf("RegisterOperand"))) 3391*0fca6ea1SDimitry Andric I.error("Input " + DI->getDef()->getName() + " must be named!"); 3392*0fca6ea1SDimitry Andric } 3393*0fca6ea1SDimitry Andric return false; 3394*0fca6ea1SDimitry Andric } 3395*0fca6ea1SDimitry Andric 3396*0fca6ea1SDimitry Andric Record *Rec; 3397*0fca6ea1SDimitry Andric if (Pat->isLeaf()) { 3398*0fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue()); 3399*0fca6ea1SDimitry Andric if (!DI) 3400*0fca6ea1SDimitry Andric I.error("Input $" + Pat->getName() + " must be an identifier!"); 3401*0fca6ea1SDimitry Andric Rec = DI->getDef(); 3402*0fca6ea1SDimitry Andric } else { 3403*0fca6ea1SDimitry Andric Rec = Pat->getOperator(); 3404*0fca6ea1SDimitry Andric } 3405*0fca6ea1SDimitry Andric 3406*0fca6ea1SDimitry Andric // SRCVALUE nodes are ignored. 3407*0fca6ea1SDimitry Andric if (Rec->getName() == "srcvalue") 3408*0fca6ea1SDimitry Andric return false; 3409*0fca6ea1SDimitry Andric 3410*0fca6ea1SDimitry Andric TreePatternNodePtr &Slot = InstInputs[Pat->getName()]; 3411*0fca6ea1SDimitry Andric if (!Slot) { 3412*0fca6ea1SDimitry Andric Slot = Pat; 3413*0fca6ea1SDimitry Andric return true; 3414*0fca6ea1SDimitry Andric } 3415*0fca6ea1SDimitry Andric Record *SlotRec; 3416*0fca6ea1SDimitry Andric if (Slot->isLeaf()) { 3417*0fca6ea1SDimitry Andric SlotRec = cast<DefInit>(Slot->getLeafValue())->getDef(); 3418*0fca6ea1SDimitry Andric } else { 3419*0fca6ea1SDimitry Andric assert(Slot->getNumChildren() == 0 && "can't be a use with children!"); 3420*0fca6ea1SDimitry Andric SlotRec = Slot->getOperator(); 3421*0fca6ea1SDimitry Andric } 3422*0fca6ea1SDimitry Andric 3423*0fca6ea1SDimitry Andric // Ensure that the inputs agree if we've already seen this input. 3424*0fca6ea1SDimitry Andric if (Rec != SlotRec) 3425*0fca6ea1SDimitry Andric I.error("All $" + Pat->getName() + " inputs must agree with each other"); 3426*0fca6ea1SDimitry Andric // Ensure that the types can agree as well. 3427*0fca6ea1SDimitry Andric Slot->UpdateNodeType(0, Pat->getExtType(0), I); 3428*0fca6ea1SDimitry Andric Pat->UpdateNodeType(0, Slot->getExtType(0), I); 3429*0fca6ea1SDimitry Andric if (Slot->getExtTypes() != Pat->getExtTypes()) 3430*0fca6ea1SDimitry Andric I.error("All $" + Pat->getName() + " inputs must agree with each other"); 3431*0fca6ea1SDimitry Andric return true; 3432*0fca6ea1SDimitry Andric } 3433*0fca6ea1SDimitry Andric 3434*0fca6ea1SDimitry Andric /// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is 3435*0fca6ea1SDimitry Andric /// part of "I", the instruction), computing the set of inputs and outputs of 3436*0fca6ea1SDimitry Andric /// the pattern. Report errors if we see anything naughty. 3437*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::FindPatternInputsAndOutputs( 3438*0fca6ea1SDimitry Andric TreePattern &I, TreePatternNodePtr Pat, 3439*0fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> &InstInputs, 3440*0fca6ea1SDimitry Andric MapVector<std::string, TreePatternNodePtr, std::map<std::string, unsigned>> 3441*0fca6ea1SDimitry Andric &InstResults, 3442*0fca6ea1SDimitry Andric std::vector<Record *> &InstImpResults) { 3443*0fca6ea1SDimitry Andric 3444*0fca6ea1SDimitry Andric // The instruction pattern still has unresolved fragments. For *named* 3445*0fca6ea1SDimitry Andric // nodes we must resolve those here. This may not result in multiple 3446*0fca6ea1SDimitry Andric // alternatives. 3447*0fca6ea1SDimitry Andric if (!Pat->getName().empty()) { 3448*0fca6ea1SDimitry Andric TreePattern SrcPattern(I.getRecord(), Pat, true, *this); 3449*0fca6ea1SDimitry Andric SrcPattern.InlinePatternFragments(); 3450*0fca6ea1SDimitry Andric SrcPattern.InferAllTypes(); 3451*0fca6ea1SDimitry Andric Pat = SrcPattern.getOnlyTree(); 3452*0fca6ea1SDimitry Andric } 3453*0fca6ea1SDimitry Andric 3454*0fca6ea1SDimitry Andric if (Pat->isLeaf()) { 3455*0fca6ea1SDimitry Andric bool isUse = HandleUse(I, Pat, InstInputs); 3456*0fca6ea1SDimitry Andric if (!isUse && Pat->getTransformFn()) 3457*0fca6ea1SDimitry Andric I.error("Cannot specify a transform function for a non-input value!"); 3458*0fca6ea1SDimitry Andric return; 3459*0fca6ea1SDimitry Andric } 3460*0fca6ea1SDimitry Andric 3461*0fca6ea1SDimitry Andric if (Pat->getOperator()->getName() == "implicit") { 3462*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { 3463*0fca6ea1SDimitry Andric TreePatternNode &Dest = Pat->getChild(i); 3464*0fca6ea1SDimitry Andric if (!Dest.isLeaf()) 3465*0fca6ea1SDimitry Andric I.error("implicitly defined value should be a register!"); 3466*0fca6ea1SDimitry Andric 3467*0fca6ea1SDimitry Andric DefInit *Val = dyn_cast<DefInit>(Dest.getLeafValue()); 3468*0fca6ea1SDimitry Andric if (!Val || !Val->getDef()->isSubClassOf("Register")) 3469*0fca6ea1SDimitry Andric I.error("implicitly defined value should be a register!"); 3470*0fca6ea1SDimitry Andric if (Val) 3471*0fca6ea1SDimitry Andric InstImpResults.push_back(Val->getDef()); 3472*0fca6ea1SDimitry Andric } 3473*0fca6ea1SDimitry Andric return; 3474*0fca6ea1SDimitry Andric } 3475*0fca6ea1SDimitry Andric 3476*0fca6ea1SDimitry Andric if (Pat->getOperator()->getName() != "set") { 3477*0fca6ea1SDimitry Andric // If this is not a set, verify that the children nodes are not void typed, 3478*0fca6ea1SDimitry Andric // and recurse. 3479*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { 3480*0fca6ea1SDimitry Andric if (Pat->getChild(i).getNumTypes() == 0) 3481*0fca6ea1SDimitry Andric I.error("Cannot have void nodes inside of patterns!"); 3482*0fca6ea1SDimitry Andric FindPatternInputsAndOutputs(I, Pat->getChildShared(i), InstInputs, 3483*0fca6ea1SDimitry Andric InstResults, InstImpResults); 3484*0fca6ea1SDimitry Andric } 3485*0fca6ea1SDimitry Andric 3486*0fca6ea1SDimitry Andric // If this is a non-leaf node with no children, treat it basically as if 3487*0fca6ea1SDimitry Andric // it were a leaf. This handles nodes like (imm). 3488*0fca6ea1SDimitry Andric bool isUse = HandleUse(I, Pat, InstInputs); 3489*0fca6ea1SDimitry Andric 3490*0fca6ea1SDimitry Andric if (!isUse && Pat->getTransformFn()) 3491*0fca6ea1SDimitry Andric I.error("Cannot specify a transform function for a non-input value!"); 3492*0fca6ea1SDimitry Andric return; 3493*0fca6ea1SDimitry Andric } 3494*0fca6ea1SDimitry Andric 3495*0fca6ea1SDimitry Andric // Otherwise, this is a set, validate and collect instruction results. 3496*0fca6ea1SDimitry Andric if (Pat->getNumChildren() == 0) 3497*0fca6ea1SDimitry Andric I.error("set requires operands!"); 3498*0fca6ea1SDimitry Andric 3499*0fca6ea1SDimitry Andric if (Pat->getTransformFn()) 3500*0fca6ea1SDimitry Andric I.error("Cannot specify a transform function on a set node!"); 3501*0fca6ea1SDimitry Andric 3502*0fca6ea1SDimitry Andric // Check the set destinations. 3503*0fca6ea1SDimitry Andric unsigned NumDests = Pat->getNumChildren() - 1; 3504*0fca6ea1SDimitry Andric for (unsigned i = 0; i != NumDests; ++i) { 3505*0fca6ea1SDimitry Andric TreePatternNodePtr Dest = Pat->getChildShared(i); 3506*0fca6ea1SDimitry Andric // For set destinations we also must resolve fragments here. 3507*0fca6ea1SDimitry Andric TreePattern DestPattern(I.getRecord(), Dest, false, *this); 3508*0fca6ea1SDimitry Andric DestPattern.InlinePatternFragments(); 3509*0fca6ea1SDimitry Andric DestPattern.InferAllTypes(); 3510*0fca6ea1SDimitry Andric Dest = DestPattern.getOnlyTree(); 3511*0fca6ea1SDimitry Andric 3512*0fca6ea1SDimitry Andric if (!Dest->isLeaf()) 3513*0fca6ea1SDimitry Andric I.error("set destination should be a register!"); 3514*0fca6ea1SDimitry Andric 3515*0fca6ea1SDimitry Andric DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue()); 3516*0fca6ea1SDimitry Andric if (!Val) { 3517*0fca6ea1SDimitry Andric I.error("set destination should be a register!"); 3518*0fca6ea1SDimitry Andric continue; 3519*0fca6ea1SDimitry Andric } 3520*0fca6ea1SDimitry Andric 3521*0fca6ea1SDimitry Andric if (Val->getDef()->isSubClassOf("RegisterClass") || 3522*0fca6ea1SDimitry Andric Val->getDef()->isSubClassOf("ValueType") || 3523*0fca6ea1SDimitry Andric Val->getDef()->isSubClassOf("RegisterOperand") || 3524*0fca6ea1SDimitry Andric Val->getDef()->isSubClassOf("PointerLikeRegClass")) { 3525*0fca6ea1SDimitry Andric if (Dest->getName().empty()) 3526*0fca6ea1SDimitry Andric I.error("set destination must have a name!"); 3527*0fca6ea1SDimitry Andric if (InstResults.count(Dest->getName())) 3528*0fca6ea1SDimitry Andric I.error("cannot set '" + Dest->getName() + "' multiple times"); 3529*0fca6ea1SDimitry Andric InstResults[Dest->getName()] = Dest; 3530*0fca6ea1SDimitry Andric } else if (Val->getDef()->isSubClassOf("Register")) { 3531*0fca6ea1SDimitry Andric InstImpResults.push_back(Val->getDef()); 3532*0fca6ea1SDimitry Andric } else { 3533*0fca6ea1SDimitry Andric I.error("set destination should be a register!"); 3534*0fca6ea1SDimitry Andric } 3535*0fca6ea1SDimitry Andric } 3536*0fca6ea1SDimitry Andric 3537*0fca6ea1SDimitry Andric // Verify and collect info from the computation. 3538*0fca6ea1SDimitry Andric FindPatternInputsAndOutputs(I, Pat->getChildShared(NumDests), InstInputs, 3539*0fca6ea1SDimitry Andric InstResults, InstImpResults); 3540*0fca6ea1SDimitry Andric } 3541*0fca6ea1SDimitry Andric 3542*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 3543*0fca6ea1SDimitry Andric // Instruction Analysis 3544*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 3545*0fca6ea1SDimitry Andric 3546*0fca6ea1SDimitry Andric class InstAnalyzer { 3547*0fca6ea1SDimitry Andric const CodeGenDAGPatterns &CDP; 3548*0fca6ea1SDimitry Andric 3549*0fca6ea1SDimitry Andric public: 3550*0fca6ea1SDimitry Andric bool hasSideEffects; 3551*0fca6ea1SDimitry Andric bool mayStore; 3552*0fca6ea1SDimitry Andric bool mayLoad; 3553*0fca6ea1SDimitry Andric bool isBitcast; 3554*0fca6ea1SDimitry Andric bool isVariadic; 3555*0fca6ea1SDimitry Andric bool hasChain; 3556*0fca6ea1SDimitry Andric 3557*0fca6ea1SDimitry Andric InstAnalyzer(const CodeGenDAGPatterns &cdp) 3558*0fca6ea1SDimitry Andric : CDP(cdp), hasSideEffects(false), mayStore(false), mayLoad(false), 3559*0fca6ea1SDimitry Andric isBitcast(false), isVariadic(false), hasChain(false) {} 3560*0fca6ea1SDimitry Andric 3561*0fca6ea1SDimitry Andric void Analyze(const PatternToMatch &Pat) { 3562*0fca6ea1SDimitry Andric const TreePatternNode &N = Pat.getSrcPattern(); 3563*0fca6ea1SDimitry Andric AnalyzeNode(N); 3564*0fca6ea1SDimitry Andric // These properties are detected only on the root node. 3565*0fca6ea1SDimitry Andric isBitcast = IsNodeBitcast(N); 3566*0fca6ea1SDimitry Andric } 3567*0fca6ea1SDimitry Andric 3568*0fca6ea1SDimitry Andric private: 3569*0fca6ea1SDimitry Andric bool IsNodeBitcast(const TreePatternNode &N) const { 3570*0fca6ea1SDimitry Andric if (hasSideEffects || mayLoad || mayStore || isVariadic) 3571*0fca6ea1SDimitry Andric return false; 3572*0fca6ea1SDimitry Andric 3573*0fca6ea1SDimitry Andric if (N.isLeaf()) 3574*0fca6ea1SDimitry Andric return false; 3575*0fca6ea1SDimitry Andric if (N.getNumChildren() != 1 || !N.getChild(0).isLeaf()) 3576*0fca6ea1SDimitry Andric return false; 3577*0fca6ea1SDimitry Andric 3578*0fca6ea1SDimitry Andric if (N.getOperator()->isSubClassOf("ComplexPattern")) 3579*0fca6ea1SDimitry Andric return false; 3580*0fca6ea1SDimitry Andric 3581*0fca6ea1SDimitry Andric const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N.getOperator()); 3582*0fca6ea1SDimitry Andric if (OpInfo.getNumResults() != 1 || OpInfo.getNumOperands() != 1) 3583*0fca6ea1SDimitry Andric return false; 3584*0fca6ea1SDimitry Andric return OpInfo.getEnumName() == "ISD::BITCAST"; 3585*0fca6ea1SDimitry Andric } 3586*0fca6ea1SDimitry Andric 3587*0fca6ea1SDimitry Andric public: 3588*0fca6ea1SDimitry Andric void AnalyzeNode(const TreePatternNode &N) { 3589*0fca6ea1SDimitry Andric if (N.isLeaf()) { 3590*0fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(N.getLeafValue())) { 3591*0fca6ea1SDimitry Andric Record *LeafRec = DI->getDef(); 3592*0fca6ea1SDimitry Andric // Handle ComplexPattern leaves. 3593*0fca6ea1SDimitry Andric if (LeafRec->isSubClassOf("ComplexPattern")) { 3594*0fca6ea1SDimitry Andric const ComplexPattern &CP = CDP.getComplexPattern(LeafRec); 3595*0fca6ea1SDimitry Andric if (CP.hasProperty(SDNPMayStore)) 3596*0fca6ea1SDimitry Andric mayStore = true; 3597*0fca6ea1SDimitry Andric if (CP.hasProperty(SDNPMayLoad)) 3598*0fca6ea1SDimitry Andric mayLoad = true; 3599*0fca6ea1SDimitry Andric if (CP.hasProperty(SDNPSideEffect)) 3600*0fca6ea1SDimitry Andric hasSideEffects = true; 3601*0fca6ea1SDimitry Andric } 3602*0fca6ea1SDimitry Andric } 3603*0fca6ea1SDimitry Andric return; 3604*0fca6ea1SDimitry Andric } 3605*0fca6ea1SDimitry Andric 3606*0fca6ea1SDimitry Andric // Analyze children. 3607*0fca6ea1SDimitry Andric for (unsigned i = 0, e = N.getNumChildren(); i != e; ++i) 3608*0fca6ea1SDimitry Andric AnalyzeNode(N.getChild(i)); 3609*0fca6ea1SDimitry Andric 3610*0fca6ea1SDimitry Andric // Notice properties of the node. 3611*0fca6ea1SDimitry Andric if (N.NodeHasProperty(SDNPMayStore, CDP)) 3612*0fca6ea1SDimitry Andric mayStore = true; 3613*0fca6ea1SDimitry Andric if (N.NodeHasProperty(SDNPMayLoad, CDP)) 3614*0fca6ea1SDimitry Andric mayLoad = true; 3615*0fca6ea1SDimitry Andric if (N.NodeHasProperty(SDNPSideEffect, CDP)) 3616*0fca6ea1SDimitry Andric hasSideEffects = true; 3617*0fca6ea1SDimitry Andric if (N.NodeHasProperty(SDNPVariadic, CDP)) 3618*0fca6ea1SDimitry Andric isVariadic = true; 3619*0fca6ea1SDimitry Andric if (N.NodeHasProperty(SDNPHasChain, CDP)) 3620*0fca6ea1SDimitry Andric hasChain = true; 3621*0fca6ea1SDimitry Andric 3622*0fca6ea1SDimitry Andric if (const CodeGenIntrinsic *IntInfo = N.getIntrinsicInfo(CDP)) { 3623*0fca6ea1SDimitry Andric ModRefInfo MR = IntInfo->ME.getModRef(); 3624*0fca6ea1SDimitry Andric // If this is an intrinsic, analyze it. 3625*0fca6ea1SDimitry Andric if (isRefSet(MR)) 3626*0fca6ea1SDimitry Andric mayLoad = true; // These may load memory. 3627*0fca6ea1SDimitry Andric 3628*0fca6ea1SDimitry Andric if (isModSet(MR)) 3629*0fca6ea1SDimitry Andric mayStore = true; // Intrinsics that can write to memory are 'mayStore'. 3630*0fca6ea1SDimitry Andric 3631*0fca6ea1SDimitry Andric // Consider intrinsics that don't specify any restrictions on memory 3632*0fca6ea1SDimitry Andric // effects as having a side-effect. 3633*0fca6ea1SDimitry Andric if (IntInfo->ME == MemoryEffects::unknown() || IntInfo->hasSideEffects) 3634*0fca6ea1SDimitry Andric hasSideEffects = true; 3635*0fca6ea1SDimitry Andric } 3636*0fca6ea1SDimitry Andric } 3637*0fca6ea1SDimitry Andric }; 3638*0fca6ea1SDimitry Andric 3639*0fca6ea1SDimitry Andric static bool InferFromPattern(CodeGenInstruction &InstInfo, 3640*0fca6ea1SDimitry Andric const InstAnalyzer &PatInfo, Record *PatDef) { 3641*0fca6ea1SDimitry Andric bool Error = false; 3642*0fca6ea1SDimitry Andric 3643*0fca6ea1SDimitry Andric // Remember where InstInfo got its flags. 3644*0fca6ea1SDimitry Andric if (InstInfo.hasUndefFlags()) 3645*0fca6ea1SDimitry Andric InstInfo.InferredFrom = PatDef; 3646*0fca6ea1SDimitry Andric 3647*0fca6ea1SDimitry Andric // Check explicitly set flags for consistency. 3648*0fca6ea1SDimitry Andric if (InstInfo.hasSideEffects != PatInfo.hasSideEffects && 3649*0fca6ea1SDimitry Andric !InstInfo.hasSideEffects_Unset) { 3650*0fca6ea1SDimitry Andric // Allow explicitly setting hasSideEffects = 1 on instructions, even when 3651*0fca6ea1SDimitry Andric // the pattern has no side effects. That could be useful for div/rem 3652*0fca6ea1SDimitry Andric // instructions that may trap. 3653*0fca6ea1SDimitry Andric if (!InstInfo.hasSideEffects) { 3654*0fca6ea1SDimitry Andric Error = true; 3655*0fca6ea1SDimitry Andric PrintError(PatDef->getLoc(), "Pattern doesn't match hasSideEffects = " + 3656*0fca6ea1SDimitry Andric Twine(InstInfo.hasSideEffects)); 3657*0fca6ea1SDimitry Andric } 3658*0fca6ea1SDimitry Andric } 3659*0fca6ea1SDimitry Andric 3660*0fca6ea1SDimitry Andric if (InstInfo.mayStore != PatInfo.mayStore && !InstInfo.mayStore_Unset) { 3661*0fca6ea1SDimitry Andric Error = true; 3662*0fca6ea1SDimitry Andric PrintError(PatDef->getLoc(), 3663*0fca6ea1SDimitry Andric "Pattern doesn't match mayStore = " + Twine(InstInfo.mayStore)); 3664*0fca6ea1SDimitry Andric } 3665*0fca6ea1SDimitry Andric 3666*0fca6ea1SDimitry Andric if (InstInfo.mayLoad != PatInfo.mayLoad && !InstInfo.mayLoad_Unset) { 3667*0fca6ea1SDimitry Andric // Allow explicitly setting mayLoad = 1, even when the pattern has no loads. 3668*0fca6ea1SDimitry Andric // Some targets translate immediates to loads. 3669*0fca6ea1SDimitry Andric if (!InstInfo.mayLoad) { 3670*0fca6ea1SDimitry Andric Error = true; 3671*0fca6ea1SDimitry Andric PrintError(PatDef->getLoc(), 3672*0fca6ea1SDimitry Andric "Pattern doesn't match mayLoad = " + Twine(InstInfo.mayLoad)); 3673*0fca6ea1SDimitry Andric } 3674*0fca6ea1SDimitry Andric } 3675*0fca6ea1SDimitry Andric 3676*0fca6ea1SDimitry Andric // Transfer inferred flags. 3677*0fca6ea1SDimitry Andric InstInfo.hasSideEffects |= PatInfo.hasSideEffects; 3678*0fca6ea1SDimitry Andric InstInfo.mayStore |= PatInfo.mayStore; 3679*0fca6ea1SDimitry Andric InstInfo.mayLoad |= PatInfo.mayLoad; 3680*0fca6ea1SDimitry Andric 3681*0fca6ea1SDimitry Andric // These flags are silently added without any verification. 3682*0fca6ea1SDimitry Andric // FIXME: To match historical behavior of TableGen, for now add those flags 3683*0fca6ea1SDimitry Andric // only when we're inferring from the primary instruction pattern. 3684*0fca6ea1SDimitry Andric if (PatDef->isSubClassOf("Instruction")) { 3685*0fca6ea1SDimitry Andric InstInfo.isBitcast |= PatInfo.isBitcast; 3686*0fca6ea1SDimitry Andric InstInfo.hasChain |= PatInfo.hasChain; 3687*0fca6ea1SDimitry Andric InstInfo.hasChain_Inferred = true; 3688*0fca6ea1SDimitry Andric } 3689*0fca6ea1SDimitry Andric 3690*0fca6ea1SDimitry Andric // Don't infer isVariadic. This flag means something different on SDNodes and 3691*0fca6ea1SDimitry Andric // instructions. For example, a CALL SDNode is variadic because it has the 3692*0fca6ea1SDimitry Andric // call arguments as operands, but a CALL instruction is not variadic - it 3693*0fca6ea1SDimitry Andric // has argument registers as implicit, not explicit uses. 3694*0fca6ea1SDimitry Andric 3695*0fca6ea1SDimitry Andric return Error; 3696*0fca6ea1SDimitry Andric } 3697*0fca6ea1SDimitry Andric 3698*0fca6ea1SDimitry Andric /// hasNullFragReference - Return true if the DAG has any reference to the 3699*0fca6ea1SDimitry Andric /// null_frag operator. 3700*0fca6ea1SDimitry Andric static bool hasNullFragReference(DagInit *DI) { 3701*0fca6ea1SDimitry Andric DefInit *OpDef = dyn_cast<DefInit>(DI->getOperator()); 3702*0fca6ea1SDimitry Andric if (!OpDef) 3703*0fca6ea1SDimitry Andric return false; 3704*0fca6ea1SDimitry Andric Record *Operator = OpDef->getDef(); 3705*0fca6ea1SDimitry Andric 3706*0fca6ea1SDimitry Andric // If this is the null fragment, return true. 3707*0fca6ea1SDimitry Andric if (Operator->getName() == "null_frag") 3708*0fca6ea1SDimitry Andric return true; 3709*0fca6ea1SDimitry Andric // If any of the arguments reference the null fragment, return true. 3710*0fca6ea1SDimitry Andric for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) { 3711*0fca6ea1SDimitry Andric if (auto Arg = dyn_cast<DefInit>(DI->getArg(i))) 3712*0fca6ea1SDimitry Andric if (Arg->getDef()->getName() == "null_frag") 3713*0fca6ea1SDimitry Andric return true; 3714*0fca6ea1SDimitry Andric DagInit *Arg = dyn_cast<DagInit>(DI->getArg(i)); 3715*0fca6ea1SDimitry Andric if (Arg && hasNullFragReference(Arg)) 3716*0fca6ea1SDimitry Andric return true; 3717*0fca6ea1SDimitry Andric } 3718*0fca6ea1SDimitry Andric 3719*0fca6ea1SDimitry Andric return false; 3720*0fca6ea1SDimitry Andric } 3721*0fca6ea1SDimitry Andric 3722*0fca6ea1SDimitry Andric /// hasNullFragReference - Return true if any DAG in the list references 3723*0fca6ea1SDimitry Andric /// the null_frag operator. 3724*0fca6ea1SDimitry Andric static bool hasNullFragReference(ListInit *LI) { 3725*0fca6ea1SDimitry Andric for (Init *I : LI->getValues()) { 3726*0fca6ea1SDimitry Andric DagInit *DI = dyn_cast<DagInit>(I); 3727*0fca6ea1SDimitry Andric assert(DI && "non-dag in an instruction Pattern list?!"); 3728*0fca6ea1SDimitry Andric if (hasNullFragReference(DI)) 3729*0fca6ea1SDimitry Andric return true; 3730*0fca6ea1SDimitry Andric } 3731*0fca6ea1SDimitry Andric return false; 3732*0fca6ea1SDimitry Andric } 3733*0fca6ea1SDimitry Andric 3734*0fca6ea1SDimitry Andric /// Get all the instructions in a tree. 3735*0fca6ea1SDimitry Andric static void getInstructionsInTree(TreePatternNode &Tree, 3736*0fca6ea1SDimitry Andric SmallVectorImpl<Record *> &Instrs) { 3737*0fca6ea1SDimitry Andric if (Tree.isLeaf()) 3738*0fca6ea1SDimitry Andric return; 3739*0fca6ea1SDimitry Andric if (Tree.getOperator()->isSubClassOf("Instruction")) 3740*0fca6ea1SDimitry Andric Instrs.push_back(Tree.getOperator()); 3741*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Tree.getNumChildren(); i != e; ++i) 3742*0fca6ea1SDimitry Andric getInstructionsInTree(Tree.getChild(i), Instrs); 3743*0fca6ea1SDimitry Andric } 3744*0fca6ea1SDimitry Andric 3745*0fca6ea1SDimitry Andric /// Check the class of a pattern leaf node against the instruction operand it 3746*0fca6ea1SDimitry Andric /// represents. 3747*0fca6ea1SDimitry Andric static bool checkOperandClass(CGIOperandList::OperandInfo &OI, Record *Leaf) { 3748*0fca6ea1SDimitry Andric if (OI.Rec == Leaf) 3749*0fca6ea1SDimitry Andric return true; 3750*0fca6ea1SDimitry Andric 3751*0fca6ea1SDimitry Andric // Allow direct value types to be used in instruction set patterns. 3752*0fca6ea1SDimitry Andric // The type will be checked later. 3753*0fca6ea1SDimitry Andric if (Leaf->isSubClassOf("ValueType")) 3754*0fca6ea1SDimitry Andric return true; 3755*0fca6ea1SDimitry Andric 3756*0fca6ea1SDimitry Andric // Patterns can also be ComplexPattern instances. 3757*0fca6ea1SDimitry Andric if (Leaf->isSubClassOf("ComplexPattern")) 3758*0fca6ea1SDimitry Andric return true; 3759*0fca6ea1SDimitry Andric 3760*0fca6ea1SDimitry Andric return false; 3761*0fca6ea1SDimitry Andric } 3762*0fca6ea1SDimitry Andric 3763*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::parseInstructionPattern(CodeGenInstruction &CGI, 3764*0fca6ea1SDimitry Andric ListInit *Pat, 3765*0fca6ea1SDimitry Andric DAGInstMap &DAGInsts) { 3766*0fca6ea1SDimitry Andric 3767*0fca6ea1SDimitry Andric assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!"); 3768*0fca6ea1SDimitry Andric 3769*0fca6ea1SDimitry Andric // Parse the instruction. 3770*0fca6ea1SDimitry Andric TreePattern I(CGI.TheDef, Pat, true, *this); 3771*0fca6ea1SDimitry Andric 3772*0fca6ea1SDimitry Andric // InstInputs - Keep track of all of the inputs of the instruction, along 3773*0fca6ea1SDimitry Andric // with the record they are declared as. 3774*0fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> InstInputs; 3775*0fca6ea1SDimitry Andric 3776*0fca6ea1SDimitry Andric // InstResults - Keep track of all the virtual registers that are 'set' 3777*0fca6ea1SDimitry Andric // in the instruction, including what reg class they are. 3778*0fca6ea1SDimitry Andric MapVector<std::string, TreePatternNodePtr, std::map<std::string, unsigned>> 3779*0fca6ea1SDimitry Andric InstResults; 3780*0fca6ea1SDimitry Andric 3781*0fca6ea1SDimitry Andric std::vector<Record *> InstImpResults; 3782*0fca6ea1SDimitry Andric 3783*0fca6ea1SDimitry Andric // Verify that the top-level forms in the instruction are of void type, and 3784*0fca6ea1SDimitry Andric // fill in the InstResults map. 3785*0fca6ea1SDimitry Andric SmallString<32> TypesString; 3786*0fca6ea1SDimitry Andric for (unsigned j = 0, e = I.getNumTrees(); j != e; ++j) { 3787*0fca6ea1SDimitry Andric TypesString.clear(); 3788*0fca6ea1SDimitry Andric TreePatternNodePtr Pat = I.getTree(j); 3789*0fca6ea1SDimitry Andric if (Pat->getNumTypes() != 0) { 3790*0fca6ea1SDimitry Andric raw_svector_ostream OS(TypesString); 3791*0fca6ea1SDimitry Andric ListSeparator LS; 3792*0fca6ea1SDimitry Andric for (unsigned k = 0, ke = Pat->getNumTypes(); k != ke; ++k) { 3793*0fca6ea1SDimitry Andric OS << LS; 3794*0fca6ea1SDimitry Andric Pat->getExtType(k).writeToStream(OS); 3795*0fca6ea1SDimitry Andric } 3796*0fca6ea1SDimitry Andric I.error("Top-level forms in instruction pattern should have" 3797*0fca6ea1SDimitry Andric " void types, has types " + 3798*0fca6ea1SDimitry Andric OS.str()); 3799*0fca6ea1SDimitry Andric } 3800*0fca6ea1SDimitry Andric 3801*0fca6ea1SDimitry Andric // Find inputs and outputs, and verify the structure of the uses/defs. 3802*0fca6ea1SDimitry Andric FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, 3803*0fca6ea1SDimitry Andric InstImpResults); 3804*0fca6ea1SDimitry Andric } 3805*0fca6ea1SDimitry Andric 3806*0fca6ea1SDimitry Andric // Now that we have inputs and outputs of the pattern, inspect the operands 3807*0fca6ea1SDimitry Andric // list for the instruction. This determines the order that operands are 3808*0fca6ea1SDimitry Andric // added to the machine instruction the node corresponds to. 3809*0fca6ea1SDimitry Andric unsigned NumResults = InstResults.size(); 3810*0fca6ea1SDimitry Andric 3811*0fca6ea1SDimitry Andric // Parse the operands list from the (ops) list, validating it. 3812*0fca6ea1SDimitry Andric assert(I.getArgList().empty() && "Args list should still be empty here!"); 3813*0fca6ea1SDimitry Andric 3814*0fca6ea1SDimitry Andric // Check that all of the results occur first in the list. 3815*0fca6ea1SDimitry Andric std::vector<Record *> Results; 3816*0fca6ea1SDimitry Andric std::vector<unsigned> ResultIndices; 3817*0fca6ea1SDimitry Andric SmallVector<TreePatternNodePtr, 2> ResNodes; 3818*0fca6ea1SDimitry Andric for (unsigned i = 0; i != NumResults; ++i) { 3819*0fca6ea1SDimitry Andric if (i == CGI.Operands.size()) { 3820*0fca6ea1SDimitry Andric const std::string &OpName = 3821*0fca6ea1SDimitry Andric llvm::find_if( 3822*0fca6ea1SDimitry Andric InstResults, 3823*0fca6ea1SDimitry Andric [](const std::pair<std::string, TreePatternNodePtr> &P) { 3824*0fca6ea1SDimitry Andric return P.second; 3825*0fca6ea1SDimitry Andric }) 3826*0fca6ea1SDimitry Andric ->first; 3827*0fca6ea1SDimitry Andric 3828*0fca6ea1SDimitry Andric I.error("'" + OpName + "' set but does not appear in operand list!"); 3829*0fca6ea1SDimitry Andric } 3830*0fca6ea1SDimitry Andric 3831*0fca6ea1SDimitry Andric const std::string &OpName = CGI.Operands[i].Name; 3832*0fca6ea1SDimitry Andric 3833*0fca6ea1SDimitry Andric // Check that it exists in InstResults. 3834*0fca6ea1SDimitry Andric auto InstResultIter = InstResults.find(OpName); 3835*0fca6ea1SDimitry Andric if (InstResultIter == InstResults.end() || !InstResultIter->second) 3836*0fca6ea1SDimitry Andric I.error("Operand $" + OpName + " does not exist in operand list!"); 3837*0fca6ea1SDimitry Andric 3838*0fca6ea1SDimitry Andric TreePatternNodePtr RNode = InstResultIter->second; 3839*0fca6ea1SDimitry Andric Record *R = cast<DefInit>(RNode->getLeafValue())->getDef(); 3840*0fca6ea1SDimitry Andric ResNodes.push_back(std::move(RNode)); 3841*0fca6ea1SDimitry Andric if (!R) 3842*0fca6ea1SDimitry Andric I.error("Operand $" + OpName + 3843*0fca6ea1SDimitry Andric " should be a set destination: all " 3844*0fca6ea1SDimitry Andric "outputs must occur before inputs in operand list!"); 3845*0fca6ea1SDimitry Andric 3846*0fca6ea1SDimitry Andric if (!checkOperandClass(CGI.Operands[i], R)) 3847*0fca6ea1SDimitry Andric I.error("Operand $" + OpName + " class mismatch!"); 3848*0fca6ea1SDimitry Andric 3849*0fca6ea1SDimitry Andric // Remember the return type. 3850*0fca6ea1SDimitry Andric Results.push_back(CGI.Operands[i].Rec); 3851*0fca6ea1SDimitry Andric 3852*0fca6ea1SDimitry Andric // Remember the result index. 3853*0fca6ea1SDimitry Andric ResultIndices.push_back(std::distance(InstResults.begin(), InstResultIter)); 3854*0fca6ea1SDimitry Andric 3855*0fca6ea1SDimitry Andric // Okay, this one checks out. 3856*0fca6ea1SDimitry Andric InstResultIter->second = nullptr; 3857*0fca6ea1SDimitry Andric } 3858*0fca6ea1SDimitry Andric 3859*0fca6ea1SDimitry Andric // Loop over the inputs next. 3860*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> ResultNodeOperands; 3861*0fca6ea1SDimitry Andric std::vector<Record *> Operands; 3862*0fca6ea1SDimitry Andric for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { 3863*0fca6ea1SDimitry Andric CGIOperandList::OperandInfo &Op = CGI.Operands[i]; 3864*0fca6ea1SDimitry Andric const std::string &OpName = Op.Name; 3865*0fca6ea1SDimitry Andric if (OpName.empty()) { 3866*0fca6ea1SDimitry Andric I.error("Operand #" + Twine(i) + " in operands list has no name!"); 3867*0fca6ea1SDimitry Andric continue; 3868*0fca6ea1SDimitry Andric } 3869*0fca6ea1SDimitry Andric 3870*0fca6ea1SDimitry Andric if (!InstInputs.count(OpName)) { 3871*0fca6ea1SDimitry Andric // If this is an operand with a DefaultOps set filled in, we can ignore 3872*0fca6ea1SDimitry Andric // this. When we codegen it, we will do so as always executed. 3873*0fca6ea1SDimitry Andric if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) { 3874*0fca6ea1SDimitry Andric // Does it have a non-empty DefaultOps field? If so, ignore this 3875*0fca6ea1SDimitry Andric // operand. 3876*0fca6ea1SDimitry Andric if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) 3877*0fca6ea1SDimitry Andric continue; 3878*0fca6ea1SDimitry Andric } 3879*0fca6ea1SDimitry Andric I.error("Operand $" + OpName + 3880*0fca6ea1SDimitry Andric " does not appear in the instruction pattern"); 3881*0fca6ea1SDimitry Andric continue; 3882*0fca6ea1SDimitry Andric } 3883*0fca6ea1SDimitry Andric TreePatternNodePtr InVal = InstInputs[OpName]; 3884*0fca6ea1SDimitry Andric InstInputs.erase(OpName); // It occurred, remove from map. 3885*0fca6ea1SDimitry Andric 3886*0fca6ea1SDimitry Andric if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) { 3887*0fca6ea1SDimitry Andric Record *InRec = cast<DefInit>(InVal->getLeafValue())->getDef(); 3888*0fca6ea1SDimitry Andric if (!checkOperandClass(Op, InRec)) { 3889*0fca6ea1SDimitry Andric I.error("Operand $" + OpName + 3890*0fca6ea1SDimitry Andric "'s register class disagrees" 3891*0fca6ea1SDimitry Andric " between the operand and pattern"); 3892*0fca6ea1SDimitry Andric continue; 3893*0fca6ea1SDimitry Andric } 3894*0fca6ea1SDimitry Andric } 3895*0fca6ea1SDimitry Andric Operands.push_back(Op.Rec); 3896*0fca6ea1SDimitry Andric 3897*0fca6ea1SDimitry Andric // Construct the result for the dest-pattern operand list. 3898*0fca6ea1SDimitry Andric TreePatternNodePtr OpNode = InVal->clone(); 3899*0fca6ea1SDimitry Andric 3900*0fca6ea1SDimitry Andric // No predicate is useful on the result. 3901*0fca6ea1SDimitry Andric OpNode->clearPredicateCalls(); 3902*0fca6ea1SDimitry Andric 3903*0fca6ea1SDimitry Andric // Promote the xform function to be an explicit node if set. 3904*0fca6ea1SDimitry Andric if (Record *Xform = OpNode->getTransformFn()) { 3905*0fca6ea1SDimitry Andric OpNode->setTransformFn(nullptr); 3906*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> Children; 3907*0fca6ea1SDimitry Andric Children.push_back(OpNode); 3908*0fca6ea1SDimitry Andric OpNode = makeIntrusiveRefCnt<TreePatternNode>(Xform, std::move(Children), 3909*0fca6ea1SDimitry Andric OpNode->getNumTypes()); 3910*0fca6ea1SDimitry Andric } 3911*0fca6ea1SDimitry Andric 3912*0fca6ea1SDimitry Andric ResultNodeOperands.push_back(std::move(OpNode)); 3913*0fca6ea1SDimitry Andric } 3914*0fca6ea1SDimitry Andric 3915*0fca6ea1SDimitry Andric if (!InstInputs.empty()) 3916*0fca6ea1SDimitry Andric I.error("Input operand $" + InstInputs.begin()->first + 3917*0fca6ea1SDimitry Andric " occurs in pattern but not in operands list!"); 3918*0fca6ea1SDimitry Andric 3919*0fca6ea1SDimitry Andric TreePatternNodePtr ResultPattern = makeIntrusiveRefCnt<TreePatternNode>( 3920*0fca6ea1SDimitry Andric I.getRecord(), std::move(ResultNodeOperands), 3921*0fca6ea1SDimitry Andric GetNumNodeResults(I.getRecord(), *this)); 3922*0fca6ea1SDimitry Andric // Copy fully inferred output node types to instruction result pattern. 3923*0fca6ea1SDimitry Andric for (unsigned i = 0; i != NumResults; ++i) { 3924*0fca6ea1SDimitry Andric assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled"); 3925*0fca6ea1SDimitry Andric ResultPattern->setType(i, ResNodes[i]->getExtType(0)); 3926*0fca6ea1SDimitry Andric ResultPattern->setResultIndex(i, ResultIndices[i]); 3927*0fca6ea1SDimitry Andric } 3928*0fca6ea1SDimitry Andric 3929*0fca6ea1SDimitry Andric // FIXME: Assume only the first tree is the pattern. The others are clobber 3930*0fca6ea1SDimitry Andric // nodes. 3931*0fca6ea1SDimitry Andric TreePatternNodePtr Pattern = I.getTree(0); 3932*0fca6ea1SDimitry Andric TreePatternNodePtr SrcPattern; 3933*0fca6ea1SDimitry Andric if (Pattern->getOperator()->getName() == "set") { 3934*0fca6ea1SDimitry Andric SrcPattern = Pattern->getChild(Pattern->getNumChildren() - 1).clone(); 3935*0fca6ea1SDimitry Andric } else { 3936*0fca6ea1SDimitry Andric // Not a set (store or something?) 3937*0fca6ea1SDimitry Andric SrcPattern = Pattern; 3938*0fca6ea1SDimitry Andric } 3939*0fca6ea1SDimitry Andric 3940*0fca6ea1SDimitry Andric // Create and insert the instruction. 3941*0fca6ea1SDimitry Andric // FIXME: InstImpResults should not be part of DAGInstruction. 3942*0fca6ea1SDimitry Andric Record *R = I.getRecord(); 3943*0fca6ea1SDimitry Andric DAGInsts.try_emplace(R, std::move(Results), std::move(Operands), 3944*0fca6ea1SDimitry Andric std::move(InstImpResults), SrcPattern, ResultPattern); 3945*0fca6ea1SDimitry Andric 3946*0fca6ea1SDimitry Andric LLVM_DEBUG(I.dump()); 3947*0fca6ea1SDimitry Andric } 3948*0fca6ea1SDimitry Andric 3949*0fca6ea1SDimitry Andric /// ParseInstructions - Parse all of the instructions, inlining and resolving 3950*0fca6ea1SDimitry Andric /// any fragments involved. This populates the Instructions list with fully 3951*0fca6ea1SDimitry Andric /// resolved instructions. 3952*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseInstructions() { 3953*0fca6ea1SDimitry Andric std::vector<Record *> Instrs = 3954*0fca6ea1SDimitry Andric Records.getAllDerivedDefinitions("Instruction"); 3955*0fca6ea1SDimitry Andric 3956*0fca6ea1SDimitry Andric for (Record *Instr : Instrs) { 3957*0fca6ea1SDimitry Andric ListInit *LI = nullptr; 3958*0fca6ea1SDimitry Andric 3959*0fca6ea1SDimitry Andric if (isa<ListInit>(Instr->getValueInit("Pattern"))) 3960*0fca6ea1SDimitry Andric LI = Instr->getValueAsListInit("Pattern"); 3961*0fca6ea1SDimitry Andric 3962*0fca6ea1SDimitry Andric // If there is no pattern, only collect minimal information about the 3963*0fca6ea1SDimitry Andric // instruction for its operand list. We have to assume that there is one 3964*0fca6ea1SDimitry Andric // result, as we have no detailed info. A pattern which references the 3965*0fca6ea1SDimitry Andric // null_frag operator is as-if no pattern were specified. Normally this 3966*0fca6ea1SDimitry Andric // is from a multiclass expansion w/ a SDPatternOperator passed in as 3967*0fca6ea1SDimitry Andric // null_frag. 3968*0fca6ea1SDimitry Andric if (!LI || LI->empty() || hasNullFragReference(LI)) { 3969*0fca6ea1SDimitry Andric std::vector<Record *> Results; 3970*0fca6ea1SDimitry Andric std::vector<Record *> Operands; 3971*0fca6ea1SDimitry Andric 3972*0fca6ea1SDimitry Andric CodeGenInstruction &InstInfo = Target.getInstruction(Instr); 3973*0fca6ea1SDimitry Andric 3974*0fca6ea1SDimitry Andric if (InstInfo.Operands.size() != 0) { 3975*0fca6ea1SDimitry Andric for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j) 3976*0fca6ea1SDimitry Andric Results.push_back(InstInfo.Operands[j].Rec); 3977*0fca6ea1SDimitry Andric 3978*0fca6ea1SDimitry Andric // The rest are inputs. 3979*0fca6ea1SDimitry Andric for (unsigned j = InstInfo.Operands.NumDefs, 3980*0fca6ea1SDimitry Andric e = InstInfo.Operands.size(); 3981*0fca6ea1SDimitry Andric j < e; ++j) 3982*0fca6ea1SDimitry Andric Operands.push_back(InstInfo.Operands[j].Rec); 3983*0fca6ea1SDimitry Andric } 3984*0fca6ea1SDimitry Andric 3985*0fca6ea1SDimitry Andric // Create and insert the instruction. 3986*0fca6ea1SDimitry Andric Instructions.try_emplace(Instr, std::move(Results), std::move(Operands), 3987*0fca6ea1SDimitry Andric std::vector<Record *>()); 3988*0fca6ea1SDimitry Andric continue; // no pattern. 3989*0fca6ea1SDimitry Andric } 3990*0fca6ea1SDimitry Andric 3991*0fca6ea1SDimitry Andric CodeGenInstruction &CGI = Target.getInstruction(Instr); 3992*0fca6ea1SDimitry Andric parseInstructionPattern(CGI, LI, Instructions); 3993*0fca6ea1SDimitry Andric } 3994*0fca6ea1SDimitry Andric 3995*0fca6ea1SDimitry Andric // If we can, convert the instructions to be patterns that are matched! 3996*0fca6ea1SDimitry Andric for (auto &Entry : Instructions) { 3997*0fca6ea1SDimitry Andric Record *Instr = Entry.first; 3998*0fca6ea1SDimitry Andric DAGInstruction &TheInst = Entry.second; 3999*0fca6ea1SDimitry Andric TreePatternNodePtr SrcPattern = TheInst.getSrcPattern(); 4000*0fca6ea1SDimitry Andric TreePatternNodePtr ResultPattern = TheInst.getResultPattern(); 4001*0fca6ea1SDimitry Andric 4002*0fca6ea1SDimitry Andric if (SrcPattern && ResultPattern) { 4003*0fca6ea1SDimitry Andric TreePattern Pattern(Instr, SrcPattern, true, *this); 4004*0fca6ea1SDimitry Andric TreePattern Result(Instr, ResultPattern, false, *this); 4005*0fca6ea1SDimitry Andric ParseOnePattern(Instr, Pattern, Result, TheInst.getImpResults()); 4006*0fca6ea1SDimitry Andric } 4007*0fca6ea1SDimitry Andric } 4008*0fca6ea1SDimitry Andric } 4009*0fca6ea1SDimitry Andric 4010*0fca6ea1SDimitry Andric typedef std::pair<TreePatternNode *, unsigned> NameRecord; 4011*0fca6ea1SDimitry Andric 4012*0fca6ea1SDimitry Andric static void FindNames(TreePatternNode &P, 4013*0fca6ea1SDimitry Andric std::map<std::string, NameRecord> &Names, 4014*0fca6ea1SDimitry Andric TreePattern *PatternTop) { 4015*0fca6ea1SDimitry Andric if (!P.getName().empty()) { 4016*0fca6ea1SDimitry Andric NameRecord &Rec = Names[P.getName()]; 4017*0fca6ea1SDimitry Andric // If this is the first instance of the name, remember the node. 4018*0fca6ea1SDimitry Andric if (Rec.second++ == 0) 4019*0fca6ea1SDimitry Andric Rec.first = &P; 4020*0fca6ea1SDimitry Andric else if (Rec.first->getExtTypes() != P.getExtTypes()) 4021*0fca6ea1SDimitry Andric PatternTop->error("repetition of value: $" + P.getName() + 4022*0fca6ea1SDimitry Andric " where different uses have different types!"); 4023*0fca6ea1SDimitry Andric } 4024*0fca6ea1SDimitry Andric 4025*0fca6ea1SDimitry Andric if (!P.isLeaf()) { 4026*0fca6ea1SDimitry Andric for (unsigned i = 0, e = P.getNumChildren(); i != e; ++i) 4027*0fca6ea1SDimitry Andric FindNames(P.getChild(i), Names, PatternTop); 4028*0fca6ea1SDimitry Andric } 4029*0fca6ea1SDimitry Andric } 4030*0fca6ea1SDimitry Andric 4031*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, 4032*0fca6ea1SDimitry Andric PatternToMatch &&PTM) { 4033*0fca6ea1SDimitry Andric // Do some sanity checking on the pattern we're about to match. 4034*0fca6ea1SDimitry Andric std::string Reason; 4035*0fca6ea1SDimitry Andric if (!PTM.getSrcPattern().canPatternMatch(Reason, *this)) { 4036*0fca6ea1SDimitry Andric PrintWarning(Pattern->getRecord()->getLoc(), 4037*0fca6ea1SDimitry Andric Twine("Pattern can never match: ") + Reason); 4038*0fca6ea1SDimitry Andric return; 4039*0fca6ea1SDimitry Andric } 4040*0fca6ea1SDimitry Andric 4041*0fca6ea1SDimitry Andric // If the source pattern's root is a complex pattern, that complex pattern 4042*0fca6ea1SDimitry Andric // must specify the nodes it can potentially match. 4043*0fca6ea1SDimitry Andric if (const ComplexPattern *CP = 4044*0fca6ea1SDimitry Andric PTM.getSrcPattern().getComplexPatternInfo(*this)) 4045*0fca6ea1SDimitry Andric if (CP->getRootNodes().empty()) 4046*0fca6ea1SDimitry Andric Pattern->error("ComplexPattern at root must specify list of opcodes it" 4047*0fca6ea1SDimitry Andric " could match"); 4048*0fca6ea1SDimitry Andric 4049*0fca6ea1SDimitry Andric // Find all of the named values in the input and output, ensure they have the 4050*0fca6ea1SDimitry Andric // same type. 4051*0fca6ea1SDimitry Andric std::map<std::string, NameRecord> SrcNames, DstNames; 4052*0fca6ea1SDimitry Andric FindNames(PTM.getSrcPattern(), SrcNames, Pattern); 4053*0fca6ea1SDimitry Andric FindNames(PTM.getDstPattern(), DstNames, Pattern); 4054*0fca6ea1SDimitry Andric 4055*0fca6ea1SDimitry Andric // Scan all of the named values in the destination pattern, rejecting them if 4056*0fca6ea1SDimitry Andric // they don't exist in the input pattern. 4057*0fca6ea1SDimitry Andric for (const auto &Entry : DstNames) { 4058*0fca6ea1SDimitry Andric if (SrcNames[Entry.first].first == nullptr) 4059*0fca6ea1SDimitry Andric Pattern->error("Pattern has input without matching name in output: $" + 4060*0fca6ea1SDimitry Andric Entry.first); 4061*0fca6ea1SDimitry Andric } 4062*0fca6ea1SDimitry Andric 4063*0fca6ea1SDimitry Andric // Scan all of the named values in the source pattern, rejecting them if the 4064*0fca6ea1SDimitry Andric // name isn't used in the dest, and isn't used to tie two values together. 4065*0fca6ea1SDimitry Andric for (const auto &Entry : SrcNames) 4066*0fca6ea1SDimitry Andric if (DstNames[Entry.first].first == nullptr && 4067*0fca6ea1SDimitry Andric SrcNames[Entry.first].second == 1) 4068*0fca6ea1SDimitry Andric Pattern->error("Pattern has dead named input: $" + Entry.first); 4069*0fca6ea1SDimitry Andric 4070*0fca6ea1SDimitry Andric PatternsToMatch.push_back(std::move(PTM)); 4071*0fca6ea1SDimitry Andric } 4072*0fca6ea1SDimitry Andric 4073*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::InferInstructionFlags() { 4074*0fca6ea1SDimitry Andric ArrayRef<const CodeGenInstruction *> Instructions = 4075*0fca6ea1SDimitry Andric Target.getInstructionsByEnumValue(); 4076*0fca6ea1SDimitry Andric 4077*0fca6ea1SDimitry Andric unsigned Errors = 0; 4078*0fca6ea1SDimitry Andric 4079*0fca6ea1SDimitry Andric // Try to infer flags from all patterns in PatternToMatch. These include 4080*0fca6ea1SDimitry Andric // both the primary instruction patterns (which always come first) and 4081*0fca6ea1SDimitry Andric // patterns defined outside the instruction. 4082*0fca6ea1SDimitry Andric for (const PatternToMatch &PTM : ptms()) { 4083*0fca6ea1SDimitry Andric // We can only infer from single-instruction patterns, otherwise we won't 4084*0fca6ea1SDimitry Andric // know which instruction should get the flags. 4085*0fca6ea1SDimitry Andric SmallVector<Record *, 8> PatInstrs; 4086*0fca6ea1SDimitry Andric getInstructionsInTree(PTM.getDstPattern(), PatInstrs); 4087*0fca6ea1SDimitry Andric if (PatInstrs.size() != 1) 4088*0fca6ea1SDimitry Andric continue; 4089*0fca6ea1SDimitry Andric 4090*0fca6ea1SDimitry Andric // Get the single instruction. 4091*0fca6ea1SDimitry Andric CodeGenInstruction &InstInfo = Target.getInstruction(PatInstrs.front()); 4092*0fca6ea1SDimitry Andric 4093*0fca6ea1SDimitry Andric // Only infer properties from the first pattern. We'll verify the others. 4094*0fca6ea1SDimitry Andric if (InstInfo.InferredFrom) 4095*0fca6ea1SDimitry Andric continue; 4096*0fca6ea1SDimitry Andric 4097*0fca6ea1SDimitry Andric InstAnalyzer PatInfo(*this); 4098*0fca6ea1SDimitry Andric PatInfo.Analyze(PTM); 4099*0fca6ea1SDimitry Andric Errors += InferFromPattern(InstInfo, PatInfo, PTM.getSrcRecord()); 4100*0fca6ea1SDimitry Andric } 4101*0fca6ea1SDimitry Andric 4102*0fca6ea1SDimitry Andric if (Errors) 4103*0fca6ea1SDimitry Andric PrintFatalError("pattern conflicts"); 4104*0fca6ea1SDimitry Andric 4105*0fca6ea1SDimitry Andric // If requested by the target, guess any undefined properties. 4106*0fca6ea1SDimitry Andric if (Target.guessInstructionProperties()) { 4107*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { 4108*0fca6ea1SDimitry Andric CodeGenInstruction *InstInfo = 4109*0fca6ea1SDimitry Andric const_cast<CodeGenInstruction *>(Instructions[i]); 4110*0fca6ea1SDimitry Andric if (InstInfo->InferredFrom) 4111*0fca6ea1SDimitry Andric continue; 4112*0fca6ea1SDimitry Andric // The mayLoad and mayStore flags default to false. 4113*0fca6ea1SDimitry Andric // Conservatively assume hasSideEffects if it wasn't explicit. 4114*0fca6ea1SDimitry Andric if (InstInfo->hasSideEffects_Unset) 4115*0fca6ea1SDimitry Andric InstInfo->hasSideEffects = true; 4116*0fca6ea1SDimitry Andric } 4117*0fca6ea1SDimitry Andric return; 4118*0fca6ea1SDimitry Andric } 4119*0fca6ea1SDimitry Andric 4120*0fca6ea1SDimitry Andric // Complain about any flags that are still undefined. 4121*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { 4122*0fca6ea1SDimitry Andric CodeGenInstruction *InstInfo = 4123*0fca6ea1SDimitry Andric const_cast<CodeGenInstruction *>(Instructions[i]); 4124*0fca6ea1SDimitry Andric if (InstInfo->InferredFrom) 4125*0fca6ea1SDimitry Andric continue; 4126*0fca6ea1SDimitry Andric if (InstInfo->hasSideEffects_Unset) 4127*0fca6ea1SDimitry Andric PrintError(InstInfo->TheDef->getLoc(), 4128*0fca6ea1SDimitry Andric "Can't infer hasSideEffects from patterns"); 4129*0fca6ea1SDimitry Andric if (InstInfo->mayStore_Unset) 4130*0fca6ea1SDimitry Andric PrintError(InstInfo->TheDef->getLoc(), 4131*0fca6ea1SDimitry Andric "Can't infer mayStore from patterns"); 4132*0fca6ea1SDimitry Andric if (InstInfo->mayLoad_Unset) 4133*0fca6ea1SDimitry Andric PrintError(InstInfo->TheDef->getLoc(), 4134*0fca6ea1SDimitry Andric "Can't infer mayLoad from patterns"); 4135*0fca6ea1SDimitry Andric } 4136*0fca6ea1SDimitry Andric } 4137*0fca6ea1SDimitry Andric 4138*0fca6ea1SDimitry Andric /// Verify instruction flags against pattern node properties. 4139*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::VerifyInstructionFlags() { 4140*0fca6ea1SDimitry Andric unsigned Errors = 0; 4141*0fca6ea1SDimitry Andric for (const PatternToMatch &PTM : ptms()) { 4142*0fca6ea1SDimitry Andric SmallVector<Record *, 8> Instrs; 4143*0fca6ea1SDimitry Andric getInstructionsInTree(PTM.getDstPattern(), Instrs); 4144*0fca6ea1SDimitry Andric if (Instrs.empty()) 4145*0fca6ea1SDimitry Andric continue; 4146*0fca6ea1SDimitry Andric 4147*0fca6ea1SDimitry Andric // Count the number of instructions with each flag set. 4148*0fca6ea1SDimitry Andric unsigned NumSideEffects = 0; 4149*0fca6ea1SDimitry Andric unsigned NumStores = 0; 4150*0fca6ea1SDimitry Andric unsigned NumLoads = 0; 4151*0fca6ea1SDimitry Andric for (const Record *Instr : Instrs) { 4152*0fca6ea1SDimitry Andric const CodeGenInstruction &InstInfo = Target.getInstruction(Instr); 4153*0fca6ea1SDimitry Andric NumSideEffects += InstInfo.hasSideEffects; 4154*0fca6ea1SDimitry Andric NumStores += InstInfo.mayStore; 4155*0fca6ea1SDimitry Andric NumLoads += InstInfo.mayLoad; 4156*0fca6ea1SDimitry Andric } 4157*0fca6ea1SDimitry Andric 4158*0fca6ea1SDimitry Andric // Analyze the source pattern. 4159*0fca6ea1SDimitry Andric InstAnalyzer PatInfo(*this); 4160*0fca6ea1SDimitry Andric PatInfo.Analyze(PTM); 4161*0fca6ea1SDimitry Andric 4162*0fca6ea1SDimitry Andric // Collect error messages. 4163*0fca6ea1SDimitry Andric SmallVector<std::string, 4> Msgs; 4164*0fca6ea1SDimitry Andric 4165*0fca6ea1SDimitry Andric // Check for missing flags in the output. 4166*0fca6ea1SDimitry Andric // Permit extra flags for now at least. 4167*0fca6ea1SDimitry Andric if (PatInfo.hasSideEffects && !NumSideEffects) 4168*0fca6ea1SDimitry Andric Msgs.push_back("pattern has side effects, but hasSideEffects isn't set"); 4169*0fca6ea1SDimitry Andric 4170*0fca6ea1SDimitry Andric // Don't verify store flags on instructions with side effects. At least for 4171*0fca6ea1SDimitry Andric // intrinsics, side effects implies mayStore. 4172*0fca6ea1SDimitry Andric if (!PatInfo.hasSideEffects && PatInfo.mayStore && !NumStores) 4173*0fca6ea1SDimitry Andric Msgs.push_back("pattern may store, but mayStore isn't set"); 4174*0fca6ea1SDimitry Andric 4175*0fca6ea1SDimitry Andric // Similarly, mayStore implies mayLoad on intrinsics. 4176*0fca6ea1SDimitry Andric if (!PatInfo.mayStore && PatInfo.mayLoad && !NumLoads) 4177*0fca6ea1SDimitry Andric Msgs.push_back("pattern may load, but mayLoad isn't set"); 4178*0fca6ea1SDimitry Andric 4179*0fca6ea1SDimitry Andric // Print error messages. 4180*0fca6ea1SDimitry Andric if (Msgs.empty()) 4181*0fca6ea1SDimitry Andric continue; 4182*0fca6ea1SDimitry Andric ++Errors; 4183*0fca6ea1SDimitry Andric 4184*0fca6ea1SDimitry Andric for (const std::string &Msg : Msgs) 4185*0fca6ea1SDimitry Andric PrintError( 4186*0fca6ea1SDimitry Andric PTM.getSrcRecord()->getLoc(), 4187*0fca6ea1SDimitry Andric Twine(Msg) + " on the " + 4188*0fca6ea1SDimitry Andric (Instrs.size() == 1 ? "instruction" : "output instructions")); 4189*0fca6ea1SDimitry Andric // Provide the location of the relevant instruction definitions. 4190*0fca6ea1SDimitry Andric for (const Record *Instr : Instrs) { 4191*0fca6ea1SDimitry Andric if (Instr != PTM.getSrcRecord()) 4192*0fca6ea1SDimitry Andric PrintError(Instr->getLoc(), "defined here"); 4193*0fca6ea1SDimitry Andric const CodeGenInstruction &InstInfo = Target.getInstruction(Instr); 4194*0fca6ea1SDimitry Andric if (InstInfo.InferredFrom && InstInfo.InferredFrom != InstInfo.TheDef && 4195*0fca6ea1SDimitry Andric InstInfo.InferredFrom != PTM.getSrcRecord()) 4196*0fca6ea1SDimitry Andric PrintError(InstInfo.InferredFrom->getLoc(), "inferred from pattern"); 4197*0fca6ea1SDimitry Andric } 4198*0fca6ea1SDimitry Andric } 4199*0fca6ea1SDimitry Andric if (Errors) 4200*0fca6ea1SDimitry Andric PrintFatalError("Errors in DAG patterns"); 4201*0fca6ea1SDimitry Andric } 4202*0fca6ea1SDimitry Andric 4203*0fca6ea1SDimitry Andric /// Given a pattern result with an unresolved type, see if we can find one 4204*0fca6ea1SDimitry Andric /// instruction with an unresolved result type. Force this result type to an 4205*0fca6ea1SDimitry Andric /// arbitrary element if it's possible types to converge results. 4206*0fca6ea1SDimitry Andric static bool ForceArbitraryInstResultType(TreePatternNode &N, TreePattern &TP) { 4207*0fca6ea1SDimitry Andric if (N.isLeaf()) 4208*0fca6ea1SDimitry Andric return false; 4209*0fca6ea1SDimitry Andric 4210*0fca6ea1SDimitry Andric // Analyze children. 4211*0fca6ea1SDimitry Andric for (unsigned i = 0, e = N.getNumChildren(); i != e; ++i) 4212*0fca6ea1SDimitry Andric if (ForceArbitraryInstResultType(N.getChild(i), TP)) 4213*0fca6ea1SDimitry Andric return true; 4214*0fca6ea1SDimitry Andric 4215*0fca6ea1SDimitry Andric if (!N.getOperator()->isSubClassOf("Instruction")) 4216*0fca6ea1SDimitry Andric return false; 4217*0fca6ea1SDimitry Andric 4218*0fca6ea1SDimitry Andric // If this type is already concrete or completely unknown we can't do 4219*0fca6ea1SDimitry Andric // anything. 4220*0fca6ea1SDimitry Andric TypeInfer &TI = TP.getInfer(); 4221*0fca6ea1SDimitry Andric for (unsigned i = 0, e = N.getNumTypes(); i != e; ++i) { 4222*0fca6ea1SDimitry Andric if (N.getExtType(i).empty() || TI.isConcrete(N.getExtType(i), false)) 4223*0fca6ea1SDimitry Andric continue; 4224*0fca6ea1SDimitry Andric 4225*0fca6ea1SDimitry Andric // Otherwise, force its type to an arbitrary choice. 4226*0fca6ea1SDimitry Andric if (TI.forceArbitrary(N.getExtType(i))) 4227*0fca6ea1SDimitry Andric return true; 4228*0fca6ea1SDimitry Andric } 4229*0fca6ea1SDimitry Andric 4230*0fca6ea1SDimitry Andric return false; 4231*0fca6ea1SDimitry Andric } 4232*0fca6ea1SDimitry Andric 4233*0fca6ea1SDimitry Andric // Promote xform function to be an explicit node wherever set. 4234*0fca6ea1SDimitry Andric static TreePatternNodePtr PromoteXForms(TreePatternNodePtr N) { 4235*0fca6ea1SDimitry Andric if (Record *Xform = N->getTransformFn()) { 4236*0fca6ea1SDimitry Andric N->setTransformFn(nullptr); 4237*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> Children; 4238*0fca6ea1SDimitry Andric Children.push_back(PromoteXForms(N)); 4239*0fca6ea1SDimitry Andric return makeIntrusiveRefCnt<TreePatternNode>(Xform, std::move(Children), 4240*0fca6ea1SDimitry Andric N->getNumTypes()); 4241*0fca6ea1SDimitry Andric } 4242*0fca6ea1SDimitry Andric 4243*0fca6ea1SDimitry Andric if (!N->isLeaf()) 4244*0fca6ea1SDimitry Andric for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { 4245*0fca6ea1SDimitry Andric TreePatternNodePtr Child = N->getChildShared(i); 4246*0fca6ea1SDimitry Andric N->setChild(i, PromoteXForms(Child)); 4247*0fca6ea1SDimitry Andric } 4248*0fca6ea1SDimitry Andric return N; 4249*0fca6ea1SDimitry Andric } 4250*0fca6ea1SDimitry Andric 4251*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseOnePattern( 4252*0fca6ea1SDimitry Andric Record *TheDef, TreePattern &Pattern, TreePattern &Result, 4253*0fca6ea1SDimitry Andric const std::vector<Record *> &InstImpResults, bool ShouldIgnore) { 4254*0fca6ea1SDimitry Andric 4255*0fca6ea1SDimitry Andric // Inline pattern fragments and expand multiple alternatives. 4256*0fca6ea1SDimitry Andric Pattern.InlinePatternFragments(); 4257*0fca6ea1SDimitry Andric Result.InlinePatternFragments(); 4258*0fca6ea1SDimitry Andric 4259*0fca6ea1SDimitry Andric if (Result.getNumTrees() != 1) 4260*0fca6ea1SDimitry Andric Result.error("Cannot use multi-alternative fragments in result pattern!"); 4261*0fca6ea1SDimitry Andric 4262*0fca6ea1SDimitry Andric // Infer types. 4263*0fca6ea1SDimitry Andric bool IterateInference; 4264*0fca6ea1SDimitry Andric bool InferredAllPatternTypes, InferredAllResultTypes; 4265*0fca6ea1SDimitry Andric do { 4266*0fca6ea1SDimitry Andric // Infer as many types as possible. If we cannot infer all of them, we 4267*0fca6ea1SDimitry Andric // can never do anything with this pattern: report it to the user. 4268*0fca6ea1SDimitry Andric InferredAllPatternTypes = 4269*0fca6ea1SDimitry Andric Pattern.InferAllTypes(&Pattern.getNamedNodesMap()); 4270*0fca6ea1SDimitry Andric 4271*0fca6ea1SDimitry Andric // Infer as many types as possible. If we cannot infer all of them, we 4272*0fca6ea1SDimitry Andric // can never do anything with this pattern: report it to the user. 4273*0fca6ea1SDimitry Andric InferredAllResultTypes = Result.InferAllTypes(&Pattern.getNamedNodesMap()); 4274*0fca6ea1SDimitry Andric 4275*0fca6ea1SDimitry Andric IterateInference = false; 4276*0fca6ea1SDimitry Andric 4277*0fca6ea1SDimitry Andric // Apply the type of the result to the source pattern. This helps us 4278*0fca6ea1SDimitry Andric // resolve cases where the input type is known to be a pointer type (which 4279*0fca6ea1SDimitry Andric // is considered resolved), but the result knows it needs to be 32- or 4280*0fca6ea1SDimitry Andric // 64-bits. Infer the other way for good measure. 4281*0fca6ea1SDimitry Andric for (const auto &T : Pattern.getTrees()) 4282*0fca6ea1SDimitry Andric for (unsigned i = 0, e = std::min(Result.getOnlyTree()->getNumTypes(), 4283*0fca6ea1SDimitry Andric T->getNumTypes()); 4284*0fca6ea1SDimitry Andric i != e; ++i) { 4285*0fca6ea1SDimitry Andric IterateInference |= 4286*0fca6ea1SDimitry Andric T->UpdateNodeType(i, Result.getOnlyTree()->getExtType(i), Result); 4287*0fca6ea1SDimitry Andric IterateInference |= 4288*0fca6ea1SDimitry Andric Result.getOnlyTree()->UpdateNodeType(i, T->getExtType(i), Result); 4289*0fca6ea1SDimitry Andric } 4290*0fca6ea1SDimitry Andric 4291*0fca6ea1SDimitry Andric // If our iteration has converged and the input pattern's types are fully 4292*0fca6ea1SDimitry Andric // resolved but the result pattern is not fully resolved, we may have a 4293*0fca6ea1SDimitry Andric // situation where we have two instructions in the result pattern and 4294*0fca6ea1SDimitry Andric // the instructions require a common register class, but don't care about 4295*0fca6ea1SDimitry Andric // what actual MVT is used. This is actually a bug in our modelling: 4296*0fca6ea1SDimitry Andric // output patterns should have register classes, not MVTs. 4297*0fca6ea1SDimitry Andric // 4298*0fca6ea1SDimitry Andric // In any case, to handle this, we just go through and disambiguate some 4299*0fca6ea1SDimitry Andric // arbitrary types to the result pattern's nodes. 4300*0fca6ea1SDimitry Andric if (!IterateInference && InferredAllPatternTypes && !InferredAllResultTypes) 4301*0fca6ea1SDimitry Andric IterateInference = 4302*0fca6ea1SDimitry Andric ForceArbitraryInstResultType(*Result.getTree(0), Result); 4303*0fca6ea1SDimitry Andric } while (IterateInference); 4304*0fca6ea1SDimitry Andric 4305*0fca6ea1SDimitry Andric // Verify that we inferred enough types that we can do something with the 4306*0fca6ea1SDimitry Andric // pattern and result. If these fire the user has to add type casts. 4307*0fca6ea1SDimitry Andric if (!InferredAllPatternTypes) 4308*0fca6ea1SDimitry Andric Pattern.error("Could not infer all types in pattern!"); 4309*0fca6ea1SDimitry Andric if (!InferredAllResultTypes) { 4310*0fca6ea1SDimitry Andric Pattern.dump(); 4311*0fca6ea1SDimitry Andric Result.error("Could not infer all types in pattern result!"); 4312*0fca6ea1SDimitry Andric } 4313*0fca6ea1SDimitry Andric 4314*0fca6ea1SDimitry Andric // Promote xform function to be an explicit node wherever set. 4315*0fca6ea1SDimitry Andric TreePatternNodePtr DstShared = PromoteXForms(Result.getOnlyTree()); 4316*0fca6ea1SDimitry Andric 4317*0fca6ea1SDimitry Andric TreePattern Temp(Result.getRecord(), DstShared, false, *this); 4318*0fca6ea1SDimitry Andric Temp.InferAllTypes(); 4319*0fca6ea1SDimitry Andric 4320*0fca6ea1SDimitry Andric ListInit *Preds = TheDef->getValueAsListInit("Predicates"); 4321*0fca6ea1SDimitry Andric int Complexity = TheDef->getValueAsInt("AddedComplexity"); 4322*0fca6ea1SDimitry Andric 4323*0fca6ea1SDimitry Andric if (PatternRewriter) 4324*0fca6ea1SDimitry Andric PatternRewriter(&Pattern); 4325*0fca6ea1SDimitry Andric 4326*0fca6ea1SDimitry Andric // A pattern may end up with an "impossible" type, i.e. a situation 4327*0fca6ea1SDimitry Andric // where all types have been eliminated for some node in this pattern. 4328*0fca6ea1SDimitry Andric // This could occur for intrinsics that only make sense for a specific 4329*0fca6ea1SDimitry Andric // value type, and use a specific register class. If, for some mode, 4330*0fca6ea1SDimitry Andric // that register class does not accept that type, the type inference 4331*0fca6ea1SDimitry Andric // will lead to a contradiction, which is not an error however, but 4332*0fca6ea1SDimitry Andric // a sign that this pattern will simply never match. 4333*0fca6ea1SDimitry Andric if (Temp.getOnlyTree()->hasPossibleType()) { 4334*0fca6ea1SDimitry Andric for (const auto &T : Pattern.getTrees()) { 4335*0fca6ea1SDimitry Andric if (T->hasPossibleType()) 4336*0fca6ea1SDimitry Andric AddPatternToMatch(&Pattern, 4337*0fca6ea1SDimitry Andric PatternToMatch(TheDef, Preds, T, Temp.getOnlyTree(), 4338*0fca6ea1SDimitry Andric InstImpResults, Complexity, 4339*0fca6ea1SDimitry Andric TheDef->getID(), ShouldIgnore)); 4340*0fca6ea1SDimitry Andric } 4341*0fca6ea1SDimitry Andric } else { 4342*0fca6ea1SDimitry Andric // Show a message about a dropped pattern with some info to make it 4343*0fca6ea1SDimitry Andric // easier to identify it in the .td files. 4344*0fca6ea1SDimitry Andric LLVM_DEBUG({ 4345*0fca6ea1SDimitry Andric dbgs() << "Dropping: "; 4346*0fca6ea1SDimitry Andric Pattern.dump(); 4347*0fca6ea1SDimitry Andric Temp.getOnlyTree()->dump(); 4348*0fca6ea1SDimitry Andric dbgs() << "\n"; 4349*0fca6ea1SDimitry Andric }); 4350*0fca6ea1SDimitry Andric } 4351*0fca6ea1SDimitry Andric } 4352*0fca6ea1SDimitry Andric 4353*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParsePatterns() { 4354*0fca6ea1SDimitry Andric std::vector<Record *> Patterns = Records.getAllDerivedDefinitions("Pattern"); 4355*0fca6ea1SDimitry Andric 4356*0fca6ea1SDimitry Andric for (Record *CurPattern : Patterns) { 4357*0fca6ea1SDimitry Andric DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch"); 4358*0fca6ea1SDimitry Andric 4359*0fca6ea1SDimitry Andric // If the pattern references the null_frag, there's nothing to do. 4360*0fca6ea1SDimitry Andric if (hasNullFragReference(Tree)) 4361*0fca6ea1SDimitry Andric continue; 4362*0fca6ea1SDimitry Andric 4363*0fca6ea1SDimitry Andric TreePattern Pattern(CurPattern, Tree, true, *this); 4364*0fca6ea1SDimitry Andric 4365*0fca6ea1SDimitry Andric ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); 4366*0fca6ea1SDimitry Andric if (LI->empty()) 4367*0fca6ea1SDimitry Andric continue; // no pattern. 4368*0fca6ea1SDimitry Andric 4369*0fca6ea1SDimitry Andric // Parse the instruction. 4370*0fca6ea1SDimitry Andric TreePattern Result(CurPattern, LI, false, *this); 4371*0fca6ea1SDimitry Andric 4372*0fca6ea1SDimitry Andric if (Result.getNumTrees() != 1) 4373*0fca6ea1SDimitry Andric Result.error("Cannot handle instructions producing instructions " 4374*0fca6ea1SDimitry Andric "with temporaries yet!"); 4375*0fca6ea1SDimitry Andric 4376*0fca6ea1SDimitry Andric // Validate that the input pattern is correct. 4377*0fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> InstInputs; 4378*0fca6ea1SDimitry Andric MapVector<std::string, TreePatternNodePtr, std::map<std::string, unsigned>> 4379*0fca6ea1SDimitry Andric InstResults; 4380*0fca6ea1SDimitry Andric std::vector<Record *> InstImpResults; 4381*0fca6ea1SDimitry Andric for (unsigned j = 0, ee = Pattern.getNumTrees(); j != ee; ++j) 4382*0fca6ea1SDimitry Andric FindPatternInputsAndOutputs(Pattern, Pattern.getTree(j), InstInputs, 4383*0fca6ea1SDimitry Andric InstResults, InstImpResults); 4384*0fca6ea1SDimitry Andric 4385*0fca6ea1SDimitry Andric ParseOnePattern(CurPattern, Pattern, Result, InstImpResults, 4386*0fca6ea1SDimitry Andric CurPattern->getValueAsBit("GISelShouldIgnore")); 4387*0fca6ea1SDimitry Andric } 4388*0fca6ea1SDimitry Andric } 4389*0fca6ea1SDimitry Andric 4390*0fca6ea1SDimitry Andric static void collectModes(std::set<unsigned> &Modes, const TreePatternNode &N) { 4391*0fca6ea1SDimitry Andric for (const TypeSetByHwMode &VTS : N.getExtTypes()) 4392*0fca6ea1SDimitry Andric for (const auto &I : VTS) 4393*0fca6ea1SDimitry Andric Modes.insert(I.first); 4394*0fca6ea1SDimitry Andric 4395*0fca6ea1SDimitry Andric for (unsigned i = 0, e = N.getNumChildren(); i != e; ++i) 4396*0fca6ea1SDimitry Andric collectModes(Modes, N.getChild(i)); 4397*0fca6ea1SDimitry Andric } 4398*0fca6ea1SDimitry Andric 4399*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::ExpandHwModeBasedTypes() { 4400*0fca6ea1SDimitry Andric const CodeGenHwModes &CGH = getTargetInfo().getHwModes(); 4401*0fca6ea1SDimitry Andric if (CGH.getNumModeIds() == 1) 4402*0fca6ea1SDimitry Andric return; 4403*0fca6ea1SDimitry Andric 4404*0fca6ea1SDimitry Andric std::vector<PatternToMatch> Copy; 4405*0fca6ea1SDimitry Andric PatternsToMatch.swap(Copy); 4406*0fca6ea1SDimitry Andric 4407*0fca6ea1SDimitry Andric auto AppendPattern = [this](PatternToMatch &P, unsigned Mode, 4408*0fca6ea1SDimitry Andric StringRef Check) { 4409*0fca6ea1SDimitry Andric TreePatternNodePtr NewSrc = P.getSrcPattern().clone(); 4410*0fca6ea1SDimitry Andric TreePatternNodePtr NewDst = P.getDstPattern().clone(); 4411*0fca6ea1SDimitry Andric if (!NewSrc->setDefaultMode(Mode) || !NewDst->setDefaultMode(Mode)) { 4412*0fca6ea1SDimitry Andric return; 4413*0fca6ea1SDimitry Andric } 4414*0fca6ea1SDimitry Andric 4415*0fca6ea1SDimitry Andric PatternsToMatch.emplace_back( 4416*0fca6ea1SDimitry Andric P.getSrcRecord(), P.getPredicates(), std::move(NewSrc), 4417*0fca6ea1SDimitry Andric std::move(NewDst), P.getDstRegs(), P.getAddedComplexity(), 4418*0fca6ea1SDimitry Andric Record::getNewUID(Records), P.getGISelShouldIgnore(), Check); 4419*0fca6ea1SDimitry Andric }; 4420*0fca6ea1SDimitry Andric 4421*0fca6ea1SDimitry Andric for (PatternToMatch &P : Copy) { 4422*0fca6ea1SDimitry Andric const TreePatternNode *SrcP = nullptr, *DstP = nullptr; 4423*0fca6ea1SDimitry Andric if (P.getSrcPattern().hasProperTypeByHwMode()) 4424*0fca6ea1SDimitry Andric SrcP = &P.getSrcPattern(); 4425*0fca6ea1SDimitry Andric if (P.getDstPattern().hasProperTypeByHwMode()) 4426*0fca6ea1SDimitry Andric DstP = &P.getDstPattern(); 4427*0fca6ea1SDimitry Andric if (!SrcP && !DstP) { 4428*0fca6ea1SDimitry Andric PatternsToMatch.push_back(P); 4429*0fca6ea1SDimitry Andric continue; 4430*0fca6ea1SDimitry Andric } 4431*0fca6ea1SDimitry Andric 4432*0fca6ea1SDimitry Andric std::set<unsigned> Modes; 4433*0fca6ea1SDimitry Andric if (SrcP) 4434*0fca6ea1SDimitry Andric collectModes(Modes, *SrcP); 4435*0fca6ea1SDimitry Andric if (DstP) 4436*0fca6ea1SDimitry Andric collectModes(Modes, *DstP); 4437*0fca6ea1SDimitry Andric 4438*0fca6ea1SDimitry Andric // The predicate for the default mode needs to be constructed for each 4439*0fca6ea1SDimitry Andric // pattern separately. 4440*0fca6ea1SDimitry Andric // Since not all modes must be present in each pattern, if a mode m is 4441*0fca6ea1SDimitry Andric // absent, then there is no point in constructing a check for m. If such 4442*0fca6ea1SDimitry Andric // a check was created, it would be equivalent to checking the default 4443*0fca6ea1SDimitry Andric // mode, except not all modes' predicates would be a part of the checking 4444*0fca6ea1SDimitry Andric // code. The subsequently generated check for the default mode would then 4445*0fca6ea1SDimitry Andric // have the exact same patterns, but a different predicate code. To avoid 4446*0fca6ea1SDimitry Andric // duplicated patterns with different predicate checks, construct the 4447*0fca6ea1SDimitry Andric // default check as a negation of all predicates that are actually present 4448*0fca6ea1SDimitry Andric // in the source/destination patterns. 4449*0fca6ea1SDimitry Andric SmallString<128> DefaultCheck; 4450*0fca6ea1SDimitry Andric 4451*0fca6ea1SDimitry Andric for (unsigned M : Modes) { 4452*0fca6ea1SDimitry Andric if (M == DefaultMode) 4453*0fca6ea1SDimitry Andric continue; 4454*0fca6ea1SDimitry Andric 4455*0fca6ea1SDimitry Andric // Fill the map entry for this mode. 4456*0fca6ea1SDimitry Andric const HwMode &HM = CGH.getMode(M); 4457*0fca6ea1SDimitry Andric AppendPattern(P, M, HM.Predicates); 4458*0fca6ea1SDimitry Andric 4459*0fca6ea1SDimitry Andric // Add negations of the HM's predicates to the default predicate. 4460*0fca6ea1SDimitry Andric if (!DefaultCheck.empty()) 4461*0fca6ea1SDimitry Andric DefaultCheck += " && "; 4462*0fca6ea1SDimitry Andric DefaultCheck += "!("; 4463*0fca6ea1SDimitry Andric DefaultCheck += HM.Predicates; 4464*0fca6ea1SDimitry Andric DefaultCheck += ")"; 4465*0fca6ea1SDimitry Andric } 4466*0fca6ea1SDimitry Andric 4467*0fca6ea1SDimitry Andric bool HasDefault = Modes.count(DefaultMode); 4468*0fca6ea1SDimitry Andric if (HasDefault) 4469*0fca6ea1SDimitry Andric AppendPattern(P, DefaultMode, DefaultCheck); 4470*0fca6ea1SDimitry Andric } 4471*0fca6ea1SDimitry Andric } 4472*0fca6ea1SDimitry Andric 4473*0fca6ea1SDimitry Andric /// Dependent variable map for CodeGenDAGPattern variant generation 4474*0fca6ea1SDimitry Andric typedef StringMap<int> DepVarMap; 4475*0fca6ea1SDimitry Andric 4476*0fca6ea1SDimitry Andric static void FindDepVarsOf(TreePatternNode &N, DepVarMap &DepMap) { 4477*0fca6ea1SDimitry Andric if (N.isLeaf()) { 4478*0fca6ea1SDimitry Andric if (N.hasName() && isa<DefInit>(N.getLeafValue())) 4479*0fca6ea1SDimitry Andric DepMap[N.getName()]++; 4480*0fca6ea1SDimitry Andric } else { 4481*0fca6ea1SDimitry Andric for (size_t i = 0, e = N.getNumChildren(); i != e; ++i) 4482*0fca6ea1SDimitry Andric FindDepVarsOf(N.getChild(i), DepMap); 4483*0fca6ea1SDimitry Andric } 4484*0fca6ea1SDimitry Andric } 4485*0fca6ea1SDimitry Andric 4486*0fca6ea1SDimitry Andric /// Find dependent variables within child patterns 4487*0fca6ea1SDimitry Andric static void FindDepVars(TreePatternNode &N, MultipleUseVarSet &DepVars) { 4488*0fca6ea1SDimitry Andric DepVarMap depcounts; 4489*0fca6ea1SDimitry Andric FindDepVarsOf(N, depcounts); 4490*0fca6ea1SDimitry Andric for (const auto &Pair : depcounts) { 4491*0fca6ea1SDimitry Andric if (Pair.getValue() > 1) 4492*0fca6ea1SDimitry Andric DepVars.insert(Pair.getKey()); 4493*0fca6ea1SDimitry Andric } 4494*0fca6ea1SDimitry Andric } 4495*0fca6ea1SDimitry Andric 4496*0fca6ea1SDimitry Andric #ifndef NDEBUG 4497*0fca6ea1SDimitry Andric /// Dump the dependent variable set: 4498*0fca6ea1SDimitry Andric static void DumpDepVars(MultipleUseVarSet &DepVars) { 4499*0fca6ea1SDimitry Andric if (DepVars.empty()) { 4500*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "<empty set>"); 4501*0fca6ea1SDimitry Andric } else { 4502*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "[ "); 4503*0fca6ea1SDimitry Andric for (const auto &DepVar : DepVars) { 4504*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << DepVar.getKey() << " "); 4505*0fca6ea1SDimitry Andric } 4506*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "]"); 4507*0fca6ea1SDimitry Andric } 4508*0fca6ea1SDimitry Andric } 4509*0fca6ea1SDimitry Andric #endif 4510*0fca6ea1SDimitry Andric 4511*0fca6ea1SDimitry Andric /// CombineChildVariants - Given a bunch of permutations of each child of the 4512*0fca6ea1SDimitry Andric /// 'operator' node, put them together in all possible ways. 4513*0fca6ea1SDimitry Andric static void CombineChildVariants( 4514*0fca6ea1SDimitry Andric TreePatternNodePtr Orig, 4515*0fca6ea1SDimitry Andric const std::vector<std::vector<TreePatternNodePtr>> &ChildVariants, 4516*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> &OutVariants, CodeGenDAGPatterns &CDP, 4517*0fca6ea1SDimitry Andric const MultipleUseVarSet &DepVars) { 4518*0fca6ea1SDimitry Andric // Make sure that each operand has at least one variant to choose from. 4519*0fca6ea1SDimitry Andric for (const auto &Variants : ChildVariants) 4520*0fca6ea1SDimitry Andric if (Variants.empty()) 4521*0fca6ea1SDimitry Andric return; 4522*0fca6ea1SDimitry Andric 4523*0fca6ea1SDimitry Andric // The end result is an all-pairs construction of the resultant pattern. 4524*0fca6ea1SDimitry Andric std::vector<unsigned> Idxs(ChildVariants.size()); 4525*0fca6ea1SDimitry Andric bool NotDone; 4526*0fca6ea1SDimitry Andric do { 4527*0fca6ea1SDimitry Andric #ifndef NDEBUG 4528*0fca6ea1SDimitry Andric LLVM_DEBUG(if (!Idxs.empty()) { 4529*0fca6ea1SDimitry Andric errs() << Orig->getOperator()->getName() << ": Idxs = [ "; 4530*0fca6ea1SDimitry Andric for (unsigned Idx : Idxs) { 4531*0fca6ea1SDimitry Andric errs() << Idx << " "; 4532*0fca6ea1SDimitry Andric } 4533*0fca6ea1SDimitry Andric errs() << "]\n"; 4534*0fca6ea1SDimitry Andric }); 4535*0fca6ea1SDimitry Andric #endif 4536*0fca6ea1SDimitry Andric // Create the variant and add it to the output list. 4537*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> NewChildren; 4538*0fca6ea1SDimitry Andric NewChildren.reserve(ChildVariants.size()); 4539*0fca6ea1SDimitry Andric for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) 4540*0fca6ea1SDimitry Andric NewChildren.push_back(ChildVariants[i][Idxs[i]]); 4541*0fca6ea1SDimitry Andric TreePatternNodePtr R = makeIntrusiveRefCnt<TreePatternNode>( 4542*0fca6ea1SDimitry Andric Orig->getOperator(), std::move(NewChildren), Orig->getNumTypes()); 4543*0fca6ea1SDimitry Andric 4544*0fca6ea1SDimitry Andric // Copy over properties. 4545*0fca6ea1SDimitry Andric R->setName(Orig->getName()); 4546*0fca6ea1SDimitry Andric R->setNamesAsPredicateArg(Orig->getNamesAsPredicateArg()); 4547*0fca6ea1SDimitry Andric R->setPredicateCalls(Orig->getPredicateCalls()); 4548*0fca6ea1SDimitry Andric R->setGISelFlagsRecord(Orig->getGISelFlagsRecord()); 4549*0fca6ea1SDimitry Andric R->setTransformFn(Orig->getTransformFn()); 4550*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i) 4551*0fca6ea1SDimitry Andric R->setType(i, Orig->getExtType(i)); 4552*0fca6ea1SDimitry Andric 4553*0fca6ea1SDimitry Andric // If this pattern cannot match, do not include it as a variant. 4554*0fca6ea1SDimitry Andric std::string ErrString; 4555*0fca6ea1SDimitry Andric // Scan to see if this pattern has already been emitted. We can get 4556*0fca6ea1SDimitry Andric // duplication due to things like commuting: 4557*0fca6ea1SDimitry Andric // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a) 4558*0fca6ea1SDimitry Andric // which are the same pattern. Ignore the dups. 4559*0fca6ea1SDimitry Andric if (R->canPatternMatch(ErrString, CDP) && 4560*0fca6ea1SDimitry Andric none_of(OutVariants, [&](TreePatternNodePtr Variant) { 4561*0fca6ea1SDimitry Andric return R->isIsomorphicTo(*Variant, DepVars); 4562*0fca6ea1SDimitry Andric })) 4563*0fca6ea1SDimitry Andric OutVariants.push_back(R); 4564*0fca6ea1SDimitry Andric 4565*0fca6ea1SDimitry Andric // Increment indices to the next permutation by incrementing the 4566*0fca6ea1SDimitry Andric // indices from last index backward, e.g., generate the sequence 4567*0fca6ea1SDimitry Andric // [0, 0], [0, 1], [1, 0], [1, 1]. 4568*0fca6ea1SDimitry Andric int IdxsIdx; 4569*0fca6ea1SDimitry Andric for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) { 4570*0fca6ea1SDimitry Andric if (++Idxs[IdxsIdx] == ChildVariants[IdxsIdx].size()) 4571*0fca6ea1SDimitry Andric Idxs[IdxsIdx] = 0; 4572*0fca6ea1SDimitry Andric else 4573*0fca6ea1SDimitry Andric break; 4574*0fca6ea1SDimitry Andric } 4575*0fca6ea1SDimitry Andric NotDone = (IdxsIdx >= 0); 4576*0fca6ea1SDimitry Andric } while (NotDone); 4577*0fca6ea1SDimitry Andric } 4578*0fca6ea1SDimitry Andric 4579*0fca6ea1SDimitry Andric /// CombineChildVariants - A helper function for binary operators. 4580*0fca6ea1SDimitry Andric /// 4581*0fca6ea1SDimitry Andric static void CombineChildVariants(TreePatternNodePtr Orig, 4582*0fca6ea1SDimitry Andric const std::vector<TreePatternNodePtr> &LHS, 4583*0fca6ea1SDimitry Andric const std::vector<TreePatternNodePtr> &RHS, 4584*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> &OutVariants, 4585*0fca6ea1SDimitry Andric CodeGenDAGPatterns &CDP, 4586*0fca6ea1SDimitry Andric const MultipleUseVarSet &DepVars) { 4587*0fca6ea1SDimitry Andric std::vector<std::vector<TreePatternNodePtr>> ChildVariants; 4588*0fca6ea1SDimitry Andric ChildVariants.push_back(LHS); 4589*0fca6ea1SDimitry Andric ChildVariants.push_back(RHS); 4590*0fca6ea1SDimitry Andric CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars); 4591*0fca6ea1SDimitry Andric } 4592*0fca6ea1SDimitry Andric 4593*0fca6ea1SDimitry Andric static void 4594*0fca6ea1SDimitry Andric GatherChildrenOfAssociativeOpcode(TreePatternNodePtr N, 4595*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> &Children) { 4596*0fca6ea1SDimitry Andric assert(N->getNumChildren() == 2 && 4597*0fca6ea1SDimitry Andric "Associative but doesn't have 2 children!"); 4598*0fca6ea1SDimitry Andric Record *Operator = N->getOperator(); 4599*0fca6ea1SDimitry Andric 4600*0fca6ea1SDimitry Andric // Only permit raw nodes. 4601*0fca6ea1SDimitry Andric if (!N->getName().empty() || !N->getPredicateCalls().empty() || 4602*0fca6ea1SDimitry Andric N->getTransformFn()) { 4603*0fca6ea1SDimitry Andric Children.push_back(N); 4604*0fca6ea1SDimitry Andric return; 4605*0fca6ea1SDimitry Andric } 4606*0fca6ea1SDimitry Andric 4607*0fca6ea1SDimitry Andric if (N->getChild(0).isLeaf() || N->getChild(0).getOperator() != Operator) 4608*0fca6ea1SDimitry Andric Children.push_back(N->getChildShared(0)); 4609*0fca6ea1SDimitry Andric else 4610*0fca6ea1SDimitry Andric GatherChildrenOfAssociativeOpcode(N->getChildShared(0), Children); 4611*0fca6ea1SDimitry Andric 4612*0fca6ea1SDimitry Andric if (N->getChild(1).isLeaf() || N->getChild(1).getOperator() != Operator) 4613*0fca6ea1SDimitry Andric Children.push_back(N->getChildShared(1)); 4614*0fca6ea1SDimitry Andric else 4615*0fca6ea1SDimitry Andric GatherChildrenOfAssociativeOpcode(N->getChildShared(1), Children); 4616*0fca6ea1SDimitry Andric } 4617*0fca6ea1SDimitry Andric 4618*0fca6ea1SDimitry Andric /// GenerateVariantsOf - Given a pattern N, generate all permutations we can of 4619*0fca6ea1SDimitry Andric /// the (potentially recursive) pattern by using algebraic laws. 4620*0fca6ea1SDimitry Andric /// 4621*0fca6ea1SDimitry Andric static void GenerateVariantsOf(TreePatternNodePtr N, 4622*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> &OutVariants, 4623*0fca6ea1SDimitry Andric CodeGenDAGPatterns &CDP, 4624*0fca6ea1SDimitry Andric const MultipleUseVarSet &DepVars) { 4625*0fca6ea1SDimitry Andric // We cannot permute leaves or ComplexPattern uses. 4626*0fca6ea1SDimitry Andric if (N->isLeaf() || N->getOperator()->isSubClassOf("ComplexPattern")) { 4627*0fca6ea1SDimitry Andric OutVariants.push_back(N); 4628*0fca6ea1SDimitry Andric return; 4629*0fca6ea1SDimitry Andric } 4630*0fca6ea1SDimitry Andric 4631*0fca6ea1SDimitry Andric // Look up interesting info about the node. 4632*0fca6ea1SDimitry Andric const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(N->getOperator()); 4633*0fca6ea1SDimitry Andric 4634*0fca6ea1SDimitry Andric // If this node is associative, re-associate. 4635*0fca6ea1SDimitry Andric if (NodeInfo.hasProperty(SDNPAssociative)) { 4636*0fca6ea1SDimitry Andric // Re-associate by pulling together all of the linked operators 4637*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> MaximalChildren; 4638*0fca6ea1SDimitry Andric GatherChildrenOfAssociativeOpcode(N, MaximalChildren); 4639*0fca6ea1SDimitry Andric 4640*0fca6ea1SDimitry Andric // Only handle child sizes of 3. Otherwise we'll end up trying too many 4641*0fca6ea1SDimitry Andric // permutations. 4642*0fca6ea1SDimitry Andric if (MaximalChildren.size() == 3) { 4643*0fca6ea1SDimitry Andric // Find the variants of all of our maximal children. 4644*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> AVariants, BVariants, CVariants; 4645*0fca6ea1SDimitry Andric GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars); 4646*0fca6ea1SDimitry Andric GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars); 4647*0fca6ea1SDimitry Andric GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars); 4648*0fca6ea1SDimitry Andric 4649*0fca6ea1SDimitry Andric // There are only two ways we can permute the tree: 4650*0fca6ea1SDimitry Andric // (A op B) op C and A op (B op C) 4651*0fca6ea1SDimitry Andric // Within these forms, we can also permute A/B/C. 4652*0fca6ea1SDimitry Andric 4653*0fca6ea1SDimitry Andric // Generate legal pair permutations of A/B/C. 4654*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> ABVariants; 4655*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> BAVariants; 4656*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> ACVariants; 4657*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> CAVariants; 4658*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> BCVariants; 4659*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> CBVariants; 4660*0fca6ea1SDimitry Andric CombineChildVariants(N, AVariants, BVariants, ABVariants, CDP, DepVars); 4661*0fca6ea1SDimitry Andric CombineChildVariants(N, BVariants, AVariants, BAVariants, CDP, DepVars); 4662*0fca6ea1SDimitry Andric CombineChildVariants(N, AVariants, CVariants, ACVariants, CDP, DepVars); 4663*0fca6ea1SDimitry Andric CombineChildVariants(N, CVariants, AVariants, CAVariants, CDP, DepVars); 4664*0fca6ea1SDimitry Andric CombineChildVariants(N, BVariants, CVariants, BCVariants, CDP, DepVars); 4665*0fca6ea1SDimitry Andric CombineChildVariants(N, CVariants, BVariants, CBVariants, CDP, DepVars); 4666*0fca6ea1SDimitry Andric 4667*0fca6ea1SDimitry Andric // Combine those into the result: (x op x) op x 4668*0fca6ea1SDimitry Andric CombineChildVariants(N, ABVariants, CVariants, OutVariants, CDP, DepVars); 4669*0fca6ea1SDimitry Andric CombineChildVariants(N, BAVariants, CVariants, OutVariants, CDP, DepVars); 4670*0fca6ea1SDimitry Andric CombineChildVariants(N, ACVariants, BVariants, OutVariants, CDP, DepVars); 4671*0fca6ea1SDimitry Andric CombineChildVariants(N, CAVariants, BVariants, OutVariants, CDP, DepVars); 4672*0fca6ea1SDimitry Andric CombineChildVariants(N, BCVariants, AVariants, OutVariants, CDP, DepVars); 4673*0fca6ea1SDimitry Andric CombineChildVariants(N, CBVariants, AVariants, OutVariants, CDP, DepVars); 4674*0fca6ea1SDimitry Andric 4675*0fca6ea1SDimitry Andric // Combine those into the result: x op (x op x) 4676*0fca6ea1SDimitry Andric CombineChildVariants(N, CVariants, ABVariants, OutVariants, CDP, DepVars); 4677*0fca6ea1SDimitry Andric CombineChildVariants(N, CVariants, BAVariants, OutVariants, CDP, DepVars); 4678*0fca6ea1SDimitry Andric CombineChildVariants(N, BVariants, ACVariants, OutVariants, CDP, DepVars); 4679*0fca6ea1SDimitry Andric CombineChildVariants(N, BVariants, CAVariants, OutVariants, CDP, DepVars); 4680*0fca6ea1SDimitry Andric CombineChildVariants(N, AVariants, BCVariants, OutVariants, CDP, DepVars); 4681*0fca6ea1SDimitry Andric CombineChildVariants(N, AVariants, CBVariants, OutVariants, CDP, DepVars); 4682*0fca6ea1SDimitry Andric return; 4683*0fca6ea1SDimitry Andric } 4684*0fca6ea1SDimitry Andric } 4685*0fca6ea1SDimitry Andric 4686*0fca6ea1SDimitry Andric // Compute permutations of all children. 4687*0fca6ea1SDimitry Andric std::vector<std::vector<TreePatternNodePtr>> ChildVariants( 4688*0fca6ea1SDimitry Andric N->getNumChildren()); 4689*0fca6ea1SDimitry Andric for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) 4690*0fca6ea1SDimitry Andric GenerateVariantsOf(N->getChildShared(i), ChildVariants[i], CDP, DepVars); 4691*0fca6ea1SDimitry Andric 4692*0fca6ea1SDimitry Andric // Build all permutations based on how the children were formed. 4693*0fca6ea1SDimitry Andric CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars); 4694*0fca6ea1SDimitry Andric 4695*0fca6ea1SDimitry Andric // If this node is commutative, consider the commuted order. 4696*0fca6ea1SDimitry Andric bool isCommIntrinsic = N->isCommutativeIntrinsic(CDP); 4697*0fca6ea1SDimitry Andric if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) { 4698*0fca6ea1SDimitry Andric unsigned Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id. 4699*0fca6ea1SDimitry Andric assert(N->getNumChildren() >= (2 + Skip) && 4700*0fca6ea1SDimitry Andric "Commutative but doesn't have 2 children!"); 4701*0fca6ea1SDimitry Andric // Don't allow commuting children which are actually register references. 4702*0fca6ea1SDimitry Andric bool NoRegisters = true; 4703*0fca6ea1SDimitry Andric unsigned i = 0 + Skip; 4704*0fca6ea1SDimitry Andric unsigned e = 2 + Skip; 4705*0fca6ea1SDimitry Andric for (; i != e; ++i) { 4706*0fca6ea1SDimitry Andric TreePatternNode &Child = N->getChild(i); 4707*0fca6ea1SDimitry Andric if (Child.isLeaf()) 4708*0fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(Child.getLeafValue())) { 4709*0fca6ea1SDimitry Andric Record *RR = DI->getDef(); 4710*0fca6ea1SDimitry Andric if (RR->isSubClassOf("Register")) 4711*0fca6ea1SDimitry Andric NoRegisters = false; 4712*0fca6ea1SDimitry Andric } 4713*0fca6ea1SDimitry Andric } 4714*0fca6ea1SDimitry Andric // Consider the commuted order. 4715*0fca6ea1SDimitry Andric if (NoRegisters) { 4716*0fca6ea1SDimitry Andric // Swap the first two operands after the intrinsic id, if present. 4717*0fca6ea1SDimitry Andric unsigned i = isCommIntrinsic ? 1 : 0; 4718*0fca6ea1SDimitry Andric std::swap(ChildVariants[i], ChildVariants[i + 1]); 4719*0fca6ea1SDimitry Andric CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars); 4720*0fca6ea1SDimitry Andric } 4721*0fca6ea1SDimitry Andric } 4722*0fca6ea1SDimitry Andric } 4723*0fca6ea1SDimitry Andric 4724*0fca6ea1SDimitry Andric // GenerateVariants - Generate variants. For example, commutative patterns can 4725*0fca6ea1SDimitry Andric // match multiple ways. Add them to PatternsToMatch as well. 4726*0fca6ea1SDimitry Andric void CodeGenDAGPatterns::GenerateVariants() { 4727*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "Generating instruction variants.\n"); 4728*0fca6ea1SDimitry Andric 4729*0fca6ea1SDimitry Andric // Loop over all of the patterns we've collected, checking to see if we can 4730*0fca6ea1SDimitry Andric // generate variants of the instruction, through the exploitation of 4731*0fca6ea1SDimitry Andric // identities. This permits the target to provide aggressive matching without 4732*0fca6ea1SDimitry Andric // the .td file having to contain tons of variants of instructions. 4733*0fca6ea1SDimitry Andric // 4734*0fca6ea1SDimitry Andric // Note that this loop adds new patterns to the PatternsToMatch list, but we 4735*0fca6ea1SDimitry Andric // intentionally do not reconsider these. Any variants of added patterns have 4736*0fca6ea1SDimitry Andric // already been added. 4737*0fca6ea1SDimitry Andric // 4738*0fca6ea1SDimitry Andric for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) { 4739*0fca6ea1SDimitry Andric MultipleUseVarSet DepVars; 4740*0fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> Variants; 4741*0fca6ea1SDimitry Andric FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars); 4742*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "Dependent/multiply used variables: "); 4743*0fca6ea1SDimitry Andric LLVM_DEBUG(DumpDepVars(DepVars)); 4744*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "\n"); 4745*0fca6ea1SDimitry Andric GenerateVariantsOf(PatternsToMatch[i].getSrcPatternShared(), Variants, 4746*0fca6ea1SDimitry Andric *this, DepVars); 4747*0fca6ea1SDimitry Andric 4748*0fca6ea1SDimitry Andric assert(PatternsToMatch[i].getHwModeFeatures().empty() && 4749*0fca6ea1SDimitry Andric "HwModes should not have been expanded yet!"); 4750*0fca6ea1SDimitry Andric 4751*0fca6ea1SDimitry Andric assert(!Variants.empty() && "Must create at least original variant!"); 4752*0fca6ea1SDimitry Andric if (Variants.size() == 1) // No additional variants for this pattern. 4753*0fca6ea1SDimitry Andric continue; 4754*0fca6ea1SDimitry Andric 4755*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "FOUND VARIANTS OF: "; 4756*0fca6ea1SDimitry Andric PatternsToMatch[i].getSrcPattern().dump(); errs() << "\n"); 4757*0fca6ea1SDimitry Andric 4758*0fca6ea1SDimitry Andric for (unsigned v = 0, e = Variants.size(); v != e; ++v) { 4759*0fca6ea1SDimitry Andric TreePatternNodePtr Variant = Variants[v]; 4760*0fca6ea1SDimitry Andric 4761*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << " VAR#" << v << ": "; Variant->dump(); 4762*0fca6ea1SDimitry Andric errs() << "\n"); 4763*0fca6ea1SDimitry Andric 4764*0fca6ea1SDimitry Andric // Scan to see if an instruction or explicit pattern already matches this. 4765*0fca6ea1SDimitry Andric bool AlreadyExists = false; 4766*0fca6ea1SDimitry Andric for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) { 4767*0fca6ea1SDimitry Andric // Skip if the top level predicates do not match. 4768*0fca6ea1SDimitry Andric if ((i != p) && (PatternsToMatch[i].getPredicates() != 4769*0fca6ea1SDimitry Andric PatternsToMatch[p].getPredicates())) 4770*0fca6ea1SDimitry Andric continue; 4771*0fca6ea1SDimitry Andric // Check to see if this variant already exists. 4772*0fca6ea1SDimitry Andric if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(), 4773*0fca6ea1SDimitry Andric DepVars)) { 4774*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n"); 4775*0fca6ea1SDimitry Andric AlreadyExists = true; 4776*0fca6ea1SDimitry Andric break; 4777*0fca6ea1SDimitry Andric } 4778*0fca6ea1SDimitry Andric } 4779*0fca6ea1SDimitry Andric // If we already have it, ignore the variant. 4780*0fca6ea1SDimitry Andric if (AlreadyExists) 4781*0fca6ea1SDimitry Andric continue; 4782*0fca6ea1SDimitry Andric 4783*0fca6ea1SDimitry Andric // Otherwise, add it to the list of patterns we have. 4784*0fca6ea1SDimitry Andric PatternsToMatch.emplace_back( 4785*0fca6ea1SDimitry Andric PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(), 4786*0fca6ea1SDimitry Andric Variant, PatternsToMatch[i].getDstPatternShared(), 4787*0fca6ea1SDimitry Andric PatternsToMatch[i].getDstRegs(), 4788*0fca6ea1SDimitry Andric PatternsToMatch[i].getAddedComplexity(), Record::getNewUID(Records), 4789*0fca6ea1SDimitry Andric PatternsToMatch[i].getGISelShouldIgnore(), 4790*0fca6ea1SDimitry Andric PatternsToMatch[i].getHwModeFeatures()); 4791*0fca6ea1SDimitry Andric } 4792*0fca6ea1SDimitry Andric 4793*0fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "\n"); 4794*0fca6ea1SDimitry Andric } 4795*0fca6ea1SDimitry Andric } 4796