179cb839fSDaniel Sanders //===- lib/CodeGen/GlobalISel/LegalizerPredicates.cpp - Predicates --------===//
279cb839fSDaniel Sanders //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
679cb839fSDaniel Sanders //
779cb839fSDaniel Sanders //===----------------------------------------------------------------------===//
879cb839fSDaniel Sanders //
979cb839fSDaniel Sanders // A library of predicate factories to use for LegalityPredicate.
1079cb839fSDaniel Sanders //
1179cb839fSDaniel Sanders //===----------------------------------------------------------------------===//
1279cb839fSDaniel Sanders 
132c73bef7SReid Kleckner // Enable optimizations to work around MSVC debug mode bug in 32-bit:
144e3edef4SReid Kleckner // https://developercommunity.visualstudio.com/content/problem/1179643/msvc-copies-overaligned-non-trivially-copyable-par.html
154e3edef4SReid Kleckner // FIXME: Remove this when the issue is closed.
164e3edef4SReid Kleckner #if defined(_MSC_VER) && !defined(__clang__) && defined(_M_IX86)
174e3edef4SReid Kleckner // We have to disable runtime checks in order to enable optimizations. This is
184e3edef4SReid Kleckner // done for the entire file because the problem is actually observed in STL
194e3edef4SReid Kleckner // template functions.
204e3edef4SReid Kleckner #pragma runtime_checks("", off)
214e3edef4SReid Kleckner #pragma optimize("gs", on)
224e3edef4SReid Kleckner #endif
234e3edef4SReid Kleckner 
2479cb839fSDaniel Sanders #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
2579cb839fSDaniel Sanders 
2679cb839fSDaniel Sanders using namespace llvm;
2779cb839fSDaniel Sanders 
typeIs(unsigned TypeIdx,LLT Type)28bdeb880dSDaniel Sanders LegalityPredicate LegalityPredicates::typeIs(unsigned TypeIdx, LLT Type) {
29bdeb880dSDaniel Sanders   return
30bdeb880dSDaniel Sanders       [=](const LegalityQuery &Query) { return Query.Types[TypeIdx] == Type; };
3179cb839fSDaniel Sanders }
3279cb839fSDaniel Sanders 
3379cb839fSDaniel Sanders LegalityPredicate
typeInSet(unsigned TypeIdx,std::initializer_list<LLT> TypesInit)3479cb839fSDaniel Sanders LegalityPredicates::typeInSet(unsigned TypeIdx,
3579cb839fSDaniel Sanders                               std::initializer_list<LLT> TypesInit) {
3679cb839fSDaniel Sanders   SmallVector<LLT, 4> Types = TypesInit;
3779cb839fSDaniel Sanders   return [=](const LegalityQuery &Query) {
38902cbcd5SKazu Hirata     return llvm::is_contained(Types, Query.Types[TypeIdx]);
3979cb839fSDaniel Sanders   };
4079cb839fSDaniel Sanders }
4179cb839fSDaniel Sanders 
typePairInSet(unsigned TypeIdx0,unsigned TypeIdx1,std::initializer_list<std::pair<LLT,LLT>> TypesInit)4279cb839fSDaniel Sanders LegalityPredicate LegalityPredicates::typePairInSet(
4379cb839fSDaniel Sanders     unsigned TypeIdx0, unsigned TypeIdx1,
4479cb839fSDaniel Sanders     std::initializer_list<std::pair<LLT, LLT>> TypesInit) {
4579cb839fSDaniel Sanders   SmallVector<std::pair<LLT, LLT>, 4> Types = TypesInit;
4679cb839fSDaniel Sanders   return [=](const LegalityQuery &Query) {
4779cb839fSDaniel Sanders     std::pair<LLT, LLT> Match = {Query.Types[TypeIdx0], Query.Types[TypeIdx1]};
48902cbcd5SKazu Hirata     return llvm::is_contained(Types, Match);
4979cb839fSDaniel Sanders   };
5079cb839fSDaniel Sanders }
5179cb839fSDaniel Sanders 
typePairAndMemDescInSet(unsigned TypeIdx0,unsigned TypeIdx1,unsigned MMOIdx,std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit)52530d05e9SMatt Arsenault LegalityPredicate LegalityPredicates::typePairAndMemDescInSet(
5327fe8a50SDaniel Sanders     unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx,
54530d05e9SMatt Arsenault     std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit) {
55530d05e9SMatt Arsenault   SmallVector<TypePairAndMemDesc, 4> TypesAndMemDesc = TypesAndMemDescInit;
5627fe8a50SDaniel Sanders   return [=](const LegalityQuery &Query) {
57530d05e9SMatt Arsenault     TypePairAndMemDesc Match = {Query.Types[TypeIdx0], Query.Types[TypeIdx1],
5828f2f662SMatt Arsenault                                 Query.MMODescrs[MMOIdx].MemoryTy,
59530d05e9SMatt Arsenault                                 Query.MMODescrs[MMOIdx].AlignInBits};
60df812115SKazu Hirata     return llvm::any_of(TypesAndMemDesc,
61530d05e9SMatt Arsenault                         [=](const TypePairAndMemDesc &Entry) -> bool {
62530d05e9SMatt Arsenault                           return Match.isCompatible(Entry);
63df812115SKazu Hirata                         });
6427fe8a50SDaniel Sanders   };
6527fe8a50SDaniel Sanders }
6627fe8a50SDaniel Sanders 
isScalar(unsigned TypeIdx)6779cb839fSDaniel Sanders LegalityPredicate LegalityPredicates::isScalar(unsigned TypeIdx) {
6879cb839fSDaniel Sanders   return [=](const LegalityQuery &Query) {
6979cb839fSDaniel Sanders     return Query.Types[TypeIdx].isScalar();
7079cb839fSDaniel Sanders   };
7179cb839fSDaniel Sanders }
7279cb839fSDaniel Sanders 
isVector(unsigned TypeIdx)73990f5077SMatt Arsenault LegalityPredicate LegalityPredicates::isVector(unsigned TypeIdx) {
74990f5077SMatt Arsenault   return [=](const LegalityQuery &Query) {
75990f5077SMatt Arsenault     return Query.Types[TypeIdx].isVector();
76990f5077SMatt Arsenault   };
77990f5077SMatt Arsenault }
78990f5077SMatt Arsenault 
isPointer(unsigned TypeIdx)79a5195829SMatt Arsenault LegalityPredicate LegalityPredicates::isPointer(unsigned TypeIdx) {
80a5195829SMatt Arsenault   return [=](const LegalityQuery &Query) {
81a5195829SMatt Arsenault     return Query.Types[TypeIdx].isPointer();
82a5195829SMatt Arsenault   };
83a5195829SMatt Arsenault }
84a5195829SMatt Arsenault 
isPointer(unsigned TypeIdx,unsigned AddrSpace)85a5195829SMatt Arsenault LegalityPredicate LegalityPredicates::isPointer(unsigned TypeIdx,
86a5195829SMatt Arsenault                                                 unsigned AddrSpace) {
87a5195829SMatt Arsenault   return [=](const LegalityQuery &Query) {
88a5195829SMatt Arsenault     LLT Ty = Query.Types[TypeIdx];
89a5195829SMatt Arsenault     return Ty.isPointer() && Ty.getAddressSpace() == AddrSpace;
90a5195829SMatt Arsenault   };
91a5195829SMatt Arsenault }
92a5195829SMatt Arsenault 
elementTypeIs(unsigned TypeIdx,LLT EltTy)93e13c84c3SMatt Arsenault LegalityPredicate LegalityPredicates::elementTypeIs(unsigned TypeIdx,
94e13c84c3SMatt Arsenault                                                     LLT EltTy) {
95e13c84c3SMatt Arsenault   return [=](const LegalityQuery &Query) {
96e13c84c3SMatt Arsenault     const LLT QueryTy = Query.Types[TypeIdx];
97e13c84c3SMatt Arsenault     return QueryTy.isVector() && QueryTy.getElementType() == EltTy;
98e13c84c3SMatt Arsenault   };
99e13c84c3SMatt Arsenault }
100e13c84c3SMatt Arsenault 
scalarNarrowerThan(unsigned TypeIdx,unsigned Size)101e13c84c3SMatt Arsenault LegalityPredicate LegalityPredicates::scalarNarrowerThan(unsigned TypeIdx,
10279cb839fSDaniel Sanders                                                          unsigned Size) {
10379cb839fSDaniel Sanders   return [=](const LegalityQuery &Query) {
10491be65beSMatt Arsenault     const LLT QueryTy = Query.Types[TypeIdx];
10579cb839fSDaniel Sanders     return QueryTy.isScalar() && QueryTy.getSizeInBits() < Size;
10679cb839fSDaniel Sanders   };
10779cb839fSDaniel Sanders }
10879cb839fSDaniel Sanders 
scalarWiderThan(unsigned TypeIdx,unsigned Size)109e13c84c3SMatt Arsenault LegalityPredicate LegalityPredicates::scalarWiderThan(unsigned TypeIdx,
11079cb839fSDaniel Sanders                                                       unsigned Size) {
11179cb839fSDaniel Sanders   return [=](const LegalityQuery &Query) {
11291be65beSMatt Arsenault     const LLT QueryTy = Query.Types[TypeIdx];
11379cb839fSDaniel Sanders     return QueryTy.isScalar() && QueryTy.getSizeInBits() > Size;
11479cb839fSDaniel Sanders   };
11579cb839fSDaniel Sanders }
11679cb839fSDaniel Sanders 
smallerThan(unsigned TypeIdx0,unsigned TypeIdx1)117e13c84c3SMatt Arsenault LegalityPredicate LegalityPredicates::smallerThan(unsigned TypeIdx0,
118e13c84c3SMatt Arsenault                                                   unsigned TypeIdx1) {
119e13c84c3SMatt Arsenault   return [=](const LegalityQuery &Query) {
120e13c84c3SMatt Arsenault     return Query.Types[TypeIdx0].getSizeInBits() <
121e13c84c3SMatt Arsenault            Query.Types[TypeIdx1].getSizeInBits();
122e13c84c3SMatt Arsenault   };
123e13c84c3SMatt Arsenault }
124e13c84c3SMatt Arsenault 
largerThan(unsigned TypeIdx0,unsigned TypeIdx1)125e13c84c3SMatt Arsenault LegalityPredicate LegalityPredicates::largerThan(unsigned TypeIdx0,
126e13c84c3SMatt Arsenault                                                   unsigned TypeIdx1) {
127e13c84c3SMatt Arsenault   return [=](const LegalityQuery &Query) {
128e13c84c3SMatt Arsenault     return Query.Types[TypeIdx0].getSizeInBits() >
129e13c84c3SMatt Arsenault            Query.Types[TypeIdx1].getSizeInBits();
130e13c84c3SMatt Arsenault   };
131e13c84c3SMatt Arsenault }
132e13c84c3SMatt Arsenault 
scalarOrEltNarrowerThan(unsigned TypeIdx,unsigned Size)13391be65beSMatt Arsenault LegalityPredicate LegalityPredicates::scalarOrEltNarrowerThan(unsigned TypeIdx,
13491be65beSMatt Arsenault                                                               unsigned Size) {
13591be65beSMatt Arsenault   return [=](const LegalityQuery &Query) {
13691be65beSMatt Arsenault     const LLT QueryTy = Query.Types[TypeIdx];
13791be65beSMatt Arsenault     return QueryTy.getScalarSizeInBits() < Size;
13891be65beSMatt Arsenault   };
13991be65beSMatt Arsenault }
14091be65beSMatt Arsenault 
scalarOrEltWiderThan(unsigned TypeIdx,unsigned Size)14191be65beSMatt Arsenault LegalityPredicate LegalityPredicates::scalarOrEltWiderThan(unsigned TypeIdx,
14291be65beSMatt Arsenault                                                            unsigned Size) {
14391be65beSMatt Arsenault   return [=](const LegalityQuery &Query) {
14491be65beSMatt Arsenault     const LLT QueryTy = Query.Types[TypeIdx];
14591be65beSMatt Arsenault     return QueryTy.getScalarSizeInBits() > Size;
14691be65beSMatt Arsenault   };
14791be65beSMatt Arsenault }
14891be65beSMatt Arsenault 
scalarOrEltSizeNotPow2(unsigned TypeIdx)14991be65beSMatt Arsenault LegalityPredicate LegalityPredicates::scalarOrEltSizeNotPow2(unsigned TypeIdx) {
15091be65beSMatt Arsenault   return [=](const LegalityQuery &Query) {
15191be65beSMatt Arsenault     const LLT QueryTy = Query.Types[TypeIdx];
15291be65beSMatt Arsenault     return !isPowerOf2_32(QueryTy.getScalarSizeInBits());
15391be65beSMatt Arsenault   };
15491be65beSMatt Arsenault }
15591be65beSMatt Arsenault 
sizeNotMultipleOf(unsigned TypeIdx,unsigned Size)1566c4b634dSMirko Brkusanin LegalityPredicate LegalityPredicates::sizeNotMultipleOf(unsigned TypeIdx,
1576c4b634dSMirko Brkusanin                                                         unsigned Size) {
1586c4b634dSMirko Brkusanin   return [=](const LegalityQuery &Query) {
1596c4b634dSMirko Brkusanin     const LLT QueryTy = Query.Types[TypeIdx];
1606c4b634dSMirko Brkusanin     return QueryTy.isScalar() && QueryTy.getSizeInBits() % Size != 0;
1616c4b634dSMirko Brkusanin   };
1626c4b634dSMirko Brkusanin }
1636c4b634dSMirko Brkusanin 
sizeNotPow2(unsigned TypeIdx)16479cb839fSDaniel Sanders LegalityPredicate LegalityPredicates::sizeNotPow2(unsigned TypeIdx) {
16579cb839fSDaniel Sanders   return [=](const LegalityQuery &Query) {
16691be65beSMatt Arsenault     const LLT QueryTy = Query.Types[TypeIdx];
16779cb839fSDaniel Sanders     return QueryTy.isScalar() && !isPowerOf2_32(QueryTy.getSizeInBits());
16879cb839fSDaniel Sanders   };
16979cb839fSDaniel Sanders }
17079cb839fSDaniel Sanders 
sizeIs(unsigned TypeIdx,unsigned Size)171ef3e8312SMatt Arsenault LegalityPredicate LegalityPredicates::sizeIs(unsigned TypeIdx, unsigned Size) {
172ef3e8312SMatt Arsenault   return [=](const LegalityQuery &Query) {
173ef3e8312SMatt Arsenault     return Query.Types[TypeIdx].getSizeInBits() == Size;
174ef3e8312SMatt Arsenault   };
175ef3e8312SMatt Arsenault }
176ef3e8312SMatt Arsenault 
sameSize(unsigned TypeIdx0,unsigned TypeIdx1)177cbaada6bSMatt Arsenault LegalityPredicate LegalityPredicates::sameSize(unsigned TypeIdx0,
178cbaada6bSMatt Arsenault                                                unsigned TypeIdx1) {
179cbaada6bSMatt Arsenault   return [=](const LegalityQuery &Query) {
180cbaada6bSMatt Arsenault     return Query.Types[TypeIdx0].getSizeInBits() ==
181cbaada6bSMatt Arsenault            Query.Types[TypeIdx1].getSizeInBits();
182cbaada6bSMatt Arsenault   };
183cbaada6bSMatt Arsenault }
184cbaada6bSMatt Arsenault 
memSizeInBytesNotPow2(unsigned MMOIdx)18527fe8a50SDaniel Sanders LegalityPredicate LegalityPredicates::memSizeInBytesNotPow2(unsigned MMOIdx) {
18627fe8a50SDaniel Sanders   return [=](const LegalityQuery &Query) {
18728f2f662SMatt Arsenault     return !isPowerOf2_32(Query.MMODescrs[MMOIdx].MemoryTy.getSizeInBytes());
18827fe8a50SDaniel Sanders   };
18927fe8a50SDaniel Sanders }
19027fe8a50SDaniel Sanders 
memSizeNotByteSizePow2(unsigned MMOIdx)191*d1f97a34SMatt Arsenault LegalityPredicate LegalityPredicates::memSizeNotByteSizePow2(unsigned MMOIdx) {
192*d1f97a34SMatt Arsenault   return [=](const LegalityQuery &Query) {
193*d1f97a34SMatt Arsenault     const LLT MemTy = Query.MMODescrs[MMOIdx].MemoryTy;
194*d1f97a34SMatt Arsenault     return !MemTy.isByteSized() || !isPowerOf2_32(MemTy.getSizeInBytes());
195*d1f97a34SMatt Arsenault   };
196*d1f97a34SMatt Arsenault }
197*d1f97a34SMatt Arsenault 
numElementsNotPow2(unsigned TypeIdx)19879cb839fSDaniel Sanders LegalityPredicate LegalityPredicates::numElementsNotPow2(unsigned TypeIdx) {
19979cb839fSDaniel Sanders   return [=](const LegalityQuery &Query) {
20007238286SMatt Arsenault     const LLT QueryTy = Query.Types[TypeIdx];
20107238286SMatt Arsenault     return QueryTy.isVector() && !isPowerOf2_32(QueryTy.getNumElements());
20279cb839fSDaniel Sanders   };
20379cb839fSDaniel Sanders }
204bdeb880dSDaniel Sanders 
atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx,AtomicOrdering Ordering)205bdeb880dSDaniel Sanders LegalityPredicate LegalityPredicates::atomicOrderingAtLeastOrStrongerThan(
206bdeb880dSDaniel Sanders     unsigned MMOIdx, AtomicOrdering Ordering) {
207bdeb880dSDaniel Sanders   return [=](const LegalityQuery &Query) {
208bdeb880dSDaniel Sanders     return isAtLeastOrStrongerThan(Query.MMODescrs[MMOIdx].Ordering, Ordering);
209bdeb880dSDaniel Sanders   };
210bdeb880dSDaniel Sanders }
211