1f22ef01cSRoman Divacky //===- CodeGenDAGPatterns.cpp - Read DAG patterns from .td file -----------===// 2f22ef01cSRoman Divacky // 3f22ef01cSRoman Divacky // The LLVM Compiler Infrastructure 4f22ef01cSRoman Divacky // 5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source 6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details. 7f22ef01cSRoman Divacky // 8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 9f22ef01cSRoman Divacky // 10f22ef01cSRoman Divacky // This file implements the CodeGenDAGPatterns class, which is used to read and 11f22ef01cSRoman Divacky // represent the patterns present in a .td file for instructions. 12f22ef01cSRoman Divacky // 13f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 14f22ef01cSRoman Divacky 15f22ef01cSRoman Divacky #include "CodeGenDAGPatterns.h" 162cab237bSDimitry Andric #include "llvm/ADT/DenseSet.h" 17f22ef01cSRoman Divacky #include "llvm/ADT/STLExtras.h" 182cab237bSDimitry Andric #include "llvm/ADT/SmallSet.h" 197d523365SDimitry Andric #include "llvm/ADT/SmallString.h" 20139f7f9bSDimitry Andric #include "llvm/ADT/StringExtras.h" 212cab237bSDimitry Andric #include "llvm/ADT/StringMap.h" 22cb4dff85SDimitry Andric #include "llvm/ADT/Twine.h" 23f22ef01cSRoman Divacky #include "llvm/Support/Debug.h" 24dff0c46cSDimitry Andric #include "llvm/Support/ErrorHandling.h" 25139f7f9bSDimitry Andric #include "llvm/TableGen/Error.h" 26139f7f9bSDimitry Andric #include "llvm/TableGen/Record.h" 27f22ef01cSRoman Divacky #include <algorithm> 28dff0c46cSDimitry Andric #include <cstdio> 29dff0c46cSDimitry Andric #include <set> 30f22ef01cSRoman Divacky using namespace llvm; 31f22ef01cSRoman Divacky 3291bc56edSDimitry Andric #define DEBUG_TYPE "dag-patterns" 3391bc56edSDimitry Andric 342cab237bSDimitry Andric static inline bool isIntegerOrPtr(MVT VT) { 352cab237bSDimitry Andric return VT.isInteger() || VT == MVT::iPTR; 36f22ef01cSRoman Divacky } 372cab237bSDimitry Andric static inline bool isFloatingPoint(MVT VT) { 382cab237bSDimitry Andric return VT.isFloatingPoint(); 39f22ef01cSRoman Divacky } 402cab237bSDimitry Andric static inline bool isVector(MVT VT) { 412cab237bSDimitry Andric return VT.isVector(); 42f22ef01cSRoman Divacky } 432cab237bSDimitry Andric static inline bool isScalar(MVT VT) { 442cab237bSDimitry Andric return !VT.isVector(); 45f22ef01cSRoman Divacky } 46f22ef01cSRoman Divacky 472cab237bSDimitry Andric template <typename Predicate> 482cab237bSDimitry Andric static bool berase_if(MachineValueTypeSet &S, Predicate P) { 492cab237bSDimitry Andric bool Erased = false; 502cab237bSDimitry Andric // It is ok to iterate over MachineValueTypeSet and remove elements from it 512cab237bSDimitry Andric // at the same time. 522cab237bSDimitry Andric for (MVT T : S) { 532cab237bSDimitry Andric if (!P(T)) 542cab237bSDimitry Andric continue; 552cab237bSDimitry Andric Erased = true; 562cab237bSDimitry Andric S.erase(T); 572cab237bSDimitry Andric } 582cab237bSDimitry Andric return Erased; 592cab237bSDimitry Andric } 602cab237bSDimitry Andric 612cab237bSDimitry Andric // --- TypeSetByHwMode 622cab237bSDimitry Andric 632cab237bSDimitry Andric // This is a parameterized type-set class. For each mode there is a list 642cab237bSDimitry Andric // of types that are currently possible for a given tree node. Type 652cab237bSDimitry Andric // inference will apply to each mode separately. 662cab237bSDimitry Andric 672cab237bSDimitry Andric TypeSetByHwMode::TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList) { 682cab237bSDimitry Andric for (const ValueTypeByHwMode &VVT : VTList) 692cab237bSDimitry Andric insert(VVT); 702cab237bSDimitry Andric } 712cab237bSDimitry Andric 722cab237bSDimitry Andric bool TypeSetByHwMode::isValueTypeByHwMode(bool AllowEmpty) const { 732cab237bSDimitry Andric for (const auto &I : *this) { 742cab237bSDimitry Andric if (I.second.size() > 1) 752cab237bSDimitry Andric return false; 762cab237bSDimitry Andric if (!AllowEmpty && I.second.empty()) 772cab237bSDimitry Andric return false; 782cab237bSDimitry Andric } 792cab237bSDimitry Andric return true; 802cab237bSDimitry Andric } 812cab237bSDimitry Andric 822cab237bSDimitry Andric ValueTypeByHwMode TypeSetByHwMode::getValueTypeByHwMode() const { 832cab237bSDimitry Andric assert(isValueTypeByHwMode(true) && 842cab237bSDimitry Andric "The type set has multiple types for at least one HW mode"); 852cab237bSDimitry Andric ValueTypeByHwMode VVT; 862cab237bSDimitry Andric for (const auto &I : *this) { 872cab237bSDimitry Andric MVT T = I.second.empty() ? MVT::Other : *I.second.begin(); 882cab237bSDimitry Andric VVT.getOrCreateTypeForMode(I.first, T); 892cab237bSDimitry Andric } 902cab237bSDimitry Andric return VVT; 912cab237bSDimitry Andric } 922cab237bSDimitry Andric 932cab237bSDimitry Andric bool TypeSetByHwMode::isPossible() const { 942cab237bSDimitry Andric for (const auto &I : *this) 952cab237bSDimitry Andric if (!I.second.empty()) 962cab237bSDimitry Andric return true; 972cab237bSDimitry Andric return false; 982cab237bSDimitry Andric } 992cab237bSDimitry Andric 1002cab237bSDimitry Andric bool TypeSetByHwMode::insert(const ValueTypeByHwMode &VVT) { 1012cab237bSDimitry Andric bool Changed = false; 1022cab237bSDimitry Andric SmallDenseSet<unsigned, 4> Modes; 1032cab237bSDimitry Andric for (const auto &P : VVT) { 1042cab237bSDimitry Andric unsigned M = P.first; 1052cab237bSDimitry Andric Modes.insert(M); 1062cab237bSDimitry Andric // Make sure there exists a set for each specific mode from VVT. 1072cab237bSDimitry Andric Changed |= getOrCreate(M).insert(P.second).second; 1082cab237bSDimitry Andric } 1092cab237bSDimitry Andric 1102cab237bSDimitry Andric // If VVT has a default mode, add the corresponding type to all 1112cab237bSDimitry Andric // modes in "this" that do not exist in VVT. 1122cab237bSDimitry Andric if (Modes.count(DefaultMode)) { 1132cab237bSDimitry Andric MVT DT = VVT.getType(DefaultMode); 1142cab237bSDimitry Andric for (auto &I : *this) 1152cab237bSDimitry Andric if (!Modes.count(I.first)) 1162cab237bSDimitry Andric Changed |= I.second.insert(DT).second; 1172cab237bSDimitry Andric } 1182cab237bSDimitry Andric return Changed; 1192cab237bSDimitry Andric } 1202cab237bSDimitry Andric 1212cab237bSDimitry Andric // Constrain the type set to be the intersection with VTS. 1222cab237bSDimitry Andric bool TypeSetByHwMode::constrain(const TypeSetByHwMode &VTS) { 1232cab237bSDimitry Andric bool Changed = false; 1242cab237bSDimitry Andric if (hasDefault()) { 1252cab237bSDimitry Andric for (const auto &I : VTS) { 1262cab237bSDimitry Andric unsigned M = I.first; 1272cab237bSDimitry Andric if (M == DefaultMode || hasMode(M)) 1282cab237bSDimitry Andric continue; 1292cab237bSDimitry Andric Map.insert({M, Map.at(DefaultMode)}); 1302cab237bSDimitry Andric Changed = true; 131f22ef01cSRoman Divacky } 132f22ef01cSRoman Divacky } 133f22ef01cSRoman Divacky 1342cab237bSDimitry Andric for (auto &I : *this) { 1352cab237bSDimitry Andric unsigned M = I.first; 1362cab237bSDimitry Andric SetType &S = I.second; 1372cab237bSDimitry Andric if (VTS.hasMode(M) || VTS.hasDefault()) { 1382cab237bSDimitry Andric Changed |= intersect(I.second, VTS.get(M)); 1392cab237bSDimitry Andric } else if (!S.empty()) { 1402cab237bSDimitry Andric S.clear(); 1412cab237bSDimitry Andric Changed = true; 1422cab237bSDimitry Andric } 1432cab237bSDimitry Andric } 1442cab237bSDimitry Andric return Changed; 145f22ef01cSRoman Divacky } 146f22ef01cSRoman Divacky 1472cab237bSDimitry Andric template <typename Predicate> 1482cab237bSDimitry Andric bool TypeSetByHwMode::constrain(Predicate P) { 1492cab237bSDimitry Andric bool Changed = false; 1502cab237bSDimitry Andric for (auto &I : *this) 1512cab237bSDimitry Andric Changed |= berase_if(I.second, [&P](MVT VT) { return !P(VT); }); 1522cab237bSDimitry Andric return Changed; 1532cab237bSDimitry Andric } 154f22ef01cSRoman Divacky 1552cab237bSDimitry Andric template <typename Predicate> 1562cab237bSDimitry Andric bool TypeSetByHwMode::assign_if(const TypeSetByHwMode &VTS, Predicate P) { 1572cab237bSDimitry Andric assert(empty()); 1582cab237bSDimitry Andric for (const auto &I : VTS) { 1592cab237bSDimitry Andric SetType &S = getOrCreate(I.first); 1602cab237bSDimitry Andric for (auto J : I.second) 1612cab237bSDimitry Andric if (P(J)) 1622cab237bSDimitry Andric S.insert(J); 1632cab237bSDimitry Andric } 1642cab237bSDimitry Andric return !empty(); 1652cab237bSDimitry Andric } 1662cab237bSDimitry Andric 1672cab237bSDimitry Andric void TypeSetByHwMode::writeToStream(raw_ostream &OS) const { 1682cab237bSDimitry Andric SmallVector<unsigned, 4> Modes; 1692cab237bSDimitry Andric Modes.reserve(Map.size()); 1702cab237bSDimitry Andric 1712cab237bSDimitry Andric for (const auto &I : *this) 1722cab237bSDimitry Andric Modes.push_back(I.first); 1732cab237bSDimitry Andric if (Modes.empty()) { 1742cab237bSDimitry Andric OS << "{}"; 1752cab237bSDimitry Andric return; 1762cab237bSDimitry Andric } 1772cab237bSDimitry Andric array_pod_sort(Modes.begin(), Modes.end()); 1782cab237bSDimitry Andric 1792cab237bSDimitry Andric OS << '{'; 1802cab237bSDimitry Andric for (unsigned M : Modes) { 1812cab237bSDimitry Andric OS << ' ' << getModeName(M) << ':'; 1822cab237bSDimitry Andric writeToStream(get(M), OS); 1832cab237bSDimitry Andric } 1842cab237bSDimitry Andric OS << " }"; 1852cab237bSDimitry Andric } 1862cab237bSDimitry Andric 1872cab237bSDimitry Andric void TypeSetByHwMode::writeToStream(const SetType &S, raw_ostream &OS) { 1882cab237bSDimitry Andric SmallVector<MVT, 4> Types(S.begin(), S.end()); 1892cab237bSDimitry Andric array_pod_sort(Types.begin(), Types.end()); 1902cab237bSDimitry Andric 1912cab237bSDimitry Andric OS << '['; 1922cab237bSDimitry Andric for (unsigned i = 0, e = Types.size(); i != e; ++i) { 1932cab237bSDimitry Andric OS << ValueTypeByHwMode::getMVTName(Types[i]); 1942cab237bSDimitry Andric if (i != e-1) 1952cab237bSDimitry Andric OS << ' '; 1962cab237bSDimitry Andric } 1972cab237bSDimitry Andric OS << ']'; 1982cab237bSDimitry Andric } 1992cab237bSDimitry Andric 2002cab237bSDimitry Andric bool TypeSetByHwMode::operator==(const TypeSetByHwMode &VTS) const { 2012cab237bSDimitry Andric bool HaveDefault = hasDefault(); 2022cab237bSDimitry Andric if (HaveDefault != VTS.hasDefault()) 2032cab237bSDimitry Andric return false; 2042cab237bSDimitry Andric 2052cab237bSDimitry Andric if (isSimple()) { 2062cab237bSDimitry Andric if (VTS.isSimple()) 2072cab237bSDimitry Andric return *begin() == *VTS.begin(); 2082cab237bSDimitry Andric return false; 2092cab237bSDimitry Andric } 2102cab237bSDimitry Andric 2112cab237bSDimitry Andric SmallDenseSet<unsigned, 4> Modes; 2122cab237bSDimitry Andric for (auto &I : *this) 2132cab237bSDimitry Andric Modes.insert(I.first); 2142cab237bSDimitry Andric for (const auto &I : VTS) 2152cab237bSDimitry Andric Modes.insert(I.first); 2162cab237bSDimitry Andric 2172cab237bSDimitry Andric if (HaveDefault) { 2182cab237bSDimitry Andric // Both sets have default mode. 2192cab237bSDimitry Andric for (unsigned M : Modes) { 2202cab237bSDimitry Andric if (get(M) != VTS.get(M)) 2212cab237bSDimitry Andric return false; 2222cab237bSDimitry Andric } 2232cab237bSDimitry Andric } else { 2242cab237bSDimitry Andric // Neither set has default mode. 2252cab237bSDimitry Andric for (unsigned M : Modes) { 2262cab237bSDimitry Andric // If there is no default mode, an empty set is equivalent to not having 2272cab237bSDimitry Andric // the corresponding mode. 2282cab237bSDimitry Andric bool NoModeThis = !hasMode(M) || get(M).empty(); 2292cab237bSDimitry Andric bool NoModeVTS = !VTS.hasMode(M) || VTS.get(M).empty(); 2302cab237bSDimitry Andric if (NoModeThis != NoModeVTS) 2312cab237bSDimitry Andric return false; 2322cab237bSDimitry Andric if (!NoModeThis) 2332cab237bSDimitry Andric if (get(M) != VTS.get(M)) 2342cab237bSDimitry Andric return false; 2352cab237bSDimitry Andric } 2362cab237bSDimitry Andric } 2372cab237bSDimitry Andric 2382cab237bSDimitry Andric return true; 2392cab237bSDimitry Andric } 2402cab237bSDimitry Andric 2412cab237bSDimitry Andric namespace llvm { 2422cab237bSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const TypeSetByHwMode &T) { 2432cab237bSDimitry Andric T.writeToStream(OS); 2442cab237bSDimitry Andric return OS; 2452cab237bSDimitry Andric } 2462cab237bSDimitry Andric } 2472cab237bSDimitry Andric 2482cab237bSDimitry Andric LLVM_DUMP_METHOD 2492cab237bSDimitry Andric void TypeSetByHwMode::dump() const { 2502cab237bSDimitry Andric dbgs() << *this << '\n'; 2512cab237bSDimitry Andric } 2522cab237bSDimitry Andric 2532cab237bSDimitry Andric bool TypeSetByHwMode::intersect(SetType &Out, const SetType &In) { 2542cab237bSDimitry Andric bool OutP = Out.count(MVT::iPTR), InP = In.count(MVT::iPTR); 2552cab237bSDimitry Andric auto Int = [&In](MVT T) -> bool { return !In.count(T); }; 2562cab237bSDimitry Andric 2572cab237bSDimitry Andric if (OutP == InP) 2582cab237bSDimitry Andric return berase_if(Out, Int); 2592cab237bSDimitry Andric 2602cab237bSDimitry Andric // Compute the intersection of scalars separately to account for only 2612cab237bSDimitry Andric // one set containing iPTR. 2622cab237bSDimitry Andric // The itersection of iPTR with a set of integer scalar types that does not 2632cab237bSDimitry Andric // include iPTR will result in the most specific scalar type: 2642cab237bSDimitry Andric // - iPTR is more specific than any set with two elements or more 2652cab237bSDimitry Andric // - iPTR is less specific than any single integer scalar type. 2662cab237bSDimitry Andric // For example 2672cab237bSDimitry Andric // { iPTR } * { i32 } -> { i32 } 2682cab237bSDimitry Andric // { iPTR } * { i32 i64 } -> { iPTR } 2692cab237bSDimitry Andric // and 2702cab237bSDimitry Andric // { iPTR i32 } * { i32 } -> { i32 } 2712cab237bSDimitry Andric // { iPTR i32 } * { i32 i64 } -> { i32 i64 } 2722cab237bSDimitry Andric // { iPTR i32 } * { i32 i64 i128 } -> { iPTR i32 } 2732cab237bSDimitry Andric 2742cab237bSDimitry Andric // Compute the difference between the two sets in such a way that the 2752cab237bSDimitry Andric // iPTR is in the set that is being subtracted. This is to see if there 2762cab237bSDimitry Andric // are any extra scalars in the set without iPTR that are not in the 2772cab237bSDimitry Andric // set containing iPTR. Then the iPTR could be considered a "wildcard" 2782cab237bSDimitry Andric // matching these scalars. If there is only one such scalar, it would 2792cab237bSDimitry Andric // replace the iPTR, if there are more, the iPTR would be retained. 2802cab237bSDimitry Andric SetType Diff; 2812cab237bSDimitry Andric if (InP) { 2822cab237bSDimitry Andric Diff = Out; 2832cab237bSDimitry Andric berase_if(Diff, [&In](MVT T) { return In.count(T); }); 2842cab237bSDimitry Andric // Pre-remove these elements and rely only on InP/OutP to determine 2852cab237bSDimitry Andric // whether a change has been made. 2862cab237bSDimitry Andric berase_if(Out, [&Diff](MVT T) { return Diff.count(T); }); 2872cab237bSDimitry Andric } else { 2882cab237bSDimitry Andric Diff = In; 2892cab237bSDimitry Andric berase_if(Diff, [&Out](MVT T) { return Out.count(T); }); 2902cab237bSDimitry Andric Out.erase(MVT::iPTR); 2912cab237bSDimitry Andric } 2922cab237bSDimitry Andric 2932cab237bSDimitry Andric // The actual intersection. 2942cab237bSDimitry Andric bool Changed = berase_if(Out, Int); 2952cab237bSDimitry Andric unsigned NumD = Diff.size(); 2962cab237bSDimitry Andric if (NumD == 0) 2972cab237bSDimitry Andric return Changed; 2982cab237bSDimitry Andric 2992cab237bSDimitry Andric if (NumD == 1) { 3002cab237bSDimitry Andric Out.insert(*Diff.begin()); 3012cab237bSDimitry Andric // This is a change only if Out was the one with iPTR (which is now 3022cab237bSDimitry Andric // being replaced). 3032cab237bSDimitry Andric Changed |= OutP; 3042cab237bSDimitry Andric } else { 3052cab237bSDimitry Andric // Multiple elements from Out are now replaced with iPTR. 3062cab237bSDimitry Andric Out.insert(MVT::iPTR); 3072cab237bSDimitry Andric Changed |= !OutP; 3082cab237bSDimitry Andric } 3092cab237bSDimitry Andric return Changed; 3102cab237bSDimitry Andric } 3112cab237bSDimitry Andric 312da09e106SDimitry Andric bool TypeSetByHwMode::validate() const { 3132cab237bSDimitry Andric #ifndef NDEBUG 3142cab237bSDimitry Andric if (empty()) 315da09e106SDimitry Andric return true; 3162cab237bSDimitry Andric bool AllEmpty = true; 3172cab237bSDimitry Andric for (const auto &I : *this) 3182cab237bSDimitry Andric AllEmpty &= I.second.empty(); 319da09e106SDimitry Andric return !AllEmpty; 3202cab237bSDimitry Andric #endif 321da09e106SDimitry Andric return true; 3222cab237bSDimitry Andric } 3232cab237bSDimitry Andric 3242cab237bSDimitry Andric // --- TypeInfer 3252cab237bSDimitry Andric 3262cab237bSDimitry Andric bool TypeInfer::MergeInTypeInfo(TypeSetByHwMode &Out, 3272cab237bSDimitry Andric const TypeSetByHwMode &In) { 328da09e106SDimitry Andric ValidateOnExit _1(Out, *this); 3292cab237bSDimitry Andric In.validate(); 3302cab237bSDimitry Andric if (In.empty() || Out == In || TP.hasError()) 3312cab237bSDimitry Andric return false; 3322cab237bSDimitry Andric if (Out.empty()) { 3332cab237bSDimitry Andric Out = In; 3342cab237bSDimitry Andric return true; 3352cab237bSDimitry Andric } 3362cab237bSDimitry Andric 3372cab237bSDimitry Andric bool Changed = Out.constrain(In); 3382cab237bSDimitry Andric if (Changed && Out.empty()) 3392cab237bSDimitry Andric TP.error("Type contradiction"); 3402cab237bSDimitry Andric 3412cab237bSDimitry Andric return Changed; 3422cab237bSDimitry Andric } 3432cab237bSDimitry Andric 3442cab237bSDimitry Andric bool TypeInfer::forceArbitrary(TypeSetByHwMode &Out) { 345da09e106SDimitry Andric ValidateOnExit _1(Out, *this); 3462cab237bSDimitry Andric if (TP.hasError()) 3472cab237bSDimitry Andric return false; 3482cab237bSDimitry Andric assert(!Out.empty() && "cannot pick from an empty set"); 3492cab237bSDimitry Andric 3502cab237bSDimitry Andric bool Changed = false; 3512cab237bSDimitry Andric for (auto &I : Out) { 3522cab237bSDimitry Andric TypeSetByHwMode::SetType &S = I.second; 3532cab237bSDimitry Andric if (S.size() <= 1) 3542cab237bSDimitry Andric continue; 3552cab237bSDimitry Andric MVT T = *S.begin(); // Pick the first element. 3562cab237bSDimitry Andric S.clear(); 3572cab237bSDimitry Andric S.insert(T); 3582cab237bSDimitry Andric Changed = true; 3592cab237bSDimitry Andric } 3602cab237bSDimitry Andric return Changed; 3612cab237bSDimitry Andric } 3622cab237bSDimitry Andric 3632cab237bSDimitry Andric bool TypeInfer::EnforceInteger(TypeSetByHwMode &Out) { 364da09e106SDimitry Andric ValidateOnExit _1(Out, *this); 3652cab237bSDimitry Andric if (TP.hasError()) 3662cab237bSDimitry Andric return false; 3672cab237bSDimitry Andric if (!Out.empty()) 3682cab237bSDimitry Andric return Out.constrain(isIntegerOrPtr); 3692cab237bSDimitry Andric 3702cab237bSDimitry Andric return Out.assign_if(getLegalTypes(), isIntegerOrPtr); 3712cab237bSDimitry Andric } 3722cab237bSDimitry Andric 3732cab237bSDimitry Andric bool TypeInfer::EnforceFloatingPoint(TypeSetByHwMode &Out) { 374da09e106SDimitry Andric ValidateOnExit _1(Out, *this); 3752cab237bSDimitry Andric if (TP.hasError()) 3762cab237bSDimitry Andric return false; 3772cab237bSDimitry Andric if (!Out.empty()) 3782cab237bSDimitry Andric return Out.constrain(isFloatingPoint); 3792cab237bSDimitry Andric 3802cab237bSDimitry Andric return Out.assign_if(getLegalTypes(), isFloatingPoint); 3812cab237bSDimitry Andric } 3822cab237bSDimitry Andric 3832cab237bSDimitry Andric bool TypeInfer::EnforceScalar(TypeSetByHwMode &Out) { 384da09e106SDimitry Andric ValidateOnExit _1(Out, *this); 3852cab237bSDimitry Andric if (TP.hasError()) 3862cab237bSDimitry Andric return false; 3872cab237bSDimitry Andric if (!Out.empty()) 3882cab237bSDimitry Andric return Out.constrain(isScalar); 3892cab237bSDimitry Andric 3902cab237bSDimitry Andric return Out.assign_if(getLegalTypes(), isScalar); 3912cab237bSDimitry Andric } 3922cab237bSDimitry Andric 3932cab237bSDimitry Andric bool TypeInfer::EnforceVector(TypeSetByHwMode &Out) { 394da09e106SDimitry Andric ValidateOnExit _1(Out, *this); 3952cab237bSDimitry Andric if (TP.hasError()) 3962cab237bSDimitry Andric return false; 3972cab237bSDimitry Andric if (!Out.empty()) 3982cab237bSDimitry Andric return Out.constrain(isVector); 3992cab237bSDimitry Andric 4002cab237bSDimitry Andric return Out.assign_if(getLegalTypes(), isVector); 4012cab237bSDimitry Andric } 4022cab237bSDimitry Andric 4032cab237bSDimitry Andric bool TypeInfer::EnforceAny(TypeSetByHwMode &Out) { 404da09e106SDimitry Andric ValidateOnExit _1(Out, *this); 4052cab237bSDimitry Andric if (TP.hasError() || !Out.empty()) 4062cab237bSDimitry Andric return false; 4072cab237bSDimitry Andric 4082cab237bSDimitry Andric Out = getLegalTypes(); 4092cab237bSDimitry Andric return true; 4102cab237bSDimitry Andric } 4112cab237bSDimitry Andric 4122cab237bSDimitry Andric template <typename Iter, typename Pred, typename Less> 4132cab237bSDimitry Andric static Iter min_if(Iter B, Iter E, Pred P, Less L) { 4142cab237bSDimitry Andric if (B == E) 4152cab237bSDimitry Andric return E; 4162cab237bSDimitry Andric Iter Min = E; 4172cab237bSDimitry Andric for (Iter I = B; I != E; ++I) { 4182cab237bSDimitry Andric if (!P(*I)) 4192cab237bSDimitry Andric continue; 4202cab237bSDimitry Andric if (Min == E || L(*I, *Min)) 4212cab237bSDimitry Andric Min = I; 4222cab237bSDimitry Andric } 4232cab237bSDimitry Andric return Min; 4242cab237bSDimitry Andric } 4252cab237bSDimitry Andric 4262cab237bSDimitry Andric template <typename Iter, typename Pred, typename Less> 4272cab237bSDimitry Andric static Iter max_if(Iter B, Iter E, Pred P, Less L) { 4282cab237bSDimitry Andric if (B == E) 4292cab237bSDimitry Andric return E; 4302cab237bSDimitry Andric Iter Max = E; 4312cab237bSDimitry Andric for (Iter I = B; I != E; ++I) { 4322cab237bSDimitry Andric if (!P(*I)) 4332cab237bSDimitry Andric continue; 4342cab237bSDimitry Andric if (Max == E || L(*Max, *I)) 4352cab237bSDimitry Andric Max = I; 4362cab237bSDimitry Andric } 4372cab237bSDimitry Andric return Max; 4382cab237bSDimitry Andric } 4392cab237bSDimitry Andric 4402cab237bSDimitry Andric /// Make sure that for each type in Small, there exists a larger type in Big. 4412cab237bSDimitry Andric bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small, 4422cab237bSDimitry Andric TypeSetByHwMode &Big) { 443da09e106SDimitry Andric ValidateOnExit _1(Small, *this), _2(Big, *this); 4442cab237bSDimitry Andric if (TP.hasError()) 4452cab237bSDimitry Andric return false; 4462cab237bSDimitry Andric bool Changed = false; 4472cab237bSDimitry Andric 4482cab237bSDimitry Andric if (Small.empty()) 4492cab237bSDimitry Andric Changed |= EnforceAny(Small); 4502cab237bSDimitry Andric if (Big.empty()) 4512cab237bSDimitry Andric Changed |= EnforceAny(Big); 4522cab237bSDimitry Andric 4532cab237bSDimitry Andric assert(Small.hasDefault() && Big.hasDefault()); 4542cab237bSDimitry Andric 4552cab237bSDimitry Andric std::vector<unsigned> Modes = union_modes(Small, Big); 4562cab237bSDimitry Andric 4572cab237bSDimitry Andric // 1. Only allow integer or floating point types and make sure that 4582cab237bSDimitry Andric // both sides are both integer or both floating point. 4592cab237bSDimitry Andric // 2. Make sure that either both sides have vector types, or neither 4602cab237bSDimitry Andric // of them does. 4612cab237bSDimitry Andric for (unsigned M : Modes) { 4622cab237bSDimitry Andric TypeSetByHwMode::SetType &S = Small.get(M); 4632cab237bSDimitry Andric TypeSetByHwMode::SetType &B = Big.get(M); 4642cab237bSDimitry Andric 4652cab237bSDimitry Andric if (any_of(S, isIntegerOrPtr) && any_of(S, isIntegerOrPtr)) { 4662cab237bSDimitry Andric auto NotInt = [](MVT VT) { return !isIntegerOrPtr(VT); }; 4672cab237bSDimitry Andric Changed |= berase_if(S, NotInt) | 4682cab237bSDimitry Andric berase_if(B, NotInt); 4692cab237bSDimitry Andric } else if (any_of(S, isFloatingPoint) && any_of(B, isFloatingPoint)) { 4702cab237bSDimitry Andric auto NotFP = [](MVT VT) { return !isFloatingPoint(VT); }; 4712cab237bSDimitry Andric Changed |= berase_if(S, NotFP) | 4722cab237bSDimitry Andric berase_if(B, NotFP); 4732cab237bSDimitry Andric } else if (S.empty() || B.empty()) { 4742cab237bSDimitry Andric Changed = !S.empty() || !B.empty(); 4752cab237bSDimitry Andric S.clear(); 4762cab237bSDimitry Andric B.clear(); 4772cab237bSDimitry Andric } else { 4782cab237bSDimitry Andric TP.error("Incompatible types"); 4792cab237bSDimitry Andric return Changed; 4802cab237bSDimitry Andric } 4812cab237bSDimitry Andric 4822cab237bSDimitry Andric if (none_of(S, isVector) || none_of(B, isVector)) { 4832cab237bSDimitry Andric Changed |= berase_if(S, isVector) | 4842cab237bSDimitry Andric berase_if(B, isVector); 4852cab237bSDimitry Andric } 4862cab237bSDimitry Andric } 4872cab237bSDimitry Andric 4882cab237bSDimitry Andric auto LT = [](MVT A, MVT B) -> bool { 4892cab237bSDimitry Andric return A.getScalarSizeInBits() < B.getScalarSizeInBits() || 4902cab237bSDimitry Andric (A.getScalarSizeInBits() == B.getScalarSizeInBits() && 4912cab237bSDimitry Andric A.getSizeInBits() < B.getSizeInBits()); 4922cab237bSDimitry Andric }; 4932cab237bSDimitry Andric auto LE = [](MVT A, MVT B) -> bool { 4942cab237bSDimitry Andric // This function is used when removing elements: when a vector is compared 4952cab237bSDimitry Andric // to a non-vector, it should return false (to avoid removal). 4962cab237bSDimitry Andric if (A.isVector() != B.isVector()) 4972cab237bSDimitry Andric return false; 4982cab237bSDimitry Andric 4992cab237bSDimitry Andric // Note on the < comparison below: 5002cab237bSDimitry Andric // X86 has patterns like 5012cab237bSDimitry Andric // (set VR128X:$dst, (v16i8 (X86vtrunc (v4i32 VR128X:$src1)))), 5022cab237bSDimitry Andric // where the truncated vector is given a type v16i8, while the source 5032cab237bSDimitry Andric // vector has type v4i32. They both have the same size in bits. 5042cab237bSDimitry Andric // The minimal type in the result is obviously v16i8, and when we remove 5052cab237bSDimitry Andric // all types from the source that are smaller-or-equal than v8i16, the 5062cab237bSDimitry Andric // only source type would also be removed (since it's equal in size). 5072cab237bSDimitry Andric return A.getScalarSizeInBits() <= B.getScalarSizeInBits() || 5082cab237bSDimitry Andric A.getSizeInBits() < B.getSizeInBits(); 5092cab237bSDimitry Andric }; 5102cab237bSDimitry Andric 5112cab237bSDimitry Andric for (unsigned M : Modes) { 5122cab237bSDimitry Andric TypeSetByHwMode::SetType &S = Small.get(M); 5132cab237bSDimitry Andric TypeSetByHwMode::SetType &B = Big.get(M); 5142cab237bSDimitry Andric // MinS = min scalar in Small, remove all scalars from Big that are 5152cab237bSDimitry Andric // smaller-or-equal than MinS. 5162cab237bSDimitry Andric auto MinS = min_if(S.begin(), S.end(), isScalar, LT); 5172cab237bSDimitry Andric if (MinS != S.end()) 5182cab237bSDimitry Andric Changed |= berase_if(B, std::bind(LE, std::placeholders::_1, *MinS)); 5192cab237bSDimitry Andric 5202cab237bSDimitry Andric // MaxS = max scalar in Big, remove all scalars from Small that are 5212cab237bSDimitry Andric // larger than MaxS. 5222cab237bSDimitry Andric auto MaxS = max_if(B.begin(), B.end(), isScalar, LT); 5232cab237bSDimitry Andric if (MaxS != B.end()) 5242cab237bSDimitry Andric Changed |= berase_if(S, std::bind(LE, *MaxS, std::placeholders::_1)); 5252cab237bSDimitry Andric 5262cab237bSDimitry Andric // MinV = min vector in Small, remove all vectors from Big that are 5272cab237bSDimitry Andric // smaller-or-equal than MinV. 5282cab237bSDimitry Andric auto MinV = min_if(S.begin(), S.end(), isVector, LT); 5292cab237bSDimitry Andric if (MinV != S.end()) 5302cab237bSDimitry Andric Changed |= berase_if(B, std::bind(LE, std::placeholders::_1, *MinV)); 5312cab237bSDimitry Andric 5322cab237bSDimitry Andric // MaxV = max vector in Big, remove all vectors from Small that are 5332cab237bSDimitry Andric // larger than MaxV. 5342cab237bSDimitry Andric auto MaxV = max_if(B.begin(), B.end(), isVector, LT); 5352cab237bSDimitry Andric if (MaxV != B.end()) 5362cab237bSDimitry Andric Changed |= berase_if(S, std::bind(LE, *MaxV, std::placeholders::_1)); 5372cab237bSDimitry Andric } 5382cab237bSDimitry Andric 5392cab237bSDimitry Andric return Changed; 5402cab237bSDimitry Andric } 5412cab237bSDimitry Andric 5422cab237bSDimitry Andric /// 1. Ensure that for each type T in Vec, T is a vector type, and that 5432cab237bSDimitry Andric /// for each type U in Elem, U is a scalar type. 5442cab237bSDimitry Andric /// 2. Ensure that for each (scalar) type U in Elem, there exists a (vector) 5452cab237bSDimitry Andric /// type T in Vec, such that U is the element type of T. 5462cab237bSDimitry Andric bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec, 5472cab237bSDimitry Andric TypeSetByHwMode &Elem) { 548da09e106SDimitry Andric ValidateOnExit _1(Vec, *this), _2(Elem, *this); 5492cab237bSDimitry Andric if (TP.hasError()) 5502cab237bSDimitry Andric return false; 5512cab237bSDimitry Andric bool Changed = false; 5522cab237bSDimitry Andric 5532cab237bSDimitry Andric if (Vec.empty()) 5542cab237bSDimitry Andric Changed |= EnforceVector(Vec); 5552cab237bSDimitry Andric if (Elem.empty()) 5562cab237bSDimitry Andric Changed |= EnforceScalar(Elem); 5572cab237bSDimitry Andric 5582cab237bSDimitry Andric for (unsigned M : union_modes(Vec, Elem)) { 5592cab237bSDimitry Andric TypeSetByHwMode::SetType &V = Vec.get(M); 5602cab237bSDimitry Andric TypeSetByHwMode::SetType &E = Elem.get(M); 5612cab237bSDimitry Andric 5622cab237bSDimitry Andric Changed |= berase_if(V, isScalar); // Scalar = !vector 5632cab237bSDimitry Andric Changed |= berase_if(E, isVector); // Vector = !scalar 5642cab237bSDimitry Andric assert(!V.empty() && !E.empty()); 5652cab237bSDimitry Andric 5662cab237bSDimitry Andric SmallSet<MVT,4> VT, ST; 5672cab237bSDimitry Andric // Collect element types from the "vector" set. 5682cab237bSDimitry Andric for (MVT T : V) 5692cab237bSDimitry Andric VT.insert(T.getVectorElementType()); 5702cab237bSDimitry Andric // Collect scalar types from the "element" set. 5712cab237bSDimitry Andric for (MVT T : E) 5722cab237bSDimitry Andric ST.insert(T); 5732cab237bSDimitry Andric 5742cab237bSDimitry Andric // Remove from V all (vector) types whose element type is not in S. 5752cab237bSDimitry Andric Changed |= berase_if(V, [&ST](MVT T) -> bool { 5762cab237bSDimitry Andric return !ST.count(T.getVectorElementType()); 5772cab237bSDimitry Andric }); 5782cab237bSDimitry Andric // Remove from E all (scalar) types, for which there is no corresponding 5792cab237bSDimitry Andric // type in V. 5802cab237bSDimitry Andric Changed |= berase_if(E, [&VT](MVT T) -> bool { return !VT.count(T); }); 5812cab237bSDimitry Andric } 5822cab237bSDimitry Andric 5832cab237bSDimitry Andric return Changed; 5842cab237bSDimitry Andric } 5852cab237bSDimitry Andric 5862cab237bSDimitry Andric bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec, 5872cab237bSDimitry Andric const ValueTypeByHwMode &VVT) { 5882cab237bSDimitry Andric TypeSetByHwMode Tmp(VVT); 589da09e106SDimitry Andric ValidateOnExit _1(Vec, *this), _2(Tmp, *this); 5902cab237bSDimitry Andric return EnforceVectorEltTypeIs(Vec, Tmp); 5912cab237bSDimitry Andric } 5922cab237bSDimitry Andric 5932cab237bSDimitry Andric /// Ensure that for each type T in Sub, T is a vector type, and there 5942cab237bSDimitry Andric /// exists a type U in Vec such that U is a vector type with the same 5952cab237bSDimitry Andric /// element type as T and at least as many elements as T. 5962cab237bSDimitry Andric bool TypeInfer::EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec, 5972cab237bSDimitry Andric TypeSetByHwMode &Sub) { 598da09e106SDimitry Andric ValidateOnExit _1(Vec, *this), _2(Sub, *this); 5993861d79fSDimitry Andric if (TP.hasError()) 6003861d79fSDimitry Andric return false; 6013861d79fSDimitry Andric 6022cab237bSDimitry Andric /// Return true if B is a suB-vector of P, i.e. P is a suPer-vector of B. 6032cab237bSDimitry Andric auto IsSubVec = [](MVT B, MVT P) -> bool { 6042cab237bSDimitry Andric if (!B.isVector() || !P.isVector()) 6053861d79fSDimitry Andric return false; 6062cab237bSDimitry Andric // Logically a <4 x i32> is a valid subvector of <n x 4 x i32> 6072cab237bSDimitry Andric // but until there are obvious use-cases for this, keep the 6082cab237bSDimitry Andric // types separate. 6092cab237bSDimitry Andric if (B.isScalableVector() != P.isScalableVector()) 6102cab237bSDimitry Andric return false; 6112cab237bSDimitry Andric if (B.getVectorElementType() != P.getVectorElementType()) 6122cab237bSDimitry Andric return false; 6132cab237bSDimitry Andric return B.getVectorNumElements() < P.getVectorNumElements(); 6142cab237bSDimitry Andric }; 615f22ef01cSRoman Divacky 6162cab237bSDimitry Andric /// Return true if S has no element (vector type) that T is a sub-vector of, 6172cab237bSDimitry Andric /// i.e. has the same element type as T and more elements. 6182cab237bSDimitry Andric auto NoSubV = [&IsSubVec](const TypeSetByHwMode::SetType &S, MVT T) -> bool { 6192cab237bSDimitry Andric for (const auto &I : S) 6202cab237bSDimitry Andric if (IsSubVec(T, I)) 6212cab237bSDimitry Andric return false; 622f22ef01cSRoman Divacky return true; 6232cab237bSDimitry Andric }; 6242cab237bSDimitry Andric 6252cab237bSDimitry Andric /// Return true if S has no element (vector type) that T is a super-vector 6262cab237bSDimitry Andric /// of, i.e. has the same element type as T and fewer elements. 6272cab237bSDimitry Andric auto NoSupV = [&IsSubVec](const TypeSetByHwMode::SetType &S, MVT T) -> bool { 6282cab237bSDimitry Andric for (const auto &I : S) 6292cab237bSDimitry Andric if (IsSubVec(I, T)) 6302cab237bSDimitry Andric return false; 6312cab237bSDimitry Andric return true; 6322cab237bSDimitry Andric }; 6332cab237bSDimitry Andric 6342cab237bSDimitry Andric bool Changed = false; 6352cab237bSDimitry Andric 6362cab237bSDimitry Andric if (Vec.empty()) 6372cab237bSDimitry Andric Changed |= EnforceVector(Vec); 6382cab237bSDimitry Andric if (Sub.empty()) 6392cab237bSDimitry Andric Changed |= EnforceVector(Sub); 6402cab237bSDimitry Andric 6412cab237bSDimitry Andric for (unsigned M : union_modes(Vec, Sub)) { 6422cab237bSDimitry Andric TypeSetByHwMode::SetType &S = Sub.get(M); 6432cab237bSDimitry Andric TypeSetByHwMode::SetType &V = Vec.get(M); 6442cab237bSDimitry Andric 6452cab237bSDimitry Andric Changed |= berase_if(S, isScalar); 6462cab237bSDimitry Andric 6472cab237bSDimitry Andric // Erase all types from S that are not sub-vectors of a type in V. 6482cab237bSDimitry Andric Changed |= berase_if(S, std::bind(NoSubV, V, std::placeholders::_1)); 6492cab237bSDimitry Andric 6502cab237bSDimitry Andric // Erase all types from V that are not super-vectors of a type in S. 6512cab237bSDimitry Andric Changed |= berase_if(V, std::bind(NoSupV, S, std::placeholders::_1)); 652f22ef01cSRoman Divacky } 653f22ef01cSRoman Divacky 6542cab237bSDimitry Andric return Changed; 655f22ef01cSRoman Divacky } 656f22ef01cSRoman Divacky 6572cab237bSDimitry Andric /// 1. Ensure that V has a scalar type iff W has a scalar type. 6582cab237bSDimitry Andric /// 2. Ensure that for each vector type T in V, there exists a vector 6592cab237bSDimitry Andric /// type U in W, such that T and U have the same number of elements. 6602cab237bSDimitry Andric /// 3. Ensure that for each vector type U in W, there exists a vector 6612cab237bSDimitry Andric /// type T in V, such that T and U have the same number of elements 6622cab237bSDimitry Andric /// (reverse of 2). 6632cab237bSDimitry Andric bool TypeInfer::EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W) { 664da09e106SDimitry Andric ValidateOnExit _1(V, *this), _2(W, *this); 6652cab237bSDimitry Andric if (TP.hasError()) 666f22ef01cSRoman Divacky return false; 667f22ef01cSRoman Divacky 6682cab237bSDimitry Andric bool Changed = false; 6692cab237bSDimitry Andric if (V.empty()) 6702cab237bSDimitry Andric Changed |= EnforceAny(V); 6712cab237bSDimitry Andric if (W.empty()) 6722cab237bSDimitry Andric Changed |= EnforceAny(W); 6732cab237bSDimitry Andric 6742cab237bSDimitry Andric // An actual vector type cannot have 0 elements, so we can treat scalars 6752cab237bSDimitry Andric // as zero-length vectors. This way both vectors and scalars can be 6762cab237bSDimitry Andric // processed identically. 6772cab237bSDimitry Andric auto NoLength = [](const SmallSet<unsigned,2> &Lengths, MVT T) -> bool { 6782cab237bSDimitry Andric return !Lengths.count(T.isVector() ? T.getVectorNumElements() : 0); 6792cab237bSDimitry Andric }; 6802cab237bSDimitry Andric 6812cab237bSDimitry Andric for (unsigned M : union_modes(V, W)) { 6822cab237bSDimitry Andric TypeSetByHwMode::SetType &VS = V.get(M); 6832cab237bSDimitry Andric TypeSetByHwMode::SetType &WS = W.get(M); 6842cab237bSDimitry Andric 6852cab237bSDimitry Andric SmallSet<unsigned,2> VN, WN; 6862cab237bSDimitry Andric for (MVT T : VS) 6872cab237bSDimitry Andric VN.insert(T.isVector() ? T.getVectorNumElements() : 0); 6882cab237bSDimitry Andric for (MVT T : WS) 6892cab237bSDimitry Andric WN.insert(T.isVector() ? T.getVectorNumElements() : 0); 6902cab237bSDimitry Andric 6912cab237bSDimitry Andric Changed |= berase_if(VS, std::bind(NoLength, WN, std::placeholders::_1)); 6922cab237bSDimitry Andric Changed |= berase_if(WS, std::bind(NoLength, VN, std::placeholders::_1)); 6932cab237bSDimitry Andric } 6942cab237bSDimitry Andric return Changed; 695f22ef01cSRoman Divacky } 696f22ef01cSRoman Divacky 6972cab237bSDimitry Andric /// 1. Ensure that for each type T in A, there exists a type U in B, 6982cab237bSDimitry Andric /// such that T and U have equal size in bits. 6992cab237bSDimitry Andric /// 2. Ensure that for each type U in B, there exists a type T in A 7002cab237bSDimitry Andric /// such that T and U have equal size in bits (reverse of 1). 7012cab237bSDimitry Andric bool TypeInfer::EnforceSameSize(TypeSetByHwMode &A, TypeSetByHwMode &B) { 702da09e106SDimitry Andric ValidateOnExit _1(A, *this), _2(B, *this); 7032cab237bSDimitry Andric if (TP.hasError()) 7042cab237bSDimitry Andric return false; 7052cab237bSDimitry Andric bool Changed = false; 7062cab237bSDimitry Andric if (A.empty()) 7072cab237bSDimitry Andric Changed |= EnforceAny(A); 7082cab237bSDimitry Andric if (B.empty()) 7092cab237bSDimitry Andric Changed |= EnforceAny(B); 710f22ef01cSRoman Divacky 7112cab237bSDimitry Andric auto NoSize = [](const SmallSet<unsigned,2> &Sizes, MVT T) -> bool { 7122cab237bSDimitry Andric return !Sizes.count(T.getSizeInBits()); 7132cab237bSDimitry Andric }; 7142cab237bSDimitry Andric 7152cab237bSDimitry Andric for (unsigned M : union_modes(A, B)) { 7162cab237bSDimitry Andric TypeSetByHwMode::SetType &AS = A.get(M); 7172cab237bSDimitry Andric TypeSetByHwMode::SetType &BS = B.get(M); 7182cab237bSDimitry Andric SmallSet<unsigned,2> AN, BN; 7192cab237bSDimitry Andric 7202cab237bSDimitry Andric for (MVT T : AS) 7212cab237bSDimitry Andric AN.insert(T.getSizeInBits()); 7222cab237bSDimitry Andric for (MVT T : BS) 7232cab237bSDimitry Andric BN.insert(T.getSizeInBits()); 7242cab237bSDimitry Andric 7252cab237bSDimitry Andric Changed |= berase_if(AS, std::bind(NoSize, BN, std::placeholders::_1)); 7262cab237bSDimitry Andric Changed |= berase_if(BS, std::bind(NoSize, AN, std::placeholders::_1)); 7272cab237bSDimitry Andric } 7282cab237bSDimitry Andric 7292cab237bSDimitry Andric return Changed; 7302cab237bSDimitry Andric } 7312cab237bSDimitry Andric 7322cab237bSDimitry Andric void TypeInfer::expandOverloads(TypeSetByHwMode &VTS) { 733da09e106SDimitry Andric ValidateOnExit _1(VTS, *this); 7342cab237bSDimitry Andric TypeSetByHwMode Legal = getLegalTypes(); 7352cab237bSDimitry Andric bool HaveLegalDef = Legal.hasDefault(); 7362cab237bSDimitry Andric 7372cab237bSDimitry Andric for (auto &I : VTS) { 7382cab237bSDimitry Andric unsigned M = I.first; 7392cab237bSDimitry Andric if (!Legal.hasMode(M) && !HaveLegalDef) { 7402cab237bSDimitry Andric TP.error("Invalid mode " + Twine(M)); 7412cab237bSDimitry Andric return; 7422cab237bSDimitry Andric } 7432cab237bSDimitry Andric expandOverloads(I.second, Legal.get(M)); 7442cab237bSDimitry Andric } 7452cab237bSDimitry Andric } 7462cab237bSDimitry Andric 7472cab237bSDimitry Andric void TypeInfer::expandOverloads(TypeSetByHwMode::SetType &Out, 7482cab237bSDimitry Andric const TypeSetByHwMode::SetType &Legal) { 7492cab237bSDimitry Andric std::set<MVT> Ovs; 7502cab237bSDimitry Andric for (MVT T : Out) { 7512cab237bSDimitry Andric if (!T.isOverloaded()) 7522cab237bSDimitry Andric continue; 7532cab237bSDimitry Andric 7542cab237bSDimitry Andric Ovs.insert(T); 7552cab237bSDimitry Andric // MachineValueTypeSet allows iteration and erasing. 7562cab237bSDimitry Andric Out.erase(T); 7572cab237bSDimitry Andric } 7582cab237bSDimitry Andric 7592cab237bSDimitry Andric for (MVT Ov : Ovs) { 7602cab237bSDimitry Andric switch (Ov.SimpleTy) { 761f22ef01cSRoman Divacky case MVT::iPTRAny: 7622cab237bSDimitry Andric Out.insert(MVT::iPTR); 7632cab237bSDimitry Andric return; 7642cab237bSDimitry Andric case MVT::iAny: 7652cab237bSDimitry Andric for (MVT T : MVT::integer_valuetypes()) 7662cab237bSDimitry Andric if (Legal.count(T)) 7672cab237bSDimitry Andric Out.insert(T); 7682cab237bSDimitry Andric for (MVT T : MVT::integer_vector_valuetypes()) 7692cab237bSDimitry Andric if (Legal.count(T)) 7702cab237bSDimitry Andric Out.insert(T); 7712cab237bSDimitry Andric return; 7722cab237bSDimitry Andric case MVT::fAny: 7732cab237bSDimitry Andric for (MVT T : MVT::fp_valuetypes()) 7742cab237bSDimitry Andric if (Legal.count(T)) 7752cab237bSDimitry Andric Out.insert(T); 7762cab237bSDimitry Andric for (MVT T : MVT::fp_vector_valuetypes()) 7772cab237bSDimitry Andric if (Legal.count(T)) 7782cab237bSDimitry Andric Out.insert(T); 7792cab237bSDimitry Andric return; 7802cab237bSDimitry Andric case MVT::vAny: 7812cab237bSDimitry Andric for (MVT T : MVT::vector_valuetypes()) 7822cab237bSDimitry Andric if (Legal.count(T)) 7832cab237bSDimitry Andric Out.insert(T); 7842cab237bSDimitry Andric return; 7852cab237bSDimitry Andric case MVT::Any: 7862cab237bSDimitry Andric for (MVT T : MVT::all_valuetypes()) 7872cab237bSDimitry Andric if (Legal.count(T)) 7882cab237bSDimitry Andric Out.insert(T); 7892cab237bSDimitry Andric return; 7902cab237bSDimitry Andric default: 791f22ef01cSRoman Divacky break; 792f22ef01cSRoman Divacky } 7933861d79fSDimitry Andric } 7947d523365SDimitry Andric } 795f22ef01cSRoman Divacky 7962cab237bSDimitry Andric TypeSetByHwMode TypeInfer::getLegalTypes() { 7972cab237bSDimitry Andric if (!LegalTypesCached) { 7982cab237bSDimitry Andric // Stuff all types from all modes into the default mode. 7992cab237bSDimitry Andric const TypeSetByHwMode <S = TP.getDAGPatterns().getLegalTypes(); 8002cab237bSDimitry Andric for (const auto &I : LTS) 8012cab237bSDimitry Andric LegalCache.insert(I.second); 8022cab237bSDimitry Andric LegalTypesCached = true; 8033861d79fSDimitry Andric } 8042cab237bSDimitry Andric TypeSetByHwMode VTS; 8052cab237bSDimitry Andric VTS.getOrCreate(DefaultMode) = LegalCache; 8062cab237bSDimitry Andric return VTS; 8077d523365SDimitry Andric } 808f22ef01cSRoman Divacky 809da09e106SDimitry Andric #ifndef NDEBUG 810da09e106SDimitry Andric TypeInfer::ValidateOnExit::~ValidateOnExit() { 811da09e106SDimitry Andric if (!VTS.validate()) { 812da09e106SDimitry Andric dbgs() << "Type set is empty for each HW mode:\n" 813da09e106SDimitry Andric "possible type contradiction in the pattern below " 814da09e106SDimitry Andric "(use -print-records with llvm-tblgen to see all " 815da09e106SDimitry Andric "expanded records).\n"; 816da09e106SDimitry Andric Infer.TP.dump(); 817da09e106SDimitry Andric llvm_unreachable(nullptr); 818da09e106SDimitry Andric } 819da09e106SDimitry Andric } 820da09e106SDimitry Andric #endif 821da09e106SDimitry Andric 8223b0f4066SDimitry Andric //===----------------------------------------------------------------------===// 8233b0f4066SDimitry Andric // TreePredicateFn Implementation 8243b0f4066SDimitry Andric //===----------------------------------------------------------------------===// 8253b0f4066SDimitry Andric 8263b0f4066SDimitry Andric /// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag. 8273b0f4066SDimitry Andric TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) { 8282cab237bSDimitry Andric assert( 8292cab237bSDimitry Andric (!hasPredCode() || !hasImmCode()) && 8303b0f4066SDimitry Andric ".td file corrupt: can't have a node predicate *and* an imm predicate"); 8313b0f4066SDimitry Andric } 8323b0f4066SDimitry Andric 8332cab237bSDimitry Andric bool TreePredicateFn::hasPredCode() const { 8342cab237bSDimitry Andric return isLoad() || isStore() || isAtomic() || 8352cab237bSDimitry Andric !PatFragRec->getRecord()->getValueAsString("PredicateCode").empty(); 8362cab237bSDimitry Andric } 8372cab237bSDimitry Andric 8383b0f4066SDimitry Andric std::string TreePredicateFn::getPredCode() const { 8392cab237bSDimitry Andric std::string Code = ""; 8402cab237bSDimitry Andric 8412cab237bSDimitry Andric if (!isLoad() && !isStore() && !isAtomic()) { 8422cab237bSDimitry Andric Record *MemoryVT = getMemoryVT(); 8432cab237bSDimitry Andric 8442cab237bSDimitry Andric if (MemoryVT) 8452cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8462cab237bSDimitry Andric "MemoryVT requires IsLoad or IsStore"); 8472cab237bSDimitry Andric } 8482cab237bSDimitry Andric 8492cab237bSDimitry Andric if (!isLoad() && !isStore()) { 8502cab237bSDimitry Andric if (isUnindexed()) 8512cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8522cab237bSDimitry Andric "IsUnindexed requires IsLoad or IsStore"); 8532cab237bSDimitry Andric 8542cab237bSDimitry Andric Record *ScalarMemoryVT = getScalarMemoryVT(); 8552cab237bSDimitry Andric 8562cab237bSDimitry Andric if (ScalarMemoryVT) 8572cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8582cab237bSDimitry Andric "ScalarMemoryVT requires IsLoad or IsStore"); 8592cab237bSDimitry Andric } 8602cab237bSDimitry Andric 8612cab237bSDimitry Andric if (isLoad() + isStore() + isAtomic() > 1) 8622cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8632cab237bSDimitry Andric "IsLoad, IsStore, and IsAtomic are mutually exclusive"); 8642cab237bSDimitry Andric 8652cab237bSDimitry Andric if (isLoad()) { 8662cab237bSDimitry Andric if (!isUnindexed() && !isNonExtLoad() && !isAnyExtLoad() && 8672cab237bSDimitry Andric !isSignExtLoad() && !isZeroExtLoad() && getMemoryVT() == nullptr && 8682cab237bSDimitry Andric getScalarMemoryVT() == nullptr) 8692cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8702cab237bSDimitry Andric "IsLoad cannot be used by itself"); 8712cab237bSDimitry Andric } else { 8722cab237bSDimitry Andric if (isNonExtLoad()) 8732cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8742cab237bSDimitry Andric "IsNonExtLoad requires IsLoad"); 8752cab237bSDimitry Andric if (isAnyExtLoad()) 8762cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8772cab237bSDimitry Andric "IsAnyExtLoad requires IsLoad"); 8782cab237bSDimitry Andric if (isSignExtLoad()) 8792cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8802cab237bSDimitry Andric "IsSignExtLoad requires IsLoad"); 8812cab237bSDimitry Andric if (isZeroExtLoad()) 8822cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8832cab237bSDimitry Andric "IsZeroExtLoad requires IsLoad"); 8842cab237bSDimitry Andric } 8852cab237bSDimitry Andric 8862cab237bSDimitry Andric if (isStore()) { 8872cab237bSDimitry Andric if (!isUnindexed() && !isTruncStore() && !isNonTruncStore() && 8882cab237bSDimitry Andric getMemoryVT() == nullptr && getScalarMemoryVT() == nullptr) 8892cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8902cab237bSDimitry Andric "IsStore cannot be used by itself"); 8912cab237bSDimitry Andric } else { 8922cab237bSDimitry Andric if (isNonTruncStore()) 8932cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8942cab237bSDimitry Andric "IsNonTruncStore requires IsStore"); 8952cab237bSDimitry Andric if (isTruncStore()) 8962cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 8972cab237bSDimitry Andric "IsTruncStore requires IsStore"); 8982cab237bSDimitry Andric } 8992cab237bSDimitry Andric 9002cab237bSDimitry Andric if (isAtomic()) { 9012cab237bSDimitry Andric if (getMemoryVT() == nullptr && !isAtomicOrderingMonotonic() && 9022cab237bSDimitry Andric !isAtomicOrderingAcquire() && !isAtomicOrderingRelease() && 9032cab237bSDimitry Andric !isAtomicOrderingAcquireRelease() && 9042cab237bSDimitry Andric !isAtomicOrderingSequentiallyConsistent() && 9052cab237bSDimitry Andric !isAtomicOrderingAcquireOrStronger() && 9062cab237bSDimitry Andric !isAtomicOrderingReleaseOrStronger() && 9072cab237bSDimitry Andric !isAtomicOrderingWeakerThanAcquire() && 9082cab237bSDimitry Andric !isAtomicOrderingWeakerThanRelease()) 9092cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9102cab237bSDimitry Andric "IsAtomic cannot be used by itself"); 9112cab237bSDimitry Andric } else { 9122cab237bSDimitry Andric if (isAtomicOrderingMonotonic()) 9132cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9142cab237bSDimitry Andric "IsAtomicOrderingMonotonic requires IsAtomic"); 9152cab237bSDimitry Andric if (isAtomicOrderingAcquire()) 9162cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9172cab237bSDimitry Andric "IsAtomicOrderingAcquire requires IsAtomic"); 9182cab237bSDimitry Andric if (isAtomicOrderingRelease()) 9192cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9202cab237bSDimitry Andric "IsAtomicOrderingRelease requires IsAtomic"); 9212cab237bSDimitry Andric if (isAtomicOrderingAcquireRelease()) 9222cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9232cab237bSDimitry Andric "IsAtomicOrderingAcquireRelease requires IsAtomic"); 9242cab237bSDimitry Andric if (isAtomicOrderingSequentiallyConsistent()) 9252cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9262cab237bSDimitry Andric "IsAtomicOrderingSequentiallyConsistent requires IsAtomic"); 9272cab237bSDimitry Andric if (isAtomicOrderingAcquireOrStronger()) 9282cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9292cab237bSDimitry Andric "IsAtomicOrderingAcquireOrStronger requires IsAtomic"); 9302cab237bSDimitry Andric if (isAtomicOrderingReleaseOrStronger()) 9312cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9322cab237bSDimitry Andric "IsAtomicOrderingReleaseOrStronger requires IsAtomic"); 9332cab237bSDimitry Andric if (isAtomicOrderingWeakerThanAcquire()) 9342cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9352cab237bSDimitry Andric "IsAtomicOrderingWeakerThanAcquire requires IsAtomic"); 9362cab237bSDimitry Andric } 9372cab237bSDimitry Andric 9382cab237bSDimitry Andric if (isLoad() || isStore() || isAtomic()) { 9392cab237bSDimitry Andric StringRef SDNodeName = 9402cab237bSDimitry Andric isLoad() ? "LoadSDNode" : isStore() ? "StoreSDNode" : "AtomicSDNode"; 9412cab237bSDimitry Andric 9422cab237bSDimitry Andric Record *MemoryVT = getMemoryVT(); 9432cab237bSDimitry Andric 9442cab237bSDimitry Andric if (MemoryVT) 9452cab237bSDimitry Andric Code += ("if (cast<" + SDNodeName + ">(N)->getMemoryVT() != MVT::" + 9462cab237bSDimitry Andric MemoryVT->getName() + ") return false;\n") 9472cab237bSDimitry Andric .str(); 9482cab237bSDimitry Andric } 9492cab237bSDimitry Andric 9502cab237bSDimitry Andric if (isAtomic() && isAtomicOrderingMonotonic()) 9512cab237bSDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getOrdering() != " 9522cab237bSDimitry Andric "AtomicOrdering::Monotonic) return false;\n"; 9532cab237bSDimitry Andric if (isAtomic() && isAtomicOrderingAcquire()) 9542cab237bSDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getOrdering() != " 9552cab237bSDimitry Andric "AtomicOrdering::Acquire) return false;\n"; 9562cab237bSDimitry Andric if (isAtomic() && isAtomicOrderingRelease()) 9572cab237bSDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getOrdering() != " 9582cab237bSDimitry Andric "AtomicOrdering::Release) return false;\n"; 9592cab237bSDimitry Andric if (isAtomic() && isAtomicOrderingAcquireRelease()) 9602cab237bSDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getOrdering() != " 9612cab237bSDimitry Andric "AtomicOrdering::AcquireRelease) return false;\n"; 9622cab237bSDimitry Andric if (isAtomic() && isAtomicOrderingSequentiallyConsistent()) 9632cab237bSDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getOrdering() != " 9642cab237bSDimitry Andric "AtomicOrdering::SequentiallyConsistent) return false;\n"; 9652cab237bSDimitry Andric 9662cab237bSDimitry Andric if (isAtomic() && isAtomicOrderingAcquireOrStronger()) 9672cab237bSDimitry Andric Code += "if (!isAcquireOrStronger(cast<AtomicSDNode>(N)->getOrdering())) " 9682cab237bSDimitry Andric "return false;\n"; 9692cab237bSDimitry Andric if (isAtomic() && isAtomicOrderingWeakerThanAcquire()) 9702cab237bSDimitry Andric Code += "if (isAcquireOrStronger(cast<AtomicSDNode>(N)->getOrdering())) " 9712cab237bSDimitry Andric "return false;\n"; 9722cab237bSDimitry Andric 9732cab237bSDimitry Andric if (isAtomic() && isAtomicOrderingReleaseOrStronger()) 9742cab237bSDimitry Andric Code += "if (!isReleaseOrStronger(cast<AtomicSDNode>(N)->getOrdering())) " 9752cab237bSDimitry Andric "return false;\n"; 9762cab237bSDimitry Andric if (isAtomic() && isAtomicOrderingWeakerThanRelease()) 9772cab237bSDimitry Andric Code += "if (isReleaseOrStronger(cast<AtomicSDNode>(N)->getOrdering())) " 9782cab237bSDimitry Andric "return false;\n"; 9792cab237bSDimitry Andric 9802cab237bSDimitry Andric if (isLoad() || isStore()) { 9812cab237bSDimitry Andric StringRef SDNodeName = isLoad() ? "LoadSDNode" : "StoreSDNode"; 9822cab237bSDimitry Andric 9832cab237bSDimitry Andric if (isUnindexed()) 9842cab237bSDimitry Andric Code += ("if (cast<" + SDNodeName + 9852cab237bSDimitry Andric ">(N)->getAddressingMode() != ISD::UNINDEXED) " 9862cab237bSDimitry Andric "return false;\n") 9872cab237bSDimitry Andric .str(); 9882cab237bSDimitry Andric 9892cab237bSDimitry Andric if (isLoad()) { 9902cab237bSDimitry Andric if ((isNonExtLoad() + isAnyExtLoad() + isSignExtLoad() + 9912cab237bSDimitry Andric isZeroExtLoad()) > 1) 9922cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9932cab237bSDimitry Andric "IsNonExtLoad, IsAnyExtLoad, IsSignExtLoad, and " 9942cab237bSDimitry Andric "IsZeroExtLoad are mutually exclusive"); 9952cab237bSDimitry Andric if (isNonExtLoad()) 9962cab237bSDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != " 9972cab237bSDimitry Andric "ISD::NON_EXTLOAD) return false;\n"; 9982cab237bSDimitry Andric if (isAnyExtLoad()) 9992cab237bSDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::EXTLOAD) " 10002cab237bSDimitry Andric "return false;\n"; 10012cab237bSDimitry Andric if (isSignExtLoad()) 10022cab237bSDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::SEXTLOAD) " 10032cab237bSDimitry Andric "return false;\n"; 10042cab237bSDimitry Andric if (isZeroExtLoad()) 10052cab237bSDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::ZEXTLOAD) " 10062cab237bSDimitry Andric "return false;\n"; 10072cab237bSDimitry Andric } else { 10082cab237bSDimitry Andric if ((isNonTruncStore() + isTruncStore()) > 1) 10092cab237bSDimitry Andric PrintFatalError( 10102cab237bSDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 10112cab237bSDimitry Andric "IsNonTruncStore, and IsTruncStore are mutually exclusive"); 10122cab237bSDimitry Andric if (isNonTruncStore()) 10132cab237bSDimitry Andric Code += 10142cab237bSDimitry Andric " if (cast<StoreSDNode>(N)->isTruncatingStore()) return false;\n"; 10152cab237bSDimitry Andric if (isTruncStore()) 10162cab237bSDimitry Andric Code += 10172cab237bSDimitry Andric " if (!cast<StoreSDNode>(N)->isTruncatingStore()) return false;\n"; 10182cab237bSDimitry Andric } 10192cab237bSDimitry Andric 10202cab237bSDimitry Andric Record *ScalarMemoryVT = getScalarMemoryVT(); 10212cab237bSDimitry Andric 10222cab237bSDimitry Andric if (ScalarMemoryVT) 10232cab237bSDimitry Andric Code += ("if (cast<" + SDNodeName + 10242cab237bSDimitry Andric ">(N)->getMemoryVT().getScalarType() != MVT::" + 10252cab237bSDimitry Andric ScalarMemoryVT->getName() + ") return false;\n") 10262cab237bSDimitry Andric .str(); 10272cab237bSDimitry Andric } 10282cab237bSDimitry Andric 10292cab237bSDimitry Andric std::string PredicateCode = PatFragRec->getRecord()->getValueAsString("PredicateCode"); 10302cab237bSDimitry Andric 10312cab237bSDimitry Andric Code += PredicateCode; 10322cab237bSDimitry Andric 10332cab237bSDimitry Andric if (PredicateCode.empty() && !Code.empty()) 10342cab237bSDimitry Andric Code += "return true;\n"; 10352cab237bSDimitry Andric 10362cab237bSDimitry Andric return Code; 10372cab237bSDimitry Andric } 10382cab237bSDimitry Andric 10392cab237bSDimitry Andric bool TreePredicateFn::hasImmCode() const { 10402cab237bSDimitry Andric return !PatFragRec->getRecord()->getValueAsString("ImmediateCode").empty(); 10413b0f4066SDimitry Andric } 10423b0f4066SDimitry Andric 10433b0f4066SDimitry Andric std::string TreePredicateFn::getImmCode() const { 1044dff0c46cSDimitry Andric return PatFragRec->getRecord()->getValueAsString("ImmediateCode"); 10453b0f4066SDimitry Andric } 10463b0f4066SDimitry Andric 10472cab237bSDimitry Andric bool TreePredicateFn::immCodeUsesAPInt() const { 10482cab237bSDimitry Andric return getOrigPatFragRecord()->getRecord()->getValueAsBit("IsAPInt"); 10492cab237bSDimitry Andric } 10502cab237bSDimitry Andric 10512cab237bSDimitry Andric bool TreePredicateFn::immCodeUsesAPFloat() const { 10522cab237bSDimitry Andric bool Unset; 10532cab237bSDimitry Andric // The return value will be false when IsAPFloat is unset. 10542cab237bSDimitry Andric return getOrigPatFragRecord()->getRecord()->getValueAsBitOrUnset("IsAPFloat", 10552cab237bSDimitry Andric Unset); 10562cab237bSDimitry Andric } 10572cab237bSDimitry Andric 10582cab237bSDimitry Andric bool TreePredicateFn::isPredefinedPredicateEqualTo(StringRef Field, 10592cab237bSDimitry Andric bool Value) const { 10602cab237bSDimitry Andric bool Unset; 10612cab237bSDimitry Andric bool Result = 10622cab237bSDimitry Andric getOrigPatFragRecord()->getRecord()->getValueAsBitOrUnset(Field, Unset); 10632cab237bSDimitry Andric if (Unset) 10642cab237bSDimitry Andric return false; 10652cab237bSDimitry Andric return Result == Value; 10662cab237bSDimitry Andric } 10672cab237bSDimitry Andric bool TreePredicateFn::isLoad() const { 10682cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsLoad", true); 10692cab237bSDimitry Andric } 10702cab237bSDimitry Andric bool TreePredicateFn::isStore() const { 10712cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsStore", true); 10722cab237bSDimitry Andric } 10732cab237bSDimitry Andric bool TreePredicateFn::isAtomic() const { 10742cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAtomic", true); 10752cab237bSDimitry Andric } 10762cab237bSDimitry Andric bool TreePredicateFn::isUnindexed() const { 10772cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsUnindexed", true); 10782cab237bSDimitry Andric } 10792cab237bSDimitry Andric bool TreePredicateFn::isNonExtLoad() const { 10802cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsNonExtLoad", true); 10812cab237bSDimitry Andric } 10822cab237bSDimitry Andric bool TreePredicateFn::isAnyExtLoad() const { 10832cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAnyExtLoad", true); 10842cab237bSDimitry Andric } 10852cab237bSDimitry Andric bool TreePredicateFn::isSignExtLoad() const { 10862cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsSignExtLoad", true); 10872cab237bSDimitry Andric } 10882cab237bSDimitry Andric bool TreePredicateFn::isZeroExtLoad() const { 10892cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsZeroExtLoad", true); 10902cab237bSDimitry Andric } 10912cab237bSDimitry Andric bool TreePredicateFn::isNonTruncStore() const { 10922cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsTruncStore", false); 10932cab237bSDimitry Andric } 10942cab237bSDimitry Andric bool TreePredicateFn::isTruncStore() const { 10952cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsTruncStore", true); 10962cab237bSDimitry Andric } 10972cab237bSDimitry Andric bool TreePredicateFn::isAtomicOrderingMonotonic() const { 10982cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingMonotonic", true); 10992cab237bSDimitry Andric } 11002cab237bSDimitry Andric bool TreePredicateFn::isAtomicOrderingAcquire() const { 11012cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquire", true); 11022cab237bSDimitry Andric } 11032cab237bSDimitry Andric bool TreePredicateFn::isAtomicOrderingRelease() const { 11042cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingRelease", true); 11052cab237bSDimitry Andric } 11062cab237bSDimitry Andric bool TreePredicateFn::isAtomicOrderingAcquireRelease() const { 11072cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireRelease", true); 11082cab237bSDimitry Andric } 11092cab237bSDimitry Andric bool TreePredicateFn::isAtomicOrderingSequentiallyConsistent() const { 11102cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingSequentiallyConsistent", 11112cab237bSDimitry Andric true); 11122cab237bSDimitry Andric } 11132cab237bSDimitry Andric bool TreePredicateFn::isAtomicOrderingAcquireOrStronger() const { 11142cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireOrStronger", true); 11152cab237bSDimitry Andric } 11162cab237bSDimitry Andric bool TreePredicateFn::isAtomicOrderingWeakerThanAcquire() const { 11172cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireOrStronger", false); 11182cab237bSDimitry Andric } 11192cab237bSDimitry Andric bool TreePredicateFn::isAtomicOrderingReleaseOrStronger() const { 11202cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingReleaseOrStronger", true); 11212cab237bSDimitry Andric } 11222cab237bSDimitry Andric bool TreePredicateFn::isAtomicOrderingWeakerThanRelease() const { 11232cab237bSDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingReleaseOrStronger", false); 11242cab237bSDimitry Andric } 11252cab237bSDimitry Andric Record *TreePredicateFn::getMemoryVT() const { 11262cab237bSDimitry Andric Record *R = getOrigPatFragRecord()->getRecord(); 11272cab237bSDimitry Andric if (R->isValueUnset("MemoryVT")) 11282cab237bSDimitry Andric return nullptr; 11292cab237bSDimitry Andric return R->getValueAsDef("MemoryVT"); 11302cab237bSDimitry Andric } 11312cab237bSDimitry Andric Record *TreePredicateFn::getScalarMemoryVT() const { 11322cab237bSDimitry Andric Record *R = getOrigPatFragRecord()->getRecord(); 11332cab237bSDimitry Andric if (R->isValueUnset("ScalarMemoryVT")) 11342cab237bSDimitry Andric return nullptr; 11352cab237bSDimitry Andric return R->getValueAsDef("ScalarMemoryVT"); 11362cab237bSDimitry Andric } 11372cab237bSDimitry Andric 11382cab237bSDimitry Andric StringRef TreePredicateFn::getImmType() const { 11392cab237bSDimitry Andric if (immCodeUsesAPInt()) 11402cab237bSDimitry Andric return "const APInt &"; 11412cab237bSDimitry Andric if (immCodeUsesAPFloat()) 11422cab237bSDimitry Andric return "const APFloat &"; 11432cab237bSDimitry Andric return "int64_t"; 11442cab237bSDimitry Andric } 11452cab237bSDimitry Andric 11462cab237bSDimitry Andric StringRef TreePredicateFn::getImmTypeIdentifier() const { 11472cab237bSDimitry Andric if (immCodeUsesAPInt()) 11482cab237bSDimitry Andric return "APInt"; 11492cab237bSDimitry Andric else if (immCodeUsesAPFloat()) 11502cab237bSDimitry Andric return "APFloat"; 11512cab237bSDimitry Andric return "I64"; 11522cab237bSDimitry Andric } 11533b0f4066SDimitry Andric 11543b0f4066SDimitry Andric /// isAlwaysTrue - Return true if this is a noop predicate. 11553b0f4066SDimitry Andric bool TreePredicateFn::isAlwaysTrue() const { 11562cab237bSDimitry Andric return !hasPredCode() && !hasImmCode(); 11573b0f4066SDimitry Andric } 11583b0f4066SDimitry Andric 11593b0f4066SDimitry Andric /// Return the name to use in the generated code to reference this, this is 11603b0f4066SDimitry Andric /// "Predicate_foo" if from a pattern fragment "foo". 11613b0f4066SDimitry Andric std::string TreePredicateFn::getFnName() const { 1162d88c1a5aSDimitry Andric return "Predicate_" + PatFragRec->getRecord()->getName().str(); 11633b0f4066SDimitry Andric } 11643b0f4066SDimitry Andric 11653b0f4066SDimitry Andric /// getCodeToRunOnSDNode - Return the code for the function body that 11663b0f4066SDimitry Andric /// evaluates this predicate. The argument is expected to be in "Node", 11673b0f4066SDimitry Andric /// not N. This handles casting and conversion to a concrete node type as 11683b0f4066SDimitry Andric /// appropriate. 11693b0f4066SDimitry Andric std::string TreePredicateFn::getCodeToRunOnSDNode() const { 11703b0f4066SDimitry Andric // Handle immediate predicates first. 11713b0f4066SDimitry Andric std::string ImmCode = getImmCode(); 11723b0f4066SDimitry Andric if (!ImmCode.empty()) { 11732cab237bSDimitry Andric if (isLoad()) 11742cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 11752cab237bSDimitry Andric "IsLoad cannot be used with ImmLeaf or its subclasses"); 11762cab237bSDimitry Andric if (isStore()) 11772cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 11782cab237bSDimitry Andric "IsStore cannot be used with ImmLeaf or its subclasses"); 11792cab237bSDimitry Andric if (isUnindexed()) 11802cab237bSDimitry Andric PrintFatalError( 11812cab237bSDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 11822cab237bSDimitry Andric "IsUnindexed cannot be used with ImmLeaf or its subclasses"); 11832cab237bSDimitry Andric if (isNonExtLoad()) 11842cab237bSDimitry Andric PrintFatalError( 11852cab237bSDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 11862cab237bSDimitry Andric "IsNonExtLoad cannot be used with ImmLeaf or its subclasses"); 11872cab237bSDimitry Andric if (isAnyExtLoad()) 11882cab237bSDimitry Andric PrintFatalError( 11892cab237bSDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 11902cab237bSDimitry Andric "IsAnyExtLoad cannot be used with ImmLeaf or its subclasses"); 11912cab237bSDimitry Andric if (isSignExtLoad()) 11922cab237bSDimitry Andric PrintFatalError( 11932cab237bSDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 11942cab237bSDimitry Andric "IsSignExtLoad cannot be used with ImmLeaf or its subclasses"); 11952cab237bSDimitry Andric if (isZeroExtLoad()) 11962cab237bSDimitry Andric PrintFatalError( 11972cab237bSDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 11982cab237bSDimitry Andric "IsZeroExtLoad cannot be used with ImmLeaf or its subclasses"); 11992cab237bSDimitry Andric if (isNonTruncStore()) 12002cab237bSDimitry Andric PrintFatalError( 12012cab237bSDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 12022cab237bSDimitry Andric "IsNonTruncStore cannot be used with ImmLeaf or its subclasses"); 12032cab237bSDimitry Andric if (isTruncStore()) 12042cab237bSDimitry Andric PrintFatalError( 12052cab237bSDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 12062cab237bSDimitry Andric "IsTruncStore cannot be used with ImmLeaf or its subclasses"); 12072cab237bSDimitry Andric if (getMemoryVT()) 12082cab237bSDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 12092cab237bSDimitry Andric "MemoryVT cannot be used with ImmLeaf or its subclasses"); 12102cab237bSDimitry Andric if (getScalarMemoryVT()) 12112cab237bSDimitry Andric PrintFatalError( 12122cab237bSDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 12132cab237bSDimitry Andric "ScalarMemoryVT cannot be used with ImmLeaf or its subclasses"); 12142cab237bSDimitry Andric 12152cab237bSDimitry Andric std::string Result = (" " + getImmType() + " Imm = ").str(); 12162cab237bSDimitry Andric if (immCodeUsesAPFloat()) 12172cab237bSDimitry Andric Result += "cast<ConstantFPSDNode>(Node)->getValueAPF();\n"; 12182cab237bSDimitry Andric else if (immCodeUsesAPInt()) 12192cab237bSDimitry Andric Result += "cast<ConstantSDNode>(Node)->getAPIntValue();\n"; 12202cab237bSDimitry Andric else 12212cab237bSDimitry Andric Result += "cast<ConstantSDNode>(Node)->getSExtValue();\n"; 12223b0f4066SDimitry Andric return Result + ImmCode; 12233b0f4066SDimitry Andric } 12243b0f4066SDimitry Andric 12253b0f4066SDimitry Andric // Handle arbitrary node predicates. 12262cab237bSDimitry Andric assert(hasPredCode() && "Don't have any predicate code!"); 12272cab237bSDimitry Andric StringRef ClassName; 12283b0f4066SDimitry Andric if (PatFragRec->getOnlyTree()->isLeaf()) 12293b0f4066SDimitry Andric ClassName = "SDNode"; 12303b0f4066SDimitry Andric else { 12313b0f4066SDimitry Andric Record *Op = PatFragRec->getOnlyTree()->getOperator(); 12323b0f4066SDimitry Andric ClassName = PatFragRec->getDAGPatterns().getSDNodeInfo(Op).getSDClassName(); 12333b0f4066SDimitry Andric } 12343b0f4066SDimitry Andric std::string Result; 12353b0f4066SDimitry Andric if (ClassName == "SDNode") 12363b0f4066SDimitry Andric Result = " SDNode *N = Node;\n"; 12373b0f4066SDimitry Andric else 12382cab237bSDimitry Andric Result = " auto *N = cast<" + ClassName.str() + ">(Node);\n"; 12393b0f4066SDimitry Andric 12403b0f4066SDimitry Andric return Result + getPredCode(); 1241f22ef01cSRoman Divacky } 1242f22ef01cSRoman Divacky 1243f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 1244f22ef01cSRoman Divacky // PatternToMatch implementation 1245f22ef01cSRoman Divacky // 1246f22ef01cSRoman Divacky 1247f22ef01cSRoman Divacky /// getPatternSize - Return the 'size' of this pattern. We want to match large 1248f22ef01cSRoman Divacky /// patterns before small ones. This is used to determine the size of a 1249f22ef01cSRoman Divacky /// pattern. 1250f22ef01cSRoman Divacky static unsigned getPatternSize(const TreePatternNode *P, 1251f22ef01cSRoman Divacky const CodeGenDAGPatterns &CGP) { 1252f22ef01cSRoman Divacky unsigned Size = 3; // The node itself. 1253f22ef01cSRoman Divacky // If the root node is a ConstantSDNode, increases its size. 1254f22ef01cSRoman Divacky // e.g. (set R32:$dst, 0). 12553861d79fSDimitry Andric if (P->isLeaf() && isa<IntInit>(P->getLeafValue())) 1256f22ef01cSRoman Divacky Size += 2; 1257f22ef01cSRoman Divacky 12582cab237bSDimitry Andric if (const ComplexPattern *AM = P->getComplexPatternInfo(CGP)) { 1259d88c1a5aSDimitry Andric Size += AM->getComplexity(); 126091bc56edSDimitry Andric // We don't want to count any children twice, so return early. 126191bc56edSDimitry Andric return Size; 126291bc56edSDimitry Andric } 126391bc56edSDimitry Andric 1264f22ef01cSRoman Divacky // If this node has some predicate function that must match, it adds to the 1265f22ef01cSRoman Divacky // complexity of this node. 1266f22ef01cSRoman Divacky if (!P->getPredicateFns().empty()) 1267f22ef01cSRoman Divacky ++Size; 1268f22ef01cSRoman Divacky 1269f22ef01cSRoman Divacky // Count children in the count if they are also nodes. 1270f22ef01cSRoman Divacky for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) { 12712cab237bSDimitry Andric const TreePatternNode *Child = P->getChild(i); 12722cab237bSDimitry Andric if (!Child->isLeaf() && Child->getNumTypes()) { 12732cab237bSDimitry Andric const TypeSetByHwMode &T0 = Child->getType(0); 12742cab237bSDimitry Andric // At this point, all variable type sets should be simple, i.e. only 12752cab237bSDimitry Andric // have a default mode. 12762cab237bSDimitry Andric if (T0.getMachineValueType() != MVT::Other) { 1277f22ef01cSRoman Divacky Size += getPatternSize(Child, CGP); 12782cab237bSDimitry Andric continue; 12792cab237bSDimitry Andric } 12802cab237bSDimitry Andric } 12812cab237bSDimitry Andric if (Child->isLeaf()) { 12823861d79fSDimitry Andric if (isa<IntInit>(Child->getLeafValue())) 1283f22ef01cSRoman Divacky Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). 1284f22ef01cSRoman Divacky else if (Child->getComplexPatternInfo(CGP)) 1285f22ef01cSRoman Divacky Size += getPatternSize(Child, CGP); 1286f22ef01cSRoman Divacky else if (!Child->getPredicateFns().empty()) 1287f22ef01cSRoman Divacky ++Size; 1288f22ef01cSRoman Divacky } 1289f22ef01cSRoman Divacky } 1290f22ef01cSRoman Divacky 1291f22ef01cSRoman Divacky return Size; 1292f22ef01cSRoman Divacky } 1293f22ef01cSRoman Divacky 1294f22ef01cSRoman Divacky /// Compute the complexity metric for the input pattern. This roughly 1295f22ef01cSRoman Divacky /// corresponds to the number of nodes that are covered. 129639d628a0SDimitry Andric int PatternToMatch:: 1297f22ef01cSRoman Divacky getPatternComplexity(const CodeGenDAGPatterns &CGP) const { 1298f22ef01cSRoman Divacky return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity(); 1299f22ef01cSRoman Divacky } 1300f22ef01cSRoman Divacky 1301f22ef01cSRoman Divacky /// getPredicateCheck - Return a single string containing all of this 1302f22ef01cSRoman Divacky /// pattern's predicates concatenated with "&&" operators. 1303f22ef01cSRoman Divacky /// 1304f22ef01cSRoman Divacky std::string PatternToMatch::getPredicateCheck() const { 13052cab237bSDimitry Andric SmallVector<const Predicate*,4> PredList; 13062cab237bSDimitry Andric for (const Predicate &P : Predicates) 13072cab237bSDimitry Andric PredList.push_back(&P); 13082cab237bSDimitry Andric std::sort(PredList.begin(), PredList.end(), deref<llvm::less>()); 13097d523365SDimitry Andric 13102cab237bSDimitry Andric std::string Check; 13112cab237bSDimitry Andric for (unsigned i = 0, e = PredList.size(); i != e; ++i) { 13122cab237bSDimitry Andric if (i != 0) 13132cab237bSDimitry Andric Check += " && "; 13142cab237bSDimitry Andric Check += '(' + PredList[i]->getCondString() + ')'; 1315f22ef01cSRoman Divacky } 13162cab237bSDimitry Andric return Check; 1317f22ef01cSRoman Divacky } 1318f22ef01cSRoman Divacky 1319f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 1320f22ef01cSRoman Divacky // SDTypeConstraint implementation 1321f22ef01cSRoman Divacky // 1322f22ef01cSRoman Divacky 13232cab237bSDimitry Andric SDTypeConstraint::SDTypeConstraint(Record *R, const CodeGenHwModes &CGH) { 1324f22ef01cSRoman Divacky OperandNo = R->getValueAsInt("OperandNum"); 1325f22ef01cSRoman Divacky 1326f22ef01cSRoman Divacky if (R->isSubClassOf("SDTCisVT")) { 1327f22ef01cSRoman Divacky ConstraintType = SDTCisVT; 13282cab237bSDimitry Andric VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH); 13292cab237bSDimitry Andric for (const auto &P : VVT) 13302cab237bSDimitry Andric if (P.second == MVT::isVoid) 13313861d79fSDimitry Andric PrintFatalError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT"); 1332f22ef01cSRoman Divacky } else if (R->isSubClassOf("SDTCisPtrTy")) { 1333f22ef01cSRoman Divacky ConstraintType = SDTCisPtrTy; 1334f22ef01cSRoman Divacky } else if (R->isSubClassOf("SDTCisInt")) { 1335f22ef01cSRoman Divacky ConstraintType = SDTCisInt; 1336f22ef01cSRoman Divacky } else if (R->isSubClassOf("SDTCisFP")) { 1337f22ef01cSRoman Divacky ConstraintType = SDTCisFP; 1338f22ef01cSRoman Divacky } else if (R->isSubClassOf("SDTCisVec")) { 1339f22ef01cSRoman Divacky ConstraintType = SDTCisVec; 1340f22ef01cSRoman Divacky } else if (R->isSubClassOf("SDTCisSameAs")) { 1341f22ef01cSRoman Divacky ConstraintType = SDTCisSameAs; 1342f22ef01cSRoman Divacky x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum"); 1343f22ef01cSRoman Divacky } else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) { 1344f22ef01cSRoman Divacky ConstraintType = SDTCisVTSmallerThanOp; 1345f22ef01cSRoman Divacky x.SDTCisVTSmallerThanOp_Info.OtherOperandNum = 1346f22ef01cSRoman Divacky R->getValueAsInt("OtherOperandNum"); 1347f22ef01cSRoman Divacky } else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) { 1348f22ef01cSRoman Divacky ConstraintType = SDTCisOpSmallerThanOp; 1349f22ef01cSRoman Divacky x.SDTCisOpSmallerThanOp_Info.BigOperandNum = 1350f22ef01cSRoman Divacky R->getValueAsInt("BigOperandNum"); 1351f22ef01cSRoman Divacky } else if (R->isSubClassOf("SDTCisEltOfVec")) { 1352f22ef01cSRoman Divacky ConstraintType = SDTCisEltOfVec; 1353f22ef01cSRoman Divacky x.SDTCisEltOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum"); 13542754fe60SDimitry Andric } else if (R->isSubClassOf("SDTCisSubVecOfVec")) { 13552754fe60SDimitry Andric ConstraintType = SDTCisSubVecOfVec; 13562754fe60SDimitry Andric x.SDTCisSubVecOfVec_Info.OtherOperandNum = 13572754fe60SDimitry Andric R->getValueAsInt("OtherOpNum"); 1358ff0cc061SDimitry Andric } else if (R->isSubClassOf("SDTCVecEltisVT")) { 1359ff0cc061SDimitry Andric ConstraintType = SDTCVecEltisVT; 13602cab237bSDimitry Andric VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH); 13612cab237bSDimitry Andric for (const auto &P : VVT) { 13622cab237bSDimitry Andric MVT T = P.second; 13632cab237bSDimitry Andric if (T.isVector()) 13642cab237bSDimitry Andric PrintFatalError(R->getLoc(), 13652cab237bSDimitry Andric "Cannot use vector type as SDTCVecEltisVT"); 13662cab237bSDimitry Andric if (!T.isInteger() && !T.isFloatingPoint()) 1367ff0cc061SDimitry Andric PrintFatalError(R->getLoc(), "Must use integer or floating point type " 1368ff0cc061SDimitry Andric "as SDTCVecEltisVT"); 13692cab237bSDimitry Andric } 1370ff0cc061SDimitry Andric } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) { 1371ff0cc061SDimitry Andric ConstraintType = SDTCisSameNumEltsAs; 1372ff0cc061SDimitry Andric x.SDTCisSameNumEltsAs_Info.OtherOperandNum = 1373ff0cc061SDimitry Andric R->getValueAsInt("OtherOperandNum"); 13747d523365SDimitry Andric } else if (R->isSubClassOf("SDTCisSameSizeAs")) { 13757d523365SDimitry Andric ConstraintType = SDTCisSameSizeAs; 13767d523365SDimitry Andric x.SDTCisSameSizeAs_Info.OtherOperandNum = 13777d523365SDimitry Andric R->getValueAsInt("OtherOperandNum"); 1378f22ef01cSRoman Divacky } else { 1379ff0cc061SDimitry Andric PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); 1380f22ef01cSRoman Divacky } 1381f22ef01cSRoman Divacky } 1382f22ef01cSRoman Divacky 1383f22ef01cSRoman Divacky /// getOperandNum - Return the node corresponding to operand #OpNo in tree 1384f22ef01cSRoman Divacky /// N, and the result number in ResNo. 1385f22ef01cSRoman Divacky static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, 1386f22ef01cSRoman Divacky const SDNodeInfo &NodeInfo, 1387f22ef01cSRoman Divacky unsigned &ResNo) { 1388f22ef01cSRoman Divacky unsigned NumResults = NodeInfo.getNumResults(); 1389f22ef01cSRoman Divacky if (OpNo < NumResults) { 1390f22ef01cSRoman Divacky ResNo = OpNo; 1391f22ef01cSRoman Divacky return N; 1392f22ef01cSRoman Divacky } 1393f22ef01cSRoman Divacky 1394f22ef01cSRoman Divacky OpNo -= NumResults; 1395f22ef01cSRoman Divacky 1396f22ef01cSRoman Divacky if (OpNo >= N->getNumChildren()) { 1397ff0cc061SDimitry Andric std::string S; 1398ff0cc061SDimitry Andric raw_string_ostream OS(S); 1399ff0cc061SDimitry Andric OS << "Invalid operand number in type constraint " 1400f22ef01cSRoman Divacky << (OpNo+NumResults) << " "; 1401ff0cc061SDimitry Andric N->print(OS); 1402ff0cc061SDimitry Andric PrintFatalError(OS.str()); 1403f22ef01cSRoman Divacky } 1404f22ef01cSRoman Divacky 1405f22ef01cSRoman Divacky return N->getChild(OpNo); 1406f22ef01cSRoman Divacky } 1407f22ef01cSRoman Divacky 1408f22ef01cSRoman Divacky /// ApplyTypeConstraint - Given a node in a pattern, apply this type 1409f22ef01cSRoman Divacky /// constraint to the nodes operands. This returns true if it makes a 14103861d79fSDimitry Andric /// change, false otherwise. If a type contradiction is found, flag an error. 1411f22ef01cSRoman Divacky bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, 1412f22ef01cSRoman Divacky const SDNodeInfo &NodeInfo, 1413f22ef01cSRoman Divacky TreePattern &TP) const { 14143861d79fSDimitry Andric if (TP.hasError()) 14153861d79fSDimitry Andric return false; 14163861d79fSDimitry Andric 1417f22ef01cSRoman Divacky unsigned ResNo = 0; // The result number being referenced. 1418f22ef01cSRoman Divacky TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); 14192cab237bSDimitry Andric TypeInfer &TI = TP.getInfer(); 1420f22ef01cSRoman Divacky 1421f22ef01cSRoman Divacky switch (ConstraintType) { 1422f22ef01cSRoman Divacky case SDTCisVT: 1423f22ef01cSRoman Divacky // Operand must be a particular type. 14242cab237bSDimitry Andric return NodeToApply->UpdateNodeType(ResNo, VVT, TP); 1425f22ef01cSRoman Divacky case SDTCisPtrTy: 1426f22ef01cSRoman Divacky // Operand must be same as target pointer type. 1427f22ef01cSRoman Divacky return NodeToApply->UpdateNodeType(ResNo, MVT::iPTR, TP); 1428f22ef01cSRoman Divacky case SDTCisInt: 1429f22ef01cSRoman Divacky // Require it to be one of the legal integer VTs. 14302cab237bSDimitry Andric return TI.EnforceInteger(NodeToApply->getExtType(ResNo)); 1431f22ef01cSRoman Divacky case SDTCisFP: 1432f22ef01cSRoman Divacky // Require it to be one of the legal fp VTs. 14332cab237bSDimitry Andric return TI.EnforceFloatingPoint(NodeToApply->getExtType(ResNo)); 1434f22ef01cSRoman Divacky case SDTCisVec: 1435f22ef01cSRoman Divacky // Require it to be one of the legal vector VTs. 14362cab237bSDimitry Andric return TI.EnforceVector(NodeToApply->getExtType(ResNo)); 1437f22ef01cSRoman Divacky case SDTCisSameAs: { 1438f22ef01cSRoman Divacky unsigned OResNo = 0; 1439f22ef01cSRoman Divacky TreePatternNode *OtherNode = 1440f22ef01cSRoman Divacky getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo); 1441ff0cc061SDimitry Andric return NodeToApply->UpdateNodeType(ResNo, OtherNode->getExtType(OResNo),TP)| 1442ff0cc061SDimitry Andric OtherNode->UpdateNodeType(OResNo,NodeToApply->getExtType(ResNo),TP); 1443f22ef01cSRoman Divacky } 1444f22ef01cSRoman Divacky case SDTCisVTSmallerThanOp: { 1445f22ef01cSRoman Divacky // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must 1446f22ef01cSRoman Divacky // have an integer type that is smaller than the VT. 1447f22ef01cSRoman Divacky if (!NodeToApply->isLeaf() || 14483861d79fSDimitry Andric !isa<DefInit>(NodeToApply->getLeafValue()) || 1449f22ef01cSRoman Divacky !static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef() 14503861d79fSDimitry Andric ->isSubClassOf("ValueType")) { 1451f22ef01cSRoman Divacky TP.error(N->getOperator()->getName() + " expects a VT operand!"); 14523861d79fSDimitry Andric return false; 14533861d79fSDimitry Andric } 14542cab237bSDimitry Andric DefInit *DI = static_cast<DefInit*>(NodeToApply->getLeafValue()); 14552cab237bSDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 14562cab237bSDimitry Andric auto VVT = getValueTypeByHwMode(DI->getDef(), T.getHwModes()); 14572cab237bSDimitry Andric TypeSetByHwMode TypeListTmp(VVT); 1458f22ef01cSRoman Divacky 1459f22ef01cSRoman Divacky unsigned OResNo = 0; 1460f22ef01cSRoman Divacky TreePatternNode *OtherNode = 1461f22ef01cSRoman Divacky getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo, 1462f22ef01cSRoman Divacky OResNo); 1463f22ef01cSRoman Divacky 14642cab237bSDimitry Andric return TI.EnforceSmallerThan(TypeListTmp, OtherNode->getExtType(OResNo)); 1465f22ef01cSRoman Divacky } 1466f22ef01cSRoman Divacky case SDTCisOpSmallerThanOp: { 1467f22ef01cSRoman Divacky unsigned BResNo = 0; 1468f22ef01cSRoman Divacky TreePatternNode *BigOperand = 1469f22ef01cSRoman Divacky getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NodeInfo, 1470f22ef01cSRoman Divacky BResNo); 14712cab237bSDimitry Andric return TI.EnforceSmallerThan(NodeToApply->getExtType(ResNo), 14722cab237bSDimitry Andric BigOperand->getExtType(BResNo)); 1473f22ef01cSRoman Divacky } 1474f22ef01cSRoman Divacky case SDTCisEltOfVec: { 1475f22ef01cSRoman Divacky unsigned VResNo = 0; 1476f22ef01cSRoman Divacky TreePatternNode *VecOperand = 1477f22ef01cSRoman Divacky getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo, 1478f22ef01cSRoman Divacky VResNo); 1479f22ef01cSRoman Divacky // Filter vector types out of VecOperand that don't have the right element 1480f22ef01cSRoman Divacky // type. 14812cab237bSDimitry Andric return TI.EnforceVectorEltTypeIs(VecOperand->getExtType(VResNo), 14822cab237bSDimitry Andric NodeToApply->getExtType(ResNo)); 1483f22ef01cSRoman Divacky } 14842754fe60SDimitry Andric case SDTCisSubVecOfVec: { 14852754fe60SDimitry Andric unsigned VResNo = 0; 14862754fe60SDimitry Andric TreePatternNode *BigVecOperand = 14872754fe60SDimitry Andric getOperandNum(x.SDTCisSubVecOfVec_Info.OtherOperandNum, N, NodeInfo, 14882754fe60SDimitry Andric VResNo); 14892754fe60SDimitry Andric 14902754fe60SDimitry Andric // Filter vector types out of BigVecOperand that don't have the 14912754fe60SDimitry Andric // right subvector type. 14922cab237bSDimitry Andric return TI.EnforceVectorSubVectorTypeIs(BigVecOperand->getExtType(VResNo), 14932cab237bSDimitry Andric NodeToApply->getExtType(ResNo)); 14942754fe60SDimitry Andric } 1495ff0cc061SDimitry Andric case SDTCVecEltisVT: { 14962cab237bSDimitry Andric return TI.EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), VVT); 1497ff0cc061SDimitry Andric } 1498ff0cc061SDimitry Andric case SDTCisSameNumEltsAs: { 1499ff0cc061SDimitry Andric unsigned OResNo = 0; 1500ff0cc061SDimitry Andric TreePatternNode *OtherNode = 1501ff0cc061SDimitry Andric getOperandNum(x.SDTCisSameNumEltsAs_Info.OtherOperandNum, 1502ff0cc061SDimitry Andric N, NodeInfo, OResNo); 15032cab237bSDimitry Andric return TI.EnforceSameNumElts(OtherNode->getExtType(OResNo), 15042cab237bSDimitry Andric NodeToApply->getExtType(ResNo)); 1505ff0cc061SDimitry Andric } 15067d523365SDimitry Andric case SDTCisSameSizeAs: { 15077d523365SDimitry Andric unsigned OResNo = 0; 15087d523365SDimitry Andric TreePatternNode *OtherNode = 15097d523365SDimitry Andric getOperandNum(x.SDTCisSameSizeAs_Info.OtherOperandNum, 15107d523365SDimitry Andric N, NodeInfo, OResNo); 15112cab237bSDimitry Andric return TI.EnforceSameSize(OtherNode->getExtType(OResNo), 15122cab237bSDimitry Andric NodeToApply->getExtType(ResNo)); 15137d523365SDimitry Andric } 1514f22ef01cSRoman Divacky } 1515dff0c46cSDimitry Andric llvm_unreachable("Invalid ConstraintType!"); 1516f22ef01cSRoman Divacky } 1517f22ef01cSRoman Divacky 1518139f7f9bSDimitry Andric // Update the node type to match an instruction operand or result as specified 1519139f7f9bSDimitry Andric // in the ins or outs lists on the instruction definition. Return true if the 1520139f7f9bSDimitry Andric // type was actually changed. 1521139f7f9bSDimitry Andric bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo, 1522139f7f9bSDimitry Andric Record *Operand, 1523139f7f9bSDimitry Andric TreePattern &TP) { 1524139f7f9bSDimitry Andric // The 'unknown' operand indicates that types should be inferred from the 1525139f7f9bSDimitry Andric // context. 1526139f7f9bSDimitry Andric if (Operand->isSubClassOf("unknown_class")) 1527139f7f9bSDimitry Andric return false; 1528139f7f9bSDimitry Andric 1529139f7f9bSDimitry Andric // The Operand class specifies a type directly. 15302cab237bSDimitry Andric if (Operand->isSubClassOf("Operand")) { 15312cab237bSDimitry Andric Record *R = Operand->getValueAsDef("Type"); 15322cab237bSDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 15332cab237bSDimitry Andric return UpdateNodeType(ResNo, getValueTypeByHwMode(R, T.getHwModes()), TP); 15342cab237bSDimitry Andric } 1535139f7f9bSDimitry Andric 1536139f7f9bSDimitry Andric // PointerLikeRegClass has a type that is determined at runtime. 1537139f7f9bSDimitry Andric if (Operand->isSubClassOf("PointerLikeRegClass")) 1538139f7f9bSDimitry Andric return UpdateNodeType(ResNo, MVT::iPTR, TP); 1539139f7f9bSDimitry Andric 1540139f7f9bSDimitry Andric // Both RegisterClass and RegisterOperand operands derive their types from a 1541139f7f9bSDimitry Andric // register class def. 154291bc56edSDimitry Andric Record *RC = nullptr; 1543139f7f9bSDimitry Andric if (Operand->isSubClassOf("RegisterClass")) 1544139f7f9bSDimitry Andric RC = Operand; 1545139f7f9bSDimitry Andric else if (Operand->isSubClassOf("RegisterOperand")) 1546139f7f9bSDimitry Andric RC = Operand->getValueAsDef("RegClass"); 1547139f7f9bSDimitry Andric 1548139f7f9bSDimitry Andric assert(RC && "Unknown operand type"); 1549139f7f9bSDimitry Andric CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo(); 1550139f7f9bSDimitry Andric return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP); 1551139f7f9bSDimitry Andric } 1552139f7f9bSDimitry Andric 15532cab237bSDimitry Andric bool TreePatternNode::ContainsUnresolvedType(TreePattern &TP) const { 15542cab237bSDimitry Andric for (unsigned i = 0, e = Types.size(); i != e; ++i) 15552cab237bSDimitry Andric if (!TP.getInfer().isConcrete(Types[i], true)) 15562cab237bSDimitry Andric return true; 15572cab237bSDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 15582cab237bSDimitry Andric if (getChild(i)->ContainsUnresolvedType(TP)) 15592cab237bSDimitry Andric return true; 15602cab237bSDimitry Andric return false; 15612cab237bSDimitry Andric } 15622cab237bSDimitry Andric 15632cab237bSDimitry Andric bool TreePatternNode::hasProperTypeByHwMode() const { 15642cab237bSDimitry Andric for (const TypeSetByHwMode &S : Types) 15652cab237bSDimitry Andric if (!S.isDefaultOnly()) 15662cab237bSDimitry Andric return true; 15672cab237bSDimitry Andric for (TreePatternNode *C : Children) 15682cab237bSDimitry Andric if (C->hasProperTypeByHwMode()) 15692cab237bSDimitry Andric return true; 15702cab237bSDimitry Andric return false; 15712cab237bSDimitry Andric } 15722cab237bSDimitry Andric 15732cab237bSDimitry Andric bool TreePatternNode::hasPossibleType() const { 15742cab237bSDimitry Andric for (const TypeSetByHwMode &S : Types) 15752cab237bSDimitry Andric if (!S.isPossible()) 15762cab237bSDimitry Andric return false; 15772cab237bSDimitry Andric for (TreePatternNode *C : Children) 15782cab237bSDimitry Andric if (!C->hasPossibleType()) 15792cab237bSDimitry Andric return false; 15802cab237bSDimitry Andric return true; 15812cab237bSDimitry Andric } 15822cab237bSDimitry Andric 15832cab237bSDimitry Andric bool TreePatternNode::setDefaultMode(unsigned Mode) { 15842cab237bSDimitry Andric for (TypeSetByHwMode &S : Types) { 15852cab237bSDimitry Andric S.makeSimple(Mode); 15862cab237bSDimitry Andric // Check if the selected mode had a type conflict. 15872cab237bSDimitry Andric if (S.get(DefaultMode).empty()) 15882cab237bSDimitry Andric return false; 15892cab237bSDimitry Andric } 15902cab237bSDimitry Andric for (TreePatternNode *C : Children) 15912cab237bSDimitry Andric if (!C->setDefaultMode(Mode)) 15922cab237bSDimitry Andric return false; 15932cab237bSDimitry Andric return true; 15942cab237bSDimitry Andric } 1595139f7f9bSDimitry Andric 1596f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 1597f22ef01cSRoman Divacky // SDNodeInfo implementation 1598f22ef01cSRoman Divacky // 15992cab237bSDimitry Andric SDNodeInfo::SDNodeInfo(Record *R, const CodeGenHwModes &CGH) : Def(R) { 1600f22ef01cSRoman Divacky EnumName = R->getValueAsString("Opcode"); 1601f22ef01cSRoman Divacky SDClassName = R->getValueAsString("SDClass"); 1602f22ef01cSRoman Divacky Record *TypeProfile = R->getValueAsDef("TypeProfile"); 1603f22ef01cSRoman Divacky NumResults = TypeProfile->getValueAsInt("NumResults"); 1604f22ef01cSRoman Divacky NumOperands = TypeProfile->getValueAsInt("NumOperands"); 1605f22ef01cSRoman Divacky 1606f22ef01cSRoman Divacky // Parse the properties. 1607da09e106SDimitry Andric Properties = parseSDPatternOperatorProperties(R); 1608f22ef01cSRoman Divacky 1609f22ef01cSRoman Divacky // Parse the type constraints. 1610f22ef01cSRoman Divacky std::vector<Record*> ConstraintList = 1611f22ef01cSRoman Divacky TypeProfile->getValueAsListOfDefs("Constraints"); 16122cab237bSDimitry Andric for (Record *R : ConstraintList) 16132cab237bSDimitry Andric TypeConstraints.emplace_back(R, CGH); 1614f22ef01cSRoman Divacky } 1615f22ef01cSRoman Divacky 1616f22ef01cSRoman Divacky /// getKnownType - If the type constraints on this node imply a fixed type 1617f22ef01cSRoman Divacky /// (e.g. all stores return void, etc), then return it as an 1618f22ef01cSRoman Divacky /// MVT::SimpleValueType. Otherwise, return EEVT::Other. 1619f22ef01cSRoman Divacky MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const { 1620f22ef01cSRoman Divacky unsigned NumResults = getNumResults(); 1621f22ef01cSRoman Divacky assert(NumResults <= 1 && 1622f22ef01cSRoman Divacky "We only work with nodes with zero or one result so far!"); 1623f22ef01cSRoman Divacky assert(ResNo == 0 && "Only handles single result nodes so far"); 1624f22ef01cSRoman Divacky 16257d523365SDimitry Andric for (const SDTypeConstraint &Constraint : TypeConstraints) { 1626f22ef01cSRoman Divacky // Make sure that this applies to the correct node result. 16277d523365SDimitry Andric if (Constraint.OperandNo >= NumResults) // FIXME: need value # 1628f22ef01cSRoman Divacky continue; 1629f22ef01cSRoman Divacky 16307d523365SDimitry Andric switch (Constraint.ConstraintType) { 1631f22ef01cSRoman Divacky default: break; 1632f22ef01cSRoman Divacky case SDTypeConstraint::SDTCisVT: 16332cab237bSDimitry Andric if (Constraint.VVT.isSimple()) 16342cab237bSDimitry Andric return Constraint.VVT.getSimple().SimpleTy; 16352cab237bSDimitry Andric break; 1636f22ef01cSRoman Divacky case SDTypeConstraint::SDTCisPtrTy: 1637f22ef01cSRoman Divacky return MVT::iPTR; 1638f22ef01cSRoman Divacky } 1639f22ef01cSRoman Divacky } 1640f22ef01cSRoman Divacky return MVT::Other; 1641f22ef01cSRoman Divacky } 1642f22ef01cSRoman Divacky 1643f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 1644f22ef01cSRoman Divacky // TreePatternNode implementation 1645f22ef01cSRoman Divacky // 1646f22ef01cSRoman Divacky 1647f22ef01cSRoman Divacky TreePatternNode::~TreePatternNode() { 1648f22ef01cSRoman Divacky #if 0 // FIXME: implement refcounted tree nodes! 1649f22ef01cSRoman Divacky for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 1650f22ef01cSRoman Divacky delete getChild(i); 1651f22ef01cSRoman Divacky #endif 1652f22ef01cSRoman Divacky } 1653f22ef01cSRoman Divacky 1654f22ef01cSRoman Divacky static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { 1655f22ef01cSRoman Divacky if (Operator->getName() == "set" || 1656f22ef01cSRoman Divacky Operator->getName() == "implicit") 1657f22ef01cSRoman Divacky return 0; // All return nothing. 1658f22ef01cSRoman Divacky 1659f22ef01cSRoman Divacky if (Operator->isSubClassOf("Intrinsic")) 1660f22ef01cSRoman Divacky return CDP.getIntrinsic(Operator).IS.RetVTs.size(); 1661f22ef01cSRoman Divacky 1662f22ef01cSRoman Divacky if (Operator->isSubClassOf("SDNode")) 1663f22ef01cSRoman Divacky return CDP.getSDNodeInfo(Operator).getNumResults(); 1664f22ef01cSRoman Divacky 1665f22ef01cSRoman Divacky if (Operator->isSubClassOf("PatFrag")) { 1666f22ef01cSRoman Divacky // If we've already parsed this pattern fragment, get it. Otherwise, handle 1667f22ef01cSRoman Divacky // the forward reference case where one pattern fragment references another 1668f22ef01cSRoman Divacky // before it is processed. 1669f22ef01cSRoman Divacky if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator)) 1670f22ef01cSRoman Divacky return PFRec->getOnlyTree()->getNumTypes(); 1671f22ef01cSRoman Divacky 1672f22ef01cSRoman Divacky // Get the result tree. 1673f22ef01cSRoman Divacky DagInit *Tree = Operator->getValueAsDag("Fragment"); 167491bc56edSDimitry Andric Record *Op = nullptr; 16753861d79fSDimitry Andric if (Tree) 16763861d79fSDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(Tree->getOperator())) 16773861d79fSDimitry Andric Op = DI->getDef(); 1678f22ef01cSRoman Divacky assert(Op && "Invalid Fragment"); 1679f22ef01cSRoman Divacky return GetNumNodeResults(Op, CDP); 1680f22ef01cSRoman Divacky } 1681f22ef01cSRoman Divacky 1682f22ef01cSRoman Divacky if (Operator->isSubClassOf("Instruction")) { 1683f22ef01cSRoman Divacky CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); 1684f22ef01cSRoman Divacky 1685ff0cc061SDimitry Andric unsigned NumDefsToAdd = InstInfo.Operands.NumDefs; 1686ff0cc061SDimitry Andric 1687ff0cc061SDimitry Andric // Subtract any defaulted outputs. 1688ff0cc061SDimitry Andric for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) { 1689ff0cc061SDimitry Andric Record *OperandNode = InstInfo.Operands[i].Rec; 1690ff0cc061SDimitry Andric 1691ff0cc061SDimitry Andric if (OperandNode->isSubClassOf("OperandWithDefaultOps") && 1692ff0cc061SDimitry Andric !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) 1693ff0cc061SDimitry Andric --NumDefsToAdd; 1694ff0cc061SDimitry Andric } 1695f22ef01cSRoman Divacky 1696f22ef01cSRoman Divacky // Add on one implicit def if it has a resolvable type. 1697f22ef01cSRoman Divacky if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) 1698f22ef01cSRoman Divacky ++NumDefsToAdd; 1699f22ef01cSRoman Divacky return NumDefsToAdd; 1700f22ef01cSRoman Divacky } 1701f22ef01cSRoman Divacky 1702f22ef01cSRoman Divacky if (Operator->isSubClassOf("SDNodeXForm")) 1703f22ef01cSRoman Divacky return 1; // FIXME: Generalize SDNodeXForm 1704f22ef01cSRoman Divacky 170591bc56edSDimitry Andric if (Operator->isSubClassOf("ValueType")) 170691bc56edSDimitry Andric return 1; // A type-cast of one result. 170791bc56edSDimitry Andric 170891bc56edSDimitry Andric if (Operator->isSubClassOf("ComplexPattern")) 170991bc56edSDimitry Andric return 1; 171091bc56edSDimitry Andric 17117a7e6055SDimitry Andric errs() << *Operator; 1712ff0cc061SDimitry Andric PrintFatalError("Unhandled node in GetNumNodeResults"); 1713f22ef01cSRoman Divacky } 1714f22ef01cSRoman Divacky 1715f22ef01cSRoman Divacky void TreePatternNode::print(raw_ostream &OS) const { 1716f22ef01cSRoman Divacky if (isLeaf()) 1717f22ef01cSRoman Divacky OS << *getLeafValue(); 1718f22ef01cSRoman Divacky else 1719f22ef01cSRoman Divacky OS << '(' << getOperator()->getName(); 1720f22ef01cSRoman Divacky 17212cab237bSDimitry Andric for (unsigned i = 0, e = Types.size(); i != e; ++i) { 17222cab237bSDimitry Andric OS << ':'; 17232cab237bSDimitry Andric getExtType(i).writeToStream(OS); 17242cab237bSDimitry Andric } 1725f22ef01cSRoman Divacky 1726f22ef01cSRoman Divacky if (!isLeaf()) { 1727f22ef01cSRoman Divacky if (getNumChildren() != 0) { 1728f22ef01cSRoman Divacky OS << " "; 1729f22ef01cSRoman Divacky getChild(0)->print(OS); 1730f22ef01cSRoman Divacky for (unsigned i = 1, e = getNumChildren(); i != e; ++i) { 1731f22ef01cSRoman Divacky OS << ", "; 1732f22ef01cSRoman Divacky getChild(i)->print(OS); 1733f22ef01cSRoman Divacky } 1734f22ef01cSRoman Divacky } 1735f22ef01cSRoman Divacky OS << ")"; 1736f22ef01cSRoman Divacky } 1737f22ef01cSRoman Divacky 17387d523365SDimitry Andric for (const TreePredicateFn &Pred : PredicateFns) 17397d523365SDimitry Andric OS << "<<P:" << Pred.getFnName() << ">>"; 1740f22ef01cSRoman Divacky if (TransformFn) 1741f22ef01cSRoman Divacky OS << "<<X:" << TransformFn->getName() << ">>"; 1742f22ef01cSRoman Divacky if (!getName().empty()) 1743f22ef01cSRoman Divacky OS << ":$" << getName(); 1744f22ef01cSRoman Divacky 1745f22ef01cSRoman Divacky } 1746f22ef01cSRoman Divacky void TreePatternNode::dump() const { 1747f22ef01cSRoman Divacky print(errs()); 1748f22ef01cSRoman Divacky } 1749f22ef01cSRoman Divacky 1750f22ef01cSRoman Divacky /// isIsomorphicTo - Return true if this node is recursively 1751f22ef01cSRoman Divacky /// isomorphic to the specified node. For this comparison, the node's 1752f22ef01cSRoman Divacky /// entire state is considered. The assigned name is ignored, since 1753f22ef01cSRoman Divacky /// nodes with differing names are considered isomorphic. However, if 1754f22ef01cSRoman Divacky /// the assigned name is present in the dependent variable set, then 1755f22ef01cSRoman Divacky /// the assigned name is considered significant and the node is 1756f22ef01cSRoman Divacky /// isomorphic if the names match. 1757f22ef01cSRoman Divacky bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N, 1758f22ef01cSRoman Divacky const MultipleUseVarSet &DepVars) const { 1759f22ef01cSRoman Divacky if (N == this) return true; 1760f22ef01cSRoman Divacky if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() || 1761f22ef01cSRoman Divacky getPredicateFns() != N->getPredicateFns() || 1762f22ef01cSRoman Divacky getTransformFn() != N->getTransformFn()) 1763f22ef01cSRoman Divacky return false; 1764f22ef01cSRoman Divacky 1765f22ef01cSRoman Divacky if (isLeaf()) { 17663861d79fSDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) { 17673861d79fSDimitry Andric if (DefInit *NDI = dyn_cast<DefInit>(N->getLeafValue())) { 1768f22ef01cSRoman Divacky return ((DI->getDef() == NDI->getDef()) 1769f22ef01cSRoman Divacky && (DepVars.find(getName()) == DepVars.end() 1770f22ef01cSRoman Divacky || getName() == N->getName())); 1771f22ef01cSRoman Divacky } 1772f22ef01cSRoman Divacky } 1773f22ef01cSRoman Divacky return getLeafValue() == N->getLeafValue(); 1774f22ef01cSRoman Divacky } 1775f22ef01cSRoman Divacky 1776f22ef01cSRoman Divacky if (N->getOperator() != getOperator() || 1777f22ef01cSRoman Divacky N->getNumChildren() != getNumChildren()) return false; 1778f22ef01cSRoman Divacky for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 1779f22ef01cSRoman Divacky if (!getChild(i)->isIsomorphicTo(N->getChild(i), DepVars)) 1780f22ef01cSRoman Divacky return false; 1781f22ef01cSRoman Divacky return true; 1782f22ef01cSRoman Divacky } 1783f22ef01cSRoman Divacky 1784f22ef01cSRoman Divacky /// clone - Make a copy of this tree and all of its children. 1785f22ef01cSRoman Divacky /// 1786f22ef01cSRoman Divacky TreePatternNode *TreePatternNode::clone() const { 1787f22ef01cSRoman Divacky TreePatternNode *New; 1788f22ef01cSRoman Divacky if (isLeaf()) { 1789f22ef01cSRoman Divacky New = new TreePatternNode(getLeafValue(), getNumTypes()); 1790f22ef01cSRoman Divacky } else { 1791f22ef01cSRoman Divacky std::vector<TreePatternNode*> CChildren; 1792f22ef01cSRoman Divacky CChildren.reserve(Children.size()); 1793f22ef01cSRoman Divacky for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 1794f22ef01cSRoman Divacky CChildren.push_back(getChild(i)->clone()); 1795f22ef01cSRoman Divacky New = new TreePatternNode(getOperator(), CChildren, getNumTypes()); 1796f22ef01cSRoman Divacky } 1797f22ef01cSRoman Divacky New->setName(getName()); 1798f22ef01cSRoman Divacky New->Types = Types; 1799f22ef01cSRoman Divacky New->setPredicateFns(getPredicateFns()); 1800f22ef01cSRoman Divacky New->setTransformFn(getTransformFn()); 1801f22ef01cSRoman Divacky return New; 1802f22ef01cSRoman Divacky } 1803f22ef01cSRoman Divacky 1804f22ef01cSRoman Divacky /// RemoveAllTypes - Recursively strip all the types of this tree. 1805f22ef01cSRoman Divacky void TreePatternNode::RemoveAllTypes() { 18067d523365SDimitry Andric // Reset to unknown type. 18072cab237bSDimitry Andric std::fill(Types.begin(), Types.end(), TypeSetByHwMode()); 1808f22ef01cSRoman Divacky if (isLeaf()) return; 1809f22ef01cSRoman Divacky for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 1810f22ef01cSRoman Divacky getChild(i)->RemoveAllTypes(); 1811f22ef01cSRoman Divacky } 1812f22ef01cSRoman Divacky 1813f22ef01cSRoman Divacky 1814f22ef01cSRoman Divacky /// SubstituteFormalArguments - Replace the formal arguments in this tree 1815f22ef01cSRoman Divacky /// with actual values specified by ArgMap. 1816f22ef01cSRoman Divacky void TreePatternNode:: 1817f22ef01cSRoman Divacky SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) { 1818f22ef01cSRoman Divacky if (isLeaf()) return; 1819f22ef01cSRoman Divacky 1820f22ef01cSRoman Divacky for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { 1821f22ef01cSRoman Divacky TreePatternNode *Child = getChild(i); 1822f22ef01cSRoman Divacky if (Child->isLeaf()) { 1823f22ef01cSRoman Divacky Init *Val = Child->getLeafValue(); 182491bc56edSDimitry Andric // Note that, when substituting into an output pattern, Val might be an 182591bc56edSDimitry Andric // UnsetInit. 182691bc56edSDimitry Andric if (isa<UnsetInit>(Val) || (isa<DefInit>(Val) && 182791bc56edSDimitry Andric cast<DefInit>(Val)->getDef()->getName() == "node")) { 1828f22ef01cSRoman Divacky // We found a use of a formal argument, replace it with its value. 1829f22ef01cSRoman Divacky TreePatternNode *NewChild = ArgMap[Child->getName()]; 1830f22ef01cSRoman Divacky assert(NewChild && "Couldn't find formal argument!"); 1831f22ef01cSRoman Divacky assert((Child->getPredicateFns().empty() || 1832f22ef01cSRoman Divacky NewChild->getPredicateFns() == Child->getPredicateFns()) && 1833f22ef01cSRoman Divacky "Non-empty child predicate clobbered!"); 1834f22ef01cSRoman Divacky setChild(i, NewChild); 1835f22ef01cSRoman Divacky } 1836f22ef01cSRoman Divacky } else { 1837f22ef01cSRoman Divacky getChild(i)->SubstituteFormalArguments(ArgMap); 1838f22ef01cSRoman Divacky } 1839f22ef01cSRoman Divacky } 1840f22ef01cSRoman Divacky } 1841f22ef01cSRoman Divacky 1842f22ef01cSRoman Divacky 1843f22ef01cSRoman Divacky /// InlinePatternFragments - If this pattern refers to any pattern 1844f22ef01cSRoman Divacky /// fragments, inline them into place, giving us a pattern without any 1845f22ef01cSRoman Divacky /// PatFrag references. 1846f22ef01cSRoman Divacky TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { 18473861d79fSDimitry Andric if (TP.hasError()) 184891bc56edSDimitry Andric return nullptr; 18493861d79fSDimitry Andric 18503861d79fSDimitry Andric if (isLeaf()) 18513861d79fSDimitry Andric return this; // nothing to do. 1852f22ef01cSRoman Divacky Record *Op = getOperator(); 1853f22ef01cSRoman Divacky 1854f22ef01cSRoman Divacky if (!Op->isSubClassOf("PatFrag")) { 1855f22ef01cSRoman Divacky // Just recursively inline children nodes. 1856f22ef01cSRoman Divacky for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { 1857f22ef01cSRoman Divacky TreePatternNode *Child = getChild(i); 1858f22ef01cSRoman Divacky TreePatternNode *NewChild = Child->InlinePatternFragments(TP); 1859f22ef01cSRoman Divacky 1860f22ef01cSRoman Divacky assert((Child->getPredicateFns().empty() || 1861f22ef01cSRoman Divacky NewChild->getPredicateFns() == Child->getPredicateFns()) && 1862f22ef01cSRoman Divacky "Non-empty child predicate clobbered!"); 1863f22ef01cSRoman Divacky 1864f22ef01cSRoman Divacky setChild(i, NewChild); 1865f22ef01cSRoman Divacky } 1866f22ef01cSRoman Divacky return this; 1867f22ef01cSRoman Divacky } 1868f22ef01cSRoman Divacky 1869f22ef01cSRoman Divacky // Otherwise, we found a reference to a fragment. First, look up its 1870f22ef01cSRoman Divacky // TreePattern record. 1871f22ef01cSRoman Divacky TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op); 1872f22ef01cSRoman Divacky 1873f22ef01cSRoman Divacky // Verify that we are passing the right number of operands. 18743861d79fSDimitry Andric if (Frag->getNumArgs() != Children.size()) { 1875f22ef01cSRoman Divacky TP.error("'" + Op->getName() + "' fragment requires " + 1876fe4fed2eSDimitry Andric Twine(Frag->getNumArgs()) + " operands!"); 187791bc56edSDimitry Andric return nullptr; 18783861d79fSDimitry Andric } 1879f22ef01cSRoman Divacky 1880f22ef01cSRoman Divacky TreePatternNode *FragTree = Frag->getOnlyTree()->clone(); 1881f22ef01cSRoman Divacky 18823b0f4066SDimitry Andric TreePredicateFn PredFn(Frag); 18833b0f4066SDimitry Andric if (!PredFn.isAlwaysTrue()) 18843b0f4066SDimitry Andric FragTree->addPredicateFn(PredFn); 1885f22ef01cSRoman Divacky 1886f22ef01cSRoman Divacky // Resolve formal arguments to their actual value. 1887f22ef01cSRoman Divacky if (Frag->getNumArgs()) { 1888f22ef01cSRoman Divacky // Compute the map of formal to actual arguments. 1889f22ef01cSRoman Divacky std::map<std::string, TreePatternNode*> ArgMap; 1890f22ef01cSRoman Divacky for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) 1891f22ef01cSRoman Divacky ArgMap[Frag->getArgName(i)] = getChild(i)->InlinePatternFragments(TP); 1892f22ef01cSRoman Divacky 1893f22ef01cSRoman Divacky FragTree->SubstituteFormalArguments(ArgMap); 1894f22ef01cSRoman Divacky } 1895f22ef01cSRoman Divacky 1896f22ef01cSRoman Divacky FragTree->setName(getName()); 1897f22ef01cSRoman Divacky for (unsigned i = 0, e = Types.size(); i != e; ++i) 1898f22ef01cSRoman Divacky FragTree->UpdateNodeType(i, getExtType(i), TP); 1899f22ef01cSRoman Divacky 1900f22ef01cSRoman Divacky // Transfer in the old predicates. 19017d523365SDimitry Andric for (const TreePredicateFn &Pred : getPredicateFns()) 19027d523365SDimitry Andric FragTree->addPredicateFn(Pred); 1903f22ef01cSRoman Divacky 1904f22ef01cSRoman Divacky // Get a new copy of this fragment to stitch into here. 1905f22ef01cSRoman Divacky //delete this; // FIXME: implement refcounting! 1906f22ef01cSRoman Divacky 1907f22ef01cSRoman Divacky // The fragment we inlined could have recursive inlining that is needed. See 1908f22ef01cSRoman Divacky // if there are any pattern fragments in it and inline them as needed. 1909f22ef01cSRoman Divacky return FragTree->InlinePatternFragments(TP); 1910f22ef01cSRoman Divacky } 1911f22ef01cSRoman Divacky 1912f22ef01cSRoman Divacky /// getImplicitType - Check to see if the specified record has an implicit 1913f22ef01cSRoman Divacky /// type which should be applied to it. This will infer the type of register 1914f22ef01cSRoman Divacky /// references from the register file information, for example. 1915f22ef01cSRoman Divacky /// 1916139f7f9bSDimitry Andric /// When Unnamed is set, return the type of a DAG operand with no name, such as 1917139f7f9bSDimitry Andric /// the F8RC register class argument in: 1918139f7f9bSDimitry Andric /// 1919139f7f9bSDimitry Andric /// (COPY_TO_REGCLASS GPR:$src, F8RC) 1920139f7f9bSDimitry Andric /// 1921139f7f9bSDimitry Andric /// When Unnamed is false, return the type of a named DAG operand such as the 1922139f7f9bSDimitry Andric /// GPR:$src operand above. 1923139f7f9bSDimitry Andric /// 19242cab237bSDimitry Andric static TypeSetByHwMode getImplicitType(Record *R, unsigned ResNo, 1925139f7f9bSDimitry Andric bool NotRegisters, 1926139f7f9bSDimitry Andric bool Unnamed, 1927139f7f9bSDimitry Andric TreePattern &TP) { 19282cab237bSDimitry Andric CodeGenDAGPatterns &CDP = TP.getDAGPatterns(); 19292cab237bSDimitry Andric 193017a519f9SDimitry Andric // Check to see if this is a register operand. 193117a519f9SDimitry Andric if (R->isSubClassOf("RegisterOperand")) { 193217a519f9SDimitry Andric assert(ResNo == 0 && "Regoperand ref only has one result!"); 193317a519f9SDimitry Andric if (NotRegisters) 19342cab237bSDimitry Andric return TypeSetByHwMode(); // Unknown. 193517a519f9SDimitry Andric Record *RegClass = R->getValueAsDef("RegClass"); 193617a519f9SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 19372cab237bSDimitry Andric return TypeSetByHwMode(T.getRegisterClass(RegClass).getValueTypes()); 193817a519f9SDimitry Andric } 193917a519f9SDimitry Andric 1940f22ef01cSRoman Divacky // Check to see if this is a register or a register class. 1941f22ef01cSRoman Divacky if (R->isSubClassOf("RegisterClass")) { 1942f22ef01cSRoman Divacky assert(ResNo == 0 && "Regclass ref only has one result!"); 1943139f7f9bSDimitry Andric // An unnamed register class represents itself as an i32 immediate, for 1944139f7f9bSDimitry Andric // example on a COPY_TO_REGCLASS instruction. 1945139f7f9bSDimitry Andric if (Unnamed) 19462cab237bSDimitry Andric return TypeSetByHwMode(MVT::i32); 1947139f7f9bSDimitry Andric 1948139f7f9bSDimitry Andric // In a named operand, the register class provides the possible set of 1949139f7f9bSDimitry Andric // types. 1950f22ef01cSRoman Divacky if (NotRegisters) 19512cab237bSDimitry Andric return TypeSetByHwMode(); // Unknown. 1952f22ef01cSRoman Divacky const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 19532cab237bSDimitry Andric return TypeSetByHwMode(T.getRegisterClass(R).getValueTypes()); 1954f22ef01cSRoman Divacky } 1955f22ef01cSRoman Divacky 1956f22ef01cSRoman Divacky if (R->isSubClassOf("PatFrag")) { 1957f22ef01cSRoman Divacky assert(ResNo == 0 && "FIXME: PatFrag with multiple results?"); 1958f22ef01cSRoman Divacky // Pattern fragment types will be resolved when they are inlined. 19592cab237bSDimitry Andric return TypeSetByHwMode(); // Unknown. 1960f22ef01cSRoman Divacky } 1961f22ef01cSRoman Divacky 1962f22ef01cSRoman Divacky if (R->isSubClassOf("Register")) { 1963f22ef01cSRoman Divacky assert(ResNo == 0 && "Registers only produce one result!"); 1964f22ef01cSRoman Divacky if (NotRegisters) 19652cab237bSDimitry Andric return TypeSetByHwMode(); // Unknown. 1966f22ef01cSRoman Divacky const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 19672cab237bSDimitry Andric return TypeSetByHwMode(T.getRegisterVTs(R)); 1968f22ef01cSRoman Divacky } 1969f22ef01cSRoman Divacky 1970f22ef01cSRoman Divacky if (R->isSubClassOf("SubRegIndex")) { 1971f22ef01cSRoman Divacky assert(ResNo == 0 && "SubRegisterIndices only produce one result!"); 19722cab237bSDimitry Andric return TypeSetByHwMode(MVT::i32); 1973f22ef01cSRoman Divacky } 1974f22ef01cSRoman Divacky 1975139f7f9bSDimitry Andric if (R->isSubClassOf("ValueType")) { 1976f22ef01cSRoman Divacky assert(ResNo == 0 && "This node only has one result!"); 1977139f7f9bSDimitry Andric // An unnamed VTSDNode represents itself as an MVT::Other immediate. 1978139f7f9bSDimitry Andric // 1979139f7f9bSDimitry Andric // (sext_inreg GPR:$src, i16) 1980139f7f9bSDimitry Andric // ~~~ 1981139f7f9bSDimitry Andric if (Unnamed) 19822cab237bSDimitry Andric return TypeSetByHwMode(MVT::Other); 1983139f7f9bSDimitry Andric // With a name, the ValueType simply provides the type of the named 1984139f7f9bSDimitry Andric // variable. 1985139f7f9bSDimitry Andric // 1986139f7f9bSDimitry Andric // (sext_inreg i32:$src, i16) 1987139f7f9bSDimitry Andric // ~~~~~~~~ 1988139f7f9bSDimitry Andric if (NotRegisters) 19892cab237bSDimitry Andric return TypeSetByHwMode(); // Unknown. 19902cab237bSDimitry Andric const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); 19912cab237bSDimitry Andric return TypeSetByHwMode(getValueTypeByHwMode(R, CGH)); 1992139f7f9bSDimitry Andric } 1993139f7f9bSDimitry Andric 1994139f7f9bSDimitry Andric if (R->isSubClassOf("CondCode")) { 1995139f7f9bSDimitry Andric assert(ResNo == 0 && "This node only has one result!"); 1996139f7f9bSDimitry Andric // Using a CondCodeSDNode. 19972cab237bSDimitry Andric return TypeSetByHwMode(MVT::Other); 1998f22ef01cSRoman Divacky } 1999f22ef01cSRoman Divacky 2000f22ef01cSRoman Divacky if (R->isSubClassOf("ComplexPattern")) { 2001f22ef01cSRoman Divacky assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?"); 2002f22ef01cSRoman Divacky if (NotRegisters) 20032cab237bSDimitry Andric return TypeSetByHwMode(); // Unknown. 20042cab237bSDimitry Andric return TypeSetByHwMode(CDP.getComplexPattern(R).getValueType()); 2005f22ef01cSRoman Divacky } 2006f22ef01cSRoman Divacky if (R->isSubClassOf("PointerLikeRegClass")) { 2007f22ef01cSRoman Divacky assert(ResNo == 0 && "Regclass can only have one result!"); 20082cab237bSDimitry Andric TypeSetByHwMode VTS(MVT::iPTR); 20092cab237bSDimitry Andric TP.getInfer().expandOverloads(VTS); 20102cab237bSDimitry Andric return VTS; 2011f22ef01cSRoman Divacky } 2012f22ef01cSRoman Divacky 2013f22ef01cSRoman Divacky if (R->getName() == "node" || R->getName() == "srcvalue" || 2014f22ef01cSRoman Divacky R->getName() == "zero_reg") { 2015f22ef01cSRoman Divacky // Placeholder. 20162cab237bSDimitry Andric return TypeSetByHwMode(); // Unknown. 2017f22ef01cSRoman Divacky } 2018f22ef01cSRoman Divacky 20192cab237bSDimitry Andric if (R->isSubClassOf("Operand")) { 20202cab237bSDimitry Andric const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); 20212cab237bSDimitry Andric Record *T = R->getValueAsDef("Type"); 20222cab237bSDimitry Andric return TypeSetByHwMode(getValueTypeByHwMode(T, CGH)); 20232cab237bSDimitry Andric } 202491bc56edSDimitry Andric 2025f22ef01cSRoman Divacky TP.error("Unknown node flavor used in pattern: " + R->getName()); 20262cab237bSDimitry Andric return TypeSetByHwMode(MVT::Other); 2027f22ef01cSRoman Divacky } 2028f22ef01cSRoman Divacky 2029f22ef01cSRoman Divacky 2030f22ef01cSRoman Divacky /// getIntrinsicInfo - If this node corresponds to an intrinsic, return the 2031f22ef01cSRoman Divacky /// CodeGenIntrinsic information for it, otherwise return a null pointer. 2032f22ef01cSRoman Divacky const CodeGenIntrinsic *TreePatternNode:: 2033f22ef01cSRoman Divacky getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { 2034f22ef01cSRoman Divacky if (getOperator() != CDP.get_intrinsic_void_sdnode() && 2035f22ef01cSRoman Divacky getOperator() != CDP.get_intrinsic_w_chain_sdnode() && 2036f22ef01cSRoman Divacky getOperator() != CDP.get_intrinsic_wo_chain_sdnode()) 203791bc56edSDimitry Andric return nullptr; 2038f22ef01cSRoman Divacky 20393861d79fSDimitry Andric unsigned IID = cast<IntInit>(getChild(0)->getLeafValue())->getValue(); 2040f22ef01cSRoman Divacky return &CDP.getIntrinsicInfo(IID); 2041f22ef01cSRoman Divacky } 2042f22ef01cSRoman Divacky 2043f22ef01cSRoman Divacky /// getComplexPatternInfo - If this node corresponds to a ComplexPattern, 2044f22ef01cSRoman Divacky /// return the ComplexPattern information, otherwise return null. 2045f22ef01cSRoman Divacky const ComplexPattern * 2046f22ef01cSRoman Divacky TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const { 204791bc56edSDimitry Andric Record *Rec; 204891bc56edSDimitry Andric if (isLeaf()) { 20493861d79fSDimitry Andric DefInit *DI = dyn_cast<DefInit>(getLeafValue()); 205091bc56edSDimitry Andric if (!DI) 205191bc56edSDimitry Andric return nullptr; 205291bc56edSDimitry Andric Rec = DI->getDef(); 205391bc56edSDimitry Andric } else 205491bc56edSDimitry Andric Rec = getOperator(); 205591bc56edSDimitry Andric 205691bc56edSDimitry Andric if (!Rec->isSubClassOf("ComplexPattern")) 205791bc56edSDimitry Andric return nullptr; 205891bc56edSDimitry Andric return &CGP.getComplexPattern(Rec); 205991bc56edSDimitry Andric } 206091bc56edSDimitry Andric 206191bc56edSDimitry Andric unsigned TreePatternNode::getNumMIResults(const CodeGenDAGPatterns &CGP) const { 206291bc56edSDimitry Andric // A ComplexPattern specifically declares how many results it fills in. 206391bc56edSDimitry Andric if (const ComplexPattern *CP = getComplexPatternInfo(CGP)) 206491bc56edSDimitry Andric return CP->getNumOperands(); 206591bc56edSDimitry Andric 206691bc56edSDimitry Andric // If MIOperandInfo is specified, that gives the count. 206791bc56edSDimitry Andric if (isLeaf()) { 206891bc56edSDimitry Andric DefInit *DI = dyn_cast<DefInit>(getLeafValue()); 206991bc56edSDimitry Andric if (DI && DI->getDef()->isSubClassOf("Operand")) { 207091bc56edSDimitry Andric DagInit *MIOps = DI->getDef()->getValueAsDag("MIOperandInfo"); 207191bc56edSDimitry Andric if (MIOps->getNumArgs()) 207291bc56edSDimitry Andric return MIOps->getNumArgs(); 207391bc56edSDimitry Andric } 207491bc56edSDimitry Andric } 207591bc56edSDimitry Andric 207691bc56edSDimitry Andric // Otherwise there is just one result. 207791bc56edSDimitry Andric return 1; 2078f22ef01cSRoman Divacky } 2079f22ef01cSRoman Divacky 2080f22ef01cSRoman Divacky /// NodeHasProperty - Return true if this node has the specified property. 2081f22ef01cSRoman Divacky bool TreePatternNode::NodeHasProperty(SDNP Property, 2082f22ef01cSRoman Divacky const CodeGenDAGPatterns &CGP) const { 2083f22ef01cSRoman Divacky if (isLeaf()) { 2084f22ef01cSRoman Divacky if (const ComplexPattern *CP = getComplexPatternInfo(CGP)) 2085f22ef01cSRoman Divacky return CP->hasProperty(Property); 2086da09e106SDimitry Andric 2087f22ef01cSRoman Divacky return false; 2088f22ef01cSRoman Divacky } 2089f22ef01cSRoman Divacky 2090da09e106SDimitry Andric if (Property != SDNPHasChain) { 2091da09e106SDimitry Andric // The chain proprety is already present on the different intrinsic node 2092da09e106SDimitry Andric // types (intrinsic_w_chain, intrinsic_void), and is not explicitly listed 2093da09e106SDimitry Andric // on the intrinsic. Anything else is specific to the individual intrinsic. 2094da09e106SDimitry Andric if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CGP)) 2095da09e106SDimitry Andric return Int->hasProperty(Property); 2096da09e106SDimitry Andric } 2097da09e106SDimitry Andric 2098da09e106SDimitry Andric if (!Operator->isSubClassOf("SDPatternOperator")) 2099da09e106SDimitry Andric return false; 2100f22ef01cSRoman Divacky 2101f22ef01cSRoman Divacky return CGP.getSDNodeInfo(Operator).hasProperty(Property); 2102f22ef01cSRoman Divacky } 2103f22ef01cSRoman Divacky 2104f22ef01cSRoman Divacky 2105f22ef01cSRoman Divacky 2106f22ef01cSRoman Divacky 2107f22ef01cSRoman Divacky /// TreeHasProperty - Return true if any node in this tree has the specified 2108f22ef01cSRoman Divacky /// property. 2109f22ef01cSRoman Divacky bool TreePatternNode::TreeHasProperty(SDNP Property, 2110f22ef01cSRoman Divacky const CodeGenDAGPatterns &CGP) const { 2111f22ef01cSRoman Divacky if (NodeHasProperty(Property, CGP)) 2112f22ef01cSRoman Divacky return true; 2113f22ef01cSRoman Divacky for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2114f22ef01cSRoman Divacky if (getChild(i)->TreeHasProperty(Property, CGP)) 2115f22ef01cSRoman Divacky return true; 2116f22ef01cSRoman Divacky return false; 2117f22ef01cSRoman Divacky } 2118f22ef01cSRoman Divacky 2119f22ef01cSRoman Divacky /// isCommutativeIntrinsic - Return true if the node corresponds to a 2120f22ef01cSRoman Divacky /// commutative intrinsic. 2121f22ef01cSRoman Divacky bool 2122f22ef01cSRoman Divacky TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const { 2123f22ef01cSRoman Divacky if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) 2124f22ef01cSRoman Divacky return Int->isCommutative; 2125f22ef01cSRoman Divacky return false; 2126f22ef01cSRoman Divacky } 2127f22ef01cSRoman Divacky 212839d628a0SDimitry Andric static bool isOperandClass(const TreePatternNode *N, StringRef Class) { 212939d628a0SDimitry Andric if (!N->isLeaf()) 213039d628a0SDimitry Andric return N->getOperator()->isSubClassOf(Class); 213139d628a0SDimitry Andric 213239d628a0SDimitry Andric DefInit *DI = dyn_cast<DefInit>(N->getLeafValue()); 213339d628a0SDimitry Andric if (DI && DI->getDef()->isSubClassOf(Class)) 213439d628a0SDimitry Andric return true; 213539d628a0SDimitry Andric 213639d628a0SDimitry Andric return false; 213739d628a0SDimitry Andric } 213839d628a0SDimitry Andric 213939d628a0SDimitry Andric static void emitTooManyOperandsError(TreePattern &TP, 214039d628a0SDimitry Andric StringRef InstName, 214139d628a0SDimitry Andric unsigned Expected, 214239d628a0SDimitry Andric unsigned Actual) { 214339d628a0SDimitry Andric TP.error("Instruction '" + InstName + "' was provided " + Twine(Actual) + 214439d628a0SDimitry Andric " operands but expected only " + Twine(Expected) + "!"); 214539d628a0SDimitry Andric } 214639d628a0SDimitry Andric 214739d628a0SDimitry Andric static void emitTooFewOperandsError(TreePattern &TP, 214839d628a0SDimitry Andric StringRef InstName, 214939d628a0SDimitry Andric unsigned Actual) { 215039d628a0SDimitry Andric TP.error("Instruction '" + InstName + 215139d628a0SDimitry Andric "' expects more than the provided " + Twine(Actual) + " operands!"); 215239d628a0SDimitry Andric } 2153f22ef01cSRoman Divacky 2154f22ef01cSRoman Divacky /// ApplyTypeConstraints - Apply all of the type constraints relevant to 2155f22ef01cSRoman Divacky /// this node and its children in the tree. This returns true if it makes a 21563861d79fSDimitry Andric /// change, false otherwise. If a type contradiction is found, flag an error. 2157f22ef01cSRoman Divacky bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { 21583861d79fSDimitry Andric if (TP.hasError()) 21593861d79fSDimitry Andric return false; 21603861d79fSDimitry Andric 2161f22ef01cSRoman Divacky CodeGenDAGPatterns &CDP = TP.getDAGPatterns(); 2162f22ef01cSRoman Divacky if (isLeaf()) { 21633861d79fSDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) { 2164f22ef01cSRoman Divacky // If it's a regclass or something else known, include the type. 2165f22ef01cSRoman Divacky bool MadeChange = false; 2166f22ef01cSRoman Divacky for (unsigned i = 0, e = Types.size(); i != e; ++i) 2167f22ef01cSRoman Divacky MadeChange |= UpdateNodeType(i, getImplicitType(DI->getDef(), i, 2168139f7f9bSDimitry Andric NotRegisters, 2169139f7f9bSDimitry Andric !hasName(), TP), TP); 2170f22ef01cSRoman Divacky return MadeChange; 2171f22ef01cSRoman Divacky } 2172f22ef01cSRoman Divacky 21733861d79fSDimitry Andric if (IntInit *II = dyn_cast<IntInit>(getLeafValue())) { 2174f22ef01cSRoman Divacky assert(Types.size() == 1 && "Invalid IntInit"); 2175f22ef01cSRoman Divacky 2176f22ef01cSRoman Divacky // Int inits are always integers. :) 21772cab237bSDimitry Andric bool MadeChange = TP.getInfer().EnforceInteger(Types[0]); 2178f22ef01cSRoman Divacky 21792cab237bSDimitry Andric if (!TP.getInfer().isConcrete(Types[0], false)) 2180f22ef01cSRoman Divacky return MadeChange; 2181f22ef01cSRoman Divacky 21822cab237bSDimitry Andric ValueTypeByHwMode VVT = TP.getInfer().getConcrete(Types[0], false); 21832cab237bSDimitry Andric for (auto &P : VVT) { 21842cab237bSDimitry Andric MVT::SimpleValueType VT = P.second.SimpleTy; 2185f22ef01cSRoman Divacky if (VT == MVT::iPTR || VT == MVT::iPTRAny) 21862cab237bSDimitry Andric continue; 2187f785676fSDimitry Andric unsigned Size = MVT(VT).getSizeInBits(); 2188f22ef01cSRoman Divacky // Make sure that the value is representable for this type. 21892cab237bSDimitry Andric if (Size >= 32) 21902cab237bSDimitry Andric continue; 21912cab237bSDimitry Andric // Check that the value doesn't use more bits than we have. It must 21922cab237bSDimitry Andric // either be a sign- or zero-extended equivalent of the original. 21933861d79fSDimitry Andric int64_t SignBitAndAbove = II->getValue() >> (Size - 1); 21942cab237bSDimitry Andric if (SignBitAndAbove == -1 || SignBitAndAbove == 0 || 21952cab237bSDimitry Andric SignBitAndAbove == 1) 21962cab237bSDimitry Andric continue; 2197f22ef01cSRoman Divacky 2198fe4fed2eSDimitry Andric TP.error("Integer value '" + Twine(II->getValue()) + 21992cab237bSDimitry Andric "' is out of range for type '" + getEnumName(VT) + "'!"); 22002cab237bSDimitry Andric break; 2201f22ef01cSRoman Divacky } 22022cab237bSDimitry Andric return MadeChange; 22032cab237bSDimitry Andric } 22042cab237bSDimitry Andric 2205f22ef01cSRoman Divacky return false; 2206f22ef01cSRoman Divacky } 2207f22ef01cSRoman Divacky 2208f22ef01cSRoman Divacky // special handling for set, which isn't really an SDNode. 2209f22ef01cSRoman Divacky if (getOperator()->getName() == "set") { 2210f22ef01cSRoman Divacky assert(getNumTypes() == 0 && "Set doesn't produce a value"); 2211f22ef01cSRoman Divacky assert(getNumChildren() >= 2 && "Missing RHS of a set?"); 2212f22ef01cSRoman Divacky unsigned NC = getNumChildren(); 2213f22ef01cSRoman Divacky 2214f22ef01cSRoman Divacky TreePatternNode *SetVal = getChild(NC-1); 2215f22ef01cSRoman Divacky bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters); 2216f22ef01cSRoman Divacky 2217f22ef01cSRoman Divacky for (unsigned i = 0; i < NC-1; ++i) { 2218f22ef01cSRoman Divacky TreePatternNode *Child = getChild(i); 2219f22ef01cSRoman Divacky MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); 2220f22ef01cSRoman Divacky 2221f22ef01cSRoman Divacky // Types of operands must match. 2222f22ef01cSRoman Divacky MadeChange |= Child->UpdateNodeType(0, SetVal->getExtType(i), TP); 2223f22ef01cSRoman Divacky MadeChange |= SetVal->UpdateNodeType(i, Child->getExtType(0), TP); 2224f22ef01cSRoman Divacky } 2225f22ef01cSRoman Divacky return MadeChange; 2226f22ef01cSRoman Divacky } 2227f22ef01cSRoman Divacky 2228f22ef01cSRoman Divacky if (getOperator()->getName() == "implicit") { 2229f22ef01cSRoman Divacky assert(getNumTypes() == 0 && "Node doesn't produce a value"); 2230f22ef01cSRoman Divacky 2231f22ef01cSRoman Divacky bool MadeChange = false; 2232f22ef01cSRoman Divacky for (unsigned i = 0; i < getNumChildren(); ++i) 22332cab237bSDimitry Andric MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); 2234f22ef01cSRoman Divacky return MadeChange; 2235f22ef01cSRoman Divacky } 2236f22ef01cSRoman Divacky 2237f22ef01cSRoman Divacky if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) { 2238f22ef01cSRoman Divacky bool MadeChange = false; 2239f22ef01cSRoman Divacky 2240f22ef01cSRoman Divacky // Apply the result type to the node. 2241f22ef01cSRoman Divacky unsigned NumRetVTs = Int->IS.RetVTs.size(); 2242f22ef01cSRoman Divacky unsigned NumParamVTs = Int->IS.ParamVTs.size(); 2243f22ef01cSRoman Divacky 2244f22ef01cSRoman Divacky for (unsigned i = 0, e = NumRetVTs; i != e; ++i) 2245f22ef01cSRoman Divacky MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP); 2246f22ef01cSRoman Divacky 22473861d79fSDimitry Andric if (getNumChildren() != NumParamVTs + 1) { 2248fe4fed2eSDimitry Andric TP.error("Intrinsic '" + Int->Name + "' expects " + Twine(NumParamVTs) + 2249fe4fed2eSDimitry Andric " operands, not " + Twine(getNumChildren() - 1) + " operands!"); 22503861d79fSDimitry Andric return false; 22513861d79fSDimitry Andric } 2252f22ef01cSRoman Divacky 2253f22ef01cSRoman Divacky // Apply type info to the intrinsic ID. 2254f22ef01cSRoman Divacky MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP); 2255f22ef01cSRoman Divacky 2256f22ef01cSRoman Divacky for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i) { 2257f22ef01cSRoman Divacky MadeChange |= getChild(i+1)->ApplyTypeConstraints(TP, NotRegisters); 2258f22ef01cSRoman Divacky 2259f22ef01cSRoman Divacky MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i]; 2260f22ef01cSRoman Divacky assert(getChild(i+1)->getNumTypes() == 1 && "Unhandled case"); 2261f22ef01cSRoman Divacky MadeChange |= getChild(i+1)->UpdateNodeType(0, OpVT, TP); 2262f22ef01cSRoman Divacky } 2263f22ef01cSRoman Divacky return MadeChange; 2264f22ef01cSRoman Divacky } 2265f22ef01cSRoman Divacky 2266f22ef01cSRoman Divacky if (getOperator()->isSubClassOf("SDNode")) { 2267f22ef01cSRoman Divacky const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator()); 2268f22ef01cSRoman Divacky 2269f22ef01cSRoman Divacky // Check that the number of operands is sane. Negative operands -> varargs. 2270f22ef01cSRoman Divacky if (NI.getNumOperands() >= 0 && 22713861d79fSDimitry Andric getNumChildren() != (unsigned)NI.getNumOperands()) { 2272f22ef01cSRoman Divacky TP.error(getOperator()->getName() + " node requires exactly " + 2273fe4fed2eSDimitry Andric Twine(NI.getNumOperands()) + " operands!"); 22743861d79fSDimitry Andric return false; 22753861d79fSDimitry Andric } 2276f22ef01cSRoman Divacky 22772cab237bSDimitry Andric bool MadeChange = false; 2278f22ef01cSRoman Divacky for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2279f22ef01cSRoman Divacky MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); 22802cab237bSDimitry Andric MadeChange |= NI.ApplyTypeConstraints(this, TP); 2281f22ef01cSRoman Divacky return MadeChange; 2282f22ef01cSRoman Divacky } 2283f22ef01cSRoman Divacky 2284f22ef01cSRoman Divacky if (getOperator()->isSubClassOf("Instruction")) { 2285f22ef01cSRoman Divacky const DAGInstruction &Inst = CDP.getInstruction(getOperator()); 2286f22ef01cSRoman Divacky CodeGenInstruction &InstInfo = 2287f22ef01cSRoman Divacky CDP.getTargetInfo().getInstruction(getOperator()); 2288f22ef01cSRoman Divacky 2289f22ef01cSRoman Divacky bool MadeChange = false; 2290f22ef01cSRoman Divacky 2291f22ef01cSRoman Divacky // Apply the result types to the node, these come from the things in the 2292f22ef01cSRoman Divacky // (outs) list of the instruction. 2293ff0cc061SDimitry Andric unsigned NumResultsToAdd = std::min(InstInfo.Operands.NumDefs, 2294ff0cc061SDimitry Andric Inst.getNumResults()); 2295139f7f9bSDimitry Andric for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) 2296139f7f9bSDimitry Andric MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP); 2297f22ef01cSRoman Divacky 2298f22ef01cSRoman Divacky // If the instruction has implicit defs, we apply the first one as a result. 2299f22ef01cSRoman Divacky // FIXME: This sucks, it should apply all implicit defs. 2300f22ef01cSRoman Divacky if (!InstInfo.ImplicitDefs.empty()) { 2301f22ef01cSRoman Divacky unsigned ResNo = NumResultsToAdd; 2302f22ef01cSRoman Divacky 2303f22ef01cSRoman Divacky // FIXME: Generalize to multiple possible types and multiple possible 2304f22ef01cSRoman Divacky // ImplicitDefs. 2305f22ef01cSRoman Divacky MVT::SimpleValueType VT = 2306f22ef01cSRoman Divacky InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()); 2307f22ef01cSRoman Divacky 2308f22ef01cSRoman Divacky if (VT != MVT::Other) 2309f22ef01cSRoman Divacky MadeChange |= UpdateNodeType(ResNo, VT, TP); 2310f22ef01cSRoman Divacky } 2311f22ef01cSRoman Divacky 2312f22ef01cSRoman Divacky // If this is an INSERT_SUBREG, constrain the source and destination VTs to 2313f22ef01cSRoman Divacky // be the same. 2314f22ef01cSRoman Divacky if (getOperator()->getName() == "INSERT_SUBREG") { 2315f22ef01cSRoman Divacky assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled"); 2316f22ef01cSRoman Divacky MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP); 2317f22ef01cSRoman Divacky MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP); 231839d628a0SDimitry Andric } else if (getOperator()->getName() == "REG_SEQUENCE") { 231939d628a0SDimitry Andric // We need to do extra, custom typechecking for REG_SEQUENCE since it is 232039d628a0SDimitry Andric // variadic. 232139d628a0SDimitry Andric 232239d628a0SDimitry Andric unsigned NChild = getNumChildren(); 232339d628a0SDimitry Andric if (NChild < 3) { 232439d628a0SDimitry Andric TP.error("REG_SEQUENCE requires at least 3 operands!"); 232539d628a0SDimitry Andric return false; 232639d628a0SDimitry Andric } 232739d628a0SDimitry Andric 232839d628a0SDimitry Andric if (NChild % 2 == 0) { 232939d628a0SDimitry Andric TP.error("REG_SEQUENCE requires an odd number of operands!"); 233039d628a0SDimitry Andric return false; 233139d628a0SDimitry Andric } 233239d628a0SDimitry Andric 233339d628a0SDimitry Andric if (!isOperandClass(getChild(0), "RegisterClass")) { 233439d628a0SDimitry Andric TP.error("REG_SEQUENCE requires a RegisterClass for first operand!"); 233539d628a0SDimitry Andric return false; 233639d628a0SDimitry Andric } 233739d628a0SDimitry Andric 233839d628a0SDimitry Andric for (unsigned I = 1; I < NChild; I += 2) { 233939d628a0SDimitry Andric TreePatternNode *SubIdxChild = getChild(I + 1); 234039d628a0SDimitry Andric if (!isOperandClass(SubIdxChild, "SubRegIndex")) { 234139d628a0SDimitry Andric TP.error("REG_SEQUENCE requires a SubRegIndex for operand " + 2342fe4fed2eSDimitry Andric Twine(I + 1) + "!"); 234339d628a0SDimitry Andric return false; 234439d628a0SDimitry Andric } 234539d628a0SDimitry Andric } 2346f22ef01cSRoman Divacky } 2347f22ef01cSRoman Divacky 2348f22ef01cSRoman Divacky unsigned ChildNo = 0; 2349f22ef01cSRoman Divacky for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) { 2350f22ef01cSRoman Divacky Record *OperandNode = Inst.getOperand(i); 2351f22ef01cSRoman Divacky 2352f22ef01cSRoman Divacky // If the instruction expects a predicate or optional def operand, we 2353f22ef01cSRoman Divacky // codegen this by setting the operand to it's default value if it has a 2354f22ef01cSRoman Divacky // non-empty DefaultOps field. 23553861d79fSDimitry Andric if (OperandNode->isSubClassOf("OperandWithDefaultOps") && 2356f22ef01cSRoman Divacky !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) 2357f22ef01cSRoman Divacky continue; 2358f22ef01cSRoman Divacky 2359f22ef01cSRoman Divacky // Verify that we didn't run out of provided operands. 23603861d79fSDimitry Andric if (ChildNo >= getNumChildren()) { 236139d628a0SDimitry Andric emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren()); 23623861d79fSDimitry Andric return false; 23633861d79fSDimitry Andric } 2364f22ef01cSRoman Divacky 2365f22ef01cSRoman Divacky TreePatternNode *Child = getChild(ChildNo++); 2366f22ef01cSRoman Divacky unsigned ChildResNo = 0; // Instructions always use res #0 of their op. 2367f22ef01cSRoman Divacky 2368139f7f9bSDimitry Andric // If the operand has sub-operands, they may be provided by distinct 2369139f7f9bSDimitry Andric // child patterns, so attempt to match each sub-operand separately. 2370139f7f9bSDimitry Andric if (OperandNode->isSubClassOf("Operand")) { 2371139f7f9bSDimitry Andric DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo"); 2372139f7f9bSDimitry Andric if (unsigned NumArgs = MIOpInfo->getNumArgs()) { 2373139f7f9bSDimitry Andric // But don't do that if the whole operand is being provided by 237491bc56edSDimitry Andric // a single ComplexPattern-related Operand. 237591bc56edSDimitry Andric 237691bc56edSDimitry Andric if (Child->getNumMIResults(CDP) < NumArgs) { 2377139f7f9bSDimitry Andric // Match first sub-operand against the child we already have. 2378139f7f9bSDimitry Andric Record *SubRec = cast<DefInit>(MIOpInfo->getArg(0))->getDef(); 2379139f7f9bSDimitry Andric MadeChange |= 2380139f7f9bSDimitry Andric Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP); 2381dff0c46cSDimitry Andric 2382139f7f9bSDimitry Andric // And the remaining sub-operands against subsequent children. 2383139f7f9bSDimitry Andric for (unsigned Arg = 1; Arg < NumArgs; ++Arg) { 2384139f7f9bSDimitry Andric if (ChildNo >= getNumChildren()) { 238539d628a0SDimitry Andric emitTooFewOperandsError(TP, getOperator()->getName(), 238639d628a0SDimitry Andric getNumChildren()); 2387139f7f9bSDimitry Andric return false; 2388139f7f9bSDimitry Andric } 2389139f7f9bSDimitry Andric Child = getChild(ChildNo++); 2390139f7f9bSDimitry Andric 2391139f7f9bSDimitry Andric SubRec = cast<DefInit>(MIOpInfo->getArg(Arg))->getDef(); 2392139f7f9bSDimitry Andric MadeChange |= 2393139f7f9bSDimitry Andric Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP); 2394139f7f9bSDimitry Andric } 2395139f7f9bSDimitry Andric continue; 2396139f7f9bSDimitry Andric } 2397139f7f9bSDimitry Andric } 2398139f7f9bSDimitry Andric } 2399139f7f9bSDimitry Andric 2400139f7f9bSDimitry Andric // If we didn't match by pieces above, attempt to match the whole 2401139f7f9bSDimitry Andric // operand now. 2402139f7f9bSDimitry Andric MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP); 2403f22ef01cSRoman Divacky } 2404f22ef01cSRoman Divacky 240539d628a0SDimitry Andric if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) { 240639d628a0SDimitry Andric emitTooManyOperandsError(TP, getOperator()->getName(), 240739d628a0SDimitry Andric ChildNo, getNumChildren()); 24083861d79fSDimitry Andric return false; 24093861d79fSDimitry Andric } 2410f22ef01cSRoman Divacky 2411139f7f9bSDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2412139f7f9bSDimitry Andric MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); 2413f22ef01cSRoman Divacky return MadeChange; 2414f22ef01cSRoman Divacky } 2415f22ef01cSRoman Divacky 241691bc56edSDimitry Andric if (getOperator()->isSubClassOf("ComplexPattern")) { 241791bc56edSDimitry Andric bool MadeChange = false; 241891bc56edSDimitry Andric 241991bc56edSDimitry Andric for (unsigned i = 0; i < getNumChildren(); ++i) 242091bc56edSDimitry Andric MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); 242191bc56edSDimitry Andric 242291bc56edSDimitry Andric return MadeChange; 242391bc56edSDimitry Andric } 242491bc56edSDimitry Andric 2425f22ef01cSRoman Divacky assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); 2426f22ef01cSRoman Divacky 2427f22ef01cSRoman Divacky // Node transforms always take one operand. 24283861d79fSDimitry Andric if (getNumChildren() != 1) { 2429f22ef01cSRoman Divacky TP.error("Node transform '" + getOperator()->getName() + 2430f22ef01cSRoman Divacky "' requires one operand!"); 24313861d79fSDimitry Andric return false; 24323861d79fSDimitry Andric } 2433f22ef01cSRoman Divacky 2434f22ef01cSRoman Divacky bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters); 2435f22ef01cSRoman Divacky return MadeChange; 2436f22ef01cSRoman Divacky } 2437f22ef01cSRoman Divacky 2438f22ef01cSRoman Divacky /// OnlyOnRHSOfCommutative - Return true if this value is only allowed on the 2439f22ef01cSRoman Divacky /// RHS of a commutative operation, not the on LHS. 2440f22ef01cSRoman Divacky static bool OnlyOnRHSOfCommutative(TreePatternNode *N) { 2441f22ef01cSRoman Divacky if (!N->isLeaf() && N->getOperator()->getName() == "imm") 2442f22ef01cSRoman Divacky return true; 24433861d79fSDimitry Andric if (N->isLeaf() && isa<IntInit>(N->getLeafValue())) 2444f22ef01cSRoman Divacky return true; 2445f22ef01cSRoman Divacky return false; 2446f22ef01cSRoman Divacky } 2447f22ef01cSRoman Divacky 2448f22ef01cSRoman Divacky 2449f22ef01cSRoman Divacky /// canPatternMatch - If it is impossible for this pattern to match on this 2450f22ef01cSRoman Divacky /// target, fill in Reason and return false. Otherwise, return true. This is 2451f22ef01cSRoman Divacky /// used as a sanity check for .td files (to prevent people from writing stuff 2452f22ef01cSRoman Divacky /// that can never possibly work), and to prevent the pattern permuter from 2453f22ef01cSRoman Divacky /// generating stuff that is useless. 2454f22ef01cSRoman Divacky bool TreePatternNode::canPatternMatch(std::string &Reason, 2455f22ef01cSRoman Divacky const CodeGenDAGPatterns &CDP) { 2456f22ef01cSRoman Divacky if (isLeaf()) return true; 2457f22ef01cSRoman Divacky 2458f22ef01cSRoman Divacky for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 2459f22ef01cSRoman Divacky if (!getChild(i)->canPatternMatch(Reason, CDP)) 2460f22ef01cSRoman Divacky return false; 2461f22ef01cSRoman Divacky 2462f22ef01cSRoman Divacky // If this is an intrinsic, handle cases that would make it not match. For 2463f22ef01cSRoman Divacky // example, if an operand is required to be an immediate. 2464f22ef01cSRoman Divacky if (getOperator()->isSubClassOf("Intrinsic")) { 2465f22ef01cSRoman Divacky // TODO: 2466f22ef01cSRoman Divacky return true; 2467f22ef01cSRoman Divacky } 2468f22ef01cSRoman Divacky 246991bc56edSDimitry Andric if (getOperator()->isSubClassOf("ComplexPattern")) 247091bc56edSDimitry Andric return true; 247191bc56edSDimitry Andric 2472f22ef01cSRoman Divacky // If this node is a commutative operator, check that the LHS isn't an 2473f22ef01cSRoman Divacky // immediate. 2474f22ef01cSRoman Divacky const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator()); 2475f22ef01cSRoman Divacky bool isCommIntrinsic = isCommutativeIntrinsic(CDP); 2476f22ef01cSRoman Divacky if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) { 2477f22ef01cSRoman Divacky // Scan all of the operands of the node and make sure that only the last one 2478f22ef01cSRoman Divacky // is a constant node, unless the RHS also is. 2479f22ef01cSRoman Divacky if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) { 2480d88c1a5aSDimitry Andric unsigned Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id. 2481f22ef01cSRoman Divacky for (unsigned i = Skip, e = getNumChildren()-1; i != e; ++i) 2482f22ef01cSRoman Divacky if (OnlyOnRHSOfCommutative(getChild(i))) { 2483f22ef01cSRoman Divacky Reason="Immediate value must be on the RHS of commutative operators!"; 2484f22ef01cSRoman Divacky return false; 2485f22ef01cSRoman Divacky } 2486f22ef01cSRoman Divacky } 2487f22ef01cSRoman Divacky } 2488f22ef01cSRoman Divacky 2489f22ef01cSRoman Divacky return true; 2490f22ef01cSRoman Divacky } 2491f22ef01cSRoman Divacky 2492f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 2493f22ef01cSRoman Divacky // TreePattern implementation 2494f22ef01cSRoman Divacky // 2495f22ef01cSRoman Divacky 2496f22ef01cSRoman Divacky TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, 24973861d79fSDimitry Andric CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), 24982cab237bSDimitry Andric isInputPattern(isInput), HasError(false), 24992cab237bSDimitry Andric Infer(*this) { 250097bc6c73SDimitry Andric for (Init *I : RawPat->getValues()) 250197bc6c73SDimitry Andric Trees.push_back(ParseTreePattern(I, "")); 2502f22ef01cSRoman Divacky } 2503f22ef01cSRoman Divacky 2504f22ef01cSRoman Divacky TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput, 25053861d79fSDimitry Andric CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), 25062cab237bSDimitry Andric isInputPattern(isInput), HasError(false), 25072cab237bSDimitry Andric Infer(*this) { 2508f22ef01cSRoman Divacky Trees.push_back(ParseTreePattern(Pat, "")); 2509f22ef01cSRoman Divacky } 2510f22ef01cSRoman Divacky 2511f22ef01cSRoman Divacky TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, 25123861d79fSDimitry Andric CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), 25132cab237bSDimitry Andric isInputPattern(isInput), HasError(false), 25142cab237bSDimitry Andric Infer(*this) { 2515f22ef01cSRoman Divacky Trees.push_back(Pat); 2516f22ef01cSRoman Divacky } 2517f22ef01cSRoman Divacky 251839d628a0SDimitry Andric void TreePattern::error(const Twine &Msg) { 25193861d79fSDimitry Andric if (HasError) 25203861d79fSDimitry Andric return; 2521f22ef01cSRoman Divacky dump(); 25223861d79fSDimitry Andric PrintError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg); 25233861d79fSDimitry Andric HasError = true; 2524f22ef01cSRoman Divacky } 2525f22ef01cSRoman Divacky 2526f22ef01cSRoman Divacky void TreePattern::ComputeNamedNodes() { 25277d523365SDimitry Andric for (TreePatternNode *Tree : Trees) 25287d523365SDimitry Andric ComputeNamedNodes(Tree); 2529f22ef01cSRoman Divacky } 2530f22ef01cSRoman Divacky 2531f22ef01cSRoman Divacky void TreePattern::ComputeNamedNodes(TreePatternNode *N) { 2532f22ef01cSRoman Divacky if (!N->getName().empty()) 2533f22ef01cSRoman Divacky NamedNodes[N->getName()].push_back(N); 2534f22ef01cSRoman Divacky 2535f22ef01cSRoman Divacky for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) 2536f22ef01cSRoman Divacky ComputeNamedNodes(N->getChild(i)); 2537f22ef01cSRoman Divacky } 2538f22ef01cSRoman Divacky 2539f22ef01cSRoman Divacky 2540f22ef01cSRoman Divacky TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ 25413861d79fSDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(TheInit)) { 2542f22ef01cSRoman Divacky Record *R = DI->getDef(); 2543f22ef01cSRoman Divacky 2544f22ef01cSRoman Divacky // Direct reference to a leaf DagNode or PatFrag? Turn it into a 254517a519f9SDimitry Andric // TreePatternNode of its own. For example: 2546f22ef01cSRoman Divacky /// (foo GPR, imm) -> (foo GPR, (imm)) 2547f22ef01cSRoman Divacky if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) 25486122f3e6SDimitry Andric return ParseTreePattern( 2549d88c1a5aSDimitry Andric DagInit::get(DI, nullptr, 2550d88c1a5aSDimitry Andric std::vector<std::pair<Init*, StringInit*> >()), 2551f22ef01cSRoman Divacky OpName); 2552f22ef01cSRoman Divacky 2553f22ef01cSRoman Divacky // Input argument? 2554f22ef01cSRoman Divacky TreePatternNode *Res = new TreePatternNode(DI, 1); 2555f22ef01cSRoman Divacky if (R->getName() == "node" && !OpName.empty()) { 2556f22ef01cSRoman Divacky if (OpName.empty()) 2557f22ef01cSRoman Divacky error("'node' argument requires a name to match with operand list"); 2558f22ef01cSRoman Divacky Args.push_back(OpName); 2559f22ef01cSRoman Divacky } 2560f22ef01cSRoman Divacky 2561f22ef01cSRoman Divacky Res->setName(OpName); 2562f22ef01cSRoman Divacky return Res; 2563f22ef01cSRoman Divacky } 2564f22ef01cSRoman Divacky 2565139f7f9bSDimitry Andric // ?:$name or just $name. 2566ff0cc061SDimitry Andric if (isa<UnsetInit>(TheInit)) { 2567139f7f9bSDimitry Andric if (OpName.empty()) 2568139f7f9bSDimitry Andric error("'?' argument requires a name to match with operand list"); 2569139f7f9bSDimitry Andric TreePatternNode *Res = new TreePatternNode(TheInit, 1); 2570139f7f9bSDimitry Andric Args.push_back(OpName); 2571139f7f9bSDimitry Andric Res->setName(OpName); 2572139f7f9bSDimitry Andric return Res; 2573139f7f9bSDimitry Andric } 2574139f7f9bSDimitry Andric 25753861d79fSDimitry Andric if (IntInit *II = dyn_cast<IntInit>(TheInit)) { 2576f22ef01cSRoman Divacky if (!OpName.empty()) 2577f22ef01cSRoman Divacky error("Constant int argument should not have a name!"); 2578f22ef01cSRoman Divacky return new TreePatternNode(II, 1); 2579f22ef01cSRoman Divacky } 2580f22ef01cSRoman Divacky 25813861d79fSDimitry Andric if (BitsInit *BI = dyn_cast<BitsInit>(TheInit)) { 2582f22ef01cSRoman Divacky // Turn this into an IntInit. 25836122f3e6SDimitry Andric Init *II = BI->convertInitializerTo(IntRecTy::get()); 258491bc56edSDimitry Andric if (!II || !isa<IntInit>(II)) 2585f22ef01cSRoman Divacky error("Bits value must be constants!"); 2586f22ef01cSRoman Divacky return ParseTreePattern(II, OpName); 2587f22ef01cSRoman Divacky } 2588f22ef01cSRoman Divacky 25893861d79fSDimitry Andric DagInit *Dag = dyn_cast<DagInit>(TheInit); 2590f22ef01cSRoman Divacky if (!Dag) { 25917a7e6055SDimitry Andric TheInit->print(errs()); 2592f22ef01cSRoman Divacky error("Pattern has unexpected init kind!"); 2593f22ef01cSRoman Divacky } 25943861d79fSDimitry Andric DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator()); 2595f22ef01cSRoman Divacky if (!OpDef) error("Pattern has unexpected operator type!"); 2596f22ef01cSRoman Divacky Record *Operator = OpDef->getDef(); 2597f22ef01cSRoman Divacky 2598f22ef01cSRoman Divacky if (Operator->isSubClassOf("ValueType")) { 2599f22ef01cSRoman Divacky // If the operator is a ValueType, then this must be "type cast" of a leaf 2600f22ef01cSRoman Divacky // node. 2601f22ef01cSRoman Divacky if (Dag->getNumArgs() != 1) 2602f22ef01cSRoman Divacky error("Type cast only takes one operand!"); 2603f22ef01cSRoman Divacky 2604d88c1a5aSDimitry Andric TreePatternNode *New = ParseTreePattern(Dag->getArg(0), 2605d88c1a5aSDimitry Andric Dag->getArgNameStr(0)); 2606f22ef01cSRoman Divacky 2607f22ef01cSRoman Divacky // Apply the type cast. 2608f22ef01cSRoman Divacky assert(New->getNumTypes() == 1 && "FIXME: Unhandled"); 26092cab237bSDimitry Andric const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes(); 26102cab237bSDimitry Andric New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this); 2611f22ef01cSRoman Divacky 2612f22ef01cSRoman Divacky if (!OpName.empty()) 2613f22ef01cSRoman Divacky error("ValueType cast should not have a name!"); 2614f22ef01cSRoman Divacky return New; 2615f22ef01cSRoman Divacky } 2616f22ef01cSRoman Divacky 2617f22ef01cSRoman Divacky // Verify that this is something that makes sense for an operator. 2618f22ef01cSRoman Divacky if (!Operator->isSubClassOf("PatFrag") && 2619f22ef01cSRoman Divacky !Operator->isSubClassOf("SDNode") && 2620f22ef01cSRoman Divacky !Operator->isSubClassOf("Instruction") && 2621f22ef01cSRoman Divacky !Operator->isSubClassOf("SDNodeXForm") && 2622f22ef01cSRoman Divacky !Operator->isSubClassOf("Intrinsic") && 262391bc56edSDimitry Andric !Operator->isSubClassOf("ComplexPattern") && 2624f22ef01cSRoman Divacky Operator->getName() != "set" && 2625f22ef01cSRoman Divacky Operator->getName() != "implicit") 2626f22ef01cSRoman Divacky error("Unrecognized node '" + Operator->getName() + "'!"); 2627f22ef01cSRoman Divacky 2628f22ef01cSRoman Divacky // Check to see if this is something that is illegal in an input pattern. 2629f22ef01cSRoman Divacky if (isInputPattern) { 2630f22ef01cSRoman Divacky if (Operator->isSubClassOf("Instruction") || 2631f22ef01cSRoman Divacky Operator->isSubClassOf("SDNodeXForm")) 2632f22ef01cSRoman Divacky error("Cannot use '" + Operator->getName() + "' in an input pattern!"); 2633f22ef01cSRoman Divacky } else { 2634f22ef01cSRoman Divacky if (Operator->isSubClassOf("Intrinsic")) 2635f22ef01cSRoman Divacky error("Cannot use '" + Operator->getName() + "' in an output pattern!"); 2636f22ef01cSRoman Divacky 2637f22ef01cSRoman Divacky if (Operator->isSubClassOf("SDNode") && 2638f22ef01cSRoman Divacky Operator->getName() != "imm" && 2639f22ef01cSRoman Divacky Operator->getName() != "fpimm" && 2640f22ef01cSRoman Divacky Operator->getName() != "tglobaltlsaddr" && 2641f22ef01cSRoman Divacky Operator->getName() != "tconstpool" && 2642f22ef01cSRoman Divacky Operator->getName() != "tjumptable" && 2643f22ef01cSRoman Divacky Operator->getName() != "tframeindex" && 2644f22ef01cSRoman Divacky Operator->getName() != "texternalsym" && 2645f22ef01cSRoman Divacky Operator->getName() != "tblockaddress" && 2646f22ef01cSRoman Divacky Operator->getName() != "tglobaladdr" && 2647f22ef01cSRoman Divacky Operator->getName() != "bb" && 26483dac3a9bSDimitry Andric Operator->getName() != "vt" && 26493dac3a9bSDimitry Andric Operator->getName() != "mcsym") 2650f22ef01cSRoman Divacky error("Cannot use '" + Operator->getName() + "' in an output pattern!"); 2651f22ef01cSRoman Divacky } 2652f22ef01cSRoman Divacky 2653f22ef01cSRoman Divacky std::vector<TreePatternNode*> Children; 2654f22ef01cSRoman Divacky 2655f22ef01cSRoman Divacky // Parse all the operands. 2656f22ef01cSRoman Divacky for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) 2657d88c1a5aSDimitry Andric Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgNameStr(i))); 2658f22ef01cSRoman Divacky 2659f22ef01cSRoman Divacky // If the operator is an intrinsic, then this is just syntactic sugar for for 2660f22ef01cSRoman Divacky // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and 2661f22ef01cSRoman Divacky // convert the intrinsic name to a number. 2662f22ef01cSRoman Divacky if (Operator->isSubClassOf("Intrinsic")) { 2663f22ef01cSRoman Divacky const CodeGenIntrinsic &Int = getDAGPatterns().getIntrinsic(Operator); 2664f22ef01cSRoman Divacky unsigned IID = getDAGPatterns().getIntrinsicID(Operator)+1; 2665f22ef01cSRoman Divacky 2666f22ef01cSRoman Divacky // If this intrinsic returns void, it must have side-effects and thus a 2667f22ef01cSRoman Divacky // chain. 2668f22ef01cSRoman Divacky if (Int.IS.RetVTs.empty()) 2669f22ef01cSRoman Divacky Operator = getDAGPatterns().get_intrinsic_void_sdnode(); 2670f22ef01cSRoman Divacky else if (Int.ModRef != CodeGenIntrinsic::NoMem) 2671f22ef01cSRoman Divacky // Has side-effects, requires chain. 2672f22ef01cSRoman Divacky Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode(); 2673f22ef01cSRoman Divacky else // Otherwise, no chain. 2674f22ef01cSRoman Divacky Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode(); 2675f22ef01cSRoman Divacky 26766122f3e6SDimitry Andric TreePatternNode *IIDNode = new TreePatternNode(IntInit::get(IID), 1); 2677f22ef01cSRoman Divacky Children.insert(Children.begin(), IIDNode); 2678f22ef01cSRoman Divacky } 2679f22ef01cSRoman Divacky 268091bc56edSDimitry Andric if (Operator->isSubClassOf("ComplexPattern")) { 268191bc56edSDimitry Andric for (unsigned i = 0; i < Children.size(); ++i) { 268291bc56edSDimitry Andric TreePatternNode *Child = Children[i]; 268391bc56edSDimitry Andric 268491bc56edSDimitry Andric if (Child->getName().empty()) 268591bc56edSDimitry Andric error("All arguments to a ComplexPattern must be named"); 268691bc56edSDimitry Andric 268791bc56edSDimitry Andric // Check that the ComplexPattern uses are consistent: "(MY_PAT $a, $b)" 268891bc56edSDimitry Andric // and "(MY_PAT $b, $a)" should not be allowed in the same pattern; 268991bc56edSDimitry Andric // neither should "(MY_PAT_1 $a, $b)" and "(MY_PAT_2 $a, $b)". 269091bc56edSDimitry Andric auto OperandId = std::make_pair(Operator, i); 269191bc56edSDimitry Andric auto PrevOp = ComplexPatternOperands.find(Child->getName()); 269291bc56edSDimitry Andric if (PrevOp != ComplexPatternOperands.end()) { 269391bc56edSDimitry Andric if (PrevOp->getValue() != OperandId) 269491bc56edSDimitry Andric error("All ComplexPattern operands must appear consistently: " 269591bc56edSDimitry Andric "in the same order in just one ComplexPattern instance."); 269691bc56edSDimitry Andric } else 269791bc56edSDimitry Andric ComplexPatternOperands[Child->getName()] = OperandId; 269891bc56edSDimitry Andric } 269991bc56edSDimitry Andric } 270091bc56edSDimitry Andric 2701f22ef01cSRoman Divacky unsigned NumResults = GetNumNodeResults(Operator, CDP); 2702f22ef01cSRoman Divacky TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults); 2703f22ef01cSRoman Divacky Result->setName(OpName); 2704f22ef01cSRoman Divacky 2705d88c1a5aSDimitry Andric if (Dag->getName()) { 2706f22ef01cSRoman Divacky assert(Result->getName().empty()); 2707d88c1a5aSDimitry Andric Result->setName(Dag->getNameStr()); 2708f22ef01cSRoman Divacky } 2709f22ef01cSRoman Divacky return Result; 2710f22ef01cSRoman Divacky } 2711f22ef01cSRoman Divacky 2712f22ef01cSRoman Divacky /// SimplifyTree - See if we can simplify this tree to eliminate something that 2713f22ef01cSRoman Divacky /// will never match in favor of something obvious that will. This is here 2714f22ef01cSRoman Divacky /// strictly as a convenience to target authors because it allows them to write 2715f22ef01cSRoman Divacky /// more type generic things and have useless type casts fold away. 2716f22ef01cSRoman Divacky /// 2717f22ef01cSRoman Divacky /// This returns true if any change is made. 2718f22ef01cSRoman Divacky static bool SimplifyTree(TreePatternNode *&N) { 2719f22ef01cSRoman Divacky if (N->isLeaf()) 2720f22ef01cSRoman Divacky return false; 2721f22ef01cSRoman Divacky 2722f22ef01cSRoman Divacky // If we have a bitconvert with a resolved type and if the source and 2723f22ef01cSRoman Divacky // destination types are the same, then the bitconvert is useless, remove it. 2724f22ef01cSRoman Divacky if (N->getOperator()->getName() == "bitconvert" && 27252cab237bSDimitry Andric N->getExtType(0).isValueTypeByHwMode(false) && 2726f22ef01cSRoman Divacky N->getExtType(0) == N->getChild(0)->getExtType(0) && 2727f22ef01cSRoman Divacky N->getName().empty()) { 2728f22ef01cSRoman Divacky N = N->getChild(0); 2729f22ef01cSRoman Divacky SimplifyTree(N); 2730f22ef01cSRoman Divacky return true; 2731f22ef01cSRoman Divacky } 2732f22ef01cSRoman Divacky 2733f22ef01cSRoman Divacky // Walk all children. 2734f22ef01cSRoman Divacky bool MadeChange = false; 2735f22ef01cSRoman Divacky for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { 2736f22ef01cSRoman Divacky TreePatternNode *Child = N->getChild(i); 2737f22ef01cSRoman Divacky MadeChange |= SimplifyTree(Child); 2738f22ef01cSRoman Divacky N->setChild(i, Child); 2739f22ef01cSRoman Divacky } 2740f22ef01cSRoman Divacky return MadeChange; 2741f22ef01cSRoman Divacky } 2742f22ef01cSRoman Divacky 2743f22ef01cSRoman Divacky 2744f22ef01cSRoman Divacky 2745f22ef01cSRoman Divacky /// InferAllTypes - Infer/propagate as many types throughout the expression 2746f22ef01cSRoman Divacky /// patterns as possible. Return true if all types are inferred, false 27473861d79fSDimitry Andric /// otherwise. Flags an error if a type contradiction is found. 2748f22ef01cSRoman Divacky bool TreePattern:: 2749f22ef01cSRoman Divacky InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { 2750f22ef01cSRoman Divacky if (NamedNodes.empty()) 2751f22ef01cSRoman Divacky ComputeNamedNodes(); 2752f22ef01cSRoman Divacky 2753f22ef01cSRoman Divacky bool MadeChange = true; 2754f22ef01cSRoman Divacky while (MadeChange) { 2755f22ef01cSRoman Divacky MadeChange = false; 27562cab237bSDimitry Andric for (TreePatternNode *&Tree : Trees) { 27577d523365SDimitry Andric MadeChange |= Tree->ApplyTypeConstraints(*this, false); 27587d523365SDimitry Andric MadeChange |= SimplifyTree(Tree); 2759f22ef01cSRoman Divacky } 2760f22ef01cSRoman Divacky 2761f22ef01cSRoman Divacky // If there are constraints on our named nodes, apply them. 27627d523365SDimitry Andric for (auto &Entry : NamedNodes) { 27637d523365SDimitry Andric SmallVectorImpl<TreePatternNode*> &Nodes = Entry.second; 2764f22ef01cSRoman Divacky 2765f22ef01cSRoman Divacky // If we have input named node types, propagate their types to the named 2766f22ef01cSRoman Divacky // values here. 2767f22ef01cSRoman Divacky if (InNamedTypes) { 27687d523365SDimitry Andric if (!InNamedTypes->count(Entry.getKey())) { 27697d523365SDimitry Andric error("Node '" + std::string(Entry.getKey()) + 277091bc56edSDimitry Andric "' in output pattern but not input pattern"); 277191bc56edSDimitry Andric return true; 277291bc56edSDimitry Andric } 2773f22ef01cSRoman Divacky 2774f22ef01cSRoman Divacky const SmallVectorImpl<TreePatternNode*> &InNodes = 27757d523365SDimitry Andric InNamedTypes->find(Entry.getKey())->second; 2776f22ef01cSRoman Divacky 2777f22ef01cSRoman Divacky // The input types should be fully resolved by now. 27787d523365SDimitry Andric for (TreePatternNode *Node : Nodes) { 2779f22ef01cSRoman Divacky // If this node is a register class, and it is the root of the pattern 2780f22ef01cSRoman Divacky // then we're mapping something onto an input register. We allow 2781f22ef01cSRoman Divacky // changing the type of the input register in this case. This allows 2782f22ef01cSRoman Divacky // us to match things like: 2783f22ef01cSRoman Divacky // def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>; 27847d523365SDimitry Andric if (Node == Trees[0] && Node->isLeaf()) { 27857d523365SDimitry Andric DefInit *DI = dyn_cast<DefInit>(Node->getLeafValue()); 278617a519f9SDimitry Andric if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || 278717a519f9SDimitry Andric DI->getDef()->isSubClassOf("RegisterOperand"))) 2788f22ef01cSRoman Divacky continue; 2789f22ef01cSRoman Divacky } 2790f22ef01cSRoman Divacky 27917d523365SDimitry Andric assert(Node->getNumTypes() == 1 && 2792f22ef01cSRoman Divacky InNodes[0]->getNumTypes() == 1 && 2793f22ef01cSRoman Divacky "FIXME: cannot name multiple result nodes yet"); 27947d523365SDimitry Andric MadeChange |= Node->UpdateNodeType(0, InNodes[0]->getExtType(0), 2795f22ef01cSRoman Divacky *this); 2796f22ef01cSRoman Divacky } 2797f22ef01cSRoman Divacky } 2798f22ef01cSRoman Divacky 2799f22ef01cSRoman Divacky // If there are multiple nodes with the same name, they must all have the 2800f22ef01cSRoman Divacky // same type. 28017d523365SDimitry Andric if (Entry.second.size() > 1) { 2802f22ef01cSRoman Divacky for (unsigned i = 0, e = Nodes.size()-1; i != e; ++i) { 2803f22ef01cSRoman Divacky TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1]; 2804f22ef01cSRoman Divacky assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 && 2805f22ef01cSRoman Divacky "FIXME: cannot name multiple result nodes yet"); 2806f22ef01cSRoman Divacky 2807f22ef01cSRoman Divacky MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this); 2808f22ef01cSRoman Divacky MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this); 2809f22ef01cSRoman Divacky } 2810f22ef01cSRoman Divacky } 2811f22ef01cSRoman Divacky } 2812f22ef01cSRoman Divacky } 2813f22ef01cSRoman Divacky 2814f22ef01cSRoman Divacky bool HasUnresolvedTypes = false; 28157d523365SDimitry Andric for (const TreePatternNode *Tree : Trees) 28162cab237bSDimitry Andric HasUnresolvedTypes |= Tree->ContainsUnresolvedType(*this); 2817f22ef01cSRoman Divacky return !HasUnresolvedTypes; 2818f22ef01cSRoman Divacky } 2819f22ef01cSRoman Divacky 2820f22ef01cSRoman Divacky void TreePattern::print(raw_ostream &OS) const { 2821f22ef01cSRoman Divacky OS << getRecord()->getName(); 2822f22ef01cSRoman Divacky if (!Args.empty()) { 2823f22ef01cSRoman Divacky OS << "(" << Args[0]; 2824f22ef01cSRoman Divacky for (unsigned i = 1, e = Args.size(); i != e; ++i) 2825f22ef01cSRoman Divacky OS << ", " << Args[i]; 2826f22ef01cSRoman Divacky OS << ")"; 2827f22ef01cSRoman Divacky } 2828f22ef01cSRoman Divacky OS << ": "; 2829f22ef01cSRoman Divacky 2830f22ef01cSRoman Divacky if (Trees.size() > 1) 2831f22ef01cSRoman Divacky OS << "[\n"; 28327d523365SDimitry Andric for (const TreePatternNode *Tree : Trees) { 2833f22ef01cSRoman Divacky OS << "\t"; 28347d523365SDimitry Andric Tree->print(OS); 2835f22ef01cSRoman Divacky OS << "\n"; 2836f22ef01cSRoman Divacky } 2837f22ef01cSRoman Divacky 2838f22ef01cSRoman Divacky if (Trees.size() > 1) 2839f22ef01cSRoman Divacky OS << "]\n"; 2840f22ef01cSRoman Divacky } 2841f22ef01cSRoman Divacky 2842f22ef01cSRoman Divacky void TreePattern::dump() const { print(errs()); } 2843f22ef01cSRoman Divacky 2844f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 2845f22ef01cSRoman Divacky // CodeGenDAGPatterns implementation 2846f22ef01cSRoman Divacky // 2847f22ef01cSRoman Divacky 28482cab237bSDimitry Andric CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R, 28492cab237bSDimitry Andric PatternRewriterFn PatternRewriter) 28502cab237bSDimitry Andric : Records(R), Target(R), LegalVTS(Target.getLegalValueTypes()), 28512cab237bSDimitry Andric PatternRewriter(PatternRewriter) { 28522754fe60SDimitry Andric 28533ca95b02SDimitry Andric Intrinsics = CodeGenIntrinsicTable(Records, false); 28543ca95b02SDimitry Andric TgtIntrinsics = CodeGenIntrinsicTable(Records, true); 2855f22ef01cSRoman Divacky ParseNodeInfo(); 2856f22ef01cSRoman Divacky ParseNodeTransforms(); 2857f22ef01cSRoman Divacky ParseComplexPatterns(); 2858f22ef01cSRoman Divacky ParsePatternFragments(); 2859f22ef01cSRoman Divacky ParseDefaultOperands(); 2860f22ef01cSRoman Divacky ParseInstructions(); 286191bc56edSDimitry Andric ParsePatternFragments(/*OutFrags*/true); 2862f22ef01cSRoman Divacky ParsePatterns(); 2863f22ef01cSRoman Divacky 28642cab237bSDimitry Andric // Break patterns with parameterized types into a series of patterns, 28652cab237bSDimitry Andric // where each one has a fixed type and is predicated on the conditions 28662cab237bSDimitry Andric // of the associated HW mode. 28672cab237bSDimitry Andric ExpandHwModeBasedTypes(); 28682cab237bSDimitry Andric 2869f22ef01cSRoman Divacky // Generate variants. For example, commutative patterns can match 2870f22ef01cSRoman Divacky // multiple ways. Add them to PatternsToMatch as well. 2871f22ef01cSRoman Divacky GenerateVariants(); 2872f22ef01cSRoman Divacky 2873f22ef01cSRoman Divacky // Infer instruction flags. For example, we can detect loads, 2874f22ef01cSRoman Divacky // stores, and side effects in many cases by examining an 2875f22ef01cSRoman Divacky // instruction's pattern. 2876f22ef01cSRoman Divacky InferInstructionFlags(); 28773861d79fSDimitry Andric 28783861d79fSDimitry Andric // Verify that instruction flags match the patterns. 28793861d79fSDimitry Andric VerifyInstructionFlags(); 2880f22ef01cSRoman Divacky } 2881f22ef01cSRoman Divacky 2882f22ef01cSRoman Divacky Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const { 2883f22ef01cSRoman Divacky Record *N = Records.getDef(Name); 2884ff0cc061SDimitry Andric if (!N || !N->isSubClassOf("SDNode")) 2885ff0cc061SDimitry Andric PrintFatalError("Error getting SDNode '" + Name + "'!"); 2886ff0cc061SDimitry Andric 2887f22ef01cSRoman Divacky return N; 2888f22ef01cSRoman Divacky } 2889f22ef01cSRoman Divacky 2890f22ef01cSRoman Divacky // Parse all of the SDNode definitions for the target, populating SDNodes. 2891f22ef01cSRoman Divacky void CodeGenDAGPatterns::ParseNodeInfo() { 2892f22ef01cSRoman Divacky std::vector<Record*> Nodes = Records.getAllDerivedDefinitions("SDNode"); 28932cab237bSDimitry Andric const CodeGenHwModes &CGH = getTargetInfo().getHwModes(); 28942cab237bSDimitry Andric 2895f22ef01cSRoman Divacky while (!Nodes.empty()) { 28962cab237bSDimitry Andric Record *R = Nodes.back(); 28972cab237bSDimitry Andric SDNodes.insert(std::make_pair(R, SDNodeInfo(R, CGH))); 2898f22ef01cSRoman Divacky Nodes.pop_back(); 2899f22ef01cSRoman Divacky } 2900f22ef01cSRoman Divacky 2901f22ef01cSRoman Divacky // Get the builtin intrinsic nodes. 2902f22ef01cSRoman Divacky intrinsic_void_sdnode = getSDNodeNamed("intrinsic_void"); 2903f22ef01cSRoman Divacky intrinsic_w_chain_sdnode = getSDNodeNamed("intrinsic_w_chain"); 2904f22ef01cSRoman Divacky intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain"); 2905f22ef01cSRoman Divacky } 2906f22ef01cSRoman Divacky 2907f22ef01cSRoman Divacky /// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms 2908f22ef01cSRoman Divacky /// map, and emit them to the file as functions. 2909f22ef01cSRoman Divacky void CodeGenDAGPatterns::ParseNodeTransforms() { 2910f22ef01cSRoman Divacky std::vector<Record*> Xforms = Records.getAllDerivedDefinitions("SDNodeXForm"); 2911f22ef01cSRoman Divacky while (!Xforms.empty()) { 2912f22ef01cSRoman Divacky Record *XFormNode = Xforms.back(); 2913f22ef01cSRoman Divacky Record *SDNode = XFormNode->getValueAsDef("Opcode"); 2914f9448bf3SDimitry Andric StringRef Code = XFormNode->getValueAsString("XFormFunction"); 2915f22ef01cSRoman Divacky SDNodeXForms.insert(std::make_pair(XFormNode, NodeXForm(SDNode, Code))); 2916f22ef01cSRoman Divacky 2917f22ef01cSRoman Divacky Xforms.pop_back(); 2918f22ef01cSRoman Divacky } 2919f22ef01cSRoman Divacky } 2920f22ef01cSRoman Divacky 2921f22ef01cSRoman Divacky void CodeGenDAGPatterns::ParseComplexPatterns() { 2922f22ef01cSRoman Divacky std::vector<Record*> AMs = Records.getAllDerivedDefinitions("ComplexPattern"); 2923f22ef01cSRoman Divacky while (!AMs.empty()) { 2924f22ef01cSRoman Divacky ComplexPatterns.insert(std::make_pair(AMs.back(), AMs.back())); 2925f22ef01cSRoman Divacky AMs.pop_back(); 2926f22ef01cSRoman Divacky } 2927f22ef01cSRoman Divacky } 2928f22ef01cSRoman Divacky 2929f22ef01cSRoman Divacky 2930f22ef01cSRoman Divacky /// ParsePatternFragments - Parse all of the PatFrag definitions in the .td 2931f22ef01cSRoman Divacky /// file, building up the PatternFragments map. After we've collected them all, 2932f22ef01cSRoman Divacky /// inline fragments together as necessary, so that there are no references left 2933f22ef01cSRoman Divacky /// inside a pattern fragment to a pattern fragment. 2934f22ef01cSRoman Divacky /// 293591bc56edSDimitry Andric void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { 2936f22ef01cSRoman Divacky std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag"); 2937f22ef01cSRoman Divacky 2938f22ef01cSRoman Divacky // First step, parse all of the fragments. 29397d523365SDimitry Andric for (Record *Frag : Fragments) { 29407d523365SDimitry Andric if (OutFrags != Frag->isSubClassOf("OutPatFrag")) 294191bc56edSDimitry Andric continue; 294291bc56edSDimitry Andric 29437d523365SDimitry Andric DagInit *Tree = Frag->getValueAsDag("Fragment"); 294491bc56edSDimitry Andric TreePattern *P = 29457d523365SDimitry Andric (PatternFragments[Frag] = llvm::make_unique<TreePattern>( 29467d523365SDimitry Andric Frag, Tree, !Frag->isSubClassOf("OutPatFrag"), 294739d628a0SDimitry Andric *this)).get(); 2948f22ef01cSRoman Divacky 2949f22ef01cSRoman Divacky // Validate the argument list, converting it to set, to discard duplicates. 2950f22ef01cSRoman Divacky std::vector<std::string> &Args = P->getArgList(); 29512cab237bSDimitry Andric // Copy the args so we can take StringRefs to them. 29522cab237bSDimitry Andric auto ArgsCopy = Args; 29532cab237bSDimitry Andric SmallDenseSet<StringRef, 4> OperandsSet; 29542cab237bSDimitry Andric OperandsSet.insert(ArgsCopy.begin(), ArgsCopy.end()); 2955f22ef01cSRoman Divacky 2956f22ef01cSRoman Divacky if (OperandsSet.count("")) 2957f22ef01cSRoman Divacky P->error("Cannot have unnamed 'node' values in pattern fragment!"); 2958f22ef01cSRoman Divacky 2959f22ef01cSRoman Divacky // Parse the operands list. 29607d523365SDimitry Andric DagInit *OpsList = Frag->getValueAsDag("Operands"); 29613861d79fSDimitry Andric DefInit *OpsOp = dyn_cast<DefInit>(OpsList->getOperator()); 2962f22ef01cSRoman Divacky // Special cases: ops == outs == ins. Different names are used to 2963f22ef01cSRoman Divacky // improve readability. 2964f22ef01cSRoman Divacky if (!OpsOp || 2965f22ef01cSRoman Divacky (OpsOp->getDef()->getName() != "ops" && 2966f22ef01cSRoman Divacky OpsOp->getDef()->getName() != "outs" && 2967f22ef01cSRoman Divacky OpsOp->getDef()->getName() != "ins")) 2968f22ef01cSRoman Divacky P->error("Operands list should start with '(ops ... '!"); 2969f22ef01cSRoman Divacky 2970f22ef01cSRoman Divacky // Copy over the arguments. 2971f22ef01cSRoman Divacky Args.clear(); 2972f22ef01cSRoman Divacky for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) { 29733861d79fSDimitry Andric if (!isa<DefInit>(OpsList->getArg(j)) || 29743861d79fSDimitry Andric cast<DefInit>(OpsList->getArg(j))->getDef()->getName() != "node") 2975f22ef01cSRoman Divacky P->error("Operands list should all be 'node' values."); 2976d88c1a5aSDimitry Andric if (!OpsList->getArgName(j)) 2977f22ef01cSRoman Divacky P->error("Operands list should have names for each operand!"); 2978d88c1a5aSDimitry Andric StringRef ArgNameStr = OpsList->getArgNameStr(j); 2979d88c1a5aSDimitry Andric if (!OperandsSet.count(ArgNameStr)) 2980d88c1a5aSDimitry Andric P->error("'" + ArgNameStr + 2981f22ef01cSRoman Divacky "' does not occur in pattern or was multiply specified!"); 2982d88c1a5aSDimitry Andric OperandsSet.erase(ArgNameStr); 2983d88c1a5aSDimitry Andric Args.push_back(ArgNameStr); 2984f22ef01cSRoman Divacky } 2985f22ef01cSRoman Divacky 2986f22ef01cSRoman Divacky if (!OperandsSet.empty()) 2987f22ef01cSRoman Divacky P->error("Operands list does not contain an entry for operand '" + 2988f22ef01cSRoman Divacky *OperandsSet.begin() + "'!"); 2989f22ef01cSRoman Divacky 2990f22ef01cSRoman Divacky // If there is a code init for this fragment, keep track of the fact that 2991f22ef01cSRoman Divacky // this fragment uses it. 29923b0f4066SDimitry Andric TreePredicateFn PredFn(P); 29933b0f4066SDimitry Andric if (!PredFn.isAlwaysTrue()) 29943b0f4066SDimitry Andric P->getOnlyTree()->addPredicateFn(PredFn); 2995f22ef01cSRoman Divacky 2996f22ef01cSRoman Divacky // If there is a node transformation corresponding to this, keep track of 2997f22ef01cSRoman Divacky // it. 29987d523365SDimitry Andric Record *Transform = Frag->getValueAsDef("OperandTransform"); 2999f22ef01cSRoman Divacky if (!getSDNodeTransform(Transform).second.empty()) // not noop xform? 3000f22ef01cSRoman Divacky P->getOnlyTree()->setTransformFn(Transform); 3001f22ef01cSRoman Divacky } 3002f22ef01cSRoman Divacky 3003f22ef01cSRoman Divacky // Now that we've parsed all of the tree fragments, do a closure on them so 3004f22ef01cSRoman Divacky // that there are not references to PatFrags left inside of them. 30057d523365SDimitry Andric for (Record *Frag : Fragments) { 30067d523365SDimitry Andric if (OutFrags != Frag->isSubClassOf("OutPatFrag")) 300791bc56edSDimitry Andric continue; 300891bc56edSDimitry Andric 30097d523365SDimitry Andric TreePattern &ThePat = *PatternFragments[Frag]; 301039d628a0SDimitry Andric ThePat.InlinePatternFragments(); 3011f22ef01cSRoman Divacky 3012f22ef01cSRoman Divacky // Infer as many types as possible. Don't worry about it if we don't infer 3013f22ef01cSRoman Divacky // all of them, some may depend on the inputs of the pattern. 301439d628a0SDimitry Andric ThePat.InferAllTypes(); 301539d628a0SDimitry Andric ThePat.resetError(); 3016f22ef01cSRoman Divacky 3017f22ef01cSRoman Divacky // If debugging, print out the pattern fragment result. 301839d628a0SDimitry Andric DEBUG(ThePat.dump()); 3019f22ef01cSRoman Divacky } 3020f22ef01cSRoman Divacky } 3021f22ef01cSRoman Divacky 3022f22ef01cSRoman Divacky void CodeGenDAGPatterns::ParseDefaultOperands() { 30233861d79fSDimitry Andric std::vector<Record*> DefaultOps; 30243861d79fSDimitry Andric DefaultOps = Records.getAllDerivedDefinitions("OperandWithDefaultOps"); 3025f22ef01cSRoman Divacky 3026f22ef01cSRoman Divacky // Find some SDNode. 3027f22ef01cSRoman Divacky assert(!SDNodes.empty() && "No SDNodes parsed?"); 30286122f3e6SDimitry Andric Init *SomeSDNode = DefInit::get(SDNodes.begin()->first); 3029f22ef01cSRoman Divacky 30303861d79fSDimitry Andric for (unsigned i = 0, e = DefaultOps.size(); i != e; ++i) { 30313861d79fSDimitry Andric DagInit *DefaultInfo = DefaultOps[i]->getValueAsDag("DefaultOps"); 3032f22ef01cSRoman Divacky 3033f22ef01cSRoman Divacky // Clone the DefaultInfo dag node, changing the operator from 'ops' to 3034f22ef01cSRoman Divacky // SomeSDnode so that we can parse this. 3035d88c1a5aSDimitry Andric std::vector<std::pair<Init*, StringInit*> > Ops; 3036f22ef01cSRoman Divacky for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op) 3037f22ef01cSRoman Divacky Ops.push_back(std::make_pair(DefaultInfo->getArg(op), 3038f22ef01cSRoman Divacky DefaultInfo->getArgName(op))); 3039d88c1a5aSDimitry Andric DagInit *DI = DagInit::get(SomeSDNode, nullptr, Ops); 3040f22ef01cSRoman Divacky 3041f22ef01cSRoman Divacky // Create a TreePattern to parse this. 30423861d79fSDimitry Andric TreePattern P(DefaultOps[i], DI, false, *this); 3043f22ef01cSRoman Divacky assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!"); 3044f22ef01cSRoman Divacky 3045f22ef01cSRoman Divacky // Copy the operands over into a DAGDefaultOperand. 3046f22ef01cSRoman Divacky DAGDefaultOperand DefaultOpInfo; 3047f22ef01cSRoman Divacky 3048f22ef01cSRoman Divacky TreePatternNode *T = P.getTree(0); 3049f22ef01cSRoman Divacky for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) { 3050f22ef01cSRoman Divacky TreePatternNode *TPN = T->getChild(op); 3051f22ef01cSRoman Divacky while (TPN->ApplyTypeConstraints(P, false)) 3052f22ef01cSRoman Divacky /* Resolve all types */; 3053f22ef01cSRoman Divacky 30542cab237bSDimitry Andric if (TPN->ContainsUnresolvedType(P)) { 305591bc56edSDimitry Andric PrintFatalError("Value #" + Twine(i) + " of OperandWithDefaultOps '" + 305691bc56edSDimitry Andric DefaultOps[i]->getName() + 305791bc56edSDimitry Andric "' doesn't have a concrete type!"); 3058f22ef01cSRoman Divacky } 3059f22ef01cSRoman Divacky DefaultOpInfo.DefaultOps.push_back(TPN); 3060f22ef01cSRoman Divacky } 3061f22ef01cSRoman Divacky 3062f22ef01cSRoman Divacky // Insert it into the DefaultOperands map so we can find it later. 30633861d79fSDimitry Andric DefaultOperands[DefaultOps[i]] = DefaultOpInfo; 3064f22ef01cSRoman Divacky } 3065f22ef01cSRoman Divacky } 3066f22ef01cSRoman Divacky 3067f22ef01cSRoman Divacky /// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an 3068f22ef01cSRoman Divacky /// instruction input. Return true if this is a real use. 3069f22ef01cSRoman Divacky static bool HandleUse(TreePattern *I, TreePatternNode *Pat, 3070f22ef01cSRoman Divacky std::map<std::string, TreePatternNode*> &InstInputs) { 3071f22ef01cSRoman Divacky // No name -> not interesting. 3072f22ef01cSRoman Divacky if (Pat->getName().empty()) { 3073f22ef01cSRoman Divacky if (Pat->isLeaf()) { 30743861d79fSDimitry Andric DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue()); 307517a519f9SDimitry Andric if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || 307617a519f9SDimitry Andric DI->getDef()->isSubClassOf("RegisterOperand"))) 3077f22ef01cSRoman Divacky I->error("Input " + DI->getDef()->getName() + " must be named!"); 3078f22ef01cSRoman Divacky } 3079f22ef01cSRoman Divacky return false; 3080f22ef01cSRoman Divacky } 3081f22ef01cSRoman Divacky 3082f22ef01cSRoman Divacky Record *Rec; 3083f22ef01cSRoman Divacky if (Pat->isLeaf()) { 30843861d79fSDimitry Andric DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue()); 3085f22ef01cSRoman Divacky if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!"); 3086f22ef01cSRoman Divacky Rec = DI->getDef(); 3087f22ef01cSRoman Divacky } else { 3088f22ef01cSRoman Divacky Rec = Pat->getOperator(); 3089f22ef01cSRoman Divacky } 3090f22ef01cSRoman Divacky 3091f22ef01cSRoman Divacky // SRCVALUE nodes are ignored. 3092f22ef01cSRoman Divacky if (Rec->getName() == "srcvalue") 3093f22ef01cSRoman Divacky return false; 3094f22ef01cSRoman Divacky 3095f22ef01cSRoman Divacky TreePatternNode *&Slot = InstInputs[Pat->getName()]; 3096f22ef01cSRoman Divacky if (!Slot) { 3097f22ef01cSRoman Divacky Slot = Pat; 3098f22ef01cSRoman Divacky return true; 3099f22ef01cSRoman Divacky } 3100f22ef01cSRoman Divacky Record *SlotRec; 3101f22ef01cSRoman Divacky if (Slot->isLeaf()) { 31023861d79fSDimitry Andric SlotRec = cast<DefInit>(Slot->getLeafValue())->getDef(); 3103f22ef01cSRoman Divacky } else { 3104f22ef01cSRoman Divacky assert(Slot->getNumChildren() == 0 && "can't be a use with children!"); 3105f22ef01cSRoman Divacky SlotRec = Slot->getOperator(); 3106f22ef01cSRoman Divacky } 3107f22ef01cSRoman Divacky 3108f22ef01cSRoman Divacky // Ensure that the inputs agree if we've already seen this input. 3109f22ef01cSRoman Divacky if (Rec != SlotRec) 3110f22ef01cSRoman Divacky I->error("All $" + Pat->getName() + " inputs must agree with each other"); 3111f22ef01cSRoman Divacky if (Slot->getExtTypes() != Pat->getExtTypes()) 3112f22ef01cSRoman Divacky I->error("All $" + Pat->getName() + " inputs must agree with each other"); 3113f22ef01cSRoman Divacky return true; 3114f22ef01cSRoman Divacky } 3115f22ef01cSRoman Divacky 3116f22ef01cSRoman Divacky /// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is 3117f22ef01cSRoman Divacky /// part of "I", the instruction), computing the set of inputs and outputs of 3118f22ef01cSRoman Divacky /// the pattern. Report errors if we see anything naughty. 3119f22ef01cSRoman Divacky void CodeGenDAGPatterns:: 3120f22ef01cSRoman Divacky FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, 3121f22ef01cSRoman Divacky std::map<std::string, TreePatternNode*> &InstInputs, 3122f22ef01cSRoman Divacky std::map<std::string, TreePatternNode*>&InstResults, 3123f22ef01cSRoman Divacky std::vector<Record*> &InstImpResults) { 3124f22ef01cSRoman Divacky if (Pat->isLeaf()) { 3125f22ef01cSRoman Divacky bool isUse = HandleUse(I, Pat, InstInputs); 3126f22ef01cSRoman Divacky if (!isUse && Pat->getTransformFn()) 3127f22ef01cSRoman Divacky I->error("Cannot specify a transform function for a non-input value!"); 3128f22ef01cSRoman Divacky return; 3129f22ef01cSRoman Divacky } 3130f22ef01cSRoman Divacky 3131f22ef01cSRoman Divacky if (Pat->getOperator()->getName() == "implicit") { 3132f22ef01cSRoman Divacky for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { 3133f22ef01cSRoman Divacky TreePatternNode *Dest = Pat->getChild(i); 3134f22ef01cSRoman Divacky if (!Dest->isLeaf()) 3135f22ef01cSRoman Divacky I->error("implicitly defined value should be a register!"); 3136f22ef01cSRoman Divacky 31373861d79fSDimitry Andric DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue()); 3138f22ef01cSRoman Divacky if (!Val || !Val->getDef()->isSubClassOf("Register")) 3139f22ef01cSRoman Divacky I->error("implicitly defined value should be a register!"); 3140f22ef01cSRoman Divacky InstImpResults.push_back(Val->getDef()); 3141f22ef01cSRoman Divacky } 3142f22ef01cSRoman Divacky return; 3143f22ef01cSRoman Divacky } 3144f22ef01cSRoman Divacky 3145f22ef01cSRoman Divacky if (Pat->getOperator()->getName() != "set") { 3146f22ef01cSRoman Divacky // If this is not a set, verify that the children nodes are not void typed, 3147f22ef01cSRoman Divacky // and recurse. 3148f22ef01cSRoman Divacky for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { 3149f22ef01cSRoman Divacky if (Pat->getChild(i)->getNumTypes() == 0) 3150f22ef01cSRoman Divacky I->error("Cannot have void nodes inside of patterns!"); 3151f22ef01cSRoman Divacky FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults, 3152f22ef01cSRoman Divacky InstImpResults); 3153f22ef01cSRoman Divacky } 3154f22ef01cSRoman Divacky 3155f22ef01cSRoman Divacky // If this is a non-leaf node with no children, treat it basically as if 3156f22ef01cSRoman Divacky // it were a leaf. This handles nodes like (imm). 3157f22ef01cSRoman Divacky bool isUse = HandleUse(I, Pat, InstInputs); 3158f22ef01cSRoman Divacky 3159f22ef01cSRoman Divacky if (!isUse && Pat->getTransformFn()) 3160f22ef01cSRoman Divacky I->error("Cannot specify a transform function for a non-input value!"); 3161f22ef01cSRoman Divacky return; 3162f22ef01cSRoman Divacky } 3163f22ef01cSRoman Divacky 3164f22ef01cSRoman Divacky // Otherwise, this is a set, validate and collect instruction results. 3165f22ef01cSRoman Divacky if (Pat->getNumChildren() == 0) 3166f22ef01cSRoman Divacky I->error("set requires operands!"); 3167f22ef01cSRoman Divacky 3168f22ef01cSRoman Divacky if (Pat->getTransformFn()) 3169f22ef01cSRoman Divacky I->error("Cannot specify a transform function on a set node!"); 3170f22ef01cSRoman Divacky 3171f22ef01cSRoman Divacky // Check the set destinations. 3172f22ef01cSRoman Divacky unsigned NumDests = Pat->getNumChildren()-1; 3173f22ef01cSRoman Divacky for (unsigned i = 0; i != NumDests; ++i) { 3174f22ef01cSRoman Divacky TreePatternNode *Dest = Pat->getChild(i); 3175f22ef01cSRoman Divacky if (!Dest->isLeaf()) 3176f22ef01cSRoman Divacky I->error("set destination should be a register!"); 3177f22ef01cSRoman Divacky 31783861d79fSDimitry Andric DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue()); 317939d628a0SDimitry Andric if (!Val) { 3180f22ef01cSRoman Divacky I->error("set destination should be a register!"); 318139d628a0SDimitry Andric continue; 318239d628a0SDimitry Andric } 3183f22ef01cSRoman Divacky 3184f22ef01cSRoman Divacky if (Val->getDef()->isSubClassOf("RegisterClass") || 3185139f7f9bSDimitry Andric Val->getDef()->isSubClassOf("ValueType") || 318617a519f9SDimitry Andric Val->getDef()->isSubClassOf("RegisterOperand") || 3187f22ef01cSRoman Divacky Val->getDef()->isSubClassOf("PointerLikeRegClass")) { 3188f22ef01cSRoman Divacky if (Dest->getName().empty()) 3189f22ef01cSRoman Divacky I->error("set destination must have a name!"); 3190f22ef01cSRoman Divacky if (InstResults.count(Dest->getName())) 3191f22ef01cSRoman Divacky I->error("cannot set '" + Dest->getName() +"' multiple times"); 3192f22ef01cSRoman Divacky InstResults[Dest->getName()] = Dest; 3193f22ef01cSRoman Divacky } else if (Val->getDef()->isSubClassOf("Register")) { 3194f22ef01cSRoman Divacky InstImpResults.push_back(Val->getDef()); 3195f22ef01cSRoman Divacky } else { 3196f22ef01cSRoman Divacky I->error("set destination should be a register!"); 3197f22ef01cSRoman Divacky } 3198f22ef01cSRoman Divacky } 3199f22ef01cSRoman Divacky 3200f22ef01cSRoman Divacky // Verify and collect info from the computation. 3201f22ef01cSRoman Divacky FindPatternInputsAndOutputs(I, Pat->getChild(NumDests), 3202f22ef01cSRoman Divacky InstInputs, InstResults, InstImpResults); 3203f22ef01cSRoman Divacky } 3204f22ef01cSRoman Divacky 3205f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 3206f22ef01cSRoman Divacky // Instruction Analysis 3207f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 3208f22ef01cSRoman Divacky 3209f22ef01cSRoman Divacky class InstAnalyzer { 3210f22ef01cSRoman Divacky const CodeGenDAGPatterns &CDP; 3211f22ef01cSRoman Divacky public: 32123861d79fSDimitry Andric bool hasSideEffects; 32133861d79fSDimitry Andric bool mayStore; 32143861d79fSDimitry Andric bool mayLoad; 32153861d79fSDimitry Andric bool isBitcast; 32163861d79fSDimitry Andric bool isVariadic; 32173861d79fSDimitry Andric 32183861d79fSDimitry Andric InstAnalyzer(const CodeGenDAGPatterns &cdp) 32193861d79fSDimitry Andric : CDP(cdp), hasSideEffects(false), mayStore(false), mayLoad(false), 32203861d79fSDimitry Andric isBitcast(false), isVariadic(false) {} 32213861d79fSDimitry Andric 32223861d79fSDimitry Andric void Analyze(const TreePattern *Pat) { 32233861d79fSDimitry Andric // Assume only the first tree is the pattern. The others are clobber nodes. 32243861d79fSDimitry Andric AnalyzeNode(Pat->getTree(0)); 3225f22ef01cSRoman Divacky } 3226f22ef01cSRoman Divacky 3227edd7eaddSDimitry Andric void Analyze(const PatternToMatch &Pat) { 3228edd7eaddSDimitry Andric AnalyzeNode(Pat.getSrcPattern()); 3229f22ef01cSRoman Divacky } 3230f22ef01cSRoman Divacky 3231f22ef01cSRoman Divacky private: 32323b0f4066SDimitry Andric bool IsNodeBitcast(const TreePatternNode *N) const { 32333861d79fSDimitry Andric if (hasSideEffects || mayLoad || mayStore || isVariadic) 32343b0f4066SDimitry Andric return false; 32353b0f4066SDimitry Andric 32363b0f4066SDimitry Andric if (N->getNumChildren() != 2) 32373b0f4066SDimitry Andric return false; 32383b0f4066SDimitry Andric 32393b0f4066SDimitry Andric const TreePatternNode *N0 = N->getChild(0); 32403861d79fSDimitry Andric if (!N0->isLeaf() || !isa<DefInit>(N0->getLeafValue())) 32413b0f4066SDimitry Andric return false; 32423b0f4066SDimitry Andric 32433b0f4066SDimitry Andric const TreePatternNode *N1 = N->getChild(1); 32443b0f4066SDimitry Andric if (N1->isLeaf()) 32453b0f4066SDimitry Andric return false; 32463b0f4066SDimitry Andric if (N1->getNumChildren() != 1 || !N1->getChild(0)->isLeaf()) 32473b0f4066SDimitry Andric return false; 32483b0f4066SDimitry Andric 32493b0f4066SDimitry Andric const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N1->getOperator()); 32503b0f4066SDimitry Andric if (OpInfo.getNumResults() != 1 || OpInfo.getNumOperands() != 1) 32513b0f4066SDimitry Andric return false; 32523b0f4066SDimitry Andric return OpInfo.getEnumName() == "ISD::BITCAST"; 32533b0f4066SDimitry Andric } 32543b0f4066SDimitry Andric 32553861d79fSDimitry Andric public: 3256f22ef01cSRoman Divacky void AnalyzeNode(const TreePatternNode *N) { 3257f22ef01cSRoman Divacky if (N->isLeaf()) { 32583861d79fSDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(N->getLeafValue())) { 3259f22ef01cSRoman Divacky Record *LeafRec = DI->getDef(); 3260f22ef01cSRoman Divacky // Handle ComplexPattern leaves. 3261f22ef01cSRoman Divacky if (LeafRec->isSubClassOf("ComplexPattern")) { 3262f22ef01cSRoman Divacky const ComplexPattern &CP = CDP.getComplexPattern(LeafRec); 3263f22ef01cSRoman Divacky if (CP.hasProperty(SDNPMayStore)) mayStore = true; 3264f22ef01cSRoman Divacky if (CP.hasProperty(SDNPMayLoad)) mayLoad = true; 32653861d79fSDimitry Andric if (CP.hasProperty(SDNPSideEffect)) hasSideEffects = true; 3266f22ef01cSRoman Divacky } 3267f22ef01cSRoman Divacky } 3268f22ef01cSRoman Divacky return; 3269f22ef01cSRoman Divacky } 3270f22ef01cSRoman Divacky 3271f22ef01cSRoman Divacky // Analyze children. 3272f22ef01cSRoman Divacky for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) 3273f22ef01cSRoman Divacky AnalyzeNode(N->getChild(i)); 3274f22ef01cSRoman Divacky 3275f22ef01cSRoman Divacky // Ignore set nodes, which are not SDNodes. 32763b0f4066SDimitry Andric if (N->getOperator()->getName() == "set") { 32773861d79fSDimitry Andric isBitcast = IsNodeBitcast(N); 3278f22ef01cSRoman Divacky return; 32793b0f4066SDimitry Andric } 3280f22ef01cSRoman Divacky 3281f22ef01cSRoman Divacky // Notice properties of the node. 328291bc56edSDimitry Andric if (N->NodeHasProperty(SDNPMayStore, CDP)) mayStore = true; 328391bc56edSDimitry Andric if (N->NodeHasProperty(SDNPMayLoad, CDP)) mayLoad = true; 328491bc56edSDimitry Andric if (N->NodeHasProperty(SDNPSideEffect, CDP)) hasSideEffects = true; 328591bc56edSDimitry Andric if (N->NodeHasProperty(SDNPVariadic, CDP)) isVariadic = true; 3286f22ef01cSRoman Divacky 3287f22ef01cSRoman Divacky if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) { 3288f22ef01cSRoman Divacky // If this is an intrinsic, analyze it. 32893ca95b02SDimitry Andric if (IntInfo->ModRef & CodeGenIntrinsic::MR_Ref) 3290f22ef01cSRoman Divacky mayLoad = true;// These may load memory. 3291f22ef01cSRoman Divacky 32923ca95b02SDimitry Andric if (IntInfo->ModRef & CodeGenIntrinsic::MR_Mod) 3293f22ef01cSRoman Divacky mayStore = true;// Intrinsics that can write to memory are 'mayStore'. 3294f22ef01cSRoman Divacky 3295f37b6182SDimitry Andric if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteMem || 3296f37b6182SDimitry Andric IntInfo->hasSideEffects) 32973ca95b02SDimitry Andric // ReadWriteMem intrinsics can have other strange effects. 32983861d79fSDimitry Andric hasSideEffects = true; 3299f22ef01cSRoman Divacky } 3300f22ef01cSRoman Divacky } 3301f22ef01cSRoman Divacky 3302f22ef01cSRoman Divacky }; 3303f22ef01cSRoman Divacky 33043861d79fSDimitry Andric static bool InferFromPattern(CodeGenInstruction &InstInfo, 33053861d79fSDimitry Andric const InstAnalyzer &PatInfo, 33063861d79fSDimitry Andric Record *PatDef) { 33073861d79fSDimitry Andric bool Error = false; 3308f22ef01cSRoman Divacky 33093861d79fSDimitry Andric // Remember where InstInfo got its flags. 33103861d79fSDimitry Andric if (InstInfo.hasUndefFlags()) 33113861d79fSDimitry Andric InstInfo.InferredFrom = PatDef; 3312f22ef01cSRoman Divacky 33133861d79fSDimitry Andric // Check explicitly set flags for consistency. 33143861d79fSDimitry Andric if (InstInfo.hasSideEffects != PatInfo.hasSideEffects && 33153861d79fSDimitry Andric !InstInfo.hasSideEffects_Unset) { 33163861d79fSDimitry Andric // Allow explicitly setting hasSideEffects = 1 on instructions, even when 33173861d79fSDimitry Andric // the pattern has no side effects. That could be useful for div/rem 33183861d79fSDimitry Andric // instructions that may trap. 33193861d79fSDimitry Andric if (!InstInfo.hasSideEffects) { 33203861d79fSDimitry Andric Error = true; 33213861d79fSDimitry Andric PrintError(PatDef->getLoc(), "Pattern doesn't match hasSideEffects = " + 33223861d79fSDimitry Andric Twine(InstInfo.hasSideEffects)); 33233861d79fSDimitry Andric } 3324f22ef01cSRoman Divacky } 3325f22ef01cSRoman Divacky 33263861d79fSDimitry Andric if (InstInfo.mayStore != PatInfo.mayStore && !InstInfo.mayStore_Unset) { 33273861d79fSDimitry Andric Error = true; 33283861d79fSDimitry Andric PrintError(PatDef->getLoc(), "Pattern doesn't match mayStore = " + 33293861d79fSDimitry Andric Twine(InstInfo.mayStore)); 3330f22ef01cSRoman Divacky } 3331f22ef01cSRoman Divacky 33323861d79fSDimitry Andric if (InstInfo.mayLoad != PatInfo.mayLoad && !InstInfo.mayLoad_Unset) { 33333861d79fSDimitry Andric // Allow explicitly setting mayLoad = 1, even when the pattern has no loads. 33347d523365SDimitry Andric // Some targets translate immediates to loads. 33353861d79fSDimitry Andric if (!InstInfo.mayLoad) { 33363861d79fSDimitry Andric Error = true; 33373861d79fSDimitry Andric PrintError(PatDef->getLoc(), "Pattern doesn't match mayLoad = " + 33383861d79fSDimitry Andric Twine(InstInfo.mayLoad)); 33393861d79fSDimitry Andric } 3340f22ef01cSRoman Divacky } 3341f22ef01cSRoman Divacky 33423861d79fSDimitry Andric // Transfer inferred flags. 33433861d79fSDimitry Andric InstInfo.hasSideEffects |= PatInfo.hasSideEffects; 33443861d79fSDimitry Andric InstInfo.mayStore |= PatInfo.mayStore; 33453861d79fSDimitry Andric InstInfo.mayLoad |= PatInfo.mayLoad; 3346f22ef01cSRoman Divacky 33473861d79fSDimitry Andric // These flags are silently added without any verification. 33483861d79fSDimitry Andric InstInfo.isBitcast |= PatInfo.isBitcast; 33493861d79fSDimitry Andric 33503861d79fSDimitry Andric // Don't infer isVariadic. This flag means something different on SDNodes and 33513861d79fSDimitry Andric // instructions. For example, a CALL SDNode is variadic because it has the 33523861d79fSDimitry Andric // call arguments as operands, but a CALL instruction is not variadic - it 33533861d79fSDimitry Andric // has argument registers as implicit, not explicit uses. 33543861d79fSDimitry Andric 33553861d79fSDimitry Andric return Error; 3356f22ef01cSRoman Divacky } 3357f22ef01cSRoman Divacky 33587ae0e2c9SDimitry Andric /// hasNullFragReference - Return true if the DAG has any reference to the 33597ae0e2c9SDimitry Andric /// null_frag operator. 33607ae0e2c9SDimitry Andric static bool hasNullFragReference(DagInit *DI) { 33613861d79fSDimitry Andric DefInit *OpDef = dyn_cast<DefInit>(DI->getOperator()); 33627ae0e2c9SDimitry Andric if (!OpDef) return false; 33637ae0e2c9SDimitry Andric Record *Operator = OpDef->getDef(); 33647ae0e2c9SDimitry Andric 33657ae0e2c9SDimitry Andric // If this is the null fragment, return true. 33667ae0e2c9SDimitry Andric if (Operator->getName() == "null_frag") return true; 33677ae0e2c9SDimitry Andric // If any of the arguments reference the null fragment, return true. 33687ae0e2c9SDimitry Andric for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) { 33693861d79fSDimitry Andric DagInit *Arg = dyn_cast<DagInit>(DI->getArg(i)); 33707ae0e2c9SDimitry Andric if (Arg && hasNullFragReference(Arg)) 33717ae0e2c9SDimitry Andric return true; 33727ae0e2c9SDimitry Andric } 33737ae0e2c9SDimitry Andric 33747ae0e2c9SDimitry Andric return false; 33757ae0e2c9SDimitry Andric } 33767ae0e2c9SDimitry Andric 33777ae0e2c9SDimitry Andric /// hasNullFragReference - Return true if any DAG in the list references 33787ae0e2c9SDimitry Andric /// the null_frag operator. 33797ae0e2c9SDimitry Andric static bool hasNullFragReference(ListInit *LI) { 338097bc6c73SDimitry Andric for (Init *I : LI->getValues()) { 338197bc6c73SDimitry Andric DagInit *DI = dyn_cast<DagInit>(I); 33827ae0e2c9SDimitry Andric assert(DI && "non-dag in an instruction Pattern list?!"); 33837ae0e2c9SDimitry Andric if (hasNullFragReference(DI)) 33847ae0e2c9SDimitry Andric return true; 33857ae0e2c9SDimitry Andric } 33867ae0e2c9SDimitry Andric return false; 33877ae0e2c9SDimitry Andric } 33887ae0e2c9SDimitry Andric 33893861d79fSDimitry Andric /// Get all the instructions in a tree. 33903861d79fSDimitry Andric static void 33913861d79fSDimitry Andric getInstructionsInTree(TreePatternNode *Tree, SmallVectorImpl<Record*> &Instrs) { 33923861d79fSDimitry Andric if (Tree->isLeaf()) 33933861d79fSDimitry Andric return; 33943861d79fSDimitry Andric if (Tree->getOperator()->isSubClassOf("Instruction")) 33953861d79fSDimitry Andric Instrs.push_back(Tree->getOperator()); 33963861d79fSDimitry Andric for (unsigned i = 0, e = Tree->getNumChildren(); i != e; ++i) 33973861d79fSDimitry Andric getInstructionsInTree(Tree->getChild(i), Instrs); 33983861d79fSDimitry Andric } 33993861d79fSDimitry Andric 3400139f7f9bSDimitry Andric /// Check the class of a pattern leaf node against the instruction operand it 3401139f7f9bSDimitry Andric /// represents. 3402139f7f9bSDimitry Andric static bool checkOperandClass(CGIOperandList::OperandInfo &OI, 3403139f7f9bSDimitry Andric Record *Leaf) { 3404139f7f9bSDimitry Andric if (OI.Rec == Leaf) 3405139f7f9bSDimitry Andric return true; 3406139f7f9bSDimitry Andric 3407139f7f9bSDimitry Andric // Allow direct value types to be used in instruction set patterns. 3408139f7f9bSDimitry Andric // The type will be checked later. 3409139f7f9bSDimitry Andric if (Leaf->isSubClassOf("ValueType")) 3410139f7f9bSDimitry Andric return true; 3411139f7f9bSDimitry Andric 3412139f7f9bSDimitry Andric // Patterns can also be ComplexPattern instances. 3413139f7f9bSDimitry Andric if (Leaf->isSubClassOf("ComplexPattern")) 3414139f7f9bSDimitry Andric return true; 3415139f7f9bSDimitry Andric 3416139f7f9bSDimitry Andric return false; 3417139f7f9bSDimitry Andric } 3418139f7f9bSDimitry Andric 3419f785676fSDimitry Andric const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( 3420f785676fSDimitry Andric CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) { 3421f22ef01cSRoman Divacky 3422f785676fSDimitry Andric assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!"); 3423f22ef01cSRoman Divacky 3424f22ef01cSRoman Divacky // Parse the instruction. 3425f785676fSDimitry Andric TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this); 3426f22ef01cSRoman Divacky // Inline pattern fragments into it. 3427f22ef01cSRoman Divacky I->InlinePatternFragments(); 3428f22ef01cSRoman Divacky 3429f22ef01cSRoman Divacky // Infer as many types as possible. If we cannot infer all of them, we can 3430f22ef01cSRoman Divacky // never do anything with this instruction pattern: report it to the user. 3431f22ef01cSRoman Divacky if (!I->InferAllTypes()) 3432f22ef01cSRoman Divacky I->error("Could not infer all types in pattern!"); 3433f22ef01cSRoman Divacky 3434f22ef01cSRoman Divacky // InstInputs - Keep track of all of the inputs of the instruction, along 3435f22ef01cSRoman Divacky // with the record they are declared as. 3436f22ef01cSRoman Divacky std::map<std::string, TreePatternNode*> InstInputs; 3437f22ef01cSRoman Divacky 3438f22ef01cSRoman Divacky // InstResults - Keep track of all the virtual registers that are 'set' 3439f22ef01cSRoman Divacky // in the instruction, including what reg class they are. 3440f22ef01cSRoman Divacky std::map<std::string, TreePatternNode*> InstResults; 3441f22ef01cSRoman Divacky 3442f22ef01cSRoman Divacky std::vector<Record*> InstImpResults; 3443f22ef01cSRoman Divacky 3444f22ef01cSRoman Divacky // Verify that the top-level forms in the instruction are of void type, and 3445f22ef01cSRoman Divacky // fill in the InstResults map. 34462cab237bSDimitry Andric SmallString<32> TypesString; 3447f22ef01cSRoman Divacky for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { 34482cab237bSDimitry Andric TypesString.clear(); 3449f22ef01cSRoman Divacky TreePatternNode *Pat = I->getTree(j); 34503ca95b02SDimitry Andric if (Pat->getNumTypes() != 0) { 34512cab237bSDimitry Andric raw_svector_ostream OS(TypesString); 34523ca95b02SDimitry Andric for (unsigned k = 0, ke = Pat->getNumTypes(); k != ke; ++k) { 34533ca95b02SDimitry Andric if (k > 0) 34542cab237bSDimitry Andric OS << ", "; 34552cab237bSDimitry Andric Pat->getExtType(k).writeToStream(OS); 34563ca95b02SDimitry Andric } 3457f22ef01cSRoman Divacky I->error("Top-level forms in instruction pattern should have" 34582cab237bSDimitry Andric " void types, has types " + 34592cab237bSDimitry Andric OS.str()); 34603ca95b02SDimitry Andric } 3461f22ef01cSRoman Divacky 3462f22ef01cSRoman Divacky // Find inputs and outputs, and verify the structure of the uses/defs. 3463f22ef01cSRoman Divacky FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, 3464f22ef01cSRoman Divacky InstImpResults); 3465f22ef01cSRoman Divacky } 3466f22ef01cSRoman Divacky 3467f22ef01cSRoman Divacky // Now that we have inputs and outputs of the pattern, inspect the operands 3468f22ef01cSRoman Divacky // list for the instruction. This determines the order that operands are 3469f22ef01cSRoman Divacky // added to the machine instruction the node corresponds to. 3470f22ef01cSRoman Divacky unsigned NumResults = InstResults.size(); 3471f22ef01cSRoman Divacky 3472f22ef01cSRoman Divacky // Parse the operands list from the (ops) list, validating it. 3473f22ef01cSRoman Divacky assert(I->getArgList().empty() && "Args list should still be empty here!"); 3474f22ef01cSRoman Divacky 3475f22ef01cSRoman Divacky // Check that all of the results occur first in the list. 3476f22ef01cSRoman Divacky std::vector<Record*> Results; 3477ff0cc061SDimitry Andric SmallVector<TreePatternNode *, 2> ResNodes; 3478f22ef01cSRoman Divacky for (unsigned i = 0; i != NumResults; ++i) { 34792754fe60SDimitry Andric if (i == CGI.Operands.size()) 3480f22ef01cSRoman Divacky I->error("'" + InstResults.begin()->first + 3481f22ef01cSRoman Divacky "' set but does not appear in operand list!"); 34822754fe60SDimitry Andric const std::string &OpName = CGI.Operands[i].Name; 3483f22ef01cSRoman Divacky 3484f22ef01cSRoman Divacky // Check that it exists in InstResults. 3485f22ef01cSRoman Divacky TreePatternNode *RNode = InstResults[OpName]; 348691bc56edSDimitry Andric if (!RNode) 3487f22ef01cSRoman Divacky I->error("Operand $" + OpName + " does not exist in operand list!"); 3488f22ef01cSRoman Divacky 3489ff0cc061SDimitry Andric ResNodes.push_back(RNode); 3490ff0cc061SDimitry Andric 34913861d79fSDimitry Andric Record *R = cast<DefInit>(RNode->getLeafValue())->getDef(); 349291bc56edSDimitry Andric if (!R) 3493f22ef01cSRoman Divacky I->error("Operand $" + OpName + " should be a set destination: all " 3494f22ef01cSRoman Divacky "outputs must occur before inputs in operand list!"); 3495f22ef01cSRoman Divacky 3496139f7f9bSDimitry Andric if (!checkOperandClass(CGI.Operands[i], R)) 3497f22ef01cSRoman Divacky I->error("Operand $" + OpName + " class mismatch!"); 3498f22ef01cSRoman Divacky 3499f22ef01cSRoman Divacky // Remember the return type. 35002754fe60SDimitry Andric Results.push_back(CGI.Operands[i].Rec); 3501f22ef01cSRoman Divacky 3502f22ef01cSRoman Divacky // Okay, this one checks out. 3503f22ef01cSRoman Divacky InstResults.erase(OpName); 3504f22ef01cSRoman Divacky } 3505f22ef01cSRoman Divacky 3506f22ef01cSRoman Divacky // Loop over the inputs next. Make a copy of InstInputs so we can destroy 3507f22ef01cSRoman Divacky // the copy while we're checking the inputs. 3508f22ef01cSRoman Divacky std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs); 3509f22ef01cSRoman Divacky 3510f22ef01cSRoman Divacky std::vector<TreePatternNode*> ResultNodeOperands; 3511f22ef01cSRoman Divacky std::vector<Record*> Operands; 35122754fe60SDimitry Andric for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { 35132754fe60SDimitry Andric CGIOperandList::OperandInfo &Op = CGI.Operands[i]; 3514f22ef01cSRoman Divacky const std::string &OpName = Op.Name; 3515f22ef01cSRoman Divacky if (OpName.empty()) 3516fe4fed2eSDimitry Andric I->error("Operand #" + Twine(i) + " in operands list has no name!"); 3517f22ef01cSRoman Divacky 3518f22ef01cSRoman Divacky if (!InstInputsCheck.count(OpName)) { 35193861d79fSDimitry Andric // If this is an operand with a DefaultOps set filled in, we can ignore 35203861d79fSDimitry Andric // this. When we codegen it, we will do so as always executed. 35213861d79fSDimitry Andric if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) { 3522f22ef01cSRoman Divacky // Does it have a non-empty DefaultOps field? If so, ignore this 3523f22ef01cSRoman Divacky // operand. 3524f22ef01cSRoman Divacky if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) 3525f22ef01cSRoman Divacky continue; 3526f22ef01cSRoman Divacky } 3527f22ef01cSRoman Divacky I->error("Operand $" + OpName + 3528f22ef01cSRoman Divacky " does not appear in the instruction pattern"); 3529f22ef01cSRoman Divacky } 3530f22ef01cSRoman Divacky TreePatternNode *InVal = InstInputsCheck[OpName]; 3531f22ef01cSRoman Divacky InstInputsCheck.erase(OpName); // It occurred, remove from map. 3532f22ef01cSRoman Divacky 35333861d79fSDimitry Andric if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) { 3534f22ef01cSRoman Divacky Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef(); 3535139f7f9bSDimitry Andric if (!checkOperandClass(Op, InRec)) 3536f22ef01cSRoman Divacky I->error("Operand $" + OpName + "'s register class disagrees" 3537f22ef01cSRoman Divacky " between the operand and pattern"); 3538f22ef01cSRoman Divacky } 3539f22ef01cSRoman Divacky Operands.push_back(Op.Rec); 3540f22ef01cSRoman Divacky 3541f22ef01cSRoman Divacky // Construct the result for the dest-pattern operand list. 3542f22ef01cSRoman Divacky TreePatternNode *OpNode = InVal->clone(); 3543f22ef01cSRoman Divacky 3544f22ef01cSRoman Divacky // No predicate is useful on the result. 3545f22ef01cSRoman Divacky OpNode->clearPredicateFns(); 3546f22ef01cSRoman Divacky 3547f22ef01cSRoman Divacky // Promote the xform function to be an explicit node if set. 3548f22ef01cSRoman Divacky if (Record *Xform = OpNode->getTransformFn()) { 354991bc56edSDimitry Andric OpNode->setTransformFn(nullptr); 3550f22ef01cSRoman Divacky std::vector<TreePatternNode*> Children; 3551f22ef01cSRoman Divacky Children.push_back(OpNode); 3552f22ef01cSRoman Divacky OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); 3553f22ef01cSRoman Divacky } 3554f22ef01cSRoman Divacky 3555f22ef01cSRoman Divacky ResultNodeOperands.push_back(OpNode); 3556f22ef01cSRoman Divacky } 3557f22ef01cSRoman Divacky 3558f22ef01cSRoman Divacky if (!InstInputsCheck.empty()) 3559f22ef01cSRoman Divacky I->error("Input operand $" + InstInputsCheck.begin()->first + 3560f22ef01cSRoman Divacky " occurs in pattern but not in operands list!"); 3561f22ef01cSRoman Divacky 3562f22ef01cSRoman Divacky TreePatternNode *ResultPattern = 3563f22ef01cSRoman Divacky new TreePatternNode(I->getRecord(), ResultNodeOperands, 3564f22ef01cSRoman Divacky GetNumNodeResults(I->getRecord(), *this)); 3565ff0cc061SDimitry Andric // Copy fully inferred output node types to instruction result pattern. 3566ff0cc061SDimitry Andric for (unsigned i = 0; i != NumResults; ++i) { 3567ff0cc061SDimitry Andric assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled"); 3568ff0cc061SDimitry Andric ResultPattern->setType(i, ResNodes[i]->getExtType(0)); 3569ff0cc061SDimitry Andric } 3570f22ef01cSRoman Divacky 3571f22ef01cSRoman Divacky // Create and insert the instruction. 3572f22ef01cSRoman Divacky // FIXME: InstImpResults should not be part of DAGInstruction. 3573f22ef01cSRoman Divacky DAGInstruction TheInst(I, Results, Operands, InstImpResults); 3574f785676fSDimitry Andric DAGInsts.insert(std::make_pair(I->getRecord(), TheInst)); 3575f22ef01cSRoman Divacky 3576f22ef01cSRoman Divacky // Use a temporary tree pattern to infer all types and make sure that the 3577f22ef01cSRoman Divacky // constructed result is correct. This depends on the instruction already 3578f785676fSDimitry Andric // being inserted into the DAGInsts map. 3579f22ef01cSRoman Divacky TreePattern Temp(I->getRecord(), ResultPattern, false, *this); 3580f22ef01cSRoman Divacky Temp.InferAllTypes(&I->getNamedNodesMap()); 3581f22ef01cSRoman Divacky 3582f785676fSDimitry Andric DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second; 3583f22ef01cSRoman Divacky TheInsertedInst.setResultPattern(Temp.getOnlyTree()); 3584f22ef01cSRoman Divacky 3585f785676fSDimitry Andric return TheInsertedInst; 3586f785676fSDimitry Andric } 3587f785676fSDimitry Andric 3588f785676fSDimitry Andric /// ParseInstructions - Parse all of the instructions, inlining and resolving 3589f785676fSDimitry Andric /// any fragments involved. This populates the Instructions list with fully 3590f785676fSDimitry Andric /// resolved instructions. 3591f785676fSDimitry Andric void CodeGenDAGPatterns::ParseInstructions() { 3592f785676fSDimitry Andric std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction"); 3593f785676fSDimitry Andric 35947d523365SDimitry Andric for (Record *Instr : Instrs) { 359591bc56edSDimitry Andric ListInit *LI = nullptr; 3596f785676fSDimitry Andric 35977d523365SDimitry Andric if (isa<ListInit>(Instr->getValueInit("Pattern"))) 35987d523365SDimitry Andric LI = Instr->getValueAsListInit("Pattern"); 3599f785676fSDimitry Andric 3600f785676fSDimitry Andric // If there is no pattern, only collect minimal information about the 3601f785676fSDimitry Andric // instruction for its operand list. We have to assume that there is one 3602f785676fSDimitry Andric // result, as we have no detailed info. A pattern which references the 3603f785676fSDimitry Andric // null_frag operator is as-if no pattern were specified. Normally this 3604f785676fSDimitry Andric // is from a multiclass expansion w/ a SDPatternOperator passed in as 3605f785676fSDimitry Andric // null_frag. 3606ff0cc061SDimitry Andric if (!LI || LI->empty() || hasNullFragReference(LI)) { 3607f785676fSDimitry Andric std::vector<Record*> Results; 3608f785676fSDimitry Andric std::vector<Record*> Operands; 3609f785676fSDimitry Andric 36107d523365SDimitry Andric CodeGenInstruction &InstInfo = Target.getInstruction(Instr); 3611f785676fSDimitry Andric 3612f785676fSDimitry Andric if (InstInfo.Operands.size() != 0) { 3613ff0cc061SDimitry Andric for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j) 3614ff0cc061SDimitry Andric Results.push_back(InstInfo.Operands[j].Rec); 3615f785676fSDimitry Andric 3616f785676fSDimitry Andric // The rest are inputs. 3617ff0cc061SDimitry Andric for (unsigned j = InstInfo.Operands.NumDefs, 3618ff0cc061SDimitry Andric e = InstInfo.Operands.size(); j < e; ++j) 3619f785676fSDimitry Andric Operands.push_back(InstInfo.Operands[j].Rec); 3620f785676fSDimitry Andric } 3621f785676fSDimitry Andric 3622f785676fSDimitry Andric // Create and insert the instruction. 3623f785676fSDimitry Andric std::vector<Record*> ImpResults; 36247d523365SDimitry Andric Instructions.insert(std::make_pair(Instr, 362591bc56edSDimitry Andric DAGInstruction(nullptr, Results, Operands, ImpResults))); 3626f785676fSDimitry Andric continue; // no pattern. 3627f785676fSDimitry Andric } 3628f785676fSDimitry Andric 36297d523365SDimitry Andric CodeGenInstruction &CGI = Target.getInstruction(Instr); 3630f785676fSDimitry Andric const DAGInstruction &DI = parseInstructionPattern(CGI, LI, Instructions); 3631f785676fSDimitry Andric 3632f785676fSDimitry Andric (void)DI; 3633f785676fSDimitry Andric DEBUG(DI.getPattern()->dump()); 3634f22ef01cSRoman Divacky } 3635f22ef01cSRoman Divacky 3636f22ef01cSRoman Divacky // If we can, convert the instructions to be patterns that are matched! 36377d523365SDimitry Andric for (auto &Entry : Instructions) { 36387d523365SDimitry Andric DAGInstruction &TheInst = Entry.second; 36393861d79fSDimitry Andric TreePattern *I = TheInst.getPattern(); 364091bc56edSDimitry Andric if (!I) continue; // No pattern. 3641f22ef01cSRoman Divacky 36422cab237bSDimitry Andric if (PatternRewriter) 36432cab237bSDimitry Andric PatternRewriter(I); 3644f22ef01cSRoman Divacky // FIXME: Assume only the first tree is the pattern. The others are clobber 3645f22ef01cSRoman Divacky // nodes. 3646f22ef01cSRoman Divacky TreePatternNode *Pattern = I->getTree(0); 3647f22ef01cSRoman Divacky TreePatternNode *SrcPattern; 3648f22ef01cSRoman Divacky if (Pattern->getOperator()->getName() == "set") { 3649f22ef01cSRoman Divacky SrcPattern = Pattern->getChild(Pattern->getNumChildren()-1)->clone(); 3650f22ef01cSRoman Divacky } else{ 3651f22ef01cSRoman Divacky // Not a set (store or something?) 3652f22ef01cSRoman Divacky SrcPattern = Pattern; 3653f22ef01cSRoman Divacky } 3654f22ef01cSRoman Divacky 36557d523365SDimitry Andric Record *Instr = Entry.first; 36562cab237bSDimitry Andric ListInit *Preds = Instr->getValueAsListInit("Predicates"); 36572cab237bSDimitry Andric int Complexity = Instr->getValueAsInt("AddedComplexity"); 36582cab237bSDimitry Andric AddPatternToMatch( 36592cab237bSDimitry Andric I, 36602cab237bSDimitry Andric PatternToMatch(Instr, makePredList(Preds), SrcPattern, 36612cab237bSDimitry Andric TheInst.getResultPattern(), TheInst.getImpResults(), 36622cab237bSDimitry Andric Complexity, Instr->getID())); 3663f22ef01cSRoman Divacky } 3664f22ef01cSRoman Divacky } 3665f22ef01cSRoman Divacky 3666f22ef01cSRoman Divacky 3667f22ef01cSRoman Divacky typedef std::pair<const TreePatternNode*, unsigned> NameRecord; 3668f22ef01cSRoman Divacky 3669f22ef01cSRoman Divacky static void FindNames(const TreePatternNode *P, 3670f22ef01cSRoman Divacky std::map<std::string, NameRecord> &Names, 36713861d79fSDimitry Andric TreePattern *PatternTop) { 3672f22ef01cSRoman Divacky if (!P->getName().empty()) { 3673f22ef01cSRoman Divacky NameRecord &Rec = Names[P->getName()]; 3674f22ef01cSRoman Divacky // If this is the first instance of the name, remember the node. 3675f22ef01cSRoman Divacky if (Rec.second++ == 0) 3676f22ef01cSRoman Divacky Rec.first = P; 3677f22ef01cSRoman Divacky else if (Rec.first->getExtTypes() != P->getExtTypes()) 3678f22ef01cSRoman Divacky PatternTop->error("repetition of value: $" + P->getName() + 3679f22ef01cSRoman Divacky " where different uses have different types!"); 3680f22ef01cSRoman Divacky } 3681f22ef01cSRoman Divacky 3682f22ef01cSRoman Divacky if (!P->isLeaf()) { 3683f22ef01cSRoman Divacky for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) 3684f22ef01cSRoman Divacky FindNames(P->getChild(i), Names, PatternTop); 3685f22ef01cSRoman Divacky } 3686f22ef01cSRoman Divacky } 3687f22ef01cSRoman Divacky 36882cab237bSDimitry Andric std::vector<Predicate> CodeGenDAGPatterns::makePredList(ListInit *L) { 36892cab237bSDimitry Andric std::vector<Predicate> Preds; 36902cab237bSDimitry Andric for (Init *I : L->getValues()) { 36912cab237bSDimitry Andric if (DefInit *Pred = dyn_cast<DefInit>(I)) 36922cab237bSDimitry Andric Preds.push_back(Pred->getDef()); 36932cab237bSDimitry Andric else 36942cab237bSDimitry Andric llvm_unreachable("Non-def on the list"); 36952cab237bSDimitry Andric } 36962cab237bSDimitry Andric 36972cab237bSDimitry Andric // Sort so that different orders get canonicalized to the same string. 36982cab237bSDimitry Andric std::sort(Preds.begin(), Preds.end()); 36992cab237bSDimitry Andric return Preds; 37002cab237bSDimitry Andric } 37012cab237bSDimitry Andric 37023861d79fSDimitry Andric void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, 3703edd7eaddSDimitry Andric PatternToMatch &&PTM) { 3704f22ef01cSRoman Divacky // Do some sanity checking on the pattern we're about to match. 3705f22ef01cSRoman Divacky std::string Reason; 37063861d79fSDimitry Andric if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this)) { 37073861d79fSDimitry Andric PrintWarning(Pattern->getRecord()->getLoc(), 37083861d79fSDimitry Andric Twine("Pattern can never match: ") + Reason); 37093861d79fSDimitry Andric return; 37103861d79fSDimitry Andric } 3711f22ef01cSRoman Divacky 3712f22ef01cSRoman Divacky // If the source pattern's root is a complex pattern, that complex pattern 3713f22ef01cSRoman Divacky // must specify the nodes it can potentially match. 3714f22ef01cSRoman Divacky if (const ComplexPattern *CP = 3715f22ef01cSRoman Divacky PTM.getSrcPattern()->getComplexPatternInfo(*this)) 3716f22ef01cSRoman Divacky if (CP->getRootNodes().empty()) 3717f22ef01cSRoman Divacky Pattern->error("ComplexPattern at root must specify list of opcodes it" 3718f22ef01cSRoman Divacky " could match"); 3719f22ef01cSRoman Divacky 3720f22ef01cSRoman Divacky 3721f22ef01cSRoman Divacky // Find all of the named values in the input and output, ensure they have the 3722f22ef01cSRoman Divacky // same type. 3723f22ef01cSRoman Divacky std::map<std::string, NameRecord> SrcNames, DstNames; 3724f22ef01cSRoman Divacky FindNames(PTM.getSrcPattern(), SrcNames, Pattern); 3725f22ef01cSRoman Divacky FindNames(PTM.getDstPattern(), DstNames, Pattern); 3726f22ef01cSRoman Divacky 3727f22ef01cSRoman Divacky // Scan all of the named values in the destination pattern, rejecting them if 3728f22ef01cSRoman Divacky // they don't exist in the input pattern. 37297d523365SDimitry Andric for (const auto &Entry : DstNames) { 37307d523365SDimitry Andric if (SrcNames[Entry.first].first == nullptr) 3731f22ef01cSRoman Divacky Pattern->error("Pattern has input without matching name in output: $" + 37327d523365SDimitry Andric Entry.first); 3733f22ef01cSRoman Divacky } 3734f22ef01cSRoman Divacky 3735f22ef01cSRoman Divacky // Scan all of the named values in the source pattern, rejecting them if the 3736f22ef01cSRoman Divacky // name isn't used in the dest, and isn't used to tie two values together. 37377d523365SDimitry Andric for (const auto &Entry : SrcNames) 37387d523365SDimitry Andric if (DstNames[Entry.first].first == nullptr && 37397d523365SDimitry Andric SrcNames[Entry.first].second == 1) 37407d523365SDimitry Andric Pattern->error("Pattern has dead named input: $" + Entry.first); 3741f22ef01cSRoman Divacky 3742edd7eaddSDimitry Andric PatternsToMatch.push_back(std::move(PTM)); 3743f22ef01cSRoman Divacky } 3744f22ef01cSRoman Divacky 3745f22ef01cSRoman Divacky void CodeGenDAGPatterns::InferInstructionFlags() { 37463ca95b02SDimitry Andric ArrayRef<const CodeGenInstruction*> Instructions = 3747f22ef01cSRoman Divacky Target.getInstructionsByEnumValue(); 37483861d79fSDimitry Andric 37493861d79fSDimitry Andric // First try to infer flags from the primary instruction pattern, if any. 37503861d79fSDimitry Andric SmallVector<CodeGenInstruction*, 8> Revisit; 37513861d79fSDimitry Andric unsigned Errors = 0; 3752f22ef01cSRoman Divacky for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { 3753f22ef01cSRoman Divacky CodeGenInstruction &InstInfo = 3754f22ef01cSRoman Divacky const_cast<CodeGenInstruction &>(*Instructions[i]); 37556122f3e6SDimitry Andric 37563861d79fSDimitry Andric // Get the primary instruction pattern. 37573861d79fSDimitry Andric const TreePattern *Pattern = getInstruction(InstInfo.TheDef).getPattern(); 37583861d79fSDimitry Andric if (!Pattern) { 37593861d79fSDimitry Andric if (InstInfo.hasUndefFlags()) 37603861d79fSDimitry Andric Revisit.push_back(&InstInfo); 37613861d79fSDimitry Andric continue; 37623861d79fSDimitry Andric } 37633861d79fSDimitry Andric InstAnalyzer PatInfo(*this); 37643861d79fSDimitry Andric PatInfo.Analyze(Pattern); 37653861d79fSDimitry Andric Errors += InferFromPattern(InstInfo, PatInfo, InstInfo.TheDef); 37663861d79fSDimitry Andric } 37673861d79fSDimitry Andric 37683861d79fSDimitry Andric // Second, look for single-instruction patterns defined outside the 37693861d79fSDimitry Andric // instruction. 3770edd7eaddSDimitry Andric for (const PatternToMatch &PTM : ptms()) { 37713861d79fSDimitry Andric // We can only infer from single-instruction patterns, otherwise we won't 37723861d79fSDimitry Andric // know which instruction should get the flags. 37733861d79fSDimitry Andric SmallVector<Record*, 8> PatInstrs; 37743861d79fSDimitry Andric getInstructionsInTree(PTM.getDstPattern(), PatInstrs); 37753861d79fSDimitry Andric if (PatInstrs.size() != 1) 37763861d79fSDimitry Andric continue; 37773861d79fSDimitry Andric 37783861d79fSDimitry Andric // Get the single instruction. 37793861d79fSDimitry Andric CodeGenInstruction &InstInfo = Target.getInstruction(PatInstrs.front()); 37803861d79fSDimitry Andric 37813861d79fSDimitry Andric // Only infer properties from the first pattern. We'll verify the others. 37823861d79fSDimitry Andric if (InstInfo.InferredFrom) 37833861d79fSDimitry Andric continue; 37843861d79fSDimitry Andric 37853861d79fSDimitry Andric InstAnalyzer PatInfo(*this); 3786edd7eaddSDimitry Andric PatInfo.Analyze(PTM); 37873861d79fSDimitry Andric Errors += InferFromPattern(InstInfo, PatInfo, PTM.getSrcRecord()); 37883861d79fSDimitry Andric } 37893861d79fSDimitry Andric 37903861d79fSDimitry Andric if (Errors) 37913861d79fSDimitry Andric PrintFatalError("pattern conflicts"); 37923861d79fSDimitry Andric 37933861d79fSDimitry Andric // Revisit instructions with undefined flags and no pattern. 37943861d79fSDimitry Andric if (Target.guessInstructionProperties()) { 37957d523365SDimitry Andric for (CodeGenInstruction *InstInfo : Revisit) { 37967d523365SDimitry Andric if (InstInfo->InferredFrom) 37973861d79fSDimitry Andric continue; 37983861d79fSDimitry Andric // The mayLoad and mayStore flags default to false. 37993861d79fSDimitry Andric // Conservatively assume hasSideEffects if it wasn't explicit. 38007d523365SDimitry Andric if (InstInfo->hasSideEffects_Unset) 38017d523365SDimitry Andric InstInfo->hasSideEffects = true; 38023861d79fSDimitry Andric } 38033861d79fSDimitry Andric return; 38043861d79fSDimitry Andric } 38053861d79fSDimitry Andric 38063861d79fSDimitry Andric // Complain about any flags that are still undefined. 38077d523365SDimitry Andric for (CodeGenInstruction *InstInfo : Revisit) { 38087d523365SDimitry Andric if (InstInfo->InferredFrom) 38093861d79fSDimitry Andric continue; 38107d523365SDimitry Andric if (InstInfo->hasSideEffects_Unset) 38117d523365SDimitry Andric PrintError(InstInfo->TheDef->getLoc(), 38123861d79fSDimitry Andric "Can't infer hasSideEffects from patterns"); 38137d523365SDimitry Andric if (InstInfo->mayStore_Unset) 38147d523365SDimitry Andric PrintError(InstInfo->TheDef->getLoc(), 38153861d79fSDimitry Andric "Can't infer mayStore from patterns"); 38167d523365SDimitry Andric if (InstInfo->mayLoad_Unset) 38177d523365SDimitry Andric PrintError(InstInfo->TheDef->getLoc(), 38183861d79fSDimitry Andric "Can't infer mayLoad from patterns"); 38193861d79fSDimitry Andric } 38203861d79fSDimitry Andric } 38213861d79fSDimitry Andric 38223861d79fSDimitry Andric 38233861d79fSDimitry Andric /// Verify instruction flags against pattern node properties. 38243861d79fSDimitry Andric void CodeGenDAGPatterns::VerifyInstructionFlags() { 38253861d79fSDimitry Andric unsigned Errors = 0; 38263861d79fSDimitry Andric for (ptm_iterator I = ptm_begin(), E = ptm_end(); I != E; ++I) { 38273861d79fSDimitry Andric const PatternToMatch &PTM = *I; 38283861d79fSDimitry Andric SmallVector<Record*, 8> Instrs; 38293861d79fSDimitry Andric getInstructionsInTree(PTM.getDstPattern(), Instrs); 38303861d79fSDimitry Andric if (Instrs.empty()) 38313861d79fSDimitry Andric continue; 38323861d79fSDimitry Andric 38333861d79fSDimitry Andric // Count the number of instructions with each flag set. 38343861d79fSDimitry Andric unsigned NumSideEffects = 0; 38353861d79fSDimitry Andric unsigned NumStores = 0; 38363861d79fSDimitry Andric unsigned NumLoads = 0; 38377d523365SDimitry Andric for (const Record *Instr : Instrs) { 38387d523365SDimitry Andric const CodeGenInstruction &InstInfo = Target.getInstruction(Instr); 38393861d79fSDimitry Andric NumSideEffects += InstInfo.hasSideEffects; 38403861d79fSDimitry Andric NumStores += InstInfo.mayStore; 38413861d79fSDimitry Andric NumLoads += InstInfo.mayLoad; 38423861d79fSDimitry Andric } 38433861d79fSDimitry Andric 38443861d79fSDimitry Andric // Analyze the source pattern. 38453861d79fSDimitry Andric InstAnalyzer PatInfo(*this); 3846edd7eaddSDimitry Andric PatInfo.Analyze(PTM); 38473861d79fSDimitry Andric 38483861d79fSDimitry Andric // Collect error messages. 38493861d79fSDimitry Andric SmallVector<std::string, 4> Msgs; 38503861d79fSDimitry Andric 38513861d79fSDimitry Andric // Check for missing flags in the output. 38523861d79fSDimitry Andric // Permit extra flags for now at least. 38533861d79fSDimitry Andric if (PatInfo.hasSideEffects && !NumSideEffects) 38543861d79fSDimitry Andric Msgs.push_back("pattern has side effects, but hasSideEffects isn't set"); 38553861d79fSDimitry Andric 38563861d79fSDimitry Andric // Don't verify store flags on instructions with side effects. At least for 38573861d79fSDimitry Andric // intrinsics, side effects implies mayStore. 38583861d79fSDimitry Andric if (!PatInfo.hasSideEffects && PatInfo.mayStore && !NumStores) 38593861d79fSDimitry Andric Msgs.push_back("pattern may store, but mayStore isn't set"); 38603861d79fSDimitry Andric 38613861d79fSDimitry Andric // Similarly, mayStore implies mayLoad on intrinsics. 38623861d79fSDimitry Andric if (!PatInfo.mayStore && PatInfo.mayLoad && !NumLoads) 38633861d79fSDimitry Andric Msgs.push_back("pattern may load, but mayLoad isn't set"); 38643861d79fSDimitry Andric 38653861d79fSDimitry Andric // Print error messages. 38663861d79fSDimitry Andric if (Msgs.empty()) 38673861d79fSDimitry Andric continue; 38683861d79fSDimitry Andric ++Errors; 38693861d79fSDimitry Andric 38707d523365SDimitry Andric for (const std::string &Msg : Msgs) 38717d523365SDimitry Andric PrintError(PTM.getSrcRecord()->getLoc(), Twine(Msg) + " on the " + 38723861d79fSDimitry Andric (Instrs.size() == 1 ? 38733861d79fSDimitry Andric "instruction" : "output instructions")); 38743861d79fSDimitry Andric // Provide the location of the relevant instruction definitions. 38757d523365SDimitry Andric for (const Record *Instr : Instrs) { 38767d523365SDimitry Andric if (Instr != PTM.getSrcRecord()) 38777d523365SDimitry Andric PrintError(Instr->getLoc(), "defined here"); 38787d523365SDimitry Andric const CodeGenInstruction &InstInfo = Target.getInstruction(Instr); 38793861d79fSDimitry Andric if (InstInfo.InferredFrom && 38803861d79fSDimitry Andric InstInfo.InferredFrom != InstInfo.TheDef && 38813861d79fSDimitry Andric InstInfo.InferredFrom != PTM.getSrcRecord()) 38827d523365SDimitry Andric PrintError(InstInfo.InferredFrom->getLoc(), "inferred from pattern"); 38833861d79fSDimitry Andric } 38843861d79fSDimitry Andric } 38853861d79fSDimitry Andric if (Errors) 38863861d79fSDimitry Andric PrintFatalError("Errors in DAG patterns"); 3887f22ef01cSRoman Divacky } 3888f22ef01cSRoman Divacky 3889f22ef01cSRoman Divacky /// Given a pattern result with an unresolved type, see if we can find one 3890f22ef01cSRoman Divacky /// instruction with an unresolved result type. Force this result type to an 3891f22ef01cSRoman Divacky /// arbitrary element if it's possible types to converge results. 3892f22ef01cSRoman Divacky static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) { 3893f22ef01cSRoman Divacky if (N->isLeaf()) 3894f22ef01cSRoman Divacky return false; 3895f22ef01cSRoman Divacky 3896f22ef01cSRoman Divacky // Analyze children. 3897f22ef01cSRoman Divacky for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) 3898f22ef01cSRoman Divacky if (ForceArbitraryInstResultType(N->getChild(i), TP)) 3899f22ef01cSRoman Divacky return true; 3900f22ef01cSRoman Divacky 3901f22ef01cSRoman Divacky if (!N->getOperator()->isSubClassOf("Instruction")) 3902f22ef01cSRoman Divacky return false; 3903f22ef01cSRoman Divacky 3904f22ef01cSRoman Divacky // If this type is already concrete or completely unknown we can't do 3905f22ef01cSRoman Divacky // anything. 39062cab237bSDimitry Andric TypeInfer &TI = TP.getInfer(); 3907f22ef01cSRoman Divacky for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) { 39082cab237bSDimitry Andric if (N->getExtType(i).empty() || TI.isConcrete(N->getExtType(i), false)) 3909f22ef01cSRoman Divacky continue; 3910f22ef01cSRoman Divacky 39112cab237bSDimitry Andric // Otherwise, force its type to an arbitrary choice. 39122cab237bSDimitry Andric if (TI.forceArbitrary(N->getExtType(i))) 3913f22ef01cSRoman Divacky return true; 3914f22ef01cSRoman Divacky } 3915f22ef01cSRoman Divacky 3916f22ef01cSRoman Divacky return false; 3917f22ef01cSRoman Divacky } 3918f22ef01cSRoman Divacky 3919f22ef01cSRoman Divacky void CodeGenDAGPatterns::ParsePatterns() { 3920f22ef01cSRoman Divacky std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern"); 3921f22ef01cSRoman Divacky 39227d523365SDimitry Andric for (Record *CurPattern : Patterns) { 3923f22ef01cSRoman Divacky DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch"); 39247ae0e2c9SDimitry Andric 39257ae0e2c9SDimitry Andric // If the pattern references the null_frag, there's nothing to do. 39267ae0e2c9SDimitry Andric if (hasNullFragReference(Tree)) 39277ae0e2c9SDimitry Andric continue; 39287ae0e2c9SDimitry Andric 3929f22ef01cSRoman Divacky TreePattern *Pattern = new TreePattern(CurPattern, Tree, true, *this); 3930f22ef01cSRoman Divacky 3931f22ef01cSRoman Divacky // Inline pattern fragments into it. 3932f22ef01cSRoman Divacky Pattern->InlinePatternFragments(); 3933f22ef01cSRoman Divacky 3934f22ef01cSRoman Divacky ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); 3935ff0cc061SDimitry Andric if (LI->empty()) continue; // no pattern. 3936f22ef01cSRoman Divacky 3937f22ef01cSRoman Divacky // Parse the instruction. 393839d628a0SDimitry Andric TreePattern Result(CurPattern, LI, false, *this); 3939f22ef01cSRoman Divacky 3940f22ef01cSRoman Divacky // Inline pattern fragments into it. 394139d628a0SDimitry Andric Result.InlinePatternFragments(); 3942f22ef01cSRoman Divacky 394339d628a0SDimitry Andric if (Result.getNumTrees() != 1) 394439d628a0SDimitry Andric Result.error("Cannot handle instructions producing instructions " 3945f22ef01cSRoman Divacky "with temporaries yet!"); 3946f22ef01cSRoman Divacky 3947f22ef01cSRoman Divacky bool IterateInference; 3948f22ef01cSRoman Divacky bool InferredAllPatternTypes, InferredAllResultTypes; 3949f22ef01cSRoman Divacky do { 3950f22ef01cSRoman Divacky // Infer as many types as possible. If we cannot infer all of them, we 3951f22ef01cSRoman Divacky // can never do anything with this pattern: report it to the user. 3952f22ef01cSRoman Divacky InferredAllPatternTypes = 3953f22ef01cSRoman Divacky Pattern->InferAllTypes(&Pattern->getNamedNodesMap()); 3954f22ef01cSRoman Divacky 3955f22ef01cSRoman Divacky // Infer as many types as possible. If we cannot infer all of them, we 3956f22ef01cSRoman Divacky // can never do anything with this pattern: report it to the user. 3957f22ef01cSRoman Divacky InferredAllResultTypes = 395839d628a0SDimitry Andric Result.InferAllTypes(&Pattern->getNamedNodesMap()); 3959f22ef01cSRoman Divacky 3960f22ef01cSRoman Divacky IterateInference = false; 3961f22ef01cSRoman Divacky 3962f22ef01cSRoman Divacky // Apply the type of the result to the source pattern. This helps us 3963f22ef01cSRoman Divacky // resolve cases where the input type is known to be a pointer type (which 3964f22ef01cSRoman Divacky // is considered resolved), but the result knows it needs to be 32- or 3965f22ef01cSRoman Divacky // 64-bits. Infer the other way for good measure. 396639d628a0SDimitry Andric for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(), 3967f22ef01cSRoman Divacky Pattern->getTree(0)->getNumTypes()); 3968f22ef01cSRoman Divacky i != e; ++i) { 396939d628a0SDimitry Andric IterateInference = Pattern->getTree(0)->UpdateNodeType( 397039d628a0SDimitry Andric i, Result.getTree(0)->getExtType(i), Result); 397139d628a0SDimitry Andric IterateInference |= Result.getTree(0)->UpdateNodeType( 397239d628a0SDimitry Andric i, Pattern->getTree(0)->getExtType(i), Result); 3973f22ef01cSRoman Divacky } 3974f22ef01cSRoman Divacky 3975f22ef01cSRoman Divacky // If our iteration has converged and the input pattern's types are fully 3976f22ef01cSRoman Divacky // resolved but the result pattern is not fully resolved, we may have a 3977f22ef01cSRoman Divacky // situation where we have two instructions in the result pattern and 3978f22ef01cSRoman Divacky // the instructions require a common register class, but don't care about 3979f22ef01cSRoman Divacky // what actual MVT is used. This is actually a bug in our modelling: 3980f22ef01cSRoman Divacky // output patterns should have register classes, not MVTs. 3981f22ef01cSRoman Divacky // 3982f22ef01cSRoman Divacky // In any case, to handle this, we just go through and disambiguate some 3983f22ef01cSRoman Divacky // arbitrary types to the result pattern's nodes. 3984f22ef01cSRoman Divacky if (!IterateInference && InferredAllPatternTypes && 3985f22ef01cSRoman Divacky !InferredAllResultTypes) 398639d628a0SDimitry Andric IterateInference = 398739d628a0SDimitry Andric ForceArbitraryInstResultType(Result.getTree(0), Result); 3988f22ef01cSRoman Divacky } while (IterateInference); 3989f22ef01cSRoman Divacky 3990f22ef01cSRoman Divacky // Verify that we inferred enough types that we can do something with the 3991f22ef01cSRoman Divacky // pattern and result. If these fire the user has to add type casts. 3992f22ef01cSRoman Divacky if (!InferredAllPatternTypes) 3993f22ef01cSRoman Divacky Pattern->error("Could not infer all types in pattern!"); 3994f22ef01cSRoman Divacky if (!InferredAllResultTypes) { 3995f22ef01cSRoman Divacky Pattern->dump(); 399639d628a0SDimitry Andric Result.error("Could not infer all types in pattern result!"); 3997f22ef01cSRoman Divacky } 3998f22ef01cSRoman Divacky 3999f22ef01cSRoman Divacky // Validate that the input pattern is correct. 4000f22ef01cSRoman Divacky std::map<std::string, TreePatternNode*> InstInputs; 4001f22ef01cSRoman Divacky std::map<std::string, TreePatternNode*> InstResults; 4002f22ef01cSRoman Divacky std::vector<Record*> InstImpResults; 4003f22ef01cSRoman Divacky for (unsigned j = 0, ee = Pattern->getNumTrees(); j != ee; ++j) 4004f22ef01cSRoman Divacky FindPatternInputsAndOutputs(Pattern, Pattern->getTree(j), 4005f22ef01cSRoman Divacky InstInputs, InstResults, 4006f22ef01cSRoman Divacky InstImpResults); 4007f22ef01cSRoman Divacky 4008f22ef01cSRoman Divacky // Promote the xform function to be an explicit node if set. 400939d628a0SDimitry Andric TreePatternNode *DstPattern = Result.getOnlyTree(); 4010f22ef01cSRoman Divacky std::vector<TreePatternNode*> ResultNodeOperands; 4011f22ef01cSRoman Divacky for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) { 4012f22ef01cSRoman Divacky TreePatternNode *OpNode = DstPattern->getChild(ii); 4013f22ef01cSRoman Divacky if (Record *Xform = OpNode->getTransformFn()) { 401491bc56edSDimitry Andric OpNode->setTransformFn(nullptr); 4015f22ef01cSRoman Divacky std::vector<TreePatternNode*> Children; 4016f22ef01cSRoman Divacky Children.push_back(OpNode); 4017f22ef01cSRoman Divacky OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); 4018f22ef01cSRoman Divacky } 4019f22ef01cSRoman Divacky ResultNodeOperands.push_back(OpNode); 4020f22ef01cSRoman Divacky } 402139d628a0SDimitry Andric DstPattern = Result.getOnlyTree(); 4022f22ef01cSRoman Divacky if (!DstPattern->isLeaf()) 4023f22ef01cSRoman Divacky DstPattern = new TreePatternNode(DstPattern->getOperator(), 4024f22ef01cSRoman Divacky ResultNodeOperands, 4025f22ef01cSRoman Divacky DstPattern->getNumTypes()); 4026f22ef01cSRoman Divacky 402739d628a0SDimitry Andric for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i) 402839d628a0SDimitry Andric DstPattern->setType(i, Result.getOnlyTree()->getExtType(i)); 4029f22ef01cSRoman Divacky 403039d628a0SDimitry Andric TreePattern Temp(Result.getRecord(), DstPattern, false, *this); 4031f22ef01cSRoman Divacky Temp.InferAllTypes(); 4032f22ef01cSRoman Divacky 40332cab237bSDimitry Andric // A pattern may end up with an "impossible" type, i.e. a situation 40342cab237bSDimitry Andric // where all types have been eliminated for some node in this pattern. 40352cab237bSDimitry Andric // This could occur for intrinsics that only make sense for a specific 40362cab237bSDimitry Andric // value type, and use a specific register class. If, for some mode, 40372cab237bSDimitry Andric // that register class does not accept that type, the type inference 40382cab237bSDimitry Andric // will lead to a contradiction, which is not an error however, but 40392cab237bSDimitry Andric // a sign that this pattern will simply never match. 40402cab237bSDimitry Andric if (Pattern->getTree(0)->hasPossibleType() && 40412cab237bSDimitry Andric Temp.getOnlyTree()->hasPossibleType()) { 40422cab237bSDimitry Andric ListInit *Preds = CurPattern->getValueAsListInit("Predicates"); 40432cab237bSDimitry Andric int Complexity = CurPattern->getValueAsInt("AddedComplexity"); 40442cab237bSDimitry Andric if (PatternRewriter) 40452cab237bSDimitry Andric PatternRewriter(Pattern); 4046edd7eaddSDimitry Andric AddPatternToMatch( 4047edd7eaddSDimitry Andric Pattern, 4048edd7eaddSDimitry Andric PatternToMatch( 40492cab237bSDimitry Andric CurPattern, makePredList(Preds), Pattern->getTree(0), 40502cab237bSDimitry Andric Temp.getOnlyTree(), std::move(InstImpResults), Complexity, 40512cab237bSDimitry Andric CurPattern->getID())); 4052f22ef01cSRoman Divacky } 4053f22ef01cSRoman Divacky } 40542cab237bSDimitry Andric } 40552cab237bSDimitry Andric 40562cab237bSDimitry Andric static void collectModes(std::set<unsigned> &Modes, const TreePatternNode *N) { 40572cab237bSDimitry Andric for (const TypeSetByHwMode &VTS : N->getExtTypes()) 40582cab237bSDimitry Andric for (const auto &I : VTS) 40592cab237bSDimitry Andric Modes.insert(I.first); 40602cab237bSDimitry Andric 40612cab237bSDimitry Andric for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) 40622cab237bSDimitry Andric collectModes(Modes, N->getChild(i)); 40632cab237bSDimitry Andric } 40642cab237bSDimitry Andric 40652cab237bSDimitry Andric void CodeGenDAGPatterns::ExpandHwModeBasedTypes() { 40662cab237bSDimitry Andric const CodeGenHwModes &CGH = getTargetInfo().getHwModes(); 40672cab237bSDimitry Andric std::map<unsigned,std::vector<Predicate>> ModeChecks; 40682cab237bSDimitry Andric std::vector<PatternToMatch> Copy = PatternsToMatch; 40692cab237bSDimitry Andric PatternsToMatch.clear(); 40702cab237bSDimitry Andric 40712cab237bSDimitry Andric auto AppendPattern = [this,&ModeChecks](PatternToMatch &P, unsigned Mode) { 40722cab237bSDimitry Andric TreePatternNode *NewSrc = P.SrcPattern->clone(); 40732cab237bSDimitry Andric TreePatternNode *NewDst = P.DstPattern->clone(); 40742cab237bSDimitry Andric if (!NewSrc->setDefaultMode(Mode) || !NewDst->setDefaultMode(Mode)) { 40752cab237bSDimitry Andric delete NewSrc; 40762cab237bSDimitry Andric delete NewDst; 40772cab237bSDimitry Andric return; 40782cab237bSDimitry Andric } 40792cab237bSDimitry Andric 40802cab237bSDimitry Andric std::vector<Predicate> Preds = P.Predicates; 40812cab237bSDimitry Andric const std::vector<Predicate> &MC = ModeChecks[Mode]; 40822cab237bSDimitry Andric Preds.insert(Preds.end(), MC.begin(), MC.end()); 40832cab237bSDimitry Andric PatternsToMatch.emplace_back(P.getSrcRecord(), Preds, NewSrc, NewDst, 40842cab237bSDimitry Andric P.getDstRegs(), P.getAddedComplexity(), 40852cab237bSDimitry Andric Record::getNewUID(), Mode); 40862cab237bSDimitry Andric }; 40872cab237bSDimitry Andric 40882cab237bSDimitry Andric for (PatternToMatch &P : Copy) { 40892cab237bSDimitry Andric TreePatternNode *SrcP = nullptr, *DstP = nullptr; 40902cab237bSDimitry Andric if (P.SrcPattern->hasProperTypeByHwMode()) 40912cab237bSDimitry Andric SrcP = P.SrcPattern; 40922cab237bSDimitry Andric if (P.DstPattern->hasProperTypeByHwMode()) 40932cab237bSDimitry Andric DstP = P.DstPattern; 40942cab237bSDimitry Andric if (!SrcP && !DstP) { 40952cab237bSDimitry Andric PatternsToMatch.push_back(P); 40962cab237bSDimitry Andric continue; 40972cab237bSDimitry Andric } 40982cab237bSDimitry Andric 40992cab237bSDimitry Andric std::set<unsigned> Modes; 41002cab237bSDimitry Andric if (SrcP) 41012cab237bSDimitry Andric collectModes(Modes, SrcP); 41022cab237bSDimitry Andric if (DstP) 41032cab237bSDimitry Andric collectModes(Modes, DstP); 41042cab237bSDimitry Andric 41052cab237bSDimitry Andric // The predicate for the default mode needs to be constructed for each 41062cab237bSDimitry Andric // pattern separately. 41072cab237bSDimitry Andric // Since not all modes must be present in each pattern, if a mode m is 41082cab237bSDimitry Andric // absent, then there is no point in constructing a check for m. If such 41092cab237bSDimitry Andric // a check was created, it would be equivalent to checking the default 41102cab237bSDimitry Andric // mode, except not all modes' predicates would be a part of the checking 41112cab237bSDimitry Andric // code. The subsequently generated check for the default mode would then 41122cab237bSDimitry Andric // have the exact same patterns, but a different predicate code. To avoid 41132cab237bSDimitry Andric // duplicated patterns with different predicate checks, construct the 41142cab237bSDimitry Andric // default check as a negation of all predicates that are actually present 41152cab237bSDimitry Andric // in the source/destination patterns. 41162cab237bSDimitry Andric std::vector<Predicate> DefaultPred; 41172cab237bSDimitry Andric 41182cab237bSDimitry Andric for (unsigned M : Modes) { 41192cab237bSDimitry Andric if (M == DefaultMode) 41202cab237bSDimitry Andric continue; 41212cab237bSDimitry Andric if (ModeChecks.find(M) != ModeChecks.end()) 41222cab237bSDimitry Andric continue; 41232cab237bSDimitry Andric 41242cab237bSDimitry Andric // Fill the map entry for this mode. 41252cab237bSDimitry Andric const HwMode &HM = CGH.getMode(M); 41262cab237bSDimitry Andric ModeChecks[M].emplace_back(Predicate(HM.Features, true)); 41272cab237bSDimitry Andric 41282cab237bSDimitry Andric // Add negations of the HM's predicates to the default predicate. 41292cab237bSDimitry Andric DefaultPred.emplace_back(Predicate(HM.Features, false)); 41302cab237bSDimitry Andric } 41312cab237bSDimitry Andric 41322cab237bSDimitry Andric for (unsigned M : Modes) { 41332cab237bSDimitry Andric if (M == DefaultMode) 41342cab237bSDimitry Andric continue; 41352cab237bSDimitry Andric AppendPattern(P, M); 41362cab237bSDimitry Andric } 41372cab237bSDimitry Andric 41382cab237bSDimitry Andric bool HasDefault = Modes.count(DefaultMode); 41392cab237bSDimitry Andric if (HasDefault) 41402cab237bSDimitry Andric AppendPattern(P, DefaultMode); 41412cab237bSDimitry Andric } 41422cab237bSDimitry Andric } 41432cab237bSDimitry Andric 41442cab237bSDimitry Andric /// Dependent variable map for CodeGenDAGPattern variant generation 41452cab237bSDimitry Andric typedef StringMap<int> DepVarMap; 41462cab237bSDimitry Andric 41472cab237bSDimitry Andric static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { 41482cab237bSDimitry Andric if (N->isLeaf()) { 41492cab237bSDimitry Andric if (N->hasName() && isa<DefInit>(N->getLeafValue())) 41502cab237bSDimitry Andric DepMap[N->getName()]++; 41512cab237bSDimitry Andric } else { 41522cab237bSDimitry Andric for (size_t i = 0, e = N->getNumChildren(); i != e; ++i) 41532cab237bSDimitry Andric FindDepVarsOf(N->getChild(i), DepMap); 41542cab237bSDimitry Andric } 41552cab237bSDimitry Andric } 41562cab237bSDimitry Andric 41572cab237bSDimitry Andric /// Find dependent variables within child patterns 41582cab237bSDimitry Andric static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) { 41592cab237bSDimitry Andric DepVarMap depcounts; 41602cab237bSDimitry Andric FindDepVarsOf(N, depcounts); 41612cab237bSDimitry Andric for (const auto &Pair : depcounts) { 41622cab237bSDimitry Andric if (Pair.getValue() > 1) 41632cab237bSDimitry Andric DepVars.insert(Pair.getKey()); 41642cab237bSDimitry Andric } 41652cab237bSDimitry Andric } 41662cab237bSDimitry Andric 41672cab237bSDimitry Andric #ifndef NDEBUG 41682cab237bSDimitry Andric /// Dump the dependent variable set: 41692cab237bSDimitry Andric static void DumpDepVars(MultipleUseVarSet &DepVars) { 41702cab237bSDimitry Andric if (DepVars.empty()) { 41712cab237bSDimitry Andric DEBUG(errs() << "<empty set>"); 41722cab237bSDimitry Andric } else { 41732cab237bSDimitry Andric DEBUG(errs() << "[ "); 41742cab237bSDimitry Andric for (const auto &DepVar : DepVars) { 41752cab237bSDimitry Andric DEBUG(errs() << DepVar.getKey() << " "); 41762cab237bSDimitry Andric } 41772cab237bSDimitry Andric DEBUG(errs() << "]"); 41782cab237bSDimitry Andric } 41792cab237bSDimitry Andric } 41802cab237bSDimitry Andric #endif 41812cab237bSDimitry Andric 4182f22ef01cSRoman Divacky 4183f22ef01cSRoman Divacky /// CombineChildVariants - Given a bunch of permutations of each child of the 4184f22ef01cSRoman Divacky /// 'operator' node, put them together in all possible ways. 4185f22ef01cSRoman Divacky static void CombineChildVariants(TreePatternNode *Orig, 4186f22ef01cSRoman Divacky const std::vector<std::vector<TreePatternNode*> > &ChildVariants, 4187f22ef01cSRoman Divacky std::vector<TreePatternNode*> &OutVariants, 4188f22ef01cSRoman Divacky CodeGenDAGPatterns &CDP, 4189f22ef01cSRoman Divacky const MultipleUseVarSet &DepVars) { 4190f22ef01cSRoman Divacky // Make sure that each operand has at least one variant to choose from. 41917d523365SDimitry Andric for (const auto &Variants : ChildVariants) 41927d523365SDimitry Andric if (Variants.empty()) 4193f22ef01cSRoman Divacky return; 4194f22ef01cSRoman Divacky 4195f22ef01cSRoman Divacky // The end result is an all-pairs construction of the resultant pattern. 4196f22ef01cSRoman Divacky std::vector<unsigned> Idxs; 4197f22ef01cSRoman Divacky Idxs.resize(ChildVariants.size()); 4198f22ef01cSRoman Divacky bool NotDone; 4199f22ef01cSRoman Divacky do { 4200f22ef01cSRoman Divacky #ifndef NDEBUG 4201f22ef01cSRoman Divacky DEBUG(if (!Idxs.empty()) { 4202f22ef01cSRoman Divacky errs() << Orig->getOperator()->getName() << ": Idxs = [ "; 42037d523365SDimitry Andric for (unsigned Idx : Idxs) { 42047d523365SDimitry Andric errs() << Idx << " "; 4205f22ef01cSRoman Divacky } 4206f22ef01cSRoman Divacky errs() << "]\n"; 4207f22ef01cSRoman Divacky }); 4208f22ef01cSRoman Divacky #endif 4209f22ef01cSRoman Divacky // Create the variant and add it to the output list. 4210f22ef01cSRoman Divacky std::vector<TreePatternNode*> NewChildren; 4211f22ef01cSRoman Divacky for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) 4212f22ef01cSRoman Divacky NewChildren.push_back(ChildVariants[i][Idxs[i]]); 42137d523365SDimitry Andric auto R = llvm::make_unique<TreePatternNode>( 42147d523365SDimitry Andric Orig->getOperator(), NewChildren, Orig->getNumTypes()); 4215f22ef01cSRoman Divacky 4216f22ef01cSRoman Divacky // Copy over properties. 4217f22ef01cSRoman Divacky R->setName(Orig->getName()); 4218f22ef01cSRoman Divacky R->setPredicateFns(Orig->getPredicateFns()); 4219f22ef01cSRoman Divacky R->setTransformFn(Orig->getTransformFn()); 4220f22ef01cSRoman Divacky for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i) 4221f22ef01cSRoman Divacky R->setType(i, Orig->getExtType(i)); 4222f22ef01cSRoman Divacky 4223f22ef01cSRoman Divacky // If this pattern cannot match, do not include it as a variant. 4224f22ef01cSRoman Divacky std::string ErrString; 4225f22ef01cSRoman Divacky // Scan to see if this pattern has already been emitted. We can get 4226f22ef01cSRoman Divacky // duplication due to things like commuting: 4227f22ef01cSRoman Divacky // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a) 4228f22ef01cSRoman Divacky // which are the same pattern. Ignore the dups. 42297d523365SDimitry Andric if (R->canPatternMatch(ErrString, CDP) && 4230d88c1a5aSDimitry Andric none_of(OutVariants, [&](TreePatternNode *Variant) { 42317d523365SDimitry Andric return R->isIsomorphicTo(Variant, DepVars); 42327d523365SDimitry Andric })) 42337d523365SDimitry Andric OutVariants.push_back(R.release()); 4234f22ef01cSRoman Divacky 4235f22ef01cSRoman Divacky // Increment indices to the next permutation by incrementing the 42367d523365SDimitry Andric // indices from last index backward, e.g., generate the sequence 4237f22ef01cSRoman Divacky // [0, 0], [0, 1], [1, 0], [1, 1]. 4238f22ef01cSRoman Divacky int IdxsIdx; 4239f22ef01cSRoman Divacky for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) { 4240f22ef01cSRoman Divacky if (++Idxs[IdxsIdx] == ChildVariants[IdxsIdx].size()) 4241f22ef01cSRoman Divacky Idxs[IdxsIdx] = 0; 4242f22ef01cSRoman Divacky else 4243f22ef01cSRoman Divacky break; 4244f22ef01cSRoman Divacky } 4245f22ef01cSRoman Divacky NotDone = (IdxsIdx >= 0); 4246f22ef01cSRoman Divacky } while (NotDone); 4247f22ef01cSRoman Divacky } 4248f22ef01cSRoman Divacky 4249f22ef01cSRoman Divacky /// CombineChildVariants - A helper function for binary operators. 4250f22ef01cSRoman Divacky /// 4251f22ef01cSRoman Divacky static void CombineChildVariants(TreePatternNode *Orig, 4252f22ef01cSRoman Divacky const std::vector<TreePatternNode*> &LHS, 4253f22ef01cSRoman Divacky const std::vector<TreePatternNode*> &RHS, 4254f22ef01cSRoman Divacky std::vector<TreePatternNode*> &OutVariants, 4255f22ef01cSRoman Divacky CodeGenDAGPatterns &CDP, 4256f22ef01cSRoman Divacky const MultipleUseVarSet &DepVars) { 4257f22ef01cSRoman Divacky std::vector<std::vector<TreePatternNode*> > ChildVariants; 4258f22ef01cSRoman Divacky ChildVariants.push_back(LHS); 4259f22ef01cSRoman Divacky ChildVariants.push_back(RHS); 4260f22ef01cSRoman Divacky CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars); 4261f22ef01cSRoman Divacky } 4262f22ef01cSRoman Divacky 4263f22ef01cSRoman Divacky 4264f22ef01cSRoman Divacky static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N, 4265f22ef01cSRoman Divacky std::vector<TreePatternNode *> &Children) { 4266f22ef01cSRoman Divacky assert(N->getNumChildren()==2 &&"Associative but doesn't have 2 children!"); 4267f22ef01cSRoman Divacky Record *Operator = N->getOperator(); 4268f22ef01cSRoman Divacky 4269f22ef01cSRoman Divacky // Only permit raw nodes. 4270f22ef01cSRoman Divacky if (!N->getName().empty() || !N->getPredicateFns().empty() || 4271f22ef01cSRoman Divacky N->getTransformFn()) { 4272f22ef01cSRoman Divacky Children.push_back(N); 4273f22ef01cSRoman Divacky return; 4274f22ef01cSRoman Divacky } 4275f22ef01cSRoman Divacky 4276f22ef01cSRoman Divacky if (N->getChild(0)->isLeaf() || N->getChild(0)->getOperator() != Operator) 4277f22ef01cSRoman Divacky Children.push_back(N->getChild(0)); 4278f22ef01cSRoman Divacky else 4279f22ef01cSRoman Divacky GatherChildrenOfAssociativeOpcode(N->getChild(0), Children); 4280f22ef01cSRoman Divacky 4281f22ef01cSRoman Divacky if (N->getChild(1)->isLeaf() || N->getChild(1)->getOperator() != Operator) 4282f22ef01cSRoman Divacky Children.push_back(N->getChild(1)); 4283f22ef01cSRoman Divacky else 4284f22ef01cSRoman Divacky GatherChildrenOfAssociativeOpcode(N->getChild(1), Children); 4285f22ef01cSRoman Divacky } 4286f22ef01cSRoman Divacky 4287f22ef01cSRoman Divacky /// GenerateVariantsOf - Given a pattern N, generate all permutations we can of 4288f22ef01cSRoman Divacky /// the (potentially recursive) pattern by using algebraic laws. 4289f22ef01cSRoman Divacky /// 4290f22ef01cSRoman Divacky static void GenerateVariantsOf(TreePatternNode *N, 4291f22ef01cSRoman Divacky std::vector<TreePatternNode*> &OutVariants, 4292f22ef01cSRoman Divacky CodeGenDAGPatterns &CDP, 4293f22ef01cSRoman Divacky const MultipleUseVarSet &DepVars) { 429491bc56edSDimitry Andric // We cannot permute leaves or ComplexPattern uses. 429591bc56edSDimitry Andric if (N->isLeaf() || N->getOperator()->isSubClassOf("ComplexPattern")) { 4296f22ef01cSRoman Divacky OutVariants.push_back(N); 4297f22ef01cSRoman Divacky return; 4298f22ef01cSRoman Divacky } 4299f22ef01cSRoman Divacky 4300f22ef01cSRoman Divacky // Look up interesting info about the node. 4301f22ef01cSRoman Divacky const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(N->getOperator()); 4302f22ef01cSRoman Divacky 4303f22ef01cSRoman Divacky // If this node is associative, re-associate. 4304f22ef01cSRoman Divacky if (NodeInfo.hasProperty(SDNPAssociative)) { 4305f22ef01cSRoman Divacky // Re-associate by pulling together all of the linked operators 4306f22ef01cSRoman Divacky std::vector<TreePatternNode*> MaximalChildren; 4307f22ef01cSRoman Divacky GatherChildrenOfAssociativeOpcode(N, MaximalChildren); 4308f22ef01cSRoman Divacky 4309f22ef01cSRoman Divacky // Only handle child sizes of 3. Otherwise we'll end up trying too many 4310f22ef01cSRoman Divacky // permutations. 4311f22ef01cSRoman Divacky if (MaximalChildren.size() == 3) { 4312f22ef01cSRoman Divacky // Find the variants of all of our maximal children. 4313f22ef01cSRoman Divacky std::vector<TreePatternNode*> AVariants, BVariants, CVariants; 4314f22ef01cSRoman Divacky GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars); 4315f22ef01cSRoman Divacky GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars); 4316f22ef01cSRoman Divacky GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars); 4317f22ef01cSRoman Divacky 4318f22ef01cSRoman Divacky // There are only two ways we can permute the tree: 4319f22ef01cSRoman Divacky // (A op B) op C and A op (B op C) 4320f22ef01cSRoman Divacky // Within these forms, we can also permute A/B/C. 4321f22ef01cSRoman Divacky 4322f22ef01cSRoman Divacky // Generate legal pair permutations of A/B/C. 4323f22ef01cSRoman Divacky std::vector<TreePatternNode*> ABVariants; 4324f22ef01cSRoman Divacky std::vector<TreePatternNode*> BAVariants; 4325f22ef01cSRoman Divacky std::vector<TreePatternNode*> ACVariants; 4326f22ef01cSRoman Divacky std::vector<TreePatternNode*> CAVariants; 4327f22ef01cSRoman Divacky std::vector<TreePatternNode*> BCVariants; 4328f22ef01cSRoman Divacky std::vector<TreePatternNode*> CBVariants; 4329f22ef01cSRoman Divacky CombineChildVariants(N, AVariants, BVariants, ABVariants, CDP, DepVars); 4330f22ef01cSRoman Divacky CombineChildVariants(N, BVariants, AVariants, BAVariants, CDP, DepVars); 4331f22ef01cSRoman Divacky CombineChildVariants(N, AVariants, CVariants, ACVariants, CDP, DepVars); 4332f22ef01cSRoman Divacky CombineChildVariants(N, CVariants, AVariants, CAVariants, CDP, DepVars); 4333f22ef01cSRoman Divacky CombineChildVariants(N, BVariants, CVariants, BCVariants, CDP, DepVars); 4334f22ef01cSRoman Divacky CombineChildVariants(N, CVariants, BVariants, CBVariants, CDP, DepVars); 4335f22ef01cSRoman Divacky 4336f22ef01cSRoman Divacky // Combine those into the result: (x op x) op x 4337f22ef01cSRoman Divacky CombineChildVariants(N, ABVariants, CVariants, OutVariants, CDP, DepVars); 4338f22ef01cSRoman Divacky CombineChildVariants(N, BAVariants, CVariants, OutVariants, CDP, DepVars); 4339f22ef01cSRoman Divacky CombineChildVariants(N, ACVariants, BVariants, OutVariants, CDP, DepVars); 4340f22ef01cSRoman Divacky CombineChildVariants(N, CAVariants, BVariants, OutVariants, CDP, DepVars); 4341f22ef01cSRoman Divacky CombineChildVariants(N, BCVariants, AVariants, OutVariants, CDP, DepVars); 4342f22ef01cSRoman Divacky CombineChildVariants(N, CBVariants, AVariants, OutVariants, CDP, DepVars); 4343f22ef01cSRoman Divacky 4344f22ef01cSRoman Divacky // Combine those into the result: x op (x op x) 4345f22ef01cSRoman Divacky CombineChildVariants(N, CVariants, ABVariants, OutVariants, CDP, DepVars); 4346f22ef01cSRoman Divacky CombineChildVariants(N, CVariants, BAVariants, OutVariants, CDP, DepVars); 4347f22ef01cSRoman Divacky CombineChildVariants(N, BVariants, ACVariants, OutVariants, CDP, DepVars); 4348f22ef01cSRoman Divacky CombineChildVariants(N, BVariants, CAVariants, OutVariants, CDP, DepVars); 4349f22ef01cSRoman Divacky CombineChildVariants(N, AVariants, BCVariants, OutVariants, CDP, DepVars); 4350f22ef01cSRoman Divacky CombineChildVariants(N, AVariants, CBVariants, OutVariants, CDP, DepVars); 4351f22ef01cSRoman Divacky return; 4352f22ef01cSRoman Divacky } 4353f22ef01cSRoman Divacky } 4354f22ef01cSRoman Divacky 4355f22ef01cSRoman Divacky // Compute permutations of all children. 4356f22ef01cSRoman Divacky std::vector<std::vector<TreePatternNode*> > ChildVariants; 4357f22ef01cSRoman Divacky ChildVariants.resize(N->getNumChildren()); 4358f22ef01cSRoman Divacky for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) 4359f22ef01cSRoman Divacky GenerateVariantsOf(N->getChild(i), ChildVariants[i], CDP, DepVars); 4360f22ef01cSRoman Divacky 4361f22ef01cSRoman Divacky // Build all permutations based on how the children were formed. 4362f22ef01cSRoman Divacky CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars); 4363f22ef01cSRoman Divacky 4364f22ef01cSRoman Divacky // If this node is commutative, consider the commuted order. 4365f22ef01cSRoman Divacky bool isCommIntrinsic = N->isCommutativeIntrinsic(CDP); 4366f22ef01cSRoman Divacky if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) { 43672cab237bSDimitry Andric assert((N->getNumChildren()>=2 || isCommIntrinsic) && 4368f22ef01cSRoman Divacky "Commutative but doesn't have 2 children!"); 4369f22ef01cSRoman Divacky // Don't count children which are actually register references. 4370f22ef01cSRoman Divacky unsigned NC = 0; 4371f22ef01cSRoman Divacky for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { 4372f22ef01cSRoman Divacky TreePatternNode *Child = N->getChild(i); 4373f22ef01cSRoman Divacky if (Child->isLeaf()) 43743861d79fSDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(Child->getLeafValue())) { 4375f22ef01cSRoman Divacky Record *RR = DI->getDef(); 4376f22ef01cSRoman Divacky if (RR->isSubClassOf("Register")) 4377f22ef01cSRoman Divacky continue; 4378f22ef01cSRoman Divacky } 4379f22ef01cSRoman Divacky NC++; 4380f22ef01cSRoman Divacky } 4381f22ef01cSRoman Divacky // Consider the commuted order. 4382f22ef01cSRoman Divacky if (isCommIntrinsic) { 4383f22ef01cSRoman Divacky // Commutative intrinsic. First operand is the intrinsic id, 2nd and 3rd 4384f22ef01cSRoman Divacky // operands are the commutative operands, and there might be more operands 4385f22ef01cSRoman Divacky // after those. 4386f22ef01cSRoman Divacky assert(NC >= 3 && 43877d523365SDimitry Andric "Commutative intrinsic should have at least 3 children!"); 4388f22ef01cSRoman Divacky std::vector<std::vector<TreePatternNode*> > Variants; 4389f22ef01cSRoman Divacky Variants.push_back(ChildVariants[0]); // Intrinsic id. 4390f22ef01cSRoman Divacky Variants.push_back(ChildVariants[2]); 4391f22ef01cSRoman Divacky Variants.push_back(ChildVariants[1]); 4392f22ef01cSRoman Divacky for (unsigned i = 3; i != NC; ++i) 4393f22ef01cSRoman Divacky Variants.push_back(ChildVariants[i]); 4394f22ef01cSRoman Divacky CombineChildVariants(N, Variants, OutVariants, CDP, DepVars); 43952cab237bSDimitry Andric } else if (NC == N->getNumChildren()) { 43962cab237bSDimitry Andric std::vector<std::vector<TreePatternNode*> > Variants; 43972cab237bSDimitry Andric Variants.push_back(ChildVariants[1]); 43982cab237bSDimitry Andric Variants.push_back(ChildVariants[0]); 43992cab237bSDimitry Andric for (unsigned i = 2; i != NC; ++i) 44002cab237bSDimitry Andric Variants.push_back(ChildVariants[i]); 44012cab237bSDimitry Andric CombineChildVariants(N, Variants, OutVariants, CDP, DepVars); 44022cab237bSDimitry Andric } 4403f22ef01cSRoman Divacky } 4404f22ef01cSRoman Divacky } 4405f22ef01cSRoman Divacky 4406f22ef01cSRoman Divacky 4407f22ef01cSRoman Divacky // GenerateVariants - Generate variants. For example, commutative patterns can 4408f22ef01cSRoman Divacky // match multiple ways. Add them to PatternsToMatch as well. 4409f22ef01cSRoman Divacky void CodeGenDAGPatterns::GenerateVariants() { 4410f22ef01cSRoman Divacky DEBUG(errs() << "Generating instruction variants.\n"); 4411f22ef01cSRoman Divacky 4412f22ef01cSRoman Divacky // Loop over all of the patterns we've collected, checking to see if we can 4413f22ef01cSRoman Divacky // generate variants of the instruction, through the exploitation of 4414f22ef01cSRoman Divacky // identities. This permits the target to provide aggressive matching without 4415f22ef01cSRoman Divacky // the .td file having to contain tons of variants of instructions. 4416f22ef01cSRoman Divacky // 4417f22ef01cSRoman Divacky // Note that this loop adds new patterns to the PatternsToMatch list, but we 4418f22ef01cSRoman Divacky // intentionally do not reconsider these. Any variants of added patterns have 4419f22ef01cSRoman Divacky // already been added. 4420f22ef01cSRoman Divacky // 4421f22ef01cSRoman Divacky for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) { 4422f22ef01cSRoman Divacky MultipleUseVarSet DepVars; 4423f22ef01cSRoman Divacky std::vector<TreePatternNode*> Variants; 4424f22ef01cSRoman Divacky FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars); 4425f22ef01cSRoman Divacky DEBUG(errs() << "Dependent/multiply used variables: "); 4426f22ef01cSRoman Divacky DEBUG(DumpDepVars(DepVars)); 4427f22ef01cSRoman Divacky DEBUG(errs() << "\n"); 44282754fe60SDimitry Andric GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this, 44292754fe60SDimitry Andric DepVars); 4430f22ef01cSRoman Divacky 4431f22ef01cSRoman Divacky assert(!Variants.empty() && "Must create at least original variant!"); 443224d58133SDimitry Andric if (Variants.size() == 1) // No additional variants for this pattern. 4433f22ef01cSRoman Divacky continue; 4434f22ef01cSRoman Divacky 4435f22ef01cSRoman Divacky DEBUG(errs() << "FOUND VARIANTS OF: "; 4436f22ef01cSRoman Divacky PatternsToMatch[i].getSrcPattern()->dump(); 4437f22ef01cSRoman Divacky errs() << "\n"); 4438f22ef01cSRoman Divacky 4439f22ef01cSRoman Divacky for (unsigned v = 0, e = Variants.size(); v != e; ++v) { 4440f22ef01cSRoman Divacky TreePatternNode *Variant = Variants[v]; 4441f22ef01cSRoman Divacky 4442f22ef01cSRoman Divacky DEBUG(errs() << " VAR#" << v << ": "; 4443f22ef01cSRoman Divacky Variant->dump(); 4444f22ef01cSRoman Divacky errs() << "\n"); 4445f22ef01cSRoman Divacky 4446f22ef01cSRoman Divacky // Scan to see if an instruction or explicit pattern already matches this. 4447f22ef01cSRoman Divacky bool AlreadyExists = false; 4448f22ef01cSRoman Divacky for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) { 4449f22ef01cSRoman Divacky // Skip if the top level predicates do not match. 4450f22ef01cSRoman Divacky if (PatternsToMatch[i].getPredicates() != 4451f22ef01cSRoman Divacky PatternsToMatch[p].getPredicates()) 4452f22ef01cSRoman Divacky continue; 4453f22ef01cSRoman Divacky // Check to see if this variant already exists. 44542754fe60SDimitry Andric if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(), 44552754fe60SDimitry Andric DepVars)) { 4456f22ef01cSRoman Divacky DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n"); 4457f22ef01cSRoman Divacky AlreadyExists = true; 4458f22ef01cSRoman Divacky break; 4459f22ef01cSRoman Divacky } 4460f22ef01cSRoman Divacky } 4461f22ef01cSRoman Divacky // If we already have it, ignore the variant. 4462f22ef01cSRoman Divacky if (AlreadyExists) continue; 4463f22ef01cSRoman Divacky 4464f22ef01cSRoman Divacky // Otherwise, add it to the list of patterns we have. 4465a580b014SDimitry Andric PatternsToMatch.push_back(PatternToMatch( 446697bc6c73SDimitry Andric PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(), 4467f22ef01cSRoman Divacky Variant, PatternsToMatch[i].getDstPattern(), 4468f22ef01cSRoman Divacky PatternsToMatch[i].getDstRegs(), 4469a580b014SDimitry Andric PatternsToMatch[i].getAddedComplexity(), Record::getNewUID())); 4470f22ef01cSRoman Divacky } 4471f22ef01cSRoman Divacky 4472f22ef01cSRoman Divacky DEBUG(errs() << "\n"); 4473f22ef01cSRoman Divacky } 4474f22ef01cSRoman Divacky } 4475