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/GlobalISel/LegacyLegalizerInfo.h" 24 #include "llvm/CodeGen/MachineFunction.h" 25 #include "llvm/CodeGen/TargetOpcodes.h" 26 #include "llvm/Support/CommandLine.h" 27 #include "llvm/Support/LowLevelTypeImpl.h" 28 #include "llvm/Support/raw_ostream.h" 29 #include <cassert> 30 #include <cstdint> 31 #include <tuple> 32 #include <unordered_map> 33 #include <utility> 34 35 namespace llvm { 36 37 extern cl::opt<bool> DisableGISelLegalityCheck; 38 39 class LegalizerHelper; 40 class MachineInstr; 41 class MachineRegisterInfo; 42 class MCInstrInfo; 43 class GISelChangeObserver; 44 45 namespace LegalizeActions { 46 enum LegalizeAction : std::uint8_t { 47 /// The operation is expected to be selectable directly by the target, and 48 /// no transformation is necessary. 49 Legal, 50 51 /// The operation should be synthesized from multiple instructions acting on 52 /// a narrower scalar base-type. For example a 64-bit add might be 53 /// implemented in terms of 32-bit add-with-carry. 54 NarrowScalar, 55 56 /// The operation should be implemented in terms of a wider scalar 57 /// base-type. For example a <2 x s8> add could be implemented as a <2 58 /// x s32> add (ignoring the high bits). 59 WidenScalar, 60 61 /// The (vector) operation should be implemented by splitting it into 62 /// sub-vectors where the operation is legal. For example a <8 x s64> add 63 /// might be implemented as 4 separate <2 x s64> adds. 64 FewerElements, 65 66 /// The (vector) operation should be implemented by widening the input 67 /// vector and ignoring the lanes added by doing so. For example <2 x i8> is 68 /// rarely legal, but you might perform an <8 x i8> and then only look at 69 /// the first two results. 70 MoreElements, 71 72 /// Perform the operation on a different, but equivalently sized type. 73 Bitcast, 74 75 /// The operation itself must be expressed in terms of simpler actions on 76 /// this target. E.g. a SREM replaced by an SDIV and subtraction. 77 Lower, 78 79 /// The operation should be implemented as a call to some kind of runtime 80 /// support library. For example this usually happens on machines that don't 81 /// support floating-point operations natively. 82 Libcall, 83 84 /// The target wants to do something special with this combination of 85 /// operand and type. A callback will be issued when it is needed. 86 Custom, 87 88 /// This operation is completely unsupported on the target. A programming 89 /// error has occurred. 90 Unsupported, 91 92 /// Sentinel value for when no action was found in the specified table. 93 NotFound, 94 95 /// Fall back onto the old rules. 96 /// TODO: Remove this once we've migrated 97 UseLegacyRules, 98 }; 99 } // end namespace LegalizeActions 100 raw_ostream &operator<<(raw_ostream &OS, LegalizeActions::LegalizeAction Action); 101 102 using LegalizeActions::LegalizeAction; 103 104 /// The LegalityQuery object bundles together all the information that's needed 105 /// to decide whether a given operation is legal or not. 106 /// For efficiency, it doesn't make a copy of Types so care must be taken not 107 /// to free it before using the query. 108 struct LegalityQuery { 109 unsigned Opcode; 110 ArrayRef<LLT> Types; 111 112 struct MemDesc { 113 LLT MemoryTy; 114 uint64_t AlignInBits; 115 AtomicOrdering Ordering; 116 }; 117 118 /// Operations which require memory can use this to place requirements on the 119 /// memory type for each MMO. 120 ArrayRef<MemDesc> MMODescrs; 121 122 constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types, 123 const ArrayRef<MemDesc> MMODescrs) 124 : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {} 125 constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types) 126 : LegalityQuery(Opcode, Types, {}) {} 127 128 raw_ostream &print(raw_ostream &OS) const; 129 }; 130 131 /// The result of a query. It either indicates a final answer of Legal or 132 /// Unsupported or describes an action that must be taken to make an operation 133 /// more legal. 134 struct LegalizeActionStep { 135 /// The action to take or the final answer. 136 LegalizeAction Action; 137 /// If describing an action, the type index to change. Otherwise zero. 138 unsigned TypeIdx; 139 /// If describing an action, the new type for TypeIdx. Otherwise LLT{}. 140 LLT NewType; 141 142 LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx, 143 const LLT NewType) 144 : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {} 145 146 LegalizeActionStep(LegacyLegalizeActionStep Step) 147 : TypeIdx(Step.TypeIdx), NewType(Step.NewType) { 148 switch (Step.Action) { 149 case LegacyLegalizeActions::Legal: 150 Action = LegalizeActions::Legal; 151 break; 152 case LegacyLegalizeActions::NarrowScalar: 153 Action = LegalizeActions::NarrowScalar; 154 break; 155 case LegacyLegalizeActions::WidenScalar: 156 Action = LegalizeActions::WidenScalar; 157 break; 158 case LegacyLegalizeActions::FewerElements: 159 Action = LegalizeActions::FewerElements; 160 break; 161 case LegacyLegalizeActions::MoreElements: 162 Action = LegalizeActions::MoreElements; 163 break; 164 case LegacyLegalizeActions::Bitcast: 165 Action = LegalizeActions::Bitcast; 166 break; 167 case LegacyLegalizeActions::Lower: 168 Action = LegalizeActions::Lower; 169 break; 170 case LegacyLegalizeActions::Libcall: 171 Action = LegalizeActions::Libcall; 172 break; 173 case LegacyLegalizeActions::Custom: 174 Action = LegalizeActions::Custom; 175 break; 176 case LegacyLegalizeActions::Unsupported: 177 Action = LegalizeActions::Unsupported; 178 break; 179 case LegacyLegalizeActions::NotFound: 180 Action = LegalizeActions::NotFound; 181 break; 182 } 183 } 184 185 bool operator==(const LegalizeActionStep &RHS) const { 186 return std::tie(Action, TypeIdx, NewType) == 187 std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType); 188 } 189 }; 190 191 using LegalityPredicate = std::function<bool (const LegalityQuery &)>; 192 using LegalizeMutation = 193 std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>; 194 195 namespace LegalityPredicates { 196 struct TypePairAndMemDesc { 197 LLT Type0; 198 LLT Type1; 199 LLT MemTy; 200 uint64_t Align; 201 202 bool operator==(const TypePairAndMemDesc &Other) const { 203 return Type0 == Other.Type0 && Type1 == Other.Type1 && 204 Align == Other.Align && MemTy == Other.MemTy; 205 } 206 207 /// \returns true if this memory access is legal with for the access described 208 /// by \p Other (The alignment is sufficient for the size and result type). 209 bool isCompatible(const TypePairAndMemDesc &Other) const { 210 return Type0 == Other.Type0 && Type1 == Other.Type1 && 211 Align >= Other.Align && 212 // FIXME: This perhaps should be stricter, but the current legality 213 // rules are written only considering the size. 214 MemTy.getSizeInBits() == Other.MemTy.getSizeInBits(); 215 } 216 }; 217 218 /// True iff P0 and P1 are true. 219 template<typename Predicate> 220 Predicate all(Predicate P0, Predicate P1) { 221 return [=](const LegalityQuery &Query) { 222 return P0(Query) && P1(Query); 223 }; 224 } 225 /// True iff all given predicates are true. 226 template<typename Predicate, typename... Args> 227 Predicate all(Predicate P0, Predicate P1, Args... args) { 228 return all(all(P0, P1), args...); 229 } 230 231 /// True iff P0 or P1 are true. 232 template<typename Predicate> 233 Predicate any(Predicate P0, Predicate P1) { 234 return [=](const LegalityQuery &Query) { 235 return P0(Query) || P1(Query); 236 }; 237 } 238 /// True iff any given predicates are true. 239 template<typename Predicate, typename... Args> 240 Predicate any(Predicate P0, Predicate P1, Args... args) { 241 return any(any(P0, P1), args...); 242 } 243 244 /// True iff the given type index is the specified type. 245 LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit); 246 /// True iff the given type index is one of the specified types. 247 LegalityPredicate typeInSet(unsigned TypeIdx, 248 std::initializer_list<LLT> TypesInit); 249 250 /// True iff the given type index is not the specified type. 251 inline LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type) { 252 return [=](const LegalityQuery &Query) { 253 return Query.Types[TypeIdx] != Type; 254 }; 255 } 256 257 /// True iff the given types for the given pair of type indexes is one of the 258 /// specified type pairs. 259 LegalityPredicate 260 typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1, 261 std::initializer_list<std::pair<LLT, LLT>> TypesInit); 262 /// True iff the given types for the given pair of type indexes is one of the 263 /// specified type pairs. 264 LegalityPredicate typePairAndMemDescInSet( 265 unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, 266 std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit); 267 /// True iff the specified type index is a scalar. 268 LegalityPredicate isScalar(unsigned TypeIdx); 269 /// True iff the specified type index is a vector. 270 LegalityPredicate isVector(unsigned TypeIdx); 271 /// True iff the specified type index is a pointer (with any address space). 272 LegalityPredicate isPointer(unsigned TypeIdx); 273 /// True iff the specified type index is a pointer with the specified address 274 /// space. 275 LegalityPredicate isPointer(unsigned TypeIdx, unsigned AddrSpace); 276 277 /// True if the type index is a vector with element type \p EltTy 278 LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy); 279 280 /// True iff the specified type index is a scalar that's narrower than the given 281 /// size. 282 LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size); 283 284 /// True iff the specified type index is a scalar that's wider than the given 285 /// size. 286 LegalityPredicate scalarWiderThan(unsigned TypeIdx, unsigned Size); 287 288 /// True iff the specified type index is a scalar or vector with an element type 289 /// that's narrower than the given size. 290 LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size); 291 292 /// True iff the specified type index is a scalar or a vector with an element 293 /// type that's wider than the given size. 294 LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size); 295 296 /// True iff the specified type index is a scalar whose size is not a power of 297 /// 2. 298 LegalityPredicate sizeNotPow2(unsigned TypeIdx); 299 300 /// True iff the specified type index is a scalar or vector whose element size 301 /// is not a power of 2. 302 LegalityPredicate scalarOrEltSizeNotPow2(unsigned TypeIdx); 303 304 /// True if the total bitwidth of the specified type index is \p Size bits. 305 LegalityPredicate sizeIs(unsigned TypeIdx, unsigned Size); 306 307 /// True iff the specified type indices are both the same bit size. 308 LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1); 309 310 /// True iff the first type index has a larger total bit size than second type 311 /// index. 312 LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1); 313 314 /// True iff the first type index has a smaller total bit size than second type 315 /// index. 316 LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1); 317 318 /// True iff the specified MMO index has a size that is not a power of 2 319 LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx); 320 /// True iff the specified type index is a vector whose element count is not a 321 /// power of 2. 322 LegalityPredicate numElementsNotPow2(unsigned TypeIdx); 323 /// True iff the specified MMO index has at an atomic ordering of at Ordering or 324 /// stronger. 325 LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx, 326 AtomicOrdering Ordering); 327 } // end namespace LegalityPredicates 328 329 namespace LegalizeMutations { 330 /// Select this specific type for the given type index. 331 LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty); 332 333 /// Keep the same type as the given type index. 334 LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx); 335 336 /// Keep the same scalar or element type as the given type index. 337 LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx); 338 339 /// Keep the same scalar or element type as the given type. 340 LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty); 341 342 /// Change the scalar size or element size to have the same scalar size as type 343 /// index \p FromIndex. Unlike changeElementTo, this discards pointer types and 344 /// only changes the size. 345 LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx); 346 347 /// Widen the scalar type or vector element type for the given type index to the 348 /// next power of 2. 349 LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0); 350 351 /// Add more elements to the type for the given type index to the next power of 352 /// 2. 353 LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0); 354 /// Break up the vector type for the given type index into the element type. 355 LegalizeMutation scalarize(unsigned TypeIdx); 356 } // end namespace LegalizeMutations 357 358 /// A single rule in a legalizer info ruleset. 359 /// The specified action is chosen when the predicate is true. Where appropriate 360 /// for the action (e.g. for WidenScalar) the new type is selected using the 361 /// given mutator. 362 class LegalizeRule { 363 LegalityPredicate Predicate; 364 LegalizeAction Action; 365 LegalizeMutation Mutation; 366 367 public: 368 LegalizeRule(LegalityPredicate Predicate, LegalizeAction Action, 369 LegalizeMutation Mutation = nullptr) 370 : Predicate(Predicate), Action(Action), Mutation(Mutation) {} 371 372 /// Test whether the LegalityQuery matches. 373 bool match(const LegalityQuery &Query) const { 374 return Predicate(Query); 375 } 376 377 LegalizeAction getAction() const { return Action; } 378 379 /// Determine the change to make. 380 std::pair<unsigned, LLT> determineMutation(const LegalityQuery &Query) const { 381 if (Mutation) 382 return Mutation(Query); 383 return std::make_pair(0, LLT{}); 384 } 385 }; 386 387 class LegalizeRuleSet { 388 /// When non-zero, the opcode we are an alias of 389 unsigned AliasOf; 390 /// If true, there is another opcode that aliases this one 391 bool IsAliasedByAnother; 392 SmallVector<LegalizeRule, 2> Rules; 393 394 #ifndef NDEBUG 395 /// If bit I is set, this rule set contains a rule that may handle (predicate 396 /// or perform an action upon (or both)) the type index I. The uncertainty 397 /// comes from free-form rules executing user-provided lambda functions. We 398 /// conservatively assume such rules do the right thing and cover all type 399 /// indices. The bitset is intentionally 1 bit wider than it absolutely needs 400 /// to be to distinguish such cases from the cases where all type indices are 401 /// individually handled. 402 SmallBitVector TypeIdxsCovered{MCOI::OPERAND_LAST_GENERIC - 403 MCOI::OPERAND_FIRST_GENERIC + 2}; 404 SmallBitVector ImmIdxsCovered{MCOI::OPERAND_LAST_GENERIC_IMM - 405 MCOI::OPERAND_FIRST_GENERIC_IMM + 2}; 406 #endif 407 408 unsigned typeIdx(unsigned TypeIdx) { 409 assert(TypeIdx <= 410 (MCOI::OPERAND_LAST_GENERIC - MCOI::OPERAND_FIRST_GENERIC) && 411 "Type Index is out of bounds"); 412 #ifndef NDEBUG 413 TypeIdxsCovered.set(TypeIdx); 414 #endif 415 return TypeIdx; 416 } 417 418 unsigned immIdx(unsigned ImmIdx) { 419 assert(ImmIdx <= (MCOI::OPERAND_LAST_GENERIC_IMM - 420 MCOI::OPERAND_FIRST_GENERIC_IMM) && 421 "Imm Index is out of bounds"); 422 #ifndef NDEBUG 423 ImmIdxsCovered.set(ImmIdx); 424 #endif 425 return ImmIdx; 426 } 427 428 void markAllIdxsAsCovered() { 429 #ifndef NDEBUG 430 TypeIdxsCovered.set(); 431 ImmIdxsCovered.set(); 432 #endif 433 } 434 435 void add(const LegalizeRule &Rule) { 436 assert(AliasOf == 0 && 437 "RuleSet is aliased, change the representative opcode instead"); 438 Rules.push_back(Rule); 439 } 440 441 static bool always(const LegalityQuery &) { return true; } 442 443 /// Use the given action when the predicate is true. 444 /// Action should not be an action that requires mutation. 445 LegalizeRuleSet &actionIf(LegalizeAction Action, 446 LegalityPredicate Predicate) { 447 add({Predicate, Action}); 448 return *this; 449 } 450 /// Use the given action when the predicate is true. 451 /// Action should be an action that requires mutation. 452 LegalizeRuleSet &actionIf(LegalizeAction Action, LegalityPredicate Predicate, 453 LegalizeMutation Mutation) { 454 add({Predicate, Action, Mutation}); 455 return *this; 456 } 457 /// Use the given action when type index 0 is any type in the given list. 458 /// Action should not be an action that requires mutation. 459 LegalizeRuleSet &actionFor(LegalizeAction Action, 460 std::initializer_list<LLT> Types) { 461 using namespace LegalityPredicates; 462 return actionIf(Action, typeInSet(typeIdx(0), Types)); 463 } 464 /// Use the given action when type index 0 is any type in the given list. 465 /// Action should be an action that requires mutation. 466 LegalizeRuleSet &actionFor(LegalizeAction Action, 467 std::initializer_list<LLT> Types, 468 LegalizeMutation Mutation) { 469 using namespace LegalityPredicates; 470 return actionIf(Action, typeInSet(typeIdx(0), Types), Mutation); 471 } 472 /// Use the given action when type indexes 0 and 1 is any type pair in the 473 /// given list. 474 /// Action should not be an action that requires mutation. 475 LegalizeRuleSet &actionFor(LegalizeAction Action, 476 std::initializer_list<std::pair<LLT, LLT>> Types) { 477 using namespace LegalityPredicates; 478 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types)); 479 } 480 /// Use the given action when type indexes 0 and 1 is any type pair in the 481 /// given list. 482 /// Action should be an action that requires mutation. 483 LegalizeRuleSet &actionFor(LegalizeAction Action, 484 std::initializer_list<std::pair<LLT, LLT>> Types, 485 LegalizeMutation Mutation) { 486 using namespace LegalityPredicates; 487 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types), 488 Mutation); 489 } 490 /// Use the given action when type index 0 is any type in the given list and 491 /// imm index 0 is anything. Action should not be an action that requires 492 /// mutation. 493 LegalizeRuleSet &actionForTypeWithAnyImm(LegalizeAction Action, 494 std::initializer_list<LLT> Types) { 495 using namespace LegalityPredicates; 496 immIdx(0); // Inform verifier imm idx 0 is handled. 497 return actionIf(Action, typeInSet(typeIdx(0), Types)); 498 } 499 500 LegalizeRuleSet &actionForTypeWithAnyImm( 501 LegalizeAction Action, std::initializer_list<std::pair<LLT, LLT>> Types) { 502 using namespace LegalityPredicates; 503 immIdx(0); // Inform verifier imm idx 0 is handled. 504 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types)); 505 } 506 507 /// Use the given action when type indexes 0 and 1 are both in the given list. 508 /// That is, the type pair is in the cartesian product of the list. 509 /// Action should not be an action that requires mutation. 510 LegalizeRuleSet &actionForCartesianProduct(LegalizeAction Action, 511 std::initializer_list<LLT> Types) { 512 using namespace LegalityPredicates; 513 return actionIf(Action, all(typeInSet(typeIdx(0), Types), 514 typeInSet(typeIdx(1), Types))); 515 } 516 /// Use the given action when type indexes 0 and 1 are both in their 517 /// respective lists. 518 /// That is, the type pair is in the cartesian product of the lists 519 /// Action should not be an action that requires mutation. 520 LegalizeRuleSet & 521 actionForCartesianProduct(LegalizeAction Action, 522 std::initializer_list<LLT> Types0, 523 std::initializer_list<LLT> Types1) { 524 using namespace LegalityPredicates; 525 return actionIf(Action, all(typeInSet(typeIdx(0), Types0), 526 typeInSet(typeIdx(1), Types1))); 527 } 528 /// Use the given action when type indexes 0, 1, and 2 are all in their 529 /// respective lists. 530 /// That is, the type triple is in the cartesian product of the lists 531 /// Action should not be an action that requires mutation. 532 LegalizeRuleSet &actionForCartesianProduct( 533 LegalizeAction Action, std::initializer_list<LLT> Types0, 534 std::initializer_list<LLT> Types1, std::initializer_list<LLT> Types2) { 535 using namespace LegalityPredicates; 536 return actionIf(Action, all(typeInSet(typeIdx(0), Types0), 537 all(typeInSet(typeIdx(1), Types1), 538 typeInSet(typeIdx(2), Types2)))); 539 } 540 541 public: 542 LegalizeRuleSet() : AliasOf(0), IsAliasedByAnother(false), Rules() {} 543 544 bool isAliasedByAnother() { return IsAliasedByAnother; } 545 void setIsAliasedByAnother() { IsAliasedByAnother = true; } 546 void aliasTo(unsigned Opcode) { 547 assert((AliasOf == 0 || AliasOf == Opcode) && 548 "Opcode is already aliased to another opcode"); 549 assert(Rules.empty() && "Aliasing will discard rules"); 550 AliasOf = Opcode; 551 } 552 unsigned getAlias() const { return AliasOf; } 553 554 /// The instruction is legal if predicate is true. 555 LegalizeRuleSet &legalIf(LegalityPredicate Predicate) { 556 // We have no choice but conservatively assume that the free-form 557 // user-provided Predicate properly handles all type indices: 558 markAllIdxsAsCovered(); 559 return actionIf(LegalizeAction::Legal, Predicate); 560 } 561 /// The instruction is legal when type index 0 is any type in the given list. 562 LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) { 563 return actionFor(LegalizeAction::Legal, Types); 564 } 565 /// The instruction is legal when type indexes 0 and 1 is any type pair in the 566 /// given list. 567 LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) { 568 return actionFor(LegalizeAction::Legal, Types); 569 } 570 /// The instruction is legal when type index 0 is any type in the given list 571 /// and imm index 0 is anything. 572 LegalizeRuleSet &legalForTypeWithAnyImm(std::initializer_list<LLT> Types) { 573 markAllIdxsAsCovered(); 574 return actionForTypeWithAnyImm(LegalizeAction::Legal, Types); 575 } 576 577 LegalizeRuleSet &legalForTypeWithAnyImm( 578 std::initializer_list<std::pair<LLT, LLT>> Types) { 579 markAllIdxsAsCovered(); 580 return actionForTypeWithAnyImm(LegalizeAction::Legal, Types); 581 } 582 583 /// The instruction is legal when type indexes 0 and 1 along with the memory 584 /// size and minimum alignment is any type and size tuple in the given list. 585 LegalizeRuleSet &legalForTypesWithMemDesc( 586 std::initializer_list<LegalityPredicates::TypePairAndMemDesc> 587 TypesAndMemDesc) { 588 return actionIf(LegalizeAction::Legal, 589 LegalityPredicates::typePairAndMemDescInSet( 590 typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc)); 591 } 592 /// The instruction is legal when type indexes 0 and 1 are both in the given 593 /// list. That is, the type pair is in the cartesian product of the list. 594 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types) { 595 return actionForCartesianProduct(LegalizeAction::Legal, Types); 596 } 597 /// The instruction is legal when type indexes 0 and 1 are both their 598 /// respective lists. 599 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0, 600 std::initializer_list<LLT> Types1) { 601 return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1); 602 } 603 /// The instruction is legal when type indexes 0, 1, and 2 are both their 604 /// respective lists. 605 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0, 606 std::initializer_list<LLT> Types1, 607 std::initializer_list<LLT> Types2) { 608 return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1, 609 Types2); 610 } 611 612 LegalizeRuleSet &alwaysLegal() { 613 using namespace LegalizeMutations; 614 markAllIdxsAsCovered(); 615 return actionIf(LegalizeAction::Legal, always); 616 } 617 618 /// The specified type index is coerced if predicate is true. 619 LegalizeRuleSet &bitcastIf(LegalityPredicate Predicate, 620 LegalizeMutation Mutation) { 621 // We have no choice but conservatively assume that lowering with a 622 // free-form user provided Predicate properly handles all type indices: 623 markAllIdxsAsCovered(); 624 return actionIf(LegalizeAction::Bitcast, Predicate, Mutation); 625 } 626 627 /// The instruction is lowered. 628 LegalizeRuleSet &lower() { 629 using namespace LegalizeMutations; 630 // We have no choice but conservatively assume that predicate-less lowering 631 // properly handles all type indices by design: 632 markAllIdxsAsCovered(); 633 return actionIf(LegalizeAction::Lower, always); 634 } 635 /// The instruction is lowered if predicate is true. Keep type index 0 as the 636 /// same type. 637 LegalizeRuleSet &lowerIf(LegalityPredicate Predicate) { 638 using namespace LegalizeMutations; 639 // We have no choice but conservatively assume that lowering with a 640 // free-form user provided Predicate properly handles all type indices: 641 markAllIdxsAsCovered(); 642 return actionIf(LegalizeAction::Lower, Predicate); 643 } 644 /// The instruction is lowered if predicate is true. 645 LegalizeRuleSet &lowerIf(LegalityPredicate Predicate, 646 LegalizeMutation Mutation) { 647 // We have no choice but conservatively assume that lowering with a 648 // free-form user provided Predicate properly handles all type indices: 649 markAllIdxsAsCovered(); 650 return actionIf(LegalizeAction::Lower, Predicate, Mutation); 651 } 652 /// The instruction is lowered when type index 0 is any type in the given 653 /// list. Keep type index 0 as the same type. 654 LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types) { 655 return actionFor(LegalizeAction::Lower, Types); 656 } 657 /// The instruction is lowered when type index 0 is any type in the given 658 /// list. 659 LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types, 660 LegalizeMutation Mutation) { 661 return actionFor(LegalizeAction::Lower, Types, Mutation); 662 } 663 /// The instruction is lowered when type indexes 0 and 1 is any type pair in 664 /// the given list. Keep type index 0 as the same type. 665 LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) { 666 return actionFor(LegalizeAction::Lower, Types); 667 } 668 /// The instruction is lowered when type indexes 0 and 1 is any type pair in 669 /// the given list. 670 LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types, 671 LegalizeMutation Mutation) { 672 return actionFor(LegalizeAction::Lower, Types, Mutation); 673 } 674 /// The instruction is lowered when type indexes 0 and 1 are both in their 675 /// respective lists. 676 LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0, 677 std::initializer_list<LLT> Types1) { 678 using namespace LegalityPredicates; 679 return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1); 680 } 681 /// The instruction is lowered when when type indexes 0, 1, and 2 are all in 682 /// their respective lists. 683 LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0, 684 std::initializer_list<LLT> Types1, 685 std::initializer_list<LLT> Types2) { 686 using namespace LegalityPredicates; 687 return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1, 688 Types2); 689 } 690 691 /// The instruction is emitted as a library call. 692 LegalizeRuleSet &libcall() { 693 using namespace LegalizeMutations; 694 // We have no choice but conservatively assume that predicate-less lowering 695 // properly handles all type indices by design: 696 markAllIdxsAsCovered(); 697 return actionIf(LegalizeAction::Libcall, always); 698 } 699 700 /// Like legalIf, but for the Libcall action. 701 LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) { 702 // We have no choice but conservatively assume that a libcall with a 703 // free-form user provided Predicate properly handles all type indices: 704 markAllIdxsAsCovered(); 705 return actionIf(LegalizeAction::Libcall, Predicate); 706 } 707 LegalizeRuleSet &libcallFor(std::initializer_list<LLT> Types) { 708 return actionFor(LegalizeAction::Libcall, Types); 709 } 710 LegalizeRuleSet & 711 libcallFor(std::initializer_list<std::pair<LLT, LLT>> Types) { 712 return actionFor(LegalizeAction::Libcall, Types); 713 } 714 LegalizeRuleSet & 715 libcallForCartesianProduct(std::initializer_list<LLT> Types) { 716 return actionForCartesianProduct(LegalizeAction::Libcall, Types); 717 } 718 LegalizeRuleSet & 719 libcallForCartesianProduct(std::initializer_list<LLT> Types0, 720 std::initializer_list<LLT> Types1) { 721 return actionForCartesianProduct(LegalizeAction::Libcall, Types0, Types1); 722 } 723 724 /// Widen the scalar to the one selected by the mutation if the predicate is 725 /// true. 726 LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate, 727 LegalizeMutation Mutation) { 728 // We have no choice but conservatively assume that an action with a 729 // free-form user provided Predicate properly handles all type indices: 730 markAllIdxsAsCovered(); 731 return actionIf(LegalizeAction::WidenScalar, Predicate, Mutation); 732 } 733 /// Narrow the scalar to the one selected by the mutation if the predicate is 734 /// true. 735 LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate, 736 LegalizeMutation Mutation) { 737 // We have no choice but conservatively assume that an action with a 738 // free-form user provided Predicate properly handles all type indices: 739 markAllIdxsAsCovered(); 740 return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation); 741 } 742 /// Narrow the scalar, specified in mutation, when type indexes 0 and 1 is any 743 /// type pair in the given list. 744 LegalizeRuleSet & 745 narrowScalarFor(std::initializer_list<std::pair<LLT, LLT>> Types, 746 LegalizeMutation Mutation) { 747 return actionFor(LegalizeAction::NarrowScalar, Types, Mutation); 748 } 749 750 /// Add more elements to reach the type selected by the mutation if the 751 /// predicate is true. 752 LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate, 753 LegalizeMutation Mutation) { 754 // We have no choice but conservatively assume that an action with a 755 // free-form user provided Predicate properly handles all type indices: 756 markAllIdxsAsCovered(); 757 return actionIf(LegalizeAction::MoreElements, Predicate, Mutation); 758 } 759 /// Remove elements to reach the type selected by the mutation if the 760 /// predicate is true. 761 LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate, 762 LegalizeMutation Mutation) { 763 // We have no choice but conservatively assume that an action with a 764 // free-form user provided Predicate properly handles all type indices: 765 markAllIdxsAsCovered(); 766 return actionIf(LegalizeAction::FewerElements, Predicate, Mutation); 767 } 768 769 /// The instruction is unsupported. 770 LegalizeRuleSet &unsupported() { 771 markAllIdxsAsCovered(); 772 return actionIf(LegalizeAction::Unsupported, always); 773 } 774 LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) { 775 return actionIf(LegalizeAction::Unsupported, Predicate); 776 } 777 778 LegalizeRuleSet &unsupportedFor(std::initializer_list<LLT> Types) { 779 return actionFor(LegalizeAction::Unsupported, Types); 780 } 781 782 LegalizeRuleSet &unsupportedIfMemSizeNotPow2() { 783 return actionIf(LegalizeAction::Unsupported, 784 LegalityPredicates::memSizeInBytesNotPow2(0)); 785 } 786 LegalizeRuleSet &lowerIfMemSizeNotPow2() { 787 return actionIf(LegalizeAction::Lower, 788 LegalityPredicates::memSizeInBytesNotPow2(0)); 789 } 790 791 LegalizeRuleSet &customIf(LegalityPredicate Predicate) { 792 // We have no choice but conservatively assume that a custom action with a 793 // free-form user provided Predicate properly handles all type indices: 794 markAllIdxsAsCovered(); 795 return actionIf(LegalizeAction::Custom, Predicate); 796 } 797 LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) { 798 return actionFor(LegalizeAction::Custom, Types); 799 } 800 801 /// The instruction is custom when type indexes 0 and 1 is any type pair in the 802 /// given list. 803 LegalizeRuleSet &customFor(std::initializer_list<std::pair<LLT, LLT>> Types) { 804 return actionFor(LegalizeAction::Custom, Types); 805 } 806 807 LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) { 808 return actionForCartesianProduct(LegalizeAction::Custom, Types); 809 } 810 LegalizeRuleSet & 811 customForCartesianProduct(std::initializer_list<LLT> Types0, 812 std::initializer_list<LLT> Types1) { 813 return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1); 814 } 815 816 /// Unconditionally custom lower. 817 LegalizeRuleSet &custom() { 818 return customIf(always); 819 } 820 821 /// Widen the scalar to the next power of two that is at least MinSize. 822 /// No effect if the type is not a scalar or is a power of two. 823 LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx, 824 unsigned MinSize = 0) { 825 using namespace LegalityPredicates; 826 return actionIf( 827 LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)), 828 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize)); 829 } 830 831 /// Widen the scalar or vector element type to the next power of two that is 832 /// at least MinSize. No effect if the scalar size is a power of two. 833 LegalizeRuleSet &widenScalarOrEltToNextPow2(unsigned TypeIdx, 834 unsigned MinSize = 0) { 835 using namespace LegalityPredicates; 836 return actionIf( 837 LegalizeAction::WidenScalar, scalarOrEltSizeNotPow2(typeIdx(TypeIdx)), 838 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize)); 839 } 840 841 LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) { 842 using namespace LegalityPredicates; 843 return actionIf(LegalizeAction::NarrowScalar, isScalar(typeIdx(TypeIdx)), 844 Mutation); 845 } 846 847 LegalizeRuleSet &scalarize(unsigned TypeIdx) { 848 using namespace LegalityPredicates; 849 return actionIf(LegalizeAction::FewerElements, isVector(typeIdx(TypeIdx)), 850 LegalizeMutations::scalarize(TypeIdx)); 851 } 852 853 LegalizeRuleSet &scalarizeIf(LegalityPredicate Predicate, unsigned TypeIdx) { 854 using namespace LegalityPredicates; 855 return actionIf(LegalizeAction::FewerElements, 856 all(Predicate, isVector(typeIdx(TypeIdx))), 857 LegalizeMutations::scalarize(TypeIdx)); 858 } 859 860 /// Ensure the scalar or element is at least as wide as Ty. 861 LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT Ty) { 862 using namespace LegalityPredicates; 863 using namespace LegalizeMutations; 864 return actionIf(LegalizeAction::WidenScalar, 865 scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()), 866 changeElementTo(typeIdx(TypeIdx), Ty)); 867 } 868 869 /// Ensure the scalar or element is at least as wide as Ty. 870 LegalizeRuleSet &minScalarOrEltIf(LegalityPredicate Predicate, 871 unsigned TypeIdx, const LLT Ty) { 872 using namespace LegalityPredicates; 873 using namespace LegalizeMutations; 874 return actionIf(LegalizeAction::WidenScalar, 875 all(Predicate, scalarOrEltNarrowerThan( 876 TypeIdx, Ty.getScalarSizeInBits())), 877 changeElementTo(typeIdx(TypeIdx), Ty)); 878 } 879 880 /// Ensure the scalar is at least as wide as Ty. 881 LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT Ty) { 882 using namespace LegalityPredicates; 883 using namespace LegalizeMutations; 884 return actionIf(LegalizeAction::WidenScalar, 885 scalarNarrowerThan(TypeIdx, Ty.getSizeInBits()), 886 changeTo(typeIdx(TypeIdx), Ty)); 887 } 888 889 /// Ensure the scalar is at most as wide as Ty. 890 LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT Ty) { 891 using namespace LegalityPredicates; 892 using namespace LegalizeMutations; 893 return actionIf(LegalizeAction::NarrowScalar, 894 scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()), 895 changeElementTo(typeIdx(TypeIdx), Ty)); 896 } 897 898 /// Ensure the scalar is at most as wide as Ty. 899 LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT Ty) { 900 using namespace LegalityPredicates; 901 using namespace LegalizeMutations; 902 return actionIf(LegalizeAction::NarrowScalar, 903 scalarWiderThan(TypeIdx, Ty.getSizeInBits()), 904 changeTo(typeIdx(TypeIdx), Ty)); 905 } 906 907 /// Conditionally limit the maximum size of the scalar. 908 /// For example, when the maximum size of one type depends on the size of 909 /// another such as extracting N bits from an M bit container. 910 LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, 911 const LLT Ty) { 912 using namespace LegalityPredicates; 913 using namespace LegalizeMutations; 914 return actionIf( 915 LegalizeAction::NarrowScalar, 916 [=](const LegalityQuery &Query) { 917 const LLT QueryTy = Query.Types[TypeIdx]; 918 return QueryTy.isScalar() && 919 QueryTy.getSizeInBits() > Ty.getSizeInBits() && 920 Predicate(Query); 921 }, 922 changeElementTo(typeIdx(TypeIdx), Ty)); 923 } 924 925 /// Limit the range of scalar sizes to MinTy and MaxTy. 926 LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT MinTy, 927 const LLT MaxTy) { 928 assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types"); 929 return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy); 930 } 931 932 /// Limit the range of scalar sizes to MinTy and MaxTy. 933 LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT MinTy, 934 const LLT MaxTy) { 935 return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy); 936 } 937 938 /// Widen the scalar to match the size of another. 939 LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) { 940 typeIdx(TypeIdx); 941 return widenScalarIf( 942 [=](const LegalityQuery &Query) { 943 return Query.Types[LargeTypeIdx].getScalarSizeInBits() > 944 Query.Types[TypeIdx].getSizeInBits(); 945 }, 946 LegalizeMutations::changeElementSizeTo(TypeIdx, LargeTypeIdx)); 947 } 948 949 /// Narrow the scalar to match the size of another. 950 LegalizeRuleSet &maxScalarSameAs(unsigned TypeIdx, unsigned NarrowTypeIdx) { 951 typeIdx(TypeIdx); 952 return narrowScalarIf( 953 [=](const LegalityQuery &Query) { 954 return Query.Types[NarrowTypeIdx].getScalarSizeInBits() < 955 Query.Types[TypeIdx].getSizeInBits(); 956 }, 957 LegalizeMutations::changeElementSizeTo(TypeIdx, NarrowTypeIdx)); 958 } 959 960 /// Change the type \p TypeIdx to have the same scalar size as type \p 961 /// SameSizeIdx. 962 LegalizeRuleSet &scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx) { 963 return minScalarSameAs(TypeIdx, SameSizeIdx) 964 .maxScalarSameAs(TypeIdx, SameSizeIdx); 965 } 966 967 /// Conditionally widen the scalar or elt to match the size of another. 968 LegalizeRuleSet &minScalarEltSameAsIf(LegalityPredicate Predicate, 969 unsigned TypeIdx, unsigned LargeTypeIdx) { 970 typeIdx(TypeIdx); 971 return widenScalarIf( 972 [=](const LegalityQuery &Query) { 973 return Query.Types[LargeTypeIdx].getScalarSizeInBits() > 974 Query.Types[TypeIdx].getScalarSizeInBits() && 975 Predicate(Query); 976 }, 977 [=](const LegalityQuery &Query) { 978 LLT T = Query.Types[LargeTypeIdx]; 979 return std::make_pair(TypeIdx, T); 980 }); 981 } 982 983 /// Conditionally narrow the scalar or elt to match the size of another. 984 LegalizeRuleSet &maxScalarEltSameAsIf(LegalityPredicate Predicate, 985 unsigned TypeIdx, 986 unsigned SmallTypeIdx) { 987 typeIdx(TypeIdx); 988 return narrowScalarIf( 989 [=](const LegalityQuery &Query) { 990 return Query.Types[SmallTypeIdx].getScalarSizeInBits() < 991 Query.Types[TypeIdx].getScalarSizeInBits() && 992 Predicate(Query); 993 }, 994 [=](const LegalityQuery &Query) { 995 LLT T = Query.Types[SmallTypeIdx]; 996 return std::make_pair(TypeIdx, T); 997 }); 998 } 999 1000 /// Add more elements to the vector to reach the next power of two. 1001 /// No effect if the type is not a vector or the element count is a power of 1002 /// two. 1003 LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) { 1004 using namespace LegalityPredicates; 1005 return actionIf(LegalizeAction::MoreElements, 1006 numElementsNotPow2(typeIdx(TypeIdx)), 1007 LegalizeMutations::moreElementsToNextPow2(TypeIdx)); 1008 } 1009 1010 /// Limit the number of elements in EltTy vectors to at least MinElements. 1011 LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT EltTy, 1012 unsigned MinElements) { 1013 // Mark the type index as covered: 1014 typeIdx(TypeIdx); 1015 return actionIf( 1016 LegalizeAction::MoreElements, 1017 [=](const LegalityQuery &Query) { 1018 LLT VecTy = Query.Types[TypeIdx]; 1019 return VecTy.isVector() && VecTy.getElementType() == EltTy && 1020 VecTy.getNumElements() < MinElements; 1021 }, 1022 [=](const LegalityQuery &Query) { 1023 LLT VecTy = Query.Types[TypeIdx]; 1024 return std::make_pair( 1025 TypeIdx, LLT::fixed_vector(MinElements, VecTy.getElementType())); 1026 }); 1027 } 1028 /// Limit the number of elements in EltTy vectors to at most MaxElements. 1029 LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, 1030 unsigned MaxElements) { 1031 // Mark the type index as covered: 1032 typeIdx(TypeIdx); 1033 return actionIf( 1034 LegalizeAction::FewerElements, 1035 [=](const LegalityQuery &Query) { 1036 LLT VecTy = Query.Types[TypeIdx]; 1037 return VecTy.isVector() && VecTy.getElementType() == EltTy && 1038 VecTy.getNumElements() > MaxElements; 1039 }, 1040 [=](const LegalityQuery &Query) { 1041 LLT VecTy = Query.Types[TypeIdx]; 1042 LLT NewTy = LLT::scalarOrVector(ElementCount::getFixed(MaxElements), 1043 VecTy.getElementType()); 1044 return std::make_pair(TypeIdx, NewTy); 1045 }); 1046 } 1047 /// Limit the number of elements for the given vectors to at least MinTy's 1048 /// number of elements and at most MaxTy's number of elements. 1049 /// 1050 /// No effect if the type is not a vector or does not have the same element 1051 /// type as the constraints. 1052 /// The element type of MinTy and MaxTy must match. 1053 LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT MinTy, 1054 const LLT MaxTy) { 1055 assert(MinTy.getElementType() == MaxTy.getElementType() && 1056 "Expected element types to agree"); 1057 1058 const LLT EltTy = MinTy.getElementType(); 1059 return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements()) 1060 .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements()); 1061 } 1062 1063 /// Fallback on the previous implementation. This should only be used while 1064 /// porting a rule. 1065 LegalizeRuleSet &fallback() { 1066 add({always, LegalizeAction::UseLegacyRules}); 1067 return *this; 1068 } 1069 1070 /// Check if there is no type index which is obviously not handled by the 1071 /// LegalizeRuleSet in any way at all. 1072 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set. 1073 bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const; 1074 /// Check if there is no imm index which is obviously not handled by the 1075 /// LegalizeRuleSet in any way at all. 1076 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set. 1077 bool verifyImmIdxsCoverage(unsigned NumImmIdxs) const; 1078 1079 /// Apply the ruleset to the given LegalityQuery. 1080 LegalizeActionStep apply(const LegalityQuery &Query) const; 1081 }; 1082 1083 class LegalizerInfo { 1084 public: 1085 virtual ~LegalizerInfo() = default; 1086 1087 const LegacyLegalizerInfo &getLegacyLegalizerInfo() const { 1088 return LegacyInfo; 1089 } 1090 LegacyLegalizerInfo &getLegacyLegalizerInfo() { return LegacyInfo; } 1091 1092 unsigned getOpcodeIdxForOpcode(unsigned Opcode) const; 1093 unsigned getActionDefinitionsIdx(unsigned Opcode) const; 1094 1095 /// Perform simple self-diagnostic and assert if there is anything obviously 1096 /// wrong with the actions set up. 1097 void verify(const MCInstrInfo &MII) const; 1098 1099 /// Get the action definitions for the given opcode. Use this to run a 1100 /// LegalityQuery through the definitions. 1101 const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const; 1102 1103 /// Get the action definition builder for the given opcode. Use this to define 1104 /// the action definitions. 1105 /// 1106 /// It is an error to request an opcode that has already been requested by the 1107 /// multiple-opcode variant. 1108 LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode); 1109 1110 /// Get the action definition builder for the given set of opcodes. Use this 1111 /// to define the action definitions for multiple opcodes at once. The first 1112 /// opcode given will be considered the representative opcode and will hold 1113 /// the definitions whereas the other opcodes will be configured to refer to 1114 /// the representative opcode. This lowers memory requirements and very 1115 /// slightly improves performance. 1116 /// 1117 /// It would be very easy to introduce unexpected side-effects as a result of 1118 /// this aliasing if it were permitted to request different but intersecting 1119 /// sets of opcodes but that is difficult to keep track of. It is therefore an 1120 /// error to request the same opcode twice using this API, to request an 1121 /// opcode that already has definitions, or to use the single-opcode API on an 1122 /// opcode that has already been requested by this API. 1123 LegalizeRuleSet & 1124 getActionDefinitionsBuilder(std::initializer_list<unsigned> Opcodes); 1125 void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom); 1126 1127 /// Determine what action should be taken to legalize the described 1128 /// instruction. Requires computeTables to have been called. 1129 /// 1130 /// \returns a description of the next legalization step to perform. 1131 LegalizeActionStep getAction(const LegalityQuery &Query) const; 1132 1133 /// Determine what action should be taken to legalize the given generic 1134 /// instruction. 1135 /// 1136 /// \returns a description of the next legalization step to perform. 1137 LegalizeActionStep getAction(const MachineInstr &MI, 1138 const MachineRegisterInfo &MRI) const; 1139 1140 bool isLegal(const LegalityQuery &Query) const { 1141 return getAction(Query).Action == LegalizeAction::Legal; 1142 } 1143 1144 bool isLegalOrCustom(const LegalityQuery &Query) const { 1145 auto Action = getAction(Query).Action; 1146 return Action == LegalizeAction::Legal || Action == LegalizeAction::Custom; 1147 } 1148 1149 bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; 1150 bool isLegalOrCustom(const MachineInstr &MI, 1151 const MachineRegisterInfo &MRI) const; 1152 1153 /// Called for instructions with the Custom LegalizationAction. 1154 virtual bool legalizeCustom(LegalizerHelper &Helper, 1155 MachineInstr &MI) const { 1156 llvm_unreachable("must implement this if custom action is used"); 1157 } 1158 1159 /// \returns true if MI is either legal or has been legalized and false if not 1160 /// legal. 1161 /// Return true if MI is either legal or has been legalized and false 1162 /// if not legal. 1163 virtual bool legalizeIntrinsic(LegalizerHelper &Helper, 1164 MachineInstr &MI) const { 1165 return true; 1166 } 1167 1168 /// Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while 1169 /// widening a constant of type SmallTy which targets can override. 1170 /// For eg, the DAG does (SmallTy.isByteSized() ? G_SEXT : G_ZEXT) which 1171 /// will be the default. 1172 virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const; 1173 1174 private: 1175 static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START; 1176 static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END; 1177 1178 LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1]; 1179 LegacyLegalizerInfo LegacyInfo; 1180 }; 1181 1182 #ifndef NDEBUG 1183 /// Checks that MIR is fully legal, returns an illegal instruction if it's not, 1184 /// nullptr otherwise 1185 const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF); 1186 #endif 1187 1188 } // end namespace llvm. 1189 1190 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H 1191