10fca6ea1SDimitry Andric //===- CodeGenDAGPatterns.cpp - Read DAG patterns from .td file -----------===// 20fca6ea1SDimitry Andric // 30fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60fca6ea1SDimitry Andric // 70fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 80fca6ea1SDimitry Andric // 90fca6ea1SDimitry Andric // This file implements the CodeGenDAGPatterns class, which is used to read and 100fca6ea1SDimitry Andric // represent the patterns present in a .td file for instructions. 110fca6ea1SDimitry Andric // 120fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 130fca6ea1SDimitry Andric 140fca6ea1SDimitry Andric #include "CodeGenDAGPatterns.h" 150fca6ea1SDimitry Andric #include "CodeGenInstruction.h" 160fca6ea1SDimitry Andric #include "CodeGenRegisters.h" 170fca6ea1SDimitry Andric #include "llvm/ADT/DenseSet.h" 180fca6ea1SDimitry Andric #include "llvm/ADT/MapVector.h" 190fca6ea1SDimitry Andric #include "llvm/ADT/STLExtras.h" 200fca6ea1SDimitry Andric #include "llvm/ADT/SmallSet.h" 210fca6ea1SDimitry Andric #include "llvm/ADT/SmallString.h" 220fca6ea1SDimitry Andric #include "llvm/ADT/StringExtras.h" 230fca6ea1SDimitry Andric #include "llvm/ADT/StringMap.h" 240fca6ea1SDimitry Andric #include "llvm/ADT/Twine.h" 250fca6ea1SDimitry Andric #include "llvm/Support/Debug.h" 260fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h" 270fca6ea1SDimitry Andric #include "llvm/Support/TypeSize.h" 280fca6ea1SDimitry Andric #include "llvm/TableGen/Error.h" 290fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h" 300fca6ea1SDimitry Andric #include <algorithm> 310fca6ea1SDimitry Andric #include <cstdio> 320fca6ea1SDimitry Andric #include <iterator> 330fca6ea1SDimitry Andric #include <set> 340fca6ea1SDimitry Andric using namespace llvm; 350fca6ea1SDimitry Andric 360fca6ea1SDimitry Andric #define DEBUG_TYPE "dag-patterns" 370fca6ea1SDimitry Andric 380fca6ea1SDimitry Andric static inline bool isIntegerOrPtr(MVT VT) { 390fca6ea1SDimitry Andric return VT.isInteger() || VT == MVT::iPTR; 400fca6ea1SDimitry Andric } 410fca6ea1SDimitry Andric static inline bool isFloatingPoint(MVT VT) { return VT.isFloatingPoint(); } 420fca6ea1SDimitry Andric static inline bool isVector(MVT VT) { return VT.isVector(); } 430fca6ea1SDimitry Andric static inline bool isScalar(MVT VT) { return !VT.isVector(); } 440fca6ea1SDimitry Andric 450fca6ea1SDimitry Andric template <typename Predicate> 460fca6ea1SDimitry Andric static bool berase_if(MachineValueTypeSet &S, Predicate P) { 470fca6ea1SDimitry Andric bool Erased = false; 480fca6ea1SDimitry Andric // It is ok to iterate over MachineValueTypeSet and remove elements from it 490fca6ea1SDimitry Andric // at the same time. 500fca6ea1SDimitry Andric for (MVT T : S) { 510fca6ea1SDimitry Andric if (!P(T)) 520fca6ea1SDimitry Andric continue; 530fca6ea1SDimitry Andric Erased = true; 540fca6ea1SDimitry Andric S.erase(T); 550fca6ea1SDimitry Andric } 560fca6ea1SDimitry Andric return Erased; 570fca6ea1SDimitry Andric } 580fca6ea1SDimitry Andric 590fca6ea1SDimitry Andric void MachineValueTypeSet::writeToStream(raw_ostream &OS) const { 600fca6ea1SDimitry Andric SmallVector<MVT, 4> Types(begin(), end()); 610fca6ea1SDimitry Andric array_pod_sort(Types.begin(), Types.end()); 620fca6ea1SDimitry Andric 630fca6ea1SDimitry Andric OS << '['; 640fca6ea1SDimitry Andric ListSeparator LS(" "); 650fca6ea1SDimitry Andric for (const MVT &T : Types) 660fca6ea1SDimitry Andric OS << LS << ValueTypeByHwMode::getMVTName(T); 670fca6ea1SDimitry Andric OS << ']'; 680fca6ea1SDimitry Andric } 690fca6ea1SDimitry Andric 700fca6ea1SDimitry Andric // --- TypeSetByHwMode 710fca6ea1SDimitry Andric 720fca6ea1SDimitry Andric // This is a parameterized type-set class. For each mode there is a list 730fca6ea1SDimitry Andric // of types that are currently possible for a given tree node. Type 740fca6ea1SDimitry Andric // inference will apply to each mode separately. 750fca6ea1SDimitry Andric 760fca6ea1SDimitry Andric TypeSetByHwMode::TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList) { 770fca6ea1SDimitry Andric // Take the address space from the first type in the list. 780fca6ea1SDimitry Andric if (!VTList.empty()) 790fca6ea1SDimitry Andric AddrSpace = VTList[0].PtrAddrSpace; 800fca6ea1SDimitry Andric 810fca6ea1SDimitry Andric for (const ValueTypeByHwMode &VVT : VTList) 820fca6ea1SDimitry Andric insert(VVT); 830fca6ea1SDimitry Andric } 840fca6ea1SDimitry Andric 850fca6ea1SDimitry Andric bool TypeSetByHwMode::isValueTypeByHwMode(bool AllowEmpty) const { 860fca6ea1SDimitry Andric for (const auto &I : *this) { 870fca6ea1SDimitry Andric if (I.second.size() > 1) 880fca6ea1SDimitry Andric return false; 890fca6ea1SDimitry Andric if (!AllowEmpty && I.second.empty()) 900fca6ea1SDimitry Andric return false; 910fca6ea1SDimitry Andric } 920fca6ea1SDimitry Andric return true; 930fca6ea1SDimitry Andric } 940fca6ea1SDimitry Andric 950fca6ea1SDimitry Andric ValueTypeByHwMode TypeSetByHwMode::getValueTypeByHwMode() const { 960fca6ea1SDimitry Andric assert(isValueTypeByHwMode(true) && 970fca6ea1SDimitry Andric "The type set has multiple types for at least one HW mode"); 980fca6ea1SDimitry Andric ValueTypeByHwMode VVT; 990fca6ea1SDimitry Andric VVT.PtrAddrSpace = AddrSpace; 1000fca6ea1SDimitry Andric 1010fca6ea1SDimitry Andric for (const auto &I : *this) { 1020fca6ea1SDimitry Andric MVT T = I.second.empty() ? MVT::Other : *I.second.begin(); 1030fca6ea1SDimitry Andric VVT.getOrCreateTypeForMode(I.first, T); 1040fca6ea1SDimitry Andric } 1050fca6ea1SDimitry Andric return VVT; 1060fca6ea1SDimitry Andric } 1070fca6ea1SDimitry Andric 1080fca6ea1SDimitry Andric bool TypeSetByHwMode::isPossible() const { 1090fca6ea1SDimitry Andric for (const auto &I : *this) 1100fca6ea1SDimitry Andric if (!I.second.empty()) 1110fca6ea1SDimitry Andric return true; 1120fca6ea1SDimitry Andric return false; 1130fca6ea1SDimitry Andric } 1140fca6ea1SDimitry Andric 1150fca6ea1SDimitry Andric bool TypeSetByHwMode::insert(const ValueTypeByHwMode &VVT) { 1160fca6ea1SDimitry Andric bool Changed = false; 1170fca6ea1SDimitry Andric bool ContainsDefault = false; 1180fca6ea1SDimitry Andric MVT DT = MVT::Other; 1190fca6ea1SDimitry Andric 1200fca6ea1SDimitry Andric for (const auto &P : VVT) { 1210fca6ea1SDimitry Andric unsigned M = P.first; 1220fca6ea1SDimitry Andric // Make sure there exists a set for each specific mode from VVT. 1230fca6ea1SDimitry Andric Changed |= getOrCreate(M).insert(P.second).second; 1240fca6ea1SDimitry Andric // Cache VVT's default mode. 1250fca6ea1SDimitry Andric if (DefaultMode == M) { 1260fca6ea1SDimitry Andric ContainsDefault = true; 1270fca6ea1SDimitry Andric DT = P.second; 1280fca6ea1SDimitry Andric } 1290fca6ea1SDimitry Andric } 1300fca6ea1SDimitry Andric 1310fca6ea1SDimitry Andric // If VVT has a default mode, add the corresponding type to all 1320fca6ea1SDimitry Andric // modes in "this" that do not exist in VVT. 1330fca6ea1SDimitry Andric if (ContainsDefault) 1340fca6ea1SDimitry Andric for (auto &I : *this) 1350fca6ea1SDimitry Andric if (!VVT.hasMode(I.first)) 1360fca6ea1SDimitry Andric Changed |= I.second.insert(DT).second; 1370fca6ea1SDimitry Andric 1380fca6ea1SDimitry Andric return Changed; 1390fca6ea1SDimitry Andric } 1400fca6ea1SDimitry Andric 1410fca6ea1SDimitry Andric // Constrain the type set to be the intersection with VTS. 1420fca6ea1SDimitry Andric bool TypeSetByHwMode::constrain(const TypeSetByHwMode &VTS) { 1430fca6ea1SDimitry Andric bool Changed = false; 1440fca6ea1SDimitry Andric if (hasDefault()) { 1450fca6ea1SDimitry Andric for (const auto &I : VTS) { 1460fca6ea1SDimitry Andric unsigned M = I.first; 1470fca6ea1SDimitry Andric if (M == DefaultMode || hasMode(M)) 1480fca6ea1SDimitry Andric continue; 1490fca6ea1SDimitry Andric Map.insert({M, Map.at(DefaultMode)}); 1500fca6ea1SDimitry Andric Changed = true; 1510fca6ea1SDimitry Andric } 1520fca6ea1SDimitry Andric } 1530fca6ea1SDimitry Andric 1540fca6ea1SDimitry Andric for (auto &I : *this) { 1550fca6ea1SDimitry Andric unsigned M = I.first; 1560fca6ea1SDimitry Andric SetType &S = I.second; 1570fca6ea1SDimitry Andric if (VTS.hasMode(M) || VTS.hasDefault()) { 1580fca6ea1SDimitry Andric Changed |= intersect(I.second, VTS.get(M)); 1590fca6ea1SDimitry Andric } else if (!S.empty()) { 1600fca6ea1SDimitry Andric S.clear(); 1610fca6ea1SDimitry Andric Changed = true; 1620fca6ea1SDimitry Andric } 1630fca6ea1SDimitry Andric } 1640fca6ea1SDimitry Andric return Changed; 1650fca6ea1SDimitry Andric } 1660fca6ea1SDimitry Andric 1670fca6ea1SDimitry Andric template <typename Predicate> bool TypeSetByHwMode::constrain(Predicate P) { 1680fca6ea1SDimitry Andric bool Changed = false; 1690fca6ea1SDimitry Andric for (auto &I : *this) 1700fca6ea1SDimitry Andric Changed |= berase_if(I.second, [&P](MVT VT) { return !P(VT); }); 1710fca6ea1SDimitry Andric return Changed; 1720fca6ea1SDimitry Andric } 1730fca6ea1SDimitry Andric 1740fca6ea1SDimitry Andric template <typename Predicate> 1750fca6ea1SDimitry Andric bool TypeSetByHwMode::assign_if(const TypeSetByHwMode &VTS, Predicate P) { 1760fca6ea1SDimitry Andric assert(empty()); 1770fca6ea1SDimitry Andric for (const auto &I : VTS) { 1780fca6ea1SDimitry Andric SetType &S = getOrCreate(I.first); 1790fca6ea1SDimitry Andric for (auto J : I.second) 1800fca6ea1SDimitry Andric if (P(J)) 1810fca6ea1SDimitry Andric S.insert(J); 1820fca6ea1SDimitry Andric } 1830fca6ea1SDimitry Andric return !empty(); 1840fca6ea1SDimitry Andric } 1850fca6ea1SDimitry Andric 1860fca6ea1SDimitry Andric void TypeSetByHwMode::writeToStream(raw_ostream &OS) const { 1870fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 1880fca6ea1SDimitry Andric Modes.reserve(Map.size()); 1890fca6ea1SDimitry Andric 1900fca6ea1SDimitry Andric for (const auto &I : *this) 1910fca6ea1SDimitry Andric Modes.push_back(I.first); 1920fca6ea1SDimitry Andric if (Modes.empty()) { 1930fca6ea1SDimitry Andric OS << "{}"; 1940fca6ea1SDimitry Andric return; 1950fca6ea1SDimitry Andric } 1960fca6ea1SDimitry Andric array_pod_sort(Modes.begin(), Modes.end()); 1970fca6ea1SDimitry Andric 1980fca6ea1SDimitry Andric OS << '{'; 1990fca6ea1SDimitry Andric for (unsigned M : Modes) { 2000fca6ea1SDimitry Andric OS << ' ' << getModeName(M) << ':'; 2010fca6ea1SDimitry Andric get(M).writeToStream(OS); 2020fca6ea1SDimitry Andric } 2030fca6ea1SDimitry Andric OS << " }"; 2040fca6ea1SDimitry Andric } 2050fca6ea1SDimitry Andric 2060fca6ea1SDimitry Andric bool TypeSetByHwMode::operator==(const TypeSetByHwMode &VTS) const { 2070fca6ea1SDimitry Andric // The isSimple call is much quicker than hasDefault - check this first. 2080fca6ea1SDimitry Andric bool IsSimple = isSimple(); 2090fca6ea1SDimitry Andric bool VTSIsSimple = VTS.isSimple(); 2100fca6ea1SDimitry Andric if (IsSimple && VTSIsSimple) 2110fca6ea1SDimitry Andric return getSimple() == VTS.getSimple(); 2120fca6ea1SDimitry Andric 2130fca6ea1SDimitry Andric // Speedup: We have a default if the set is simple. 2140fca6ea1SDimitry Andric bool HaveDefault = IsSimple || hasDefault(); 2150fca6ea1SDimitry Andric bool VTSHaveDefault = VTSIsSimple || VTS.hasDefault(); 2160fca6ea1SDimitry Andric if (HaveDefault != VTSHaveDefault) 2170fca6ea1SDimitry Andric return false; 2180fca6ea1SDimitry Andric 2190fca6ea1SDimitry Andric SmallSet<unsigned, 4> Modes; 2200fca6ea1SDimitry Andric for (auto &I : *this) 2210fca6ea1SDimitry Andric Modes.insert(I.first); 2220fca6ea1SDimitry Andric for (const auto &I : VTS) 2230fca6ea1SDimitry Andric Modes.insert(I.first); 2240fca6ea1SDimitry Andric 2250fca6ea1SDimitry Andric if (HaveDefault) { 2260fca6ea1SDimitry Andric // Both sets have default mode. 2270fca6ea1SDimitry Andric for (unsigned M : Modes) { 2280fca6ea1SDimitry Andric if (get(M) != VTS.get(M)) 2290fca6ea1SDimitry Andric return false; 2300fca6ea1SDimitry Andric } 2310fca6ea1SDimitry Andric } else { 2320fca6ea1SDimitry Andric // Neither set has default mode. 2330fca6ea1SDimitry Andric for (unsigned M : Modes) { 2340fca6ea1SDimitry Andric // If there is no default mode, an empty set is equivalent to not having 2350fca6ea1SDimitry Andric // the corresponding mode. 2360fca6ea1SDimitry Andric bool NoModeThis = !hasMode(M) || get(M).empty(); 2370fca6ea1SDimitry Andric bool NoModeVTS = !VTS.hasMode(M) || VTS.get(M).empty(); 2380fca6ea1SDimitry Andric if (NoModeThis != NoModeVTS) 2390fca6ea1SDimitry Andric return false; 2400fca6ea1SDimitry Andric if (!NoModeThis) 2410fca6ea1SDimitry Andric if (get(M) != VTS.get(M)) 2420fca6ea1SDimitry Andric return false; 2430fca6ea1SDimitry Andric } 2440fca6ea1SDimitry Andric } 2450fca6ea1SDimitry Andric 2460fca6ea1SDimitry Andric return true; 2470fca6ea1SDimitry Andric } 2480fca6ea1SDimitry Andric 2490fca6ea1SDimitry Andric namespace llvm { 2500fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const MachineValueTypeSet &T) { 2510fca6ea1SDimitry Andric T.writeToStream(OS); 2520fca6ea1SDimitry Andric return OS; 2530fca6ea1SDimitry Andric } 2540fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const TypeSetByHwMode &T) { 2550fca6ea1SDimitry Andric T.writeToStream(OS); 2560fca6ea1SDimitry Andric return OS; 2570fca6ea1SDimitry Andric } 2580fca6ea1SDimitry Andric } // namespace llvm 2590fca6ea1SDimitry Andric 2600fca6ea1SDimitry Andric LLVM_DUMP_METHOD 2610fca6ea1SDimitry Andric void TypeSetByHwMode::dump() const { dbgs() << *this << '\n'; } 2620fca6ea1SDimitry Andric 2630fca6ea1SDimitry Andric bool TypeSetByHwMode::intersect(SetType &Out, const SetType &In) { 2640fca6ea1SDimitry Andric auto IntersectP = [&](std::optional<MVT> WildVT, function_ref<bool(MVT)> P) { 2650fca6ea1SDimitry Andric // Complement of In within this partition. 2660fca6ea1SDimitry Andric auto CompIn = [&](MVT T) -> bool { return !In.count(T) && P(T); }; 2670fca6ea1SDimitry Andric 2680fca6ea1SDimitry Andric if (!WildVT) 2690fca6ea1SDimitry Andric return berase_if(Out, CompIn); 2700fca6ea1SDimitry Andric 2710fca6ea1SDimitry Andric bool OutW = Out.count(*WildVT), InW = In.count(*WildVT); 2720fca6ea1SDimitry Andric if (OutW == InW) 2730fca6ea1SDimitry Andric return berase_if(Out, CompIn); 2740fca6ea1SDimitry Andric 2750fca6ea1SDimitry Andric // Compute the intersection of scalars separately to account for only one 2760fca6ea1SDimitry Andric // set containing WildVT. 2770fca6ea1SDimitry Andric // The intersection of WildVT with a set of corresponding types that does 2780fca6ea1SDimitry Andric // not include WildVT will result in the most specific type: 2790fca6ea1SDimitry Andric // - WildVT is more specific than any set with two elements or more 2800fca6ea1SDimitry Andric // - WildVT is less specific than any single type. 2810fca6ea1SDimitry Andric // For example, for iPTR and scalar integer types 2820fca6ea1SDimitry Andric // { iPTR } * { i32 } -> { i32 } 2830fca6ea1SDimitry Andric // { iPTR } * { i32 i64 } -> { iPTR } 2840fca6ea1SDimitry Andric // and 2850fca6ea1SDimitry Andric // { iPTR i32 } * { i32 } -> { i32 } 2860fca6ea1SDimitry Andric // { iPTR i32 } * { i32 i64 } -> { i32 i64 } 2870fca6ea1SDimitry Andric // { iPTR i32 } * { i32 i64 i128 } -> { iPTR i32 } 2880fca6ea1SDimitry Andric 2890fca6ea1SDimitry Andric // Looking at just this partition, let In' = elements only in In, 2900fca6ea1SDimitry Andric // Out' = elements only in Out, and IO = elements common to both. Normally 2910fca6ea1SDimitry Andric // IO would be returned as the result of the intersection, but we need to 2920fca6ea1SDimitry Andric // account for WildVT being a "wildcard" of sorts. Since elements in IO are 2930fca6ea1SDimitry Andric // those that match both sets exactly, they will all belong to the output. 2940fca6ea1SDimitry Andric // If any of the "leftovers" (i.e. In' or Out') contain WildVT, it means 2950fca6ea1SDimitry Andric // that the other set doesn't have it, but it could have (1) a more 2960fca6ea1SDimitry Andric // specific type, or (2) a set of types that is less specific. The 2970fca6ea1SDimitry Andric // "leftovers" from the other set is what we want to examine more closely. 2980fca6ea1SDimitry Andric 2990fca6ea1SDimitry Andric auto Leftovers = [&](const SetType &A, const SetType &B) { 3000fca6ea1SDimitry Andric SetType Diff = A; 3010fca6ea1SDimitry Andric berase_if(Diff, [&](MVT T) { return B.count(T) || !P(T); }); 3020fca6ea1SDimitry Andric return Diff; 3030fca6ea1SDimitry Andric }; 3040fca6ea1SDimitry Andric 3050fca6ea1SDimitry Andric if (InW) { 3060fca6ea1SDimitry Andric SetType OutLeftovers = Leftovers(Out, In); 3070fca6ea1SDimitry Andric if (OutLeftovers.size() < 2) { 3080fca6ea1SDimitry Andric // WildVT not added to Out. Keep the possible single leftover. 3090fca6ea1SDimitry Andric return false; 3100fca6ea1SDimitry Andric } 3110fca6ea1SDimitry Andric // WildVT replaces the leftovers. 3120fca6ea1SDimitry Andric berase_if(Out, CompIn); 3130fca6ea1SDimitry Andric Out.insert(*WildVT); 3140fca6ea1SDimitry Andric return true; 3150fca6ea1SDimitry Andric } 3160fca6ea1SDimitry Andric 3170fca6ea1SDimitry Andric // OutW == true 3180fca6ea1SDimitry Andric SetType InLeftovers = Leftovers(In, Out); 3190fca6ea1SDimitry Andric unsigned SizeOut = Out.size(); 3200fca6ea1SDimitry Andric berase_if(Out, CompIn); // This will remove at least the WildVT. 3210fca6ea1SDimitry Andric if (InLeftovers.size() < 2) { 3220fca6ea1SDimitry Andric // WildVT deleted from Out. Add back the possible single leftover. 3230fca6ea1SDimitry Andric Out.insert(InLeftovers); 3240fca6ea1SDimitry Andric return true; 3250fca6ea1SDimitry Andric } 3260fca6ea1SDimitry Andric 3270fca6ea1SDimitry Andric // Keep the WildVT in Out. 3280fca6ea1SDimitry Andric Out.insert(*WildVT); 3290fca6ea1SDimitry Andric // If WildVT was the only element initially removed from Out, then Out 3300fca6ea1SDimitry Andric // has not changed. 3310fca6ea1SDimitry Andric return SizeOut != Out.size(); 3320fca6ea1SDimitry Andric }; 3330fca6ea1SDimitry Andric 3340fca6ea1SDimitry Andric // Note: must be non-overlapping 3350fca6ea1SDimitry Andric using WildPartT = std::pair<MVT, std::function<bool(MVT)>>; 3360fca6ea1SDimitry Andric static const WildPartT WildParts[] = { 3370fca6ea1SDimitry Andric {MVT::iPTR, [](MVT T) { return T.isScalarInteger() || T == MVT::iPTR; }}, 3380fca6ea1SDimitry Andric }; 3390fca6ea1SDimitry Andric 3400fca6ea1SDimitry Andric bool Changed = false; 3410fca6ea1SDimitry Andric for (const auto &I : WildParts) 3420fca6ea1SDimitry Andric Changed |= IntersectP(I.first, I.second); 3430fca6ea1SDimitry Andric 3440fca6ea1SDimitry Andric Changed |= IntersectP(std::nullopt, [&](MVT T) { 3450fca6ea1SDimitry Andric return !any_of(WildParts, [=](const WildPartT &I) { return I.second(T); }); 3460fca6ea1SDimitry Andric }); 3470fca6ea1SDimitry Andric 3480fca6ea1SDimitry Andric return Changed; 3490fca6ea1SDimitry Andric } 3500fca6ea1SDimitry Andric 3510fca6ea1SDimitry Andric bool TypeSetByHwMode::validate() const { 3520fca6ea1SDimitry Andric if (empty()) 3530fca6ea1SDimitry Andric return true; 3540fca6ea1SDimitry Andric bool AllEmpty = true; 3550fca6ea1SDimitry Andric for (const auto &I : *this) 3560fca6ea1SDimitry Andric AllEmpty &= I.second.empty(); 3570fca6ea1SDimitry Andric return !AllEmpty; 3580fca6ea1SDimitry Andric } 3590fca6ea1SDimitry Andric 3600fca6ea1SDimitry Andric // --- TypeInfer 3610fca6ea1SDimitry Andric 3620fca6ea1SDimitry Andric bool TypeInfer::MergeInTypeInfo(TypeSetByHwMode &Out, 3630fca6ea1SDimitry Andric const TypeSetByHwMode &In) const { 3640fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 3650fca6ea1SDimitry Andric In.validate(); 3660fca6ea1SDimitry Andric if (In.empty() || Out == In || TP.hasError()) 3670fca6ea1SDimitry Andric return false; 3680fca6ea1SDimitry Andric if (Out.empty()) { 3690fca6ea1SDimitry Andric Out = In; 3700fca6ea1SDimitry Andric return true; 3710fca6ea1SDimitry Andric } 3720fca6ea1SDimitry Andric 3730fca6ea1SDimitry Andric bool Changed = Out.constrain(In); 3740fca6ea1SDimitry Andric if (Changed && Out.empty()) 3750fca6ea1SDimitry Andric TP.error("Type contradiction"); 3760fca6ea1SDimitry Andric 3770fca6ea1SDimitry Andric return Changed; 3780fca6ea1SDimitry Andric } 3790fca6ea1SDimitry Andric 3800fca6ea1SDimitry Andric bool TypeInfer::forceArbitrary(TypeSetByHwMode &Out) { 3810fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 3820fca6ea1SDimitry Andric if (TP.hasError()) 3830fca6ea1SDimitry Andric return false; 3840fca6ea1SDimitry Andric assert(!Out.empty() && "cannot pick from an empty set"); 3850fca6ea1SDimitry Andric 3860fca6ea1SDimitry Andric bool Changed = false; 3870fca6ea1SDimitry Andric for (auto &I : Out) { 3880fca6ea1SDimitry Andric TypeSetByHwMode::SetType &S = I.second; 3890fca6ea1SDimitry Andric if (S.size() <= 1) 3900fca6ea1SDimitry Andric continue; 3910fca6ea1SDimitry Andric MVT T = *S.begin(); // Pick the first element. 3920fca6ea1SDimitry Andric S.clear(); 3930fca6ea1SDimitry Andric S.insert(T); 3940fca6ea1SDimitry Andric Changed = true; 3950fca6ea1SDimitry Andric } 3960fca6ea1SDimitry Andric return Changed; 3970fca6ea1SDimitry Andric } 3980fca6ea1SDimitry Andric 3990fca6ea1SDimitry Andric bool TypeInfer::EnforceInteger(TypeSetByHwMode &Out) { 4000fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 4010fca6ea1SDimitry Andric if (TP.hasError()) 4020fca6ea1SDimitry Andric return false; 4030fca6ea1SDimitry Andric if (!Out.empty()) 4040fca6ea1SDimitry Andric return Out.constrain(isIntegerOrPtr); 4050fca6ea1SDimitry Andric 4060fca6ea1SDimitry Andric return Out.assign_if(getLegalTypes(), isIntegerOrPtr); 4070fca6ea1SDimitry Andric } 4080fca6ea1SDimitry Andric 4090fca6ea1SDimitry Andric bool TypeInfer::EnforceFloatingPoint(TypeSetByHwMode &Out) { 4100fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 4110fca6ea1SDimitry Andric if (TP.hasError()) 4120fca6ea1SDimitry Andric return false; 4130fca6ea1SDimitry Andric if (!Out.empty()) 4140fca6ea1SDimitry Andric return Out.constrain(isFloatingPoint); 4150fca6ea1SDimitry Andric 4160fca6ea1SDimitry Andric return Out.assign_if(getLegalTypes(), isFloatingPoint); 4170fca6ea1SDimitry Andric } 4180fca6ea1SDimitry Andric 4190fca6ea1SDimitry Andric bool TypeInfer::EnforceScalar(TypeSetByHwMode &Out) { 4200fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 4210fca6ea1SDimitry Andric if (TP.hasError()) 4220fca6ea1SDimitry Andric return false; 4230fca6ea1SDimitry Andric if (!Out.empty()) 4240fca6ea1SDimitry Andric return Out.constrain(isScalar); 4250fca6ea1SDimitry Andric 4260fca6ea1SDimitry Andric return Out.assign_if(getLegalTypes(), isScalar); 4270fca6ea1SDimitry Andric } 4280fca6ea1SDimitry Andric 4290fca6ea1SDimitry Andric bool TypeInfer::EnforceVector(TypeSetByHwMode &Out) { 4300fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 4310fca6ea1SDimitry Andric if (TP.hasError()) 4320fca6ea1SDimitry Andric return false; 4330fca6ea1SDimitry Andric if (!Out.empty()) 4340fca6ea1SDimitry Andric return Out.constrain(isVector); 4350fca6ea1SDimitry Andric 4360fca6ea1SDimitry Andric return Out.assign_if(getLegalTypes(), isVector); 4370fca6ea1SDimitry Andric } 4380fca6ea1SDimitry Andric 4390fca6ea1SDimitry Andric bool TypeInfer::EnforceAny(TypeSetByHwMode &Out) { 4400fca6ea1SDimitry Andric ValidateOnExit _1(Out, *this); 4410fca6ea1SDimitry Andric if (TP.hasError() || !Out.empty()) 4420fca6ea1SDimitry Andric return false; 4430fca6ea1SDimitry Andric 4440fca6ea1SDimitry Andric Out = getLegalTypes(); 4450fca6ea1SDimitry Andric return true; 4460fca6ea1SDimitry Andric } 4470fca6ea1SDimitry Andric 4480fca6ea1SDimitry Andric template <typename Iter, typename Pred, typename Less> 4490fca6ea1SDimitry Andric static Iter min_if(Iter B, Iter E, Pred P, Less L) { 4500fca6ea1SDimitry Andric if (B == E) 4510fca6ea1SDimitry Andric return E; 4520fca6ea1SDimitry Andric Iter Min = E; 4530fca6ea1SDimitry Andric for (Iter I = B; I != E; ++I) { 4540fca6ea1SDimitry Andric if (!P(*I)) 4550fca6ea1SDimitry Andric continue; 4560fca6ea1SDimitry Andric if (Min == E || L(*I, *Min)) 4570fca6ea1SDimitry Andric Min = I; 4580fca6ea1SDimitry Andric } 4590fca6ea1SDimitry Andric return Min; 4600fca6ea1SDimitry Andric } 4610fca6ea1SDimitry Andric 4620fca6ea1SDimitry Andric template <typename Iter, typename Pred, typename Less> 4630fca6ea1SDimitry Andric static Iter max_if(Iter B, Iter E, Pred P, Less L) { 4640fca6ea1SDimitry Andric if (B == E) 4650fca6ea1SDimitry Andric return E; 4660fca6ea1SDimitry Andric Iter Max = E; 4670fca6ea1SDimitry Andric for (Iter I = B; I != E; ++I) { 4680fca6ea1SDimitry Andric if (!P(*I)) 4690fca6ea1SDimitry Andric continue; 4700fca6ea1SDimitry Andric if (Max == E || L(*Max, *I)) 4710fca6ea1SDimitry Andric Max = I; 4720fca6ea1SDimitry Andric } 4730fca6ea1SDimitry Andric return Max; 4740fca6ea1SDimitry Andric } 4750fca6ea1SDimitry Andric 4760fca6ea1SDimitry Andric /// Make sure that for each type in Small, there exists a larger type in Big. 4770fca6ea1SDimitry Andric bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small, TypeSetByHwMode &Big, 4780fca6ea1SDimitry Andric bool SmallIsVT) { 4790fca6ea1SDimitry Andric ValidateOnExit _1(Small, *this), _2(Big, *this); 4800fca6ea1SDimitry Andric if (TP.hasError()) 4810fca6ea1SDimitry Andric return false; 4820fca6ea1SDimitry Andric bool Changed = false; 4830fca6ea1SDimitry Andric 4840fca6ea1SDimitry Andric assert((!SmallIsVT || !Small.empty()) && 4850fca6ea1SDimitry Andric "Small should not be empty for SDTCisVTSmallerThanOp"); 4860fca6ea1SDimitry Andric 4870fca6ea1SDimitry Andric if (Small.empty()) 4880fca6ea1SDimitry Andric Changed |= EnforceAny(Small); 4890fca6ea1SDimitry Andric if (Big.empty()) 4900fca6ea1SDimitry Andric Changed |= EnforceAny(Big); 4910fca6ea1SDimitry Andric 4920fca6ea1SDimitry Andric assert(Small.hasDefault() && Big.hasDefault()); 4930fca6ea1SDimitry Andric 4940fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 4950fca6ea1SDimitry Andric union_modes(Small, Big, Modes); 4960fca6ea1SDimitry Andric 4970fca6ea1SDimitry Andric // 1. Only allow integer or floating point types and make sure that 4980fca6ea1SDimitry Andric // both sides are both integer or both floating point. 4990fca6ea1SDimitry Andric // 2. Make sure that either both sides have vector types, or neither 5000fca6ea1SDimitry Andric // of them does. 5010fca6ea1SDimitry Andric for (unsigned M : Modes) { 5020fca6ea1SDimitry Andric TypeSetByHwMode::SetType &S = Small.get(M); 5030fca6ea1SDimitry Andric TypeSetByHwMode::SetType &B = Big.get(M); 5040fca6ea1SDimitry Andric 5050fca6ea1SDimitry Andric assert((!SmallIsVT || !S.empty()) && "Expected non-empty type"); 5060fca6ea1SDimitry Andric 5070fca6ea1SDimitry Andric if (any_of(S, isIntegerOrPtr) && any_of(B, isIntegerOrPtr)) { 5080fca6ea1SDimitry Andric auto NotInt = [](MVT VT) { return !isIntegerOrPtr(VT); }; 5090fca6ea1SDimitry Andric Changed |= berase_if(S, NotInt); 5100fca6ea1SDimitry Andric Changed |= berase_if(B, NotInt); 5110fca6ea1SDimitry Andric } else if (any_of(S, isFloatingPoint) && any_of(B, isFloatingPoint)) { 5120fca6ea1SDimitry Andric auto NotFP = [](MVT VT) { return !isFloatingPoint(VT); }; 5130fca6ea1SDimitry Andric Changed |= berase_if(S, NotFP); 5140fca6ea1SDimitry Andric Changed |= berase_if(B, NotFP); 5150fca6ea1SDimitry Andric } else if (SmallIsVT && B.empty()) { 5160fca6ea1SDimitry Andric // B is empty and since S is a specific VT, it will never be empty. Don't 5170fca6ea1SDimitry Andric // report this as a change, just clear S and continue. This prevents an 5180fca6ea1SDimitry Andric // infinite loop. 5190fca6ea1SDimitry Andric S.clear(); 5200fca6ea1SDimitry Andric } else if (S.empty() || B.empty()) { 5210fca6ea1SDimitry Andric Changed = !S.empty() || !B.empty(); 5220fca6ea1SDimitry Andric S.clear(); 5230fca6ea1SDimitry Andric B.clear(); 5240fca6ea1SDimitry Andric } else { 5250fca6ea1SDimitry Andric TP.error("Incompatible types"); 5260fca6ea1SDimitry Andric return Changed; 5270fca6ea1SDimitry Andric } 5280fca6ea1SDimitry Andric 5290fca6ea1SDimitry Andric if (none_of(S, isVector) || none_of(B, isVector)) { 5300fca6ea1SDimitry Andric Changed |= berase_if(S, isVector); 5310fca6ea1SDimitry Andric Changed |= berase_if(B, isVector); 5320fca6ea1SDimitry Andric } 5330fca6ea1SDimitry Andric } 5340fca6ea1SDimitry Andric 5350fca6ea1SDimitry Andric auto LT = [](MVT A, MVT B) -> bool { 5360fca6ea1SDimitry Andric // Always treat non-scalable MVTs as smaller than scalable MVTs for the 5370fca6ea1SDimitry Andric // purposes of ordering. 5380fca6ea1SDimitry Andric auto ASize = std::tuple(A.isScalableVector(), A.getScalarSizeInBits(), 5390fca6ea1SDimitry Andric A.getSizeInBits().getKnownMinValue()); 5400fca6ea1SDimitry Andric auto BSize = std::tuple(B.isScalableVector(), B.getScalarSizeInBits(), 5410fca6ea1SDimitry Andric B.getSizeInBits().getKnownMinValue()); 5420fca6ea1SDimitry Andric return ASize < BSize; 5430fca6ea1SDimitry Andric }; 5440fca6ea1SDimitry Andric auto SameKindLE = [](MVT A, MVT B) -> bool { 5450fca6ea1SDimitry Andric // This function is used when removing elements: when a vector is compared 5460fca6ea1SDimitry Andric // to a non-vector or a scalable vector to any non-scalable MVT, it should 5470fca6ea1SDimitry Andric // return false (to avoid removal). 5480fca6ea1SDimitry Andric if (std::tuple(A.isVector(), A.isScalableVector()) != 5490fca6ea1SDimitry Andric std::tuple(B.isVector(), B.isScalableVector())) 5500fca6ea1SDimitry Andric return false; 5510fca6ea1SDimitry Andric 5520fca6ea1SDimitry Andric return std::tuple(A.getScalarSizeInBits(), 5530fca6ea1SDimitry Andric A.getSizeInBits().getKnownMinValue()) <= 5540fca6ea1SDimitry Andric std::tuple(B.getScalarSizeInBits(), 5550fca6ea1SDimitry Andric B.getSizeInBits().getKnownMinValue()); 5560fca6ea1SDimitry Andric }; 5570fca6ea1SDimitry Andric 5580fca6ea1SDimitry Andric for (unsigned M : Modes) { 5590fca6ea1SDimitry Andric TypeSetByHwMode::SetType &S = Small.get(M); 5600fca6ea1SDimitry Andric TypeSetByHwMode::SetType &B = Big.get(M); 5610fca6ea1SDimitry Andric // MinS = min scalar in Small, remove all scalars from Big that are 5620fca6ea1SDimitry Andric // smaller-or-equal than MinS. 5630fca6ea1SDimitry Andric auto MinS = min_if(S.begin(), S.end(), isScalar, LT); 5640fca6ea1SDimitry Andric if (MinS != S.end()) 5650fca6ea1SDimitry Andric Changed |= 5660fca6ea1SDimitry Andric berase_if(B, std::bind(SameKindLE, std::placeholders::_1, *MinS)); 5670fca6ea1SDimitry Andric 5680fca6ea1SDimitry Andric // MaxS = max scalar in Big, remove all scalars from Small that are 5690fca6ea1SDimitry Andric // larger than MaxS. 5700fca6ea1SDimitry Andric auto MaxS = max_if(B.begin(), B.end(), isScalar, LT); 5710fca6ea1SDimitry Andric if (MaxS != B.end()) 5720fca6ea1SDimitry Andric Changed |= 5730fca6ea1SDimitry Andric berase_if(S, std::bind(SameKindLE, *MaxS, std::placeholders::_1)); 5740fca6ea1SDimitry Andric 5750fca6ea1SDimitry Andric // MinV = min vector in Small, remove all vectors from Big that are 5760fca6ea1SDimitry Andric // smaller-or-equal than MinV. 5770fca6ea1SDimitry Andric auto MinV = min_if(S.begin(), S.end(), isVector, LT); 5780fca6ea1SDimitry Andric if (MinV != S.end()) 5790fca6ea1SDimitry Andric Changed |= 5800fca6ea1SDimitry Andric berase_if(B, std::bind(SameKindLE, std::placeholders::_1, *MinV)); 5810fca6ea1SDimitry Andric 5820fca6ea1SDimitry Andric // MaxV = max vector in Big, remove all vectors from Small that are 5830fca6ea1SDimitry Andric // larger than MaxV. 5840fca6ea1SDimitry Andric auto MaxV = max_if(B.begin(), B.end(), isVector, LT); 5850fca6ea1SDimitry Andric if (MaxV != B.end()) 5860fca6ea1SDimitry Andric Changed |= 5870fca6ea1SDimitry Andric berase_if(S, std::bind(SameKindLE, *MaxV, std::placeholders::_1)); 5880fca6ea1SDimitry Andric } 5890fca6ea1SDimitry Andric 5900fca6ea1SDimitry Andric return Changed; 5910fca6ea1SDimitry Andric } 5920fca6ea1SDimitry Andric 5930fca6ea1SDimitry Andric /// 1. Ensure that for each type T in Vec, T is a vector type, and that 5940fca6ea1SDimitry Andric /// for each type U in Elem, U is a scalar type. 5950fca6ea1SDimitry Andric /// 2. Ensure that for each (scalar) type U in Elem, there exists a (vector) 5960fca6ea1SDimitry Andric /// type T in Vec, such that U is the element type of T. 5970fca6ea1SDimitry Andric bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec, 5980fca6ea1SDimitry Andric TypeSetByHwMode &Elem) { 5990fca6ea1SDimitry Andric ValidateOnExit _1(Vec, *this), _2(Elem, *this); 6000fca6ea1SDimitry Andric if (TP.hasError()) 6010fca6ea1SDimitry Andric return false; 6020fca6ea1SDimitry Andric bool Changed = false; 6030fca6ea1SDimitry Andric 6040fca6ea1SDimitry Andric if (Vec.empty()) 6050fca6ea1SDimitry Andric Changed |= EnforceVector(Vec); 6060fca6ea1SDimitry Andric if (Elem.empty()) 6070fca6ea1SDimitry Andric Changed |= EnforceScalar(Elem); 6080fca6ea1SDimitry Andric 6090fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 6100fca6ea1SDimitry Andric union_modes(Vec, Elem, Modes); 6110fca6ea1SDimitry Andric for (unsigned M : Modes) { 6120fca6ea1SDimitry Andric TypeSetByHwMode::SetType &V = Vec.get(M); 6130fca6ea1SDimitry Andric TypeSetByHwMode::SetType &E = Elem.get(M); 6140fca6ea1SDimitry Andric 6150fca6ea1SDimitry Andric Changed |= berase_if(V, isScalar); // Scalar = !vector 6160fca6ea1SDimitry Andric Changed |= berase_if(E, isVector); // Vector = !scalar 6170fca6ea1SDimitry Andric assert(!V.empty() && !E.empty()); 6180fca6ea1SDimitry Andric 6190fca6ea1SDimitry Andric MachineValueTypeSet VT, ST; 6200fca6ea1SDimitry Andric // Collect element types from the "vector" set. 6210fca6ea1SDimitry Andric for (MVT T : V) 6220fca6ea1SDimitry Andric VT.insert(T.getVectorElementType()); 6230fca6ea1SDimitry Andric // Collect scalar types from the "element" set. 6240fca6ea1SDimitry Andric for (MVT T : E) 6250fca6ea1SDimitry Andric ST.insert(T); 6260fca6ea1SDimitry Andric 6270fca6ea1SDimitry Andric // Remove from V all (vector) types whose element type is not in S. 6280fca6ea1SDimitry Andric Changed |= berase_if(V, [&ST](MVT T) -> bool { 6290fca6ea1SDimitry Andric return !ST.count(T.getVectorElementType()); 6300fca6ea1SDimitry Andric }); 6310fca6ea1SDimitry Andric // Remove from E all (scalar) types, for which there is no corresponding 6320fca6ea1SDimitry Andric // type in V. 6330fca6ea1SDimitry Andric Changed |= berase_if(E, [&VT](MVT T) -> bool { return !VT.count(T); }); 6340fca6ea1SDimitry Andric } 6350fca6ea1SDimitry Andric 6360fca6ea1SDimitry Andric return Changed; 6370fca6ea1SDimitry Andric } 6380fca6ea1SDimitry Andric 6390fca6ea1SDimitry Andric bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec, 6400fca6ea1SDimitry Andric const ValueTypeByHwMode &VVT) { 6410fca6ea1SDimitry Andric TypeSetByHwMode Tmp(VVT); 6420fca6ea1SDimitry Andric ValidateOnExit _1(Vec, *this), _2(Tmp, *this); 6430fca6ea1SDimitry Andric return EnforceVectorEltTypeIs(Vec, Tmp); 6440fca6ea1SDimitry Andric } 6450fca6ea1SDimitry Andric 6460fca6ea1SDimitry Andric /// Ensure that for each type T in Sub, T is a vector type, and there 6470fca6ea1SDimitry Andric /// exists a type U in Vec such that U is a vector type with the same 6480fca6ea1SDimitry Andric /// element type as T and at least as many elements as T. 6490fca6ea1SDimitry Andric bool TypeInfer::EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec, 6500fca6ea1SDimitry Andric TypeSetByHwMode &Sub) { 6510fca6ea1SDimitry Andric ValidateOnExit _1(Vec, *this), _2(Sub, *this); 6520fca6ea1SDimitry Andric if (TP.hasError()) 6530fca6ea1SDimitry Andric return false; 6540fca6ea1SDimitry Andric 6550fca6ea1SDimitry Andric /// Return true if B is a suB-vector of P, i.e. P is a suPer-vector of B. 6560fca6ea1SDimitry Andric auto IsSubVec = [](MVT B, MVT P) -> bool { 6570fca6ea1SDimitry Andric if (!B.isVector() || !P.isVector()) 6580fca6ea1SDimitry Andric return false; 6590fca6ea1SDimitry Andric // Logically a <4 x i32> is a valid subvector of <n x 4 x i32> 6600fca6ea1SDimitry Andric // but until there are obvious use-cases for this, keep the 6610fca6ea1SDimitry Andric // types separate. 6620fca6ea1SDimitry Andric if (B.isScalableVector() != P.isScalableVector()) 6630fca6ea1SDimitry Andric return false; 6640fca6ea1SDimitry Andric if (B.getVectorElementType() != P.getVectorElementType()) 6650fca6ea1SDimitry Andric return false; 6660fca6ea1SDimitry Andric return B.getVectorMinNumElements() < P.getVectorMinNumElements(); 6670fca6ea1SDimitry Andric }; 6680fca6ea1SDimitry Andric 6690fca6ea1SDimitry Andric /// Return true if S has no element (vector type) that T is a sub-vector of, 6700fca6ea1SDimitry Andric /// i.e. has the same element type as T and more elements. 6710fca6ea1SDimitry Andric auto NoSubV = [&IsSubVec](const TypeSetByHwMode::SetType &S, MVT T) -> bool { 6720fca6ea1SDimitry Andric for (auto I : S) 6730fca6ea1SDimitry Andric if (IsSubVec(T, I)) 6740fca6ea1SDimitry Andric return false; 6750fca6ea1SDimitry Andric return true; 6760fca6ea1SDimitry Andric }; 6770fca6ea1SDimitry Andric 6780fca6ea1SDimitry Andric /// Return true if S has no element (vector type) that T is a super-vector 6790fca6ea1SDimitry Andric /// of, i.e. has the same element type as T and fewer elements. 6800fca6ea1SDimitry Andric auto NoSupV = [&IsSubVec](const TypeSetByHwMode::SetType &S, MVT T) -> bool { 6810fca6ea1SDimitry Andric for (auto I : S) 6820fca6ea1SDimitry Andric if (IsSubVec(I, T)) 6830fca6ea1SDimitry Andric return false; 6840fca6ea1SDimitry Andric return true; 6850fca6ea1SDimitry Andric }; 6860fca6ea1SDimitry Andric 6870fca6ea1SDimitry Andric bool Changed = false; 6880fca6ea1SDimitry Andric 6890fca6ea1SDimitry Andric if (Vec.empty()) 6900fca6ea1SDimitry Andric Changed |= EnforceVector(Vec); 6910fca6ea1SDimitry Andric if (Sub.empty()) 6920fca6ea1SDimitry Andric Changed |= EnforceVector(Sub); 6930fca6ea1SDimitry Andric 6940fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 6950fca6ea1SDimitry Andric union_modes(Vec, Sub, Modes); 6960fca6ea1SDimitry Andric for (unsigned M : Modes) { 6970fca6ea1SDimitry Andric TypeSetByHwMode::SetType &S = Sub.get(M); 6980fca6ea1SDimitry Andric TypeSetByHwMode::SetType &V = Vec.get(M); 6990fca6ea1SDimitry Andric 7000fca6ea1SDimitry Andric Changed |= berase_if(S, isScalar); 7010fca6ea1SDimitry Andric 7020fca6ea1SDimitry Andric // Erase all types from S that are not sub-vectors of a type in V. 7030fca6ea1SDimitry Andric Changed |= berase_if(S, std::bind(NoSubV, V, std::placeholders::_1)); 7040fca6ea1SDimitry Andric 7050fca6ea1SDimitry Andric // Erase all types from V that are not super-vectors of a type in S. 7060fca6ea1SDimitry Andric Changed |= berase_if(V, std::bind(NoSupV, S, std::placeholders::_1)); 7070fca6ea1SDimitry Andric } 7080fca6ea1SDimitry Andric 7090fca6ea1SDimitry Andric return Changed; 7100fca6ea1SDimitry Andric } 7110fca6ea1SDimitry Andric 7120fca6ea1SDimitry Andric /// 1. Ensure that V has a scalar type iff W has a scalar type. 7130fca6ea1SDimitry Andric /// 2. Ensure that for each vector type T in V, there exists a vector 7140fca6ea1SDimitry Andric /// type U in W, such that T and U have the same number of elements. 7150fca6ea1SDimitry Andric /// 3. Ensure that for each vector type U in W, there exists a vector 7160fca6ea1SDimitry Andric /// type T in V, such that T and U have the same number of elements 7170fca6ea1SDimitry Andric /// (reverse of 2). 7180fca6ea1SDimitry Andric bool TypeInfer::EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W) { 7190fca6ea1SDimitry Andric ValidateOnExit _1(V, *this), _2(W, *this); 7200fca6ea1SDimitry Andric if (TP.hasError()) 7210fca6ea1SDimitry Andric return false; 7220fca6ea1SDimitry Andric 7230fca6ea1SDimitry Andric bool Changed = false; 7240fca6ea1SDimitry Andric if (V.empty()) 7250fca6ea1SDimitry Andric Changed |= EnforceAny(V); 7260fca6ea1SDimitry Andric if (W.empty()) 7270fca6ea1SDimitry Andric Changed |= EnforceAny(W); 7280fca6ea1SDimitry Andric 7290fca6ea1SDimitry Andric // An actual vector type cannot have 0 elements, so we can treat scalars 7300fca6ea1SDimitry Andric // as zero-length vectors. This way both vectors and scalars can be 7310fca6ea1SDimitry Andric // processed identically. 7320fca6ea1SDimitry Andric auto NoLength = [](const SmallDenseSet<ElementCount> &Lengths, 7330fca6ea1SDimitry Andric MVT T) -> bool { 7340fca6ea1SDimitry Andric return !Lengths.count(T.isVector() ? T.getVectorElementCount() 7350fca6ea1SDimitry Andric : ElementCount()); 7360fca6ea1SDimitry Andric }; 7370fca6ea1SDimitry Andric 7380fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 7390fca6ea1SDimitry Andric union_modes(V, W, Modes); 7400fca6ea1SDimitry Andric for (unsigned M : Modes) { 7410fca6ea1SDimitry Andric TypeSetByHwMode::SetType &VS = V.get(M); 7420fca6ea1SDimitry Andric TypeSetByHwMode::SetType &WS = W.get(M); 7430fca6ea1SDimitry Andric 7440fca6ea1SDimitry Andric SmallDenseSet<ElementCount> VN, WN; 7450fca6ea1SDimitry Andric for (MVT T : VS) 7460fca6ea1SDimitry Andric VN.insert(T.isVector() ? T.getVectorElementCount() : ElementCount()); 7470fca6ea1SDimitry Andric for (MVT T : WS) 7480fca6ea1SDimitry Andric WN.insert(T.isVector() ? T.getVectorElementCount() : ElementCount()); 7490fca6ea1SDimitry Andric 7500fca6ea1SDimitry Andric Changed |= berase_if(VS, std::bind(NoLength, WN, std::placeholders::_1)); 7510fca6ea1SDimitry Andric Changed |= berase_if(WS, std::bind(NoLength, VN, std::placeholders::_1)); 7520fca6ea1SDimitry Andric } 7530fca6ea1SDimitry Andric return Changed; 7540fca6ea1SDimitry Andric } 7550fca6ea1SDimitry Andric 7560fca6ea1SDimitry Andric namespace { 7570fca6ea1SDimitry Andric struct TypeSizeComparator { 7580fca6ea1SDimitry Andric bool operator()(const TypeSize &LHS, const TypeSize &RHS) const { 7590fca6ea1SDimitry Andric return std::tuple(LHS.isScalable(), LHS.getKnownMinValue()) < 7600fca6ea1SDimitry Andric std::tuple(RHS.isScalable(), RHS.getKnownMinValue()); 7610fca6ea1SDimitry Andric } 7620fca6ea1SDimitry Andric }; 7630fca6ea1SDimitry Andric } // end anonymous namespace 7640fca6ea1SDimitry Andric 7650fca6ea1SDimitry Andric /// 1. Ensure that for each type T in A, there exists a type U in B, 7660fca6ea1SDimitry Andric /// such that T and U have equal size in bits. 7670fca6ea1SDimitry Andric /// 2. Ensure that for each type U in B, there exists a type T in A 7680fca6ea1SDimitry Andric /// such that T and U have equal size in bits (reverse of 1). 7690fca6ea1SDimitry Andric bool TypeInfer::EnforceSameSize(TypeSetByHwMode &A, TypeSetByHwMode &B) { 7700fca6ea1SDimitry Andric ValidateOnExit _1(A, *this), _2(B, *this); 7710fca6ea1SDimitry Andric if (TP.hasError()) 7720fca6ea1SDimitry Andric return false; 7730fca6ea1SDimitry Andric bool Changed = false; 7740fca6ea1SDimitry Andric if (A.empty()) 7750fca6ea1SDimitry Andric Changed |= EnforceAny(A); 7760fca6ea1SDimitry Andric if (B.empty()) 7770fca6ea1SDimitry Andric Changed |= EnforceAny(B); 7780fca6ea1SDimitry Andric 7790fca6ea1SDimitry Andric typedef SmallSet<TypeSize, 2, TypeSizeComparator> TypeSizeSet; 7800fca6ea1SDimitry Andric 7810fca6ea1SDimitry Andric auto NoSize = [](const TypeSizeSet &Sizes, MVT T) -> bool { 7820fca6ea1SDimitry Andric return !Sizes.count(T.getSizeInBits()); 7830fca6ea1SDimitry Andric }; 7840fca6ea1SDimitry Andric 7850fca6ea1SDimitry Andric SmallVector<unsigned, 4> Modes; 7860fca6ea1SDimitry Andric union_modes(A, B, Modes); 7870fca6ea1SDimitry Andric for (unsigned M : Modes) { 7880fca6ea1SDimitry Andric TypeSetByHwMode::SetType &AS = A.get(M); 7890fca6ea1SDimitry Andric TypeSetByHwMode::SetType &BS = B.get(M); 7900fca6ea1SDimitry Andric TypeSizeSet AN, BN; 7910fca6ea1SDimitry Andric 7920fca6ea1SDimitry Andric for (MVT T : AS) 7930fca6ea1SDimitry Andric AN.insert(T.getSizeInBits()); 7940fca6ea1SDimitry Andric for (MVT T : BS) 7950fca6ea1SDimitry Andric BN.insert(T.getSizeInBits()); 7960fca6ea1SDimitry Andric 7970fca6ea1SDimitry Andric Changed |= berase_if(AS, std::bind(NoSize, BN, std::placeholders::_1)); 7980fca6ea1SDimitry Andric Changed |= berase_if(BS, std::bind(NoSize, AN, std::placeholders::_1)); 7990fca6ea1SDimitry Andric } 8000fca6ea1SDimitry Andric 8010fca6ea1SDimitry Andric return Changed; 8020fca6ea1SDimitry Andric } 8030fca6ea1SDimitry Andric 8040fca6ea1SDimitry Andric void TypeInfer::expandOverloads(TypeSetByHwMode &VTS) const { 8050fca6ea1SDimitry Andric ValidateOnExit _1(VTS, *this); 8060fca6ea1SDimitry Andric const TypeSetByHwMode &Legal = getLegalTypes(); 8070fca6ea1SDimitry Andric assert(Legal.isSimple() && "Default-mode only expected"); 8080fca6ea1SDimitry Andric const TypeSetByHwMode::SetType &LegalTypes = Legal.getSimple(); 8090fca6ea1SDimitry Andric 8100fca6ea1SDimitry Andric for (auto &I : VTS) 8110fca6ea1SDimitry Andric expandOverloads(I.second, LegalTypes); 8120fca6ea1SDimitry Andric } 8130fca6ea1SDimitry Andric 8140fca6ea1SDimitry Andric void TypeInfer::expandOverloads(TypeSetByHwMode::SetType &Out, 8150fca6ea1SDimitry Andric const TypeSetByHwMode::SetType &Legal) const { 8160fca6ea1SDimitry Andric if (Out.count(MVT::iPTRAny)) { 8170fca6ea1SDimitry Andric Out.erase(MVT::iPTRAny); 8180fca6ea1SDimitry Andric Out.insert(MVT::iPTR); 8190fca6ea1SDimitry Andric } else if (Out.count(MVT::iAny)) { 8200fca6ea1SDimitry Andric Out.erase(MVT::iAny); 8210fca6ea1SDimitry Andric for (MVT T : MVT::integer_valuetypes()) 8220fca6ea1SDimitry Andric if (Legal.count(T)) 8230fca6ea1SDimitry Andric Out.insert(T); 8240fca6ea1SDimitry Andric for (MVT T : MVT::integer_fixedlen_vector_valuetypes()) 8250fca6ea1SDimitry Andric if (Legal.count(T)) 8260fca6ea1SDimitry Andric Out.insert(T); 8270fca6ea1SDimitry Andric for (MVT T : MVT::integer_scalable_vector_valuetypes()) 8280fca6ea1SDimitry Andric if (Legal.count(T)) 8290fca6ea1SDimitry Andric Out.insert(T); 8300fca6ea1SDimitry Andric } else if (Out.count(MVT::fAny)) { 8310fca6ea1SDimitry Andric Out.erase(MVT::fAny); 8320fca6ea1SDimitry Andric for (MVT T : MVT::fp_valuetypes()) 8330fca6ea1SDimitry Andric if (Legal.count(T)) 8340fca6ea1SDimitry Andric Out.insert(T); 8350fca6ea1SDimitry Andric for (MVT T : MVT::fp_fixedlen_vector_valuetypes()) 8360fca6ea1SDimitry Andric if (Legal.count(T)) 8370fca6ea1SDimitry Andric Out.insert(T); 8380fca6ea1SDimitry Andric for (MVT T : MVT::fp_scalable_vector_valuetypes()) 8390fca6ea1SDimitry Andric if (Legal.count(T)) 8400fca6ea1SDimitry Andric Out.insert(T); 8410fca6ea1SDimitry Andric } else if (Out.count(MVT::vAny)) { 8420fca6ea1SDimitry Andric Out.erase(MVT::vAny); 8430fca6ea1SDimitry Andric for (MVT T : MVT::vector_valuetypes()) 8440fca6ea1SDimitry Andric if (Legal.count(T)) 8450fca6ea1SDimitry Andric Out.insert(T); 8460fca6ea1SDimitry Andric } else if (Out.count(MVT::Any)) { 8470fca6ea1SDimitry Andric Out.erase(MVT::Any); 8480fca6ea1SDimitry Andric for (MVT T : MVT::all_valuetypes()) 8490fca6ea1SDimitry Andric if (Legal.count(T)) 8500fca6ea1SDimitry Andric Out.insert(T); 8510fca6ea1SDimitry Andric } 8520fca6ea1SDimitry Andric } 8530fca6ea1SDimitry Andric 8540fca6ea1SDimitry Andric const TypeSetByHwMode &TypeInfer::getLegalTypes() const { 8550fca6ea1SDimitry Andric if (!LegalTypesCached) { 8560fca6ea1SDimitry Andric TypeSetByHwMode::SetType &LegalTypes = LegalCache.getOrCreate(DefaultMode); 8570fca6ea1SDimitry Andric // Stuff all types from all modes into the default mode. 8580fca6ea1SDimitry Andric const TypeSetByHwMode <S = TP.getDAGPatterns().getLegalTypes(); 8590fca6ea1SDimitry Andric for (const auto &I : LTS) 8600fca6ea1SDimitry Andric LegalTypes.insert(I.second); 8610fca6ea1SDimitry Andric LegalTypesCached = true; 8620fca6ea1SDimitry Andric } 8630fca6ea1SDimitry Andric assert(LegalCache.isSimple() && "Default-mode only expected"); 8640fca6ea1SDimitry Andric return LegalCache; 8650fca6ea1SDimitry Andric } 8660fca6ea1SDimitry Andric 8670fca6ea1SDimitry Andric TypeInfer::ValidateOnExit::~ValidateOnExit() { 8680fca6ea1SDimitry Andric if (Infer.Validate && !VTS.validate()) { 8690fca6ea1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 8700fca6ea1SDimitry Andric errs() << "Type set is empty for each HW mode:\n" 8710fca6ea1SDimitry Andric "possible type contradiction in the pattern below " 8720fca6ea1SDimitry Andric "(use -print-records with llvm-tblgen to see all " 8730fca6ea1SDimitry Andric "expanded records).\n"; 8740fca6ea1SDimitry Andric Infer.TP.dump(); 8750fca6ea1SDimitry Andric errs() << "Generated from record:\n"; 8760fca6ea1SDimitry Andric Infer.TP.getRecord()->dump(); 8770fca6ea1SDimitry Andric #endif 8780fca6ea1SDimitry Andric PrintFatalError(Infer.TP.getRecord()->getLoc(), 8790fca6ea1SDimitry Andric "Type set is empty for each HW mode in '" + 8800fca6ea1SDimitry Andric Infer.TP.getRecord()->getName() + "'"); 8810fca6ea1SDimitry Andric } 8820fca6ea1SDimitry Andric } 8830fca6ea1SDimitry Andric 8840fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8850fca6ea1SDimitry Andric // ScopedName Implementation 8860fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8870fca6ea1SDimitry Andric 8880fca6ea1SDimitry Andric bool ScopedName::operator==(const ScopedName &o) const { 8890fca6ea1SDimitry Andric return Scope == o.Scope && Identifier == o.Identifier; 8900fca6ea1SDimitry Andric } 8910fca6ea1SDimitry Andric 8920fca6ea1SDimitry Andric bool ScopedName::operator!=(const ScopedName &o) const { return !(*this == o); } 8930fca6ea1SDimitry Andric 8940fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8950fca6ea1SDimitry Andric // TreePredicateFn Implementation 8960fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8970fca6ea1SDimitry Andric 8980fca6ea1SDimitry Andric /// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag. 8990fca6ea1SDimitry Andric TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) { 9000fca6ea1SDimitry Andric assert( 9010fca6ea1SDimitry Andric (!hasPredCode() || !hasImmCode()) && 9020fca6ea1SDimitry Andric ".td file corrupt: can't have a node predicate *and* an imm predicate"); 9030fca6ea1SDimitry Andric } 9040fca6ea1SDimitry Andric 9050fca6ea1SDimitry Andric bool TreePredicateFn::hasPredCode() const { 9060fca6ea1SDimitry Andric return isLoad() || isStore() || isAtomic() || hasNoUse() || hasOneUse() || 9070fca6ea1SDimitry Andric !PatFragRec->getRecord()->getValueAsString("PredicateCode").empty(); 9080fca6ea1SDimitry Andric } 9090fca6ea1SDimitry Andric 9100fca6ea1SDimitry Andric std::string TreePredicateFn::getPredCode() const { 9110fca6ea1SDimitry Andric std::string Code; 9120fca6ea1SDimitry Andric 9130fca6ea1SDimitry Andric if (!isLoad() && !isStore() && !isAtomic()) { 9140fca6ea1SDimitry Andric Record *MemoryVT = getMemoryVT(); 9150fca6ea1SDimitry Andric 9160fca6ea1SDimitry Andric if (MemoryVT) 9170fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9180fca6ea1SDimitry Andric "MemoryVT requires IsLoad or IsStore"); 9190fca6ea1SDimitry Andric } 9200fca6ea1SDimitry Andric 9210fca6ea1SDimitry Andric if (!isLoad() && !isStore()) { 9220fca6ea1SDimitry Andric if (isUnindexed()) 9230fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9240fca6ea1SDimitry Andric "IsUnindexed requires IsLoad or IsStore"); 9250fca6ea1SDimitry Andric 9260fca6ea1SDimitry Andric Record *ScalarMemoryVT = getScalarMemoryVT(); 9270fca6ea1SDimitry Andric 9280fca6ea1SDimitry Andric if (ScalarMemoryVT) 9290fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9300fca6ea1SDimitry Andric "ScalarMemoryVT requires IsLoad or IsStore"); 9310fca6ea1SDimitry Andric } 9320fca6ea1SDimitry Andric 9330fca6ea1SDimitry Andric if (isLoad() + isStore() + isAtomic() > 1) 9340fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9350fca6ea1SDimitry Andric "IsLoad, IsStore, and IsAtomic are mutually exclusive"); 9360fca6ea1SDimitry Andric 9370fca6ea1SDimitry Andric if (isLoad()) { 9380fca6ea1SDimitry Andric if (!isUnindexed() && !isNonExtLoad() && !isAnyExtLoad() && 9390fca6ea1SDimitry Andric !isSignExtLoad() && !isZeroExtLoad() && getMemoryVT() == nullptr && 9400fca6ea1SDimitry Andric getScalarMemoryVT() == nullptr && getAddressSpaces() == nullptr && 9410fca6ea1SDimitry Andric getMinAlignment() < 1) 9420fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9430fca6ea1SDimitry Andric "IsLoad cannot be used by itself"); 9440fca6ea1SDimitry Andric } else { 9450fca6ea1SDimitry Andric if (isNonExtLoad()) 9460fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9470fca6ea1SDimitry Andric "IsNonExtLoad requires IsLoad"); 9480fca6ea1SDimitry Andric if (isAnyExtLoad()) 9490fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9500fca6ea1SDimitry Andric "IsAnyExtLoad requires IsLoad"); 9510fca6ea1SDimitry Andric 9520fca6ea1SDimitry Andric if (!isAtomic()) { 9530fca6ea1SDimitry Andric if (isSignExtLoad()) 9540fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9550fca6ea1SDimitry Andric "IsSignExtLoad requires IsLoad or IsAtomic"); 9560fca6ea1SDimitry Andric if (isZeroExtLoad()) 9570fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9580fca6ea1SDimitry Andric "IsZeroExtLoad requires IsLoad or IsAtomic"); 9590fca6ea1SDimitry Andric } 9600fca6ea1SDimitry Andric } 9610fca6ea1SDimitry Andric 9620fca6ea1SDimitry Andric if (isStore()) { 9630fca6ea1SDimitry Andric if (!isUnindexed() && !isTruncStore() && !isNonTruncStore() && 9640fca6ea1SDimitry Andric getMemoryVT() == nullptr && getScalarMemoryVT() == nullptr && 9650fca6ea1SDimitry Andric getAddressSpaces() == nullptr && getMinAlignment() < 1) 9660fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9670fca6ea1SDimitry Andric "IsStore cannot be used by itself"); 9680fca6ea1SDimitry Andric } else { 9690fca6ea1SDimitry Andric if (isNonTruncStore()) 9700fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9710fca6ea1SDimitry Andric "IsNonTruncStore requires IsStore"); 9720fca6ea1SDimitry Andric if (isTruncStore()) 9730fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9740fca6ea1SDimitry Andric "IsTruncStore requires IsStore"); 9750fca6ea1SDimitry Andric } 9760fca6ea1SDimitry Andric 9770fca6ea1SDimitry Andric if (isAtomic()) { 9780fca6ea1SDimitry Andric if (getMemoryVT() == nullptr && !isAtomicOrderingMonotonic() && 9790fca6ea1SDimitry Andric getAddressSpaces() == nullptr && 9800fca6ea1SDimitry Andric // FIXME: Should atomic loads be IsLoad, IsAtomic, or both? 9810fca6ea1SDimitry Andric !isZeroExtLoad() && !isSignExtLoad() && !isAtomicOrderingAcquire() && 9820fca6ea1SDimitry Andric !isAtomicOrderingRelease() && !isAtomicOrderingAcquireRelease() && 9830fca6ea1SDimitry Andric !isAtomicOrderingSequentiallyConsistent() && 9840fca6ea1SDimitry Andric !isAtomicOrderingAcquireOrStronger() && 9850fca6ea1SDimitry Andric !isAtomicOrderingReleaseOrStronger() && 9860fca6ea1SDimitry Andric !isAtomicOrderingWeakerThanAcquire() && 9870fca6ea1SDimitry Andric !isAtomicOrderingWeakerThanRelease()) 9880fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9890fca6ea1SDimitry Andric "IsAtomic cannot be used by itself"); 9900fca6ea1SDimitry Andric } else { 9910fca6ea1SDimitry Andric if (isAtomicOrderingMonotonic()) 9920fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9930fca6ea1SDimitry Andric "IsAtomicOrderingMonotonic requires IsAtomic"); 9940fca6ea1SDimitry Andric if (isAtomicOrderingAcquire()) 9950fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9960fca6ea1SDimitry Andric "IsAtomicOrderingAcquire requires IsAtomic"); 9970fca6ea1SDimitry Andric if (isAtomicOrderingRelease()) 9980fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 9990fca6ea1SDimitry Andric "IsAtomicOrderingRelease requires IsAtomic"); 10000fca6ea1SDimitry Andric if (isAtomicOrderingAcquireRelease()) 10010fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 10020fca6ea1SDimitry Andric "IsAtomicOrderingAcquireRelease requires IsAtomic"); 10030fca6ea1SDimitry Andric if (isAtomicOrderingSequentiallyConsistent()) 10040fca6ea1SDimitry Andric PrintFatalError( 10050fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 10060fca6ea1SDimitry Andric "IsAtomicOrderingSequentiallyConsistent requires IsAtomic"); 10070fca6ea1SDimitry Andric if (isAtomicOrderingAcquireOrStronger()) 10080fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 10090fca6ea1SDimitry Andric "IsAtomicOrderingAcquireOrStronger requires IsAtomic"); 10100fca6ea1SDimitry Andric if (isAtomicOrderingReleaseOrStronger()) 10110fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 10120fca6ea1SDimitry Andric "IsAtomicOrderingReleaseOrStronger requires IsAtomic"); 10130fca6ea1SDimitry Andric if (isAtomicOrderingWeakerThanAcquire()) 10140fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 10150fca6ea1SDimitry Andric "IsAtomicOrderingWeakerThanAcquire requires IsAtomic"); 10160fca6ea1SDimitry Andric } 10170fca6ea1SDimitry Andric 10180fca6ea1SDimitry Andric if (isLoad() || isStore() || isAtomic()) { 10190fca6ea1SDimitry Andric if (ListInit *AddressSpaces = getAddressSpaces()) { 10200fca6ea1SDimitry Andric Code += "unsigned AddrSpace = cast<MemSDNode>(N)->getAddressSpace();\n" 10210fca6ea1SDimitry Andric " if ("; 10220fca6ea1SDimitry Andric 10230fca6ea1SDimitry Andric ListSeparator LS(" && "); 10240fca6ea1SDimitry Andric for (Init *Val : AddressSpaces->getValues()) { 10250fca6ea1SDimitry Andric Code += LS; 10260fca6ea1SDimitry Andric 10270fca6ea1SDimitry Andric IntInit *IntVal = dyn_cast<IntInit>(Val); 10280fca6ea1SDimitry Andric if (!IntVal) { 10290fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 10300fca6ea1SDimitry Andric "AddressSpaces element must be integer"); 10310fca6ea1SDimitry Andric } 10320fca6ea1SDimitry Andric 10330fca6ea1SDimitry Andric Code += "AddrSpace != " + utostr(IntVal->getValue()); 10340fca6ea1SDimitry Andric } 10350fca6ea1SDimitry Andric 10360fca6ea1SDimitry Andric Code += ")\nreturn false;\n"; 10370fca6ea1SDimitry Andric } 10380fca6ea1SDimitry Andric 10390fca6ea1SDimitry Andric int64_t MinAlign = getMinAlignment(); 10400fca6ea1SDimitry Andric if (MinAlign > 0) { 10410fca6ea1SDimitry Andric Code += "if (cast<MemSDNode>(N)->getAlign() < Align("; 10420fca6ea1SDimitry Andric Code += utostr(MinAlign); 10430fca6ea1SDimitry Andric Code += "))\nreturn false;\n"; 10440fca6ea1SDimitry Andric } 10450fca6ea1SDimitry Andric 10460fca6ea1SDimitry Andric Record *MemoryVT = getMemoryVT(); 10470fca6ea1SDimitry Andric 10480fca6ea1SDimitry Andric if (MemoryVT) 10490fca6ea1SDimitry Andric Code += ("if (cast<MemSDNode>(N)->getMemoryVT() != MVT::" + 10500fca6ea1SDimitry Andric MemoryVT->getName() + ") return false;\n") 10510fca6ea1SDimitry Andric .str(); 10520fca6ea1SDimitry Andric } 10530fca6ea1SDimitry Andric 10540fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingMonotonic()) 10550fca6ea1SDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != " 10560fca6ea1SDimitry Andric "AtomicOrdering::Monotonic) return false;\n"; 10570fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingAcquire()) 10580fca6ea1SDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != " 10590fca6ea1SDimitry Andric "AtomicOrdering::Acquire) return false;\n"; 10600fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingRelease()) 10610fca6ea1SDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != " 10620fca6ea1SDimitry Andric "AtomicOrdering::Release) return false;\n"; 10630fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingAcquireRelease()) 10640fca6ea1SDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != " 10650fca6ea1SDimitry Andric "AtomicOrdering::AcquireRelease) return false;\n"; 10660fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingSequentiallyConsistent()) 10670fca6ea1SDimitry Andric Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != " 10680fca6ea1SDimitry Andric "AtomicOrdering::SequentiallyConsistent) return false;\n"; 10690fca6ea1SDimitry Andric 10700fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingAcquireOrStronger()) 10710fca6ea1SDimitry Andric Code += 10720fca6ea1SDimitry Andric "if (!isAcquireOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) " 10730fca6ea1SDimitry Andric "return false;\n"; 10740fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingWeakerThanAcquire()) 10750fca6ea1SDimitry Andric Code += 10760fca6ea1SDimitry Andric "if (isAcquireOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) " 10770fca6ea1SDimitry Andric "return false;\n"; 10780fca6ea1SDimitry Andric 10790fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingReleaseOrStronger()) 10800fca6ea1SDimitry Andric Code += 10810fca6ea1SDimitry Andric "if (!isReleaseOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) " 10820fca6ea1SDimitry Andric "return false;\n"; 10830fca6ea1SDimitry Andric if (isAtomic() && isAtomicOrderingWeakerThanRelease()) 10840fca6ea1SDimitry Andric Code += 10850fca6ea1SDimitry Andric "if (isReleaseOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) " 10860fca6ea1SDimitry Andric "return false;\n"; 10870fca6ea1SDimitry Andric 10880fca6ea1SDimitry Andric // TODO: Handle atomic sextload/zextload normally when ATOMIC_LOAD is removed. 10890fca6ea1SDimitry Andric if (isAtomic() && (isZeroExtLoad() || isSignExtLoad())) 10900fca6ea1SDimitry Andric Code += "return false;\n"; 10910fca6ea1SDimitry Andric 10920fca6ea1SDimitry Andric if (isLoad() || isStore()) { 10930fca6ea1SDimitry Andric StringRef SDNodeName = isLoad() ? "LoadSDNode" : "StoreSDNode"; 10940fca6ea1SDimitry Andric 10950fca6ea1SDimitry Andric if (isUnindexed()) 10960fca6ea1SDimitry Andric Code += ("if (cast<" + SDNodeName + 10970fca6ea1SDimitry Andric ">(N)->getAddressingMode() != ISD::UNINDEXED) " 10980fca6ea1SDimitry Andric "return false;\n") 10990fca6ea1SDimitry Andric .str(); 11000fca6ea1SDimitry Andric 11010fca6ea1SDimitry Andric if (isLoad()) { 11020fca6ea1SDimitry Andric if ((isNonExtLoad() + isAnyExtLoad() + isSignExtLoad() + 11030fca6ea1SDimitry Andric isZeroExtLoad()) > 1) 11040fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 11050fca6ea1SDimitry Andric "IsNonExtLoad, IsAnyExtLoad, IsSignExtLoad, and " 11060fca6ea1SDimitry Andric "IsZeroExtLoad are mutually exclusive"); 11070fca6ea1SDimitry Andric if (isNonExtLoad()) 11080fca6ea1SDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != " 11090fca6ea1SDimitry Andric "ISD::NON_EXTLOAD) return false;\n"; 11100fca6ea1SDimitry Andric if (isAnyExtLoad()) 11110fca6ea1SDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::EXTLOAD) " 11120fca6ea1SDimitry Andric "return false;\n"; 11130fca6ea1SDimitry Andric if (isSignExtLoad()) 11140fca6ea1SDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::SEXTLOAD) " 11150fca6ea1SDimitry Andric "return false;\n"; 11160fca6ea1SDimitry Andric if (isZeroExtLoad()) 11170fca6ea1SDimitry Andric Code += "if (cast<LoadSDNode>(N)->getExtensionType() != ISD::ZEXTLOAD) " 11180fca6ea1SDimitry Andric "return false;\n"; 11190fca6ea1SDimitry Andric } else { 11200fca6ea1SDimitry Andric if ((isNonTruncStore() + isTruncStore()) > 1) 11210fca6ea1SDimitry Andric PrintFatalError( 11220fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 11230fca6ea1SDimitry Andric "IsNonTruncStore, and IsTruncStore are mutually exclusive"); 11240fca6ea1SDimitry Andric if (isNonTruncStore()) 11250fca6ea1SDimitry Andric Code += 11260fca6ea1SDimitry Andric " if (cast<StoreSDNode>(N)->isTruncatingStore()) return false;\n"; 11270fca6ea1SDimitry Andric if (isTruncStore()) 11280fca6ea1SDimitry Andric Code += 11290fca6ea1SDimitry Andric " if (!cast<StoreSDNode>(N)->isTruncatingStore()) return false;\n"; 11300fca6ea1SDimitry Andric } 11310fca6ea1SDimitry Andric 11320fca6ea1SDimitry Andric Record *ScalarMemoryVT = getScalarMemoryVT(); 11330fca6ea1SDimitry Andric 11340fca6ea1SDimitry Andric if (ScalarMemoryVT) 11350fca6ea1SDimitry Andric Code += ("if (cast<" + SDNodeName + 11360fca6ea1SDimitry Andric ">(N)->getMemoryVT().getScalarType() != MVT::" + 11370fca6ea1SDimitry Andric ScalarMemoryVT->getName() + ") return false;\n") 11380fca6ea1SDimitry Andric .str(); 11390fca6ea1SDimitry Andric } 11400fca6ea1SDimitry Andric 11410fca6ea1SDimitry Andric if (hasNoUse()) 11420fca6ea1SDimitry Andric Code += "if (!SDValue(N, 0).use_empty()) return false;\n"; 11430fca6ea1SDimitry Andric if (hasOneUse()) 11440fca6ea1SDimitry Andric Code += "if (!SDValue(N, 0).hasOneUse()) return false;\n"; 11450fca6ea1SDimitry Andric 11460fca6ea1SDimitry Andric std::string PredicateCode = 11470fca6ea1SDimitry Andric std::string(PatFragRec->getRecord()->getValueAsString("PredicateCode")); 11480fca6ea1SDimitry Andric 11490fca6ea1SDimitry Andric Code += PredicateCode; 11500fca6ea1SDimitry Andric 11510fca6ea1SDimitry Andric if (PredicateCode.empty() && !Code.empty()) 11520fca6ea1SDimitry Andric Code += "return true;\n"; 11530fca6ea1SDimitry Andric 11540fca6ea1SDimitry Andric return Code; 11550fca6ea1SDimitry Andric } 11560fca6ea1SDimitry Andric 11570fca6ea1SDimitry Andric bool TreePredicateFn::hasImmCode() const { 11580fca6ea1SDimitry Andric return !PatFragRec->getRecord()->getValueAsString("ImmediateCode").empty(); 11590fca6ea1SDimitry Andric } 11600fca6ea1SDimitry Andric 11610fca6ea1SDimitry Andric std::string TreePredicateFn::getImmCode() const { 11620fca6ea1SDimitry Andric return std::string( 11630fca6ea1SDimitry Andric PatFragRec->getRecord()->getValueAsString("ImmediateCode")); 11640fca6ea1SDimitry Andric } 11650fca6ea1SDimitry Andric 11660fca6ea1SDimitry Andric bool TreePredicateFn::immCodeUsesAPInt() const { 11670fca6ea1SDimitry Andric return getOrigPatFragRecord()->getRecord()->getValueAsBit("IsAPInt"); 11680fca6ea1SDimitry Andric } 11690fca6ea1SDimitry Andric 11700fca6ea1SDimitry Andric bool TreePredicateFn::immCodeUsesAPFloat() const { 11710fca6ea1SDimitry Andric bool Unset; 11720fca6ea1SDimitry Andric // The return value will be false when IsAPFloat is unset. 11730fca6ea1SDimitry Andric return getOrigPatFragRecord()->getRecord()->getValueAsBitOrUnset("IsAPFloat", 11740fca6ea1SDimitry Andric Unset); 11750fca6ea1SDimitry Andric } 11760fca6ea1SDimitry Andric 11770fca6ea1SDimitry Andric bool TreePredicateFn::isPredefinedPredicateEqualTo(StringRef Field, 11780fca6ea1SDimitry Andric bool Value) const { 11790fca6ea1SDimitry Andric bool Unset; 11800fca6ea1SDimitry Andric bool Result = 11810fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getValueAsBitOrUnset(Field, Unset); 11820fca6ea1SDimitry Andric if (Unset) 11830fca6ea1SDimitry Andric return false; 11840fca6ea1SDimitry Andric return Result == Value; 11850fca6ea1SDimitry Andric } 11860fca6ea1SDimitry Andric bool TreePredicateFn::usesOperands() const { 11870fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("PredicateCodeUsesOperands", true); 11880fca6ea1SDimitry Andric } 11890fca6ea1SDimitry Andric bool TreePredicateFn::hasNoUse() const { 11900fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("HasNoUse", true); 11910fca6ea1SDimitry Andric } 11920fca6ea1SDimitry Andric bool TreePredicateFn::hasOneUse() const { 11930fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("HasOneUse", true); 11940fca6ea1SDimitry Andric } 11950fca6ea1SDimitry Andric bool TreePredicateFn::isLoad() const { 11960fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsLoad", true); 11970fca6ea1SDimitry Andric } 11980fca6ea1SDimitry Andric bool TreePredicateFn::isStore() const { 11990fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsStore", true); 12000fca6ea1SDimitry Andric } 12010fca6ea1SDimitry Andric bool TreePredicateFn::isAtomic() const { 12020fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomic", true); 12030fca6ea1SDimitry Andric } 12040fca6ea1SDimitry Andric bool TreePredicateFn::isUnindexed() const { 12050fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsUnindexed", true); 12060fca6ea1SDimitry Andric } 12070fca6ea1SDimitry Andric bool TreePredicateFn::isNonExtLoad() const { 12080fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsNonExtLoad", true); 12090fca6ea1SDimitry Andric } 12100fca6ea1SDimitry Andric bool TreePredicateFn::isAnyExtLoad() const { 12110fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAnyExtLoad", true); 12120fca6ea1SDimitry Andric } 12130fca6ea1SDimitry Andric bool TreePredicateFn::isSignExtLoad() const { 12140fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsSignExtLoad", true); 12150fca6ea1SDimitry Andric } 12160fca6ea1SDimitry Andric bool TreePredicateFn::isZeroExtLoad() const { 12170fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsZeroExtLoad", true); 12180fca6ea1SDimitry Andric } 12190fca6ea1SDimitry Andric bool TreePredicateFn::isNonTruncStore() const { 12200fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsTruncStore", false); 12210fca6ea1SDimitry Andric } 12220fca6ea1SDimitry Andric bool TreePredicateFn::isTruncStore() const { 12230fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsTruncStore", true); 12240fca6ea1SDimitry Andric } 12250fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingMonotonic() const { 12260fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingMonotonic", true); 12270fca6ea1SDimitry Andric } 12280fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingAcquire() const { 12290fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquire", true); 12300fca6ea1SDimitry Andric } 12310fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingRelease() const { 12320fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingRelease", true); 12330fca6ea1SDimitry Andric } 12340fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingAcquireRelease() const { 12350fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireRelease", true); 12360fca6ea1SDimitry Andric } 12370fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingSequentiallyConsistent() const { 12380fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingSequentiallyConsistent", 12390fca6ea1SDimitry Andric true); 12400fca6ea1SDimitry Andric } 12410fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingAcquireOrStronger() const { 12420fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireOrStronger", 12430fca6ea1SDimitry Andric true); 12440fca6ea1SDimitry Andric } 12450fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingWeakerThanAcquire() const { 12460fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireOrStronger", 12470fca6ea1SDimitry Andric false); 12480fca6ea1SDimitry Andric } 12490fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingReleaseOrStronger() const { 12500fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingReleaseOrStronger", 12510fca6ea1SDimitry Andric true); 12520fca6ea1SDimitry Andric } 12530fca6ea1SDimitry Andric bool TreePredicateFn::isAtomicOrderingWeakerThanRelease() const { 12540fca6ea1SDimitry Andric return isPredefinedPredicateEqualTo("IsAtomicOrderingReleaseOrStronger", 12550fca6ea1SDimitry Andric false); 12560fca6ea1SDimitry Andric } 12570fca6ea1SDimitry Andric Record *TreePredicateFn::getMemoryVT() const { 12580fca6ea1SDimitry Andric Record *R = getOrigPatFragRecord()->getRecord(); 12590fca6ea1SDimitry Andric if (R->isValueUnset("MemoryVT")) 12600fca6ea1SDimitry Andric return nullptr; 12610fca6ea1SDimitry Andric return R->getValueAsDef("MemoryVT"); 12620fca6ea1SDimitry Andric } 12630fca6ea1SDimitry Andric 12640fca6ea1SDimitry Andric ListInit *TreePredicateFn::getAddressSpaces() const { 12650fca6ea1SDimitry Andric Record *R = getOrigPatFragRecord()->getRecord(); 12660fca6ea1SDimitry Andric if (R->isValueUnset("AddressSpaces")) 12670fca6ea1SDimitry Andric return nullptr; 12680fca6ea1SDimitry Andric return R->getValueAsListInit("AddressSpaces"); 12690fca6ea1SDimitry Andric } 12700fca6ea1SDimitry Andric 12710fca6ea1SDimitry Andric int64_t TreePredicateFn::getMinAlignment() const { 12720fca6ea1SDimitry Andric Record *R = getOrigPatFragRecord()->getRecord(); 12730fca6ea1SDimitry Andric if (R->isValueUnset("MinAlignment")) 12740fca6ea1SDimitry Andric return 0; 12750fca6ea1SDimitry Andric return R->getValueAsInt("MinAlignment"); 12760fca6ea1SDimitry Andric } 12770fca6ea1SDimitry Andric 12780fca6ea1SDimitry Andric Record *TreePredicateFn::getScalarMemoryVT() const { 12790fca6ea1SDimitry Andric Record *R = getOrigPatFragRecord()->getRecord(); 12800fca6ea1SDimitry Andric if (R->isValueUnset("ScalarMemoryVT")) 12810fca6ea1SDimitry Andric return nullptr; 12820fca6ea1SDimitry Andric return R->getValueAsDef("ScalarMemoryVT"); 12830fca6ea1SDimitry Andric } 12840fca6ea1SDimitry Andric bool TreePredicateFn::hasGISelPredicateCode() const { 12850fca6ea1SDimitry Andric return !PatFragRec->getRecord() 12860fca6ea1SDimitry Andric ->getValueAsString("GISelPredicateCode") 12870fca6ea1SDimitry Andric .empty(); 12880fca6ea1SDimitry Andric } 12890fca6ea1SDimitry Andric std::string TreePredicateFn::getGISelPredicateCode() const { 12900fca6ea1SDimitry Andric return std::string( 12910fca6ea1SDimitry Andric PatFragRec->getRecord()->getValueAsString("GISelPredicateCode")); 12920fca6ea1SDimitry Andric } 12930fca6ea1SDimitry Andric 12940fca6ea1SDimitry Andric StringRef TreePredicateFn::getImmType() const { 12950fca6ea1SDimitry Andric if (immCodeUsesAPInt()) 12960fca6ea1SDimitry Andric return "const APInt &"; 12970fca6ea1SDimitry Andric if (immCodeUsesAPFloat()) 12980fca6ea1SDimitry Andric return "const APFloat &"; 12990fca6ea1SDimitry Andric return "int64_t"; 13000fca6ea1SDimitry Andric } 13010fca6ea1SDimitry Andric 13020fca6ea1SDimitry Andric StringRef TreePredicateFn::getImmTypeIdentifier() const { 13030fca6ea1SDimitry Andric if (immCodeUsesAPInt()) 13040fca6ea1SDimitry Andric return "APInt"; 13050fca6ea1SDimitry Andric if (immCodeUsesAPFloat()) 13060fca6ea1SDimitry Andric return "APFloat"; 13070fca6ea1SDimitry Andric return "I64"; 13080fca6ea1SDimitry Andric } 13090fca6ea1SDimitry Andric 13100fca6ea1SDimitry Andric /// isAlwaysTrue - Return true if this is a noop predicate. 13110fca6ea1SDimitry Andric bool TreePredicateFn::isAlwaysTrue() const { 13120fca6ea1SDimitry Andric return !hasPredCode() && !hasImmCode(); 13130fca6ea1SDimitry Andric } 13140fca6ea1SDimitry Andric 13150fca6ea1SDimitry Andric /// Return the name to use in the generated code to reference this, this is 13160fca6ea1SDimitry Andric /// "Predicate_foo" if from a pattern fragment "foo". 13170fca6ea1SDimitry Andric std::string TreePredicateFn::getFnName() const { 13180fca6ea1SDimitry Andric return "Predicate_" + PatFragRec->getRecord()->getName().str(); 13190fca6ea1SDimitry Andric } 13200fca6ea1SDimitry Andric 13210fca6ea1SDimitry Andric /// getCodeToRunOnSDNode - Return the code for the function body that 13220fca6ea1SDimitry Andric /// evaluates this predicate. The argument is expected to be in "Node", 13230fca6ea1SDimitry Andric /// not N. This handles casting and conversion to a concrete node type as 13240fca6ea1SDimitry Andric /// appropriate. 13250fca6ea1SDimitry Andric std::string TreePredicateFn::getCodeToRunOnSDNode() const { 13260fca6ea1SDimitry Andric // Handle immediate predicates first. 13270fca6ea1SDimitry Andric std::string ImmCode = getImmCode(); 13280fca6ea1SDimitry Andric if (!ImmCode.empty()) { 13290fca6ea1SDimitry Andric if (isLoad()) 13300fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 13310fca6ea1SDimitry Andric "IsLoad cannot be used with ImmLeaf or its subclasses"); 13320fca6ea1SDimitry Andric if (isStore()) 13330fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 13340fca6ea1SDimitry Andric "IsStore cannot be used with ImmLeaf or its subclasses"); 13350fca6ea1SDimitry Andric if (isUnindexed()) 13360fca6ea1SDimitry Andric PrintFatalError( 13370fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 13380fca6ea1SDimitry Andric "IsUnindexed cannot be used with ImmLeaf or its subclasses"); 13390fca6ea1SDimitry Andric if (isNonExtLoad()) 13400fca6ea1SDimitry Andric PrintFatalError( 13410fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 13420fca6ea1SDimitry Andric "IsNonExtLoad cannot be used with ImmLeaf or its subclasses"); 13430fca6ea1SDimitry Andric if (isAnyExtLoad()) 13440fca6ea1SDimitry Andric PrintFatalError( 13450fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 13460fca6ea1SDimitry Andric "IsAnyExtLoad cannot be used with ImmLeaf or its subclasses"); 13470fca6ea1SDimitry Andric if (isSignExtLoad()) 13480fca6ea1SDimitry Andric PrintFatalError( 13490fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 13500fca6ea1SDimitry Andric "IsSignExtLoad cannot be used with ImmLeaf or its subclasses"); 13510fca6ea1SDimitry Andric if (isZeroExtLoad()) 13520fca6ea1SDimitry Andric PrintFatalError( 13530fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 13540fca6ea1SDimitry Andric "IsZeroExtLoad cannot be used with ImmLeaf or its subclasses"); 13550fca6ea1SDimitry Andric if (isNonTruncStore()) 13560fca6ea1SDimitry Andric PrintFatalError( 13570fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 13580fca6ea1SDimitry Andric "IsNonTruncStore cannot be used with ImmLeaf or its subclasses"); 13590fca6ea1SDimitry Andric if (isTruncStore()) 13600fca6ea1SDimitry Andric PrintFatalError( 13610fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 13620fca6ea1SDimitry Andric "IsTruncStore cannot be used with ImmLeaf or its subclasses"); 13630fca6ea1SDimitry Andric if (getMemoryVT()) 13640fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 13650fca6ea1SDimitry Andric "MemoryVT cannot be used with ImmLeaf or its subclasses"); 13660fca6ea1SDimitry Andric if (getScalarMemoryVT()) 13670fca6ea1SDimitry Andric PrintFatalError( 13680fca6ea1SDimitry Andric getOrigPatFragRecord()->getRecord()->getLoc(), 13690fca6ea1SDimitry Andric "ScalarMemoryVT cannot be used with ImmLeaf or its subclasses"); 13700fca6ea1SDimitry Andric 13710fca6ea1SDimitry Andric std::string Result = (" " + getImmType() + " Imm = ").str(); 13720fca6ea1SDimitry Andric if (immCodeUsesAPFloat()) 13730fca6ea1SDimitry Andric Result += "cast<ConstantFPSDNode>(Node)->getValueAPF();\n"; 13740fca6ea1SDimitry Andric else if (immCodeUsesAPInt()) 13750fca6ea1SDimitry Andric Result += "Node->getAsAPIntVal();\n"; 13760fca6ea1SDimitry Andric else 13770fca6ea1SDimitry Andric Result += "cast<ConstantSDNode>(Node)->getSExtValue();\n"; 13780fca6ea1SDimitry Andric return Result + ImmCode; 13790fca6ea1SDimitry Andric } 13800fca6ea1SDimitry Andric 13810fca6ea1SDimitry Andric // Handle arbitrary node predicates. 13820fca6ea1SDimitry Andric assert(hasPredCode() && "Don't have any predicate code!"); 13830fca6ea1SDimitry Andric 13840fca6ea1SDimitry Andric // If this is using PatFrags, there are multiple trees to search. They should 13850fca6ea1SDimitry Andric // all have the same class. FIXME: Is there a way to find a common 13860fca6ea1SDimitry Andric // superclass? 13870fca6ea1SDimitry Andric StringRef ClassName; 13880fca6ea1SDimitry Andric for (const auto &Tree : PatFragRec->getTrees()) { 13890fca6ea1SDimitry Andric StringRef TreeClassName; 13900fca6ea1SDimitry Andric if (Tree->isLeaf()) 13910fca6ea1SDimitry Andric TreeClassName = "SDNode"; 13920fca6ea1SDimitry Andric else { 13930fca6ea1SDimitry Andric Record *Op = Tree->getOperator(); 13940fca6ea1SDimitry Andric const SDNodeInfo &Info = PatFragRec->getDAGPatterns().getSDNodeInfo(Op); 13950fca6ea1SDimitry Andric TreeClassName = Info.getSDClassName(); 13960fca6ea1SDimitry Andric } 13970fca6ea1SDimitry Andric 13980fca6ea1SDimitry Andric if (ClassName.empty()) 13990fca6ea1SDimitry Andric ClassName = TreeClassName; 14000fca6ea1SDimitry Andric else if (ClassName != TreeClassName) { 14010fca6ea1SDimitry Andric PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), 14020fca6ea1SDimitry Andric "PatFrags trees do not have consistent class"); 14030fca6ea1SDimitry Andric } 14040fca6ea1SDimitry Andric } 14050fca6ea1SDimitry Andric 14060fca6ea1SDimitry Andric std::string Result; 14070fca6ea1SDimitry Andric if (ClassName == "SDNode") 14080fca6ea1SDimitry Andric Result = " SDNode *N = Node;\n"; 14090fca6ea1SDimitry Andric else 14100fca6ea1SDimitry Andric Result = " auto *N = cast<" + ClassName.str() + ">(Node);\n"; 14110fca6ea1SDimitry Andric 14120fca6ea1SDimitry Andric return (Twine(Result) + " (void)N;\n" + getPredCode()).str(); 14130fca6ea1SDimitry Andric } 14140fca6ea1SDimitry Andric 14150fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 14160fca6ea1SDimitry Andric // PatternToMatch implementation 14170fca6ea1SDimitry Andric // 14180fca6ea1SDimitry Andric 14190fca6ea1SDimitry Andric static bool isImmAllOnesAllZerosMatch(const TreePatternNode &P) { 14200fca6ea1SDimitry Andric if (!P.isLeaf()) 14210fca6ea1SDimitry Andric return false; 14220fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(P.getLeafValue()); 14230fca6ea1SDimitry Andric if (!DI) 14240fca6ea1SDimitry Andric return false; 14250fca6ea1SDimitry Andric 14260fca6ea1SDimitry Andric Record *R = DI->getDef(); 14270fca6ea1SDimitry Andric return R->getName() == "immAllOnesV" || R->getName() == "immAllZerosV"; 14280fca6ea1SDimitry Andric } 14290fca6ea1SDimitry Andric 14300fca6ea1SDimitry Andric /// getPatternSize - Return the 'size' of this pattern. We want to match large 14310fca6ea1SDimitry Andric /// patterns before small ones. This is used to determine the size of a 14320fca6ea1SDimitry Andric /// pattern. 14330fca6ea1SDimitry Andric static unsigned getPatternSize(const TreePatternNode &P, 14340fca6ea1SDimitry Andric const CodeGenDAGPatterns &CGP) { 14350fca6ea1SDimitry Andric unsigned Size = 3; // The node itself. 14360fca6ea1SDimitry Andric // If the root node is a ConstantSDNode, increases its size. 14370fca6ea1SDimitry Andric // e.g. (set R32:$dst, 0). 14380fca6ea1SDimitry Andric if (P.isLeaf() && isa<IntInit>(P.getLeafValue())) 14390fca6ea1SDimitry Andric Size += 2; 14400fca6ea1SDimitry Andric 14410fca6ea1SDimitry Andric if (const ComplexPattern *AM = P.getComplexPatternInfo(CGP)) { 14420fca6ea1SDimitry Andric Size += AM->getComplexity(); 14430fca6ea1SDimitry Andric // We don't want to count any children twice, so return early. 14440fca6ea1SDimitry Andric return Size; 14450fca6ea1SDimitry Andric } 14460fca6ea1SDimitry Andric 14470fca6ea1SDimitry Andric // If this node has some predicate function that must match, it adds to the 14480fca6ea1SDimitry Andric // complexity of this node. 14490fca6ea1SDimitry Andric if (!P.getPredicateCalls().empty()) 14500fca6ea1SDimitry Andric ++Size; 14510fca6ea1SDimitry Andric 14520fca6ea1SDimitry Andric // Count children in the count if they are also nodes. 14530fca6ea1SDimitry Andric for (unsigned i = 0, e = P.getNumChildren(); i != e; ++i) { 14540fca6ea1SDimitry Andric const TreePatternNode &Child = P.getChild(i); 14550fca6ea1SDimitry Andric if (!Child.isLeaf() && Child.getNumTypes()) { 14560fca6ea1SDimitry Andric const TypeSetByHwMode &T0 = Child.getExtType(0); 14570fca6ea1SDimitry Andric // At this point, all variable type sets should be simple, i.e. only 14580fca6ea1SDimitry Andric // have a default mode. 14590fca6ea1SDimitry Andric if (T0.getMachineValueType() != MVT::Other) { 14600fca6ea1SDimitry Andric Size += getPatternSize(Child, CGP); 14610fca6ea1SDimitry Andric continue; 14620fca6ea1SDimitry Andric } 14630fca6ea1SDimitry Andric } 14640fca6ea1SDimitry Andric if (Child.isLeaf()) { 14650fca6ea1SDimitry Andric if (isa<IntInit>(Child.getLeafValue())) 14660fca6ea1SDimitry Andric Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). 14670fca6ea1SDimitry Andric else if (Child.getComplexPatternInfo(CGP)) 14680fca6ea1SDimitry Andric Size += getPatternSize(Child, CGP); 14690fca6ea1SDimitry Andric else if (isImmAllOnesAllZerosMatch(Child)) 14700fca6ea1SDimitry Andric Size += 4; // Matches a build_vector(+3) and a predicate (+1). 14710fca6ea1SDimitry Andric else if (!Child.getPredicateCalls().empty()) 14720fca6ea1SDimitry Andric ++Size; 14730fca6ea1SDimitry Andric } 14740fca6ea1SDimitry Andric } 14750fca6ea1SDimitry Andric 14760fca6ea1SDimitry Andric return Size; 14770fca6ea1SDimitry Andric } 14780fca6ea1SDimitry Andric 14790fca6ea1SDimitry Andric /// Compute the complexity metric for the input pattern. This roughly 14800fca6ea1SDimitry Andric /// corresponds to the number of nodes that are covered. 14810fca6ea1SDimitry Andric int PatternToMatch::getPatternComplexity(const CodeGenDAGPatterns &CGP) const { 14820fca6ea1SDimitry Andric return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity(); 14830fca6ea1SDimitry Andric } 14840fca6ea1SDimitry Andric 14850fca6ea1SDimitry Andric void PatternToMatch::getPredicateRecords( 14860fca6ea1SDimitry Andric SmallVectorImpl<Record *> &PredicateRecs) const { 14870fca6ea1SDimitry Andric for (Init *I : Predicates->getValues()) { 14880fca6ea1SDimitry Andric if (DefInit *Pred = dyn_cast<DefInit>(I)) { 14890fca6ea1SDimitry Andric Record *Def = Pred->getDef(); 14900fca6ea1SDimitry Andric if (!Def->isSubClassOf("Predicate")) { 14910fca6ea1SDimitry Andric #ifndef NDEBUG 14920fca6ea1SDimitry Andric Def->dump(); 14930fca6ea1SDimitry Andric #endif 14940fca6ea1SDimitry Andric llvm_unreachable("Unknown predicate type!"); 14950fca6ea1SDimitry Andric } 14960fca6ea1SDimitry Andric PredicateRecs.push_back(Def); 14970fca6ea1SDimitry Andric } 14980fca6ea1SDimitry Andric } 14990fca6ea1SDimitry Andric // Sort so that different orders get canonicalized to the same string. 15000fca6ea1SDimitry Andric llvm::sort(PredicateRecs, LessRecord()); 15010fca6ea1SDimitry Andric // Remove duplicate predicates. 15020fca6ea1SDimitry Andric PredicateRecs.erase(llvm::unique(PredicateRecs), PredicateRecs.end()); 15030fca6ea1SDimitry Andric } 15040fca6ea1SDimitry Andric 15050fca6ea1SDimitry Andric /// getPredicateCheck - Return a single string containing all of this 15060fca6ea1SDimitry Andric /// pattern's predicates concatenated with "&&" operators. 15070fca6ea1SDimitry Andric /// 15080fca6ea1SDimitry Andric std::string PatternToMatch::getPredicateCheck() const { 15090fca6ea1SDimitry Andric SmallVector<Record *, 4> PredicateRecs; 15100fca6ea1SDimitry Andric getPredicateRecords(PredicateRecs); 15110fca6ea1SDimitry Andric 15120fca6ea1SDimitry Andric SmallString<128> PredicateCheck; 15130fca6ea1SDimitry Andric raw_svector_ostream OS(PredicateCheck); 15140fca6ea1SDimitry Andric ListSeparator LS(" && "); 15150fca6ea1SDimitry Andric for (Record *Pred : PredicateRecs) { 15160fca6ea1SDimitry Andric StringRef CondString = Pred->getValueAsString("CondString"); 15170fca6ea1SDimitry Andric if (CondString.empty()) 15180fca6ea1SDimitry Andric continue; 15190fca6ea1SDimitry Andric OS << LS << '(' << CondString << ')'; 15200fca6ea1SDimitry Andric } 15210fca6ea1SDimitry Andric 15220fca6ea1SDimitry Andric if (!HwModeFeatures.empty()) 15230fca6ea1SDimitry Andric OS << LS << HwModeFeatures; 15240fca6ea1SDimitry Andric 15250fca6ea1SDimitry Andric return std::string(PredicateCheck); 15260fca6ea1SDimitry Andric } 15270fca6ea1SDimitry Andric 15280fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 15290fca6ea1SDimitry Andric // SDTypeConstraint implementation 15300fca6ea1SDimitry Andric // 15310fca6ea1SDimitry Andric 15320fca6ea1SDimitry Andric SDTypeConstraint::SDTypeConstraint(Record *R, const CodeGenHwModes &CGH) { 15330fca6ea1SDimitry Andric OperandNo = R->getValueAsInt("OperandNum"); 15340fca6ea1SDimitry Andric 15350fca6ea1SDimitry Andric if (R->isSubClassOf("SDTCisVT")) { 15360fca6ea1SDimitry Andric ConstraintType = SDTCisVT; 15370fca6ea1SDimitry Andric VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH); 15380fca6ea1SDimitry Andric for (const auto &P : VVT) 15390fca6ea1SDimitry Andric if (P.second == MVT::isVoid) 15400fca6ea1SDimitry Andric PrintFatalError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT"); 15410fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisPtrTy")) { 15420fca6ea1SDimitry Andric ConstraintType = SDTCisPtrTy; 15430fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisInt")) { 15440fca6ea1SDimitry Andric ConstraintType = SDTCisInt; 15450fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisFP")) { 15460fca6ea1SDimitry Andric ConstraintType = SDTCisFP; 15470fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisVec")) { 15480fca6ea1SDimitry Andric ConstraintType = SDTCisVec; 15490fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisSameAs")) { 15500fca6ea1SDimitry Andric ConstraintType = SDTCisSameAs; 15510fca6ea1SDimitry Andric x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum"); 15520fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) { 15530fca6ea1SDimitry Andric ConstraintType = SDTCisVTSmallerThanOp; 15540fca6ea1SDimitry Andric x.SDTCisVTSmallerThanOp_Info.OtherOperandNum = 15550fca6ea1SDimitry Andric R->getValueAsInt("OtherOperandNum"); 15560fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) { 15570fca6ea1SDimitry Andric ConstraintType = SDTCisOpSmallerThanOp; 15580fca6ea1SDimitry Andric x.SDTCisOpSmallerThanOp_Info.BigOperandNum = 15590fca6ea1SDimitry Andric R->getValueAsInt("BigOperandNum"); 15600fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisEltOfVec")) { 15610fca6ea1SDimitry Andric ConstraintType = SDTCisEltOfVec; 15620fca6ea1SDimitry Andric x.SDTCisEltOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum"); 15630fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisSubVecOfVec")) { 15640fca6ea1SDimitry Andric ConstraintType = SDTCisSubVecOfVec; 15650fca6ea1SDimitry Andric x.SDTCisSubVecOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum"); 15660fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCVecEltisVT")) { 15670fca6ea1SDimitry Andric ConstraintType = SDTCVecEltisVT; 15680fca6ea1SDimitry Andric VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH); 15690fca6ea1SDimitry Andric for (const auto &P : VVT) { 15700fca6ea1SDimitry Andric MVT T = P.second; 15710fca6ea1SDimitry Andric if (T.isVector()) 15720fca6ea1SDimitry Andric PrintFatalError(R->getLoc(), 15730fca6ea1SDimitry Andric "Cannot use vector type as SDTCVecEltisVT"); 15740fca6ea1SDimitry Andric if (!T.isInteger() && !T.isFloatingPoint()) 15750fca6ea1SDimitry Andric PrintFatalError(R->getLoc(), "Must use integer or floating point type " 15760fca6ea1SDimitry Andric "as SDTCVecEltisVT"); 15770fca6ea1SDimitry Andric } 15780fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) { 15790fca6ea1SDimitry Andric ConstraintType = SDTCisSameNumEltsAs; 15800fca6ea1SDimitry Andric x.SDTCisSameNumEltsAs_Info.OtherOperandNum = 15810fca6ea1SDimitry Andric R->getValueAsInt("OtherOperandNum"); 15820fca6ea1SDimitry Andric } else if (R->isSubClassOf("SDTCisSameSizeAs")) { 15830fca6ea1SDimitry Andric ConstraintType = SDTCisSameSizeAs; 15840fca6ea1SDimitry Andric x.SDTCisSameSizeAs_Info.OtherOperandNum = 15850fca6ea1SDimitry Andric R->getValueAsInt("OtherOperandNum"); 15860fca6ea1SDimitry Andric } else { 15870fca6ea1SDimitry Andric PrintFatalError(R->getLoc(), 15880fca6ea1SDimitry Andric "Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); 15890fca6ea1SDimitry Andric } 15900fca6ea1SDimitry Andric } 15910fca6ea1SDimitry Andric 15920fca6ea1SDimitry Andric /// getOperandNum - Return the node corresponding to operand #OpNo in tree 15930fca6ea1SDimitry Andric /// N, and the result number in ResNo. 15940fca6ea1SDimitry Andric static TreePatternNode &getOperandNum(unsigned OpNo, TreePatternNode &N, 15950fca6ea1SDimitry Andric const SDNodeInfo &NodeInfo, 15960fca6ea1SDimitry Andric unsigned &ResNo) { 15970fca6ea1SDimitry Andric unsigned NumResults = NodeInfo.getNumResults(); 15980fca6ea1SDimitry Andric if (OpNo < NumResults) { 15990fca6ea1SDimitry Andric ResNo = OpNo; 16000fca6ea1SDimitry Andric return N; 16010fca6ea1SDimitry Andric } 16020fca6ea1SDimitry Andric 16030fca6ea1SDimitry Andric OpNo -= NumResults; 16040fca6ea1SDimitry Andric 16050fca6ea1SDimitry Andric if (OpNo >= N.getNumChildren()) { 16060fca6ea1SDimitry Andric std::string S; 16070fca6ea1SDimitry Andric raw_string_ostream OS(S); 16080fca6ea1SDimitry Andric OS << "Invalid operand number in type constraint " << (OpNo + NumResults) 16090fca6ea1SDimitry Andric << " "; 16100fca6ea1SDimitry Andric N.print(OS); 16110fca6ea1SDimitry Andric PrintFatalError(S); 16120fca6ea1SDimitry Andric } 16130fca6ea1SDimitry Andric 16140fca6ea1SDimitry Andric return N.getChild(OpNo); 16150fca6ea1SDimitry Andric } 16160fca6ea1SDimitry Andric 16170fca6ea1SDimitry Andric /// ApplyTypeConstraint - Given a node in a pattern, apply this type 16180fca6ea1SDimitry Andric /// constraint to the nodes operands. This returns true if it makes a 16190fca6ea1SDimitry Andric /// change, false otherwise. If a type contradiction is found, flag an error. 16200fca6ea1SDimitry Andric bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode &N, 16210fca6ea1SDimitry Andric const SDNodeInfo &NodeInfo, 16220fca6ea1SDimitry Andric TreePattern &TP) const { 16230fca6ea1SDimitry Andric if (TP.hasError()) 16240fca6ea1SDimitry Andric return false; 16250fca6ea1SDimitry Andric 16260fca6ea1SDimitry Andric unsigned ResNo = 0; // The result number being referenced. 16270fca6ea1SDimitry Andric TreePatternNode &NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); 16280fca6ea1SDimitry Andric TypeInfer &TI = TP.getInfer(); 16290fca6ea1SDimitry Andric 16300fca6ea1SDimitry Andric switch (ConstraintType) { 16310fca6ea1SDimitry Andric case SDTCisVT: 16320fca6ea1SDimitry Andric // Operand must be a particular type. 16330fca6ea1SDimitry Andric return NodeToApply.UpdateNodeType(ResNo, VVT, TP); 16340fca6ea1SDimitry Andric case SDTCisPtrTy: 16350fca6ea1SDimitry Andric // Operand must be same as target pointer type. 16360fca6ea1SDimitry Andric return NodeToApply.UpdateNodeType(ResNo, MVT::iPTR, TP); 16370fca6ea1SDimitry Andric case SDTCisInt: 16380fca6ea1SDimitry Andric // Require it to be one of the legal integer VTs. 16390fca6ea1SDimitry Andric return TI.EnforceInteger(NodeToApply.getExtType(ResNo)); 16400fca6ea1SDimitry Andric case SDTCisFP: 16410fca6ea1SDimitry Andric // Require it to be one of the legal fp VTs. 16420fca6ea1SDimitry Andric return TI.EnforceFloatingPoint(NodeToApply.getExtType(ResNo)); 16430fca6ea1SDimitry Andric case SDTCisVec: 16440fca6ea1SDimitry Andric // Require it to be one of the legal vector VTs. 16450fca6ea1SDimitry Andric return TI.EnforceVector(NodeToApply.getExtType(ResNo)); 16460fca6ea1SDimitry Andric case SDTCisSameAs: { 16470fca6ea1SDimitry Andric unsigned OResNo = 0; 16480fca6ea1SDimitry Andric TreePatternNode &OtherNode = 16490fca6ea1SDimitry Andric getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo); 16500fca6ea1SDimitry Andric return (int)NodeToApply.UpdateNodeType(ResNo, OtherNode.getExtType(OResNo), 16510fca6ea1SDimitry Andric TP) | 16520fca6ea1SDimitry Andric (int)OtherNode.UpdateNodeType(OResNo, NodeToApply.getExtType(ResNo), 16530fca6ea1SDimitry Andric TP); 16540fca6ea1SDimitry Andric } 16550fca6ea1SDimitry Andric case SDTCisVTSmallerThanOp: { 16560fca6ea1SDimitry Andric // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must 16570fca6ea1SDimitry Andric // have an integer type that is smaller than the VT. 16580fca6ea1SDimitry Andric if (!NodeToApply.isLeaf() || !isa<DefInit>(NodeToApply.getLeafValue()) || 16590fca6ea1SDimitry Andric !cast<DefInit>(NodeToApply.getLeafValue()) 16600fca6ea1SDimitry Andric ->getDef() 16610fca6ea1SDimitry Andric ->isSubClassOf("ValueType")) { 16620fca6ea1SDimitry Andric TP.error(N.getOperator()->getName() + " expects a VT operand!"); 16630fca6ea1SDimitry Andric return false; 16640fca6ea1SDimitry Andric } 16650fca6ea1SDimitry Andric DefInit *DI = cast<DefInit>(NodeToApply.getLeafValue()); 16660fca6ea1SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 16670fca6ea1SDimitry Andric auto VVT = getValueTypeByHwMode(DI->getDef(), T.getHwModes()); 16680fca6ea1SDimitry Andric TypeSetByHwMode TypeListTmp(VVT); 16690fca6ea1SDimitry Andric 16700fca6ea1SDimitry Andric unsigned OResNo = 0; 16710fca6ea1SDimitry Andric TreePatternNode &OtherNode = getOperandNum( 16720fca6ea1SDimitry Andric x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo, OResNo); 16730fca6ea1SDimitry Andric 16740fca6ea1SDimitry Andric return TI.EnforceSmallerThan(TypeListTmp, OtherNode.getExtType(OResNo), 16750fca6ea1SDimitry Andric /*SmallIsVT*/ true); 16760fca6ea1SDimitry Andric } 16770fca6ea1SDimitry Andric case SDTCisOpSmallerThanOp: { 16780fca6ea1SDimitry Andric unsigned BResNo = 0; 16790fca6ea1SDimitry Andric TreePatternNode &BigOperand = getOperandNum( 16800fca6ea1SDimitry Andric x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NodeInfo, BResNo); 16810fca6ea1SDimitry Andric return TI.EnforceSmallerThan(NodeToApply.getExtType(ResNo), 16820fca6ea1SDimitry Andric BigOperand.getExtType(BResNo)); 16830fca6ea1SDimitry Andric } 16840fca6ea1SDimitry Andric case SDTCisEltOfVec: { 16850fca6ea1SDimitry Andric unsigned VResNo = 0; 16860fca6ea1SDimitry Andric TreePatternNode &VecOperand = getOperandNum( 16870fca6ea1SDimitry Andric x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo, VResNo); 16880fca6ea1SDimitry Andric // Filter vector types out of VecOperand that don't have the right element 16890fca6ea1SDimitry Andric // type. 16900fca6ea1SDimitry Andric return TI.EnforceVectorEltTypeIs(VecOperand.getExtType(VResNo), 16910fca6ea1SDimitry Andric NodeToApply.getExtType(ResNo)); 16920fca6ea1SDimitry Andric } 16930fca6ea1SDimitry Andric case SDTCisSubVecOfVec: { 16940fca6ea1SDimitry Andric unsigned VResNo = 0; 16950fca6ea1SDimitry Andric TreePatternNode &BigVecOperand = getOperandNum( 16960fca6ea1SDimitry Andric x.SDTCisSubVecOfVec_Info.OtherOperandNum, N, NodeInfo, VResNo); 16970fca6ea1SDimitry Andric 16980fca6ea1SDimitry Andric // Filter vector types out of BigVecOperand that don't have the 16990fca6ea1SDimitry Andric // right subvector type. 17000fca6ea1SDimitry Andric return TI.EnforceVectorSubVectorTypeIs(BigVecOperand.getExtType(VResNo), 17010fca6ea1SDimitry Andric NodeToApply.getExtType(ResNo)); 17020fca6ea1SDimitry Andric } 17030fca6ea1SDimitry Andric case SDTCVecEltisVT: { 17040fca6ea1SDimitry Andric return TI.EnforceVectorEltTypeIs(NodeToApply.getExtType(ResNo), VVT); 17050fca6ea1SDimitry Andric } 17060fca6ea1SDimitry Andric case SDTCisSameNumEltsAs: { 17070fca6ea1SDimitry Andric unsigned OResNo = 0; 17080fca6ea1SDimitry Andric TreePatternNode &OtherNode = getOperandNum( 17090fca6ea1SDimitry Andric x.SDTCisSameNumEltsAs_Info.OtherOperandNum, N, NodeInfo, OResNo); 17100fca6ea1SDimitry Andric return TI.EnforceSameNumElts(OtherNode.getExtType(OResNo), 17110fca6ea1SDimitry Andric NodeToApply.getExtType(ResNo)); 17120fca6ea1SDimitry Andric } 17130fca6ea1SDimitry Andric case SDTCisSameSizeAs: { 17140fca6ea1SDimitry Andric unsigned OResNo = 0; 17150fca6ea1SDimitry Andric TreePatternNode &OtherNode = getOperandNum( 17160fca6ea1SDimitry Andric x.SDTCisSameSizeAs_Info.OtherOperandNum, N, NodeInfo, OResNo); 17170fca6ea1SDimitry Andric return TI.EnforceSameSize(OtherNode.getExtType(OResNo), 17180fca6ea1SDimitry Andric NodeToApply.getExtType(ResNo)); 17190fca6ea1SDimitry Andric } 17200fca6ea1SDimitry Andric } 17210fca6ea1SDimitry Andric llvm_unreachable("Invalid ConstraintType!"); 17220fca6ea1SDimitry Andric } 17230fca6ea1SDimitry Andric 17240fca6ea1SDimitry Andric // Update the node type to match an instruction operand or result as specified 17250fca6ea1SDimitry Andric // in the ins or outs lists on the instruction definition. Return true if the 17260fca6ea1SDimitry Andric // type was actually changed. 17270fca6ea1SDimitry Andric bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo, Record *Operand, 17280fca6ea1SDimitry Andric TreePattern &TP) { 17290fca6ea1SDimitry Andric // The 'unknown' operand indicates that types should be inferred from the 17300fca6ea1SDimitry Andric // context. 17310fca6ea1SDimitry Andric if (Operand->isSubClassOf("unknown_class")) 17320fca6ea1SDimitry Andric return false; 17330fca6ea1SDimitry Andric 17340fca6ea1SDimitry Andric // The Operand class specifies a type directly. 17350fca6ea1SDimitry Andric if (Operand->isSubClassOf("Operand")) { 17360fca6ea1SDimitry Andric Record *R = Operand->getValueAsDef("Type"); 17370fca6ea1SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 17380fca6ea1SDimitry Andric return UpdateNodeType(ResNo, getValueTypeByHwMode(R, T.getHwModes()), TP); 17390fca6ea1SDimitry Andric } 17400fca6ea1SDimitry Andric 17410fca6ea1SDimitry Andric // PointerLikeRegClass has a type that is determined at runtime. 17420fca6ea1SDimitry Andric if (Operand->isSubClassOf("PointerLikeRegClass")) 17430fca6ea1SDimitry Andric return UpdateNodeType(ResNo, MVT::iPTR, TP); 17440fca6ea1SDimitry Andric 17450fca6ea1SDimitry Andric // Both RegisterClass and RegisterOperand operands derive their types from a 17460fca6ea1SDimitry Andric // register class def. 17470fca6ea1SDimitry Andric Record *RC = nullptr; 17480fca6ea1SDimitry Andric if (Operand->isSubClassOf("RegisterClass")) 17490fca6ea1SDimitry Andric RC = Operand; 17500fca6ea1SDimitry Andric else if (Operand->isSubClassOf("RegisterOperand")) 17510fca6ea1SDimitry Andric RC = Operand->getValueAsDef("RegClass"); 17520fca6ea1SDimitry Andric 17530fca6ea1SDimitry Andric assert(RC && "Unknown operand type"); 17540fca6ea1SDimitry Andric CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo(); 17550fca6ea1SDimitry Andric return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP); 17560fca6ea1SDimitry Andric } 17570fca6ea1SDimitry Andric 17580fca6ea1SDimitry Andric bool TreePatternNode::ContainsUnresolvedType(TreePattern &TP) const { 17590fca6ea1SDimitry Andric for (unsigned i = 0, e = Types.size(); i != e; ++i) 17600fca6ea1SDimitry Andric if (!TP.getInfer().isConcrete(Types[i], true)) 17610fca6ea1SDimitry Andric return true; 17620fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 17630fca6ea1SDimitry Andric if (getChild(i).ContainsUnresolvedType(TP)) 17640fca6ea1SDimitry Andric return true; 17650fca6ea1SDimitry Andric return false; 17660fca6ea1SDimitry Andric } 17670fca6ea1SDimitry Andric 17680fca6ea1SDimitry Andric bool TreePatternNode::hasProperTypeByHwMode() const { 17690fca6ea1SDimitry Andric for (const TypeSetByHwMode &S : Types) 17700fca6ea1SDimitry Andric if (!S.isSimple()) 17710fca6ea1SDimitry Andric return true; 17720fca6ea1SDimitry Andric for (const TreePatternNodePtr &C : Children) 17730fca6ea1SDimitry Andric if (C->hasProperTypeByHwMode()) 17740fca6ea1SDimitry Andric return true; 17750fca6ea1SDimitry Andric return false; 17760fca6ea1SDimitry Andric } 17770fca6ea1SDimitry Andric 17780fca6ea1SDimitry Andric bool TreePatternNode::hasPossibleType() const { 17790fca6ea1SDimitry Andric for (const TypeSetByHwMode &S : Types) 17800fca6ea1SDimitry Andric if (!S.isPossible()) 17810fca6ea1SDimitry Andric return false; 17820fca6ea1SDimitry Andric for (const TreePatternNodePtr &C : Children) 17830fca6ea1SDimitry Andric if (!C->hasPossibleType()) 17840fca6ea1SDimitry Andric return false; 17850fca6ea1SDimitry Andric return true; 17860fca6ea1SDimitry Andric } 17870fca6ea1SDimitry Andric 17880fca6ea1SDimitry Andric bool TreePatternNode::setDefaultMode(unsigned Mode) { 17890fca6ea1SDimitry Andric for (TypeSetByHwMode &S : Types) { 17900fca6ea1SDimitry Andric S.makeSimple(Mode); 17910fca6ea1SDimitry Andric // Check if the selected mode had a type conflict. 17920fca6ea1SDimitry Andric if (S.get(DefaultMode).empty()) 17930fca6ea1SDimitry Andric return false; 17940fca6ea1SDimitry Andric } 17950fca6ea1SDimitry Andric for (const TreePatternNodePtr &C : Children) 17960fca6ea1SDimitry Andric if (!C->setDefaultMode(Mode)) 17970fca6ea1SDimitry Andric return false; 17980fca6ea1SDimitry Andric return true; 17990fca6ea1SDimitry Andric } 18000fca6ea1SDimitry Andric 18010fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 18020fca6ea1SDimitry Andric // SDNodeInfo implementation 18030fca6ea1SDimitry Andric // 18040fca6ea1SDimitry Andric SDNodeInfo::SDNodeInfo(Record *R, const CodeGenHwModes &CGH) : Def(R) { 18050fca6ea1SDimitry Andric EnumName = R->getValueAsString("Opcode"); 18060fca6ea1SDimitry Andric SDClassName = R->getValueAsString("SDClass"); 18070fca6ea1SDimitry Andric Record *TypeProfile = R->getValueAsDef("TypeProfile"); 18080fca6ea1SDimitry Andric NumResults = TypeProfile->getValueAsInt("NumResults"); 18090fca6ea1SDimitry Andric NumOperands = TypeProfile->getValueAsInt("NumOperands"); 18100fca6ea1SDimitry Andric 18110fca6ea1SDimitry Andric // Parse the properties. 18120fca6ea1SDimitry Andric Properties = parseSDPatternOperatorProperties(R); 18130fca6ea1SDimitry Andric 18140fca6ea1SDimitry Andric // Parse the type constraints. 18150fca6ea1SDimitry Andric std::vector<Record *> ConstraintList = 18160fca6ea1SDimitry Andric TypeProfile->getValueAsListOfDefs("Constraints"); 18170fca6ea1SDimitry Andric for (Record *R : ConstraintList) 18180fca6ea1SDimitry Andric TypeConstraints.emplace_back(R, CGH); 18190fca6ea1SDimitry Andric } 18200fca6ea1SDimitry Andric 18210fca6ea1SDimitry Andric /// getKnownType - If the type constraints on this node imply a fixed type 18220fca6ea1SDimitry Andric /// (e.g. all stores return void, etc), then return it as an 18230fca6ea1SDimitry Andric /// MVT::SimpleValueType. Otherwise, return EEVT::Other. 18240fca6ea1SDimitry Andric MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const { 18250fca6ea1SDimitry Andric unsigned NumResults = getNumResults(); 18260fca6ea1SDimitry Andric assert(NumResults <= 1 && 18270fca6ea1SDimitry Andric "We only work with nodes with zero or one result so far!"); 18280fca6ea1SDimitry Andric assert(ResNo == 0 && "Only handles single result nodes so far"); 18290fca6ea1SDimitry Andric 18300fca6ea1SDimitry Andric for (const SDTypeConstraint &Constraint : TypeConstraints) { 18310fca6ea1SDimitry Andric // Make sure that this applies to the correct node result. 18320fca6ea1SDimitry Andric if (Constraint.OperandNo >= NumResults) // FIXME: need value # 18330fca6ea1SDimitry Andric continue; 18340fca6ea1SDimitry Andric 18350fca6ea1SDimitry Andric switch (Constraint.ConstraintType) { 18360fca6ea1SDimitry Andric default: 18370fca6ea1SDimitry Andric break; 18380fca6ea1SDimitry Andric case SDTypeConstraint::SDTCisVT: 18390fca6ea1SDimitry Andric if (Constraint.VVT.isSimple()) 18400fca6ea1SDimitry Andric return Constraint.VVT.getSimple().SimpleTy; 18410fca6ea1SDimitry Andric break; 18420fca6ea1SDimitry Andric case SDTypeConstraint::SDTCisPtrTy: 18430fca6ea1SDimitry Andric return MVT::iPTR; 18440fca6ea1SDimitry Andric } 18450fca6ea1SDimitry Andric } 18460fca6ea1SDimitry Andric return MVT::Other; 18470fca6ea1SDimitry Andric } 18480fca6ea1SDimitry Andric 18490fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 18500fca6ea1SDimitry Andric // TreePatternNode implementation 18510fca6ea1SDimitry Andric // 18520fca6ea1SDimitry Andric 18530fca6ea1SDimitry Andric static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { 18540fca6ea1SDimitry Andric if (Operator->getName() == "set" || Operator->getName() == "implicit") 18550fca6ea1SDimitry Andric return 0; // All return nothing. 18560fca6ea1SDimitry Andric 18570fca6ea1SDimitry Andric if (Operator->isSubClassOf("Intrinsic")) 18580fca6ea1SDimitry Andric return CDP.getIntrinsic(Operator).IS.RetTys.size(); 18590fca6ea1SDimitry Andric 18600fca6ea1SDimitry Andric if (Operator->isSubClassOf("SDNode")) 18610fca6ea1SDimitry Andric return CDP.getSDNodeInfo(Operator).getNumResults(); 18620fca6ea1SDimitry Andric 18630fca6ea1SDimitry Andric if (Operator->isSubClassOf("PatFrags")) { 18640fca6ea1SDimitry Andric // If we've already parsed this pattern fragment, get it. Otherwise, handle 18650fca6ea1SDimitry Andric // the forward reference case where one pattern fragment references another 18660fca6ea1SDimitry Andric // before it is processed. 18670fca6ea1SDimitry Andric if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator)) { 18680fca6ea1SDimitry Andric // The number of results of a fragment with alternative records is the 18690fca6ea1SDimitry Andric // maximum number of results across all alternatives. 18700fca6ea1SDimitry Andric unsigned NumResults = 0; 18710fca6ea1SDimitry Andric for (const auto &T : PFRec->getTrees()) 18720fca6ea1SDimitry Andric NumResults = std::max(NumResults, T->getNumTypes()); 18730fca6ea1SDimitry Andric return NumResults; 18740fca6ea1SDimitry Andric } 18750fca6ea1SDimitry Andric 18760fca6ea1SDimitry Andric ListInit *LI = Operator->getValueAsListInit("Fragments"); 18770fca6ea1SDimitry Andric assert(LI && "Invalid Fragment"); 18780fca6ea1SDimitry Andric unsigned NumResults = 0; 18790fca6ea1SDimitry Andric for (Init *I : LI->getValues()) { 18800fca6ea1SDimitry Andric Record *Op = nullptr; 18810fca6ea1SDimitry Andric if (DagInit *Dag = dyn_cast<DagInit>(I)) 18820fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(Dag->getOperator())) 18830fca6ea1SDimitry Andric Op = DI->getDef(); 18840fca6ea1SDimitry Andric assert(Op && "Invalid Fragment"); 18850fca6ea1SDimitry Andric NumResults = std::max(NumResults, GetNumNodeResults(Op, CDP)); 18860fca6ea1SDimitry Andric } 18870fca6ea1SDimitry Andric return NumResults; 18880fca6ea1SDimitry Andric } 18890fca6ea1SDimitry Andric 18900fca6ea1SDimitry Andric if (Operator->isSubClassOf("Instruction")) { 18910fca6ea1SDimitry Andric CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); 18920fca6ea1SDimitry Andric 18930fca6ea1SDimitry Andric unsigned NumDefsToAdd = InstInfo.Operands.NumDefs; 18940fca6ea1SDimitry Andric 18950fca6ea1SDimitry Andric // Subtract any defaulted outputs. 18960fca6ea1SDimitry Andric for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) { 18970fca6ea1SDimitry Andric Record *OperandNode = InstInfo.Operands[i].Rec; 18980fca6ea1SDimitry Andric 18990fca6ea1SDimitry Andric if (OperandNode->isSubClassOf("OperandWithDefaultOps") && 19000fca6ea1SDimitry Andric !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) 19010fca6ea1SDimitry Andric --NumDefsToAdd; 19020fca6ea1SDimitry Andric } 19030fca6ea1SDimitry Andric 19040fca6ea1SDimitry Andric // Add on one implicit def if it has a resolvable type. 19050fca6ea1SDimitry Andric if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) != 19060fca6ea1SDimitry Andric MVT::Other) 19070fca6ea1SDimitry Andric ++NumDefsToAdd; 19080fca6ea1SDimitry Andric return NumDefsToAdd; 19090fca6ea1SDimitry Andric } 19100fca6ea1SDimitry Andric 19110fca6ea1SDimitry Andric if (Operator->isSubClassOf("SDNodeXForm")) 19120fca6ea1SDimitry Andric return 1; // FIXME: Generalize SDNodeXForm 19130fca6ea1SDimitry Andric 19140fca6ea1SDimitry Andric if (Operator->isSubClassOf("ValueType")) 19150fca6ea1SDimitry Andric return 1; // A type-cast of one result. 19160fca6ea1SDimitry Andric 19170fca6ea1SDimitry Andric if (Operator->isSubClassOf("ComplexPattern")) 19180fca6ea1SDimitry Andric return 1; 19190fca6ea1SDimitry Andric 19200fca6ea1SDimitry Andric errs() << *Operator; 19210fca6ea1SDimitry Andric PrintFatalError("Unhandled node in GetNumNodeResults"); 19220fca6ea1SDimitry Andric } 19230fca6ea1SDimitry Andric 19240fca6ea1SDimitry Andric void TreePatternNode::print(raw_ostream &OS) const { 19250fca6ea1SDimitry Andric if (isLeaf()) 19260fca6ea1SDimitry Andric OS << *getLeafValue(); 19270fca6ea1SDimitry Andric else 19280fca6ea1SDimitry Andric OS << '(' << getOperator()->getName(); 19290fca6ea1SDimitry Andric 19300fca6ea1SDimitry Andric for (unsigned i = 0, e = Types.size(); i != e; ++i) { 19310fca6ea1SDimitry Andric OS << ':'; 19320fca6ea1SDimitry Andric getExtType(i).writeToStream(OS); 19330fca6ea1SDimitry Andric } 19340fca6ea1SDimitry Andric 19350fca6ea1SDimitry Andric if (!isLeaf()) { 19360fca6ea1SDimitry Andric if (getNumChildren() != 0) { 19370fca6ea1SDimitry Andric OS << " "; 19380fca6ea1SDimitry Andric ListSeparator LS; 19390fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { 19400fca6ea1SDimitry Andric OS << LS; 19410fca6ea1SDimitry Andric getChild(i).print(OS); 19420fca6ea1SDimitry Andric } 19430fca6ea1SDimitry Andric } 19440fca6ea1SDimitry Andric OS << ")"; 19450fca6ea1SDimitry Andric } 19460fca6ea1SDimitry Andric 19470fca6ea1SDimitry Andric for (const TreePredicateCall &Pred : PredicateCalls) { 19480fca6ea1SDimitry Andric OS << "<<P:"; 19490fca6ea1SDimitry Andric if (Pred.Scope) 19500fca6ea1SDimitry Andric OS << Pred.Scope << ":"; 19510fca6ea1SDimitry Andric OS << Pred.Fn.getFnName() << ">>"; 19520fca6ea1SDimitry Andric } 19530fca6ea1SDimitry Andric if (TransformFn) 19540fca6ea1SDimitry Andric OS << "<<X:" << TransformFn->getName() << ">>"; 19550fca6ea1SDimitry Andric if (!getName().empty()) 19560fca6ea1SDimitry Andric OS << ":$" << getName(); 19570fca6ea1SDimitry Andric 19580fca6ea1SDimitry Andric for (const ScopedName &Name : NamesAsPredicateArg) 19590fca6ea1SDimitry Andric OS << ":$pred:" << Name.getScope() << ":" << Name.getIdentifier(); 19600fca6ea1SDimitry Andric } 19610fca6ea1SDimitry Andric void TreePatternNode::dump() const { print(errs()); } 19620fca6ea1SDimitry Andric 19630fca6ea1SDimitry Andric /// isIsomorphicTo - Return true if this node is recursively 19640fca6ea1SDimitry Andric /// isomorphic to the specified node. For this comparison, the node's 19650fca6ea1SDimitry Andric /// entire state is considered. The assigned name is ignored, since 19660fca6ea1SDimitry Andric /// nodes with differing names are considered isomorphic. However, if 19670fca6ea1SDimitry Andric /// the assigned name is present in the dependent variable set, then 19680fca6ea1SDimitry Andric /// the assigned name is considered significant and the node is 19690fca6ea1SDimitry Andric /// isomorphic if the names match. 19700fca6ea1SDimitry Andric bool TreePatternNode::isIsomorphicTo(const TreePatternNode &N, 19710fca6ea1SDimitry Andric const MultipleUseVarSet &DepVars) const { 19720fca6ea1SDimitry Andric if (&N == this) 19730fca6ea1SDimitry Andric return true; 19740fca6ea1SDimitry Andric if (N.isLeaf() != isLeaf()) 19750fca6ea1SDimitry Andric return false; 19760fca6ea1SDimitry Andric 19770fca6ea1SDimitry Andric // Check operator of non-leaves early since it can be cheaper than checking 19780fca6ea1SDimitry Andric // types. 19790fca6ea1SDimitry Andric if (!isLeaf()) 19800fca6ea1SDimitry Andric if (N.getOperator() != getOperator() || 19810fca6ea1SDimitry Andric N.getNumChildren() != getNumChildren()) 19820fca6ea1SDimitry Andric return false; 19830fca6ea1SDimitry Andric 19840fca6ea1SDimitry Andric if (getExtTypes() != N.getExtTypes() || 19850fca6ea1SDimitry Andric getPredicateCalls() != N.getPredicateCalls() || 19860fca6ea1SDimitry Andric getTransformFn() != N.getTransformFn()) 19870fca6ea1SDimitry Andric return false; 19880fca6ea1SDimitry Andric 19890fca6ea1SDimitry Andric if (isLeaf()) { 19900fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) { 19910fca6ea1SDimitry Andric if (DefInit *NDI = dyn_cast<DefInit>(N.getLeafValue())) { 19920fca6ea1SDimitry Andric return ((DI->getDef() == NDI->getDef()) && 19930fca6ea1SDimitry Andric (!DepVars.contains(getName()) || getName() == N.getName())); 19940fca6ea1SDimitry Andric } 19950fca6ea1SDimitry Andric } 19960fca6ea1SDimitry Andric return getLeafValue() == N.getLeafValue(); 19970fca6ea1SDimitry Andric } 19980fca6ea1SDimitry Andric 19990fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 20000fca6ea1SDimitry Andric if (!getChild(i).isIsomorphicTo(N.getChild(i), DepVars)) 20010fca6ea1SDimitry Andric return false; 20020fca6ea1SDimitry Andric return true; 20030fca6ea1SDimitry Andric } 20040fca6ea1SDimitry Andric 20050fca6ea1SDimitry Andric /// clone - Make a copy of this tree and all of its children. 20060fca6ea1SDimitry Andric /// 20070fca6ea1SDimitry Andric TreePatternNodePtr TreePatternNode::clone() const { 20080fca6ea1SDimitry Andric TreePatternNodePtr New; 20090fca6ea1SDimitry Andric if (isLeaf()) { 20100fca6ea1SDimitry Andric New = makeIntrusiveRefCnt<TreePatternNode>(getLeafValue(), getNumTypes()); 20110fca6ea1SDimitry Andric } else { 20120fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> CChildren; 20130fca6ea1SDimitry Andric CChildren.reserve(Children.size()); 20140fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 20150fca6ea1SDimitry Andric CChildren.push_back(getChild(i).clone()); 20160fca6ea1SDimitry Andric New = makeIntrusiveRefCnt<TreePatternNode>( 20170fca6ea1SDimitry Andric getOperator(), std::move(CChildren), getNumTypes()); 20180fca6ea1SDimitry Andric } 20190fca6ea1SDimitry Andric New->setName(getName()); 20200fca6ea1SDimitry Andric New->setNamesAsPredicateArg(getNamesAsPredicateArg()); 20210fca6ea1SDimitry Andric New->Types = Types; 20220fca6ea1SDimitry Andric New->setPredicateCalls(getPredicateCalls()); 20230fca6ea1SDimitry Andric New->setGISelFlagsRecord(getGISelFlagsRecord()); 20240fca6ea1SDimitry Andric New->setTransformFn(getTransformFn()); 20250fca6ea1SDimitry Andric return New; 20260fca6ea1SDimitry Andric } 20270fca6ea1SDimitry Andric 20280fca6ea1SDimitry Andric /// RemoveAllTypes - Recursively strip all the types of this tree. 20290fca6ea1SDimitry Andric void TreePatternNode::RemoveAllTypes() { 20300fca6ea1SDimitry Andric // Reset to unknown type. 20310fca6ea1SDimitry Andric std::fill(Types.begin(), Types.end(), TypeSetByHwMode()); 20320fca6ea1SDimitry Andric if (isLeaf()) 20330fca6ea1SDimitry Andric return; 20340fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 20350fca6ea1SDimitry Andric getChild(i).RemoveAllTypes(); 20360fca6ea1SDimitry Andric } 20370fca6ea1SDimitry Andric 20380fca6ea1SDimitry Andric /// SubstituteFormalArguments - Replace the formal arguments in this tree 20390fca6ea1SDimitry Andric /// with actual values specified by ArgMap. 20400fca6ea1SDimitry Andric void TreePatternNode::SubstituteFormalArguments( 20410fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> &ArgMap) { 20420fca6ea1SDimitry Andric if (isLeaf()) 20430fca6ea1SDimitry Andric return; 20440fca6ea1SDimitry Andric 20450fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { 20460fca6ea1SDimitry Andric TreePatternNode &Child = getChild(i); 20470fca6ea1SDimitry Andric if (Child.isLeaf()) { 20480fca6ea1SDimitry Andric Init *Val = Child.getLeafValue(); 20490fca6ea1SDimitry Andric // Note that, when substituting into an output pattern, Val might be an 20500fca6ea1SDimitry Andric // UnsetInit. 20510fca6ea1SDimitry Andric if (isa<UnsetInit>(Val) || 20520fca6ea1SDimitry Andric (isa<DefInit>(Val) && 20530fca6ea1SDimitry Andric cast<DefInit>(Val)->getDef()->getName() == "node")) { 20540fca6ea1SDimitry Andric // We found a use of a formal argument, replace it with its value. 20550fca6ea1SDimitry Andric TreePatternNodePtr NewChild = ArgMap[Child.getName()]; 20560fca6ea1SDimitry Andric assert(NewChild && "Couldn't find formal argument!"); 20570fca6ea1SDimitry Andric assert((Child.getPredicateCalls().empty() || 20580fca6ea1SDimitry Andric NewChild->getPredicateCalls() == Child.getPredicateCalls()) && 20590fca6ea1SDimitry Andric "Non-empty child predicate clobbered!"); 20600fca6ea1SDimitry Andric setChild(i, std::move(NewChild)); 20610fca6ea1SDimitry Andric } 20620fca6ea1SDimitry Andric } else { 20630fca6ea1SDimitry Andric getChild(i).SubstituteFormalArguments(ArgMap); 20640fca6ea1SDimitry Andric } 20650fca6ea1SDimitry Andric } 20660fca6ea1SDimitry Andric } 20670fca6ea1SDimitry Andric 20680fca6ea1SDimitry Andric /// InlinePatternFragments - If this pattern refers to any pattern 20690fca6ea1SDimitry Andric /// fragments, return the set of inlined versions (this can be more than 20700fca6ea1SDimitry Andric /// one if a PatFrags record has multiple alternatives). 20710fca6ea1SDimitry Andric void TreePatternNode::InlinePatternFragments( 20720fca6ea1SDimitry Andric TreePattern &TP, std::vector<TreePatternNodePtr> &OutAlternatives) { 20730fca6ea1SDimitry Andric 20740fca6ea1SDimitry Andric if (TP.hasError()) 20750fca6ea1SDimitry Andric return; 20760fca6ea1SDimitry Andric 20770fca6ea1SDimitry Andric if (isLeaf()) { 20780fca6ea1SDimitry Andric OutAlternatives.push_back(this); // nothing to do. 20790fca6ea1SDimitry Andric return; 20800fca6ea1SDimitry Andric } 20810fca6ea1SDimitry Andric 20820fca6ea1SDimitry Andric Record *Op = getOperator(); 20830fca6ea1SDimitry Andric 20840fca6ea1SDimitry Andric if (!Op->isSubClassOf("PatFrags")) { 20850fca6ea1SDimitry Andric if (getNumChildren() == 0) { 20860fca6ea1SDimitry Andric OutAlternatives.push_back(this); 20870fca6ea1SDimitry Andric return; 20880fca6ea1SDimitry Andric } 20890fca6ea1SDimitry Andric 20900fca6ea1SDimitry Andric // Recursively inline children nodes. 20910fca6ea1SDimitry Andric std::vector<std::vector<TreePatternNodePtr>> ChildAlternatives( 20920fca6ea1SDimitry Andric getNumChildren()); 20930fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { 20940fca6ea1SDimitry Andric TreePatternNodePtr Child = getChildShared(i); 20950fca6ea1SDimitry Andric Child->InlinePatternFragments(TP, ChildAlternatives[i]); 20960fca6ea1SDimitry Andric // If there are no alternatives for any child, there are no 20970fca6ea1SDimitry Andric // alternatives for this expression as whole. 20980fca6ea1SDimitry Andric if (ChildAlternatives[i].empty()) 20990fca6ea1SDimitry Andric return; 21000fca6ea1SDimitry Andric 21010fca6ea1SDimitry Andric assert((Child->getPredicateCalls().empty() || 21020fca6ea1SDimitry Andric llvm::all_of(ChildAlternatives[i], 21030fca6ea1SDimitry Andric [&](const TreePatternNodePtr &NewChild) { 21040fca6ea1SDimitry Andric return NewChild->getPredicateCalls() == 21050fca6ea1SDimitry Andric Child->getPredicateCalls(); 21060fca6ea1SDimitry Andric })) && 21070fca6ea1SDimitry Andric "Non-empty child predicate clobbered!"); 21080fca6ea1SDimitry Andric } 21090fca6ea1SDimitry Andric 21100fca6ea1SDimitry Andric // The end result is an all-pairs construction of the resultant pattern. 21110fca6ea1SDimitry Andric std::vector<unsigned> Idxs(ChildAlternatives.size()); 21120fca6ea1SDimitry Andric bool NotDone; 21130fca6ea1SDimitry Andric do { 21140fca6ea1SDimitry Andric // Create the variant and add it to the output list. 21150fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> NewChildren; 21160fca6ea1SDimitry Andric NewChildren.reserve(ChildAlternatives.size()); 21170fca6ea1SDimitry Andric for (unsigned i = 0, e = ChildAlternatives.size(); i != e; ++i) 21180fca6ea1SDimitry Andric NewChildren.push_back(ChildAlternatives[i][Idxs[i]]); 21190fca6ea1SDimitry Andric TreePatternNodePtr R = makeIntrusiveRefCnt<TreePatternNode>( 21200fca6ea1SDimitry Andric getOperator(), std::move(NewChildren), getNumTypes()); 21210fca6ea1SDimitry Andric 21220fca6ea1SDimitry Andric // Copy over properties. 21230fca6ea1SDimitry Andric R->setName(getName()); 21240fca6ea1SDimitry Andric R->setNamesAsPredicateArg(getNamesAsPredicateArg()); 21250fca6ea1SDimitry Andric R->setPredicateCalls(getPredicateCalls()); 21260fca6ea1SDimitry Andric R->setGISelFlagsRecord(getGISelFlagsRecord()); 21270fca6ea1SDimitry Andric R->setTransformFn(getTransformFn()); 21280fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumTypes(); i != e; ++i) 21290fca6ea1SDimitry Andric R->setType(i, getExtType(i)); 21300fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumResults(); i != e; ++i) 21310fca6ea1SDimitry Andric R->setResultIndex(i, getResultIndex(i)); 21320fca6ea1SDimitry Andric 21330fca6ea1SDimitry Andric // Register alternative. 21340fca6ea1SDimitry Andric OutAlternatives.push_back(R); 21350fca6ea1SDimitry Andric 21360fca6ea1SDimitry Andric // Increment indices to the next permutation by incrementing the 21370fca6ea1SDimitry Andric // indices from last index backward, e.g., generate the sequence 21380fca6ea1SDimitry Andric // [0, 0], [0, 1], [1, 0], [1, 1]. 21390fca6ea1SDimitry Andric int IdxsIdx; 21400fca6ea1SDimitry Andric for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) { 21410fca6ea1SDimitry Andric if (++Idxs[IdxsIdx] == ChildAlternatives[IdxsIdx].size()) 21420fca6ea1SDimitry Andric Idxs[IdxsIdx] = 0; 21430fca6ea1SDimitry Andric else 21440fca6ea1SDimitry Andric break; 21450fca6ea1SDimitry Andric } 21460fca6ea1SDimitry Andric NotDone = (IdxsIdx >= 0); 21470fca6ea1SDimitry Andric } while (NotDone); 21480fca6ea1SDimitry Andric 21490fca6ea1SDimitry Andric return; 21500fca6ea1SDimitry Andric } 21510fca6ea1SDimitry Andric 21520fca6ea1SDimitry Andric // Otherwise, we found a reference to a fragment. First, look up its 21530fca6ea1SDimitry Andric // TreePattern record. 21540fca6ea1SDimitry Andric TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op); 21550fca6ea1SDimitry Andric 21560fca6ea1SDimitry Andric // Verify that we are passing the right number of operands. 21570fca6ea1SDimitry Andric if (Frag->getNumArgs() != getNumChildren()) { 21580fca6ea1SDimitry Andric TP.error("'" + Op->getName() + "' fragment requires " + 21590fca6ea1SDimitry Andric Twine(Frag->getNumArgs()) + " operands!"); 21600fca6ea1SDimitry Andric return; 21610fca6ea1SDimitry Andric } 21620fca6ea1SDimitry Andric 21630fca6ea1SDimitry Andric TreePredicateFn PredFn(Frag); 21640fca6ea1SDimitry Andric unsigned Scope = 0; 21650fca6ea1SDimitry Andric if (TreePredicateFn(Frag).usesOperands()) 21660fca6ea1SDimitry Andric Scope = TP.getDAGPatterns().allocateScope(); 21670fca6ea1SDimitry Andric 21680fca6ea1SDimitry Andric // Compute the map of formal to actual arguments. 21690fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> ArgMap; 21700fca6ea1SDimitry Andric for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) { 21710fca6ea1SDimitry Andric TreePatternNodePtr Child = getChildShared(i); 21720fca6ea1SDimitry Andric if (Scope != 0) { 21730fca6ea1SDimitry Andric Child = Child->clone(); 21740fca6ea1SDimitry Andric Child->addNameAsPredicateArg(ScopedName(Scope, Frag->getArgName(i))); 21750fca6ea1SDimitry Andric } 21760fca6ea1SDimitry Andric ArgMap[Frag->getArgName(i)] = Child; 21770fca6ea1SDimitry Andric } 21780fca6ea1SDimitry Andric 21790fca6ea1SDimitry Andric // Loop over all fragment alternatives. 21800fca6ea1SDimitry Andric for (const auto &Alternative : Frag->getTrees()) { 21810fca6ea1SDimitry Andric TreePatternNodePtr FragTree = Alternative->clone(); 21820fca6ea1SDimitry Andric 21830fca6ea1SDimitry Andric if (!PredFn.isAlwaysTrue()) 21840fca6ea1SDimitry Andric FragTree->addPredicateCall(PredFn, Scope); 21850fca6ea1SDimitry Andric 21860fca6ea1SDimitry Andric // Resolve formal arguments to their actual value. 21870fca6ea1SDimitry Andric if (Frag->getNumArgs()) 21880fca6ea1SDimitry Andric FragTree->SubstituteFormalArguments(ArgMap); 21890fca6ea1SDimitry Andric 21900fca6ea1SDimitry Andric // Transfer types. Note that the resolved alternative may have fewer 21910fca6ea1SDimitry Andric // (but not more) results than the PatFrags node. 21920fca6ea1SDimitry Andric FragTree->setName(getName()); 21930fca6ea1SDimitry Andric for (unsigned i = 0, e = FragTree->getNumTypes(); i != e; ++i) 21940fca6ea1SDimitry Andric FragTree->UpdateNodeType(i, getExtType(i), TP); 21950fca6ea1SDimitry Andric 21960fca6ea1SDimitry Andric if (Op->isSubClassOf("GISelFlags")) 21970fca6ea1SDimitry Andric FragTree->setGISelFlagsRecord(Op); 21980fca6ea1SDimitry Andric 21990fca6ea1SDimitry Andric // Transfer in the old predicates. 22000fca6ea1SDimitry Andric for (const TreePredicateCall &Pred : getPredicateCalls()) 22010fca6ea1SDimitry Andric FragTree->addPredicateCall(Pred); 22020fca6ea1SDimitry Andric 22030fca6ea1SDimitry Andric // The fragment we inlined could have recursive inlining that is needed. See 22040fca6ea1SDimitry Andric // if there are any pattern fragments in it and inline them as needed. 22050fca6ea1SDimitry Andric FragTree->InlinePatternFragments(TP, OutAlternatives); 22060fca6ea1SDimitry Andric } 22070fca6ea1SDimitry Andric } 22080fca6ea1SDimitry Andric 22090fca6ea1SDimitry Andric /// getImplicitType - Check to see if the specified record has an implicit 22100fca6ea1SDimitry Andric /// type which should be applied to it. This will infer the type of register 22110fca6ea1SDimitry Andric /// references from the register file information, for example. 22120fca6ea1SDimitry Andric /// 22130fca6ea1SDimitry Andric /// When Unnamed is set, return the type of a DAG operand with no name, such as 22140fca6ea1SDimitry Andric /// the F8RC register class argument in: 22150fca6ea1SDimitry Andric /// 22160fca6ea1SDimitry Andric /// (COPY_TO_REGCLASS GPR:$src, F8RC) 22170fca6ea1SDimitry Andric /// 22180fca6ea1SDimitry Andric /// When Unnamed is false, return the type of a named DAG operand such as the 22190fca6ea1SDimitry Andric /// GPR:$src operand above. 22200fca6ea1SDimitry Andric /// 22210fca6ea1SDimitry Andric static TypeSetByHwMode getImplicitType(Record *R, unsigned ResNo, 22220fca6ea1SDimitry Andric bool NotRegisters, bool Unnamed, 22230fca6ea1SDimitry Andric TreePattern &TP) { 22240fca6ea1SDimitry Andric CodeGenDAGPatterns &CDP = TP.getDAGPatterns(); 22250fca6ea1SDimitry Andric 22260fca6ea1SDimitry Andric // Check to see if this is a register operand. 22270fca6ea1SDimitry Andric if (R->isSubClassOf("RegisterOperand")) { 22280fca6ea1SDimitry Andric assert(ResNo == 0 && "Regoperand ref only has one result!"); 22290fca6ea1SDimitry Andric if (NotRegisters) 22300fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 22310fca6ea1SDimitry Andric Record *RegClass = R->getValueAsDef("RegClass"); 22320fca6ea1SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 22330fca6ea1SDimitry Andric return TypeSetByHwMode(T.getRegisterClass(RegClass).getValueTypes()); 22340fca6ea1SDimitry Andric } 22350fca6ea1SDimitry Andric 22360fca6ea1SDimitry Andric // Check to see if this is a register or a register class. 22370fca6ea1SDimitry Andric if (R->isSubClassOf("RegisterClass")) { 22380fca6ea1SDimitry Andric assert(ResNo == 0 && "Regclass ref only has one result!"); 22390fca6ea1SDimitry Andric // An unnamed register class represents itself as an i32 immediate, for 22400fca6ea1SDimitry Andric // example on a COPY_TO_REGCLASS instruction. 22410fca6ea1SDimitry Andric if (Unnamed) 22420fca6ea1SDimitry Andric return TypeSetByHwMode(MVT::i32); 22430fca6ea1SDimitry Andric 22440fca6ea1SDimitry Andric // In a named operand, the register class provides the possible set of 22450fca6ea1SDimitry Andric // types. 22460fca6ea1SDimitry Andric if (NotRegisters) 22470fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 22480fca6ea1SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 22490fca6ea1SDimitry Andric return TypeSetByHwMode(T.getRegisterClass(R).getValueTypes()); 22500fca6ea1SDimitry Andric } 22510fca6ea1SDimitry Andric 22520fca6ea1SDimitry Andric if (R->isSubClassOf("PatFrags")) { 22530fca6ea1SDimitry Andric assert(ResNo == 0 && "FIXME: PatFrag with multiple results?"); 22540fca6ea1SDimitry Andric // Pattern fragment types will be resolved when they are inlined. 22550fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 22560fca6ea1SDimitry Andric } 22570fca6ea1SDimitry Andric 22580fca6ea1SDimitry Andric if (R->isSubClassOf("Register")) { 22590fca6ea1SDimitry Andric assert(ResNo == 0 && "Registers only produce one result!"); 22600fca6ea1SDimitry Andric if (NotRegisters) 22610fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 22620fca6ea1SDimitry Andric const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); 22630fca6ea1SDimitry Andric return TypeSetByHwMode(T.getRegisterVTs(R)); 22640fca6ea1SDimitry Andric } 22650fca6ea1SDimitry Andric 22660fca6ea1SDimitry Andric if (R->isSubClassOf("SubRegIndex")) { 22670fca6ea1SDimitry Andric assert(ResNo == 0 && "SubRegisterIndices only produce one result!"); 22680fca6ea1SDimitry Andric return TypeSetByHwMode(MVT::i32); 22690fca6ea1SDimitry Andric } 22700fca6ea1SDimitry Andric 22710fca6ea1SDimitry Andric if (R->isSubClassOf("ValueType")) { 22720fca6ea1SDimitry Andric assert(ResNo == 0 && "This node only has one result!"); 22730fca6ea1SDimitry Andric // An unnamed VTSDNode represents itself as an MVT::Other immediate. 22740fca6ea1SDimitry Andric // 22750fca6ea1SDimitry Andric // (sext_inreg GPR:$src, i16) 22760fca6ea1SDimitry Andric // ~~~ 22770fca6ea1SDimitry Andric if (Unnamed) 22780fca6ea1SDimitry Andric return TypeSetByHwMode(MVT::Other); 22790fca6ea1SDimitry Andric // With a name, the ValueType simply provides the type of the named 22800fca6ea1SDimitry Andric // variable. 22810fca6ea1SDimitry Andric // 22820fca6ea1SDimitry Andric // (sext_inreg i32:$src, i16) 22830fca6ea1SDimitry Andric // ~~~~~~~~ 22840fca6ea1SDimitry Andric if (NotRegisters) 22850fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 22860fca6ea1SDimitry Andric const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); 22870fca6ea1SDimitry Andric return TypeSetByHwMode(getValueTypeByHwMode(R, CGH)); 22880fca6ea1SDimitry Andric } 22890fca6ea1SDimitry Andric 22900fca6ea1SDimitry Andric if (R->isSubClassOf("CondCode")) { 22910fca6ea1SDimitry Andric assert(ResNo == 0 && "This node only has one result!"); 22920fca6ea1SDimitry Andric // Using a CondCodeSDNode. 22930fca6ea1SDimitry Andric return TypeSetByHwMode(MVT::Other); 22940fca6ea1SDimitry Andric } 22950fca6ea1SDimitry Andric 22960fca6ea1SDimitry Andric if (R->isSubClassOf("ComplexPattern")) { 22970fca6ea1SDimitry Andric assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?"); 22980fca6ea1SDimitry Andric if (NotRegisters) 22990fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 23000fca6ea1SDimitry Andric Record *T = CDP.getComplexPattern(R).getValueType(); 23010fca6ea1SDimitry Andric const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); 23020fca6ea1SDimitry Andric return TypeSetByHwMode(getValueTypeByHwMode(T, CGH)); 23030fca6ea1SDimitry Andric } 23040fca6ea1SDimitry Andric if (R->isSubClassOf("PointerLikeRegClass")) { 23050fca6ea1SDimitry Andric assert(ResNo == 0 && "Regclass can only have one result!"); 23060fca6ea1SDimitry Andric TypeSetByHwMode VTS(MVT::iPTR); 23070fca6ea1SDimitry Andric TP.getInfer().expandOverloads(VTS); 23080fca6ea1SDimitry Andric return VTS; 23090fca6ea1SDimitry Andric } 23100fca6ea1SDimitry Andric 23110fca6ea1SDimitry Andric if (R->getName() == "node" || R->getName() == "srcvalue" || 23120fca6ea1SDimitry Andric R->getName() == "zero_reg" || R->getName() == "immAllOnesV" || 23130fca6ea1SDimitry Andric R->getName() == "immAllZerosV" || R->getName() == "undef_tied_input") { 23140fca6ea1SDimitry Andric // Placeholder. 23150fca6ea1SDimitry Andric return TypeSetByHwMode(); // Unknown. 23160fca6ea1SDimitry Andric } 23170fca6ea1SDimitry Andric 23180fca6ea1SDimitry Andric if (R->isSubClassOf("Operand")) { 23190fca6ea1SDimitry Andric const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); 23200fca6ea1SDimitry Andric Record *T = R->getValueAsDef("Type"); 23210fca6ea1SDimitry Andric return TypeSetByHwMode(getValueTypeByHwMode(T, CGH)); 23220fca6ea1SDimitry Andric } 23230fca6ea1SDimitry Andric 23240fca6ea1SDimitry Andric TP.error("Unknown node flavor used in pattern: " + R->getName()); 23250fca6ea1SDimitry Andric return TypeSetByHwMode(MVT::Other); 23260fca6ea1SDimitry Andric } 23270fca6ea1SDimitry Andric 23280fca6ea1SDimitry Andric /// getIntrinsicInfo - If this node corresponds to an intrinsic, return the 23290fca6ea1SDimitry Andric /// CodeGenIntrinsic information for it, otherwise return a null pointer. 23300fca6ea1SDimitry Andric const CodeGenIntrinsic * 23310fca6ea1SDimitry Andric TreePatternNode::getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { 23320fca6ea1SDimitry Andric if (getOperator() != CDP.get_intrinsic_void_sdnode() && 23330fca6ea1SDimitry Andric getOperator() != CDP.get_intrinsic_w_chain_sdnode() && 23340fca6ea1SDimitry Andric getOperator() != CDP.get_intrinsic_wo_chain_sdnode()) 23350fca6ea1SDimitry Andric return nullptr; 23360fca6ea1SDimitry Andric 23370fca6ea1SDimitry Andric unsigned IID = cast<IntInit>(getChild(0).getLeafValue())->getValue(); 23380fca6ea1SDimitry Andric return &CDP.getIntrinsicInfo(IID); 23390fca6ea1SDimitry Andric } 23400fca6ea1SDimitry Andric 23410fca6ea1SDimitry Andric /// getComplexPatternInfo - If this node corresponds to a ComplexPattern, 23420fca6ea1SDimitry Andric /// return the ComplexPattern information, otherwise return null. 23430fca6ea1SDimitry Andric const ComplexPattern * 23440fca6ea1SDimitry Andric TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const { 23450fca6ea1SDimitry Andric Record *Rec; 23460fca6ea1SDimitry Andric if (isLeaf()) { 23470fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(getLeafValue()); 23480fca6ea1SDimitry Andric if (!DI) 23490fca6ea1SDimitry Andric return nullptr; 23500fca6ea1SDimitry Andric Rec = DI->getDef(); 23510fca6ea1SDimitry Andric } else 23520fca6ea1SDimitry Andric Rec = getOperator(); 23530fca6ea1SDimitry Andric 23540fca6ea1SDimitry Andric if (!Rec->isSubClassOf("ComplexPattern")) 23550fca6ea1SDimitry Andric return nullptr; 23560fca6ea1SDimitry Andric return &CGP.getComplexPattern(Rec); 23570fca6ea1SDimitry Andric } 23580fca6ea1SDimitry Andric 23590fca6ea1SDimitry Andric unsigned TreePatternNode::getNumMIResults(const CodeGenDAGPatterns &CGP) const { 23600fca6ea1SDimitry Andric // A ComplexPattern specifically declares how many results it fills in. 23610fca6ea1SDimitry Andric if (const ComplexPattern *CP = getComplexPatternInfo(CGP)) 23620fca6ea1SDimitry Andric return CP->getNumOperands(); 23630fca6ea1SDimitry Andric 23640fca6ea1SDimitry Andric // If MIOperandInfo is specified, that gives the count. 23650fca6ea1SDimitry Andric if (isLeaf()) { 23660fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(getLeafValue()); 23670fca6ea1SDimitry Andric if (DI && DI->getDef()->isSubClassOf("Operand")) { 23680fca6ea1SDimitry Andric DagInit *MIOps = DI->getDef()->getValueAsDag("MIOperandInfo"); 23690fca6ea1SDimitry Andric if (MIOps->getNumArgs()) 23700fca6ea1SDimitry Andric return MIOps->getNumArgs(); 23710fca6ea1SDimitry Andric } 23720fca6ea1SDimitry Andric } 23730fca6ea1SDimitry Andric 23740fca6ea1SDimitry Andric // Otherwise there is just one result. 23750fca6ea1SDimitry Andric return 1; 23760fca6ea1SDimitry Andric } 23770fca6ea1SDimitry Andric 23780fca6ea1SDimitry Andric /// NodeHasProperty - Return true if this node has the specified property. 23790fca6ea1SDimitry Andric bool TreePatternNode::NodeHasProperty(SDNP Property, 23800fca6ea1SDimitry Andric const CodeGenDAGPatterns &CGP) const { 23810fca6ea1SDimitry Andric if (isLeaf()) { 23820fca6ea1SDimitry Andric if (const ComplexPattern *CP = getComplexPatternInfo(CGP)) 23830fca6ea1SDimitry Andric return CP->hasProperty(Property); 23840fca6ea1SDimitry Andric 23850fca6ea1SDimitry Andric return false; 23860fca6ea1SDimitry Andric } 23870fca6ea1SDimitry Andric 23880fca6ea1SDimitry Andric if (Property != SDNPHasChain) { 23890fca6ea1SDimitry Andric // The chain proprety is already present on the different intrinsic node 23900fca6ea1SDimitry Andric // types (intrinsic_w_chain, intrinsic_void), and is not explicitly listed 23910fca6ea1SDimitry Andric // on the intrinsic. Anything else is specific to the individual intrinsic. 23920fca6ea1SDimitry Andric if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CGP)) 23930fca6ea1SDimitry Andric return Int->hasProperty(Property); 23940fca6ea1SDimitry Andric } 23950fca6ea1SDimitry Andric 23960fca6ea1SDimitry Andric if (!getOperator()->isSubClassOf("SDPatternOperator")) 23970fca6ea1SDimitry Andric return false; 23980fca6ea1SDimitry Andric 23990fca6ea1SDimitry Andric return CGP.getSDNodeInfo(getOperator()).hasProperty(Property); 24000fca6ea1SDimitry Andric } 24010fca6ea1SDimitry Andric 24020fca6ea1SDimitry Andric /// TreeHasProperty - Return true if any node in this tree has the specified 24030fca6ea1SDimitry Andric /// property. 24040fca6ea1SDimitry Andric bool TreePatternNode::TreeHasProperty(SDNP Property, 24050fca6ea1SDimitry Andric const CodeGenDAGPatterns &CGP) const { 24060fca6ea1SDimitry Andric if (NodeHasProperty(Property, CGP)) 24070fca6ea1SDimitry Andric return true; 24080fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 24090fca6ea1SDimitry Andric if (getChild(i).TreeHasProperty(Property, CGP)) 24100fca6ea1SDimitry Andric return true; 24110fca6ea1SDimitry Andric return false; 24120fca6ea1SDimitry Andric } 24130fca6ea1SDimitry Andric 24140fca6ea1SDimitry Andric /// isCommutativeIntrinsic - Return true if the node corresponds to a 24150fca6ea1SDimitry Andric /// commutative intrinsic. 24160fca6ea1SDimitry Andric bool TreePatternNode::isCommutativeIntrinsic( 24170fca6ea1SDimitry Andric const CodeGenDAGPatterns &CDP) const { 24180fca6ea1SDimitry Andric if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) 24190fca6ea1SDimitry Andric return Int->isCommutative; 24200fca6ea1SDimitry Andric return false; 24210fca6ea1SDimitry Andric } 24220fca6ea1SDimitry Andric 24230fca6ea1SDimitry Andric static bool isOperandClass(const TreePatternNode &N, StringRef Class) { 24240fca6ea1SDimitry Andric if (!N.isLeaf()) 24250fca6ea1SDimitry Andric return N.getOperator()->isSubClassOf(Class); 24260fca6ea1SDimitry Andric 24270fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(N.getLeafValue()); 24280fca6ea1SDimitry Andric if (DI && DI->getDef()->isSubClassOf(Class)) 24290fca6ea1SDimitry Andric return true; 24300fca6ea1SDimitry Andric 24310fca6ea1SDimitry Andric return false; 24320fca6ea1SDimitry Andric } 24330fca6ea1SDimitry Andric 24340fca6ea1SDimitry Andric static void emitTooManyOperandsError(TreePattern &TP, StringRef InstName, 24350fca6ea1SDimitry Andric unsigned Expected, unsigned Actual) { 24360fca6ea1SDimitry Andric TP.error("Instruction '" + InstName + "' was provided " + Twine(Actual) + 24370fca6ea1SDimitry Andric " operands but expected only " + Twine(Expected) + "!"); 24380fca6ea1SDimitry Andric } 24390fca6ea1SDimitry Andric 24400fca6ea1SDimitry Andric static void emitTooFewOperandsError(TreePattern &TP, StringRef InstName, 24410fca6ea1SDimitry Andric unsigned Actual) { 24420fca6ea1SDimitry Andric TP.error("Instruction '" + InstName + "' expects more than the provided " + 24430fca6ea1SDimitry Andric Twine(Actual) + " operands!"); 24440fca6ea1SDimitry Andric } 24450fca6ea1SDimitry Andric 24460fca6ea1SDimitry Andric /// ApplyTypeConstraints - Apply all of the type constraints relevant to 24470fca6ea1SDimitry Andric /// this node and its children in the tree. This returns true if it makes a 24480fca6ea1SDimitry Andric /// change, false otherwise. If a type contradiction is found, flag an error. 24490fca6ea1SDimitry Andric bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { 24500fca6ea1SDimitry Andric if (TP.hasError()) 24510fca6ea1SDimitry Andric return false; 24520fca6ea1SDimitry Andric 24530fca6ea1SDimitry Andric CodeGenDAGPatterns &CDP = TP.getDAGPatterns(); 24540fca6ea1SDimitry Andric if (isLeaf()) { 24550fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) { 24560fca6ea1SDimitry Andric // If it's a regclass or something else known, include the type. 24570fca6ea1SDimitry Andric bool MadeChange = false; 24580fca6ea1SDimitry Andric for (unsigned i = 0, e = Types.size(); i != e; ++i) 24590fca6ea1SDimitry Andric MadeChange |= UpdateNodeType( 24600fca6ea1SDimitry Andric i, getImplicitType(DI->getDef(), i, NotRegisters, !hasName(), TP), 24610fca6ea1SDimitry Andric TP); 24620fca6ea1SDimitry Andric return MadeChange; 24630fca6ea1SDimitry Andric } 24640fca6ea1SDimitry Andric 24650fca6ea1SDimitry Andric if (IntInit *II = dyn_cast<IntInit>(getLeafValue())) { 24660fca6ea1SDimitry Andric assert(Types.size() == 1 && "Invalid IntInit"); 24670fca6ea1SDimitry Andric 24680fca6ea1SDimitry Andric // Int inits are always integers. :) 24690fca6ea1SDimitry Andric bool MadeChange = TP.getInfer().EnforceInteger(Types[0]); 24700fca6ea1SDimitry Andric 24710fca6ea1SDimitry Andric if (!TP.getInfer().isConcrete(Types[0], false)) 24720fca6ea1SDimitry Andric return MadeChange; 24730fca6ea1SDimitry Andric 24740fca6ea1SDimitry Andric ValueTypeByHwMode VVT = TP.getInfer().getConcrete(Types[0], false); 24750fca6ea1SDimitry Andric for (auto &P : VVT) { 24760fca6ea1SDimitry Andric MVT::SimpleValueType VT = P.second.SimpleTy; 24770fca6ea1SDimitry Andric if (VT == MVT::iPTR || VT == MVT::iPTRAny) 24780fca6ea1SDimitry Andric continue; 24790fca6ea1SDimitry Andric unsigned Size = MVT(VT).getFixedSizeInBits(); 24800fca6ea1SDimitry Andric // Make sure that the value is representable for this type. 24810fca6ea1SDimitry Andric if (Size >= 32) 24820fca6ea1SDimitry Andric continue; 24830fca6ea1SDimitry Andric // Check that the value doesn't use more bits than we have. It must 24840fca6ea1SDimitry Andric // either be a sign- or zero-extended equivalent of the original. 24850fca6ea1SDimitry Andric int64_t SignBitAndAbove = II->getValue() >> (Size - 1); 24860fca6ea1SDimitry Andric if (SignBitAndAbove == -1 || SignBitAndAbove == 0 || 24870fca6ea1SDimitry Andric SignBitAndAbove == 1) 24880fca6ea1SDimitry Andric continue; 24890fca6ea1SDimitry Andric 24900fca6ea1SDimitry Andric TP.error("Integer value '" + Twine(II->getValue()) + 24910fca6ea1SDimitry Andric "' is out of range for type '" + getEnumName(VT) + "'!"); 24920fca6ea1SDimitry Andric break; 24930fca6ea1SDimitry Andric } 24940fca6ea1SDimitry Andric return MadeChange; 24950fca6ea1SDimitry Andric } 24960fca6ea1SDimitry Andric 24970fca6ea1SDimitry Andric return false; 24980fca6ea1SDimitry Andric } 24990fca6ea1SDimitry Andric 25000fca6ea1SDimitry Andric if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) { 25010fca6ea1SDimitry Andric bool MadeChange = false; 25020fca6ea1SDimitry Andric 25030fca6ea1SDimitry Andric // Apply the result type to the node. 25040fca6ea1SDimitry Andric unsigned NumRetVTs = Int->IS.RetTys.size(); 25050fca6ea1SDimitry Andric unsigned NumParamVTs = Int->IS.ParamTys.size(); 25060fca6ea1SDimitry Andric 25070fca6ea1SDimitry Andric for (unsigned i = 0, e = NumRetVTs; i != e; ++i) 25080fca6ea1SDimitry Andric MadeChange |= UpdateNodeType( 25090fca6ea1SDimitry Andric i, getValueType(Int->IS.RetTys[i]->getValueAsDef("VT")), TP); 25100fca6ea1SDimitry Andric 25110fca6ea1SDimitry Andric if (getNumChildren() != NumParamVTs + 1) { 25120fca6ea1SDimitry Andric TP.error("Intrinsic '" + Int->Name + "' expects " + Twine(NumParamVTs) + 25130fca6ea1SDimitry Andric " operands, not " + Twine(getNumChildren() - 1) + " operands!"); 25140fca6ea1SDimitry Andric return false; 25150fca6ea1SDimitry Andric } 25160fca6ea1SDimitry Andric 25170fca6ea1SDimitry Andric // Apply type info to the intrinsic ID. 25180fca6ea1SDimitry Andric MadeChange |= getChild(0).UpdateNodeType(0, MVT::iPTR, TP); 25190fca6ea1SDimitry Andric 25200fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren() - 1; i != e; ++i) { 25210fca6ea1SDimitry Andric MadeChange |= getChild(i + 1).ApplyTypeConstraints(TP, NotRegisters); 25220fca6ea1SDimitry Andric 25230fca6ea1SDimitry Andric MVT::SimpleValueType OpVT = 25240fca6ea1SDimitry Andric getValueType(Int->IS.ParamTys[i]->getValueAsDef("VT")); 25250fca6ea1SDimitry Andric assert(getChild(i + 1).getNumTypes() == 1 && "Unhandled case"); 25260fca6ea1SDimitry Andric MadeChange |= getChild(i + 1).UpdateNodeType(0, OpVT, TP); 25270fca6ea1SDimitry Andric } 25280fca6ea1SDimitry Andric return MadeChange; 25290fca6ea1SDimitry Andric } 25300fca6ea1SDimitry Andric 25310fca6ea1SDimitry Andric if (getOperator()->isSubClassOf("SDNode")) { 25320fca6ea1SDimitry Andric const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator()); 25330fca6ea1SDimitry Andric 25340fca6ea1SDimitry Andric // Check that the number of operands is sane. Negative operands -> varargs. 25350fca6ea1SDimitry Andric if (NI.getNumOperands() >= 0 && 25360fca6ea1SDimitry Andric getNumChildren() != (unsigned)NI.getNumOperands()) { 25370fca6ea1SDimitry Andric TP.error(getOperator()->getName() + " node requires exactly " + 25380fca6ea1SDimitry Andric Twine(NI.getNumOperands()) + " operands!"); 25390fca6ea1SDimitry Andric return false; 25400fca6ea1SDimitry Andric } 25410fca6ea1SDimitry Andric 25420fca6ea1SDimitry Andric bool MadeChange = false; 25430fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 25440fca6ea1SDimitry Andric MadeChange |= getChild(i).ApplyTypeConstraints(TP, NotRegisters); 25450fca6ea1SDimitry Andric MadeChange |= NI.ApplyTypeConstraints(*this, TP); 25460fca6ea1SDimitry Andric return MadeChange; 25470fca6ea1SDimitry Andric } 25480fca6ea1SDimitry Andric 25490fca6ea1SDimitry Andric if (getOperator()->isSubClassOf("Instruction")) { 25500fca6ea1SDimitry Andric const DAGInstruction &Inst = CDP.getInstruction(getOperator()); 25510fca6ea1SDimitry Andric CodeGenInstruction &InstInfo = 25520fca6ea1SDimitry Andric CDP.getTargetInfo().getInstruction(getOperator()); 25530fca6ea1SDimitry Andric 25540fca6ea1SDimitry Andric bool MadeChange = false; 25550fca6ea1SDimitry Andric 25560fca6ea1SDimitry Andric // Apply the result types to the node, these come from the things in the 25570fca6ea1SDimitry Andric // (outs) list of the instruction. 25580fca6ea1SDimitry Andric unsigned NumResultsToAdd = 25590fca6ea1SDimitry Andric std::min(InstInfo.Operands.NumDefs, Inst.getNumResults()); 25600fca6ea1SDimitry Andric for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) 25610fca6ea1SDimitry Andric MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP); 25620fca6ea1SDimitry Andric 25630fca6ea1SDimitry Andric // If the instruction has implicit defs, we apply the first one as a result. 25640fca6ea1SDimitry Andric // FIXME: This sucks, it should apply all implicit defs. 25650fca6ea1SDimitry Andric if (!InstInfo.ImplicitDefs.empty()) { 25660fca6ea1SDimitry Andric unsigned ResNo = NumResultsToAdd; 25670fca6ea1SDimitry Andric 25680fca6ea1SDimitry Andric // FIXME: Generalize to multiple possible types and multiple possible 25690fca6ea1SDimitry Andric // ImplicitDefs. 25700fca6ea1SDimitry Andric MVT::SimpleValueType VT = 25710fca6ea1SDimitry Andric InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()); 25720fca6ea1SDimitry Andric 25730fca6ea1SDimitry Andric if (VT != MVT::Other) 25740fca6ea1SDimitry Andric MadeChange |= UpdateNodeType(ResNo, VT, TP); 25750fca6ea1SDimitry Andric } 25760fca6ea1SDimitry Andric 25770fca6ea1SDimitry Andric // If this is an INSERT_SUBREG, constrain the source and destination VTs to 25780fca6ea1SDimitry Andric // be the same. 25790fca6ea1SDimitry Andric if (getOperator()->getName() == "INSERT_SUBREG") { 25800fca6ea1SDimitry Andric assert(getChild(0).getNumTypes() == 1 && "FIXME: Unhandled"); 25810fca6ea1SDimitry Andric MadeChange |= UpdateNodeType(0, getChild(0).getExtType(0), TP); 25820fca6ea1SDimitry Andric MadeChange |= getChild(0).UpdateNodeType(0, getExtType(0), TP); 25830fca6ea1SDimitry Andric } else if (getOperator()->getName() == "REG_SEQUENCE") { 25840fca6ea1SDimitry Andric // We need to do extra, custom typechecking for REG_SEQUENCE since it is 25850fca6ea1SDimitry Andric // variadic. 25860fca6ea1SDimitry Andric 25870fca6ea1SDimitry Andric unsigned NChild = getNumChildren(); 25880fca6ea1SDimitry Andric if (NChild < 3) { 25890fca6ea1SDimitry Andric TP.error("REG_SEQUENCE requires at least 3 operands!"); 25900fca6ea1SDimitry Andric return false; 25910fca6ea1SDimitry Andric } 25920fca6ea1SDimitry Andric 25930fca6ea1SDimitry Andric if (NChild % 2 == 0) { 25940fca6ea1SDimitry Andric TP.error("REG_SEQUENCE requires an odd number of operands!"); 25950fca6ea1SDimitry Andric return false; 25960fca6ea1SDimitry Andric } 25970fca6ea1SDimitry Andric 25980fca6ea1SDimitry Andric if (!isOperandClass(getChild(0), "RegisterClass")) { 25990fca6ea1SDimitry Andric TP.error("REG_SEQUENCE requires a RegisterClass for first operand!"); 26000fca6ea1SDimitry Andric return false; 26010fca6ea1SDimitry Andric } 26020fca6ea1SDimitry Andric 26030fca6ea1SDimitry Andric for (unsigned I = 1; I < NChild; I += 2) { 26040fca6ea1SDimitry Andric TreePatternNode &SubIdxChild = getChild(I + 1); 26050fca6ea1SDimitry Andric if (!isOperandClass(SubIdxChild, "SubRegIndex")) { 26060fca6ea1SDimitry Andric TP.error("REG_SEQUENCE requires a SubRegIndex for operand " + 26070fca6ea1SDimitry Andric Twine(I + 1) + "!"); 26080fca6ea1SDimitry Andric return false; 26090fca6ea1SDimitry Andric } 26100fca6ea1SDimitry Andric } 26110fca6ea1SDimitry Andric } 26120fca6ea1SDimitry Andric 26130fca6ea1SDimitry Andric unsigned NumResults = Inst.getNumResults(); 26140fca6ea1SDimitry Andric unsigned NumFixedOperands = InstInfo.Operands.size(); 26150fca6ea1SDimitry Andric 26160fca6ea1SDimitry Andric // If one or more operands with a default value appear at the end of the 26170fca6ea1SDimitry Andric // formal operand list for an instruction, we allow them to be overridden 26180fca6ea1SDimitry Andric // by optional operands provided in the pattern. 26190fca6ea1SDimitry Andric // 26200fca6ea1SDimitry Andric // But if an operand B without a default appears at any point after an 26210fca6ea1SDimitry Andric // operand A with a default, then we don't allow A to be overridden, 26220fca6ea1SDimitry Andric // because there would be no way to specify whether the next operand in 26230fca6ea1SDimitry Andric // the pattern was intended to override A or skip it. 26240fca6ea1SDimitry Andric unsigned NonOverridableOperands = NumFixedOperands; 26250fca6ea1SDimitry Andric while (NonOverridableOperands > NumResults && 26260fca6ea1SDimitry Andric CDP.operandHasDefault( 26270fca6ea1SDimitry Andric InstInfo.Operands[NonOverridableOperands - 1].Rec)) 26280fca6ea1SDimitry Andric --NonOverridableOperands; 26290fca6ea1SDimitry Andric 26300fca6ea1SDimitry Andric unsigned ChildNo = 0; 26310fca6ea1SDimitry Andric assert(NumResults <= NumFixedOperands); 26320fca6ea1SDimitry Andric for (unsigned i = NumResults, e = NumFixedOperands; i != e; ++i) { 26330fca6ea1SDimitry Andric Record *OperandNode = InstInfo.Operands[i].Rec; 26340fca6ea1SDimitry Andric 26350fca6ea1SDimitry Andric // If the operand has a default value, do we use it? We must use the 26360fca6ea1SDimitry Andric // default if we've run out of children of the pattern DAG to consume, 26370fca6ea1SDimitry Andric // or if the operand is followed by a non-defaulted one. 26380fca6ea1SDimitry Andric if (CDP.operandHasDefault(OperandNode) && 26390fca6ea1SDimitry Andric (i < NonOverridableOperands || ChildNo >= getNumChildren())) 26400fca6ea1SDimitry Andric continue; 26410fca6ea1SDimitry Andric 26420fca6ea1SDimitry Andric // If we have run out of child nodes and there _isn't_ a default 26430fca6ea1SDimitry Andric // value we can use for the next operand, give an error. 26440fca6ea1SDimitry Andric if (ChildNo >= getNumChildren()) { 26450fca6ea1SDimitry Andric emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren()); 26460fca6ea1SDimitry Andric return false; 26470fca6ea1SDimitry Andric } 26480fca6ea1SDimitry Andric 26490fca6ea1SDimitry Andric TreePatternNode *Child = &getChild(ChildNo++); 26500fca6ea1SDimitry Andric unsigned ChildResNo = 0; // Instructions always use res #0 of their op. 26510fca6ea1SDimitry Andric 26520fca6ea1SDimitry Andric // If the operand has sub-operands, they may be provided by distinct 26530fca6ea1SDimitry Andric // child patterns, so attempt to match each sub-operand separately. 26540fca6ea1SDimitry Andric if (OperandNode->isSubClassOf("Operand")) { 26550fca6ea1SDimitry Andric DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo"); 26560fca6ea1SDimitry Andric if (unsigned NumArgs = MIOpInfo->getNumArgs()) { 26570fca6ea1SDimitry Andric // But don't do that if the whole operand is being provided by 26580fca6ea1SDimitry Andric // a single ComplexPattern-related Operand. 26590fca6ea1SDimitry Andric 26600fca6ea1SDimitry Andric if (Child->getNumMIResults(CDP) < NumArgs) { 26610fca6ea1SDimitry Andric // Match first sub-operand against the child we already have. 26620fca6ea1SDimitry Andric Record *SubRec = cast<DefInit>(MIOpInfo->getArg(0))->getDef(); 26630fca6ea1SDimitry Andric MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP); 26640fca6ea1SDimitry Andric 26650fca6ea1SDimitry Andric // And the remaining sub-operands against subsequent children. 26660fca6ea1SDimitry Andric for (unsigned Arg = 1; Arg < NumArgs; ++Arg) { 26670fca6ea1SDimitry Andric if (ChildNo >= getNumChildren()) { 26680fca6ea1SDimitry Andric emitTooFewOperandsError(TP, getOperator()->getName(), 26690fca6ea1SDimitry Andric getNumChildren()); 26700fca6ea1SDimitry Andric return false; 26710fca6ea1SDimitry Andric } 26720fca6ea1SDimitry Andric Child = &getChild(ChildNo++); 26730fca6ea1SDimitry Andric 26740fca6ea1SDimitry Andric SubRec = cast<DefInit>(MIOpInfo->getArg(Arg))->getDef(); 26750fca6ea1SDimitry Andric MadeChange |= 26760fca6ea1SDimitry Andric Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP); 26770fca6ea1SDimitry Andric } 26780fca6ea1SDimitry Andric continue; 26790fca6ea1SDimitry Andric } 26800fca6ea1SDimitry Andric } 26810fca6ea1SDimitry Andric } 26820fca6ea1SDimitry Andric 26830fca6ea1SDimitry Andric // If we didn't match by pieces above, attempt to match the whole 26840fca6ea1SDimitry Andric // operand now. 26850fca6ea1SDimitry Andric MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP); 26860fca6ea1SDimitry Andric } 26870fca6ea1SDimitry Andric 26880fca6ea1SDimitry Andric if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) { 26890fca6ea1SDimitry Andric emitTooManyOperandsError(TP, getOperator()->getName(), ChildNo, 26900fca6ea1SDimitry Andric getNumChildren()); 26910fca6ea1SDimitry Andric return false; 26920fca6ea1SDimitry Andric } 26930fca6ea1SDimitry Andric 26940fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 26950fca6ea1SDimitry Andric MadeChange |= getChild(i).ApplyTypeConstraints(TP, NotRegisters); 26960fca6ea1SDimitry Andric return MadeChange; 26970fca6ea1SDimitry Andric } 26980fca6ea1SDimitry Andric 26990fca6ea1SDimitry Andric if (getOperator()->isSubClassOf("ComplexPattern")) { 27000fca6ea1SDimitry Andric bool MadeChange = false; 27010fca6ea1SDimitry Andric 27020fca6ea1SDimitry Andric if (!NotRegisters) { 27030fca6ea1SDimitry Andric assert(Types.size() == 1 && "ComplexPatterns only produce one result!"); 27040fca6ea1SDimitry Andric Record *T = CDP.getComplexPattern(getOperator()).getValueType(); 27050fca6ea1SDimitry Andric const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes(); 27060fca6ea1SDimitry Andric const ValueTypeByHwMode VVT = getValueTypeByHwMode(T, CGH); 27070fca6ea1SDimitry Andric // TODO: AArch64 and AMDGPU use ComplexPattern<untyped, ...> and then 27080fca6ea1SDimitry Andric // exclusively use those as non-leaf nodes with explicit type casts, so 27090fca6ea1SDimitry Andric // for backwards compatibility we do no inference in that case. This is 27100fca6ea1SDimitry Andric // not supported when the ComplexPattern is used as a leaf value, 27110fca6ea1SDimitry Andric // however; this inconsistency should be resolved, either by adding this 27120fca6ea1SDimitry Andric // case there or by altering the backends to not do this (e.g. using Any 27130fca6ea1SDimitry Andric // instead may work). 27140fca6ea1SDimitry Andric if (!VVT.isSimple() || VVT.getSimple() != MVT::Untyped) 27150fca6ea1SDimitry Andric MadeChange |= UpdateNodeType(0, VVT, TP); 27160fca6ea1SDimitry Andric } 27170fca6ea1SDimitry Andric 27180fca6ea1SDimitry Andric for (unsigned i = 0; i < getNumChildren(); ++i) 27190fca6ea1SDimitry Andric MadeChange |= getChild(i).ApplyTypeConstraints(TP, NotRegisters); 27200fca6ea1SDimitry Andric 27210fca6ea1SDimitry Andric return MadeChange; 27220fca6ea1SDimitry Andric } 27230fca6ea1SDimitry Andric 27240fca6ea1SDimitry Andric assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); 27250fca6ea1SDimitry Andric 27260fca6ea1SDimitry Andric // Node transforms always take one operand. 27270fca6ea1SDimitry Andric if (getNumChildren() != 1) { 27280fca6ea1SDimitry Andric TP.error("Node transform '" + getOperator()->getName() + 27290fca6ea1SDimitry Andric "' requires one operand!"); 27300fca6ea1SDimitry Andric return false; 27310fca6ea1SDimitry Andric } 27320fca6ea1SDimitry Andric 27330fca6ea1SDimitry Andric bool MadeChange = getChild(0).ApplyTypeConstraints(TP, NotRegisters); 27340fca6ea1SDimitry Andric return MadeChange; 27350fca6ea1SDimitry Andric } 27360fca6ea1SDimitry Andric 27370fca6ea1SDimitry Andric /// OnlyOnRHSOfCommutative - Return true if this value is only allowed on the 27380fca6ea1SDimitry Andric /// RHS of a commutative operation, not the on LHS. 27390fca6ea1SDimitry Andric static bool OnlyOnRHSOfCommutative(TreePatternNode &N) { 27400fca6ea1SDimitry Andric if (!N.isLeaf() && N.getOperator()->getName() == "imm") 27410fca6ea1SDimitry Andric return true; 27420fca6ea1SDimitry Andric if (N.isLeaf() && isa<IntInit>(N.getLeafValue())) 27430fca6ea1SDimitry Andric return true; 27440fca6ea1SDimitry Andric if (isImmAllOnesAllZerosMatch(N)) 27450fca6ea1SDimitry Andric return true; 27460fca6ea1SDimitry Andric return false; 27470fca6ea1SDimitry Andric } 27480fca6ea1SDimitry Andric 27490fca6ea1SDimitry Andric /// canPatternMatch - If it is impossible for this pattern to match on this 27500fca6ea1SDimitry Andric /// target, fill in Reason and return false. Otherwise, return true. This is 27510fca6ea1SDimitry Andric /// used as a sanity check for .td files (to prevent people from writing stuff 27520fca6ea1SDimitry Andric /// that can never possibly work), and to prevent the pattern permuter from 27530fca6ea1SDimitry Andric /// generating stuff that is useless. 27540fca6ea1SDimitry Andric bool TreePatternNode::canPatternMatch(std::string &Reason, 27550fca6ea1SDimitry Andric const CodeGenDAGPatterns &CDP) { 27560fca6ea1SDimitry Andric if (isLeaf()) 27570fca6ea1SDimitry Andric return true; 27580fca6ea1SDimitry Andric 27590fca6ea1SDimitry Andric for (unsigned i = 0, e = getNumChildren(); i != e; ++i) 27600fca6ea1SDimitry Andric if (!getChild(i).canPatternMatch(Reason, CDP)) 27610fca6ea1SDimitry Andric return false; 27620fca6ea1SDimitry Andric 27630fca6ea1SDimitry Andric // If this is an intrinsic, handle cases that would make it not match. For 27640fca6ea1SDimitry Andric // example, if an operand is required to be an immediate. 27650fca6ea1SDimitry Andric if (getOperator()->isSubClassOf("Intrinsic")) { 27660fca6ea1SDimitry Andric // TODO: 27670fca6ea1SDimitry Andric return true; 27680fca6ea1SDimitry Andric } 27690fca6ea1SDimitry Andric 27700fca6ea1SDimitry Andric if (getOperator()->isSubClassOf("ComplexPattern")) 27710fca6ea1SDimitry Andric return true; 27720fca6ea1SDimitry Andric 27730fca6ea1SDimitry Andric // If this node is a commutative operator, check that the LHS isn't an 27740fca6ea1SDimitry Andric // immediate. 27750fca6ea1SDimitry Andric const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator()); 27760fca6ea1SDimitry Andric bool isCommIntrinsic = isCommutativeIntrinsic(CDP); 27770fca6ea1SDimitry Andric if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) { 27780fca6ea1SDimitry Andric // Scan all of the operands of the node and make sure that only the last one 27790fca6ea1SDimitry Andric // is a constant node, unless the RHS also is. 27800fca6ea1SDimitry Andric if (!OnlyOnRHSOfCommutative(getChild(getNumChildren() - 1))) { 27810fca6ea1SDimitry Andric unsigned Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id. 27820fca6ea1SDimitry Andric for (unsigned i = Skip, e = getNumChildren() - 1; i != e; ++i) 27830fca6ea1SDimitry Andric if (OnlyOnRHSOfCommutative(getChild(i))) { 27840fca6ea1SDimitry Andric Reason = 27850fca6ea1SDimitry Andric "Immediate value must be on the RHS of commutative operators!"; 27860fca6ea1SDimitry Andric return false; 27870fca6ea1SDimitry Andric } 27880fca6ea1SDimitry Andric } 27890fca6ea1SDimitry Andric } 27900fca6ea1SDimitry Andric 27910fca6ea1SDimitry Andric return true; 27920fca6ea1SDimitry Andric } 27930fca6ea1SDimitry Andric 27940fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 27950fca6ea1SDimitry Andric // TreePattern implementation 27960fca6ea1SDimitry Andric // 27970fca6ea1SDimitry Andric 27980fca6ea1SDimitry Andric TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, 27990fca6ea1SDimitry Andric CodeGenDAGPatterns &cdp) 28000fca6ea1SDimitry Andric : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false), 28010fca6ea1SDimitry Andric Infer(*this) { 28020fca6ea1SDimitry Andric for (Init *I : RawPat->getValues()) 28030fca6ea1SDimitry Andric Trees.push_back(ParseTreePattern(I, "")); 28040fca6ea1SDimitry Andric } 28050fca6ea1SDimitry Andric 28060fca6ea1SDimitry Andric TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput, 28070fca6ea1SDimitry Andric CodeGenDAGPatterns &cdp) 28080fca6ea1SDimitry Andric : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false), 28090fca6ea1SDimitry Andric Infer(*this) { 28100fca6ea1SDimitry Andric Trees.push_back(ParseTreePattern(Pat, "")); 28110fca6ea1SDimitry Andric } 28120fca6ea1SDimitry Andric 28130fca6ea1SDimitry Andric TreePattern::TreePattern(Record *TheRec, TreePatternNodePtr Pat, bool isInput, 28140fca6ea1SDimitry Andric CodeGenDAGPatterns &cdp) 28150fca6ea1SDimitry Andric : TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false), 28160fca6ea1SDimitry Andric Infer(*this) { 28170fca6ea1SDimitry Andric Trees.push_back(Pat); 28180fca6ea1SDimitry Andric } 28190fca6ea1SDimitry Andric 28200fca6ea1SDimitry Andric void TreePattern::error(const Twine &Msg) { 28210fca6ea1SDimitry Andric if (HasError) 28220fca6ea1SDimitry Andric return; 28230fca6ea1SDimitry Andric dump(); 28240fca6ea1SDimitry Andric PrintError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg); 28250fca6ea1SDimitry Andric HasError = true; 28260fca6ea1SDimitry Andric } 28270fca6ea1SDimitry Andric 28280fca6ea1SDimitry Andric void TreePattern::ComputeNamedNodes() { 28290fca6ea1SDimitry Andric for (TreePatternNodePtr &Tree : Trees) 28300fca6ea1SDimitry Andric ComputeNamedNodes(*Tree); 28310fca6ea1SDimitry Andric } 28320fca6ea1SDimitry Andric 28330fca6ea1SDimitry Andric void TreePattern::ComputeNamedNodes(TreePatternNode &N) { 28340fca6ea1SDimitry Andric if (!N.getName().empty()) 28350fca6ea1SDimitry Andric NamedNodes[N.getName()].push_back(&N); 28360fca6ea1SDimitry Andric 28370fca6ea1SDimitry Andric for (unsigned i = 0, e = N.getNumChildren(); i != e; ++i) 28380fca6ea1SDimitry Andric ComputeNamedNodes(N.getChild(i)); 28390fca6ea1SDimitry Andric } 28400fca6ea1SDimitry Andric 28410fca6ea1SDimitry Andric TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit, 28420fca6ea1SDimitry Andric StringRef OpName) { 28430fca6ea1SDimitry Andric RecordKeeper &RK = TheInit->getRecordKeeper(); 28440fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(TheInit)) { 28450fca6ea1SDimitry Andric Record *R = DI->getDef(); 28460fca6ea1SDimitry Andric 28470fca6ea1SDimitry Andric // Direct reference to a leaf DagNode or PatFrag? Turn it into a 28480fca6ea1SDimitry Andric // TreePatternNode of its own. For example: 28490fca6ea1SDimitry Andric /// (foo GPR, imm) -> (foo GPR, (imm)) 28500fca6ea1SDimitry Andric if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrags")) 28510fca6ea1SDimitry Andric return ParseTreePattern( 28520fca6ea1SDimitry Andric DagInit::get(DI, nullptr, 28530fca6ea1SDimitry Andric std::vector<std::pair<Init *, StringInit *>>()), 28540fca6ea1SDimitry Andric OpName); 28550fca6ea1SDimitry Andric 28560fca6ea1SDimitry Andric // Input argument? 28570fca6ea1SDimitry Andric TreePatternNodePtr Res = makeIntrusiveRefCnt<TreePatternNode>(DI, 1); 28580fca6ea1SDimitry Andric if (R->getName() == "node" && !OpName.empty()) { 28590fca6ea1SDimitry Andric if (OpName.empty()) 28600fca6ea1SDimitry Andric error("'node' argument requires a name to match with operand list"); 28610fca6ea1SDimitry Andric Args.push_back(std::string(OpName)); 28620fca6ea1SDimitry Andric } 28630fca6ea1SDimitry Andric 28640fca6ea1SDimitry Andric Res->setName(OpName); 28650fca6ea1SDimitry Andric return Res; 28660fca6ea1SDimitry Andric } 28670fca6ea1SDimitry Andric 28680fca6ea1SDimitry Andric // ?:$name or just $name. 28690fca6ea1SDimitry Andric if (isa<UnsetInit>(TheInit)) { 28700fca6ea1SDimitry Andric if (OpName.empty()) 28710fca6ea1SDimitry Andric error("'?' argument requires a name to match with operand list"); 28720fca6ea1SDimitry Andric TreePatternNodePtr Res = makeIntrusiveRefCnt<TreePatternNode>(TheInit, 1); 28730fca6ea1SDimitry Andric Args.push_back(std::string(OpName)); 28740fca6ea1SDimitry Andric Res->setName(OpName); 28750fca6ea1SDimitry Andric return Res; 28760fca6ea1SDimitry Andric } 28770fca6ea1SDimitry Andric 28780fca6ea1SDimitry Andric if (isa<IntInit>(TheInit) || isa<BitInit>(TheInit)) { 28790fca6ea1SDimitry Andric if (!OpName.empty()) 28800fca6ea1SDimitry Andric error("Constant int or bit argument should not have a name!"); 28810fca6ea1SDimitry Andric if (isa<BitInit>(TheInit)) 28820fca6ea1SDimitry Andric TheInit = TheInit->convertInitializerTo(IntRecTy::get(RK)); 28830fca6ea1SDimitry Andric return makeIntrusiveRefCnt<TreePatternNode>(TheInit, 1); 28840fca6ea1SDimitry Andric } 28850fca6ea1SDimitry Andric 28860fca6ea1SDimitry Andric if (BitsInit *BI = dyn_cast<BitsInit>(TheInit)) { 28870fca6ea1SDimitry Andric // Turn this into an IntInit. 28880fca6ea1SDimitry Andric Init *II = BI->convertInitializerTo(IntRecTy::get(RK)); 28890fca6ea1SDimitry Andric if (!II || !isa<IntInit>(II)) 28900fca6ea1SDimitry Andric error("Bits value must be constants!"); 28910fca6ea1SDimitry Andric return II ? ParseTreePattern(II, OpName) : nullptr; 28920fca6ea1SDimitry Andric } 28930fca6ea1SDimitry Andric 28940fca6ea1SDimitry Andric DagInit *Dag = dyn_cast<DagInit>(TheInit); 28950fca6ea1SDimitry Andric if (!Dag) { 28960fca6ea1SDimitry Andric TheInit->print(errs()); 28970fca6ea1SDimitry Andric error("Pattern has unexpected init kind!"); 28980fca6ea1SDimitry Andric return nullptr; 28990fca6ea1SDimitry Andric } 29000fca6ea1SDimitry Andric DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator()); 29010fca6ea1SDimitry Andric if (!OpDef) { 29020fca6ea1SDimitry Andric error("Pattern has unexpected operator type!"); 29030fca6ea1SDimitry Andric return nullptr; 29040fca6ea1SDimitry Andric } 29050fca6ea1SDimitry Andric Record *Operator = OpDef->getDef(); 29060fca6ea1SDimitry Andric 29070fca6ea1SDimitry Andric if (Operator->isSubClassOf("ValueType")) { 29080fca6ea1SDimitry Andric // If the operator is a ValueType, then this must be "type cast" of a leaf 29090fca6ea1SDimitry Andric // node. 29100fca6ea1SDimitry Andric if (Dag->getNumArgs() != 1) 29110fca6ea1SDimitry Andric error("Type cast only takes one operand!"); 29120fca6ea1SDimitry Andric 29130fca6ea1SDimitry Andric TreePatternNodePtr New = 29140fca6ea1SDimitry Andric ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0)); 29150fca6ea1SDimitry Andric 29160fca6ea1SDimitry Andric // Apply the type cast. 29170fca6ea1SDimitry Andric if (New->getNumTypes() != 1) 29180fca6ea1SDimitry Andric error("Type cast can only have one type!"); 29190fca6ea1SDimitry Andric const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes(); 29200fca6ea1SDimitry Andric New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this); 29210fca6ea1SDimitry Andric 29220fca6ea1SDimitry Andric if (!OpName.empty()) 29230fca6ea1SDimitry Andric error("ValueType cast should not have a name!"); 29240fca6ea1SDimitry Andric return New; 29250fca6ea1SDimitry Andric } 29260fca6ea1SDimitry Andric 29270fca6ea1SDimitry Andric // Verify that this is something that makes sense for an operator. 29280fca6ea1SDimitry Andric if (!Operator->isSubClassOf("PatFrags") && 29290fca6ea1SDimitry Andric !Operator->isSubClassOf("SDNode") && 29300fca6ea1SDimitry Andric !Operator->isSubClassOf("Instruction") && 29310fca6ea1SDimitry Andric !Operator->isSubClassOf("SDNodeXForm") && 29320fca6ea1SDimitry Andric !Operator->isSubClassOf("Intrinsic") && 29330fca6ea1SDimitry Andric !Operator->isSubClassOf("ComplexPattern") && 29340fca6ea1SDimitry Andric Operator->getName() != "set" && Operator->getName() != "implicit") 29350fca6ea1SDimitry Andric error("Unrecognized node '" + Operator->getName() + "'!"); 29360fca6ea1SDimitry Andric 29370fca6ea1SDimitry Andric // Check to see if this is something that is illegal in an input pattern. 29380fca6ea1SDimitry Andric if (isInputPattern) { 29390fca6ea1SDimitry Andric if (Operator->isSubClassOf("Instruction") || 29400fca6ea1SDimitry Andric Operator->isSubClassOf("SDNodeXForm")) 29410fca6ea1SDimitry Andric error("Cannot use '" + Operator->getName() + "' in an input pattern!"); 29420fca6ea1SDimitry Andric } else { 29430fca6ea1SDimitry Andric if (Operator->isSubClassOf("Intrinsic")) 29440fca6ea1SDimitry Andric error("Cannot use '" + Operator->getName() + "' in an output pattern!"); 29450fca6ea1SDimitry Andric 29460fca6ea1SDimitry Andric if (Operator->isSubClassOf("SDNode") && Operator->getName() != "imm" && 29470fca6ea1SDimitry Andric Operator->getName() != "timm" && Operator->getName() != "fpimm" && 29480fca6ea1SDimitry Andric Operator->getName() != "tglobaltlsaddr" && 29490fca6ea1SDimitry Andric Operator->getName() != "tconstpool" && 29500fca6ea1SDimitry Andric Operator->getName() != "tjumptable" && 29510fca6ea1SDimitry Andric Operator->getName() != "tframeindex" && 29520fca6ea1SDimitry Andric Operator->getName() != "texternalsym" && 29530fca6ea1SDimitry Andric Operator->getName() != "tblockaddress" && 29540fca6ea1SDimitry Andric Operator->getName() != "tglobaladdr" && Operator->getName() != "bb" && 29550fca6ea1SDimitry Andric Operator->getName() != "vt" && Operator->getName() != "mcsym") 29560fca6ea1SDimitry Andric error("Cannot use '" + Operator->getName() + "' in an output pattern!"); 29570fca6ea1SDimitry Andric } 29580fca6ea1SDimitry Andric 29590fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> Children; 29600fca6ea1SDimitry Andric 29610fca6ea1SDimitry Andric // Parse all the operands. 29620fca6ea1SDimitry Andric for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) 29630fca6ea1SDimitry Andric Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgNameStr(i))); 29640fca6ea1SDimitry Andric 29650fca6ea1SDimitry Andric // Get the actual number of results before Operator is converted to an 29660fca6ea1SDimitry Andric // intrinsic node (which is hard-coded to have either zero or one result). 29670fca6ea1SDimitry Andric unsigned NumResults = GetNumNodeResults(Operator, CDP); 29680fca6ea1SDimitry Andric 29690fca6ea1SDimitry Andric // If the operator is an intrinsic, then this is just syntactic sugar for 29700fca6ea1SDimitry Andric // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and 29710fca6ea1SDimitry Andric // convert the intrinsic name to a number. 29720fca6ea1SDimitry Andric if (Operator->isSubClassOf("Intrinsic")) { 29730fca6ea1SDimitry Andric const CodeGenIntrinsic &Int = getDAGPatterns().getIntrinsic(Operator); 29740fca6ea1SDimitry Andric unsigned IID = getDAGPatterns().getIntrinsicID(Operator) + 1; 29750fca6ea1SDimitry Andric 29760fca6ea1SDimitry Andric // If this intrinsic returns void, it must have side-effects and thus a 29770fca6ea1SDimitry Andric // chain. 29780fca6ea1SDimitry Andric if (Int.IS.RetTys.empty()) 29790fca6ea1SDimitry Andric Operator = getDAGPatterns().get_intrinsic_void_sdnode(); 29800fca6ea1SDimitry Andric else if (!Int.ME.doesNotAccessMemory() || Int.hasSideEffects) 29810fca6ea1SDimitry Andric // Has side-effects, requires chain. 29820fca6ea1SDimitry Andric Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode(); 29830fca6ea1SDimitry Andric else // Otherwise, no chain. 29840fca6ea1SDimitry Andric Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode(); 29850fca6ea1SDimitry Andric 29860fca6ea1SDimitry Andric Children.insert(Children.begin(), makeIntrusiveRefCnt<TreePatternNode>( 29870fca6ea1SDimitry Andric IntInit::get(RK, IID), 1)); 29880fca6ea1SDimitry Andric } 29890fca6ea1SDimitry Andric 29900fca6ea1SDimitry Andric if (Operator->isSubClassOf("ComplexPattern")) { 29910fca6ea1SDimitry Andric for (unsigned i = 0; i < Children.size(); ++i) { 29920fca6ea1SDimitry Andric TreePatternNodePtr Child = Children[i]; 29930fca6ea1SDimitry Andric 29940fca6ea1SDimitry Andric if (Child->getName().empty()) 29950fca6ea1SDimitry Andric error("All arguments to a ComplexPattern must be named"); 29960fca6ea1SDimitry Andric 29970fca6ea1SDimitry Andric // Check that the ComplexPattern uses are consistent: "(MY_PAT $a, $b)" 29980fca6ea1SDimitry Andric // and "(MY_PAT $b, $a)" should not be allowed in the same pattern; 29990fca6ea1SDimitry Andric // neither should "(MY_PAT_1 $a, $b)" and "(MY_PAT_2 $a, $b)". 30000fca6ea1SDimitry Andric auto OperandId = std::pair(Operator, i); 30010fca6ea1SDimitry Andric auto PrevOp = ComplexPatternOperands.find(Child->getName()); 30020fca6ea1SDimitry Andric if (PrevOp != ComplexPatternOperands.end()) { 30030fca6ea1SDimitry Andric if (PrevOp->getValue() != OperandId) 30040fca6ea1SDimitry Andric error("All ComplexPattern operands must appear consistently: " 30050fca6ea1SDimitry Andric "in the same order in just one ComplexPattern instance."); 30060fca6ea1SDimitry Andric } else 30070fca6ea1SDimitry Andric ComplexPatternOperands[Child->getName()] = OperandId; 30080fca6ea1SDimitry Andric } 30090fca6ea1SDimitry Andric } 30100fca6ea1SDimitry Andric 30110fca6ea1SDimitry Andric TreePatternNodePtr Result = makeIntrusiveRefCnt<TreePatternNode>( 30120fca6ea1SDimitry Andric Operator, std::move(Children), NumResults); 30130fca6ea1SDimitry Andric Result->setName(OpName); 30140fca6ea1SDimitry Andric 30150fca6ea1SDimitry Andric if (Dag->getName()) { 30160fca6ea1SDimitry Andric assert(Result->getName().empty()); 30170fca6ea1SDimitry Andric Result->setName(Dag->getNameStr()); 30180fca6ea1SDimitry Andric } 30190fca6ea1SDimitry Andric return Result; 30200fca6ea1SDimitry Andric } 30210fca6ea1SDimitry Andric 30220fca6ea1SDimitry Andric /// SimplifyTree - See if we can simplify this tree to eliminate something that 30230fca6ea1SDimitry Andric /// will never match in favor of something obvious that will. This is here 30240fca6ea1SDimitry Andric /// strictly as a convenience to target authors because it allows them to write 30250fca6ea1SDimitry Andric /// more type generic things and have useless type casts fold away. 30260fca6ea1SDimitry Andric /// 30270fca6ea1SDimitry Andric /// This returns true if any change is made. 30280fca6ea1SDimitry Andric static bool SimplifyTree(TreePatternNodePtr &N) { 30290fca6ea1SDimitry Andric if (N->isLeaf()) 30300fca6ea1SDimitry Andric return false; 30310fca6ea1SDimitry Andric 30320fca6ea1SDimitry Andric // If we have a bitconvert with a resolved type and if the source and 30330fca6ea1SDimitry Andric // destination types are the same, then the bitconvert is useless, remove it. 30340fca6ea1SDimitry Andric // 30350fca6ea1SDimitry Andric // We make an exception if the types are completely empty. This can come up 30360fca6ea1SDimitry Andric // when the pattern being simplified is in the Fragments list of a PatFrags, 30370fca6ea1SDimitry Andric // so that the operand is just an untyped "node". In that situation we leave 30380fca6ea1SDimitry Andric // bitconverts unsimplified, and simplify them later once the fragment is 30390fca6ea1SDimitry Andric // expanded into its true context. 30400fca6ea1SDimitry Andric if (N->getOperator()->getName() == "bitconvert" && 30410fca6ea1SDimitry Andric N->getExtType(0).isValueTypeByHwMode(false) && 30420fca6ea1SDimitry Andric !N->getExtType(0).empty() && 30430fca6ea1SDimitry Andric N->getExtType(0) == N->getChild(0).getExtType(0) && 30440fca6ea1SDimitry Andric N->getName().empty()) { 3045*71ac745dSDimitry Andric if (!N->getPredicateCalls().empty()) { 3046*71ac745dSDimitry Andric std::string Str; 3047*71ac745dSDimitry Andric raw_string_ostream OS(Str); 3048*71ac745dSDimitry Andric OS << *N 3049*71ac745dSDimitry Andric << "\n trivial bitconvert node should not have predicate calls\n"; 3050*71ac745dSDimitry Andric PrintFatalError(Str); 3051*71ac745dSDimitry Andric return false; 3052*71ac745dSDimitry Andric } 30530fca6ea1SDimitry Andric N = N->getChildShared(0); 30540fca6ea1SDimitry Andric SimplifyTree(N); 30550fca6ea1SDimitry Andric return true; 30560fca6ea1SDimitry Andric } 30570fca6ea1SDimitry Andric 30580fca6ea1SDimitry Andric // Walk all children. 30590fca6ea1SDimitry Andric bool MadeChange = false; 30600fca6ea1SDimitry Andric for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) 30610fca6ea1SDimitry Andric MadeChange |= SimplifyTree(N->getChildSharedPtr(i)); 30620fca6ea1SDimitry Andric 30630fca6ea1SDimitry Andric return MadeChange; 30640fca6ea1SDimitry Andric } 30650fca6ea1SDimitry Andric 30660fca6ea1SDimitry Andric /// InferAllTypes - Infer/propagate as many types throughout the expression 30670fca6ea1SDimitry Andric /// patterns as possible. Return true if all types are inferred, false 30680fca6ea1SDimitry Andric /// otherwise. Flags an error if a type contradiction is found. 30690fca6ea1SDimitry Andric bool TreePattern::InferAllTypes( 30700fca6ea1SDimitry Andric const StringMap<SmallVector<TreePatternNode *, 1>> *InNamedTypes) { 30710fca6ea1SDimitry Andric if (NamedNodes.empty()) 30720fca6ea1SDimitry Andric ComputeNamedNodes(); 30730fca6ea1SDimitry Andric 30740fca6ea1SDimitry Andric bool MadeChange = true; 30750fca6ea1SDimitry Andric while (MadeChange) { 30760fca6ea1SDimitry Andric MadeChange = false; 30770fca6ea1SDimitry Andric for (TreePatternNodePtr &Tree : Trees) { 30780fca6ea1SDimitry Andric MadeChange |= Tree->ApplyTypeConstraints(*this, false); 30790fca6ea1SDimitry Andric MadeChange |= SimplifyTree(Tree); 30800fca6ea1SDimitry Andric } 30810fca6ea1SDimitry Andric 30820fca6ea1SDimitry Andric // If there are constraints on our named nodes, apply them. 30830fca6ea1SDimitry Andric for (auto &Entry : NamedNodes) { 30840fca6ea1SDimitry Andric SmallVectorImpl<TreePatternNode *> &Nodes = Entry.second; 30850fca6ea1SDimitry Andric 30860fca6ea1SDimitry Andric // If we have input named node types, propagate their types to the named 30870fca6ea1SDimitry Andric // values here. 30880fca6ea1SDimitry Andric if (InNamedTypes) { 30890fca6ea1SDimitry Andric if (!InNamedTypes->count(Entry.getKey())) { 30900fca6ea1SDimitry Andric error("Node '" + std::string(Entry.getKey()) + 30910fca6ea1SDimitry Andric "' in output pattern but not input pattern"); 30920fca6ea1SDimitry Andric return true; 30930fca6ea1SDimitry Andric } 30940fca6ea1SDimitry Andric 30950fca6ea1SDimitry Andric const SmallVectorImpl<TreePatternNode *> &InNodes = 30960fca6ea1SDimitry Andric InNamedTypes->find(Entry.getKey())->second; 30970fca6ea1SDimitry Andric 30980fca6ea1SDimitry Andric // The input types should be fully resolved by now. 30990fca6ea1SDimitry Andric for (TreePatternNode *Node : Nodes) { 31000fca6ea1SDimitry Andric // If this node is a register class, and it is the root of the pattern 31010fca6ea1SDimitry Andric // then we're mapping something onto an input register. We allow 31020fca6ea1SDimitry Andric // changing the type of the input register in this case. This allows 31030fca6ea1SDimitry Andric // us to match things like: 31040fca6ea1SDimitry Andric // def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>; 31050fca6ea1SDimitry Andric if (Node == Trees[0].get() && Node->isLeaf()) { 31060fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(Node->getLeafValue()); 31070fca6ea1SDimitry Andric if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || 31080fca6ea1SDimitry Andric DI->getDef()->isSubClassOf("RegisterOperand"))) 31090fca6ea1SDimitry Andric continue; 31100fca6ea1SDimitry Andric } 31110fca6ea1SDimitry Andric 31120fca6ea1SDimitry Andric assert(Node->getNumTypes() == 1 && InNodes[0]->getNumTypes() == 1 && 31130fca6ea1SDimitry Andric "FIXME: cannot name multiple result nodes yet"); 31140fca6ea1SDimitry Andric MadeChange |= 31150fca6ea1SDimitry Andric Node->UpdateNodeType(0, InNodes[0]->getExtType(0), *this); 31160fca6ea1SDimitry Andric } 31170fca6ea1SDimitry Andric } 31180fca6ea1SDimitry Andric 31190fca6ea1SDimitry Andric // If there are multiple nodes with the same name, they must all have the 31200fca6ea1SDimitry Andric // same type. 31210fca6ea1SDimitry Andric if (Entry.second.size() > 1) { 31220fca6ea1SDimitry Andric for (unsigned i = 0, e = Nodes.size() - 1; i != e; ++i) { 31230fca6ea1SDimitry Andric TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i + 1]; 31240fca6ea1SDimitry Andric assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 && 31250fca6ea1SDimitry Andric "FIXME: cannot name multiple result nodes yet"); 31260fca6ea1SDimitry Andric 31270fca6ea1SDimitry Andric MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this); 31280fca6ea1SDimitry Andric MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this); 31290fca6ea1SDimitry Andric } 31300fca6ea1SDimitry Andric } 31310fca6ea1SDimitry Andric } 31320fca6ea1SDimitry Andric } 31330fca6ea1SDimitry Andric 31340fca6ea1SDimitry Andric bool HasUnresolvedTypes = false; 31350fca6ea1SDimitry Andric for (const TreePatternNodePtr &Tree : Trees) 31360fca6ea1SDimitry Andric HasUnresolvedTypes |= Tree->ContainsUnresolvedType(*this); 31370fca6ea1SDimitry Andric return !HasUnresolvedTypes; 31380fca6ea1SDimitry Andric } 31390fca6ea1SDimitry Andric 31400fca6ea1SDimitry Andric void TreePattern::print(raw_ostream &OS) const { 31410fca6ea1SDimitry Andric OS << getRecord()->getName(); 31420fca6ea1SDimitry Andric if (!Args.empty()) { 31430fca6ea1SDimitry Andric OS << "("; 31440fca6ea1SDimitry Andric ListSeparator LS; 31450fca6ea1SDimitry Andric for (const std::string &Arg : Args) 31460fca6ea1SDimitry Andric OS << LS << Arg; 31470fca6ea1SDimitry Andric OS << ")"; 31480fca6ea1SDimitry Andric } 31490fca6ea1SDimitry Andric OS << ": "; 31500fca6ea1SDimitry Andric 31510fca6ea1SDimitry Andric if (Trees.size() > 1) 31520fca6ea1SDimitry Andric OS << "[\n"; 31530fca6ea1SDimitry Andric for (const TreePatternNodePtr &Tree : Trees) { 31540fca6ea1SDimitry Andric OS << "\t"; 31550fca6ea1SDimitry Andric Tree->print(OS); 31560fca6ea1SDimitry Andric OS << "\n"; 31570fca6ea1SDimitry Andric } 31580fca6ea1SDimitry Andric 31590fca6ea1SDimitry Andric if (Trees.size() > 1) 31600fca6ea1SDimitry Andric OS << "]\n"; 31610fca6ea1SDimitry Andric } 31620fca6ea1SDimitry Andric 31630fca6ea1SDimitry Andric void TreePattern::dump() const { print(errs()); } 31640fca6ea1SDimitry Andric 31650fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 31660fca6ea1SDimitry Andric // CodeGenDAGPatterns implementation 31670fca6ea1SDimitry Andric // 31680fca6ea1SDimitry Andric 31690fca6ea1SDimitry Andric CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R, 31700fca6ea1SDimitry Andric PatternRewriterFn PatternRewriter) 31710fca6ea1SDimitry Andric : Records(R), Target(R), LegalVTS(Target.getLegalValueTypes()), 31720fca6ea1SDimitry Andric PatternRewriter(PatternRewriter) { 31730fca6ea1SDimitry Andric 31740fca6ea1SDimitry Andric Intrinsics = CodeGenIntrinsicTable(Records); 31750fca6ea1SDimitry Andric ParseNodeInfo(); 31760fca6ea1SDimitry Andric ParseNodeTransforms(); 31770fca6ea1SDimitry Andric ParseComplexPatterns(); 31780fca6ea1SDimitry Andric ParsePatternFragments(); 31790fca6ea1SDimitry Andric ParseDefaultOperands(); 31800fca6ea1SDimitry Andric ParseInstructions(); 31810fca6ea1SDimitry Andric ParsePatternFragments(/*OutFrags*/ true); 31820fca6ea1SDimitry Andric ParsePatterns(); 31830fca6ea1SDimitry Andric 31840fca6ea1SDimitry Andric // Generate variants. For example, commutative patterns can match 31850fca6ea1SDimitry Andric // multiple ways. Add them to PatternsToMatch as well. 31860fca6ea1SDimitry Andric GenerateVariants(); 31870fca6ea1SDimitry Andric 31880fca6ea1SDimitry Andric // Break patterns with parameterized types into a series of patterns, 31890fca6ea1SDimitry Andric // where each one has a fixed type and is predicated on the conditions 31900fca6ea1SDimitry Andric // of the associated HW mode. 31910fca6ea1SDimitry Andric ExpandHwModeBasedTypes(); 31920fca6ea1SDimitry Andric 31930fca6ea1SDimitry Andric // Infer instruction flags. For example, we can detect loads, 31940fca6ea1SDimitry Andric // stores, and side effects in many cases by examining an 31950fca6ea1SDimitry Andric // instruction's pattern. 31960fca6ea1SDimitry Andric InferInstructionFlags(); 31970fca6ea1SDimitry Andric 31980fca6ea1SDimitry Andric // Verify that instruction flags match the patterns. 31990fca6ea1SDimitry Andric VerifyInstructionFlags(); 32000fca6ea1SDimitry Andric } 32010fca6ea1SDimitry Andric 32020fca6ea1SDimitry Andric Record *CodeGenDAGPatterns::getSDNodeNamed(StringRef Name) const { 32030fca6ea1SDimitry Andric Record *N = Records.getDef(Name); 32040fca6ea1SDimitry Andric if (!N || !N->isSubClassOf("SDNode")) 32050fca6ea1SDimitry Andric PrintFatalError("Error getting SDNode '" + Name + "'!"); 32060fca6ea1SDimitry Andric 32070fca6ea1SDimitry Andric return N; 32080fca6ea1SDimitry Andric } 32090fca6ea1SDimitry Andric 32100fca6ea1SDimitry Andric // Parse all of the SDNode definitions for the target, populating SDNodes. 32110fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseNodeInfo() { 32120fca6ea1SDimitry Andric std::vector<Record *> Nodes = Records.getAllDerivedDefinitions("SDNode"); 32130fca6ea1SDimitry Andric const CodeGenHwModes &CGH = getTargetInfo().getHwModes(); 32140fca6ea1SDimitry Andric 32150fca6ea1SDimitry Andric while (!Nodes.empty()) { 32160fca6ea1SDimitry Andric Record *R = Nodes.back(); 32170fca6ea1SDimitry Andric SDNodes.insert(std::pair(R, SDNodeInfo(R, CGH))); 32180fca6ea1SDimitry Andric Nodes.pop_back(); 32190fca6ea1SDimitry Andric } 32200fca6ea1SDimitry Andric 32210fca6ea1SDimitry Andric // Get the builtin intrinsic nodes. 32220fca6ea1SDimitry Andric intrinsic_void_sdnode = getSDNodeNamed("intrinsic_void"); 32230fca6ea1SDimitry Andric intrinsic_w_chain_sdnode = getSDNodeNamed("intrinsic_w_chain"); 32240fca6ea1SDimitry Andric intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain"); 32250fca6ea1SDimitry Andric } 32260fca6ea1SDimitry Andric 32270fca6ea1SDimitry Andric /// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms 32280fca6ea1SDimitry Andric /// map, and emit them to the file as functions. 32290fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseNodeTransforms() { 32300fca6ea1SDimitry Andric std::vector<Record *> Xforms = 32310fca6ea1SDimitry Andric Records.getAllDerivedDefinitions("SDNodeXForm"); 32320fca6ea1SDimitry Andric while (!Xforms.empty()) { 32330fca6ea1SDimitry Andric Record *XFormNode = Xforms.back(); 32340fca6ea1SDimitry Andric Record *SDNode = XFormNode->getValueAsDef("Opcode"); 32350fca6ea1SDimitry Andric StringRef Code = XFormNode->getValueAsString("XFormFunction"); 32360fca6ea1SDimitry Andric SDNodeXForms.insert( 32370fca6ea1SDimitry Andric std::pair(XFormNode, NodeXForm(SDNode, std::string(Code)))); 32380fca6ea1SDimitry Andric 32390fca6ea1SDimitry Andric Xforms.pop_back(); 32400fca6ea1SDimitry Andric } 32410fca6ea1SDimitry Andric } 32420fca6ea1SDimitry Andric 32430fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseComplexPatterns() { 32440fca6ea1SDimitry Andric std::vector<Record *> AMs = 32450fca6ea1SDimitry Andric Records.getAllDerivedDefinitions("ComplexPattern"); 32460fca6ea1SDimitry Andric while (!AMs.empty()) { 32470fca6ea1SDimitry Andric ComplexPatterns.insert(std::pair(AMs.back(), AMs.back())); 32480fca6ea1SDimitry Andric AMs.pop_back(); 32490fca6ea1SDimitry Andric } 32500fca6ea1SDimitry Andric } 32510fca6ea1SDimitry Andric 32520fca6ea1SDimitry Andric /// ParsePatternFragments - Parse all of the PatFrag definitions in the .td 32530fca6ea1SDimitry Andric /// file, building up the PatternFragments map. After we've collected them all, 32540fca6ea1SDimitry Andric /// inline fragments together as necessary, so that there are no references left 32550fca6ea1SDimitry Andric /// inside a pattern fragment to a pattern fragment. 32560fca6ea1SDimitry Andric /// 32570fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { 32580fca6ea1SDimitry Andric std::vector<Record *> Fragments = 32590fca6ea1SDimitry Andric Records.getAllDerivedDefinitions("PatFrags"); 32600fca6ea1SDimitry Andric 32610fca6ea1SDimitry Andric // First step, parse all of the fragments. 32620fca6ea1SDimitry Andric for (Record *Frag : Fragments) { 32630fca6ea1SDimitry Andric if (OutFrags != Frag->isSubClassOf("OutPatFrag")) 32640fca6ea1SDimitry Andric continue; 32650fca6ea1SDimitry Andric 32660fca6ea1SDimitry Andric ListInit *LI = Frag->getValueAsListInit("Fragments"); 32670fca6ea1SDimitry Andric TreePattern *P = (PatternFragments[Frag] = std::make_unique<TreePattern>( 32680fca6ea1SDimitry Andric Frag, LI, !Frag->isSubClassOf("OutPatFrag"), *this)) 32690fca6ea1SDimitry Andric .get(); 32700fca6ea1SDimitry Andric 32710fca6ea1SDimitry Andric // Validate the argument list, converting it to set, to discard duplicates. 32720fca6ea1SDimitry Andric std::vector<std::string> &Args = P->getArgList(); 32730fca6ea1SDimitry Andric // Copy the args so we can take StringRefs to them. 32740fca6ea1SDimitry Andric auto ArgsCopy = Args; 32750fca6ea1SDimitry Andric SmallDenseSet<StringRef, 4> OperandsSet; 32760fca6ea1SDimitry Andric OperandsSet.insert(ArgsCopy.begin(), ArgsCopy.end()); 32770fca6ea1SDimitry Andric 32780fca6ea1SDimitry Andric if (OperandsSet.count("")) 32790fca6ea1SDimitry Andric P->error("Cannot have unnamed 'node' values in pattern fragment!"); 32800fca6ea1SDimitry Andric 32810fca6ea1SDimitry Andric // Parse the operands list. 32820fca6ea1SDimitry Andric DagInit *OpsList = Frag->getValueAsDag("Operands"); 32830fca6ea1SDimitry Andric DefInit *OpsOp = dyn_cast<DefInit>(OpsList->getOperator()); 32840fca6ea1SDimitry Andric // Special cases: ops == outs == ins. Different names are used to 32850fca6ea1SDimitry Andric // improve readability. 32860fca6ea1SDimitry Andric if (!OpsOp || (OpsOp->getDef()->getName() != "ops" && 32870fca6ea1SDimitry Andric OpsOp->getDef()->getName() != "outs" && 32880fca6ea1SDimitry Andric OpsOp->getDef()->getName() != "ins")) 32890fca6ea1SDimitry Andric P->error("Operands list should start with '(ops ... '!"); 32900fca6ea1SDimitry Andric 32910fca6ea1SDimitry Andric // Copy over the arguments. 32920fca6ea1SDimitry Andric Args.clear(); 32930fca6ea1SDimitry Andric for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) { 32940fca6ea1SDimitry Andric if (!isa<DefInit>(OpsList->getArg(j)) || 32950fca6ea1SDimitry Andric cast<DefInit>(OpsList->getArg(j))->getDef()->getName() != "node") 32960fca6ea1SDimitry Andric P->error("Operands list should all be 'node' values."); 32970fca6ea1SDimitry Andric if (!OpsList->getArgName(j)) 32980fca6ea1SDimitry Andric P->error("Operands list should have names for each operand!"); 32990fca6ea1SDimitry Andric StringRef ArgNameStr = OpsList->getArgNameStr(j); 33000fca6ea1SDimitry Andric if (!OperandsSet.count(ArgNameStr)) 33010fca6ea1SDimitry Andric P->error("'" + ArgNameStr + 33020fca6ea1SDimitry Andric "' does not occur in pattern or was multiply specified!"); 33030fca6ea1SDimitry Andric OperandsSet.erase(ArgNameStr); 33040fca6ea1SDimitry Andric Args.push_back(std::string(ArgNameStr)); 33050fca6ea1SDimitry Andric } 33060fca6ea1SDimitry Andric 33070fca6ea1SDimitry Andric if (!OperandsSet.empty()) 33080fca6ea1SDimitry Andric P->error("Operands list does not contain an entry for operand '" + 33090fca6ea1SDimitry Andric *OperandsSet.begin() + "'!"); 33100fca6ea1SDimitry Andric 33110fca6ea1SDimitry Andric // If there is a node transformation corresponding to this, keep track of 33120fca6ea1SDimitry Andric // it. 33130fca6ea1SDimitry Andric Record *Transform = Frag->getValueAsDef("OperandTransform"); 33140fca6ea1SDimitry Andric if (!getSDNodeTransform(Transform).second.empty()) // not noop xform? 33150fca6ea1SDimitry Andric for (const auto &T : P->getTrees()) 33160fca6ea1SDimitry Andric T->setTransformFn(Transform); 33170fca6ea1SDimitry Andric } 33180fca6ea1SDimitry Andric 33190fca6ea1SDimitry Andric // Now that we've parsed all of the tree fragments, do a closure on them so 33200fca6ea1SDimitry Andric // that there are not references to PatFrags left inside of them. 33210fca6ea1SDimitry Andric for (Record *Frag : Fragments) { 33220fca6ea1SDimitry Andric if (OutFrags != Frag->isSubClassOf("OutPatFrag")) 33230fca6ea1SDimitry Andric continue; 33240fca6ea1SDimitry Andric 33250fca6ea1SDimitry Andric TreePattern &ThePat = *PatternFragments[Frag]; 33260fca6ea1SDimitry Andric ThePat.InlinePatternFragments(); 33270fca6ea1SDimitry Andric 33280fca6ea1SDimitry Andric // Infer as many types as possible. Don't worry about it if we don't infer 33290fca6ea1SDimitry Andric // all of them, some may depend on the inputs of the pattern. Also, don't 33300fca6ea1SDimitry Andric // validate type sets; validation may cause spurious failures e.g. if a 33310fca6ea1SDimitry Andric // fragment needs floating-point types but the current target does not have 33320fca6ea1SDimitry Andric // any (this is only an error if that fragment is ever used!). 33330fca6ea1SDimitry Andric { 33340fca6ea1SDimitry Andric TypeInfer::SuppressValidation SV(ThePat.getInfer()); 33350fca6ea1SDimitry Andric ThePat.InferAllTypes(); 33360fca6ea1SDimitry Andric ThePat.resetError(); 33370fca6ea1SDimitry Andric } 33380fca6ea1SDimitry Andric 33390fca6ea1SDimitry Andric // If debugging, print out the pattern fragment result. 33400fca6ea1SDimitry Andric LLVM_DEBUG(ThePat.dump()); 33410fca6ea1SDimitry Andric } 33420fca6ea1SDimitry Andric } 33430fca6ea1SDimitry Andric 33440fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseDefaultOperands() { 33450fca6ea1SDimitry Andric std::vector<Record *> DefaultOps; 33460fca6ea1SDimitry Andric DefaultOps = Records.getAllDerivedDefinitions("OperandWithDefaultOps"); 33470fca6ea1SDimitry Andric 33480fca6ea1SDimitry Andric // Find some SDNode. 33490fca6ea1SDimitry Andric assert(!SDNodes.empty() && "No SDNodes parsed?"); 33500fca6ea1SDimitry Andric Init *SomeSDNode = DefInit::get(SDNodes.begin()->first); 33510fca6ea1SDimitry Andric 33520fca6ea1SDimitry Andric for (unsigned i = 0, e = DefaultOps.size(); i != e; ++i) { 33530fca6ea1SDimitry Andric DagInit *DefaultInfo = DefaultOps[i]->getValueAsDag("DefaultOps"); 33540fca6ea1SDimitry Andric 33550fca6ea1SDimitry Andric // Clone the DefaultInfo dag node, changing the operator from 'ops' to 33560fca6ea1SDimitry Andric // SomeSDnode so that we can parse this. 33570fca6ea1SDimitry Andric std::vector<std::pair<Init *, StringInit *>> Ops; 33580fca6ea1SDimitry Andric for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op) 33590fca6ea1SDimitry Andric Ops.push_back( 33600fca6ea1SDimitry Andric std::pair(DefaultInfo->getArg(op), DefaultInfo->getArgName(op))); 33610fca6ea1SDimitry Andric DagInit *DI = DagInit::get(SomeSDNode, nullptr, Ops); 33620fca6ea1SDimitry Andric 33630fca6ea1SDimitry Andric // Create a TreePattern to parse this. 33640fca6ea1SDimitry Andric TreePattern P(DefaultOps[i], DI, false, *this); 33650fca6ea1SDimitry Andric assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!"); 33660fca6ea1SDimitry Andric 33670fca6ea1SDimitry Andric // Copy the operands over into a DAGDefaultOperand. 33680fca6ea1SDimitry Andric DAGDefaultOperand DefaultOpInfo; 33690fca6ea1SDimitry Andric 33700fca6ea1SDimitry Andric const TreePatternNodePtr &T = P.getTree(0); 33710fca6ea1SDimitry Andric for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) { 33720fca6ea1SDimitry Andric TreePatternNodePtr TPN = T->getChildShared(op); 33730fca6ea1SDimitry Andric while (TPN->ApplyTypeConstraints(P, false)) 33740fca6ea1SDimitry Andric /* Resolve all types */; 33750fca6ea1SDimitry Andric 33760fca6ea1SDimitry Andric if (TPN->ContainsUnresolvedType(P)) { 33770fca6ea1SDimitry Andric PrintFatalError("Value #" + Twine(i) + " of OperandWithDefaultOps '" + 33780fca6ea1SDimitry Andric DefaultOps[i]->getName() + 33790fca6ea1SDimitry Andric "' doesn't have a concrete type!"); 33800fca6ea1SDimitry Andric } 33810fca6ea1SDimitry Andric DefaultOpInfo.DefaultOps.push_back(std::move(TPN)); 33820fca6ea1SDimitry Andric } 33830fca6ea1SDimitry Andric 33840fca6ea1SDimitry Andric // Insert it into the DefaultOperands map so we can find it later. 33850fca6ea1SDimitry Andric DefaultOperands[DefaultOps[i]] = DefaultOpInfo; 33860fca6ea1SDimitry Andric } 33870fca6ea1SDimitry Andric } 33880fca6ea1SDimitry Andric 33890fca6ea1SDimitry Andric /// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an 33900fca6ea1SDimitry Andric /// instruction input. Return true if this is a real use. 33910fca6ea1SDimitry Andric static bool HandleUse(TreePattern &I, TreePatternNodePtr Pat, 33920fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> &InstInputs) { 33930fca6ea1SDimitry Andric // No name -> not interesting. 33940fca6ea1SDimitry Andric if (Pat->getName().empty()) { 33950fca6ea1SDimitry Andric if (Pat->isLeaf()) { 33960fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue()); 33970fca6ea1SDimitry Andric if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || 33980fca6ea1SDimitry Andric DI->getDef()->isSubClassOf("RegisterOperand"))) 33990fca6ea1SDimitry Andric I.error("Input " + DI->getDef()->getName() + " must be named!"); 34000fca6ea1SDimitry Andric } 34010fca6ea1SDimitry Andric return false; 34020fca6ea1SDimitry Andric } 34030fca6ea1SDimitry Andric 34040fca6ea1SDimitry Andric Record *Rec; 34050fca6ea1SDimitry Andric if (Pat->isLeaf()) { 34060fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue()); 34070fca6ea1SDimitry Andric if (!DI) 34080fca6ea1SDimitry Andric I.error("Input $" + Pat->getName() + " must be an identifier!"); 34090fca6ea1SDimitry Andric Rec = DI->getDef(); 34100fca6ea1SDimitry Andric } else { 34110fca6ea1SDimitry Andric Rec = Pat->getOperator(); 34120fca6ea1SDimitry Andric } 34130fca6ea1SDimitry Andric 34140fca6ea1SDimitry Andric // SRCVALUE nodes are ignored. 34150fca6ea1SDimitry Andric if (Rec->getName() == "srcvalue") 34160fca6ea1SDimitry Andric return false; 34170fca6ea1SDimitry Andric 34180fca6ea1SDimitry Andric TreePatternNodePtr &Slot = InstInputs[Pat->getName()]; 34190fca6ea1SDimitry Andric if (!Slot) { 34200fca6ea1SDimitry Andric Slot = Pat; 34210fca6ea1SDimitry Andric return true; 34220fca6ea1SDimitry Andric } 34230fca6ea1SDimitry Andric Record *SlotRec; 34240fca6ea1SDimitry Andric if (Slot->isLeaf()) { 34250fca6ea1SDimitry Andric SlotRec = cast<DefInit>(Slot->getLeafValue())->getDef(); 34260fca6ea1SDimitry Andric } else { 34270fca6ea1SDimitry Andric assert(Slot->getNumChildren() == 0 && "can't be a use with children!"); 34280fca6ea1SDimitry Andric SlotRec = Slot->getOperator(); 34290fca6ea1SDimitry Andric } 34300fca6ea1SDimitry Andric 34310fca6ea1SDimitry Andric // Ensure that the inputs agree if we've already seen this input. 34320fca6ea1SDimitry Andric if (Rec != SlotRec) 34330fca6ea1SDimitry Andric I.error("All $" + Pat->getName() + " inputs must agree with each other"); 34340fca6ea1SDimitry Andric // Ensure that the types can agree as well. 34350fca6ea1SDimitry Andric Slot->UpdateNodeType(0, Pat->getExtType(0), I); 34360fca6ea1SDimitry Andric Pat->UpdateNodeType(0, Slot->getExtType(0), I); 34370fca6ea1SDimitry Andric if (Slot->getExtTypes() != Pat->getExtTypes()) 34380fca6ea1SDimitry Andric I.error("All $" + Pat->getName() + " inputs must agree with each other"); 34390fca6ea1SDimitry Andric return true; 34400fca6ea1SDimitry Andric } 34410fca6ea1SDimitry Andric 34420fca6ea1SDimitry Andric /// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is 34430fca6ea1SDimitry Andric /// part of "I", the instruction), computing the set of inputs and outputs of 34440fca6ea1SDimitry Andric /// the pattern. Report errors if we see anything naughty. 34450fca6ea1SDimitry Andric void CodeGenDAGPatterns::FindPatternInputsAndOutputs( 34460fca6ea1SDimitry Andric TreePattern &I, TreePatternNodePtr Pat, 34470fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> &InstInputs, 34480fca6ea1SDimitry Andric MapVector<std::string, TreePatternNodePtr, std::map<std::string, unsigned>> 34490fca6ea1SDimitry Andric &InstResults, 34500fca6ea1SDimitry Andric std::vector<Record *> &InstImpResults) { 34510fca6ea1SDimitry Andric 34520fca6ea1SDimitry Andric // The instruction pattern still has unresolved fragments. For *named* 34530fca6ea1SDimitry Andric // nodes we must resolve those here. This may not result in multiple 34540fca6ea1SDimitry Andric // alternatives. 34550fca6ea1SDimitry Andric if (!Pat->getName().empty()) { 34560fca6ea1SDimitry Andric TreePattern SrcPattern(I.getRecord(), Pat, true, *this); 34570fca6ea1SDimitry Andric SrcPattern.InlinePatternFragments(); 34580fca6ea1SDimitry Andric SrcPattern.InferAllTypes(); 34590fca6ea1SDimitry Andric Pat = SrcPattern.getOnlyTree(); 34600fca6ea1SDimitry Andric } 34610fca6ea1SDimitry Andric 34620fca6ea1SDimitry Andric if (Pat->isLeaf()) { 34630fca6ea1SDimitry Andric bool isUse = HandleUse(I, Pat, InstInputs); 34640fca6ea1SDimitry Andric if (!isUse && Pat->getTransformFn()) 34650fca6ea1SDimitry Andric I.error("Cannot specify a transform function for a non-input value!"); 34660fca6ea1SDimitry Andric return; 34670fca6ea1SDimitry Andric } 34680fca6ea1SDimitry Andric 34690fca6ea1SDimitry Andric if (Pat->getOperator()->getName() == "implicit") { 34700fca6ea1SDimitry Andric for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { 34710fca6ea1SDimitry Andric TreePatternNode &Dest = Pat->getChild(i); 34720fca6ea1SDimitry Andric if (!Dest.isLeaf()) 34730fca6ea1SDimitry Andric I.error("implicitly defined value should be a register!"); 34740fca6ea1SDimitry Andric 34750fca6ea1SDimitry Andric DefInit *Val = dyn_cast<DefInit>(Dest.getLeafValue()); 34760fca6ea1SDimitry Andric if (!Val || !Val->getDef()->isSubClassOf("Register")) 34770fca6ea1SDimitry Andric I.error("implicitly defined value should be a register!"); 34780fca6ea1SDimitry Andric if (Val) 34790fca6ea1SDimitry Andric InstImpResults.push_back(Val->getDef()); 34800fca6ea1SDimitry Andric } 34810fca6ea1SDimitry Andric return; 34820fca6ea1SDimitry Andric } 34830fca6ea1SDimitry Andric 34840fca6ea1SDimitry Andric if (Pat->getOperator()->getName() != "set") { 34850fca6ea1SDimitry Andric // If this is not a set, verify that the children nodes are not void typed, 34860fca6ea1SDimitry Andric // and recurse. 34870fca6ea1SDimitry Andric for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { 34880fca6ea1SDimitry Andric if (Pat->getChild(i).getNumTypes() == 0) 34890fca6ea1SDimitry Andric I.error("Cannot have void nodes inside of patterns!"); 34900fca6ea1SDimitry Andric FindPatternInputsAndOutputs(I, Pat->getChildShared(i), InstInputs, 34910fca6ea1SDimitry Andric InstResults, InstImpResults); 34920fca6ea1SDimitry Andric } 34930fca6ea1SDimitry Andric 34940fca6ea1SDimitry Andric // If this is a non-leaf node with no children, treat it basically as if 34950fca6ea1SDimitry Andric // it were a leaf. This handles nodes like (imm). 34960fca6ea1SDimitry Andric bool isUse = HandleUse(I, Pat, InstInputs); 34970fca6ea1SDimitry Andric 34980fca6ea1SDimitry Andric if (!isUse && Pat->getTransformFn()) 34990fca6ea1SDimitry Andric I.error("Cannot specify a transform function for a non-input value!"); 35000fca6ea1SDimitry Andric return; 35010fca6ea1SDimitry Andric } 35020fca6ea1SDimitry Andric 35030fca6ea1SDimitry Andric // Otherwise, this is a set, validate and collect instruction results. 35040fca6ea1SDimitry Andric if (Pat->getNumChildren() == 0) 35050fca6ea1SDimitry Andric I.error("set requires operands!"); 35060fca6ea1SDimitry Andric 35070fca6ea1SDimitry Andric if (Pat->getTransformFn()) 35080fca6ea1SDimitry Andric I.error("Cannot specify a transform function on a set node!"); 35090fca6ea1SDimitry Andric 35100fca6ea1SDimitry Andric // Check the set destinations. 35110fca6ea1SDimitry Andric unsigned NumDests = Pat->getNumChildren() - 1; 35120fca6ea1SDimitry Andric for (unsigned i = 0; i != NumDests; ++i) { 35130fca6ea1SDimitry Andric TreePatternNodePtr Dest = Pat->getChildShared(i); 35140fca6ea1SDimitry Andric // For set destinations we also must resolve fragments here. 35150fca6ea1SDimitry Andric TreePattern DestPattern(I.getRecord(), Dest, false, *this); 35160fca6ea1SDimitry Andric DestPattern.InlinePatternFragments(); 35170fca6ea1SDimitry Andric DestPattern.InferAllTypes(); 35180fca6ea1SDimitry Andric Dest = DestPattern.getOnlyTree(); 35190fca6ea1SDimitry Andric 35200fca6ea1SDimitry Andric if (!Dest->isLeaf()) 35210fca6ea1SDimitry Andric I.error("set destination should be a register!"); 35220fca6ea1SDimitry Andric 35230fca6ea1SDimitry Andric DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue()); 35240fca6ea1SDimitry Andric if (!Val) { 35250fca6ea1SDimitry Andric I.error("set destination should be a register!"); 35260fca6ea1SDimitry Andric continue; 35270fca6ea1SDimitry Andric } 35280fca6ea1SDimitry Andric 35290fca6ea1SDimitry Andric if (Val->getDef()->isSubClassOf("RegisterClass") || 35300fca6ea1SDimitry Andric Val->getDef()->isSubClassOf("ValueType") || 35310fca6ea1SDimitry Andric Val->getDef()->isSubClassOf("RegisterOperand") || 35320fca6ea1SDimitry Andric Val->getDef()->isSubClassOf("PointerLikeRegClass")) { 35330fca6ea1SDimitry Andric if (Dest->getName().empty()) 35340fca6ea1SDimitry Andric I.error("set destination must have a name!"); 35350fca6ea1SDimitry Andric if (InstResults.count(Dest->getName())) 35360fca6ea1SDimitry Andric I.error("cannot set '" + Dest->getName() + "' multiple times"); 35370fca6ea1SDimitry Andric InstResults[Dest->getName()] = Dest; 35380fca6ea1SDimitry Andric } else if (Val->getDef()->isSubClassOf("Register")) { 35390fca6ea1SDimitry Andric InstImpResults.push_back(Val->getDef()); 35400fca6ea1SDimitry Andric } else { 35410fca6ea1SDimitry Andric I.error("set destination should be a register!"); 35420fca6ea1SDimitry Andric } 35430fca6ea1SDimitry Andric } 35440fca6ea1SDimitry Andric 35450fca6ea1SDimitry Andric // Verify and collect info from the computation. 35460fca6ea1SDimitry Andric FindPatternInputsAndOutputs(I, Pat->getChildShared(NumDests), InstInputs, 35470fca6ea1SDimitry Andric InstResults, InstImpResults); 35480fca6ea1SDimitry Andric } 35490fca6ea1SDimitry Andric 35500fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 35510fca6ea1SDimitry Andric // Instruction Analysis 35520fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 35530fca6ea1SDimitry Andric 35540fca6ea1SDimitry Andric class InstAnalyzer { 35550fca6ea1SDimitry Andric const CodeGenDAGPatterns &CDP; 35560fca6ea1SDimitry Andric 35570fca6ea1SDimitry Andric public: 35580fca6ea1SDimitry Andric bool hasSideEffects; 35590fca6ea1SDimitry Andric bool mayStore; 35600fca6ea1SDimitry Andric bool mayLoad; 35610fca6ea1SDimitry Andric bool isBitcast; 35620fca6ea1SDimitry Andric bool isVariadic; 35630fca6ea1SDimitry Andric bool hasChain; 35640fca6ea1SDimitry Andric 35650fca6ea1SDimitry Andric InstAnalyzer(const CodeGenDAGPatterns &cdp) 35660fca6ea1SDimitry Andric : CDP(cdp), hasSideEffects(false), mayStore(false), mayLoad(false), 35670fca6ea1SDimitry Andric isBitcast(false), isVariadic(false), hasChain(false) {} 35680fca6ea1SDimitry Andric 35690fca6ea1SDimitry Andric void Analyze(const PatternToMatch &Pat) { 35700fca6ea1SDimitry Andric const TreePatternNode &N = Pat.getSrcPattern(); 35710fca6ea1SDimitry Andric AnalyzeNode(N); 35720fca6ea1SDimitry Andric // These properties are detected only on the root node. 35730fca6ea1SDimitry Andric isBitcast = IsNodeBitcast(N); 35740fca6ea1SDimitry Andric } 35750fca6ea1SDimitry Andric 35760fca6ea1SDimitry Andric private: 35770fca6ea1SDimitry Andric bool IsNodeBitcast(const TreePatternNode &N) const { 35780fca6ea1SDimitry Andric if (hasSideEffects || mayLoad || mayStore || isVariadic) 35790fca6ea1SDimitry Andric return false; 35800fca6ea1SDimitry Andric 35810fca6ea1SDimitry Andric if (N.isLeaf()) 35820fca6ea1SDimitry Andric return false; 35830fca6ea1SDimitry Andric if (N.getNumChildren() != 1 || !N.getChild(0).isLeaf()) 35840fca6ea1SDimitry Andric return false; 35850fca6ea1SDimitry Andric 35860fca6ea1SDimitry Andric if (N.getOperator()->isSubClassOf("ComplexPattern")) 35870fca6ea1SDimitry Andric return false; 35880fca6ea1SDimitry Andric 35890fca6ea1SDimitry Andric const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N.getOperator()); 35900fca6ea1SDimitry Andric if (OpInfo.getNumResults() != 1 || OpInfo.getNumOperands() != 1) 35910fca6ea1SDimitry Andric return false; 35920fca6ea1SDimitry Andric return OpInfo.getEnumName() == "ISD::BITCAST"; 35930fca6ea1SDimitry Andric } 35940fca6ea1SDimitry Andric 35950fca6ea1SDimitry Andric public: 35960fca6ea1SDimitry Andric void AnalyzeNode(const TreePatternNode &N) { 35970fca6ea1SDimitry Andric if (N.isLeaf()) { 35980fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(N.getLeafValue())) { 35990fca6ea1SDimitry Andric Record *LeafRec = DI->getDef(); 36000fca6ea1SDimitry Andric // Handle ComplexPattern leaves. 36010fca6ea1SDimitry Andric if (LeafRec->isSubClassOf("ComplexPattern")) { 36020fca6ea1SDimitry Andric const ComplexPattern &CP = CDP.getComplexPattern(LeafRec); 36030fca6ea1SDimitry Andric if (CP.hasProperty(SDNPMayStore)) 36040fca6ea1SDimitry Andric mayStore = true; 36050fca6ea1SDimitry Andric if (CP.hasProperty(SDNPMayLoad)) 36060fca6ea1SDimitry Andric mayLoad = true; 36070fca6ea1SDimitry Andric if (CP.hasProperty(SDNPSideEffect)) 36080fca6ea1SDimitry Andric hasSideEffects = true; 36090fca6ea1SDimitry Andric } 36100fca6ea1SDimitry Andric } 36110fca6ea1SDimitry Andric return; 36120fca6ea1SDimitry Andric } 36130fca6ea1SDimitry Andric 36140fca6ea1SDimitry Andric // Analyze children. 36150fca6ea1SDimitry Andric for (unsigned i = 0, e = N.getNumChildren(); i != e; ++i) 36160fca6ea1SDimitry Andric AnalyzeNode(N.getChild(i)); 36170fca6ea1SDimitry Andric 36180fca6ea1SDimitry Andric // Notice properties of the node. 36190fca6ea1SDimitry Andric if (N.NodeHasProperty(SDNPMayStore, CDP)) 36200fca6ea1SDimitry Andric mayStore = true; 36210fca6ea1SDimitry Andric if (N.NodeHasProperty(SDNPMayLoad, CDP)) 36220fca6ea1SDimitry Andric mayLoad = true; 36230fca6ea1SDimitry Andric if (N.NodeHasProperty(SDNPSideEffect, CDP)) 36240fca6ea1SDimitry Andric hasSideEffects = true; 36250fca6ea1SDimitry Andric if (N.NodeHasProperty(SDNPVariadic, CDP)) 36260fca6ea1SDimitry Andric isVariadic = true; 36270fca6ea1SDimitry Andric if (N.NodeHasProperty(SDNPHasChain, CDP)) 36280fca6ea1SDimitry Andric hasChain = true; 36290fca6ea1SDimitry Andric 36300fca6ea1SDimitry Andric if (const CodeGenIntrinsic *IntInfo = N.getIntrinsicInfo(CDP)) { 36310fca6ea1SDimitry Andric ModRefInfo MR = IntInfo->ME.getModRef(); 36320fca6ea1SDimitry Andric // If this is an intrinsic, analyze it. 36330fca6ea1SDimitry Andric if (isRefSet(MR)) 36340fca6ea1SDimitry Andric mayLoad = true; // These may load memory. 36350fca6ea1SDimitry Andric 36360fca6ea1SDimitry Andric if (isModSet(MR)) 36370fca6ea1SDimitry Andric mayStore = true; // Intrinsics that can write to memory are 'mayStore'. 36380fca6ea1SDimitry Andric 36390fca6ea1SDimitry Andric // Consider intrinsics that don't specify any restrictions on memory 36400fca6ea1SDimitry Andric // effects as having a side-effect. 36410fca6ea1SDimitry Andric if (IntInfo->ME == MemoryEffects::unknown() || IntInfo->hasSideEffects) 36420fca6ea1SDimitry Andric hasSideEffects = true; 36430fca6ea1SDimitry Andric } 36440fca6ea1SDimitry Andric } 36450fca6ea1SDimitry Andric }; 36460fca6ea1SDimitry Andric 36470fca6ea1SDimitry Andric static bool InferFromPattern(CodeGenInstruction &InstInfo, 36480fca6ea1SDimitry Andric const InstAnalyzer &PatInfo, Record *PatDef) { 36490fca6ea1SDimitry Andric bool Error = false; 36500fca6ea1SDimitry Andric 36510fca6ea1SDimitry Andric // Remember where InstInfo got its flags. 36520fca6ea1SDimitry Andric if (InstInfo.hasUndefFlags()) 36530fca6ea1SDimitry Andric InstInfo.InferredFrom = PatDef; 36540fca6ea1SDimitry Andric 36550fca6ea1SDimitry Andric // Check explicitly set flags for consistency. 36560fca6ea1SDimitry Andric if (InstInfo.hasSideEffects != PatInfo.hasSideEffects && 36570fca6ea1SDimitry Andric !InstInfo.hasSideEffects_Unset) { 36580fca6ea1SDimitry Andric // Allow explicitly setting hasSideEffects = 1 on instructions, even when 36590fca6ea1SDimitry Andric // the pattern has no side effects. That could be useful for div/rem 36600fca6ea1SDimitry Andric // instructions that may trap. 36610fca6ea1SDimitry Andric if (!InstInfo.hasSideEffects) { 36620fca6ea1SDimitry Andric Error = true; 36630fca6ea1SDimitry Andric PrintError(PatDef->getLoc(), "Pattern doesn't match hasSideEffects = " + 36640fca6ea1SDimitry Andric Twine(InstInfo.hasSideEffects)); 36650fca6ea1SDimitry Andric } 36660fca6ea1SDimitry Andric } 36670fca6ea1SDimitry Andric 36680fca6ea1SDimitry Andric if (InstInfo.mayStore != PatInfo.mayStore && !InstInfo.mayStore_Unset) { 36690fca6ea1SDimitry Andric Error = true; 36700fca6ea1SDimitry Andric PrintError(PatDef->getLoc(), 36710fca6ea1SDimitry Andric "Pattern doesn't match mayStore = " + Twine(InstInfo.mayStore)); 36720fca6ea1SDimitry Andric } 36730fca6ea1SDimitry Andric 36740fca6ea1SDimitry Andric if (InstInfo.mayLoad != PatInfo.mayLoad && !InstInfo.mayLoad_Unset) { 36750fca6ea1SDimitry Andric // Allow explicitly setting mayLoad = 1, even when the pattern has no loads. 36760fca6ea1SDimitry Andric // Some targets translate immediates to loads. 36770fca6ea1SDimitry Andric if (!InstInfo.mayLoad) { 36780fca6ea1SDimitry Andric Error = true; 36790fca6ea1SDimitry Andric PrintError(PatDef->getLoc(), 36800fca6ea1SDimitry Andric "Pattern doesn't match mayLoad = " + Twine(InstInfo.mayLoad)); 36810fca6ea1SDimitry Andric } 36820fca6ea1SDimitry Andric } 36830fca6ea1SDimitry Andric 36840fca6ea1SDimitry Andric // Transfer inferred flags. 36850fca6ea1SDimitry Andric InstInfo.hasSideEffects |= PatInfo.hasSideEffects; 36860fca6ea1SDimitry Andric InstInfo.mayStore |= PatInfo.mayStore; 36870fca6ea1SDimitry Andric InstInfo.mayLoad |= PatInfo.mayLoad; 36880fca6ea1SDimitry Andric 36890fca6ea1SDimitry Andric // These flags are silently added without any verification. 36900fca6ea1SDimitry Andric // FIXME: To match historical behavior of TableGen, for now add those flags 36910fca6ea1SDimitry Andric // only when we're inferring from the primary instruction pattern. 36920fca6ea1SDimitry Andric if (PatDef->isSubClassOf("Instruction")) { 36930fca6ea1SDimitry Andric InstInfo.isBitcast |= PatInfo.isBitcast; 36940fca6ea1SDimitry Andric InstInfo.hasChain |= PatInfo.hasChain; 36950fca6ea1SDimitry Andric InstInfo.hasChain_Inferred = true; 36960fca6ea1SDimitry Andric } 36970fca6ea1SDimitry Andric 36980fca6ea1SDimitry Andric // Don't infer isVariadic. This flag means something different on SDNodes and 36990fca6ea1SDimitry Andric // instructions. For example, a CALL SDNode is variadic because it has the 37000fca6ea1SDimitry Andric // call arguments as operands, but a CALL instruction is not variadic - it 37010fca6ea1SDimitry Andric // has argument registers as implicit, not explicit uses. 37020fca6ea1SDimitry Andric 37030fca6ea1SDimitry Andric return Error; 37040fca6ea1SDimitry Andric } 37050fca6ea1SDimitry Andric 37060fca6ea1SDimitry Andric /// hasNullFragReference - Return true if the DAG has any reference to the 37070fca6ea1SDimitry Andric /// null_frag operator. 37080fca6ea1SDimitry Andric static bool hasNullFragReference(DagInit *DI) { 37090fca6ea1SDimitry Andric DefInit *OpDef = dyn_cast<DefInit>(DI->getOperator()); 37100fca6ea1SDimitry Andric if (!OpDef) 37110fca6ea1SDimitry Andric return false; 37120fca6ea1SDimitry Andric Record *Operator = OpDef->getDef(); 37130fca6ea1SDimitry Andric 37140fca6ea1SDimitry Andric // If this is the null fragment, return true. 37150fca6ea1SDimitry Andric if (Operator->getName() == "null_frag") 37160fca6ea1SDimitry Andric return true; 37170fca6ea1SDimitry Andric // If any of the arguments reference the null fragment, return true. 37180fca6ea1SDimitry Andric for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) { 37190fca6ea1SDimitry Andric if (auto Arg = dyn_cast<DefInit>(DI->getArg(i))) 37200fca6ea1SDimitry Andric if (Arg->getDef()->getName() == "null_frag") 37210fca6ea1SDimitry Andric return true; 37220fca6ea1SDimitry Andric DagInit *Arg = dyn_cast<DagInit>(DI->getArg(i)); 37230fca6ea1SDimitry Andric if (Arg && hasNullFragReference(Arg)) 37240fca6ea1SDimitry Andric return true; 37250fca6ea1SDimitry Andric } 37260fca6ea1SDimitry Andric 37270fca6ea1SDimitry Andric return false; 37280fca6ea1SDimitry Andric } 37290fca6ea1SDimitry Andric 37300fca6ea1SDimitry Andric /// hasNullFragReference - Return true if any DAG in the list references 37310fca6ea1SDimitry Andric /// the null_frag operator. 37320fca6ea1SDimitry Andric static bool hasNullFragReference(ListInit *LI) { 37330fca6ea1SDimitry Andric for (Init *I : LI->getValues()) { 37340fca6ea1SDimitry Andric DagInit *DI = dyn_cast<DagInit>(I); 37350fca6ea1SDimitry Andric assert(DI && "non-dag in an instruction Pattern list?!"); 37360fca6ea1SDimitry Andric if (hasNullFragReference(DI)) 37370fca6ea1SDimitry Andric return true; 37380fca6ea1SDimitry Andric } 37390fca6ea1SDimitry Andric return false; 37400fca6ea1SDimitry Andric } 37410fca6ea1SDimitry Andric 37420fca6ea1SDimitry Andric /// Get all the instructions in a tree. 37430fca6ea1SDimitry Andric static void getInstructionsInTree(TreePatternNode &Tree, 37440fca6ea1SDimitry Andric SmallVectorImpl<Record *> &Instrs) { 37450fca6ea1SDimitry Andric if (Tree.isLeaf()) 37460fca6ea1SDimitry Andric return; 37470fca6ea1SDimitry Andric if (Tree.getOperator()->isSubClassOf("Instruction")) 37480fca6ea1SDimitry Andric Instrs.push_back(Tree.getOperator()); 37490fca6ea1SDimitry Andric for (unsigned i = 0, e = Tree.getNumChildren(); i != e; ++i) 37500fca6ea1SDimitry Andric getInstructionsInTree(Tree.getChild(i), Instrs); 37510fca6ea1SDimitry Andric } 37520fca6ea1SDimitry Andric 37530fca6ea1SDimitry Andric /// Check the class of a pattern leaf node against the instruction operand it 37540fca6ea1SDimitry Andric /// represents. 37550fca6ea1SDimitry Andric static bool checkOperandClass(CGIOperandList::OperandInfo &OI, Record *Leaf) { 37560fca6ea1SDimitry Andric if (OI.Rec == Leaf) 37570fca6ea1SDimitry Andric return true; 37580fca6ea1SDimitry Andric 37590fca6ea1SDimitry Andric // Allow direct value types to be used in instruction set patterns. 37600fca6ea1SDimitry Andric // The type will be checked later. 37610fca6ea1SDimitry Andric if (Leaf->isSubClassOf("ValueType")) 37620fca6ea1SDimitry Andric return true; 37630fca6ea1SDimitry Andric 37640fca6ea1SDimitry Andric // Patterns can also be ComplexPattern instances. 37650fca6ea1SDimitry Andric if (Leaf->isSubClassOf("ComplexPattern")) 37660fca6ea1SDimitry Andric return true; 37670fca6ea1SDimitry Andric 37680fca6ea1SDimitry Andric return false; 37690fca6ea1SDimitry Andric } 37700fca6ea1SDimitry Andric 37710fca6ea1SDimitry Andric void CodeGenDAGPatterns::parseInstructionPattern(CodeGenInstruction &CGI, 37720fca6ea1SDimitry Andric ListInit *Pat, 37730fca6ea1SDimitry Andric DAGInstMap &DAGInsts) { 37740fca6ea1SDimitry Andric 37750fca6ea1SDimitry Andric assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!"); 37760fca6ea1SDimitry Andric 37770fca6ea1SDimitry Andric // Parse the instruction. 37780fca6ea1SDimitry Andric TreePattern I(CGI.TheDef, Pat, true, *this); 37790fca6ea1SDimitry Andric 37800fca6ea1SDimitry Andric // InstInputs - Keep track of all of the inputs of the instruction, along 37810fca6ea1SDimitry Andric // with the record they are declared as. 37820fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> InstInputs; 37830fca6ea1SDimitry Andric 37840fca6ea1SDimitry Andric // InstResults - Keep track of all the virtual registers that are 'set' 37850fca6ea1SDimitry Andric // in the instruction, including what reg class they are. 37860fca6ea1SDimitry Andric MapVector<std::string, TreePatternNodePtr, std::map<std::string, unsigned>> 37870fca6ea1SDimitry Andric InstResults; 37880fca6ea1SDimitry Andric 37890fca6ea1SDimitry Andric std::vector<Record *> InstImpResults; 37900fca6ea1SDimitry Andric 37910fca6ea1SDimitry Andric // Verify that the top-level forms in the instruction are of void type, and 37920fca6ea1SDimitry Andric // fill in the InstResults map. 37930fca6ea1SDimitry Andric SmallString<32> TypesString; 37940fca6ea1SDimitry Andric for (unsigned j = 0, e = I.getNumTrees(); j != e; ++j) { 37950fca6ea1SDimitry Andric TypesString.clear(); 37960fca6ea1SDimitry Andric TreePatternNodePtr Pat = I.getTree(j); 37970fca6ea1SDimitry Andric if (Pat->getNumTypes() != 0) { 37980fca6ea1SDimitry Andric raw_svector_ostream OS(TypesString); 37990fca6ea1SDimitry Andric ListSeparator LS; 38000fca6ea1SDimitry Andric for (unsigned k = 0, ke = Pat->getNumTypes(); k != ke; ++k) { 38010fca6ea1SDimitry Andric OS << LS; 38020fca6ea1SDimitry Andric Pat->getExtType(k).writeToStream(OS); 38030fca6ea1SDimitry Andric } 38040fca6ea1SDimitry Andric I.error("Top-level forms in instruction pattern should have" 38050fca6ea1SDimitry Andric " void types, has types " + 38060fca6ea1SDimitry Andric OS.str()); 38070fca6ea1SDimitry Andric } 38080fca6ea1SDimitry Andric 38090fca6ea1SDimitry Andric // Find inputs and outputs, and verify the structure of the uses/defs. 38100fca6ea1SDimitry Andric FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, 38110fca6ea1SDimitry Andric InstImpResults); 38120fca6ea1SDimitry Andric } 38130fca6ea1SDimitry Andric 38140fca6ea1SDimitry Andric // Now that we have inputs and outputs of the pattern, inspect the operands 38150fca6ea1SDimitry Andric // list for the instruction. This determines the order that operands are 38160fca6ea1SDimitry Andric // added to the machine instruction the node corresponds to. 38170fca6ea1SDimitry Andric unsigned NumResults = InstResults.size(); 38180fca6ea1SDimitry Andric 38190fca6ea1SDimitry Andric // Parse the operands list from the (ops) list, validating it. 38200fca6ea1SDimitry Andric assert(I.getArgList().empty() && "Args list should still be empty here!"); 38210fca6ea1SDimitry Andric 38220fca6ea1SDimitry Andric // Check that all of the results occur first in the list. 38230fca6ea1SDimitry Andric std::vector<Record *> Results; 38240fca6ea1SDimitry Andric std::vector<unsigned> ResultIndices; 38250fca6ea1SDimitry Andric SmallVector<TreePatternNodePtr, 2> ResNodes; 38260fca6ea1SDimitry Andric for (unsigned i = 0; i != NumResults; ++i) { 38270fca6ea1SDimitry Andric if (i == CGI.Operands.size()) { 38280fca6ea1SDimitry Andric const std::string &OpName = 38290fca6ea1SDimitry Andric llvm::find_if( 38300fca6ea1SDimitry Andric InstResults, 38310fca6ea1SDimitry Andric [](const std::pair<std::string, TreePatternNodePtr> &P) { 38320fca6ea1SDimitry Andric return P.second; 38330fca6ea1SDimitry Andric }) 38340fca6ea1SDimitry Andric ->first; 38350fca6ea1SDimitry Andric 38360fca6ea1SDimitry Andric I.error("'" + OpName + "' set but does not appear in operand list!"); 38370fca6ea1SDimitry Andric } 38380fca6ea1SDimitry Andric 38390fca6ea1SDimitry Andric const std::string &OpName = CGI.Operands[i].Name; 38400fca6ea1SDimitry Andric 38410fca6ea1SDimitry Andric // Check that it exists in InstResults. 38420fca6ea1SDimitry Andric auto InstResultIter = InstResults.find(OpName); 38430fca6ea1SDimitry Andric if (InstResultIter == InstResults.end() || !InstResultIter->second) 38440fca6ea1SDimitry Andric I.error("Operand $" + OpName + " does not exist in operand list!"); 38450fca6ea1SDimitry Andric 38460fca6ea1SDimitry Andric TreePatternNodePtr RNode = InstResultIter->second; 38470fca6ea1SDimitry Andric Record *R = cast<DefInit>(RNode->getLeafValue())->getDef(); 38480fca6ea1SDimitry Andric ResNodes.push_back(std::move(RNode)); 38490fca6ea1SDimitry Andric if (!R) 38500fca6ea1SDimitry Andric I.error("Operand $" + OpName + 38510fca6ea1SDimitry Andric " should be a set destination: all " 38520fca6ea1SDimitry Andric "outputs must occur before inputs in operand list!"); 38530fca6ea1SDimitry Andric 38540fca6ea1SDimitry Andric if (!checkOperandClass(CGI.Operands[i], R)) 38550fca6ea1SDimitry Andric I.error("Operand $" + OpName + " class mismatch!"); 38560fca6ea1SDimitry Andric 38570fca6ea1SDimitry Andric // Remember the return type. 38580fca6ea1SDimitry Andric Results.push_back(CGI.Operands[i].Rec); 38590fca6ea1SDimitry Andric 38600fca6ea1SDimitry Andric // Remember the result index. 38610fca6ea1SDimitry Andric ResultIndices.push_back(std::distance(InstResults.begin(), InstResultIter)); 38620fca6ea1SDimitry Andric 38630fca6ea1SDimitry Andric // Okay, this one checks out. 38640fca6ea1SDimitry Andric InstResultIter->second = nullptr; 38650fca6ea1SDimitry Andric } 38660fca6ea1SDimitry Andric 38670fca6ea1SDimitry Andric // Loop over the inputs next. 38680fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> ResultNodeOperands; 38690fca6ea1SDimitry Andric std::vector<Record *> Operands; 38700fca6ea1SDimitry Andric for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { 38710fca6ea1SDimitry Andric CGIOperandList::OperandInfo &Op = CGI.Operands[i]; 38720fca6ea1SDimitry Andric const std::string &OpName = Op.Name; 38730fca6ea1SDimitry Andric if (OpName.empty()) { 38740fca6ea1SDimitry Andric I.error("Operand #" + Twine(i) + " in operands list has no name!"); 38750fca6ea1SDimitry Andric continue; 38760fca6ea1SDimitry Andric } 38770fca6ea1SDimitry Andric 38780fca6ea1SDimitry Andric if (!InstInputs.count(OpName)) { 38790fca6ea1SDimitry Andric // If this is an operand with a DefaultOps set filled in, we can ignore 38800fca6ea1SDimitry Andric // this. When we codegen it, we will do so as always executed. 38810fca6ea1SDimitry Andric if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) { 38820fca6ea1SDimitry Andric // Does it have a non-empty DefaultOps field? If so, ignore this 38830fca6ea1SDimitry Andric // operand. 38840fca6ea1SDimitry Andric if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) 38850fca6ea1SDimitry Andric continue; 38860fca6ea1SDimitry Andric } 38870fca6ea1SDimitry Andric I.error("Operand $" + OpName + 38880fca6ea1SDimitry Andric " does not appear in the instruction pattern"); 38890fca6ea1SDimitry Andric continue; 38900fca6ea1SDimitry Andric } 38910fca6ea1SDimitry Andric TreePatternNodePtr InVal = InstInputs[OpName]; 38920fca6ea1SDimitry Andric InstInputs.erase(OpName); // It occurred, remove from map. 38930fca6ea1SDimitry Andric 38940fca6ea1SDimitry Andric if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) { 38950fca6ea1SDimitry Andric Record *InRec = cast<DefInit>(InVal->getLeafValue())->getDef(); 38960fca6ea1SDimitry Andric if (!checkOperandClass(Op, InRec)) { 38970fca6ea1SDimitry Andric I.error("Operand $" + OpName + 38980fca6ea1SDimitry Andric "'s register class disagrees" 38990fca6ea1SDimitry Andric " between the operand and pattern"); 39000fca6ea1SDimitry Andric continue; 39010fca6ea1SDimitry Andric } 39020fca6ea1SDimitry Andric } 39030fca6ea1SDimitry Andric Operands.push_back(Op.Rec); 39040fca6ea1SDimitry Andric 39050fca6ea1SDimitry Andric // Construct the result for the dest-pattern operand list. 39060fca6ea1SDimitry Andric TreePatternNodePtr OpNode = InVal->clone(); 39070fca6ea1SDimitry Andric 39080fca6ea1SDimitry Andric // No predicate is useful on the result. 39090fca6ea1SDimitry Andric OpNode->clearPredicateCalls(); 39100fca6ea1SDimitry Andric 39110fca6ea1SDimitry Andric // Promote the xform function to be an explicit node if set. 39120fca6ea1SDimitry Andric if (Record *Xform = OpNode->getTransformFn()) { 39130fca6ea1SDimitry Andric OpNode->setTransformFn(nullptr); 39140fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> Children; 39150fca6ea1SDimitry Andric Children.push_back(OpNode); 39160fca6ea1SDimitry Andric OpNode = makeIntrusiveRefCnt<TreePatternNode>(Xform, std::move(Children), 39170fca6ea1SDimitry Andric OpNode->getNumTypes()); 39180fca6ea1SDimitry Andric } 39190fca6ea1SDimitry Andric 39200fca6ea1SDimitry Andric ResultNodeOperands.push_back(std::move(OpNode)); 39210fca6ea1SDimitry Andric } 39220fca6ea1SDimitry Andric 39230fca6ea1SDimitry Andric if (!InstInputs.empty()) 39240fca6ea1SDimitry Andric I.error("Input operand $" + InstInputs.begin()->first + 39250fca6ea1SDimitry Andric " occurs in pattern but not in operands list!"); 39260fca6ea1SDimitry Andric 39270fca6ea1SDimitry Andric TreePatternNodePtr ResultPattern = makeIntrusiveRefCnt<TreePatternNode>( 39280fca6ea1SDimitry Andric I.getRecord(), std::move(ResultNodeOperands), 39290fca6ea1SDimitry Andric GetNumNodeResults(I.getRecord(), *this)); 39300fca6ea1SDimitry Andric // Copy fully inferred output node types to instruction result pattern. 39310fca6ea1SDimitry Andric for (unsigned i = 0; i != NumResults; ++i) { 39320fca6ea1SDimitry Andric assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled"); 39330fca6ea1SDimitry Andric ResultPattern->setType(i, ResNodes[i]->getExtType(0)); 39340fca6ea1SDimitry Andric ResultPattern->setResultIndex(i, ResultIndices[i]); 39350fca6ea1SDimitry Andric } 39360fca6ea1SDimitry Andric 39370fca6ea1SDimitry Andric // FIXME: Assume only the first tree is the pattern. The others are clobber 39380fca6ea1SDimitry Andric // nodes. 39390fca6ea1SDimitry Andric TreePatternNodePtr Pattern = I.getTree(0); 39400fca6ea1SDimitry Andric TreePatternNodePtr SrcPattern; 39410fca6ea1SDimitry Andric if (Pattern->getOperator()->getName() == "set") { 39420fca6ea1SDimitry Andric SrcPattern = Pattern->getChild(Pattern->getNumChildren() - 1).clone(); 39430fca6ea1SDimitry Andric } else { 39440fca6ea1SDimitry Andric // Not a set (store or something?) 39450fca6ea1SDimitry Andric SrcPattern = Pattern; 39460fca6ea1SDimitry Andric } 39470fca6ea1SDimitry Andric 39480fca6ea1SDimitry Andric // Create and insert the instruction. 39490fca6ea1SDimitry Andric // FIXME: InstImpResults should not be part of DAGInstruction. 39500fca6ea1SDimitry Andric Record *R = I.getRecord(); 39510fca6ea1SDimitry Andric DAGInsts.try_emplace(R, std::move(Results), std::move(Operands), 39520fca6ea1SDimitry Andric std::move(InstImpResults), SrcPattern, ResultPattern); 39530fca6ea1SDimitry Andric 39540fca6ea1SDimitry Andric LLVM_DEBUG(I.dump()); 39550fca6ea1SDimitry Andric } 39560fca6ea1SDimitry Andric 39570fca6ea1SDimitry Andric /// ParseInstructions - Parse all of the instructions, inlining and resolving 39580fca6ea1SDimitry Andric /// any fragments involved. This populates the Instructions list with fully 39590fca6ea1SDimitry Andric /// resolved instructions. 39600fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseInstructions() { 39610fca6ea1SDimitry Andric std::vector<Record *> Instrs = 39620fca6ea1SDimitry Andric Records.getAllDerivedDefinitions("Instruction"); 39630fca6ea1SDimitry Andric 39640fca6ea1SDimitry Andric for (Record *Instr : Instrs) { 39650fca6ea1SDimitry Andric ListInit *LI = nullptr; 39660fca6ea1SDimitry Andric 39670fca6ea1SDimitry Andric if (isa<ListInit>(Instr->getValueInit("Pattern"))) 39680fca6ea1SDimitry Andric LI = Instr->getValueAsListInit("Pattern"); 39690fca6ea1SDimitry Andric 39700fca6ea1SDimitry Andric // If there is no pattern, only collect minimal information about the 39710fca6ea1SDimitry Andric // instruction for its operand list. We have to assume that there is one 39720fca6ea1SDimitry Andric // result, as we have no detailed info. A pattern which references the 39730fca6ea1SDimitry Andric // null_frag operator is as-if no pattern were specified. Normally this 39740fca6ea1SDimitry Andric // is from a multiclass expansion w/ a SDPatternOperator passed in as 39750fca6ea1SDimitry Andric // null_frag. 39760fca6ea1SDimitry Andric if (!LI || LI->empty() || hasNullFragReference(LI)) { 39770fca6ea1SDimitry Andric std::vector<Record *> Results; 39780fca6ea1SDimitry Andric std::vector<Record *> Operands; 39790fca6ea1SDimitry Andric 39800fca6ea1SDimitry Andric CodeGenInstruction &InstInfo = Target.getInstruction(Instr); 39810fca6ea1SDimitry Andric 39820fca6ea1SDimitry Andric if (InstInfo.Operands.size() != 0) { 39830fca6ea1SDimitry Andric for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j) 39840fca6ea1SDimitry Andric Results.push_back(InstInfo.Operands[j].Rec); 39850fca6ea1SDimitry Andric 39860fca6ea1SDimitry Andric // The rest are inputs. 39870fca6ea1SDimitry Andric for (unsigned j = InstInfo.Operands.NumDefs, 39880fca6ea1SDimitry Andric e = InstInfo.Operands.size(); 39890fca6ea1SDimitry Andric j < e; ++j) 39900fca6ea1SDimitry Andric Operands.push_back(InstInfo.Operands[j].Rec); 39910fca6ea1SDimitry Andric } 39920fca6ea1SDimitry Andric 39930fca6ea1SDimitry Andric // Create and insert the instruction. 39940fca6ea1SDimitry Andric Instructions.try_emplace(Instr, std::move(Results), std::move(Operands), 39950fca6ea1SDimitry Andric std::vector<Record *>()); 39960fca6ea1SDimitry Andric continue; // no pattern. 39970fca6ea1SDimitry Andric } 39980fca6ea1SDimitry Andric 39990fca6ea1SDimitry Andric CodeGenInstruction &CGI = Target.getInstruction(Instr); 40000fca6ea1SDimitry Andric parseInstructionPattern(CGI, LI, Instructions); 40010fca6ea1SDimitry Andric } 40020fca6ea1SDimitry Andric 40030fca6ea1SDimitry Andric // If we can, convert the instructions to be patterns that are matched! 40040fca6ea1SDimitry Andric for (auto &Entry : Instructions) { 40050fca6ea1SDimitry Andric Record *Instr = Entry.first; 40060fca6ea1SDimitry Andric DAGInstruction &TheInst = Entry.second; 40070fca6ea1SDimitry Andric TreePatternNodePtr SrcPattern = TheInst.getSrcPattern(); 40080fca6ea1SDimitry Andric TreePatternNodePtr ResultPattern = TheInst.getResultPattern(); 40090fca6ea1SDimitry Andric 40100fca6ea1SDimitry Andric if (SrcPattern && ResultPattern) { 40110fca6ea1SDimitry Andric TreePattern Pattern(Instr, SrcPattern, true, *this); 40120fca6ea1SDimitry Andric TreePattern Result(Instr, ResultPattern, false, *this); 40130fca6ea1SDimitry Andric ParseOnePattern(Instr, Pattern, Result, TheInst.getImpResults()); 40140fca6ea1SDimitry Andric } 40150fca6ea1SDimitry Andric } 40160fca6ea1SDimitry Andric } 40170fca6ea1SDimitry Andric 40180fca6ea1SDimitry Andric typedef std::pair<TreePatternNode *, unsigned> NameRecord; 40190fca6ea1SDimitry Andric 40200fca6ea1SDimitry Andric static void FindNames(TreePatternNode &P, 40210fca6ea1SDimitry Andric std::map<std::string, NameRecord> &Names, 40220fca6ea1SDimitry Andric TreePattern *PatternTop) { 40230fca6ea1SDimitry Andric if (!P.getName().empty()) { 40240fca6ea1SDimitry Andric NameRecord &Rec = Names[P.getName()]; 40250fca6ea1SDimitry Andric // If this is the first instance of the name, remember the node. 40260fca6ea1SDimitry Andric if (Rec.second++ == 0) 40270fca6ea1SDimitry Andric Rec.first = &P; 40280fca6ea1SDimitry Andric else if (Rec.first->getExtTypes() != P.getExtTypes()) 40290fca6ea1SDimitry Andric PatternTop->error("repetition of value: $" + P.getName() + 40300fca6ea1SDimitry Andric " where different uses have different types!"); 40310fca6ea1SDimitry Andric } 40320fca6ea1SDimitry Andric 40330fca6ea1SDimitry Andric if (!P.isLeaf()) { 40340fca6ea1SDimitry Andric for (unsigned i = 0, e = P.getNumChildren(); i != e; ++i) 40350fca6ea1SDimitry Andric FindNames(P.getChild(i), Names, PatternTop); 40360fca6ea1SDimitry Andric } 40370fca6ea1SDimitry Andric } 40380fca6ea1SDimitry Andric 40390fca6ea1SDimitry Andric void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, 40400fca6ea1SDimitry Andric PatternToMatch &&PTM) { 40410fca6ea1SDimitry Andric // Do some sanity checking on the pattern we're about to match. 40420fca6ea1SDimitry Andric std::string Reason; 40430fca6ea1SDimitry Andric if (!PTM.getSrcPattern().canPatternMatch(Reason, *this)) { 40440fca6ea1SDimitry Andric PrintWarning(Pattern->getRecord()->getLoc(), 40450fca6ea1SDimitry Andric Twine("Pattern can never match: ") + Reason); 40460fca6ea1SDimitry Andric return; 40470fca6ea1SDimitry Andric } 40480fca6ea1SDimitry Andric 40490fca6ea1SDimitry Andric // If the source pattern's root is a complex pattern, that complex pattern 40500fca6ea1SDimitry Andric // must specify the nodes it can potentially match. 40510fca6ea1SDimitry Andric if (const ComplexPattern *CP = 40520fca6ea1SDimitry Andric PTM.getSrcPattern().getComplexPatternInfo(*this)) 40530fca6ea1SDimitry Andric if (CP->getRootNodes().empty()) 40540fca6ea1SDimitry Andric Pattern->error("ComplexPattern at root must specify list of opcodes it" 40550fca6ea1SDimitry Andric " could match"); 40560fca6ea1SDimitry Andric 40570fca6ea1SDimitry Andric // Find all of the named values in the input and output, ensure they have the 40580fca6ea1SDimitry Andric // same type. 40590fca6ea1SDimitry Andric std::map<std::string, NameRecord> SrcNames, DstNames; 40600fca6ea1SDimitry Andric FindNames(PTM.getSrcPattern(), SrcNames, Pattern); 40610fca6ea1SDimitry Andric FindNames(PTM.getDstPattern(), DstNames, Pattern); 40620fca6ea1SDimitry Andric 40630fca6ea1SDimitry Andric // Scan all of the named values in the destination pattern, rejecting them if 40640fca6ea1SDimitry Andric // they don't exist in the input pattern. 40650fca6ea1SDimitry Andric for (const auto &Entry : DstNames) { 40660fca6ea1SDimitry Andric if (SrcNames[Entry.first].first == nullptr) 40670fca6ea1SDimitry Andric Pattern->error("Pattern has input without matching name in output: $" + 40680fca6ea1SDimitry Andric Entry.first); 40690fca6ea1SDimitry Andric } 40700fca6ea1SDimitry Andric 40710fca6ea1SDimitry Andric // Scan all of the named values in the source pattern, rejecting them if the 40720fca6ea1SDimitry Andric // name isn't used in the dest, and isn't used to tie two values together. 40730fca6ea1SDimitry Andric for (const auto &Entry : SrcNames) 40740fca6ea1SDimitry Andric if (DstNames[Entry.first].first == nullptr && 40750fca6ea1SDimitry Andric SrcNames[Entry.first].second == 1) 40760fca6ea1SDimitry Andric Pattern->error("Pattern has dead named input: $" + Entry.first); 40770fca6ea1SDimitry Andric 40780fca6ea1SDimitry Andric PatternsToMatch.push_back(std::move(PTM)); 40790fca6ea1SDimitry Andric } 40800fca6ea1SDimitry Andric 40810fca6ea1SDimitry Andric void CodeGenDAGPatterns::InferInstructionFlags() { 40820fca6ea1SDimitry Andric ArrayRef<const CodeGenInstruction *> Instructions = 40830fca6ea1SDimitry Andric Target.getInstructionsByEnumValue(); 40840fca6ea1SDimitry Andric 40850fca6ea1SDimitry Andric unsigned Errors = 0; 40860fca6ea1SDimitry Andric 40870fca6ea1SDimitry Andric // Try to infer flags from all patterns in PatternToMatch. These include 40880fca6ea1SDimitry Andric // both the primary instruction patterns (which always come first) and 40890fca6ea1SDimitry Andric // patterns defined outside the instruction. 40900fca6ea1SDimitry Andric for (const PatternToMatch &PTM : ptms()) { 40910fca6ea1SDimitry Andric // We can only infer from single-instruction patterns, otherwise we won't 40920fca6ea1SDimitry Andric // know which instruction should get the flags. 40930fca6ea1SDimitry Andric SmallVector<Record *, 8> PatInstrs; 40940fca6ea1SDimitry Andric getInstructionsInTree(PTM.getDstPattern(), PatInstrs); 40950fca6ea1SDimitry Andric if (PatInstrs.size() != 1) 40960fca6ea1SDimitry Andric continue; 40970fca6ea1SDimitry Andric 40980fca6ea1SDimitry Andric // Get the single instruction. 40990fca6ea1SDimitry Andric CodeGenInstruction &InstInfo = Target.getInstruction(PatInstrs.front()); 41000fca6ea1SDimitry Andric 41010fca6ea1SDimitry Andric // Only infer properties from the first pattern. We'll verify the others. 41020fca6ea1SDimitry Andric if (InstInfo.InferredFrom) 41030fca6ea1SDimitry Andric continue; 41040fca6ea1SDimitry Andric 41050fca6ea1SDimitry Andric InstAnalyzer PatInfo(*this); 41060fca6ea1SDimitry Andric PatInfo.Analyze(PTM); 41070fca6ea1SDimitry Andric Errors += InferFromPattern(InstInfo, PatInfo, PTM.getSrcRecord()); 41080fca6ea1SDimitry Andric } 41090fca6ea1SDimitry Andric 41100fca6ea1SDimitry Andric if (Errors) 41110fca6ea1SDimitry Andric PrintFatalError("pattern conflicts"); 41120fca6ea1SDimitry Andric 41130fca6ea1SDimitry Andric // If requested by the target, guess any undefined properties. 41140fca6ea1SDimitry Andric if (Target.guessInstructionProperties()) { 41150fca6ea1SDimitry Andric for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { 41160fca6ea1SDimitry Andric CodeGenInstruction *InstInfo = 41170fca6ea1SDimitry Andric const_cast<CodeGenInstruction *>(Instructions[i]); 41180fca6ea1SDimitry Andric if (InstInfo->InferredFrom) 41190fca6ea1SDimitry Andric continue; 41200fca6ea1SDimitry Andric // The mayLoad and mayStore flags default to false. 41210fca6ea1SDimitry Andric // Conservatively assume hasSideEffects if it wasn't explicit. 41220fca6ea1SDimitry Andric if (InstInfo->hasSideEffects_Unset) 41230fca6ea1SDimitry Andric InstInfo->hasSideEffects = true; 41240fca6ea1SDimitry Andric } 41250fca6ea1SDimitry Andric return; 41260fca6ea1SDimitry Andric } 41270fca6ea1SDimitry Andric 41280fca6ea1SDimitry Andric // Complain about any flags that are still undefined. 41290fca6ea1SDimitry Andric for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { 41300fca6ea1SDimitry Andric CodeGenInstruction *InstInfo = 41310fca6ea1SDimitry Andric const_cast<CodeGenInstruction *>(Instructions[i]); 41320fca6ea1SDimitry Andric if (InstInfo->InferredFrom) 41330fca6ea1SDimitry Andric continue; 41340fca6ea1SDimitry Andric if (InstInfo->hasSideEffects_Unset) 41350fca6ea1SDimitry Andric PrintError(InstInfo->TheDef->getLoc(), 41360fca6ea1SDimitry Andric "Can't infer hasSideEffects from patterns"); 41370fca6ea1SDimitry Andric if (InstInfo->mayStore_Unset) 41380fca6ea1SDimitry Andric PrintError(InstInfo->TheDef->getLoc(), 41390fca6ea1SDimitry Andric "Can't infer mayStore from patterns"); 41400fca6ea1SDimitry Andric if (InstInfo->mayLoad_Unset) 41410fca6ea1SDimitry Andric PrintError(InstInfo->TheDef->getLoc(), 41420fca6ea1SDimitry Andric "Can't infer mayLoad from patterns"); 41430fca6ea1SDimitry Andric } 41440fca6ea1SDimitry Andric } 41450fca6ea1SDimitry Andric 41460fca6ea1SDimitry Andric /// Verify instruction flags against pattern node properties. 41470fca6ea1SDimitry Andric void CodeGenDAGPatterns::VerifyInstructionFlags() { 41480fca6ea1SDimitry Andric unsigned Errors = 0; 41490fca6ea1SDimitry Andric for (const PatternToMatch &PTM : ptms()) { 41500fca6ea1SDimitry Andric SmallVector<Record *, 8> Instrs; 41510fca6ea1SDimitry Andric getInstructionsInTree(PTM.getDstPattern(), Instrs); 41520fca6ea1SDimitry Andric if (Instrs.empty()) 41530fca6ea1SDimitry Andric continue; 41540fca6ea1SDimitry Andric 41550fca6ea1SDimitry Andric // Count the number of instructions with each flag set. 41560fca6ea1SDimitry Andric unsigned NumSideEffects = 0; 41570fca6ea1SDimitry Andric unsigned NumStores = 0; 41580fca6ea1SDimitry Andric unsigned NumLoads = 0; 41590fca6ea1SDimitry Andric for (const Record *Instr : Instrs) { 41600fca6ea1SDimitry Andric const CodeGenInstruction &InstInfo = Target.getInstruction(Instr); 41610fca6ea1SDimitry Andric NumSideEffects += InstInfo.hasSideEffects; 41620fca6ea1SDimitry Andric NumStores += InstInfo.mayStore; 41630fca6ea1SDimitry Andric NumLoads += InstInfo.mayLoad; 41640fca6ea1SDimitry Andric } 41650fca6ea1SDimitry Andric 41660fca6ea1SDimitry Andric // Analyze the source pattern. 41670fca6ea1SDimitry Andric InstAnalyzer PatInfo(*this); 41680fca6ea1SDimitry Andric PatInfo.Analyze(PTM); 41690fca6ea1SDimitry Andric 41700fca6ea1SDimitry Andric // Collect error messages. 41710fca6ea1SDimitry Andric SmallVector<std::string, 4> Msgs; 41720fca6ea1SDimitry Andric 41730fca6ea1SDimitry Andric // Check for missing flags in the output. 41740fca6ea1SDimitry Andric // Permit extra flags for now at least. 41750fca6ea1SDimitry Andric if (PatInfo.hasSideEffects && !NumSideEffects) 41760fca6ea1SDimitry Andric Msgs.push_back("pattern has side effects, but hasSideEffects isn't set"); 41770fca6ea1SDimitry Andric 41780fca6ea1SDimitry Andric // Don't verify store flags on instructions with side effects. At least for 41790fca6ea1SDimitry Andric // intrinsics, side effects implies mayStore. 41800fca6ea1SDimitry Andric if (!PatInfo.hasSideEffects && PatInfo.mayStore && !NumStores) 41810fca6ea1SDimitry Andric Msgs.push_back("pattern may store, but mayStore isn't set"); 41820fca6ea1SDimitry Andric 41830fca6ea1SDimitry Andric // Similarly, mayStore implies mayLoad on intrinsics. 41840fca6ea1SDimitry Andric if (!PatInfo.mayStore && PatInfo.mayLoad && !NumLoads) 41850fca6ea1SDimitry Andric Msgs.push_back("pattern may load, but mayLoad isn't set"); 41860fca6ea1SDimitry Andric 41870fca6ea1SDimitry Andric // Print error messages. 41880fca6ea1SDimitry Andric if (Msgs.empty()) 41890fca6ea1SDimitry Andric continue; 41900fca6ea1SDimitry Andric ++Errors; 41910fca6ea1SDimitry Andric 41920fca6ea1SDimitry Andric for (const std::string &Msg : Msgs) 41930fca6ea1SDimitry Andric PrintError( 41940fca6ea1SDimitry Andric PTM.getSrcRecord()->getLoc(), 41950fca6ea1SDimitry Andric Twine(Msg) + " on the " + 41960fca6ea1SDimitry Andric (Instrs.size() == 1 ? "instruction" : "output instructions")); 41970fca6ea1SDimitry Andric // Provide the location of the relevant instruction definitions. 41980fca6ea1SDimitry Andric for (const Record *Instr : Instrs) { 41990fca6ea1SDimitry Andric if (Instr != PTM.getSrcRecord()) 42000fca6ea1SDimitry Andric PrintError(Instr->getLoc(), "defined here"); 42010fca6ea1SDimitry Andric const CodeGenInstruction &InstInfo = Target.getInstruction(Instr); 42020fca6ea1SDimitry Andric if (InstInfo.InferredFrom && InstInfo.InferredFrom != InstInfo.TheDef && 42030fca6ea1SDimitry Andric InstInfo.InferredFrom != PTM.getSrcRecord()) 42040fca6ea1SDimitry Andric PrintError(InstInfo.InferredFrom->getLoc(), "inferred from pattern"); 42050fca6ea1SDimitry Andric } 42060fca6ea1SDimitry Andric } 42070fca6ea1SDimitry Andric if (Errors) 42080fca6ea1SDimitry Andric PrintFatalError("Errors in DAG patterns"); 42090fca6ea1SDimitry Andric } 42100fca6ea1SDimitry Andric 42110fca6ea1SDimitry Andric /// Given a pattern result with an unresolved type, see if we can find one 42120fca6ea1SDimitry Andric /// instruction with an unresolved result type. Force this result type to an 42130fca6ea1SDimitry Andric /// arbitrary element if it's possible types to converge results. 42140fca6ea1SDimitry Andric static bool ForceArbitraryInstResultType(TreePatternNode &N, TreePattern &TP) { 42150fca6ea1SDimitry Andric if (N.isLeaf()) 42160fca6ea1SDimitry Andric return false; 42170fca6ea1SDimitry Andric 42180fca6ea1SDimitry Andric // Analyze children. 42190fca6ea1SDimitry Andric for (unsigned i = 0, e = N.getNumChildren(); i != e; ++i) 42200fca6ea1SDimitry Andric if (ForceArbitraryInstResultType(N.getChild(i), TP)) 42210fca6ea1SDimitry Andric return true; 42220fca6ea1SDimitry Andric 42230fca6ea1SDimitry Andric if (!N.getOperator()->isSubClassOf("Instruction")) 42240fca6ea1SDimitry Andric return false; 42250fca6ea1SDimitry Andric 42260fca6ea1SDimitry Andric // If this type is already concrete or completely unknown we can't do 42270fca6ea1SDimitry Andric // anything. 42280fca6ea1SDimitry Andric TypeInfer &TI = TP.getInfer(); 42290fca6ea1SDimitry Andric for (unsigned i = 0, e = N.getNumTypes(); i != e; ++i) { 42300fca6ea1SDimitry Andric if (N.getExtType(i).empty() || TI.isConcrete(N.getExtType(i), false)) 42310fca6ea1SDimitry Andric continue; 42320fca6ea1SDimitry Andric 42330fca6ea1SDimitry Andric // Otherwise, force its type to an arbitrary choice. 42340fca6ea1SDimitry Andric if (TI.forceArbitrary(N.getExtType(i))) 42350fca6ea1SDimitry Andric return true; 42360fca6ea1SDimitry Andric } 42370fca6ea1SDimitry Andric 42380fca6ea1SDimitry Andric return false; 42390fca6ea1SDimitry Andric } 42400fca6ea1SDimitry Andric 42410fca6ea1SDimitry Andric // Promote xform function to be an explicit node wherever set. 42420fca6ea1SDimitry Andric static TreePatternNodePtr PromoteXForms(TreePatternNodePtr N) { 42430fca6ea1SDimitry Andric if (Record *Xform = N->getTransformFn()) { 42440fca6ea1SDimitry Andric N->setTransformFn(nullptr); 42450fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> Children; 42460fca6ea1SDimitry Andric Children.push_back(PromoteXForms(N)); 42470fca6ea1SDimitry Andric return makeIntrusiveRefCnt<TreePatternNode>(Xform, std::move(Children), 42480fca6ea1SDimitry Andric N->getNumTypes()); 42490fca6ea1SDimitry Andric } 42500fca6ea1SDimitry Andric 42510fca6ea1SDimitry Andric if (!N->isLeaf()) 42520fca6ea1SDimitry Andric for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { 42530fca6ea1SDimitry Andric TreePatternNodePtr Child = N->getChildShared(i); 42540fca6ea1SDimitry Andric N->setChild(i, PromoteXForms(Child)); 42550fca6ea1SDimitry Andric } 42560fca6ea1SDimitry Andric return N; 42570fca6ea1SDimitry Andric } 42580fca6ea1SDimitry Andric 42590fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParseOnePattern( 42600fca6ea1SDimitry Andric Record *TheDef, TreePattern &Pattern, TreePattern &Result, 42610fca6ea1SDimitry Andric const std::vector<Record *> &InstImpResults, bool ShouldIgnore) { 42620fca6ea1SDimitry Andric 42630fca6ea1SDimitry Andric // Inline pattern fragments and expand multiple alternatives. 42640fca6ea1SDimitry Andric Pattern.InlinePatternFragments(); 42650fca6ea1SDimitry Andric Result.InlinePatternFragments(); 42660fca6ea1SDimitry Andric 42670fca6ea1SDimitry Andric if (Result.getNumTrees() != 1) 42680fca6ea1SDimitry Andric Result.error("Cannot use multi-alternative fragments in result pattern!"); 42690fca6ea1SDimitry Andric 42700fca6ea1SDimitry Andric // Infer types. 42710fca6ea1SDimitry Andric bool IterateInference; 42720fca6ea1SDimitry Andric bool InferredAllPatternTypes, InferredAllResultTypes; 42730fca6ea1SDimitry Andric do { 42740fca6ea1SDimitry Andric // Infer as many types as possible. If we cannot infer all of them, we 42750fca6ea1SDimitry Andric // can never do anything with this pattern: report it to the user. 42760fca6ea1SDimitry Andric InferredAllPatternTypes = 42770fca6ea1SDimitry Andric Pattern.InferAllTypes(&Pattern.getNamedNodesMap()); 42780fca6ea1SDimitry Andric 42790fca6ea1SDimitry Andric // Infer as many types as possible. If we cannot infer all of them, we 42800fca6ea1SDimitry Andric // can never do anything with this pattern: report it to the user. 42810fca6ea1SDimitry Andric InferredAllResultTypes = Result.InferAllTypes(&Pattern.getNamedNodesMap()); 42820fca6ea1SDimitry Andric 42830fca6ea1SDimitry Andric IterateInference = false; 42840fca6ea1SDimitry Andric 42850fca6ea1SDimitry Andric // Apply the type of the result to the source pattern. This helps us 42860fca6ea1SDimitry Andric // resolve cases where the input type is known to be a pointer type (which 42870fca6ea1SDimitry Andric // is considered resolved), but the result knows it needs to be 32- or 42880fca6ea1SDimitry Andric // 64-bits. Infer the other way for good measure. 42890fca6ea1SDimitry Andric for (const auto &T : Pattern.getTrees()) 42900fca6ea1SDimitry Andric for (unsigned i = 0, e = std::min(Result.getOnlyTree()->getNumTypes(), 42910fca6ea1SDimitry Andric T->getNumTypes()); 42920fca6ea1SDimitry Andric i != e; ++i) { 42930fca6ea1SDimitry Andric IterateInference |= 42940fca6ea1SDimitry Andric T->UpdateNodeType(i, Result.getOnlyTree()->getExtType(i), Result); 42950fca6ea1SDimitry Andric IterateInference |= 42960fca6ea1SDimitry Andric Result.getOnlyTree()->UpdateNodeType(i, T->getExtType(i), Result); 42970fca6ea1SDimitry Andric } 42980fca6ea1SDimitry Andric 42990fca6ea1SDimitry Andric // If our iteration has converged and the input pattern's types are fully 43000fca6ea1SDimitry Andric // resolved but the result pattern is not fully resolved, we may have a 43010fca6ea1SDimitry Andric // situation where we have two instructions in the result pattern and 43020fca6ea1SDimitry Andric // the instructions require a common register class, but don't care about 43030fca6ea1SDimitry Andric // what actual MVT is used. This is actually a bug in our modelling: 43040fca6ea1SDimitry Andric // output patterns should have register classes, not MVTs. 43050fca6ea1SDimitry Andric // 43060fca6ea1SDimitry Andric // In any case, to handle this, we just go through and disambiguate some 43070fca6ea1SDimitry Andric // arbitrary types to the result pattern's nodes. 43080fca6ea1SDimitry Andric if (!IterateInference && InferredAllPatternTypes && !InferredAllResultTypes) 43090fca6ea1SDimitry Andric IterateInference = 43100fca6ea1SDimitry Andric ForceArbitraryInstResultType(*Result.getTree(0), Result); 43110fca6ea1SDimitry Andric } while (IterateInference); 43120fca6ea1SDimitry Andric 43130fca6ea1SDimitry Andric // Verify that we inferred enough types that we can do something with the 43140fca6ea1SDimitry Andric // pattern and result. If these fire the user has to add type casts. 43150fca6ea1SDimitry Andric if (!InferredAllPatternTypes) 43160fca6ea1SDimitry Andric Pattern.error("Could not infer all types in pattern!"); 43170fca6ea1SDimitry Andric if (!InferredAllResultTypes) { 43180fca6ea1SDimitry Andric Pattern.dump(); 43190fca6ea1SDimitry Andric Result.error("Could not infer all types in pattern result!"); 43200fca6ea1SDimitry Andric } 43210fca6ea1SDimitry Andric 43220fca6ea1SDimitry Andric // Promote xform function to be an explicit node wherever set. 43230fca6ea1SDimitry Andric TreePatternNodePtr DstShared = PromoteXForms(Result.getOnlyTree()); 43240fca6ea1SDimitry Andric 43250fca6ea1SDimitry Andric TreePattern Temp(Result.getRecord(), DstShared, false, *this); 43260fca6ea1SDimitry Andric Temp.InferAllTypes(); 43270fca6ea1SDimitry Andric 43280fca6ea1SDimitry Andric ListInit *Preds = TheDef->getValueAsListInit("Predicates"); 43290fca6ea1SDimitry Andric int Complexity = TheDef->getValueAsInt("AddedComplexity"); 43300fca6ea1SDimitry Andric 43310fca6ea1SDimitry Andric if (PatternRewriter) 43320fca6ea1SDimitry Andric PatternRewriter(&Pattern); 43330fca6ea1SDimitry Andric 43340fca6ea1SDimitry Andric // A pattern may end up with an "impossible" type, i.e. a situation 43350fca6ea1SDimitry Andric // where all types have been eliminated for some node in this pattern. 43360fca6ea1SDimitry Andric // This could occur for intrinsics that only make sense for a specific 43370fca6ea1SDimitry Andric // value type, and use a specific register class. If, for some mode, 43380fca6ea1SDimitry Andric // that register class does not accept that type, the type inference 43390fca6ea1SDimitry Andric // will lead to a contradiction, which is not an error however, but 43400fca6ea1SDimitry Andric // a sign that this pattern will simply never match. 43410fca6ea1SDimitry Andric if (Temp.getOnlyTree()->hasPossibleType()) { 43420fca6ea1SDimitry Andric for (const auto &T : Pattern.getTrees()) { 43430fca6ea1SDimitry Andric if (T->hasPossibleType()) 43440fca6ea1SDimitry Andric AddPatternToMatch(&Pattern, 43450fca6ea1SDimitry Andric PatternToMatch(TheDef, Preds, T, Temp.getOnlyTree(), 43460fca6ea1SDimitry Andric InstImpResults, Complexity, 43470fca6ea1SDimitry Andric TheDef->getID(), ShouldIgnore)); 43480fca6ea1SDimitry Andric } 43490fca6ea1SDimitry Andric } else { 43500fca6ea1SDimitry Andric // Show a message about a dropped pattern with some info to make it 43510fca6ea1SDimitry Andric // easier to identify it in the .td files. 43520fca6ea1SDimitry Andric LLVM_DEBUG({ 43530fca6ea1SDimitry Andric dbgs() << "Dropping: "; 43540fca6ea1SDimitry Andric Pattern.dump(); 43550fca6ea1SDimitry Andric Temp.getOnlyTree()->dump(); 43560fca6ea1SDimitry Andric dbgs() << "\n"; 43570fca6ea1SDimitry Andric }); 43580fca6ea1SDimitry Andric } 43590fca6ea1SDimitry Andric } 43600fca6ea1SDimitry Andric 43610fca6ea1SDimitry Andric void CodeGenDAGPatterns::ParsePatterns() { 43620fca6ea1SDimitry Andric std::vector<Record *> Patterns = Records.getAllDerivedDefinitions("Pattern"); 43630fca6ea1SDimitry Andric 43640fca6ea1SDimitry Andric for (Record *CurPattern : Patterns) { 43650fca6ea1SDimitry Andric DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch"); 43660fca6ea1SDimitry Andric 43670fca6ea1SDimitry Andric // If the pattern references the null_frag, there's nothing to do. 43680fca6ea1SDimitry Andric if (hasNullFragReference(Tree)) 43690fca6ea1SDimitry Andric continue; 43700fca6ea1SDimitry Andric 43710fca6ea1SDimitry Andric TreePattern Pattern(CurPattern, Tree, true, *this); 43720fca6ea1SDimitry Andric 43730fca6ea1SDimitry Andric ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); 43740fca6ea1SDimitry Andric if (LI->empty()) 43750fca6ea1SDimitry Andric continue; // no pattern. 43760fca6ea1SDimitry Andric 43770fca6ea1SDimitry Andric // Parse the instruction. 43780fca6ea1SDimitry Andric TreePattern Result(CurPattern, LI, false, *this); 43790fca6ea1SDimitry Andric 43800fca6ea1SDimitry Andric if (Result.getNumTrees() != 1) 43810fca6ea1SDimitry Andric Result.error("Cannot handle instructions producing instructions " 43820fca6ea1SDimitry Andric "with temporaries yet!"); 43830fca6ea1SDimitry Andric 43840fca6ea1SDimitry Andric // Validate that the input pattern is correct. 43850fca6ea1SDimitry Andric std::map<std::string, TreePatternNodePtr> InstInputs; 43860fca6ea1SDimitry Andric MapVector<std::string, TreePatternNodePtr, std::map<std::string, unsigned>> 43870fca6ea1SDimitry Andric InstResults; 43880fca6ea1SDimitry Andric std::vector<Record *> InstImpResults; 43890fca6ea1SDimitry Andric for (unsigned j = 0, ee = Pattern.getNumTrees(); j != ee; ++j) 43900fca6ea1SDimitry Andric FindPatternInputsAndOutputs(Pattern, Pattern.getTree(j), InstInputs, 43910fca6ea1SDimitry Andric InstResults, InstImpResults); 43920fca6ea1SDimitry Andric 43930fca6ea1SDimitry Andric ParseOnePattern(CurPattern, Pattern, Result, InstImpResults, 43940fca6ea1SDimitry Andric CurPattern->getValueAsBit("GISelShouldIgnore")); 43950fca6ea1SDimitry Andric } 43960fca6ea1SDimitry Andric } 43970fca6ea1SDimitry Andric 43980fca6ea1SDimitry Andric static void collectModes(std::set<unsigned> &Modes, const TreePatternNode &N) { 43990fca6ea1SDimitry Andric for (const TypeSetByHwMode &VTS : N.getExtTypes()) 44000fca6ea1SDimitry Andric for (const auto &I : VTS) 44010fca6ea1SDimitry Andric Modes.insert(I.first); 44020fca6ea1SDimitry Andric 44030fca6ea1SDimitry Andric for (unsigned i = 0, e = N.getNumChildren(); i != e; ++i) 44040fca6ea1SDimitry Andric collectModes(Modes, N.getChild(i)); 44050fca6ea1SDimitry Andric } 44060fca6ea1SDimitry Andric 44070fca6ea1SDimitry Andric void CodeGenDAGPatterns::ExpandHwModeBasedTypes() { 44080fca6ea1SDimitry Andric const CodeGenHwModes &CGH = getTargetInfo().getHwModes(); 44090fca6ea1SDimitry Andric if (CGH.getNumModeIds() == 1) 44100fca6ea1SDimitry Andric return; 44110fca6ea1SDimitry Andric 44120fca6ea1SDimitry Andric std::vector<PatternToMatch> Copy; 44130fca6ea1SDimitry Andric PatternsToMatch.swap(Copy); 44140fca6ea1SDimitry Andric 44150fca6ea1SDimitry Andric auto AppendPattern = [this](PatternToMatch &P, unsigned Mode, 44160fca6ea1SDimitry Andric StringRef Check) { 44170fca6ea1SDimitry Andric TreePatternNodePtr NewSrc = P.getSrcPattern().clone(); 44180fca6ea1SDimitry Andric TreePatternNodePtr NewDst = P.getDstPattern().clone(); 44190fca6ea1SDimitry Andric if (!NewSrc->setDefaultMode(Mode) || !NewDst->setDefaultMode(Mode)) { 44200fca6ea1SDimitry Andric return; 44210fca6ea1SDimitry Andric } 44220fca6ea1SDimitry Andric 44230fca6ea1SDimitry Andric PatternsToMatch.emplace_back( 44240fca6ea1SDimitry Andric P.getSrcRecord(), P.getPredicates(), std::move(NewSrc), 44250fca6ea1SDimitry Andric std::move(NewDst), P.getDstRegs(), P.getAddedComplexity(), 44260fca6ea1SDimitry Andric Record::getNewUID(Records), P.getGISelShouldIgnore(), Check); 44270fca6ea1SDimitry Andric }; 44280fca6ea1SDimitry Andric 44290fca6ea1SDimitry Andric for (PatternToMatch &P : Copy) { 44300fca6ea1SDimitry Andric const TreePatternNode *SrcP = nullptr, *DstP = nullptr; 44310fca6ea1SDimitry Andric if (P.getSrcPattern().hasProperTypeByHwMode()) 44320fca6ea1SDimitry Andric SrcP = &P.getSrcPattern(); 44330fca6ea1SDimitry Andric if (P.getDstPattern().hasProperTypeByHwMode()) 44340fca6ea1SDimitry Andric DstP = &P.getDstPattern(); 44350fca6ea1SDimitry Andric if (!SrcP && !DstP) { 44360fca6ea1SDimitry Andric PatternsToMatch.push_back(P); 44370fca6ea1SDimitry Andric continue; 44380fca6ea1SDimitry Andric } 44390fca6ea1SDimitry Andric 44400fca6ea1SDimitry Andric std::set<unsigned> Modes; 44410fca6ea1SDimitry Andric if (SrcP) 44420fca6ea1SDimitry Andric collectModes(Modes, *SrcP); 44430fca6ea1SDimitry Andric if (DstP) 44440fca6ea1SDimitry Andric collectModes(Modes, *DstP); 44450fca6ea1SDimitry Andric 44460fca6ea1SDimitry Andric // The predicate for the default mode needs to be constructed for each 44470fca6ea1SDimitry Andric // pattern separately. 44480fca6ea1SDimitry Andric // Since not all modes must be present in each pattern, if a mode m is 44490fca6ea1SDimitry Andric // absent, then there is no point in constructing a check for m. If such 44500fca6ea1SDimitry Andric // a check was created, it would be equivalent to checking the default 44510fca6ea1SDimitry Andric // mode, except not all modes' predicates would be a part of the checking 44520fca6ea1SDimitry Andric // code. The subsequently generated check for the default mode would then 44530fca6ea1SDimitry Andric // have the exact same patterns, but a different predicate code. To avoid 44540fca6ea1SDimitry Andric // duplicated patterns with different predicate checks, construct the 44550fca6ea1SDimitry Andric // default check as a negation of all predicates that are actually present 44560fca6ea1SDimitry Andric // in the source/destination patterns. 44570fca6ea1SDimitry Andric SmallString<128> DefaultCheck; 44580fca6ea1SDimitry Andric 44590fca6ea1SDimitry Andric for (unsigned M : Modes) { 44600fca6ea1SDimitry Andric if (M == DefaultMode) 44610fca6ea1SDimitry Andric continue; 44620fca6ea1SDimitry Andric 44630fca6ea1SDimitry Andric // Fill the map entry for this mode. 44640fca6ea1SDimitry Andric const HwMode &HM = CGH.getMode(M); 44650fca6ea1SDimitry Andric AppendPattern(P, M, HM.Predicates); 44660fca6ea1SDimitry Andric 44670fca6ea1SDimitry Andric // Add negations of the HM's predicates to the default predicate. 44680fca6ea1SDimitry Andric if (!DefaultCheck.empty()) 44690fca6ea1SDimitry Andric DefaultCheck += " && "; 44700fca6ea1SDimitry Andric DefaultCheck += "!("; 44710fca6ea1SDimitry Andric DefaultCheck += HM.Predicates; 44720fca6ea1SDimitry Andric DefaultCheck += ")"; 44730fca6ea1SDimitry Andric } 44740fca6ea1SDimitry Andric 44750fca6ea1SDimitry Andric bool HasDefault = Modes.count(DefaultMode); 44760fca6ea1SDimitry Andric if (HasDefault) 44770fca6ea1SDimitry Andric AppendPattern(P, DefaultMode, DefaultCheck); 44780fca6ea1SDimitry Andric } 44790fca6ea1SDimitry Andric } 44800fca6ea1SDimitry Andric 44810fca6ea1SDimitry Andric /// Dependent variable map for CodeGenDAGPattern variant generation 44820fca6ea1SDimitry Andric typedef StringMap<int> DepVarMap; 44830fca6ea1SDimitry Andric 44840fca6ea1SDimitry Andric static void FindDepVarsOf(TreePatternNode &N, DepVarMap &DepMap) { 44850fca6ea1SDimitry Andric if (N.isLeaf()) { 44860fca6ea1SDimitry Andric if (N.hasName() && isa<DefInit>(N.getLeafValue())) 44870fca6ea1SDimitry Andric DepMap[N.getName()]++; 44880fca6ea1SDimitry Andric } else { 44890fca6ea1SDimitry Andric for (size_t i = 0, e = N.getNumChildren(); i != e; ++i) 44900fca6ea1SDimitry Andric FindDepVarsOf(N.getChild(i), DepMap); 44910fca6ea1SDimitry Andric } 44920fca6ea1SDimitry Andric } 44930fca6ea1SDimitry Andric 44940fca6ea1SDimitry Andric /// Find dependent variables within child patterns 44950fca6ea1SDimitry Andric static void FindDepVars(TreePatternNode &N, MultipleUseVarSet &DepVars) { 44960fca6ea1SDimitry Andric DepVarMap depcounts; 44970fca6ea1SDimitry Andric FindDepVarsOf(N, depcounts); 44980fca6ea1SDimitry Andric for (const auto &Pair : depcounts) { 44990fca6ea1SDimitry Andric if (Pair.getValue() > 1) 45000fca6ea1SDimitry Andric DepVars.insert(Pair.getKey()); 45010fca6ea1SDimitry Andric } 45020fca6ea1SDimitry Andric } 45030fca6ea1SDimitry Andric 45040fca6ea1SDimitry Andric #ifndef NDEBUG 45050fca6ea1SDimitry Andric /// Dump the dependent variable set: 45060fca6ea1SDimitry Andric static void DumpDepVars(MultipleUseVarSet &DepVars) { 45070fca6ea1SDimitry Andric if (DepVars.empty()) { 45080fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "<empty set>"); 45090fca6ea1SDimitry Andric } else { 45100fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "[ "); 45110fca6ea1SDimitry Andric for (const auto &DepVar : DepVars) { 45120fca6ea1SDimitry Andric LLVM_DEBUG(errs() << DepVar.getKey() << " "); 45130fca6ea1SDimitry Andric } 45140fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "]"); 45150fca6ea1SDimitry Andric } 45160fca6ea1SDimitry Andric } 45170fca6ea1SDimitry Andric #endif 45180fca6ea1SDimitry Andric 45190fca6ea1SDimitry Andric /// CombineChildVariants - Given a bunch of permutations of each child of the 45200fca6ea1SDimitry Andric /// 'operator' node, put them together in all possible ways. 45210fca6ea1SDimitry Andric static void CombineChildVariants( 45220fca6ea1SDimitry Andric TreePatternNodePtr Orig, 45230fca6ea1SDimitry Andric const std::vector<std::vector<TreePatternNodePtr>> &ChildVariants, 45240fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> &OutVariants, CodeGenDAGPatterns &CDP, 45250fca6ea1SDimitry Andric const MultipleUseVarSet &DepVars) { 45260fca6ea1SDimitry Andric // Make sure that each operand has at least one variant to choose from. 45270fca6ea1SDimitry Andric for (const auto &Variants : ChildVariants) 45280fca6ea1SDimitry Andric if (Variants.empty()) 45290fca6ea1SDimitry Andric return; 45300fca6ea1SDimitry Andric 45310fca6ea1SDimitry Andric // The end result is an all-pairs construction of the resultant pattern. 45320fca6ea1SDimitry Andric std::vector<unsigned> Idxs(ChildVariants.size()); 45330fca6ea1SDimitry Andric bool NotDone; 45340fca6ea1SDimitry Andric do { 45350fca6ea1SDimitry Andric #ifndef NDEBUG 45360fca6ea1SDimitry Andric LLVM_DEBUG(if (!Idxs.empty()) { 45370fca6ea1SDimitry Andric errs() << Orig->getOperator()->getName() << ": Idxs = [ "; 45380fca6ea1SDimitry Andric for (unsigned Idx : Idxs) { 45390fca6ea1SDimitry Andric errs() << Idx << " "; 45400fca6ea1SDimitry Andric } 45410fca6ea1SDimitry Andric errs() << "]\n"; 45420fca6ea1SDimitry Andric }); 45430fca6ea1SDimitry Andric #endif 45440fca6ea1SDimitry Andric // Create the variant and add it to the output list. 45450fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> NewChildren; 45460fca6ea1SDimitry Andric NewChildren.reserve(ChildVariants.size()); 45470fca6ea1SDimitry Andric for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) 45480fca6ea1SDimitry Andric NewChildren.push_back(ChildVariants[i][Idxs[i]]); 45490fca6ea1SDimitry Andric TreePatternNodePtr R = makeIntrusiveRefCnt<TreePatternNode>( 45500fca6ea1SDimitry Andric Orig->getOperator(), std::move(NewChildren), Orig->getNumTypes()); 45510fca6ea1SDimitry Andric 45520fca6ea1SDimitry Andric // Copy over properties. 45530fca6ea1SDimitry Andric R->setName(Orig->getName()); 45540fca6ea1SDimitry Andric R->setNamesAsPredicateArg(Orig->getNamesAsPredicateArg()); 45550fca6ea1SDimitry Andric R->setPredicateCalls(Orig->getPredicateCalls()); 45560fca6ea1SDimitry Andric R->setGISelFlagsRecord(Orig->getGISelFlagsRecord()); 45570fca6ea1SDimitry Andric R->setTransformFn(Orig->getTransformFn()); 45580fca6ea1SDimitry Andric for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i) 45590fca6ea1SDimitry Andric R->setType(i, Orig->getExtType(i)); 45600fca6ea1SDimitry Andric 45610fca6ea1SDimitry Andric // If this pattern cannot match, do not include it as a variant. 45620fca6ea1SDimitry Andric std::string ErrString; 45630fca6ea1SDimitry Andric // Scan to see if this pattern has already been emitted. We can get 45640fca6ea1SDimitry Andric // duplication due to things like commuting: 45650fca6ea1SDimitry Andric // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a) 45660fca6ea1SDimitry Andric // which are the same pattern. Ignore the dups. 45670fca6ea1SDimitry Andric if (R->canPatternMatch(ErrString, CDP) && 45680fca6ea1SDimitry Andric none_of(OutVariants, [&](TreePatternNodePtr Variant) { 45690fca6ea1SDimitry Andric return R->isIsomorphicTo(*Variant, DepVars); 45700fca6ea1SDimitry Andric })) 45710fca6ea1SDimitry Andric OutVariants.push_back(R); 45720fca6ea1SDimitry Andric 45730fca6ea1SDimitry Andric // Increment indices to the next permutation by incrementing the 45740fca6ea1SDimitry Andric // indices from last index backward, e.g., generate the sequence 45750fca6ea1SDimitry Andric // [0, 0], [0, 1], [1, 0], [1, 1]. 45760fca6ea1SDimitry Andric int IdxsIdx; 45770fca6ea1SDimitry Andric for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) { 45780fca6ea1SDimitry Andric if (++Idxs[IdxsIdx] == ChildVariants[IdxsIdx].size()) 45790fca6ea1SDimitry Andric Idxs[IdxsIdx] = 0; 45800fca6ea1SDimitry Andric else 45810fca6ea1SDimitry Andric break; 45820fca6ea1SDimitry Andric } 45830fca6ea1SDimitry Andric NotDone = (IdxsIdx >= 0); 45840fca6ea1SDimitry Andric } while (NotDone); 45850fca6ea1SDimitry Andric } 45860fca6ea1SDimitry Andric 45870fca6ea1SDimitry Andric /// CombineChildVariants - A helper function for binary operators. 45880fca6ea1SDimitry Andric /// 45890fca6ea1SDimitry Andric static void CombineChildVariants(TreePatternNodePtr Orig, 45900fca6ea1SDimitry Andric const std::vector<TreePatternNodePtr> &LHS, 45910fca6ea1SDimitry Andric const std::vector<TreePatternNodePtr> &RHS, 45920fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> &OutVariants, 45930fca6ea1SDimitry Andric CodeGenDAGPatterns &CDP, 45940fca6ea1SDimitry Andric const MultipleUseVarSet &DepVars) { 45950fca6ea1SDimitry Andric std::vector<std::vector<TreePatternNodePtr>> ChildVariants; 45960fca6ea1SDimitry Andric ChildVariants.push_back(LHS); 45970fca6ea1SDimitry Andric ChildVariants.push_back(RHS); 45980fca6ea1SDimitry Andric CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars); 45990fca6ea1SDimitry Andric } 46000fca6ea1SDimitry Andric 46010fca6ea1SDimitry Andric static void 46020fca6ea1SDimitry Andric GatherChildrenOfAssociativeOpcode(TreePatternNodePtr N, 46030fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> &Children) { 46040fca6ea1SDimitry Andric assert(N->getNumChildren() == 2 && 46050fca6ea1SDimitry Andric "Associative but doesn't have 2 children!"); 46060fca6ea1SDimitry Andric Record *Operator = N->getOperator(); 46070fca6ea1SDimitry Andric 46080fca6ea1SDimitry Andric // Only permit raw nodes. 46090fca6ea1SDimitry Andric if (!N->getName().empty() || !N->getPredicateCalls().empty() || 46100fca6ea1SDimitry Andric N->getTransformFn()) { 46110fca6ea1SDimitry Andric Children.push_back(N); 46120fca6ea1SDimitry Andric return; 46130fca6ea1SDimitry Andric } 46140fca6ea1SDimitry Andric 46150fca6ea1SDimitry Andric if (N->getChild(0).isLeaf() || N->getChild(0).getOperator() != Operator) 46160fca6ea1SDimitry Andric Children.push_back(N->getChildShared(0)); 46170fca6ea1SDimitry Andric else 46180fca6ea1SDimitry Andric GatherChildrenOfAssociativeOpcode(N->getChildShared(0), Children); 46190fca6ea1SDimitry Andric 46200fca6ea1SDimitry Andric if (N->getChild(1).isLeaf() || N->getChild(1).getOperator() != Operator) 46210fca6ea1SDimitry Andric Children.push_back(N->getChildShared(1)); 46220fca6ea1SDimitry Andric else 46230fca6ea1SDimitry Andric GatherChildrenOfAssociativeOpcode(N->getChildShared(1), Children); 46240fca6ea1SDimitry Andric } 46250fca6ea1SDimitry Andric 46260fca6ea1SDimitry Andric /// GenerateVariantsOf - Given a pattern N, generate all permutations we can of 46270fca6ea1SDimitry Andric /// the (potentially recursive) pattern by using algebraic laws. 46280fca6ea1SDimitry Andric /// 46290fca6ea1SDimitry Andric static void GenerateVariantsOf(TreePatternNodePtr N, 46300fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> &OutVariants, 46310fca6ea1SDimitry Andric CodeGenDAGPatterns &CDP, 46320fca6ea1SDimitry Andric const MultipleUseVarSet &DepVars) { 46330fca6ea1SDimitry Andric // We cannot permute leaves or ComplexPattern uses. 46340fca6ea1SDimitry Andric if (N->isLeaf() || N->getOperator()->isSubClassOf("ComplexPattern")) { 46350fca6ea1SDimitry Andric OutVariants.push_back(N); 46360fca6ea1SDimitry Andric return; 46370fca6ea1SDimitry Andric } 46380fca6ea1SDimitry Andric 46390fca6ea1SDimitry Andric // Look up interesting info about the node. 46400fca6ea1SDimitry Andric const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(N->getOperator()); 46410fca6ea1SDimitry Andric 46420fca6ea1SDimitry Andric // If this node is associative, re-associate. 46430fca6ea1SDimitry Andric if (NodeInfo.hasProperty(SDNPAssociative)) { 46440fca6ea1SDimitry Andric // Re-associate by pulling together all of the linked operators 46450fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> MaximalChildren; 46460fca6ea1SDimitry Andric GatherChildrenOfAssociativeOpcode(N, MaximalChildren); 46470fca6ea1SDimitry Andric 46480fca6ea1SDimitry Andric // Only handle child sizes of 3. Otherwise we'll end up trying too many 46490fca6ea1SDimitry Andric // permutations. 46500fca6ea1SDimitry Andric if (MaximalChildren.size() == 3) { 46510fca6ea1SDimitry Andric // Find the variants of all of our maximal children. 46520fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> AVariants, BVariants, CVariants; 46530fca6ea1SDimitry Andric GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars); 46540fca6ea1SDimitry Andric GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars); 46550fca6ea1SDimitry Andric GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars); 46560fca6ea1SDimitry Andric 46570fca6ea1SDimitry Andric // There are only two ways we can permute the tree: 46580fca6ea1SDimitry Andric // (A op B) op C and A op (B op C) 46590fca6ea1SDimitry Andric // Within these forms, we can also permute A/B/C. 46600fca6ea1SDimitry Andric 46610fca6ea1SDimitry Andric // Generate legal pair permutations of A/B/C. 46620fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> ABVariants; 46630fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> BAVariants; 46640fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> ACVariants; 46650fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> CAVariants; 46660fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> BCVariants; 46670fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> CBVariants; 46680fca6ea1SDimitry Andric CombineChildVariants(N, AVariants, BVariants, ABVariants, CDP, DepVars); 46690fca6ea1SDimitry Andric CombineChildVariants(N, BVariants, AVariants, BAVariants, CDP, DepVars); 46700fca6ea1SDimitry Andric CombineChildVariants(N, AVariants, CVariants, ACVariants, CDP, DepVars); 46710fca6ea1SDimitry Andric CombineChildVariants(N, CVariants, AVariants, CAVariants, CDP, DepVars); 46720fca6ea1SDimitry Andric CombineChildVariants(N, BVariants, CVariants, BCVariants, CDP, DepVars); 46730fca6ea1SDimitry Andric CombineChildVariants(N, CVariants, BVariants, CBVariants, CDP, DepVars); 46740fca6ea1SDimitry Andric 46750fca6ea1SDimitry Andric // Combine those into the result: (x op x) op x 46760fca6ea1SDimitry Andric CombineChildVariants(N, ABVariants, CVariants, OutVariants, CDP, DepVars); 46770fca6ea1SDimitry Andric CombineChildVariants(N, BAVariants, CVariants, OutVariants, CDP, DepVars); 46780fca6ea1SDimitry Andric CombineChildVariants(N, ACVariants, BVariants, OutVariants, CDP, DepVars); 46790fca6ea1SDimitry Andric CombineChildVariants(N, CAVariants, BVariants, OutVariants, CDP, DepVars); 46800fca6ea1SDimitry Andric CombineChildVariants(N, BCVariants, AVariants, OutVariants, CDP, DepVars); 46810fca6ea1SDimitry Andric CombineChildVariants(N, CBVariants, AVariants, OutVariants, CDP, DepVars); 46820fca6ea1SDimitry Andric 46830fca6ea1SDimitry Andric // Combine those into the result: x op (x op x) 46840fca6ea1SDimitry Andric CombineChildVariants(N, CVariants, ABVariants, OutVariants, CDP, DepVars); 46850fca6ea1SDimitry Andric CombineChildVariants(N, CVariants, BAVariants, OutVariants, CDP, DepVars); 46860fca6ea1SDimitry Andric CombineChildVariants(N, BVariants, ACVariants, OutVariants, CDP, DepVars); 46870fca6ea1SDimitry Andric CombineChildVariants(N, BVariants, CAVariants, OutVariants, CDP, DepVars); 46880fca6ea1SDimitry Andric CombineChildVariants(N, AVariants, BCVariants, OutVariants, CDP, DepVars); 46890fca6ea1SDimitry Andric CombineChildVariants(N, AVariants, CBVariants, OutVariants, CDP, DepVars); 46900fca6ea1SDimitry Andric return; 46910fca6ea1SDimitry Andric } 46920fca6ea1SDimitry Andric } 46930fca6ea1SDimitry Andric 46940fca6ea1SDimitry Andric // Compute permutations of all children. 46950fca6ea1SDimitry Andric std::vector<std::vector<TreePatternNodePtr>> ChildVariants( 46960fca6ea1SDimitry Andric N->getNumChildren()); 46970fca6ea1SDimitry Andric for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) 46980fca6ea1SDimitry Andric GenerateVariantsOf(N->getChildShared(i), ChildVariants[i], CDP, DepVars); 46990fca6ea1SDimitry Andric 47000fca6ea1SDimitry Andric // Build all permutations based on how the children were formed. 47010fca6ea1SDimitry Andric CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars); 47020fca6ea1SDimitry Andric 47030fca6ea1SDimitry Andric // If this node is commutative, consider the commuted order. 47040fca6ea1SDimitry Andric bool isCommIntrinsic = N->isCommutativeIntrinsic(CDP); 47050fca6ea1SDimitry Andric if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) { 47060fca6ea1SDimitry Andric unsigned Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id. 47070fca6ea1SDimitry Andric assert(N->getNumChildren() >= (2 + Skip) && 47080fca6ea1SDimitry Andric "Commutative but doesn't have 2 children!"); 47090fca6ea1SDimitry Andric // Don't allow commuting children which are actually register references. 47100fca6ea1SDimitry Andric bool NoRegisters = true; 47110fca6ea1SDimitry Andric unsigned i = 0 + Skip; 47120fca6ea1SDimitry Andric unsigned e = 2 + Skip; 47130fca6ea1SDimitry Andric for (; i != e; ++i) { 47140fca6ea1SDimitry Andric TreePatternNode &Child = N->getChild(i); 47150fca6ea1SDimitry Andric if (Child.isLeaf()) 47160fca6ea1SDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(Child.getLeafValue())) { 47170fca6ea1SDimitry Andric Record *RR = DI->getDef(); 47180fca6ea1SDimitry Andric if (RR->isSubClassOf("Register")) 47190fca6ea1SDimitry Andric NoRegisters = false; 47200fca6ea1SDimitry Andric } 47210fca6ea1SDimitry Andric } 47220fca6ea1SDimitry Andric // Consider the commuted order. 47230fca6ea1SDimitry Andric if (NoRegisters) { 47240fca6ea1SDimitry Andric // Swap the first two operands after the intrinsic id, if present. 47250fca6ea1SDimitry Andric unsigned i = isCommIntrinsic ? 1 : 0; 47260fca6ea1SDimitry Andric std::swap(ChildVariants[i], ChildVariants[i + 1]); 47270fca6ea1SDimitry Andric CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars); 47280fca6ea1SDimitry Andric } 47290fca6ea1SDimitry Andric } 47300fca6ea1SDimitry Andric } 47310fca6ea1SDimitry Andric 47320fca6ea1SDimitry Andric // GenerateVariants - Generate variants. For example, commutative patterns can 47330fca6ea1SDimitry Andric // match multiple ways. Add them to PatternsToMatch as well. 47340fca6ea1SDimitry Andric void CodeGenDAGPatterns::GenerateVariants() { 47350fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "Generating instruction variants.\n"); 47360fca6ea1SDimitry Andric 47370fca6ea1SDimitry Andric // Loop over all of the patterns we've collected, checking to see if we can 47380fca6ea1SDimitry Andric // generate variants of the instruction, through the exploitation of 47390fca6ea1SDimitry Andric // identities. This permits the target to provide aggressive matching without 47400fca6ea1SDimitry Andric // the .td file having to contain tons of variants of instructions. 47410fca6ea1SDimitry Andric // 47420fca6ea1SDimitry Andric // Note that this loop adds new patterns to the PatternsToMatch list, but we 47430fca6ea1SDimitry Andric // intentionally do not reconsider these. Any variants of added patterns have 47440fca6ea1SDimitry Andric // already been added. 47450fca6ea1SDimitry Andric // 47460fca6ea1SDimitry Andric for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) { 47470fca6ea1SDimitry Andric MultipleUseVarSet DepVars; 47480fca6ea1SDimitry Andric std::vector<TreePatternNodePtr> Variants; 47490fca6ea1SDimitry Andric FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars); 47500fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "Dependent/multiply used variables: "); 47510fca6ea1SDimitry Andric LLVM_DEBUG(DumpDepVars(DepVars)); 47520fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "\n"); 47530fca6ea1SDimitry Andric GenerateVariantsOf(PatternsToMatch[i].getSrcPatternShared(), Variants, 47540fca6ea1SDimitry Andric *this, DepVars); 47550fca6ea1SDimitry Andric 47560fca6ea1SDimitry Andric assert(PatternsToMatch[i].getHwModeFeatures().empty() && 47570fca6ea1SDimitry Andric "HwModes should not have been expanded yet!"); 47580fca6ea1SDimitry Andric 47590fca6ea1SDimitry Andric assert(!Variants.empty() && "Must create at least original variant!"); 47600fca6ea1SDimitry Andric if (Variants.size() == 1) // No additional variants for this pattern. 47610fca6ea1SDimitry Andric continue; 47620fca6ea1SDimitry Andric 47630fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "FOUND VARIANTS OF: "; 47640fca6ea1SDimitry Andric PatternsToMatch[i].getSrcPattern().dump(); errs() << "\n"); 47650fca6ea1SDimitry Andric 47660fca6ea1SDimitry Andric for (unsigned v = 0, e = Variants.size(); v != e; ++v) { 47670fca6ea1SDimitry Andric TreePatternNodePtr Variant = Variants[v]; 47680fca6ea1SDimitry Andric 47690fca6ea1SDimitry Andric LLVM_DEBUG(errs() << " VAR#" << v << ": "; Variant->dump(); 47700fca6ea1SDimitry Andric errs() << "\n"); 47710fca6ea1SDimitry Andric 47720fca6ea1SDimitry Andric // Scan to see if an instruction or explicit pattern already matches this. 47730fca6ea1SDimitry Andric bool AlreadyExists = false; 47740fca6ea1SDimitry Andric for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) { 47750fca6ea1SDimitry Andric // Skip if the top level predicates do not match. 47760fca6ea1SDimitry Andric if ((i != p) && (PatternsToMatch[i].getPredicates() != 47770fca6ea1SDimitry Andric PatternsToMatch[p].getPredicates())) 47780fca6ea1SDimitry Andric continue; 47790fca6ea1SDimitry Andric // Check to see if this variant already exists. 47800fca6ea1SDimitry Andric if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(), 47810fca6ea1SDimitry Andric DepVars)) { 47820fca6ea1SDimitry Andric LLVM_DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n"); 47830fca6ea1SDimitry Andric AlreadyExists = true; 47840fca6ea1SDimitry Andric break; 47850fca6ea1SDimitry Andric } 47860fca6ea1SDimitry Andric } 47870fca6ea1SDimitry Andric // If we already have it, ignore the variant. 47880fca6ea1SDimitry Andric if (AlreadyExists) 47890fca6ea1SDimitry Andric continue; 47900fca6ea1SDimitry Andric 47910fca6ea1SDimitry Andric // Otherwise, add it to the list of patterns we have. 47920fca6ea1SDimitry Andric PatternsToMatch.emplace_back( 47930fca6ea1SDimitry Andric PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(), 47940fca6ea1SDimitry Andric Variant, PatternsToMatch[i].getDstPatternShared(), 47950fca6ea1SDimitry Andric PatternsToMatch[i].getDstRegs(), 47960fca6ea1SDimitry Andric PatternsToMatch[i].getAddedComplexity(), Record::getNewUID(Records), 47970fca6ea1SDimitry Andric PatternsToMatch[i].getGISelShouldIgnore(), 47980fca6ea1SDimitry Andric PatternsToMatch[i].getHwModeFeatures()); 47990fca6ea1SDimitry Andric } 48000fca6ea1SDimitry Andric 48010fca6ea1SDimitry Andric LLVM_DEBUG(errs() << "\n"); 48020fca6ea1SDimitry Andric } 48030fca6ea1SDimitry Andric } 4804