LLVM  7.0.0svn
LegalizerInfo.cpp
Go to the documentation of this file.
1 //===- lib/CodeGen/GlobalISel/LegalizerInfo.cpp - Legalizer ---------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Implement an interface to specify and query how an illegal operation on a
11 // given type should be expanded.
12 //
13 // Issues to be resolved:
14 // + Make it fast.
15 // + Support weird types like i3, <7 x i3>, ...
16 // + Operations with more than one type (ICMP, CMPXCHG, intrinsics, ...)
17 //
18 //===----------------------------------------------------------------------===//
19 
26 #include "llvm/MC/MCInstrDesc.h"
27 #include "llvm/MC/MCInstrInfo.h"
28 #include "llvm/Support/Debug.h"
32 #include <algorithm>
33 #include <map>
34 
35 using namespace llvm;
36 using namespace LegalizeActions;
37 
38 #define DEBUG_TYPE "legalizer-info"
39 
41  "disable-gisel-legality-check",
42  cl::desc("Don't verify that MIR is fully legal between GlobalISel passes"),
43  cl::Hidden);
44 
46  OS << Opcode << ", Tys={";
47  for (const auto &Type : Types) {
48  OS << Type << ", ";
49  }
50  OS << "}, Opcode=";
51 
52  OS << Opcode << ", MMOs={";
53  for (const auto &MMODescr : MMODescrs) {
54  OS << MMODescr.Size << ", ";
55  }
56  OS << "}";
57 
58  return OS;
59 }
60 
62  LLVM_DEBUG(dbgs() << "Applying legalizer ruleset to: "; Query.print(dbgs());
63  dbgs() << "\n");
64  if (Rules.empty()) {
65  LLVM_DEBUG(dbgs() << ".. fallback to legacy rules (no rules defined)\n");
66  return {LegalizeAction::UseLegacyRules, 0, LLT{}};
67  }
68  for (const auto &Rule : Rules) {
69  if (Rule.match(Query)) {
70  LLVM_DEBUG(dbgs() << ".. match\n");
71  std::pair<unsigned, LLT> Mutation = Rule.determineMutation(Query);
72  LLVM_DEBUG(dbgs() << ".. .. " << (unsigned)Rule.getAction() << ", "
73  << Mutation.first << ", " << Mutation.second << "\n");
74  assert((Query.Types[Mutation.first] != Mutation.second ||
75  Rule.getAction() == Lower ||
76  Rule.getAction() == MoreElements ||
77  Rule.getAction() == FewerElements) &&
78  "Simple loop detected");
79  return {Rule.getAction(), Mutation.first, Mutation.second};
80  } else
81  LLVM_DEBUG(dbgs() << ".. no match\n");
82  }
83  LLVM_DEBUG(dbgs() << ".. unsupported\n");
84  return {LegalizeAction::Unsupported, 0, LLT{}};
85 }
86 
87 bool LegalizeRuleSet::verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const {
88 #ifndef NDEBUG
89  if (Rules.empty()) {
90  LLVM_DEBUG(
91  dbgs() << ".. type index coverage check SKIPPED: no rules defined\n");
92  return true;
93  }
94  const int64_t FirstUncovered = TypeIdxsCovered.find_first_unset();
95  if (FirstUncovered < 0) {
96  LLVM_DEBUG(dbgs() << ".. type index coverage check SKIPPED:"
97  " user-defined predicate detected\n");
98  return true;
99  }
100  const bool AllCovered = (FirstUncovered >= NumTypeIdxs);
101  LLVM_DEBUG(dbgs() << ".. the first uncovered type index: " << FirstUncovered
102  << ", " << (AllCovered ? "OK" : "FAIL") << "\n");
103  return AllCovered;
104 #else
105  return true;
106 #endif
107 }
108 
109 LegalizerInfo::LegalizerInfo() : TablesInitialized(false) {
110  // Set defaults.
111  // FIXME: these two (G_ANYEXT and G_TRUNC?) can be legalized to the
112  // fundamental load/store Jakob proposed. Once loads & stores are supported.
113  setScalarAction(TargetOpcode::G_ANYEXT, 1, {{1, Legal}});
114  setScalarAction(TargetOpcode::G_ZEXT, 1, {{1, Legal}});
115  setScalarAction(TargetOpcode::G_SEXT, 1, {{1, Legal}});
116  setScalarAction(TargetOpcode::G_TRUNC, 0, {{1, Legal}});
117  setScalarAction(TargetOpcode::G_TRUNC, 1, {{1, Legal}});
118 
119  setScalarAction(TargetOpcode::G_INTRINSIC, 0, {{1, Legal}});
120  setScalarAction(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS, 0, {{1, Legal}});
121 
123  TargetOpcode::G_IMPLICIT_DEF, 0, narrowToSmallerAndUnsupportedIfTooSmall);
125  TargetOpcode::G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
127  TargetOpcode::G_OR, 0, widenToLargerTypesAndNarrowToLargest);
129  TargetOpcode::G_LOAD, 0, narrowToSmallerAndUnsupportedIfTooSmall);
131  TargetOpcode::G_STORE, 0, narrowToSmallerAndUnsupportedIfTooSmall);
132 
134  TargetOpcode::G_BRCOND, 0, widenToLargerTypesUnsupportedOtherwise);
136  TargetOpcode::G_INSERT, 0, narrowToSmallerAndUnsupportedIfTooSmall);
138  TargetOpcode::G_EXTRACT, 0, narrowToSmallerAndUnsupportedIfTooSmall);
140  TargetOpcode::G_EXTRACT, 1, narrowToSmallerAndUnsupportedIfTooSmall);
141  setScalarAction(TargetOpcode::G_FNEG, 0, {{1, Lower}});
142 }
143 
145  assert(TablesInitialized == false);
146 
147  for (unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {
148  const unsigned Opcode = FirstOp + OpcodeIdx;
149  for (unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size();
150  ++TypeIdx) {
151  // 0. Collect information specified through the setAction API, i.e.
152  // for specific bit sizes.
153  // For scalar types:
154  SizeAndActionsVec ScalarSpecifiedActions;
155  // For pointer types:
156  std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;
157  // For vector types:
158  std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;
159  for (auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {
160  const LLT Type = LLT2Action.first;
161  const LegalizeAction Action = LLT2Action.second;
162 
163  auto SizeAction = std::make_pair(Type.getSizeInBits(), Action);
164  if (Type.isPointer())
165  AddressSpace2SpecifiedActions[Type.getAddressSpace()].push_back(
166  SizeAction);
167  else if (Type.isVector())
168  ElemSize2SpecifiedActions[Type.getElementType().getSizeInBits()]
169  .push_back(SizeAction);
170  else
171  ScalarSpecifiedActions.push_back(SizeAction);
172  }
173 
174  // 1. Handle scalar types
175  {
176  // Decide how to handle bit sizes for which no explicit specification
177  // was given.
179  if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].size() &&
180  ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
181  S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx];
182  llvm::sort(ScalarSpecifiedActions.begin(),
183  ScalarSpecifiedActions.end());
184  checkPartialSizeAndActionsVector(ScalarSpecifiedActions);
185  setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));
186  }
187 
188  // 2. Handle pointer types
189  for (auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {
190  llvm::sort(PointerSpecifiedActions.second.begin(),
191  PointerSpecifiedActions.second.end());
192  checkPartialSizeAndActionsVector(PointerSpecifiedActions.second);
193  // For pointer types, we assume that there isn't a meaningfull way
194  // to change the number of bits used in the pointer.
195  setPointerAction(
196  Opcode, TypeIdx, PointerSpecifiedActions.first,
197  unsupportedForDifferentSizes(PointerSpecifiedActions.second));
198  }
199 
200  // 3. Handle vector types
201  SizeAndActionsVec ElementSizesSeen;
202  for (auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {
203  llvm::sort(VectorSpecifiedActions.second.begin(),
204  VectorSpecifiedActions.second.end());
205  const uint16_t ElementSize = VectorSpecifiedActions.first;
206  ElementSizesSeen.push_back({ElementSize, Legal});
207  checkPartialSizeAndActionsVector(VectorSpecifiedActions.second);
208  // For vector types, we assume that the best way to adapt the number
209  // of elements is to the next larger number of elements type for which
210  // the vector type is legal, unless there is no such type. In that case,
211  // legalize towards a vector type with a smaller number of elements.
212  SizeAndActionsVec NumElementsActions;
213  for (SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) {
214  assert(BitsizeAndAction.first % ElementSize == 0);
215  const uint16_t NumElements = BitsizeAndAction.first / ElementSize;
216  NumElementsActions.push_back({NumElements, BitsizeAndAction.second});
217  }
218  setVectorNumElementAction(
219  Opcode, TypeIdx, ElementSize,
220  moreToWiderTypesAndLessToWidest(NumElementsActions));
221  }
222  llvm::sort(ElementSizesSeen.begin(), ElementSizesSeen.end());
223  SizeChangeStrategy VectorElementSizeChangeStrategy =
225  if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].size() &&
226  VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
227  VectorElementSizeChangeStrategy =
228  VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];
229  setScalarInVectorAction(
230  Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen));
231  }
232  }
233 
234  TablesInitialized = true;
235 }
236 
237 // FIXME: inefficient implementation for now. Without ComputeValueVTs we're
238 // probably going to need specialized lookup structures for various types before
239 // we have any hope of doing well with something like <13 x i3>. Even the common
240 // cases should do better than what we have now.
241 std::pair<LegalizeAction, LLT>
242 LegalizerInfo::getAspectAction(const InstrAspect &Aspect) const {
243  assert(TablesInitialized && "backend forgot to call computeTables");
244  // These *have* to be implemented for now, they're the fundamental basis of
245  // how everything else is transformed.
246  if (Aspect.Type.isScalar() || Aspect.Type.isPointer())
247  return findScalarLegalAction(Aspect);
248  assert(Aspect.Type.isVector());
249  return findVectorLegalAction(Aspect);
250 }
251 
252 /// Helper function to get LLT for the given type index.
254  const MachineRegisterInfo &MRI, unsigned OpIdx,
255  unsigned TypeIdx) {
256  assert(TypeIdx < MI.getNumOperands() && "Unexpected TypeIdx");
257  // G_UNMERGE_VALUES has variable number of operands, but there is only
258  // one source type and one destination type as all destinations must be the
259  // same type. So, get the last operand if TypeIdx == 1.
260  if (MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES && TypeIdx == 1)
261  return MRI.getType(MI.getOperand(MI.getNumOperands() - 1).getReg());
262  return MRI.getType(MI.getOperand(OpIdx).getReg());
263 }
264 
265 unsigned LegalizerInfo::getOpcodeIdxForOpcode(unsigned Opcode) const {
266  assert(Opcode >= FirstOp && Opcode <= LastOp && "Unsupported opcode");
267  return Opcode - FirstOp;
268 }
269 
270 unsigned LegalizerInfo::getActionDefinitionsIdx(unsigned Opcode) const {
271  unsigned OpcodeIdx = getOpcodeIdxForOpcode(Opcode);
272  if (unsigned Alias = RulesForOpcode[OpcodeIdx].getAlias()) {
273  LLVM_DEBUG(dbgs() << ".. opcode " << Opcode << " is aliased to " << Alias
274  << "\n");
275  OpcodeIdx = getOpcodeIdxForOpcode(Alias);
276  LLVM_DEBUG(dbgs() << ".. opcode " << Alias << " is aliased to "
277  << RulesForOpcode[OpcodeIdx].getAlias() << "\n");
278  assert(RulesForOpcode[OpcodeIdx].getAlias() == 0 && "Cannot chain aliases");
279  }
280 
281  return OpcodeIdx;
282 }
283 
284 const LegalizeRuleSet &
285 LegalizerInfo::getActionDefinitions(unsigned Opcode) const {
286  unsigned OpcodeIdx = getActionDefinitionsIdx(Opcode);
287  return RulesForOpcode[OpcodeIdx];
288 }
289 
291  unsigned OpcodeIdx = getActionDefinitionsIdx(Opcode);
292  auto &Result = RulesForOpcode[OpcodeIdx];
293  assert(!Result.isAliasedByAnother() && "Modifying this opcode will modify aliases");
294  return Result;
295 }
296 
298  std::initializer_list<unsigned> Opcodes) {
299  unsigned Representative = *Opcodes.begin();
300 
301  assert(Opcodes.begin() != Opcodes.end() &&
302  Opcodes.begin() + 1 != Opcodes.end() &&
303  "Initializer list must have at least two opcodes");
304 
305  for (auto I = Opcodes.begin() + 1, E = Opcodes.end(); I != E; ++I)
306  aliasActionDefinitions(Representative, *I);
307 
308  auto &Return = getActionDefinitionsBuilder(Representative);
309  Return.setIsAliasedByAnother();
310  return Return;
311 }
312 
314  unsigned OpcodeFrom) {
315  assert(OpcodeTo != OpcodeFrom && "Cannot alias to self");
316  assert(OpcodeTo >= FirstOp && OpcodeTo <= LastOp && "Unsupported opcode");
317  const unsigned OpcodeFromIdx = getOpcodeIdxForOpcode(OpcodeFrom);
318  RulesForOpcode[OpcodeFromIdx].aliasTo(OpcodeTo);
319 }
320 
325  return Step;
326  }
327 
328  for (unsigned i = 0; i < Query.Types.size(); ++i) {
329  auto Action = getAspectAction({Query.Opcode, i, Query.Types[i]});
330  if (Action.first != Legal) {
331  LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i
332  << " Action=" << (unsigned)Action.first << ", "
333  << Action.second << "\n");
334  return {Action.first, i, Action.second};
335  } else
336  LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Legal\n");
337  }
338  LLVM_DEBUG(dbgs() << ".. (legacy) Legal\n");
339  return {Legal, 0, LLT{}};
340 }
341 
344  const MachineRegisterInfo &MRI) const {
345  SmallVector<LLT, 2> Types;
346  SmallBitVector SeenTypes(8);
347  const MCOperandInfo *OpInfo = MI.getDesc().OpInfo;
348  // FIXME: probably we'll need to cache the results here somehow?
349  for (unsigned i = 0; i < MI.getDesc().getNumOperands(); ++i) {
350  if (!OpInfo[i].isGenericType())
351  continue;
352 
353  // We must only record actions once for each TypeIdx; otherwise we'd
354  // try to legalize operands multiple times down the line.
355  unsigned TypeIdx = OpInfo[i].getGenericTypeIndex();
356  if (SeenTypes[TypeIdx])
357  continue;
358 
359  SeenTypes.set(TypeIdx);
360 
361  LLT Ty = getTypeFromTypeIdx(MI, MRI, i, TypeIdx);
362  Types.push_back(Ty);
363  }
364 
366  for (const auto &MMO : MI.memoperands())
367  MemDescrs.push_back({MMO->getSize() /* in bytes */ * 8});
368 
369  return getAction({MI.getOpcode(), Types, MemDescrs});
370 }
371 
373  const MachineRegisterInfo &MRI) const {
374  return getAction(MI, MRI).Action == Legal;
375 }
376 
378  MachineIRBuilder &MIRBuilder) const {
379  return false;
380 }
381 
384  const SizeAndActionsVec &v, LegalizeAction IncreaseAction,
385  LegalizeAction DecreaseAction) {
386  SizeAndActionsVec result;
387  unsigned LargestSizeSoFar = 0;
388  if (v.size() >= 1 && v[0].first != 1)
389  result.push_back({1, IncreaseAction});
390  for (size_t i = 0; i < v.size(); ++i) {
391  result.push_back(v[i]);
392  LargestSizeSoFar = v[i].first;
393  if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {
394  result.push_back({LargestSizeSoFar + 1, IncreaseAction});
395  LargestSizeSoFar = v[i].first + 1;
396  }
397  }
398  result.push_back({LargestSizeSoFar + 1, DecreaseAction});
399  return result;
400 }
401 
404  const SizeAndActionsVec &v, LegalizeAction DecreaseAction,
405  LegalizeAction IncreaseAction) {
406  SizeAndActionsVec result;
407  if (v.size() == 0 || v[0].first != 1)
408  result.push_back({1, IncreaseAction});
409  for (size_t i = 0; i < v.size(); ++i) {
410  result.push_back(v[i]);
411  if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {
412  result.push_back({v[i].first + 1, DecreaseAction});
413  }
414  }
415  return result;
416 }
417 
419 LegalizerInfo::findAction(const SizeAndActionsVec &Vec, const uint32_t Size) {
420  assert(Size >= 1);
421  // Find the last element in Vec that has a bitsize equal to or smaller than
422  // the requested bit size.
423  // That is the element just before the first element that is bigger than Size.
424  auto VecIt = std::upper_bound(
425  Vec.begin(), Vec.end(), Size,
426  [](const uint32_t Size, const SizeAndAction lhs) -> bool {
427  return Size < lhs.first;
428  });
429  assert(VecIt != Vec.begin() && "Does Vec not start with size 1?");
430  --VecIt;
431  int VecIdx = VecIt - Vec.begin();
432 
433  LegalizeAction Action = Vec[VecIdx].second;
434  switch (Action) {
435  case Legal:
436  case Lower:
437  case Libcall:
438  case Custom:
439  return {Size, Action};
440  case FewerElements:
441  // FIXME: is this special case still needed and correct?
442  // Special case for scalarization:
443  if (Vec == SizeAndActionsVec({{1, FewerElements}}))
444  return {1, FewerElements};
446  case NarrowScalar: {
447  // The following needs to be a loop, as for now, we do allow needing to
448  // go over "Unsupported" bit sizes before finding a legalizable bit size.
449  // e.g. (s8, WidenScalar), (s9, Unsupported), (s32, Legal). if Size==8,
450  // we need to iterate over s9, and then to s32 to return (s32, Legal).
451  // If we want to get rid of the below loop, we should have stronger asserts
452  // when building the SizeAndActionsVecs, probably not allowing
453  // "Unsupported" unless at the ends of the vector.
454  for (int i = VecIdx - 1; i >= 0; --i)
455  if (!needsLegalizingToDifferentSize(Vec[i].second) &&
456  Vec[i].second != Unsupported)
457  return {Vec[i].first, Action};
458  llvm_unreachable("");
459  }
460  case WidenScalar:
461  case MoreElements: {
462  // See above, the following needs to be a loop, at least for now.
463  for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)
464  if (!needsLegalizingToDifferentSize(Vec[i].second) &&
465  Vec[i].second != Unsupported)
466  return {Vec[i].first, Action};
467  llvm_unreachable("");
468  }
469  case Unsupported:
470  return {Size, Unsupported};
471  case NotFound:
472  case UseLegacyRules:
473  llvm_unreachable("NotFound");
474  }
475  llvm_unreachable("Action has an unknown enum value");
476 }
477 
478 std::pair<LegalizeAction, LLT>
479 LegalizerInfo::findScalarLegalAction(const InstrAspect &Aspect) const {
480  assert(Aspect.Type.isScalar() || Aspect.Type.isPointer());
481  if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
482  return {NotFound, LLT()};
483  const unsigned OpcodeIdx = getOpcodeIdxForOpcode(Aspect.Opcode);
484  if (Aspect.Type.isPointer() &&
485  AddrSpace2PointerActions[OpcodeIdx].find(Aspect.Type.getAddressSpace()) ==
486  AddrSpace2PointerActions[OpcodeIdx].end()) {
487  return {NotFound, LLT()};
488  }
489  const SmallVector<SizeAndActionsVec, 1> &Actions =
490  Aspect.Type.isPointer()
491  ? AddrSpace2PointerActions[OpcodeIdx]
492  .find(Aspect.Type.getAddressSpace())
493  ->second
494  : ScalarActions[OpcodeIdx];
495  if (Aspect.Idx >= Actions.size())
496  return {NotFound, LLT()};
497  const SizeAndActionsVec &Vec = Actions[Aspect.Idx];
498  // FIXME: speed up this search, e.g. by using a results cache for repeated
499  // queries?
500  auto SizeAndAction = findAction(Vec, Aspect.Type.getSizeInBits());
501  return {SizeAndAction.second,
502  Aspect.Type.isScalar() ? LLT::scalar(SizeAndAction.first)
503  : LLT::pointer(Aspect.Type.getAddressSpace(),
504  SizeAndAction.first)};
505 }
506 
507 std::pair<LegalizeAction, LLT>
508 LegalizerInfo::findVectorLegalAction(const InstrAspect &Aspect) const {
509  assert(Aspect.Type.isVector());
510  // First legalize the vector element size, then legalize the number of
511  // lanes in the vector.
512  if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
513  return {NotFound, Aspect.Type};
514  const unsigned OpcodeIdx = getOpcodeIdxForOpcode(Aspect.Opcode);
515  const unsigned TypeIdx = Aspect.Idx;
516  if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].size())
517  return {NotFound, Aspect.Type};
518  const SizeAndActionsVec &ElemSizeVec =
519  ScalarInVectorActions[OpcodeIdx][TypeIdx];
520 
521  LLT IntermediateType;
522  auto ElementSizeAndAction =
523  findAction(ElemSizeVec, Aspect.Type.getScalarSizeInBits());
524  IntermediateType =
525  LLT::vector(Aspect.Type.getNumElements(), ElementSizeAndAction.first);
526  if (ElementSizeAndAction.second != Legal)
527  return {ElementSizeAndAction.second, IntermediateType};
528 
529  auto i = NumElements2Actions[OpcodeIdx].find(
530  IntermediateType.getScalarSizeInBits());
531  if (i == NumElements2Actions[OpcodeIdx].end()) {
532  return {NotFound, IntermediateType};
533  }
534  const SizeAndActionsVec &NumElementsVec = (*i).second[TypeIdx];
535  auto NumElementsAndAction =
536  findAction(NumElementsVec, IntermediateType.getNumElements());
537  return {NumElementsAndAction.second,
538  LLT::vector(NumElementsAndAction.first,
539  IntermediateType.getScalarSizeInBits())};
540 }
541 
542 /// \pre Type indices of every opcode form a dense set starting from 0.
543 void LegalizerInfo::verify(const MCInstrInfo &MII) const {
544 #ifndef NDEBUG
545  std::vector<unsigned> FailedOpcodes;
546  for (unsigned Opcode = FirstOp; Opcode <= LastOp; ++Opcode) {
547  const MCInstrDesc &MCID = MII.get(Opcode);
548  const unsigned NumTypeIdxs = std::accumulate(
549  MCID.opInfo_begin(), MCID.opInfo_end(), 0U,
550  [](unsigned Acc, const MCOperandInfo &OpInfo) {
551  return OpInfo.isGenericType()
552  ? std::max(OpInfo.getGenericTypeIndex() + 1U, Acc)
553  : Acc;
554  });
555  LLVM_DEBUG(dbgs() << MII.getName(Opcode) << " (opcode " << Opcode
556  << "): " << NumTypeIdxs << " type ind"
557  << (NumTypeIdxs == 1 ? "ex" : "ices") << "\n");
558  const LegalizeRuleSet &RuleSet = getActionDefinitions(Opcode);
559  if (!RuleSet.verifyTypeIdxsCoverage(NumTypeIdxs))
560  FailedOpcodes.push_back(Opcode);
561  }
562  if (!FailedOpcodes.empty()) {
563  errs() << "The following opcodes have ill-defined legalization rules:";
564  for (unsigned Opcode : FailedOpcodes)
565  errs() << " " << MII.getName(Opcode);
566  errs() << "\n";
567 
568  report_fatal_error("ill-defined LegalizerInfo"
569  ", try -debug-only=legalizer-info for details");
570  }
571 #endif
572 }
573 
574 #ifndef NDEBUG
575 // FIXME: This should be in the MachineVerifier, but it can't use the
576 // LegalizerInfo as it's currently in the separate GlobalISel library.
577 // Note that RegBankSelected property already checked in the verifier
578 // has the same layering problem, but we only use inline methods so
579 // end up not needing to link against the GlobalISel library.
581  if (const LegalizerInfo *MLI = MF.getSubtarget().getLegalizerInfo()) {
582  const MachineRegisterInfo &MRI = MF.getRegInfo();
583  for (const MachineBasicBlock &MBB : MF)
584  for (const MachineInstr &MI : MBB)
585  if (isPreISelGenericOpcode(MI.getOpcode()) && !MLI->isLegal(MI, MRI))
586  return &MI;
587  }
588  return nullptr;
589 }
590 #endif
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:250
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This is a &#39;bitvector&#39; (really, a variable-sized bit array), optimized for the case when the array is ...
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:115
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
The result of a query.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:137
static SizeAndActionsVec increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec &v, LegalizeAction IncreaseAction, LegalizeAction DecreaseAction)
Helper function to implement many typical SizeChangeStrategy functions.
unsigned getScalarSizeInBits() const
The operation should be implemented in terms of a wider scalar base-type.
Definition: LegalizerInfo.h:57
raw_ostream & print(raw_ostream &OS) const
std::function< SizeAndActionsVec(const SizeAndActionsVec &v)> SizeChangeStrategy
The LegalityQuery object bundles together all the information that&#39;s needed to decide whether a given...
bool isScalar() const
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:161
unsigned getReg() const
getReg - Returns the register number.
static LLT getTypeFromTypeIdx(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned OpIdx, unsigned TypeIdx)
Helper function to get LLT for the given type index.
std::vector< SizeAndAction > SizeAndActionsVec
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
Definition: LegalizerInfo.h:62
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit...
static SizeAndActionsVec narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v)
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
const_opInfo_iterator opInfo_begin() const
Definition: MCInstrDesc.h:212
unsigned second
iterator_range< mmo_iterator > memoperands()
Definition: MachineInstr.h:423
const LegalizeRuleSet & getActionDefinitions(unsigned Opcode) const
Get the action definitions for the given opcode.
static SizeAndActionsVec unsupportedForDifferentSizes(const SizeAndActionsVec &v)
A SizeChangeStrategy for the common case where legalization for a particular operation consists of on...
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type...
Definition: LegalizerInfo.h:52
bool isVector() const
LegalizeActionStep getAction(const LegalityQuery &Query) const
Determine what action should be taken to legalize the described instruction.
static SizeAndActionsVec widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v)
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:208
unsigned getNumOperands() const
Access to explicit operands of the instruction.
Definition: MachineInstr.h:314
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:311
This operation is completely unsupported on the target.
Definition: LegalizerInfo.h:85
LLT getElementType() const
Returns the vector&#39;s element type. Only valid for vector types.
void verify(const MCInstrInfo &MII) const
Perform simple self-diagnostic and assert if there is anything obviously wrong with the actions set u...
PowerPC VSX FMA Mutation
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:308
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
Definition: LegalizerInfo.h:68
void computeTables()
Compute any ancillary tables needed to quickly decide how an operation should be handled.
void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom)
static LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
The operation itself must be expressed in terms of simpler actions on this target.
Definition: LegalizerInfo.h:72
bool isGenericType() const
Definition: MCInstrDesc.h:98
virtual const LegalizerInfo * getLegalizerInfo() const
bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
static SizeAndActionsVec decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec &v, LegalizeAction DecreaseAction, LegalizeAction IncreaseAction)
Helper function to implement many typical SizeChangeStrategy functions.
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
Sentinel value for when no action was found in the specified table.
Definition: LegalizerInfo.h:88
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:24
bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const
Check if there is no type index which is obviously not handled by the LegalizeRuleSet in any way at a...
unsigned getAddressSpace() const
Legalization is decided based on an instruction&#39;s opcode, which type slot we&#39;re considering, and what the existing type is.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
Definition: MCInstrInfo.h:51
cl::opt< bool > DisableGISelLegalityCheck
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:859
SmallBitVector & set()
const MachineInstr * machineFunctionIsIllegal(const MachineFunction &MF)
Checks that MIR is fully legal, returns an illegal instruction if it&#39;s not, nullptr otherwise...
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
Definition: STLExtras.h:1032
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
The target wants to do something special with this combination of operand and type.
Definition: LegalizerInfo.h:81
unsigned getOpcodeIdxForOpcode(unsigned Opcode) const
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
bool isPointer() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
virtual bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder) const
Representation of each machine instruction.
Definition: MachineInstr.h:60
LegalizeAction Action
The action to take or the final answer.
static bool needsLegalizingToDifferentSize(const LegalizeAction Action)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Fall back onto the old rules.
Definition: LegalizerInfo.h:92
static SizeAndActionsVec widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v)
A SizeChangeStrategy for the common case where legalization for a particular operation consists of wi...
static SizeAndActionsVec moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v)
A SizeChangeStrategy for the common case where legalization for a particular vector operation consist...
LegalizeActionStep apply(const LegalityQuery &Query) const
Apply the ruleset to the given LegalityQuery.
ArrayRef< LLT > Types
const_opInfo_iterator opInfo_end() const
Definition: MCInstrDesc.h:213
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
void aliasTo(unsigned Opcode)
#define I(x, y, z)
Definition: MD5.cpp:58
void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode, const unsigned TypeIdx, SizeChangeStrategy S)
The setAction calls record the non-size-changing legalization actions to take on specificly-sized typ...
static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read, bool &Write, bool &Effects, bool &StackPointer)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
Definition: TargetOpcodes.h:31
static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space (defaulting to 0).
uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr char Size[]
Key for Kernel::Arg::Metadata::mSize.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:235
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:172
unsigned getActionDefinitionsIdx(unsigned Opcode) const
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
unsigned getGenericTypeIndex() const
Definition: MCInstrDesc.h:103
IRTranslator LLVM IR MI
static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:67
#define LLVM_DEBUG(X)
Definition: Debug.h:119
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:316
The operation is expected to be selectable directly by the target, and no transformation is necessary...
Definition: LegalizerInfo.h:47
std::pair< uint16_t, LegalizeAction > SizeAndAction