1 //===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- C++ -*-===// 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 /// \file 9 /// Interface for Targets to specify which operations they can successfully 10 /// select and how the others should be expanded most efficiently. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H 15 #define LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H 16 17 #include "llvm/ADT/DenseMap.h" 18 #include "llvm/ADT/None.h" 19 #include "llvm/ADT/Optional.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/ADT/SmallBitVector.h" 22 #include "llvm/ADT/SmallVector.h" 23 #include "llvm/CodeGen/MachineFunction.h" 24 #include "llvm/CodeGen/TargetOpcodes.h" 25 #include "llvm/Support/CommandLine.h" 26 #include "llvm/Support/LowLevelTypeImpl.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include <cassert> 29 #include <cstdint> 30 #include <tuple> 31 #include <unordered_map> 32 #include <utility> 33 34 namespace llvm { 35 36 extern cl::opt<bool> DisableGISelLegalityCheck; 37 38 class LegalizerHelper; 39 class MachineInstr; 40 class MachineRegisterInfo; 41 class MCInstrInfo; 42 class GISelChangeObserver; 43 44 namespace LegalizeActions { 45 enum LegalizeAction : std::uint8_t { 46 /// The operation is expected to be selectable directly by the target, and 47 /// no transformation is necessary. 48 Legal, 49 50 /// The operation should be synthesized from multiple instructions acting on 51 /// a narrower scalar base-type. For example a 64-bit add might be 52 /// implemented in terms of 32-bit add-with-carry. 53 NarrowScalar, 54 55 /// The operation should be implemented in terms of a wider scalar 56 /// base-type. For example a <2 x s8> add could be implemented as a <2 57 /// x s32> add (ignoring the high bits). 58 WidenScalar, 59 60 /// The (vector) operation should be implemented by splitting it into 61 /// sub-vectors where the operation is legal. For example a <8 x s64> add 62 /// might be implemented as 4 separate <2 x s64> adds. 63 FewerElements, 64 65 /// The (vector) operation should be implemented by widening the input 66 /// vector and ignoring the lanes added by doing so. For example <2 x i8> is 67 /// rarely legal, but you might perform an <8 x i8> and then only look at 68 /// the first two results. 69 MoreElements, 70 71 /// Perform the operation on a different, but equivalently sized type. 72 Bitcast, 73 74 /// The operation itself must be expressed in terms of simpler actions on 75 /// this target. E.g. a SREM replaced by an SDIV and subtraction. 76 Lower, 77 78 /// The operation should be implemented as a call to some kind of runtime 79 /// support library. For example this usually happens on machines that don't 80 /// support floating-point operations natively. 81 Libcall, 82 83 /// The target wants to do something special with this combination of 84 /// operand and type. A callback will be issued when it is needed. 85 Custom, 86 87 /// This operation is completely unsupported on the target. A programming 88 /// error has occurred. 89 Unsupported, 90 91 /// Sentinel value for when no action was found in the specified table. 92 NotFound, 93 94 /// Fall back onto the old rules. 95 /// TODO: Remove this once we've migrated 96 UseLegacyRules, 97 }; 98 } // end namespace LegalizeActions 99 raw_ostream &operator<<(raw_ostream &OS, LegalizeActions::LegalizeAction Action); 100 101 using LegalizeActions::LegalizeAction; 102 103 /// Legalization is decided based on an instruction's opcode, which type slot 104 /// we're considering, and what the existing type is. These aspects are gathered 105 /// together for convenience in the InstrAspect class. 106 struct InstrAspect { 107 unsigned Opcode; 108 unsigned Idx = 0; 109 LLT Type; 110 111 InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {} 112 InstrAspect(unsigned Opcode, unsigned Idx, LLT Type) 113 : Opcode(Opcode), Idx(Idx), Type(Type) {} 114 115 bool operator==(const InstrAspect &RHS) const { 116 return Opcode == RHS.Opcode && Idx == RHS.Idx && Type == RHS.Type; 117 } 118 }; 119 120 /// The LegalityQuery object bundles together all the information that's needed 121 /// to decide whether a given operation is legal or not. 122 /// For efficiency, it doesn't make a copy of Types so care must be taken not 123 /// to free it before using the query. 124 struct LegalityQuery { 125 unsigned Opcode; 126 ArrayRef<LLT> Types; 127 128 struct MemDesc { 129 uint64_t SizeInBits; 130 uint64_t AlignInBits; 131 AtomicOrdering Ordering; 132 }; 133 134 /// Operations which require memory can use this to place requirements on the 135 /// memory type for each MMO. 136 ArrayRef<MemDesc> MMODescrs; 137 138 constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types, 139 const ArrayRef<MemDesc> MMODescrs) 140 : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {} 141 constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types) 142 : LegalityQuery(Opcode, Types, {}) {} 143 144 raw_ostream &print(raw_ostream &OS) const; 145 }; 146 147 /// The result of a query. It either indicates a final answer of Legal or 148 /// Unsupported or describes an action that must be taken to make an operation 149 /// more legal. 150 struct LegalizeActionStep { 151 /// The action to take or the final answer. 152 LegalizeAction Action; 153 /// If describing an action, the type index to change. Otherwise zero. 154 unsigned TypeIdx; 155 /// If describing an action, the new type for TypeIdx. Otherwise LLT{}. 156 LLT NewType; 157 158 LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx, 159 const LLT NewType) 160 : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {} 161 162 bool operator==(const LegalizeActionStep &RHS) const { 163 return std::tie(Action, TypeIdx, NewType) == 164 std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType); 165 } 166 }; 167 168 using LegalityPredicate = std::function<bool (const LegalityQuery &)>; 169 using LegalizeMutation = 170 std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>; 171 172 namespace LegalityPredicates { 173 struct TypePairAndMemDesc { 174 LLT Type0; 175 LLT Type1; 176 uint64_t MemSize; 177 uint64_t Align; 178 179 bool operator==(const TypePairAndMemDesc &Other) const { 180 return Type0 == Other.Type0 && Type1 == Other.Type1 && 181 Align == Other.Align && 182 MemSize == Other.MemSize; 183 } 184 185 /// \returns true if this memory access is legal with for the access described 186 /// by \p Other (The alignment is sufficient for the size and result type). 187 bool isCompatible(const TypePairAndMemDesc &Other) const { 188 return Type0 == Other.Type0 && Type1 == Other.Type1 && 189 Align >= Other.Align && 190 MemSize == Other.MemSize; 191 } 192 }; 193 194 /// True iff P0 and P1 are true. 195 template<typename Predicate> 196 Predicate all(Predicate P0, Predicate P1) { 197 return [=](const LegalityQuery &Query) { 198 return P0(Query) && P1(Query); 199 }; 200 } 201 /// True iff all given predicates are true. 202 template<typename Predicate, typename... Args> 203 Predicate all(Predicate P0, Predicate P1, Args... args) { 204 return all(all(P0, P1), args...); 205 } 206 207 /// True iff P0 or P1 are true. 208 template<typename Predicate> 209 Predicate any(Predicate P0, Predicate P1) { 210 return [=](const LegalityQuery &Query) { 211 return P0(Query) || P1(Query); 212 }; 213 } 214 /// True iff any given predicates are true. 215 template<typename Predicate, typename... Args> 216 Predicate any(Predicate P0, Predicate P1, Args... args) { 217 return any(any(P0, P1), args...); 218 } 219 220 /// True iff the given type index is the specified type. 221 LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit); 222 /// True iff the given type index is one of the specified types. 223 LegalityPredicate typeInSet(unsigned TypeIdx, 224 std::initializer_list<LLT> TypesInit); 225 226 /// True iff the given type index is not the specified type. 227 inline LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type) { 228 return [=](const LegalityQuery &Query) { 229 return Query.Types[TypeIdx] != Type; 230 }; 231 } 232 233 /// True iff the given types for the given pair of type indexes is one of the 234 /// specified type pairs. 235 LegalityPredicate 236 typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1, 237 std::initializer_list<std::pair<LLT, LLT>> TypesInit); 238 /// True iff the given types for the given pair of type indexes is one of the 239 /// specified type pairs. 240 LegalityPredicate typePairAndMemDescInSet( 241 unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, 242 std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit); 243 /// True iff the specified type index is a scalar. 244 LegalityPredicate isScalar(unsigned TypeIdx); 245 /// True iff the specified type index is a vector. 246 LegalityPredicate isVector(unsigned TypeIdx); 247 /// True iff the specified type index is a pointer (with any address space). 248 LegalityPredicate isPointer(unsigned TypeIdx); 249 /// True iff the specified type index is a pointer with the specified address 250 /// space. 251 LegalityPredicate isPointer(unsigned TypeIdx, unsigned AddrSpace); 252 253 /// True if the type index is a vector with element type \p EltTy 254 LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy); 255 256 /// True iff the specified type index is a scalar that's narrower than the given 257 /// size. 258 LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size); 259 260 /// True iff the specified type index is a scalar that's wider than the given 261 /// size. 262 LegalityPredicate scalarWiderThan(unsigned TypeIdx, unsigned Size); 263 264 /// True iff the specified type index is a scalar or vector with an element type 265 /// that's narrower than the given size. 266 LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size); 267 268 /// True iff the specified type index is a scalar or a vector with an element 269 /// type that's wider than the given size. 270 LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size); 271 272 /// True iff the specified type index is a scalar whose size is not a power of 273 /// 2. 274 LegalityPredicate sizeNotPow2(unsigned TypeIdx); 275 276 /// True iff the specified type index is a scalar or vector whose element size 277 /// is not a power of 2. 278 LegalityPredicate scalarOrEltSizeNotPow2(unsigned TypeIdx); 279 280 /// True if the total bitwidth of the specified type index is \p Size bits. 281 LegalityPredicate sizeIs(unsigned TypeIdx, unsigned Size); 282 283 /// True iff the specified type indices are both the same bit size. 284 LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1); 285 286 /// True iff the first type index has a larger total bit size than second type 287 /// index. 288 LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1); 289 290 /// True iff the first type index has a smaller total bit size than second type 291 /// index. 292 LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1); 293 294 /// True iff the specified MMO index has a size that is not a power of 2 295 LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx); 296 /// True iff the specified type index is a vector whose element count is not a 297 /// power of 2. 298 LegalityPredicate numElementsNotPow2(unsigned TypeIdx); 299 /// True iff the specified MMO index has at an atomic ordering of at Ordering or 300 /// stronger. 301 LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx, 302 AtomicOrdering Ordering); 303 } // end namespace LegalityPredicates 304 305 namespace LegalizeMutations { 306 /// Select this specific type for the given type index. 307 LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty); 308 309 /// Keep the same type as the given type index. 310 LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx); 311 312 /// Keep the same scalar or element type as the given type index. 313 LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx); 314 315 /// Keep the same scalar or element type as the given type. 316 LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty); 317 318 /// Change the scalar size or element size to have the same scalar size as type 319 /// index \p FromIndex. Unlike changeElementTo, this discards pointer types and 320 /// only changes the size. 321 LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx); 322 323 /// Widen the scalar type or vector element type for the given type index to the 324 /// next power of 2. 325 LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0); 326 327 /// Add more elements to the type for the given type index to the next power of 328 /// 2. 329 LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0); 330 /// Break up the vector type for the given type index into the element type. 331 LegalizeMutation scalarize(unsigned TypeIdx); 332 } // end namespace LegalizeMutations 333 334 /// A single rule in a legalizer info ruleset. 335 /// The specified action is chosen when the predicate is true. Where appropriate 336 /// for the action (e.g. for WidenScalar) the new type is selected using the 337 /// given mutator. 338 class LegalizeRule { 339 LegalityPredicate Predicate; 340 LegalizeAction Action; 341 LegalizeMutation Mutation; 342 343 public: 344 LegalizeRule(LegalityPredicate Predicate, LegalizeAction Action, 345 LegalizeMutation Mutation = nullptr) 346 : Predicate(Predicate), Action(Action), Mutation(Mutation) {} 347 348 /// Test whether the LegalityQuery matches. 349 bool match(const LegalityQuery &Query) const { 350 return Predicate(Query); 351 } 352 353 LegalizeAction getAction() const { return Action; } 354 355 /// Determine the change to make. 356 std::pair<unsigned, LLT> determineMutation(const LegalityQuery &Query) const { 357 if (Mutation) 358 return Mutation(Query); 359 return std::make_pair(0, LLT{}); 360 } 361 }; 362 363 class LegalizeRuleSet { 364 /// When non-zero, the opcode we are an alias of 365 unsigned AliasOf; 366 /// If true, there is another opcode that aliases this one 367 bool IsAliasedByAnother; 368 SmallVector<LegalizeRule, 2> Rules; 369 370 #ifndef NDEBUG 371 /// If bit I is set, this rule set contains a rule that may handle (predicate 372 /// or perform an action upon (or both)) the type index I. The uncertainty 373 /// comes from free-form rules executing user-provided lambda functions. We 374 /// conservatively assume such rules do the right thing and cover all type 375 /// indices. The bitset is intentionally 1 bit wider than it absolutely needs 376 /// to be to distinguish such cases from the cases where all type indices are 377 /// individually handled. 378 SmallBitVector TypeIdxsCovered{MCOI::OPERAND_LAST_GENERIC - 379 MCOI::OPERAND_FIRST_GENERIC + 2}; 380 SmallBitVector ImmIdxsCovered{MCOI::OPERAND_LAST_GENERIC_IMM - 381 MCOI::OPERAND_FIRST_GENERIC_IMM + 2}; 382 #endif 383 384 unsigned typeIdx(unsigned TypeIdx) { 385 assert(TypeIdx <= 386 (MCOI::OPERAND_LAST_GENERIC - MCOI::OPERAND_FIRST_GENERIC) && 387 "Type Index is out of bounds"); 388 #ifndef NDEBUG 389 TypeIdxsCovered.set(TypeIdx); 390 #endif 391 return TypeIdx; 392 } 393 394 unsigned immIdx(unsigned ImmIdx) { 395 assert(ImmIdx <= (MCOI::OPERAND_LAST_GENERIC_IMM - 396 MCOI::OPERAND_FIRST_GENERIC_IMM) && 397 "Imm Index is out of bounds"); 398 #ifndef NDEBUG 399 ImmIdxsCovered.set(ImmIdx); 400 #endif 401 return ImmIdx; 402 } 403 404 void markAllIdxsAsCovered() { 405 #ifndef NDEBUG 406 TypeIdxsCovered.set(); 407 ImmIdxsCovered.set(); 408 #endif 409 } 410 411 void add(const LegalizeRule &Rule) { 412 assert(AliasOf == 0 && 413 "RuleSet is aliased, change the representative opcode instead"); 414 Rules.push_back(Rule); 415 } 416 417 static bool always(const LegalityQuery &) { return true; } 418 419 /// Use the given action when the predicate is true. 420 /// Action should not be an action that requires mutation. 421 LegalizeRuleSet &actionIf(LegalizeAction Action, 422 LegalityPredicate Predicate) { 423 add({Predicate, Action}); 424 return *this; 425 } 426 /// Use the given action when the predicate is true. 427 /// Action should be an action that requires mutation. 428 LegalizeRuleSet &actionIf(LegalizeAction Action, LegalityPredicate Predicate, 429 LegalizeMutation Mutation) { 430 add({Predicate, Action, Mutation}); 431 return *this; 432 } 433 /// Use the given action when type index 0 is any type in the given list. 434 /// Action should not be an action that requires mutation. 435 LegalizeRuleSet &actionFor(LegalizeAction Action, 436 std::initializer_list<LLT> Types) { 437 using namespace LegalityPredicates; 438 return actionIf(Action, typeInSet(typeIdx(0), Types)); 439 } 440 /// Use the given action when type index 0 is any type in the given list. 441 /// Action should be an action that requires mutation. 442 LegalizeRuleSet &actionFor(LegalizeAction Action, 443 std::initializer_list<LLT> Types, 444 LegalizeMutation Mutation) { 445 using namespace LegalityPredicates; 446 return actionIf(Action, typeInSet(typeIdx(0), Types), Mutation); 447 } 448 /// Use the given action when type indexes 0 and 1 is any type pair in the 449 /// given list. 450 /// Action should not be an action that requires mutation. 451 LegalizeRuleSet &actionFor(LegalizeAction Action, 452 std::initializer_list<std::pair<LLT, LLT>> Types) { 453 using namespace LegalityPredicates; 454 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types)); 455 } 456 /// Use the given action when type indexes 0 and 1 is any type pair in the 457 /// given list. 458 /// Action should be an action that requires mutation. 459 LegalizeRuleSet &actionFor(LegalizeAction Action, 460 std::initializer_list<std::pair<LLT, LLT>> Types, 461 LegalizeMutation Mutation) { 462 using namespace LegalityPredicates; 463 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types), 464 Mutation); 465 } 466 /// Use the given action when type index 0 is any type in the given list and 467 /// imm index 0 is anything. Action should not be an action that requires 468 /// mutation. 469 LegalizeRuleSet &actionForTypeWithAnyImm(LegalizeAction Action, 470 std::initializer_list<LLT> Types) { 471 using namespace LegalityPredicates; 472 immIdx(0); // Inform verifier imm idx 0 is handled. 473 return actionIf(Action, typeInSet(typeIdx(0), Types)); 474 } 475 476 LegalizeRuleSet &actionForTypeWithAnyImm( 477 LegalizeAction Action, std::initializer_list<std::pair<LLT, LLT>> Types) { 478 using namespace LegalityPredicates; 479 immIdx(0); // Inform verifier imm idx 0 is handled. 480 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types)); 481 } 482 483 /// Use the given action when type indexes 0 and 1 are both in the given list. 484 /// That is, the type pair is in the cartesian product of the list. 485 /// Action should not be an action that requires mutation. 486 LegalizeRuleSet &actionForCartesianProduct(LegalizeAction Action, 487 std::initializer_list<LLT> Types) { 488 using namespace LegalityPredicates; 489 return actionIf(Action, all(typeInSet(typeIdx(0), Types), 490 typeInSet(typeIdx(1), Types))); 491 } 492 /// Use the given action when type indexes 0 and 1 are both in their 493 /// respective lists. 494 /// That is, the type pair is in the cartesian product of the lists 495 /// Action should not be an action that requires mutation. 496 LegalizeRuleSet & 497 actionForCartesianProduct(LegalizeAction Action, 498 std::initializer_list<LLT> Types0, 499 std::initializer_list<LLT> Types1) { 500 using namespace LegalityPredicates; 501 return actionIf(Action, all(typeInSet(typeIdx(0), Types0), 502 typeInSet(typeIdx(1), Types1))); 503 } 504 /// Use the given action when type indexes 0, 1, and 2 are all in their 505 /// respective lists. 506 /// That is, the type triple is in the cartesian product of the lists 507 /// Action should not be an action that requires mutation. 508 LegalizeRuleSet &actionForCartesianProduct( 509 LegalizeAction Action, std::initializer_list<LLT> Types0, 510 std::initializer_list<LLT> Types1, std::initializer_list<LLT> Types2) { 511 using namespace LegalityPredicates; 512 return actionIf(Action, all(typeInSet(typeIdx(0), Types0), 513 all(typeInSet(typeIdx(1), Types1), 514 typeInSet(typeIdx(2), Types2)))); 515 } 516 517 public: 518 LegalizeRuleSet() : AliasOf(0), IsAliasedByAnother(false), Rules() {} 519 520 bool isAliasedByAnother() { return IsAliasedByAnother; } 521 void setIsAliasedByAnother() { IsAliasedByAnother = true; } 522 void aliasTo(unsigned Opcode) { 523 assert((AliasOf == 0 || AliasOf == Opcode) && 524 "Opcode is already aliased to another opcode"); 525 assert(Rules.empty() && "Aliasing will discard rules"); 526 AliasOf = Opcode; 527 } 528 unsigned getAlias() const { return AliasOf; } 529 530 /// The instruction is legal if predicate is true. 531 LegalizeRuleSet &legalIf(LegalityPredicate Predicate) { 532 // We have no choice but conservatively assume that the free-form 533 // user-provided Predicate properly handles all type indices: 534 markAllIdxsAsCovered(); 535 return actionIf(LegalizeAction::Legal, Predicate); 536 } 537 /// The instruction is legal when type index 0 is any type in the given list. 538 LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) { 539 return actionFor(LegalizeAction::Legal, Types); 540 } 541 /// The instruction is legal when type indexes 0 and 1 is any type pair in the 542 /// given list. 543 LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) { 544 return actionFor(LegalizeAction::Legal, Types); 545 } 546 /// The instruction is legal when type index 0 is any type in the given list 547 /// and imm index 0 is anything. 548 LegalizeRuleSet &legalForTypeWithAnyImm(std::initializer_list<LLT> Types) { 549 markAllIdxsAsCovered(); 550 return actionForTypeWithAnyImm(LegalizeAction::Legal, Types); 551 } 552 553 LegalizeRuleSet &legalForTypeWithAnyImm( 554 std::initializer_list<std::pair<LLT, LLT>> Types) { 555 markAllIdxsAsCovered(); 556 return actionForTypeWithAnyImm(LegalizeAction::Legal, Types); 557 } 558 559 /// The instruction is legal when type indexes 0 and 1 along with the memory 560 /// size and minimum alignment is any type and size tuple in the given list. 561 LegalizeRuleSet &legalForTypesWithMemDesc( 562 std::initializer_list<LegalityPredicates::TypePairAndMemDesc> 563 TypesAndMemDesc) { 564 return actionIf(LegalizeAction::Legal, 565 LegalityPredicates::typePairAndMemDescInSet( 566 typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc)); 567 } 568 /// The instruction is legal when type indexes 0 and 1 are both in the given 569 /// list. That is, the type pair is in the cartesian product of the list. 570 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types) { 571 return actionForCartesianProduct(LegalizeAction::Legal, Types); 572 } 573 /// The instruction is legal when type indexes 0 and 1 are both their 574 /// respective lists. 575 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0, 576 std::initializer_list<LLT> Types1) { 577 return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1); 578 } 579 /// The instruction is legal when type indexes 0, 1, and 2 are both their 580 /// respective lists. 581 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0, 582 std::initializer_list<LLT> Types1, 583 std::initializer_list<LLT> Types2) { 584 return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1, 585 Types2); 586 } 587 588 LegalizeRuleSet &alwaysLegal() { 589 using namespace LegalizeMutations; 590 markAllIdxsAsCovered(); 591 return actionIf(LegalizeAction::Legal, always); 592 } 593 594 /// The specified type index is coerced if predicate is true. 595 LegalizeRuleSet &bitcastIf(LegalityPredicate Predicate, 596 LegalizeMutation Mutation) { 597 // We have no choice but conservatively assume that lowering with a 598 // free-form user provided Predicate properly handles all type indices: 599 markAllIdxsAsCovered(); 600 return actionIf(LegalizeAction::Bitcast, Predicate, Mutation); 601 } 602 603 /// The instruction is lowered. 604 LegalizeRuleSet &lower() { 605 using namespace LegalizeMutations; 606 // We have no choice but conservatively assume that predicate-less lowering 607 // properly handles all type indices by design: 608 markAllIdxsAsCovered(); 609 return actionIf(LegalizeAction::Lower, always); 610 } 611 /// The instruction is lowered if predicate is true. Keep type index 0 as the 612 /// same type. 613 LegalizeRuleSet &lowerIf(LegalityPredicate Predicate) { 614 using namespace LegalizeMutations; 615 // We have no choice but conservatively assume that lowering with a 616 // free-form user provided Predicate properly handles all type indices: 617 markAllIdxsAsCovered(); 618 return actionIf(LegalizeAction::Lower, Predicate); 619 } 620 /// The instruction is lowered if predicate is true. 621 LegalizeRuleSet &lowerIf(LegalityPredicate Predicate, 622 LegalizeMutation Mutation) { 623 // We have no choice but conservatively assume that lowering with a 624 // free-form user provided Predicate properly handles all type indices: 625 markAllIdxsAsCovered(); 626 return actionIf(LegalizeAction::Lower, Predicate, Mutation); 627 } 628 /// The instruction is lowered when type index 0 is any type in the given 629 /// list. Keep type index 0 as the same type. 630 LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types) { 631 return actionFor(LegalizeAction::Lower, Types); 632 } 633 /// The instruction is lowered when type index 0 is any type in the given 634 /// list. 635 LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types, 636 LegalizeMutation Mutation) { 637 return actionFor(LegalizeAction::Lower, Types, Mutation); 638 } 639 /// The instruction is lowered when type indexes 0 and 1 is any type pair in 640 /// the given list. Keep type index 0 as the same type. 641 LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) { 642 return actionFor(LegalizeAction::Lower, Types); 643 } 644 /// The instruction is lowered when type indexes 0 and 1 is any type pair in 645 /// the given list. 646 LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types, 647 LegalizeMutation Mutation) { 648 return actionFor(LegalizeAction::Lower, Types, Mutation); 649 } 650 /// The instruction is lowered when type indexes 0 and 1 are both in their 651 /// respective lists. 652 LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0, 653 std::initializer_list<LLT> Types1) { 654 using namespace LegalityPredicates; 655 return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1); 656 } 657 /// The instruction is lowered when when type indexes 0, 1, and 2 are all in 658 /// their respective lists. 659 LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0, 660 std::initializer_list<LLT> Types1, 661 std::initializer_list<LLT> Types2) { 662 using namespace LegalityPredicates; 663 return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1, 664 Types2); 665 } 666 667 /// The instruction is emitted as a library call. 668 LegalizeRuleSet &libcall() { 669 using namespace LegalizeMutations; 670 // We have no choice but conservatively assume that predicate-less lowering 671 // properly handles all type indices by design: 672 markAllIdxsAsCovered(); 673 return actionIf(LegalizeAction::Libcall, always); 674 } 675 676 /// Like legalIf, but for the Libcall action. 677 LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) { 678 // We have no choice but conservatively assume that a libcall with a 679 // free-form user provided Predicate properly handles all type indices: 680 markAllIdxsAsCovered(); 681 return actionIf(LegalizeAction::Libcall, Predicate); 682 } 683 LegalizeRuleSet &libcallFor(std::initializer_list<LLT> Types) { 684 return actionFor(LegalizeAction::Libcall, Types); 685 } 686 LegalizeRuleSet & 687 libcallFor(std::initializer_list<std::pair<LLT, LLT>> Types) { 688 return actionFor(LegalizeAction::Libcall, Types); 689 } 690 LegalizeRuleSet & 691 libcallForCartesianProduct(std::initializer_list<LLT> Types) { 692 return actionForCartesianProduct(LegalizeAction::Libcall, Types); 693 } 694 LegalizeRuleSet & 695 libcallForCartesianProduct(std::initializer_list<LLT> Types0, 696 std::initializer_list<LLT> Types1) { 697 return actionForCartesianProduct(LegalizeAction::Libcall, Types0, Types1); 698 } 699 700 /// Widen the scalar to the one selected by the mutation if the predicate is 701 /// true. 702 LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate, 703 LegalizeMutation Mutation) { 704 // We have no choice but conservatively assume that an action with a 705 // free-form user provided Predicate properly handles all type indices: 706 markAllIdxsAsCovered(); 707 return actionIf(LegalizeAction::WidenScalar, Predicate, Mutation); 708 } 709 /// Narrow the scalar to the one selected by the mutation if the predicate is 710 /// true. 711 LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate, 712 LegalizeMutation Mutation) { 713 // We have no choice but conservatively assume that an action with a 714 // free-form user provided Predicate properly handles all type indices: 715 markAllIdxsAsCovered(); 716 return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation); 717 } 718 /// Narrow the scalar, specified in mutation, when type indexes 0 and 1 is any 719 /// type pair in the given list. 720 LegalizeRuleSet & 721 narrowScalarFor(std::initializer_list<std::pair<LLT, LLT>> Types, 722 LegalizeMutation Mutation) { 723 return actionFor(LegalizeAction::NarrowScalar, Types, Mutation); 724 } 725 726 /// Add more elements to reach the type selected by the mutation if the 727 /// predicate is true. 728 LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate, 729 LegalizeMutation Mutation) { 730 // We have no choice but conservatively assume that an action with a 731 // free-form user provided Predicate properly handles all type indices: 732 markAllIdxsAsCovered(); 733 return actionIf(LegalizeAction::MoreElements, Predicate, Mutation); 734 } 735 /// Remove elements to reach the type selected by the mutation if the 736 /// predicate is true. 737 LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate, 738 LegalizeMutation Mutation) { 739 // We have no choice but conservatively assume that an action with a 740 // free-form user provided Predicate properly handles all type indices: 741 markAllIdxsAsCovered(); 742 return actionIf(LegalizeAction::FewerElements, Predicate, Mutation); 743 } 744 745 /// The instruction is unsupported. 746 LegalizeRuleSet &unsupported() { 747 markAllIdxsAsCovered(); 748 return actionIf(LegalizeAction::Unsupported, always); 749 } 750 LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) { 751 return actionIf(LegalizeAction::Unsupported, Predicate); 752 } 753 754 LegalizeRuleSet &unsupportedFor(std::initializer_list<LLT> Types) { 755 return actionFor(LegalizeAction::Unsupported, Types); 756 } 757 758 LegalizeRuleSet &unsupportedIfMemSizeNotPow2() { 759 return actionIf(LegalizeAction::Unsupported, 760 LegalityPredicates::memSizeInBytesNotPow2(0)); 761 } 762 LegalizeRuleSet &lowerIfMemSizeNotPow2() { 763 return actionIf(LegalizeAction::Lower, 764 LegalityPredicates::memSizeInBytesNotPow2(0)); 765 } 766 767 LegalizeRuleSet &customIf(LegalityPredicate Predicate) { 768 // We have no choice but conservatively assume that a custom action with a 769 // free-form user provided Predicate properly handles all type indices: 770 markAllIdxsAsCovered(); 771 return actionIf(LegalizeAction::Custom, Predicate); 772 } 773 LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) { 774 return actionFor(LegalizeAction::Custom, Types); 775 } 776 777 /// The instruction is custom when type indexes 0 and 1 is any type pair in the 778 /// given list. 779 LegalizeRuleSet &customFor(std::initializer_list<std::pair<LLT, LLT>> Types) { 780 return actionFor(LegalizeAction::Custom, Types); 781 } 782 783 LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) { 784 return actionForCartesianProduct(LegalizeAction::Custom, Types); 785 } 786 LegalizeRuleSet & 787 customForCartesianProduct(std::initializer_list<LLT> Types0, 788 std::initializer_list<LLT> Types1) { 789 return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1); 790 } 791 792 /// Unconditionally custom lower. 793 LegalizeRuleSet &custom() { 794 return customIf(always); 795 } 796 797 /// Widen the scalar to the next power of two that is at least MinSize. 798 /// No effect if the type is not a scalar or is a power of two. 799 LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx, 800 unsigned MinSize = 0) { 801 using namespace LegalityPredicates; 802 return actionIf( 803 LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)), 804 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize)); 805 } 806 807 /// Widen the scalar or vector element type to the next power of two that is 808 /// at least MinSize. No effect if the scalar size is a power of two. 809 LegalizeRuleSet &widenScalarOrEltToNextPow2(unsigned TypeIdx, 810 unsigned MinSize = 0) { 811 using namespace LegalityPredicates; 812 return actionIf( 813 LegalizeAction::WidenScalar, scalarOrEltSizeNotPow2(typeIdx(TypeIdx)), 814 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize)); 815 } 816 817 LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) { 818 using namespace LegalityPredicates; 819 return actionIf(LegalizeAction::NarrowScalar, isScalar(typeIdx(TypeIdx)), 820 Mutation); 821 } 822 823 LegalizeRuleSet &scalarize(unsigned TypeIdx) { 824 using namespace LegalityPredicates; 825 return actionIf(LegalizeAction::FewerElements, isVector(typeIdx(TypeIdx)), 826 LegalizeMutations::scalarize(TypeIdx)); 827 } 828 829 LegalizeRuleSet &scalarizeIf(LegalityPredicate Predicate, unsigned TypeIdx) { 830 using namespace LegalityPredicates; 831 return actionIf(LegalizeAction::FewerElements, 832 all(Predicate, isVector(typeIdx(TypeIdx))), 833 LegalizeMutations::scalarize(TypeIdx)); 834 } 835 836 /// Ensure the scalar or element is at least as wide as Ty. 837 LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT Ty) { 838 using namespace LegalityPredicates; 839 using namespace LegalizeMutations; 840 return actionIf(LegalizeAction::WidenScalar, 841 scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()), 842 changeElementTo(typeIdx(TypeIdx), Ty)); 843 } 844 845 /// Ensure the scalar or element is at least as wide as Ty. 846 LegalizeRuleSet &minScalarOrEltIf(LegalityPredicate Predicate, 847 unsigned TypeIdx, const LLT Ty) { 848 using namespace LegalityPredicates; 849 using namespace LegalizeMutations; 850 return actionIf(LegalizeAction::WidenScalar, 851 all(Predicate, scalarOrEltNarrowerThan( 852 TypeIdx, Ty.getScalarSizeInBits())), 853 changeElementTo(typeIdx(TypeIdx), Ty)); 854 } 855 856 /// Ensure the scalar is at least as wide as Ty. 857 LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT Ty) { 858 using namespace LegalityPredicates; 859 using namespace LegalizeMutations; 860 return actionIf(LegalizeAction::WidenScalar, 861 scalarNarrowerThan(TypeIdx, Ty.getSizeInBits()), 862 changeTo(typeIdx(TypeIdx), Ty)); 863 } 864 865 /// Ensure the scalar is at most as wide as Ty. 866 LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT Ty) { 867 using namespace LegalityPredicates; 868 using namespace LegalizeMutations; 869 return actionIf(LegalizeAction::NarrowScalar, 870 scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()), 871 changeElementTo(typeIdx(TypeIdx), Ty)); 872 } 873 874 /// Ensure the scalar is at most as wide as Ty. 875 LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT Ty) { 876 using namespace LegalityPredicates; 877 using namespace LegalizeMutations; 878 return actionIf(LegalizeAction::NarrowScalar, 879 scalarWiderThan(TypeIdx, Ty.getSizeInBits()), 880 changeTo(typeIdx(TypeIdx), Ty)); 881 } 882 883 /// Conditionally limit the maximum size of the scalar. 884 /// For example, when the maximum size of one type depends on the size of 885 /// another such as extracting N bits from an M bit container. 886 LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, 887 const LLT Ty) { 888 using namespace LegalityPredicates; 889 using namespace LegalizeMutations; 890 return actionIf( 891 LegalizeAction::NarrowScalar, 892 [=](const LegalityQuery &Query) { 893 const LLT QueryTy = Query.Types[TypeIdx]; 894 return QueryTy.isScalar() && 895 QueryTy.getSizeInBits() > Ty.getSizeInBits() && 896 Predicate(Query); 897 }, 898 changeElementTo(typeIdx(TypeIdx), Ty)); 899 } 900 901 /// Limit the range of scalar sizes to MinTy and MaxTy. 902 LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT MinTy, 903 const LLT MaxTy) { 904 assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types"); 905 return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy); 906 } 907 908 /// Limit the range of scalar sizes to MinTy and MaxTy. 909 LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, 910 const LLT MaxTy) { 911 return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy); 912 } 913 914 /// Widen the scalar to match the size of another. 915 LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) { 916 typeIdx(TypeIdx); 917 return widenScalarIf( 918 [=](const LegalityQuery &Query) { 919 return Query.Types[LargeTypeIdx].getScalarSizeInBits() > 920 Query.Types[TypeIdx].getSizeInBits(); 921 }, 922 LegalizeMutations::changeElementSizeTo(TypeIdx, LargeTypeIdx)); 923 } 924 925 /// Narrow the scalar to match the size of another. 926 LegalizeRuleSet &maxScalarSameAs(unsigned TypeIdx, unsigned NarrowTypeIdx) { 927 typeIdx(TypeIdx); 928 return narrowScalarIf( 929 [=](const LegalityQuery &Query) { 930 return Query.Types[NarrowTypeIdx].getScalarSizeInBits() < 931 Query.Types[TypeIdx].getSizeInBits(); 932 }, 933 LegalizeMutations::changeElementSizeTo(TypeIdx, NarrowTypeIdx)); 934 } 935 936 /// Change the type \p TypeIdx to have the same scalar size as type \p 937 /// SameSizeIdx. 938 LegalizeRuleSet &scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx) { 939 return minScalarSameAs(TypeIdx, SameSizeIdx) 940 .maxScalarSameAs(TypeIdx, SameSizeIdx); 941 } 942 943 /// Conditionally widen the scalar or elt to match the size of another. 944 LegalizeRuleSet &minScalarEltSameAsIf(LegalityPredicate Predicate, 945 unsigned TypeIdx, unsigned LargeTypeIdx) { 946 typeIdx(TypeIdx); 947 return widenScalarIf( 948 [=](const LegalityQuery &Query) { 949 return Query.Types[LargeTypeIdx].getScalarSizeInBits() > 950 Query.Types[TypeIdx].getScalarSizeInBits() && 951 Predicate(Query); 952 }, 953 [=](const LegalityQuery &Query) { 954 LLT T = Query.Types[LargeTypeIdx]; 955 return std::make_pair(TypeIdx, T); 956 }); 957 } 958 959 /// Conditionally narrow the scalar or elt to match the size of another. 960 LegalizeRuleSet &maxScalarEltSameAsIf(LegalityPredicate Predicate, 961 unsigned TypeIdx, 962 unsigned SmallTypeIdx) { 963 typeIdx(TypeIdx); 964 return narrowScalarIf( 965 [=](const LegalityQuery &Query) { 966 return Query.Types[SmallTypeIdx].getScalarSizeInBits() < 967 Query.Types[TypeIdx].getScalarSizeInBits() && 968 Predicate(Query); 969 }, 970 [=](const LegalityQuery &Query) { 971 LLT T = Query.Types[SmallTypeIdx]; 972 return std::make_pair(TypeIdx, T); 973 }); 974 } 975 976 /// Add more elements to the vector to reach the next power of two. 977 /// No effect if the type is not a vector or the element count is a power of 978 /// two. 979 LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) { 980 using namespace LegalityPredicates; 981 return actionIf(LegalizeAction::MoreElements, 982 numElementsNotPow2(typeIdx(TypeIdx)), 983 LegalizeMutations::moreElementsToNextPow2(TypeIdx)); 984 } 985 986 /// Limit the number of elements in EltTy vectors to at least MinElements. 987 LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT EltTy, 988 unsigned MinElements) { 989 // Mark the type index as covered: 990 typeIdx(TypeIdx); 991 return actionIf( 992 LegalizeAction::MoreElements, 993 [=](const LegalityQuery &Query) { 994 LLT VecTy = Query.Types[TypeIdx]; 995 return VecTy.isVector() && VecTy.getElementType() == EltTy && 996 VecTy.getNumElements() < MinElements; 997 }, 998 [=](const LegalityQuery &Query) { 999 LLT VecTy = Query.Types[TypeIdx]; 1000 return std::make_pair( 1001 TypeIdx, LLT::vector(MinElements, VecTy.getElementType())); 1002 }); 1003 } 1004 /// Limit the number of elements in EltTy vectors to at most MaxElements. 1005 LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, 1006 unsigned MaxElements) { 1007 // Mark the type index as covered: 1008 typeIdx(TypeIdx); 1009 return actionIf( 1010 LegalizeAction::FewerElements, 1011 [=](const LegalityQuery &Query) { 1012 LLT VecTy = Query.Types[TypeIdx]; 1013 return VecTy.isVector() && VecTy.getElementType() == EltTy && 1014 VecTy.getNumElements() > MaxElements; 1015 }, 1016 [=](const LegalityQuery &Query) { 1017 LLT VecTy = Query.Types[TypeIdx]; 1018 LLT NewTy = LLT::scalarOrVector(MaxElements, VecTy.getElementType()); 1019 return std::make_pair(TypeIdx, NewTy); 1020 }); 1021 } 1022 /// Limit the number of elements for the given vectors to at least MinTy's 1023 /// number of elements and at most MaxTy's number of elements. 1024 /// 1025 /// No effect if the type is not a vector or does not have the same element 1026 /// type as the constraints. 1027 /// The element type of MinTy and MaxTy must match. 1028 LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT MinTy, 1029 const LLT MaxTy) { 1030 assert(MinTy.getElementType() == MaxTy.getElementType() && 1031 "Expected element types to agree"); 1032 1033 const LLT EltTy = MinTy.getElementType(); 1034 return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements()) 1035 .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements()); 1036 } 1037 1038 /// Fallback on the previous implementation. This should only be used while 1039 /// porting a rule. 1040 LegalizeRuleSet &fallback() { 1041 add({always, LegalizeAction::UseLegacyRules}); 1042 return *this; 1043 } 1044 1045 /// Check if there is no type index which is obviously not handled by the 1046 /// LegalizeRuleSet in any way at all. 1047 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set. 1048 bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const; 1049 /// Check if there is no imm index which is obviously not handled by the 1050 /// LegalizeRuleSet in any way at all. 1051 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set. 1052 bool verifyImmIdxsCoverage(unsigned NumImmIdxs) const; 1053 1054 /// Apply the ruleset to the given LegalityQuery. 1055 LegalizeActionStep apply(const LegalityQuery &Query) const; 1056 }; 1057 1058 class LegalizerInfo { 1059 public: 1060 LegalizerInfo(); 1061 virtual ~LegalizerInfo() = default; 1062 1063 unsigned getOpcodeIdxForOpcode(unsigned Opcode) const; 1064 unsigned getActionDefinitionsIdx(unsigned Opcode) const; 1065 1066 /// Compute any ancillary tables needed to quickly decide how an operation 1067 /// should be handled. This must be called after all "set*Action"methods but 1068 /// before any query is made or incorrect results may be returned. 1069 void computeTables(); 1070 1071 /// Perform simple self-diagnostic and assert if there is anything obviously 1072 /// wrong with the actions set up. 1073 void verify(const MCInstrInfo &MII) const; 1074 1075 static bool needsLegalizingToDifferentSize(const LegalizeAction Action) { 1076 using namespace LegalizeActions; 1077 switch (Action) { 1078 case NarrowScalar: 1079 case WidenScalar: 1080 case FewerElements: 1081 case MoreElements: 1082 case Unsupported: 1083 return true; 1084 default: 1085 return false; 1086 } 1087 } 1088 1089 using SizeAndAction = std::pair<uint16_t, LegalizeAction>; 1090 using SizeAndActionsVec = std::vector<SizeAndAction>; 1091 using SizeChangeStrategy = 1092 std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>; 1093 1094 /// More friendly way to set an action for common types that have an LLT 1095 /// representation. 1096 /// The LegalizeAction must be one for which NeedsLegalizingToDifferentSize 1097 /// returns false. 1098 void setAction(const InstrAspect &Aspect, LegalizeAction Action) { 1099 assert(!needsLegalizingToDifferentSize(Action)); 1100 TablesInitialized = false; 1101 const unsigned OpcodeIdx = Aspect.Opcode - FirstOp; 1102 if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx) 1103 SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1); 1104 SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action; 1105 } 1106 1107 /// The setAction calls record the non-size-changing legalization actions 1108 /// to take on specificly-sized types. The SizeChangeStrategy defines what 1109 /// to do when the size of the type needs to be changed to reach a legally 1110 /// sized type (i.e., one that was defined through a setAction call). 1111 /// e.g. 1112 /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal); 1113 /// setLegalizeScalarToDifferentSizeStrategy( 1114 /// G_ADD, 0, widenToLargerTypesAndNarrowToLargest); 1115 /// will end up defining getAction({G_ADD, 0, T}) to return the following 1116 /// actions for different scalar types T: 1117 /// LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)} 1118 /// LLT::scalar(32): {Legal, 0, LLT::scalar(32)} 1119 /// LLT::scalar(33)..: {NarrowScalar, 0, LLT::scalar(32)} 1120 /// 1121 /// If no SizeChangeAction gets defined, through this function, 1122 /// the default is unsupportedForDifferentSizes. 1123 void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode, 1124 const unsigned TypeIdx, 1125 SizeChangeStrategy S) { 1126 const unsigned OpcodeIdx = Opcode - FirstOp; 1127 if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx) 1128 ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1); 1129 ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S; 1130 } 1131 1132 /// See also setLegalizeScalarToDifferentSizeStrategy. 1133 /// This function allows to set the SizeChangeStrategy for vector elements. 1134 void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode, 1135 const unsigned TypeIdx, 1136 SizeChangeStrategy S) { 1137 const unsigned OpcodeIdx = Opcode - FirstOp; 1138 if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx) 1139 VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1); 1140 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S; 1141 } 1142 1143 /// A SizeChangeStrategy for the common case where legalization for a 1144 /// particular operation consists of only supporting a specific set of type 1145 /// sizes. E.g. 1146 /// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal); 1147 /// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal); 1148 /// setLegalizeScalarToDifferentSizeStrategy( 1149 /// G_DIV, 0, unsupportedForDifferentSizes); 1150 /// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64, 1151 /// and Unsupported for all other scalar types T. 1152 static SizeAndActionsVec 1153 unsupportedForDifferentSizes(const SizeAndActionsVec &v) { 1154 using namespace LegalizeActions; 1155 return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported, 1156 Unsupported); 1157 } 1158 1159 /// A SizeChangeStrategy for the common case where legalization for a 1160 /// particular operation consists of widening the type to a large legal type, 1161 /// unless there is no such type and then instead it should be narrowed to the 1162 /// largest legal type. 1163 static SizeAndActionsVec 1164 widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) { 1165 using namespace LegalizeActions; 1166 assert(v.size() > 0 && 1167 "At least one size that can be legalized towards is needed" 1168 " for this SizeChangeStrategy"); 1169 return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar, 1170 NarrowScalar); 1171 } 1172 1173 static SizeAndActionsVec 1174 widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) { 1175 using namespace LegalizeActions; 1176 return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar, 1177 Unsupported); 1178 } 1179 1180 static SizeAndActionsVec 1181 narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) { 1182 using namespace LegalizeActions; 1183 return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar, 1184 Unsupported); 1185 } 1186 1187 static SizeAndActionsVec 1188 narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) { 1189 using namespace LegalizeActions; 1190 assert(v.size() > 0 && 1191 "At least one size that can be legalized towards is needed" 1192 " for this SizeChangeStrategy"); 1193 return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar, 1194 WidenScalar); 1195 } 1196 1197 /// A SizeChangeStrategy for the common case where legalization for a 1198 /// particular vector operation consists of having more elements in the 1199 /// vector, to a type that is legal. Unless there is no such type and then 1200 /// instead it should be legalized towards the widest vector that's still 1201 /// legal. E.g. 1202 /// setAction({G_ADD, LLT::vector(8, 8)}, Legal); 1203 /// setAction({G_ADD, LLT::vector(16, 8)}, Legal); 1204 /// setAction({G_ADD, LLT::vector(2, 32)}, Legal); 1205 /// setAction({G_ADD, LLT::vector(4, 32)}, Legal); 1206 /// setLegalizeVectorElementToDifferentSizeStrategy( 1207 /// G_ADD, 0, moreToWiderTypesAndLessToWidest); 1208 /// will result in the following getAction results: 1209 /// * getAction({G_ADD, LLT::vector(8,8)}) returns 1210 /// (Legal, vector(8,8)). 1211 /// * getAction({G_ADD, LLT::vector(9,8)}) returns 1212 /// (MoreElements, vector(16,8)). 1213 /// * getAction({G_ADD, LLT::vector(8,32)}) returns 1214 /// (FewerElements, vector(4,32)). 1215 static SizeAndActionsVec 1216 moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) { 1217 using namespace LegalizeActions; 1218 return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements, 1219 FewerElements); 1220 } 1221 1222 /// Helper function to implement many typical SizeChangeStrategy functions. 1223 static SizeAndActionsVec 1224 increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec &v, 1225 LegalizeAction IncreaseAction, 1226 LegalizeAction DecreaseAction); 1227 /// Helper function to implement many typical SizeChangeStrategy functions. 1228 static SizeAndActionsVec 1229 decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec &v, 1230 LegalizeAction DecreaseAction, 1231 LegalizeAction IncreaseAction); 1232 1233 /// Get the action definitions for the given opcode. Use this to run a 1234 /// LegalityQuery through the definitions. 1235 const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const; 1236 1237 /// Get the action definition builder for the given opcode. Use this to define 1238 /// the action definitions. 1239 /// 1240 /// It is an error to request an opcode that has already been requested by the 1241 /// multiple-opcode variant. 1242 LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode); 1243 1244 /// Get the action definition builder for the given set of opcodes. Use this 1245 /// to define the action definitions for multiple opcodes at once. The first 1246 /// opcode given will be considered the representative opcode and will hold 1247 /// the definitions whereas the other opcodes will be configured to refer to 1248 /// the representative opcode. This lowers memory requirements and very 1249 /// slightly improves performance. 1250 /// 1251 /// It would be very easy to introduce unexpected side-effects as a result of 1252 /// this aliasing if it were permitted to request different but intersecting 1253 /// sets of opcodes but that is difficult to keep track of. It is therefore an 1254 /// error to request the same opcode twice using this API, to request an 1255 /// opcode that already has definitions, or to use the single-opcode API on an 1256 /// opcode that has already been requested by this API. 1257 LegalizeRuleSet & 1258 getActionDefinitionsBuilder(std::initializer_list<unsigned> Opcodes); 1259 void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom); 1260 1261 /// Determine what action should be taken to legalize the described 1262 /// instruction. Requires computeTables to have been called. 1263 /// 1264 /// \returns a description of the next legalization step to perform. 1265 LegalizeActionStep getAction(const LegalityQuery &Query) const; 1266 1267 /// Determine what action should be taken to legalize the given generic 1268 /// instruction. 1269 /// 1270 /// \returns a description of the next legalization step to perform. 1271 LegalizeActionStep getAction(const MachineInstr &MI, 1272 const MachineRegisterInfo &MRI) const; 1273 1274 bool isLegal(const LegalityQuery &Query) const { 1275 return getAction(Query).Action == LegalizeAction::Legal; 1276 } 1277 1278 bool isLegalOrCustom(const LegalityQuery &Query) const { 1279 auto Action = getAction(Query).Action; 1280 return Action == LegalizeAction::Legal || Action == LegalizeAction::Custom; 1281 } 1282 1283 bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; 1284 bool isLegalOrCustom(const MachineInstr &MI, 1285 const MachineRegisterInfo &MRI) const; 1286 1287 /// Called for instructions with the Custom LegalizationAction. 1288 virtual bool legalizeCustom(LegalizerHelper &Helper, 1289 MachineInstr &MI) const { 1290 llvm_unreachable("must implement this if custom action is used"); 1291 } 1292 1293 /// \returns true if MI is either legal or has been legalized and false if not 1294 /// legal. 1295 /// Return true if MI is either legal or has been legalized and false 1296 /// if not legal. 1297 virtual bool legalizeIntrinsic(LegalizerHelper &Helper, 1298 MachineInstr &MI) const { 1299 return true; 1300 } 1301 1302 /// Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while 1303 /// widening a constant of type SmallTy which targets can override. 1304 /// For eg, the DAG does (SmallTy.isByteSized() ? G_SEXT : G_ZEXT) which 1305 /// will be the default. 1306 virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const; 1307 1308 private: 1309 /// Determine what action should be taken to legalize the given generic 1310 /// instruction opcode, type-index and type. Requires computeTables to have 1311 /// been called. 1312 /// 1313 /// \returns a pair consisting of the kind of legalization that should be 1314 /// performed and the destination type. 1315 std::pair<LegalizeAction, LLT> 1316 getAspectAction(const InstrAspect &Aspect) const; 1317 1318 /// The SizeAndActionsVec is a representation mapping between all natural 1319 /// numbers and an Action. The natural number represents the bit size of 1320 /// the InstrAspect. For example, for a target with native support for 32-bit 1321 /// and 64-bit additions, you'd express that as: 1322 /// setScalarAction(G_ADD, 0, 1323 /// {{1, WidenScalar}, // bit sizes [ 1, 31[ 1324 /// {32, Legal}, // bit sizes [32, 33[ 1325 /// {33, WidenScalar}, // bit sizes [33, 64[ 1326 /// {64, Legal}, // bit sizes [64, 65[ 1327 /// {65, NarrowScalar} // bit sizes [65, +inf[ 1328 /// }); 1329 /// It may be that only 64-bit pointers are supported on your target: 1330 /// setPointerAction(G_PTR_ADD, 0, LLT:pointer(1), 1331 /// {{1, Unsupported}, // bit sizes [ 1, 63[ 1332 /// {64, Legal}, // bit sizes [64, 65[ 1333 /// {65, Unsupported}, // bit sizes [65, +inf[ 1334 /// }); 1335 void setScalarAction(const unsigned Opcode, const unsigned TypeIndex, 1336 const SizeAndActionsVec &SizeAndActions) { 1337 const unsigned OpcodeIdx = Opcode - FirstOp; 1338 SmallVector<SizeAndActionsVec, 1> &Actions = ScalarActions[OpcodeIdx]; 1339 setActions(TypeIndex, Actions, SizeAndActions); 1340 } 1341 void setPointerAction(const unsigned Opcode, const unsigned TypeIndex, 1342 const unsigned AddressSpace, 1343 const SizeAndActionsVec &SizeAndActions) { 1344 const unsigned OpcodeIdx = Opcode - FirstOp; 1345 if (AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace) == 1346 AddrSpace2PointerActions[OpcodeIdx].end()) 1347 AddrSpace2PointerActions[OpcodeIdx][AddressSpace] = {{}}; 1348 SmallVector<SizeAndActionsVec, 1> &Actions = 1349 AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace)->second; 1350 setActions(TypeIndex, Actions, SizeAndActions); 1351 } 1352 1353 /// If an operation on a given vector type (say <M x iN>) isn't explicitly 1354 /// specified, we proceed in 2 stages. First we legalize the underlying scalar 1355 /// (so that there's at least one legal vector with that scalar), then we 1356 /// adjust the number of elements in the vector so that it is legal. The 1357 /// desired action in the first step is controlled by this function. 1358 void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex, 1359 const SizeAndActionsVec &SizeAndActions) { 1360 unsigned OpcodeIdx = Opcode - FirstOp; 1361 SmallVector<SizeAndActionsVec, 1> &Actions = 1362 ScalarInVectorActions[OpcodeIdx]; 1363 setActions(TypeIndex, Actions, SizeAndActions); 1364 } 1365 1366 /// See also setScalarInVectorAction. 1367 /// This function let's you specify the number of elements in a vector that 1368 /// are legal for a legal element size. 1369 void setVectorNumElementAction(const unsigned Opcode, 1370 const unsigned TypeIndex, 1371 const unsigned ElementSize, 1372 const SizeAndActionsVec &SizeAndActions) { 1373 const unsigned OpcodeIdx = Opcode - FirstOp; 1374 if (NumElements2Actions[OpcodeIdx].find(ElementSize) == 1375 NumElements2Actions[OpcodeIdx].end()) 1376 NumElements2Actions[OpcodeIdx][ElementSize] = {{}}; 1377 SmallVector<SizeAndActionsVec, 1> &Actions = 1378 NumElements2Actions[OpcodeIdx].find(ElementSize)->second; 1379 setActions(TypeIndex, Actions, SizeAndActions); 1380 } 1381 1382 /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes, 1383 /// i.e. it's OK if it doesn't start from size 1. 1384 static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) { 1385 using namespace LegalizeActions; 1386 #ifndef NDEBUG 1387 // The sizes should be in increasing order 1388 int prev_size = -1; 1389 for(auto SizeAndAction: v) { 1390 assert(SizeAndAction.first > prev_size); 1391 prev_size = SizeAndAction.first; 1392 } 1393 // - for every Widen action, there should be a larger bitsize that 1394 // can be legalized towards (e.g. Legal, Lower, Libcall or Custom 1395 // action). 1396 // - for every Narrow action, there should be a smaller bitsize that 1397 // can be legalized towards. 1398 int SmallestNarrowIdx = -1; 1399 int LargestWidenIdx = -1; 1400 int SmallestLegalizableToSameSizeIdx = -1; 1401 int LargestLegalizableToSameSizeIdx = -1; 1402 for(size_t i=0; i<v.size(); ++i) { 1403 switch (v[i].second) { 1404 case FewerElements: 1405 case NarrowScalar: 1406 if (SmallestNarrowIdx == -1) 1407 SmallestNarrowIdx = i; 1408 break; 1409 case WidenScalar: 1410 case MoreElements: 1411 LargestWidenIdx = i; 1412 break; 1413 case Unsupported: 1414 break; 1415 default: 1416 if (SmallestLegalizableToSameSizeIdx == -1) 1417 SmallestLegalizableToSameSizeIdx = i; 1418 LargestLegalizableToSameSizeIdx = i; 1419 } 1420 } 1421 if (SmallestNarrowIdx != -1) { 1422 assert(SmallestLegalizableToSameSizeIdx != -1); 1423 assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeIdx); 1424 } 1425 if (LargestWidenIdx != -1) 1426 assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx); 1427 #endif 1428 } 1429 1430 /// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with 1431 /// from size 1. 1432 static void checkFullSizeAndActionsVector(const SizeAndActionsVec& v) { 1433 #ifndef NDEBUG 1434 // Data structure invariant: The first bit size must be size 1. 1435 assert(v.size() >= 1); 1436 assert(v[0].first == 1); 1437 checkPartialSizeAndActionsVector(v); 1438 #endif 1439 } 1440 1441 /// Sets actions for all bit sizes on a particular generic opcode, type 1442 /// index and scalar or pointer type. 1443 void setActions(unsigned TypeIndex, 1444 SmallVector<SizeAndActionsVec, 1> &Actions, 1445 const SizeAndActionsVec &SizeAndActions) { 1446 checkFullSizeAndActionsVector(SizeAndActions); 1447 if (Actions.size() <= TypeIndex) 1448 Actions.resize(TypeIndex + 1); 1449 Actions[TypeIndex] = SizeAndActions; 1450 } 1451 1452 static SizeAndAction findAction(const SizeAndActionsVec &Vec, 1453 const uint32_t Size); 1454 1455 /// Returns the next action needed to get the scalar or pointer type closer 1456 /// to being legal 1457 /// E.g. findLegalAction({G_REM, 13}) should return 1458 /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will 1459 /// probably be called, which should return (Lower, 32). 1460 /// This is assuming the setScalarAction on G_REM was something like: 1461 /// setScalarAction(G_REM, 0, 1462 /// {{1, WidenScalar}, // bit sizes [ 1, 31[ 1463 /// {32, Lower}, // bit sizes [32, 33[ 1464 /// {33, NarrowScalar} // bit sizes [65, +inf[ 1465 /// }); 1466 std::pair<LegalizeAction, LLT> 1467 findScalarLegalAction(const InstrAspect &Aspect) const; 1468 1469 /// Returns the next action needed towards legalizing the vector type. 1470 std::pair<LegalizeAction, LLT> 1471 findVectorLegalAction(const InstrAspect &Aspect) const; 1472 1473 static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START; 1474 static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END; 1475 1476 // Data structures used temporarily during construction of legality data: 1477 using TypeMap = DenseMap<LLT, LegalizeAction>; 1478 SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1]; 1479 SmallVector<SizeChangeStrategy, 1> 1480 ScalarSizeChangeStrategies[LastOp - FirstOp + 1]; 1481 SmallVector<SizeChangeStrategy, 1> 1482 VectorElementSizeChangeStrategies[LastOp - FirstOp + 1]; 1483 bool TablesInitialized; 1484 1485 // Data structures used by getAction: 1486 SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1]; 1487 SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1]; 1488 std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>> 1489 AddrSpace2PointerActions[LastOp - FirstOp + 1]; 1490 std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>> 1491 NumElements2Actions[LastOp - FirstOp + 1]; 1492 1493 LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1]; 1494 }; 1495 1496 #ifndef NDEBUG 1497 /// Checks that MIR is fully legal, returns an illegal instruction if it's not, 1498 /// nullptr otherwise 1499 const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF); 1500 #endif 1501 1502 } // end namespace llvm. 1503 1504 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H 1505