Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.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
/// This implementation has been deprecated for a long time but it still in use
12
/// in a few places.
13
//===----------------------------------------------------------------------===//
14
 
15
#ifndef LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H
16
#define LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H
17
 
18
#include "llvm/ADT/DenseMap.h"
19
#include "llvm/CodeGen/TargetOpcodes.h"
20
#include "llvm/Support/LowLevelTypeImpl.h"
21
#include <unordered_map>
22
 
23
namespace llvm {
24
struct LegalityQuery;
25
 
26
namespace LegacyLegalizeActions {
27
enum LegacyLegalizeAction : std::uint8_t {
28
  /// The operation is expected to be selectable directly by the target, and
29
  /// no transformation is necessary.
30
  Legal,
31
 
32
  /// The operation should be synthesized from multiple instructions acting on
33
  /// a narrower scalar base-type. For example a 64-bit add might be
34
  /// implemented in terms of 32-bit add-with-carry.
35
  NarrowScalar,
36
 
37
  /// The operation should be implemented in terms of a wider scalar
38
  /// base-type. For example a <2 x s8> add could be implemented as a <2
39
  /// x s32> add (ignoring the high bits).
40
  WidenScalar,
41
 
42
  /// The (vector) operation should be implemented by splitting it into
43
  /// sub-vectors where the operation is legal. For example a <8 x s64> add
44
  /// might be implemented as 4 separate <2 x s64> adds.
45
  FewerElements,
46
 
47
  /// The (vector) operation should be implemented by widening the input
48
  /// vector and ignoring the lanes added by doing so. For example <2 x i8> is
49
  /// rarely legal, but you might perform an <8 x i8> and then only look at
50
  /// the first two results.
51
  MoreElements,
52
 
53
  /// Perform the operation on a different, but equivalently sized type.
54
  Bitcast,
55
 
56
  /// The operation itself must be expressed in terms of simpler actions on
57
  /// this target. E.g. a SREM replaced by an SDIV and subtraction.
58
  Lower,
59
 
60
  /// The operation should be implemented as a call to some kind of runtime
61
  /// support library. For example this usually happens on machines that don't
62
  /// support floating-point operations natively.
63
  Libcall,
64
 
65
  /// The target wants to do something special with this combination of
66
  /// operand and type. A callback will be issued when it is needed.
67
  Custom,
68
 
69
  /// This operation is completely unsupported on the target. A programming
70
  /// error has occurred.
71
  Unsupported,
72
 
73
  /// Sentinel value for when no action was found in the specified table.
74
  NotFound,
75
};
76
} // end namespace LegacyLegalizeActions
77
raw_ostream &operator<<(raw_ostream &OS,
78
                        LegacyLegalizeActions::LegacyLegalizeAction Action);
79
 
80
/// Legalization is decided based on an instruction's opcode, which type slot
81
/// we're considering, and what the existing type is. These aspects are gathered
82
/// together for convenience in the InstrAspect class.
83
struct InstrAspect {
84
  unsigned Opcode;
85
  unsigned Idx = 0;
86
  LLT Type;
87
 
88
  InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {}
89
  InstrAspect(unsigned Opcode, unsigned Idx, LLT Type)
90
      : Opcode(Opcode), Idx(Idx), Type(Type) {}
91
 
92
  bool operator==(const InstrAspect &RHS) const {
93
    return Opcode == RHS.Opcode && Idx == RHS.Idx && Type == RHS.Type;
94
  }
95
};
96
 
97
/// The result of a query. It either indicates a final answer of Legal or
98
/// Unsupported or describes an action that must be taken to make an operation
99
/// more legal.
100
struct LegacyLegalizeActionStep {
101
  /// The action to take or the final answer.
102
  LegacyLegalizeActions::LegacyLegalizeAction Action;
103
  /// If describing an action, the type index to change. Otherwise zero.
104
  unsigned TypeIdx;
105
  /// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
106
  LLT NewType;
107
 
108
  LegacyLegalizeActionStep(LegacyLegalizeActions::LegacyLegalizeAction Action,
109
                           unsigned TypeIdx, const LLT NewType)
110
      : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
111
 
112
  bool operator==(const LegacyLegalizeActionStep &RHS) const {
113
    return std::tie(Action, TypeIdx, NewType) ==
114
        std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
115
  }
116
};
117
 
118
 
119
class LegacyLegalizerInfo {
120
public:
121
  using SizeAndAction =
122
      std::pair<uint16_t, LegacyLegalizeActions::LegacyLegalizeAction>;
123
  using SizeAndActionsVec = std::vector<SizeAndAction>;
124
  using SizeChangeStrategy =
125
      std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>;
126
 
127
  LegacyLegalizerInfo();
128
 
129
  static bool needsLegalizingToDifferentSize(
130
      const LegacyLegalizeActions::LegacyLegalizeAction Action) {
131
    using namespace LegacyLegalizeActions;
132
    switch (Action) {
133
    case NarrowScalar:
134
    case WidenScalar:
135
    case FewerElements:
136
    case MoreElements:
137
    case Unsupported:
138
      return true;
139
    default:
140
      return false;
141
    }
142
  }
143
 
144
  /// Compute any ancillary tables needed to quickly decide how an operation
145
  /// should be handled. This must be called after all "set*Action"methods but
146
  /// before any query is made or incorrect results may be returned.
147
  void computeTables();
148
 
149
  /// More friendly way to set an action for common types that have an LLT
150
  /// representation.
151
  /// The LegacyLegalizeAction must be one for which
152
  /// NeedsLegalizingToDifferentSize returns false.
153
  void setAction(const InstrAspect &Aspect,
154
                 LegacyLegalizeActions::LegacyLegalizeAction Action) {
155
    assert(!needsLegalizingToDifferentSize(Action));
156
    TablesInitialized = false;
157
    const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
158
    if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx)
159
      SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1);
160
    SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action;
161
  }
