10b57cec5SDimitry Andric //===- lib/CodeGen/GlobalISel/LegalizerPredicates.cpp - Predicates --------===//
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 // A library of predicate factories to use for LegalityPredicate.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
13e8d8bef9SDimitry Andric // Enable optimizations to work around MSVC debug mode bug in 32-bit:
14e8d8bef9SDimitry Andric // https://developercommunity.visualstudio.com/content/problem/1179643/msvc-copies-overaligned-non-trivially-copyable-par.html
15e8d8bef9SDimitry Andric // FIXME: Remove this when the issue is closed.
16e8d8bef9SDimitry Andric #if defined(_MSC_VER) && !defined(__clang__) && defined(_M_IX86)
17e8d8bef9SDimitry Andric // We have to disable runtime checks in order to enable optimizations. This is
18e8d8bef9SDimitry Andric // done for the entire file because the problem is actually observed in STL
19e8d8bef9SDimitry Andric // template functions.
20e8d8bef9SDimitry Andric #pragma runtime_checks("", off)
21e8d8bef9SDimitry Andric #pragma optimize("gs", on)
22e8d8bef9SDimitry Andric #endif
23e8d8bef9SDimitry Andric 
240b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric using namespace llvm;
270b57cec5SDimitry Andric 
typeIs(unsigned TypeIdx,LLT Type)280b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::typeIs(unsigned TypeIdx, LLT Type) {
290b57cec5SDimitry Andric   return
300b57cec5SDimitry Andric       [=](const LegalityQuery &Query) { return Query.Types[TypeIdx] == Type; };
310b57cec5SDimitry Andric }
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric LegalityPredicate
typeInSet(unsigned TypeIdx,std::initializer_list<LLT> TypesInit)340b57cec5SDimitry Andric LegalityPredicates::typeInSet(unsigned TypeIdx,
350b57cec5SDimitry Andric                               std::initializer_list<LLT> TypesInit) {
360b57cec5SDimitry Andric   SmallVector<LLT, 4> Types = TypesInit;
370b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
38e8d8bef9SDimitry Andric     return llvm::is_contained(Types, Query.Types[TypeIdx]);
390b57cec5SDimitry Andric   };
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric 
typePairInSet(unsigned TypeIdx0,unsigned TypeIdx1,std::initializer_list<std::pair<LLT,LLT>> TypesInit)420b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::typePairInSet(
430b57cec5SDimitry Andric     unsigned TypeIdx0, unsigned TypeIdx1,
440b57cec5SDimitry Andric     std::initializer_list<std::pair<LLT, LLT>> TypesInit) {
450b57cec5SDimitry Andric   SmallVector<std::pair<LLT, LLT>, 4> Types = TypesInit;
460b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
470b57cec5SDimitry Andric     std::pair<LLT, LLT> Match = {Query.Types[TypeIdx0], Query.Types[TypeIdx1]};
48e8d8bef9SDimitry Andric     return llvm::is_contained(Types, Match);
490b57cec5SDimitry Andric   };
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
typePairAndMemDescInSet(unsigned TypeIdx0,unsigned TypeIdx1,unsigned MMOIdx,std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit)520b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::typePairAndMemDescInSet(
530b57cec5SDimitry Andric     unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx,
540b57cec5SDimitry Andric     std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit) {
550b57cec5SDimitry Andric   SmallVector<TypePairAndMemDesc, 4> TypesAndMemDesc = TypesAndMemDescInit;
560b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
570b57cec5SDimitry Andric     TypePairAndMemDesc Match = {Query.Types[TypeIdx0], Query.Types[TypeIdx1],
58fe6060f1SDimitry Andric                                 Query.MMODescrs[MMOIdx].MemoryTy,
590b57cec5SDimitry Andric                                 Query.MMODescrs[MMOIdx].AlignInBits};
60e8d8bef9SDimitry Andric     return llvm::any_of(TypesAndMemDesc,
610b57cec5SDimitry Andric                         [=](const TypePairAndMemDesc &Entry) -> bool {
620b57cec5SDimitry Andric                           return Match.isCompatible(Entry);
63e8d8bef9SDimitry Andric                         });
640b57cec5SDimitry Andric   };
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
isScalar(unsigned TypeIdx)670b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::isScalar(unsigned TypeIdx) {
680b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
690b57cec5SDimitry Andric     return Query.Types[TypeIdx].isScalar();
700b57cec5SDimitry Andric   };
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
isVector(unsigned TypeIdx)730b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::isVector(unsigned TypeIdx) {
740b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
750b57cec5SDimitry Andric     return Query.Types[TypeIdx].isVector();
760b57cec5SDimitry Andric   };
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric 
isPointer(unsigned TypeIdx)790b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::isPointer(unsigned TypeIdx) {
800b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
810b57cec5SDimitry Andric     return Query.Types[TypeIdx].isPointer();
820b57cec5SDimitry Andric   };
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
isPointer(unsigned TypeIdx,unsigned AddrSpace)850b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::isPointer(unsigned TypeIdx,
860b57cec5SDimitry Andric                                                 unsigned AddrSpace) {
870b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
880b57cec5SDimitry Andric     LLT Ty = Query.Types[TypeIdx];
890b57cec5SDimitry Andric     return Ty.isPointer() && Ty.getAddressSpace() == AddrSpace;
900b57cec5SDimitry Andric   };
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric 
elementTypeIs(unsigned TypeIdx,LLT EltTy)935ffd83dbSDimitry Andric LegalityPredicate LegalityPredicates::elementTypeIs(unsigned TypeIdx,
945ffd83dbSDimitry Andric                                                     LLT EltTy) {
955ffd83dbSDimitry Andric   return [=](const LegalityQuery &Query) {
965ffd83dbSDimitry Andric     const LLT QueryTy = Query.Types[TypeIdx];
975ffd83dbSDimitry Andric     return QueryTy.isVector() && QueryTy.getElementType() == EltTy;
985ffd83dbSDimitry Andric   };
995ffd83dbSDimitry Andric }
1005ffd83dbSDimitry Andric 
scalarNarrowerThan(unsigned TypeIdx,unsigned Size)1015ffd83dbSDimitry Andric LegalityPredicate LegalityPredicates::scalarNarrowerThan(unsigned TypeIdx,
1020b57cec5SDimitry Andric                                                          unsigned Size) {
1030b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
1040b57cec5SDimitry Andric     const LLT QueryTy = Query.Types[TypeIdx];
1050b57cec5SDimitry Andric     return QueryTy.isScalar() && QueryTy.getSizeInBits() < Size;
1060b57cec5SDimitry Andric   };
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
scalarWiderThan(unsigned TypeIdx,unsigned Size)1095ffd83dbSDimitry Andric LegalityPredicate LegalityPredicates::scalarWiderThan(unsigned TypeIdx,
1100b57cec5SDimitry Andric                                                       unsigned Size) {
1110b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
1120b57cec5SDimitry Andric     const LLT QueryTy = Query.Types[TypeIdx];
1130b57cec5SDimitry Andric     return QueryTy.isScalar() && QueryTy.getSizeInBits() > Size;
1140b57cec5SDimitry Andric   };
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric 
smallerThan(unsigned TypeIdx0,unsigned TypeIdx1)1175ffd83dbSDimitry Andric LegalityPredicate LegalityPredicates::smallerThan(unsigned TypeIdx0,
1185ffd83dbSDimitry Andric                                                   unsigned TypeIdx1) {
1195ffd83dbSDimitry Andric   return [=](const LegalityQuery &Query) {
1205ffd83dbSDimitry Andric     return Query.Types[TypeIdx0].getSizeInBits() <
1215ffd83dbSDimitry Andric            Query.Types[TypeIdx1].getSizeInBits();
1225ffd83dbSDimitry Andric   };
1235ffd83dbSDimitry Andric }
1245ffd83dbSDimitry Andric 
largerThan(unsigned TypeIdx0,unsigned TypeIdx1)1255ffd83dbSDimitry Andric LegalityPredicate LegalityPredicates::largerThan(unsigned TypeIdx0,
1265ffd83dbSDimitry Andric                                                   unsigned TypeIdx1) {
1275ffd83dbSDimitry Andric   return [=](const LegalityQuery &Query) {
1285ffd83dbSDimitry Andric     return Query.Types[TypeIdx0].getSizeInBits() >
1295ffd83dbSDimitry Andric            Query.Types[TypeIdx1].getSizeInBits();
1305ffd83dbSDimitry Andric   };
1315ffd83dbSDimitry Andric }
1325ffd83dbSDimitry Andric 
scalarOrEltNarrowerThan(unsigned TypeIdx,unsigned Size)1330b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::scalarOrEltNarrowerThan(unsigned TypeIdx,
1340b57cec5SDimitry Andric                                                               unsigned Size) {
1350b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
1360b57cec5SDimitry Andric     const LLT QueryTy = Query.Types[TypeIdx];
1370b57cec5SDimitry Andric     return QueryTy.getScalarSizeInBits() < Size;
1380b57cec5SDimitry Andric   };
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
scalarOrEltWiderThan(unsigned TypeIdx,unsigned Size)1410b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::scalarOrEltWiderThan(unsigned TypeIdx,
1420b57cec5SDimitry Andric                                                            unsigned Size) {
1430b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
1440b57cec5SDimitry Andric     const LLT QueryTy = Query.Types[TypeIdx];
1450b57cec5SDimitry Andric     return QueryTy.getScalarSizeInBits() > Size;
1460b57cec5SDimitry Andric   };
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
scalarOrEltSizeNotPow2(unsigned TypeIdx)1490b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::scalarOrEltSizeNotPow2(unsigned TypeIdx) {
1500b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
1510b57cec5SDimitry Andric     const LLT QueryTy = Query.Types[TypeIdx];
1520b57cec5SDimitry Andric     return !isPowerOf2_32(QueryTy.getScalarSizeInBits());
1530b57cec5SDimitry Andric   };
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric 
sizeNotMultipleOf(unsigned TypeIdx,unsigned Size)156349cc55cSDimitry Andric LegalityPredicate LegalityPredicates::sizeNotMultipleOf(unsigned TypeIdx,
157349cc55cSDimitry Andric                                                         unsigned Size) {
158349cc55cSDimitry Andric   return [=](const LegalityQuery &Query) {
159349cc55cSDimitry Andric     const LLT QueryTy = Query.Types[TypeIdx];
160349cc55cSDimitry Andric     return QueryTy.isScalar() && QueryTy.getSizeInBits() % Size != 0;
161349cc55cSDimitry Andric   };
162349cc55cSDimitry Andric }
163349cc55cSDimitry Andric 
sizeNotPow2(unsigned TypeIdx)1640b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::sizeNotPow2(unsigned TypeIdx) {
1650b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
1660b57cec5SDimitry Andric     const LLT QueryTy = Query.Types[TypeIdx];
16706c3fb27SDimitry Andric     return QueryTy.isScalar() &&
16806c3fb27SDimitry Andric            !llvm::has_single_bit<uint32_t>(QueryTy.getSizeInBits());
1690b57cec5SDimitry Andric   };
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
sizeIs(unsigned TypeIdx,unsigned Size)1725ffd83dbSDimitry Andric LegalityPredicate LegalityPredicates::sizeIs(unsigned TypeIdx, unsigned Size) {
1735ffd83dbSDimitry Andric   return [=](const LegalityQuery &Query) {
1745ffd83dbSDimitry Andric     return Query.Types[TypeIdx].getSizeInBits() == Size;
1755ffd83dbSDimitry Andric   };
1765ffd83dbSDimitry Andric }
1775ffd83dbSDimitry Andric 
sameSize(unsigned TypeIdx0,unsigned TypeIdx1)1780b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::sameSize(unsigned TypeIdx0,
1790b57cec5SDimitry Andric                                                unsigned TypeIdx1) {
1800b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
1810b57cec5SDimitry Andric     return Query.Types[TypeIdx0].getSizeInBits() ==
1820b57cec5SDimitry Andric            Query.Types[TypeIdx1].getSizeInBits();
1830b57cec5SDimitry Andric   };
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric 
memSizeInBytesNotPow2(unsigned MMOIdx)1860b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::memSizeInBytesNotPow2(unsigned MMOIdx) {
1870b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
18806c3fb27SDimitry Andric     return !llvm::has_single_bit<uint32_t>(
18906c3fb27SDimitry Andric         Query.MMODescrs[MMOIdx].MemoryTy.getSizeInBytes());
1900b57cec5SDimitry Andric   };
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric 
memSizeNotByteSizePow2(unsigned MMOIdx)19381ad6265SDimitry Andric LegalityPredicate LegalityPredicates::memSizeNotByteSizePow2(unsigned MMOIdx) {
19481ad6265SDimitry Andric   return [=](const LegalityQuery &Query) {
19581ad6265SDimitry Andric     const LLT MemTy = Query.MMODescrs[MMOIdx].MemoryTy;
19606c3fb27SDimitry Andric     return !MemTy.isByteSized() ||
19706c3fb27SDimitry Andric            !llvm::has_single_bit<uint32_t>(MemTy.getSizeInBytes());
19881ad6265SDimitry Andric   };
19981ad6265SDimitry Andric }
20081ad6265SDimitry Andric 
numElementsNotPow2(unsigned TypeIdx)2010b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::numElementsNotPow2(unsigned TypeIdx) {
2020b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
2030b57cec5SDimitry Andric     const LLT QueryTy = Query.Types[TypeIdx];
2040b57cec5SDimitry Andric     return QueryTy.isVector() && !isPowerOf2_32(QueryTy.getNumElements());
2050b57cec5SDimitry Andric   };
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx,AtomicOrdering Ordering)2080b57cec5SDimitry Andric LegalityPredicate LegalityPredicates::atomicOrderingAtLeastOrStrongerThan(
2090b57cec5SDimitry Andric     unsigned MMOIdx, AtomicOrdering Ordering) {
2100b57cec5SDimitry Andric   return [=](const LegalityQuery &Query) {
2110b57cec5SDimitry Andric     return isAtLeastOrStrongerThan(Query.MMODescrs[MMOIdx].Ordering, Ordering);
2120b57cec5SDimitry Andric   };
2130b57cec5SDimitry Andric }
214