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