162
 
163
  /// The setAction calls record the non-size-changing legalization actions
164
  /// to take on specificly-sized types. The SizeChangeStrategy defines what
165
  /// to do when the size of the type needs to be changed to reach a legally
166
  /// sized type (i.e., one that was defined through a setAction call).
167
  /// e.g.
168
  /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);
169
  /// setLegalizeScalarToDifferentSizeStrategy(
170
  ///   G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
171
  /// will end up defining getAction({G_ADD, 0, T}) to return the following
172
  /// actions for different scalar types T:
173
  ///  LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)}
174
  ///  LLT::scalar(32):                 {Legal, 0, LLT::scalar(32)}
175
  ///  LLT::scalar(33)..:               {NarrowScalar, 0, LLT::scalar(32)}
176
  ///
177
  /// If no SizeChangeAction gets defined, through this function,
178
  /// the default is unsupportedForDifferentSizes.
179
  void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode,
180
                                                const unsigned TypeIdx,
181
                                                SizeChangeStrategy S) {
182
    const unsigned OpcodeIdx = Opcode - FirstOp;
183
    if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
184
      ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
185
    ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
186
  }
187
 
188
  /// See also setLegalizeScalarToDifferentSizeStrategy.
189
  /// This function allows to set the SizeChangeStrategy for vector elements.
190
  void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode,
191
                                                       const unsigned TypeIdx,
192
                                                       SizeChangeStrategy S) {
193
    const unsigned OpcodeIdx = Opcode - FirstOp;
194
    if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
195
      VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
196
    VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
197
  }
198
 
199
  /// A SizeChangeStrategy for the common case where legalization for a
200
  /// particular operation consists of only supporting a specific set of type
201
  /// sizes. E.g.
202
  ///   setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);
203
  ///   setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);
204
  ///   setLegalizeScalarToDifferentSizeStrategy(
205
  ///     G_DIV, 0, unsupportedForDifferentSizes);
206
  /// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64,
207
  /// and Unsupported for all other scalar types T.
208
  static SizeAndActionsVec
209
  unsupportedForDifferentSizes(const SizeAndActionsVec &v) {
210
    using namespace LegacyLegalizeActions;
211
    return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported,
212
                                                     Unsupported);
213
  }
214
 
