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