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::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); 63 }); 64 }; 65 } 66 67 LegalityPredicate LegalityPredicates::isScalar(unsigned TypeIdx) { 68 return [=](const LegalityQuery &Query) { 69 return Query.Types[TypeIdx].isScalar(); 70 }; 71 } 72 73 LegalityPredicate LegalityPredicates::isVector(unsigned TypeIdx) { 74 return [=](const LegalityQuery &Query) { 75 return Query.Types[TypeIdx].isVector(); 76 }; 77 } 78 79 LegalityPredicate LegalityPredicates::isPointer(unsigned TypeIdx) { 80 return [=](const LegalityQuery &Query) { 81 return Query.Types[TypeIdx].isPointer(); 82 }; 83 } 84 85 LegalityPredicate LegalityPredicates::isPointer(unsigned TypeIdx, 86 unsigned AddrSpace) { 87 return [=](const LegalityQuery &Query) { 88 LLT Ty = Query.Types[TypeIdx]; 89 return Ty.isPointer() && Ty.getAddressSpace() == AddrSpace; 90 }; 91 } 92 93 LegalityPredicate LegalityPredicates::elementTypeIs(unsigned TypeIdx, 94 LLT EltTy) { 95 return [=](const LegalityQuery &Query) { 96 const LLT QueryTy = Query.Types[TypeIdx]; 97 return QueryTy.isVector() && QueryTy.getElementType() == EltTy; 98 }; 99 } 100 101 LegalityPredicate LegalityPredicates::scalarNarrowerThan(unsigned TypeIdx, 102 unsigned Size) { 103 return [=](const LegalityQuery &Query) { 104 const LLT QueryTy = Query.Types[TypeIdx]; 105 return QueryTy.isScalar() && QueryTy.getSizeInBits() < Size; 106 }; 107 } 108 109 LegalityPredicate LegalityPredicates::scalarWiderThan(unsigned TypeIdx, 110 unsigned Size) { 111 return [=](const LegalityQuery &Query) { 112 const LLT QueryTy = Query.Types[TypeIdx]; 113 return QueryTy.isScalar() && QueryTy.getSizeInBits() > Size; 114 }; 115 } 116 117 LegalityPredicate LegalityPredicates::smallerThan(unsigned TypeIdx0, 118 unsigned TypeIdx1) { 119 return [=](const LegalityQuery &Query) { 120 return Query.Types[TypeIdx0].getSizeInBits() < 121 Query.Types[TypeIdx1].getSizeInBits(); 122 }; 123 } 124 125 LegalityPredicate LegalityPredicates::largerThan(unsigned TypeIdx0, 126 unsigned TypeIdx1) { 127 return [=](const LegalityQuery &Query) { 128 return Query.Types[TypeIdx0].getSizeInBits() > 129 Query.Types[TypeIdx1].getSizeInBits(); 130 }; 131 } 132 133 LegalityPredicate LegalityPredicates::scalarOrEltNarrowerThan(unsigned TypeIdx, 134 unsigned Size) { 135 return [=](const LegalityQuery &Query) { 136 const LLT QueryTy = Query.Types[TypeIdx]; 137 return QueryTy.getScalarSizeInBits() < Size; 138 }; 139 } 140 141 LegalityPredicate LegalityPredicates::scalarOrEltWiderThan(unsigned TypeIdx, 142 unsigned Size) { 143 return [=](const LegalityQuery &Query) { 144 const LLT QueryTy = Query.Types[TypeIdx]; 145 return QueryTy.getScalarSizeInBits() > Size; 146 }; 147 } 148 149 LegalityPredicate LegalityPredicates::scalarOrEltSizeNotPow2(unsigned TypeIdx) { 150 return [=](const LegalityQuery &Query) { 151 const LLT QueryTy = Query.Types[TypeIdx]; 152 return !isPowerOf2_32(QueryTy.getScalarSizeInBits()); 153 }; 154 } 155 156 LegalityPredicate LegalityPredicates::sizeNotMultipleOf(unsigned TypeIdx, 157 unsigned Size) { 158 return [=](const LegalityQuery &Query) { 159 const LLT QueryTy = Query.Types[TypeIdx]; 160 return QueryTy.isScalar() && QueryTy.getSizeInBits() % Size != 0; 161 }; 162 } 163 164 LegalityPredicate LegalityPredicates::sizeNotPow2(unsigned TypeIdx) { 165 return [=](const LegalityQuery &Query) { 166 const LLT QueryTy = Query.Types[TypeIdx]; 167 return QueryTy.isScalar() && !isPowerOf2_32(QueryTy.getSizeInBits()); 168 }; 169 } 170 171 LegalityPredicate LegalityPredicates::sizeIs(unsigned TypeIdx, unsigned Size) { 172 return [=](const LegalityQuery &Query) { 173 return Query.Types[TypeIdx].getSizeInBits() == Size; 174 }; 175 } 176 177 LegalityPredicate LegalityPredicates::sameSize(unsigned TypeIdx0, 178 unsigned TypeIdx1) { 179 return [=](const LegalityQuery &Query) { 180 return Query.Types[TypeIdx0].getSizeInBits() == 181 Query.Types[TypeIdx1].getSizeInBits(); 182 }; 183 } 184 185 LegalityPredicate LegalityPredicates::memSizeInBytesNotPow2(unsigned MMOIdx) { 186 return [=](const LegalityQuery &Query) { 187 return !isPowerOf2_32(Query.MMODescrs[MMOIdx].MemoryTy.getSizeInBytes()); 188 }; 189 } 190 191 LegalityPredicate LegalityPredicates::memSizeNotByteSizePow2(unsigned MMOIdx) { 192 return [=](const LegalityQuery &Query) { 193 const LLT MemTy = Query.MMODescrs[MMOIdx].MemoryTy; 194 return !MemTy.isByteSized() || !isPowerOf2_32(MemTy.getSizeInBytes()); 195 }; 196 } 197 198 LegalityPredicate LegalityPredicates::numElementsNotPow2(unsigned TypeIdx) { 199 return [=](const LegalityQuery &Query) { 200 const LLT QueryTy = Query.Types[TypeIdx]; 201 return QueryTy.isVector() && !isPowerOf2_32(QueryTy.getNumElements()); 202 }; 203 } 204 205 LegalityPredicate LegalityPredicates::atomicOrderingAtLeastOrStrongerThan( 206 unsigned MMOIdx, AtomicOrdering Ordering) { 207 return [=](const LegalityQuery &Query) { 208 return isAtLeastOrStrongerThan(Query.MMODescrs[MMOIdx].Ordering, Ordering); 209 }; 210 } 211