215
  /// A SizeChangeStrategy for the common case where legalization for a
216
  /// particular operation consists of widening the type to a large legal type,
217
  /// unless there is no such type and then instead it should be narrowed to the
218
  /// largest legal type.
219
  static SizeAndActionsVec
220
  widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) {
221
    using namespace LegacyLegalizeActions;
222
    assert(v.size() > 0 &&
223
           "At least one size that can be legalized towards is needed"
224
           " for this SizeChangeStrategy");
225
    return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
226
                                                     NarrowScalar);
227
  }
228
 
229
  static SizeAndActionsVec
230
  widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) {
231
    using namespace LegacyLegalizeActions;
232
    return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
233
                                                     Unsupported);
234
  }
235
 
236
  static SizeAndActionsVec
237
  narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) {
238
    using namespace LegacyLegalizeActions;
239
    return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
240
                                                       Unsupported);
241
  }
242
 
243
  static SizeAndActionsVec
244
  narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) {
245
    using namespace LegacyLegalizeActions;
246
    assert(v.size() > 0 &&
247
           "At least one size that can be legalized towards is needed"
248
           " for this SizeChangeStrategy");
249
    return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
250
                                                       WidenScalar);
251
  }
252
 
253
  /// A SizeChangeStrategy for the common case where legalization for a
254
  /// particular vector operation consists of having more elements in the
255
  /// vector, to a type that is legal. Unless there is no such type and then
256
  /// instead it should be legalized towards the widest vector that's still
257
  /// legal. E.g.
258
  ///   setAction({G_ADD, LLT::vector(8, 8)}, Legal);
259
  ///   setAction({G_ADD, LLT::vector(16, 8)}, Legal);
260
  ///   setAction({G_ADD, LLT::vector(2, 32)}, Legal);
261
  ///   setAction({G_ADD, LLT::vector(4, 32)}, Legal);
262
  ///   setLegalizeVectorElementToDifferentSizeStrategy(
263
  ///     G_ADD, 0, moreToWiderTypesAndLessToWidest);
264
  /// will result in the following getAction results:
265
  ///   * getAction({G_ADD, LLT::vector(8,8)}) returns
266
  ///       (Legal, vector(8,8)).
267
  ///   * getAction({G_ADD, LLT::vector(9,8)}) returns
268
  ///       (MoreElements, vector(16,8)).
269
  ///   * getAction({G_ADD, LLT::vector(8,32)}) returns
270
  ///       (FewerElements, vector(4,32)).
271
  static SizeAndActionsVec
272
  moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) {
273
    using namespace LegacyLegalizeActions;
274
    return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements,
275
                                                     FewerElements);
276
  }
277
 
278
  /// Helper function to implement many typical SizeChangeStrategy functions.
279
  static SizeAndActionsVec increaseToLargerTypesAndDecreaseToLargest(
280
      const SizeAndActionsVec &v,
281
      LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction,
282
      LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction);
283
  /// Helper function to implement many typical SizeChangeStrategy functions.
284
  static SizeAndActionsVec decreaseToSmallerTypesAndIncreaseToSmallest(
285
      const SizeAndActionsVec &v,
286
      LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction,
287
      LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction);
288
 
289
  LegacyLegalizeActionStep getAction(const LegalityQuery &Query) const;
290
 
291
  unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
292
 
293
private:
294
  /// Determine what action should be taken to legalize the given generic
295
  /// instruction opcode, type-index and type. Requires computeTables to have
296
  /// been called.
297
  ///
298
  /// \returns a pair consisting of the kind of legalization that should be
299
  /// performed and the destination type.
300
  std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
301
  getAspectAction(const InstrAspect &Aspect) const;
302
 
303
  /// The SizeAndActionsVec is a representation mapping between all natural
304
  /// numbers and an Action. The natural number represents the bit size of
305
  /// the InstrAspect. For example, for a target with native support for 32-bit
306
  /// and 64-bit additions, you'd express that as:
307
  /// setScalarAction(G_ADD, 0,
308
  ///           {{1, WidenScalar},  // bit sizes [ 1, 31[
