File: LowLevelType.h

package info (click to toggle)
llvm-toolchain-4.0 1%3A4.0.1-10~deb9u2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 493,332 kB
  • sloc: cpp: 2,698,100; ansic: 552,773; asm: 128,821; python: 121,589; objc: 105,054; sh: 21,174; lisp: 6,758; ml: 5,532; perl: 5,311; pascal: 5,245; makefile: 2,083; cs: 1,868; xml: 686; php: 212; csh: 117
file content (206 lines) | stat: -rw-r--r-- 6,973 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
//== llvm/CodeGen/GlobalISel/LowLevelType.h -------------------- -*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// Implement a low-level type suitable for MachineInstr level instruction
/// selection.
///
/// For a type attached to a MachineInstr, we only care about 2 details: total
/// size and the number of vector lanes (if any). Accordingly, there are 4
/// possible valid type-kinds:
///
///    * `sN` for scalars and aggregates
///    * `<N x sM>` for vectors, which must have at least 2 elements.
///    * `pN` for pointers
///
/// Other information required for correct selection is expected to be carried
/// by the opcode, or non-type flags. For example the distinction between G_ADD
/// and G_FADD for int/float or fast-math flags.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
#define LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H

#include <cassert>
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/CodeGen/ValueTypes.h"

namespace llvm {

class DataLayout;
class LLVMContext;
class Type;
class raw_ostream;

class LLT {
public:
  enum TypeKind : uint16_t {
    Invalid,
    Scalar,
    Pointer,
    Vector,
  };

  /// Get a low-level scalar or aggregate "bag of bits".
  static LLT scalar(unsigned SizeInBits) {
    assert(SizeInBits > 0 && "invalid scalar size");
    return LLT{Scalar, 1, SizeInBits};
  }

  /// Get a low-level pointer in the given address space (defaulting to 0).
  static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) {
    return LLT{Pointer, AddressSpace, SizeInBits};
  }

  /// Get a low-level vector of some number of elements and element width.
  /// \p NumElements must be at least 2.
  static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) {
    assert(NumElements > 1 && "invalid number of vector elements");
    return LLT{Vector, NumElements, ScalarSizeInBits};
  }

  /// Get a low-level vector of some number of elements and element type.
  static LLT vector(uint16_t NumElements, LLT ScalarTy) {
    assert(NumElements > 1 && "invalid number of vector elements");
    assert(ScalarTy.isScalar() && "invalid vector element type");
    return LLT{Vector, NumElements, ScalarTy.getSizeInBits()};
  }

  explicit LLT(TypeKind Kind, uint16_t NumElements, unsigned SizeInBits)
    : SizeInBits(SizeInBits), ElementsOrAddrSpace(NumElements), Kind(Kind) {
    assert((Kind != Vector || ElementsOrAddrSpace > 1) &&
           "invalid number of vector elements");
  }

  explicit LLT() : SizeInBits(0), ElementsOrAddrSpace(0), Kind(Invalid) {}

  /// Construct a low-level type based on an LLVM type.
  explicit LLT(Type &Ty, const DataLayout &DL);

  explicit LLT(MVT VT);

  bool isValid() const { return Kind != Invalid; }

  bool isScalar() const { return Kind == Scalar; }

  bool isPointer() const { return Kind == Pointer; }

  bool isVector() const { return Kind == Vector; }

  /// Returns the number of elements in a vector LLT. Must only be called on
  /// vector types.
  uint16_t getNumElements() const {
    assert(isVector() && "cannot get number of elements on scalar/aggregate");
    return ElementsOrAddrSpace;
  }

  /// Returns the total size of the type. Must only be called on sized types.
  unsigned getSizeInBits() const {
    if (isPointer() || isScalar())
      return SizeInBits;
    return SizeInBits * ElementsOrAddrSpace;
  }

  unsigned getScalarSizeInBits() const {
    return SizeInBits;
  }

  unsigned getAddressSpace() const {
    assert(isPointer() && "cannot get address space of non-pointer type");
    return ElementsOrAddrSpace;
  }

  /// Returns the vector's element type. Only valid for vector types.
  LLT getElementType() const {
    assert(isVector() && "cannot get element type of scalar/aggregate");
    return scalar(SizeInBits);
  }

  /// Get a low-level type with half the size of the original, by halving the
  /// size of the scalar type involved. For example `s32` will become `s16`,
  /// `<2 x s32>` will become `<2 x s16>`.
  LLT halfScalarSize() const {
    assert(!isPointer() && getScalarSizeInBits() > 1 &&
           getScalarSizeInBits() % 2 == 0 && "cannot half size of this type");
    return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2};
  }

  /// Get a low-level type with twice the size of the original, by doubling the
  /// size of the scalar type involved. For example `s32` will become `s64`,
  /// `<2 x s32>` will become `<2 x s64>`.
  LLT doubleScalarSize() const {
    assert(!isPointer() && "cannot change size of this type");
    return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2};
  }

  /// Get a low-level type with half the size of the original, by halving the
  /// number of vector elements of the scalar type involved. The source must be
  /// a vector type with an even number of elements. For example `<4 x s32>`
  /// will become `<2 x s32>`, `<2 x s32>` will become `s32`.
  LLT halfElements() const {
    assert(isVector() && ElementsOrAddrSpace % 2 == 0 &&
           "cannot half odd vector");
    if (ElementsOrAddrSpace == 2)
      return scalar(SizeInBits);

    return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2),
               SizeInBits};
  }

  /// Get a low-level type with twice the size of the original, by doubling the
  /// number of vector elements of the scalar type involved. The source must be
  /// a vector type. For example `<2 x s32>` will become `<4 x s32>`. Doubling
  /// the number of elements in sN produces <2 x sN>.
  LLT doubleElements() const {
    assert(!isPointer() && "cannot double elements in pointer");
    return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2),
               SizeInBits};
  }

  void print(raw_ostream &OS) const;

  bool operator==(const LLT &RHS) const {
    return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits &&
           ElementsOrAddrSpace == RHS.ElementsOrAddrSpace;
  }

  bool operator!=(const LLT &RHS) const { return !(*this == RHS); }

  friend struct DenseMapInfo<LLT>;
private:
  unsigned SizeInBits;
  uint16_t ElementsOrAddrSpace;
  TypeKind Kind;
};

inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
  Ty.print(OS);
  return OS;
}

template<> struct DenseMapInfo<LLT> {
  static inline LLT getEmptyKey() {
    return LLT{LLT::Invalid, 0, -1u};
  }
  static inline LLT getTombstoneKey() {
    return LLT{LLT::Invalid, 0, -2u};
  }
  static inline unsigned getHashValue(const LLT &Ty) {
    uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) |
                   ((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind;
    return DenseMapInfo<uint64_t>::getHashValue(Val);
  }
  static bool isEqual(const LLT &LHS, const LLT &RHS) {
    return LHS == RHS;
  }
};

}

#endif