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::elementTypeIs(unsigned TypeIdx, 105 LLT EltTy) { 106 return [=](const LegalityQuery &Query) { 107 const LLT QueryTy = Query.Types[TypeIdx]; 108 return QueryTy.isVector() && QueryTy.getElementType() == EltTy; 109 }; 110 } 111 112 LegalityPredicate LegalityPredicates::scalarNarrowerThan(unsigned TypeIdx, 113 unsigned Size) { 114 return [=](const LegalityQuery &Query) { 115 const LLT QueryTy = Query.Types[TypeIdx]; 116 return QueryTy.isScalar() && QueryTy.getSizeInBits() < Size; 117 }; 118 } 119 120 LegalityPredicate LegalityPredicates::scalarWiderThan(unsigned TypeIdx, 121 unsigned Size) { 122 return [=](const LegalityQuery &Query) { 123 const LLT QueryTy = Query.Types[TypeIdx]; 124 return QueryTy.isScalar() && QueryTy.getSizeInBits() > Size; 125 }; 126 } 127 128 LegalityPredicate LegalityPredicates::smallerThan(unsigned TypeIdx0, 129 unsigned TypeIdx1) { 130 return [=](const LegalityQuery &Query) { 131 return Query.Types[TypeIdx0].getSizeInBits() < 132 Query.Types[TypeIdx1].getSizeInBits(); 133 }; 134 } 135 136 LegalityPredicate LegalityPredicates::largerThan(unsigned TypeIdx0, 137 unsigned TypeIdx1) { 138 return [=](const LegalityQuery &Query) { 139 return Query.Types[TypeIdx0].getSizeInBits() > 140 Query.Types[TypeIdx1].getSizeInBits(); 141 }; 142 } 143 144 LegalityPredicate LegalityPredicates::scalarOrEltNarrowerThan(unsigned TypeIdx, 145 unsigned Size) { 146 return [=](const LegalityQuery &Query) { 147 const LLT QueryTy = Query.Types[TypeIdx]; 148 return QueryTy.getScalarSizeInBits() < Size; 149 }; 150 } 151 152 LegalityPredicate LegalityPredicates::scalarOrEltWiderThan(unsigned TypeIdx, 153 unsigned Size) { 154 return [=](const LegalityQuery &Query) { 155 const LLT QueryTy = Query.Types[TypeIdx]; 156 return QueryTy.getScalarSizeInBits() > Size; 157 }; 158 } 159 160 LegalityPredicate LegalityPredicates::scalarOrEltSizeNotPow2(unsigned TypeIdx) { 161 return [=](const LegalityQuery &Query) { 162 const LLT QueryTy = Query.Types[TypeIdx]; 163 return !isPowerOf2_32(QueryTy.getScalarSizeInBits()); 164 }; 165 } 166 167 LegalityPredicate LegalityPredicates::sizeNotMultipleOf(unsigned TypeIdx, 168 unsigned Size) { 169 return [=](const LegalityQuery &Query) { 170 const LLT QueryTy = Query.Types[TypeIdx]; 171 return QueryTy.isScalar() && QueryTy.getSizeInBits() % Size != 0; 172 }; 173 } 174 175 LegalityPredicate LegalityPredicates::sizeNotPow2(unsigned TypeIdx) { 176 return [=](const LegalityQuery &Query) { 177 const LLT QueryTy = Query.Types[TypeIdx]; 178 return QueryTy.isScalar() && 179 !llvm::has_single_bit<uint32_t>(QueryTy.getSizeInBits()); 180 }; 181 } 182 183 LegalityPredicate LegalityPredicates::sizeIs(unsigned TypeIdx, unsigned Size) { 184 return [=](const LegalityQuery &Query) { 185 return Query.Types[TypeIdx].getSizeInBits() == Size; 186 }; 187 } 188 189 LegalityPredicate LegalityPredicates::sameSize(unsigned TypeIdx0, 190 unsigned TypeIdx1) { 191 return [=](const LegalityQuery &Query) { 192 return Query.Types[TypeIdx0].getSizeInBits() == 193 Query.Types[TypeIdx1].getSizeInBits(); 194 }; 195 } 196 197 LegalityPredicate LegalityPredicates::memSizeInBytesNotPow2(unsigned MMOIdx) { 198 return [=](const LegalityQuery &Query) { 199 return !llvm::has_single_bit<uint32_t>( 200 Query.MMODescrs[MMOIdx].MemoryTy.getSizeInBytes()); 201 }; 202 } 203 204 LegalityPredicate LegalityPredicates::memSizeNotByteSizePow2(unsigned MMOIdx) { 205 return [=](const LegalityQuery &Query) { 206 const LLT MemTy = Query.MMODescrs[MMOIdx].MemoryTy; 207 return !MemTy.isByteSized() || 208 !llvm::has_single_bit<uint32_t>( 209 MemTy.getSizeInBytes().getKnownMinValue()); 210 }; 211 } 212 213 LegalityPredicate LegalityPredicates::numElementsNotPow2(unsigned TypeIdx) { 214 return [=](const LegalityQuery &Query) { 215 const LLT QueryTy = Query.Types[TypeIdx]; 216 return QueryTy.isFixedVector() && !isPowerOf2_32(QueryTy.getNumElements()); 217 }; 218 } 219 220 LegalityPredicate LegalityPredicates::atomicOrderingAtLeastOrStrongerThan( 221 unsigned MMOIdx, AtomicOrdering Ordering) { 222 return [=](const LegalityQuery &Query) { 223 return isAtLeastOrStrongerThan(Query.MMODescrs[MMOIdx].Ordering, Ordering); 224 }; 225 } 226