309
  ///            {32, Legal},       // bit sizes [32, 33[
310
  ///            {33, WidenScalar}, // bit sizes [33, 64[
311
  ///            {64, Legal},       // bit sizes [64, 65[
312
  ///            {65, NarrowScalar} // bit sizes [65, +inf[
313
  ///           });
314
  /// It may be that only 64-bit pointers are supported on your target:
315
  /// setPointerAction(G_PTR_ADD, 0, LLT:pointer(1),
316
  ///           {{1, Unsupported},  // bit sizes [ 1, 63[
317
  ///            {64, Legal},       // bit sizes [64, 65[
318
  ///            {65, Unsupported}, // bit sizes [65, +inf[
319
  ///           });
320
  void setScalarAction(const unsigned Opcode, const unsigned TypeIndex,
321
                       const SizeAndActionsVec &SizeAndActions) {
322
    const unsigned OpcodeIdx = Opcode - FirstOp;
323
    SmallVector<SizeAndActionsVec, 1> &Actions = ScalarActions[OpcodeIdx];
324
    setActions(TypeIndex, Actions, SizeAndActions);
325
  }
326
  void setPointerAction(const unsigned Opcode, const unsigned TypeIndex,
327
                        const unsigned AddressSpace,
328
                        const SizeAndActionsVec &SizeAndActions) {
329
    const unsigned OpcodeIdx = Opcode - FirstOp;
330
    if (AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace) ==
331
        AddrSpace2PointerActions[OpcodeIdx].end())
332
      AddrSpace2PointerActions[OpcodeIdx][AddressSpace] = {{}};
333
    SmallVector<SizeAndActionsVec, 1> &Actions =
334
        AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace)->second;
335
    setActions(TypeIndex, Actions, SizeAndActions);
336
  }
337
 
338
  /// If an operation on a given vector type (say <M x iN>) isn't explicitly
339
  /// specified, we proceed in 2 stages. First we legalize the underlying scalar
340
  /// (so that there's at least one legal vector with that scalar), then we
341
  /// adjust the number of elements in the vector so that it is legal. The
342
  /// desired action in the first step is controlled by this function.
343
  void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex,
344
                               const SizeAndActionsVec &SizeAndActions) {
345
    unsigned OpcodeIdx = Opcode - FirstOp;
346
    SmallVector<SizeAndActionsVec, 1> &Actions =
347
        ScalarInVectorActions[OpcodeIdx];
348
    setActions(TypeIndex, Actions, SizeAndActions);
349
  }
350
 
351
  /// See also setScalarInVectorAction.
352
  /// This function let's you specify the number of elements in a vector that
353
  /// are legal for a legal element size.
354
  void setVectorNumElementAction(const unsigned Opcode,
355
                                 const unsigned TypeIndex,
356
                                 const unsigned ElementSize,
357
                                 const SizeAndActionsVec &SizeAndActions) {
358
    const unsigned OpcodeIdx = Opcode - FirstOp;
359
    if (NumElements2Actions[OpcodeIdx].find(ElementSize) ==
360
        NumElements2Actions[OpcodeIdx].end())
361
      NumElements2Actions[OpcodeIdx][ElementSize] = {{}};
362
    SmallVector<SizeAndActionsVec, 1> &Actions =
363
        NumElements2Actions[OpcodeIdx].find(ElementSize)->second;
364
    setActions(TypeIndex, Actions, SizeAndActions);
365
  }
366
 
367
  /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,
368
  /// i.e. it's OK if it doesn't start from size 1.
