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