1 //===- lib/CodeGen/GlobalISel/LegalizerPredicates.cpp - Predicates --------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // A library of predicate factories to use for LegalityPredicate. 10 // 11 //===----------------------------------------------------------------------===// 12 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) 22 #endif 23 24 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" 25 26 using namespace llvm; 27 28 LegalityPredicate LegalityPredicates::typeIs(unsigned TypeIdx, LLT Type) { 29 return 30 [=](const LegalityQuery &Query) { return Query.Types[TypeIdx] == Type; }; 31 } 32 33 LegalityPredicate 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]); 39 }; 40 } 41 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); 49 }; 50 } 51 52 LegalityPredicate LegalityPredicates::typeTupleInSet( 53 unsigned TypeIdx0, unsigned TypeIdx1, unsigned TypeIdx2, 54 std::initializer_list<std::tuple<LLT, LLT, LLT>> TypesInit) { 55 SmallVector<std::tuple<LLT, LLT, LLT>, 4> Types = TypesInit; 56 return [=](const LegalityQuery &Query) { 57 std::tuple<LLT, LLT, LLT> Match = { 58 Query.Types[TypeIdx0], Query.Types[TypeIdx1], Query.Types[TypeIdx2]}; 59 return llvm::is_contained(Types, Match); 60 }; 61 } 62 63 LegalityPredicate LegalityPredicates::typePairAndMemDescInSet( 64 unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, 65 std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit) { 66 SmallVector<TypePairAndMemDesc, 4> TypesAndMemDesc = TypesAndMemDescInit; 67 return [=](const LegalityQuery &Query) { 68 TypePairAndMemDesc Match = {Query.Types[TypeIdx0], Query.Types[TypeIdx1], 69 Query.MMODescrs[MMOIdx].MemoryTy, 70 Query.MMODescrs[MMOIdx].AlignInBits}; 71 return llvm::any_of(TypesAndMemDesc, 72 [=](const TypePairAndMemDesc &Entry) -> bool { 73 return Match.isCompatible(Entry); 74 }); 75 }; 76 } 77 78 LegalityPredicate LegalityPredicates::isScalar(unsigned TypeIdx) { 79 return [=](const LegalityQuery &Query) { 80 return Query.Types[TypeIdx].isScalar(); 81 }; 82 } 83 84 LegalityPredicate LegalityPredicates::isVector(unsigned TypeIdx) { 85 return [=](const LegalityQuery &Query) { 86 return Query.Types[TypeIdx].isVector(); 87 }; 88 } 89 90 LegalityPredicate LegalityPredicates::isPointer(unsigned TypeIdx) { 91 return [=](const LegalityQuery &Query) { 92 return Query.Types[TypeIdx].isPointer(); 93 }; 94 } 95 96 LegalityPredicate LegalityPredicates::isPointer(unsigned TypeIdx, 97 unsigned AddrSpace) { 98 return [=](const LegalityQuery &Query) { 99 LLT Ty = Query.Types[TypeIdx]; 100 return Ty.isPointer() && Ty.getAddressSpace() == AddrSpace; 101 }; 102 } 103 104 LegalityPredicate LegalityPredicates::isPointerVector(unsigned TypeIdx) { 105 return [=](const LegalityQuery &Query) { 106 return Query.Types[TypeIdx].isPointerVector(); 107 }; 108 } 109 110 LegalityPredicate LegalityPredicates::elementTypeIs(unsigned TypeIdx, 111 LLT EltTy) { 112 return [=](const LegalityQuery &Query) { 113 const LLT QueryTy = Query.Types[TypeIdx]; 114 return QueryTy.isVector() && QueryTy.getElementType() == EltTy; 115 }; 116 } 117 118 LegalityPredicate LegalityPredicates::scalarNarrowerThan(unsigned TypeIdx, 119 unsigned Size) { 120 return [=](const LegalityQuery &Query) { 121 const LLT QueryTy = Query.Types[TypeIdx]; 122 return QueryTy.isScalar() && QueryTy.getSizeInBits() < Size; 123 }; 124 } 125 126 LegalityPredicate LegalityPredicates::scalarWiderThan(unsigned TypeIdx, 127 unsigned Size) { 128 return [=](const LegalityQuery &Query) { 129 const LLT QueryTy = Query.Types[TypeIdx]; 130 return QueryTy.isScalar() && QueryTy.getSizeInBits() > Size; 131 }; 132 } 133 134 LegalityPredicate LegalityPredicates::smallerThan(unsigned TypeIdx0, 135 unsigned TypeIdx1) { 136 return [=](const LegalityQuery &Query) { 137 return Query.Types[TypeIdx0].getSizeInBits() < 138 Query.Types[TypeIdx1].getSizeInBits(); 139 }; 140 } 141 142 LegalityPredicate LegalityPredicates::largerThan(unsigned TypeIdx0, 143 unsigned TypeIdx1) { 144 return [=](const LegalityQuery &Query) { 145 return Query.Types[TypeIdx0].getSizeInBits() > 146 Query.Types[TypeIdx1].getSizeInBits(); 147 }; 148 } 149 150 LegalityPredicate LegalityPredicates::scalarOrEltNarrowerThan(unsigned TypeIdx, 151 unsigned Size) { 152 return [=](const LegalityQuery &Query) { 153 const LLT QueryTy = Query.Types[TypeIdx]; 154 return QueryTy.getScalarSizeInBits() < Size; 155 }; 156 } 157 158 LegalityPredicate LegalityPredicates::scalarOrEltWiderThan(unsigned TypeIdx, 159 unsigned Size) { 160 return [=](const LegalityQuery &Query) { 161 const LLT QueryTy = Query.Types[TypeIdx]; 162 return QueryTy.getScalarSizeInBits() > Size; 163 }; 164 } 165 166 LegalityPredicate LegalityPredicates::scalarOrEltSizeNotPow2(unsigned TypeIdx) { 167 return [=](const LegalityQuery &Query) { 168 const LLT QueryTy = Query.Types[TypeIdx]; 169 return !isPowerOf2_32(QueryTy.getScalarSizeInBits()); 170 }; 171 } 172 173 LegalityPredicate LegalityPredicates::sizeNotMultipleOf(unsigned TypeIdx, 174 unsigned Size) { 175 return [=](const LegalityQuery &Query) { 176 const LLT QueryTy = Query.Types[TypeIdx]; 177 return QueryTy.isScalar() && QueryTy.getSizeInBits() % Size != 0; 178 }; 179 } 180 181 LegalityPredicate LegalityPredicates::sizeNotPow2(unsigned TypeIdx) { 182 return [=](const LegalityQuery &Query) { 183 const LLT QueryTy = Query.Types[TypeIdx]; 184 return QueryTy.isScalar() && 185 !llvm::has_single_bit<uint32_t>(QueryTy.getSizeInBits()); 186 }; 187 } 188 189 LegalityPredicate LegalityPredicates::sizeIs(unsigned TypeIdx, unsigned Size) { 190 return [=](const LegalityQuery &Query) { 191 return Query.Types[TypeIdx].getSizeInBits() == Size; 192 }; 193 } 194 195 LegalityPredicate LegalityPredicates::sameSize(unsigned TypeIdx0, 196 unsigned TypeIdx1) { 197 return [=](const LegalityQuery &Query) { 198 return Query.Types[TypeIdx0].getSizeInBits() == 199 Query.Types[TypeIdx1].getSizeInBits(); 200 }; 201 } 202 203 LegalityPredicate LegalityPredicates::memSizeInBytesNotPow2(unsigned MMOIdx) { 204 return [=](const LegalityQuery &Query) { 205 return !llvm::has_single_bit<uint32_t>( 206 Query.MMODescrs[MMOIdx].MemoryTy.getSizeInBytes()); 207 }; 208 } 209 210 LegalityPredicate LegalityPredicates::memSizeNotByteSizePow2(unsigned MMOIdx) { 211 return [=](const LegalityQuery &Query) { 212 const LLT MemTy = Query.MMODescrs[MMOIdx].MemoryTy; 213 return !MemTy.isByteSized() || 214 !llvm::has_single_bit<uint32_t>( 215 MemTy.getSizeInBytes().getKnownMinValue()); 216 }; 217 } 218 219 LegalityPredicate LegalityPredicates::numElementsNotPow2(unsigned TypeIdx) { 220 return [=](const LegalityQuery &Query) { 221 const LLT QueryTy = Query.Types[TypeIdx]; 222 return QueryTy.isFixedVector() && !isPowerOf2_32(QueryTy.getNumElements()); 223 }; 224 } 225 226 LegalityPredicate LegalityPredicates::atomicOrderingAtLeastOrStrongerThan( 227 unsigned MMOIdx, AtomicOrdering Ordering) { 228 return [=](const LegalityQuery &Query) { 229 return isAtLeastOrStrongerThan(Query.MMODescrs[MMOIdx].Ordering, Ordering); 230 }; 231 } 232