369
  static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) {
370
    using namespace LegacyLegalizeActions;
371
#ifndef NDEBUG
372
    // The sizes should be in increasing order
373
    int prev_size = -1;
374
    for(auto SizeAndAction: v) {
375
      assert(SizeAndAction.first > prev_size);
376
      prev_size = SizeAndAction.first;
377
    }
378
    // - for every Widen action, there should be a larger bitsize that
379
    //   can be legalized towards (e.g. Legal, Lower, Libcall or Custom
380
    //   action).
381
    // - for every Narrow action, there should be a smaller bitsize that
382
    //   can be legalized towards.
383
    int SmallestNarrowIdx = -1;
384
    int LargestWidenIdx = -1;
385
    int SmallestLegalizableToSameSizeIdx = -1;
386
    int LargestLegalizableToSameSizeIdx = -1;
387
    for(size_t i=0; i<v.size(); ++i) {
388
      switch (v[i].second) {
389
        case FewerElements:
390
        case NarrowScalar:
391
          if (SmallestNarrowIdx == -1)
392
            SmallestNarrowIdx = i;
393
          break;
394
        case WidenScalar:
395
        case MoreElements:
396
          LargestWidenIdx = i;
397
          break;
398
        case Unsupported:
399
          break;
400
        default:
401
          if (SmallestLegalizableToSameSizeIdx == -1)
402
            SmallestLegalizableToSameSizeIdx = i;
403
          LargestLegalizableToSameSizeIdx = i;
404
      }
405
    }
406
    if (SmallestNarrowIdx != -1) {
407
      assert(SmallestLegalizableToSameSizeIdx != -1);
408
      assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeIdx);
409
    }
410
    if (LargestWidenIdx != -1)
411
      assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx);
412
#endif
413
  }
414
 
415
  /// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with
416
  /// from size 1.
417
  static void checkFullSizeAndActionsVector(const SizeAndActionsVec& v) {
418
#ifndef NDEBUG
419
    // Data structure invariant: The first bit size must be size 1.
420
    assert(v.size() >= 1);
421
    assert(v[0].first == 1);
422
    checkPartialSizeAndActionsVector(v);
423
#endif
424
  }
425
 
426
  /// Sets actions for all bit sizes on a particular generic opcode, type
427
  /// index and scalar or pointer type.
428
  void setActions(unsigned TypeIndex,
429
                  SmallVector<SizeAndActionsVec, 1> &Actions,
430
                  const SizeAndActionsVec &SizeAndActions) {
431
    checkFullSizeAndActionsVector(SizeAndActions);
432
    if (Actions.size() <= TypeIndex)
433
      Actions.resize(TypeIndex + 1);
434
    Actions[TypeIndex] = SizeAndActions;
435
  }
436
 
437
  static SizeAndAction findAction(const SizeAndActionsVec &Vec,
438
                                  const uint32_t Size);
439
 
440
  /// Returns the next action needed to get the scalar or pointer type closer
441
  /// to being legal
442
  /// E.g. findLegalAction({G_REM, 13}) should return
443
  /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will
444
  /// probably be called, which should return (Lower, 32).
445
  /// This is assuming the setScalarAction on G_REM was something like:
446
  /// setScalarAction(G_REM, 0,
447
  ///           {{1, WidenScalar},  // bit sizes [ 1, 31[
448
  ///            {32, Lower},       // bit sizes [32, 33[
449
  ///            {33, NarrowScalar} // bit sizes [65, +inf[
450
  ///           });
451
  std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
452
  findScalarLegalAction(const InstrAspect &Aspect) const;
453
 
454
  /// Returns the next action needed towards legalizing the vector type.
455
  std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
456
  findVectorLegalAction(const InstrAspect &Aspect) const;
457
 
458
  static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
459
  static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
460
 
461
  // Data structures used temporarily during construction of legality data:
462
  using TypeMap = DenseMap<LLT, LegacyLegalizeActions::LegacyLegalizeAction>;
463
  SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];
464
  SmallVector<SizeChangeStrategy, 1>
465
      ScalarSizeChangeStrategies[LastOp - FirstOp + 1];
466
  SmallVector<SizeChangeStrategy, 1>
467
      VectorElementSizeChangeStrategies[LastOp - FirstOp + 1];
468
  bool TablesInitialized = false;
469
 
470
  // Data structures used by getAction:
471
  SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1];
472
  SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1];
473
  std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
474
      AddrSpace2PointerActions[LastOp - FirstOp + 1];
475
  std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
476
      NumElements2Actions[LastOp - FirstOp + 1];
477
};
478
 
479
} // end namespace llvm
480
 
481
#endif // LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H