1eb11fae6SDimitry Andric //===- lib/CodeGen/GlobalISel/LegalizerPredicates.cpp - Predicates --------===//
2eb11fae6SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6eb11fae6SDimitry Andric //
7eb11fae6SDimitry Andric //===----------------------------------------------------------------------===//
8eb11fae6SDimitry Andric //
9eb11fae6SDimitry Andric // A library of predicate factories to use for LegalityPredicate.
10eb11fae6SDimitry Andric //
11eb11fae6SDimitry Andric //===----------------------------------------------------------------------===//
12eb11fae6SDimitry Andric
13b60736ecSDimitry Andric // Enable optimizations to work around MSVC debug mode bug in 32-bit:
14b60736ecSDimitry Andric // https://developercommunity.visualstudio.com/content/problem/1179643/msvc-copies-overaligned-non-trivially-copyable-par.html
15b60736ecSDimitry Andric // FIXME: Remove this when the issue is closed.
16b60736ecSDimitry Andric #if defined(_MSC_VER) && !defined(__clang__) && defined(_M_IX86)
17b60736ecSDimitry Andric // We have to disable runtime checks in order to enable optimizations. This is
18b60736ecSDimitry Andric // done for the entire file because the problem is actually observed in STL
19b60736ecSDimitry Andric // template functions.
20b60736ecSDimitry Andric #pragma runtime_checks("", off)
21b60736ecSDimitry Andric #pragma optimize("gs", on)
22b60736ecSDimitry Andric #endif
23b60736ecSDimitry Andric
24eb11fae6SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
25eb11fae6SDimitry Andric
26eb11fae6SDimitry Andric using namespace llvm;
27eb11fae6SDimitry Andric
typeIs(unsigned TypeIdx,LLT Type)28eb11fae6SDimitry Andric LegalityPredicate LegalityPredicates::typeIs(unsigned TypeIdx, LLT Type) {
29eb11fae6SDimitry Andric return
30eb11fae6SDimitry Andric [=](const LegalityQuery &Query) { return Query.Types[TypeIdx] == Type; };
31eb11fae6SDimitry Andric }
32eb11fae6SDimitry Andric
33eb11fae6SDimitry Andric LegalityPredicate
typeInSet(unsigned TypeIdx,std::initializer_list<LLT> TypesInit)34eb11fae6SDimitry Andric LegalityPredicates::typeInSet(unsigned TypeIdx,
35eb11fae6SDimitry Andric std::initializer_list<LLT> TypesInit) {
36eb11fae6SDimitry Andric SmallVector<LLT, 4> Types = TypesInit;
37eb11fae6SDimitry Andric return [=](const LegalityQuery &Query) {
38b60736ecSDimitry Andric return llvm::is_contained(Types, Query.Types[TypeIdx]);
39eb11fae6SDimitry Andric };
40eb11fae6SDimitry Andric }
41eb11fae6SDimitry Andric
typePairInSet(unsigned TypeIdx0,unsigned TypeIdx1,std::initializer_list<std::pair<LLT,LLT>> TypesInit)42eb11fae6SDimitry Andric LegalityPredicate LegalityPredicates::typePairInSet(
43eb11fae6SDimitry Andric unsigned TypeIdx0, unsigned TypeIdx1,
44eb11fae6SDimitry Andric std::initializer_list<std::pair<LLT, LLT>> TypesInit) {
45eb11fae6SDimitry Andric SmallVector<std::pair<LLT, LLT>, 4> Types = TypesInit;
46eb11fae6SDimitry Andric return [=](const LegalityQuery &Query) {
47eb11fae6SDimitry Andric std::pair<LLT, LLT> Match = {Query.Types[TypeIdx0], Query.Types[TypeIdx1]};
48b60736ecSDimitry Andric return llvm::is_contained(Types, Match);
49eb11fae6SDimitry Andric };
50eb11fae6SDimitry Andric }
51eb11fae6SDimitry Andric
typePairAndMemDescInSet(unsigned TypeIdx0,unsigned TypeIdx1,unsigned MMOIdx,std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit)52e6d15924SDimitry Andric LegalityPredicate LegalityPredicates::typePairAndMemDescInSet(
53eb11fae6SDimitry Andric unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx,
54e6d15924SDimitry Andric std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit) {
55e6d15924SDimitry Andric SmallVector<TypePairAndMemDesc, 4> TypesAndMemDesc = TypesAndMemDescInit;
56eb11fae6SDimitry Andric return [=](const LegalityQuery &Query) {
57e6d15924SDimitry Andric TypePairAndMemDesc Match = {Query.Types[TypeIdx0], Query.Types[TypeIdx1],
58344a3780SDimitry Andric Query.MMODescrs[MMOIdx].MemoryTy,
59e6d15924SDimitry Andric Query.MMODescrs[MMOIdx].AlignInBits};
60b60736ecSDimitry Andric return llvm::any_of(TypesAndMemDesc,
61e6d15924SDimitry Andric [=](const TypePairAndMemDesc &Entry) -> bool {
62e6d15924SDimitry Andric return Match.isCompatible(Entry);
63b60736ecSDimitry Andric });
64eb11fae6SDimitry Andric };
65eb11fae6SDimitry Andric }
66eb11fae6SDimitry Andric
isScalar(unsigned TypeIdx)67eb11fae6SDimitry Andric LegalityPredicate LegalityPredicates::isScalar(unsigned TypeIdx) {
68eb11fae6SDimitry Andric return [=](const LegalityQuery &Query) {
69eb11fae6SDimitry Andric return Query.Types[TypeIdx].isScalar();
70eb11fae6SDimitry Andric };
71eb11fae6SDimitry Andric }
72eb11fae6SDimitry Andric
isVector(unsigned TypeIdx)73e6d15924SDimitry Andric LegalityPredicate LegalityPredicates::isVector(unsigned TypeIdx) {
74e6d15924SDimitry Andric return [=](const LegalityQuery &Query) {
75e6d15924SDimitry Andric return Query.Types[TypeIdx].isVector();
76e6d15924SDimitry Andric };
77e6d15924SDimitry Andric }
78e6d15924SDimitry Andric
isPointer(unsigned TypeIdx)79e6d15924SDimitry Andric LegalityPredicate LegalityPredicates::isPointer(unsigned TypeIdx) {
80e6d15924SDimitry Andric return [=](const LegalityQuery &Query) {
81e6d15924SDimitry Andric return Query.Types[TypeIdx].isPointer();
82e6d15924SDimitry Andric };
83e6d15924SDimitry Andric }
84e6d15924SDimitry Andric
isPointer(unsigned TypeIdx,unsigned AddrSpace)85e6d15924SDimitry Andric LegalityPredicate LegalityPredicates::isPointer(unsigned TypeIdx,
86e6d15924SDimitry Andric unsigned AddrSpace) {
87e6d15924SDimitry Andric return [=](const LegalityQuery &Query) {
88e6d15924SDimitry Andric LLT Ty = Query.Types[TypeIdx];
89e6d15924SDimitry Andric return Ty.isPointer() && Ty.getAddressSpace() == AddrSpace;
90e6d15924SDimitry Andric };
91e6d15924SDimitry Andric }
92e6d15924SDimitry Andric
elementTypeIs(unsigned TypeIdx,LLT EltTy)93cfca06d7SDimitry Andric LegalityPredicate LegalityPredicates::elementTypeIs(unsigned TypeIdx,
94cfca06d7SDimitry Andric LLT EltTy) {
95cfca06d7SDimitry Andric return [=](const LegalityQuery &Query) {
96cfca06d7SDimitry Andric const LLT QueryTy = Query.Types[TypeIdx];
97cfca06d7SDimitry Andric return QueryTy.isVector() && QueryTy.getElementType() == EltTy;
98cfca06d7SDimitry Andric };
99cfca06d7SDimitry Andric }
100cfca06d7SDimitry Andric
scalarNarrowerThan(unsigned TypeIdx,unsigned Size)101cfca06d7SDimitry Andric LegalityPredicate LegalityPredicates::scalarNarrowerThan(unsigned TypeIdx,
102eb11fae6SDimitry Andric unsigned Size) {
103eb11fae6SDimitry Andric return [=](const LegalityQuery &Query) {
104e6d15924SDimitry Andric const LLT QueryTy = Query.Types[TypeIdx];
105eb11fae6SDimitry Andric return QueryTy.isScalar() && QueryTy.getSizeInBits() < Size;
106eb11fae6SDimitry Andric };
107eb11fae6SDimitry Andric }
108eb11fae6SDimitry Andric
scalarWiderThan(unsigned TypeIdx,unsigned Size)109cfca06d7SDimitry Andric LegalityPredicate LegalityPredicates::scalarWiderThan(unsigned TypeIdx,
110eb11fae6SDimitry Andric unsigned Size) {
111eb11fae6SDimitry Andric return [=](const LegalityQuery &Query) {
112e6d15924SDimitry Andric const LLT QueryTy = Query.Types[TypeIdx];
113eb11fae6SDimitry Andric return QueryTy.isScalar() && QueryTy.getSizeInBits() > Size;
114eb11fae6SDimitry Andric };
115eb11fae6SDimitry Andric }
116eb11fae6SDimitry Andric
smallerThan(unsigned TypeIdx0,unsigned TypeIdx1)117cfca06d7SDimitry Andric LegalityPredicate LegalityPredicates::smallerThan(unsigned TypeIdx0,
118cfca06d7SDimitry Andric unsigned TypeIdx1) {
119cfca06d7SDimitry Andric return [=](const LegalityQuery &Query) {
120cfca06d7SDimitry Andric return Query.Types[TypeIdx0].getSizeInBits() <
121cfca06d7SDimitry Andric Query.Types[TypeIdx1].getSizeInBits();
122cfca06d7SDimitry Andric };
123cfca06d7SDimitry Andric }
124cfca06d7SDimitry Andric
largerThan(unsigned TypeIdx0,unsigned TypeIdx1)125cfca06d7SDimitry Andric LegalityPredicate LegalityPredicates::largerThan(unsigned TypeIdx0,
126cfca06d7SDimitry Andric unsigned TypeIdx1) {
127cfca06d7SDimitry Andric return [=](const LegalityQuery &Query) {
128cfca06d7SDimitry Andric return Query.Types[TypeIdx0].getSizeInBits() >
129cfca06d7SDimitry Andric Query.Types[TypeIdx1].getSizeInBits();
130cfca06d7SDimitry Andric };
131cfca06d7SDimitry Andric }
132cfca06d7SDimitry Andric
scalarOrEltNarrowerThan(unsigned TypeIdx,unsigned Size)133e6d15924SDimitry Andric LegalityPredicate LegalityPredicates::scalarOrEltNarrowerThan(unsigned TypeIdx,
134e6d15924SDimitry Andric unsigned Size) {
135e6d15924SDimitry Andric return [=](const LegalityQuery &Query) {
136e6d15924SDimitry Andric const LLT QueryTy = Query.Types[TypeIdx];
137e6d15924SDimitry Andric return QueryTy.getScalarSizeInBits() < Size;
138e6d15924SDimitry Andric };
139e6d15924SDimitry Andric }
140e6d15924SDimitry Andric
scalarOrEltWiderThan(unsigned TypeIdx,unsigned Size)141e6d15924SDimitry Andric LegalityPredicate LegalityPredicates::scalarOrEltWiderThan(unsigned TypeIdx,
142e6d15924SDimitry Andric unsigned Size) {
143e6d15924SDimitry Andric return [=](const LegalityQuery &Query) {
144e6d15924SDimitry Andric const LLT QueryTy = Query.Types[TypeIdx];
145e6d15924SDimitry Andric return QueryTy.getScalarSizeInBits() > Size;
146e6d15924SDimitry Andric };
147e6d15924SDimitry Andric }
148e6d15924SDimitry Andric
scalarOrEltSizeNotPow2(unsigned TypeIdx)149e6d15924SDimitry Andric LegalityPredicate LegalityPredicates::scalarOrEltSizeNotPow2(unsigned TypeIdx) {
150e6d15924SDimitry Andric return [=](const LegalityQuery &Query) {
151e6d15924SDimitry Andric const LLT QueryTy = Query.Types[TypeIdx];
152e6d15924SDimitry Andric return !isPowerOf2_32(QueryTy.getScalarSizeInBits());
153e6d15924SDimitry Andric };
154e6d15924SDimitry Andric }
155e6d15924SDimitry Andric
sizeNotMultipleOf(unsigned TypeIdx,unsigned Size)156c0981da4SDimitry Andric LegalityPredicate LegalityPredicates::sizeNotMultipleOf(unsigned TypeIdx,
157c0981da4SDimitry Andric unsigned Size) {
158c0981da4SDimitry Andric return [=](const LegalityQuery &Query) {
159c0981da4SDimitry Andric const LLT QueryTy = Query.Types[TypeIdx];
160c0981da4SDimitry Andric return QueryTy.isScalar() && QueryTy.getSizeInBits() % Size != 0;
161c0981da4SDimitry Andric };
162c0981da4SDimitry Andric }
163c0981da4SDimitry Andric
sizeNotPow2(unsigned TypeIdx)164eb11fae6SDimitry Andric LegalityPredicate LegalityPredicates::sizeNotPow2(unsigned TypeIdx) {
165eb11fae6SDimitry Andric return [=](const LegalityQuery &Query) {
166e6d15924SDimitry Andric const LLT QueryTy = Query.Types[TypeIdx];
1677fa27ce4SDimitry Andric return QueryTy.isScalar() &&
1687fa27ce4SDimitry Andric !llvm::has_single_bit<uint32_t>(QueryTy.getSizeInBits());
169eb11fae6SDimitry Andric };
170eb11fae6SDimitry Andric }
171eb11fae6SDimitry Andric
sizeIs(unsigned TypeIdx,unsigned Size)172cfca06d7SDimitry Andric LegalityPredicate LegalityPredicates::sizeIs(unsigned TypeIdx, unsigned Size) {
173cfca06d7SDimitry Andric return [=](const LegalityQuery &Query) {
174cfca06d7SDimitry Andric return Query.Types[TypeIdx].getSizeInBits() == Size;
175cfca06d7SDimitry Andric };
176cfca06d7SDimitry Andric }
177cfca06d7SDimitry Andric
sameSize(unsigned TypeIdx0,unsigned TypeIdx1)178e6d15924SDimitry Andric LegalityPredicate LegalityPredicates::sameSize(unsigned TypeIdx0,
179e6d15924SDimitry Andric unsigned TypeIdx1) {
180e6d15924SDimitry Andric return [=](const LegalityQuery &Query) {
181e6d15924SDimitry Andric return Query.Types[TypeIdx0].getSizeInBits() ==
182e6d15924SDimitry Andric Query.Types[TypeIdx1].getSizeInBits();
183e6d15924SDimitry Andric };
184e6d15924SDimitry Andric }
185e6d15924SDimitry Andric
memSizeInBytesNotPow2(unsigned MMOIdx)186eb11fae6SDimitry Andric LegalityPredicate LegalityPredicates::memSizeInBytesNotPow2(unsigned MMOIdx) {
187eb11fae6SDimitry Andric return [=](const LegalityQuery &Query) {
1887fa27ce4SDimitry Andric return !llvm::has_single_bit<uint32_t>(
1897fa27ce4SDimitry Andric Query.MMODescrs[MMOIdx].MemoryTy.getSizeInBytes());
190eb11fae6SDimitry Andric };
191eb11fae6SDimitry Andric }
192eb11fae6SDimitry Andric
memSizeNotByteSizePow2(unsigned MMOIdx)193145449b1SDimitry Andric LegalityPredicate LegalityPredicates::memSizeNotByteSizePow2(unsigned MMOIdx) {
194145449b1SDimitry Andric return [=](const LegalityQuery &Query) {
195145449b1SDimitry Andric const LLT MemTy = Query.MMODescrs[MMOIdx].MemoryTy;
1967fa27ce4SDimitry Andric return !MemTy.isByteSized() ||
1977fa27ce4SDimitry Andric !llvm::has_single_bit<uint32_t>(MemTy.getSizeInBytes());
198145449b1SDimitry Andric };
199145449b1SDimitry Andric }
200145449b1SDimitry Andric
numElementsNotPow2(unsigned TypeIdx)201eb11fae6SDimitry Andric LegalityPredicate LegalityPredicates::numElementsNotPow2(unsigned TypeIdx) {
202eb11fae6SDimitry Andric return [=](const LegalityQuery &Query) {
203e6d15924SDimitry Andric const LLT QueryTy = Query.Types[TypeIdx];
204e6d15924SDimitry Andric return QueryTy.isVector() && !isPowerOf2_32(QueryTy.getNumElements());
205eb11fae6SDimitry Andric };
206eb11fae6SDimitry Andric }
207eb11fae6SDimitry Andric
atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx,AtomicOrdering Ordering)208eb11fae6SDimitry Andric LegalityPredicate LegalityPredicates::atomicOrderingAtLeastOrStrongerThan(
209eb11fae6SDimitry Andric unsigned MMOIdx, AtomicOrdering Ordering) {
210eb11fae6SDimitry Andric return [=](const LegalityQuery &Query) {
211eb11fae6SDimitry Andric return isAtLeastOrStrongerThan(Query.MMODescrs[MMOIdx].Ordering, Ordering);
212eb11fae6SDimitry Andric };
213eb11fae6SDimitry Andric }
214