1 //===- lib/CodeGen/GlobalISel/LegalizerPredicates.cpp - Predicates --------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // A library of predicate factories to use for LegalityPredicate.
11 //===----------------------------------------------------------------------===//
13 // Enable optimizations to work around MSVC debug mode bug in 32-bit:
14 // https://developercommunity.visualstudio.com/content/problem/1179643/msvc-copies-overaligned-non-trivially-copyable-par.html
15 // FIXME: Remove this when the issue is closed.
16 #if defined(_MSC_VER) && !defined(__clang__) && defined(_M_IX86)
17 // We have to disable runtime checks in order to enable optimizations. This is
18 // done for the entire file because the problem is actually observed in STL
19 // template functions.
20 #pragma runtime_checks("", off)
21 #pragma optimize("gs", on)
24 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
28 LegalityPredicate
LegalityPredicates::typeIs(unsigned TypeIdx
, LLT Type
) {
30 [=](const LegalityQuery
&Query
) { return Query
.Types
[TypeIdx
] == Type
; };
34 LegalityPredicates::typeInSet(unsigned TypeIdx
,
35 std::initializer_list
<LLT
> TypesInit
) {
36 SmallVector
<LLT
, 4> Types
= TypesInit
;
37 return [=](const LegalityQuery
&Query
) {
38 return llvm::is_contained(Types
, Query
.Types
[TypeIdx
]);
42 LegalityPredicate
LegalityPredicates::typePairInSet(
43 unsigned TypeIdx0
, unsigned TypeIdx1
,
44 std::initializer_list
<std::pair
<LLT
, LLT
>> TypesInit
) {
45 SmallVector
<std::pair
<LLT
, LLT
>, 4> Types
= TypesInit
;
46 return [=](const LegalityQuery
&Query
) {
47 std::pair
<LLT
, LLT
> Match
= {Query
.Types
[TypeIdx0
], Query
.Types
[TypeIdx1
]};
48 return llvm::is_contained(Types
, Match
);
52 LegalityPredicate
LegalityPredicates::typePairAndMemDescInSet(
53 unsigned TypeIdx0
, unsigned TypeIdx1
, unsigned MMOIdx
,
54 std::initializer_list
<TypePairAndMemDesc
> TypesAndMemDescInit
) {
55 SmallVector
<TypePairAndMemDesc
, 4> TypesAndMemDesc
= TypesAndMemDescInit
;
56 return [=](const LegalityQuery
&Query
) {
57 TypePairAndMemDesc Match
= {Query
.Types
[TypeIdx0
], Query
.Types
[TypeIdx1
],
58 Query
.MMODescrs
[MMOIdx
].MemoryTy
,
59 Query
.MMODescrs
[MMOIdx
].AlignInBits
};
60 return llvm::any_of(TypesAndMemDesc
,
61 [=](const TypePairAndMemDesc
&Entry
) -> bool {
62 return Match
.isCompatible(Entry
);
67 LegalityPredicate
LegalityPredicates::isScalar(unsigned TypeIdx
) {
68 return [=](const LegalityQuery
&Query
) {
69 return Query
.Types
[TypeIdx
].isScalar();
73 LegalityPredicate
LegalityPredicates::isVector(unsigned TypeIdx
) {
74 return [=](const LegalityQuery
&Query
) {
75 return Query
.Types
[TypeIdx
].isVector();
79 LegalityPredicate
LegalityPredicates::isPointer(unsigned TypeIdx
) {
80 return [=](const LegalityQuery
&Query
) {
81 return Query
.Types
[TypeIdx
].isPointer();
85 LegalityPredicate
LegalityPredicates::isPointer(unsigned TypeIdx
,
87 return [=](const LegalityQuery
&Query
) {
88 LLT Ty
= Query
.Types
[TypeIdx
];
89 return Ty
.isPointer() && Ty
.getAddressSpace() == AddrSpace
;
93 LegalityPredicate
LegalityPredicates::elementTypeIs(unsigned TypeIdx
,
95 return [=](const LegalityQuery
&Query
) {
96 const LLT QueryTy
= Query
.Types
[TypeIdx
];
97 return QueryTy
.isVector() && QueryTy
.getElementType() == EltTy
;
101 LegalityPredicate
LegalityPredicates::scalarNarrowerThan(unsigned TypeIdx
,
103 return [=](const LegalityQuery
&Query
) {
104 const LLT QueryTy
= Query
.Types
[TypeIdx
];
105 return QueryTy
.isScalar() && QueryTy
.getSizeInBits() < Size
;
109 LegalityPredicate
LegalityPredicates::scalarWiderThan(unsigned TypeIdx
,
111 return [=](const LegalityQuery
&Query
) {
112 const LLT QueryTy
= Query
.Types
[TypeIdx
];
113 return QueryTy
.isScalar() && QueryTy
.getSizeInBits() > Size
;
117 LegalityPredicate
LegalityPredicates::smallerThan(unsigned TypeIdx0
,
119 return [=](const LegalityQuery
&Query
) {
120 return Query
.Types
[TypeIdx0
].getSizeInBits() <
121 Query
.Types
[TypeIdx1
].getSizeInBits();
125 LegalityPredicate
LegalityPredicates::largerThan(unsigned TypeIdx0
,
127 return [=](const LegalityQuery
&Query
) {
128 return Query
.Types
[TypeIdx0
].getSizeInBits() >
129 Query
.Types
[TypeIdx1
].getSizeInBits();
133 LegalityPredicate
LegalityPredicates::scalarOrEltNarrowerThan(unsigned TypeIdx
,
135 return [=](const LegalityQuery
&Query
) {
136 const LLT QueryTy
= Query
.Types
[TypeIdx
];
137 return QueryTy
.getScalarSizeInBits() < Size
;
141 LegalityPredicate
LegalityPredicates::scalarOrEltWiderThan(unsigned TypeIdx
,
143 return [=](const LegalityQuery
&Query
) {
144 const LLT QueryTy
= Query
.Types
[TypeIdx
];
145 return QueryTy
.getScalarSizeInBits() > Size
;
149 LegalityPredicate
LegalityPredicates::scalarOrEltSizeNotPow2(unsigned TypeIdx
) {
150 return [=](const LegalityQuery
&Query
) {
151 const LLT QueryTy
= Query
.Types
[TypeIdx
];
152 return !isPowerOf2_32(QueryTy
.getScalarSizeInBits());
156 LegalityPredicate
LegalityPredicates::sizeNotMultipleOf(unsigned TypeIdx
,
158 return [=](const LegalityQuery
&Query
) {
159 const LLT QueryTy
= Query
.Types
[TypeIdx
];
160 return QueryTy
.isScalar() && QueryTy
.getSizeInBits() % Size
!= 0;
164 LegalityPredicate
LegalityPredicates::sizeNotPow2(unsigned TypeIdx
) {
165 return [=](const LegalityQuery
&Query
) {
166 const LLT QueryTy
= Query
.Types
[TypeIdx
];
167 return QueryTy
.isScalar() &&
168 !llvm::has_single_bit
<uint32_t>(QueryTy
.getSizeInBits());
172 LegalityPredicate
LegalityPredicates::sizeIs(unsigned TypeIdx
, unsigned Size
) {
173 return [=](const LegalityQuery
&Query
) {
174 return Query
.Types
[TypeIdx
].getSizeInBits() == Size
;
178 LegalityPredicate
LegalityPredicates::sameSize(unsigned TypeIdx0
,
180 return [=](const LegalityQuery
&Query
) {
181 return Query
.Types
[TypeIdx0
].getSizeInBits() ==
182 Query
.Types
[TypeIdx1
].getSizeInBits();
186 LegalityPredicate
LegalityPredicates::memSizeInBytesNotPow2(unsigned MMOIdx
) {
187 return [=](const LegalityQuery
&Query
) {
188 return !llvm::has_single_bit
<uint32_t>(
189 Query
.MMODescrs
[MMOIdx
].MemoryTy
.getSizeInBytes());
193 LegalityPredicate
LegalityPredicates::memSizeNotByteSizePow2(unsigned MMOIdx
) {
194 return [=](const LegalityQuery
&Query
) {
195 const LLT MemTy
= Query
.MMODescrs
[MMOIdx
].MemoryTy
;
196 return !MemTy
.isByteSized() ||
197 !llvm::has_single_bit
<uint32_t>(MemTy
.getSizeInBytes());
201 LegalityPredicate
LegalityPredicates::numElementsNotPow2(unsigned TypeIdx
) {
202 return [=](const LegalityQuery
&Query
) {
203 const LLT QueryTy
= Query
.Types
[TypeIdx
];
204 return QueryTy
.isVector() && !isPowerOf2_32(QueryTy
.getNumElements());
208 LegalityPredicate
LegalityPredicates::atomicOrderingAtLeastOrStrongerThan(
209 unsigned MMOIdx
, AtomicOrdering Ordering
) {
210 return [=](const LegalityQuery
&Query
) {
211 return isAtLeastOrStrongerThan(Query
.MMODescrs
[MMOIdx
].Ordering
, Ordering
);