MLIR  22.0.0git
PtrTypes.cpp
Go to the documentation of this file.
1 //===- PtrTypes.cpp - Pointer dialect types ---------------------*- C++ -*-===//
2 //
3 // This file is licensed 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 //
9 // This file defines the Ptr dialect types.
10 //
11 //===----------------------------------------------------------------------===//
12 
15 
16 using namespace mlir;
17 using namespace mlir::ptr;
18 
19 //===----------------------------------------------------------------------===//
20 // Pointer type
21 //===----------------------------------------------------------------------===//
22 
23 constexpr const static unsigned kDefaultPointerSizeBits = 64;
24 constexpr const static unsigned kBitsInByte = 8;
25 constexpr const static unsigned kDefaultPointerAlignmentBits = 8;
26 
27 /// Searches the data layout for the pointer spec, returns nullptr if it is not
28 /// found.
29 static SpecAttr getPointerSpec(DataLayoutEntryListRef params, PtrType type,
30  MemorySpaceAttrInterface defaultMemorySpace) {
31  for (DataLayoutEntryInterface entry : params) {
32  if (!entry.isTypeEntry())
33  continue;
34  if (cast<PtrType>(cast<Type>(entry.getKey())).getMemorySpace() ==
35  type.getMemorySpace()) {
36  if (auto spec = dyn_cast<SpecAttr>(entry.getValue()))
37  return spec;
38  }
39  }
40  // If not found, and this is the pointer to the default memory space or if
41  // `defaultMemorySpace` is null, assume 64-bit pointers. `defaultMemorySpace`
42  // might be null if the data layout doesn't define the default memory space.
43  if (type.getMemorySpace() == defaultMemorySpace ||
44  defaultMemorySpace == nullptr)
45  return SpecAttr::get(type.getContext(), kDefaultPointerSizeBits,
48  return nullptr;
49 }
50 
51 bool PtrType::areCompatible(DataLayoutEntryListRef oldLayout,
52  DataLayoutEntryListRef newLayout,
53  DataLayoutSpecInterface newSpec,
54  const DataLayoutIdentifiedEntryMap &map) const {
55  for (DataLayoutEntryInterface newEntry : newLayout) {
56  if (!newEntry.isTypeEntry())
57  continue;
58  uint32_t size = kDefaultPointerSizeBits;
59  uint32_t abi = kDefaultPointerAlignmentBits;
60  auto newType = llvm::cast<PtrType>(llvm::cast<Type>(newEntry.getKey()));
61  const auto *it =
62  llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
63  if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
64  return llvm::cast<PtrType>(type).getMemorySpace() ==
65  newType.getMemorySpace();
66  }
67  return false;
68  });
69  if (it == oldLayout.end()) {
71  map.lookup(newSpec.getDefaultMemorySpaceIdentifier(getContext())));
72  it = llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
73  if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
74  auto ptrTy = llvm::cast<PtrType>(type);
75  return ptrTy.getMemorySpace() == defaultMemorySpace;
76  }
77  return false;
78  });
79  }
80  if (it != oldLayout.end()) {
81  auto spec = llvm::cast<SpecAttr>(*it);
82  size = spec.getSize();
83  abi = spec.getAbi();
84  }
85 
86  auto newSpec = llvm::cast<SpecAttr>(newEntry.getValue());
87  uint32_t newSize = newSpec.getSize();
88  uint32_t newAbi = newSpec.getAbi();
89  if (size != newSize || abi < newAbi || abi % newAbi != 0)
90  return false;
91  }
92  return true;
93 }
94 
95 uint64_t PtrType::getABIAlignment(const DataLayout &dataLayout,
96  DataLayoutEntryListRef params) const {
97  auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
98  dataLayout.getDefaultMemorySpace());
99  if (SpecAttr spec = getPointerSpec(params, *this, defaultMemorySpace))
100  return spec.getAbi() / kBitsInByte;
101 
102  return dataLayout.getTypeABIAlignment(get(defaultMemorySpace));
103 }
104 
105 std::optional<uint64_t>
106 PtrType::getIndexBitwidth(const DataLayout &dataLayout,
107  DataLayoutEntryListRef params) const {
108  auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
109  dataLayout.getDefaultMemorySpace());
110  if (SpecAttr spec = getPointerSpec(params, *this, defaultMemorySpace)) {
111  return spec.getIndex() == SpecAttr::kOptionalSpecValue ? spec.getSize()
112  : spec.getIndex();
113  }
114 
115  return dataLayout.getTypeIndexBitwidth(get(defaultMemorySpace));
116 }
117 
118 llvm::TypeSize PtrType::getTypeSizeInBits(const DataLayout &dataLayout,
119  DataLayoutEntryListRef params) const {
120  auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
121  dataLayout.getDefaultMemorySpace());
122  if (SpecAttr spec = getPointerSpec(params, *this, defaultMemorySpace))
123  return llvm::TypeSize::getFixed(spec.getSize());
124 
125  // For other memory spaces, use the size of the pointer to the default memory
126  // space.
127  return dataLayout.getTypeSizeInBits(get(defaultMemorySpace));
128 }
129 
130 uint64_t PtrType::getPreferredAlignment(const DataLayout &dataLayout,
131  DataLayoutEntryListRef params) const {
132  auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
133  dataLayout.getDefaultMemorySpace());
134  if (SpecAttr spec = getPointerSpec(params, *this, defaultMemorySpace))
135  return spec.getPreferred() / kBitsInByte;
136 
137  return dataLayout.getTypePreferredAlignment(get(defaultMemorySpace));
138 }
139 
140 LogicalResult PtrType::verifyEntries(DataLayoutEntryListRef entries,
141  Location loc) const {
142  for (DataLayoutEntryInterface entry : entries) {
143  if (!entry.isTypeEntry())
144  continue;
145  auto key = llvm::cast<Type>(entry.getKey());
146  if (!llvm::isa<SpecAttr>(entry.getValue())) {
147  return emitError(loc) << "expected layout attribute for " << key
148  << " to be a #ptr.spec attribute";
149  }
150  }
151  return success();
152 }
153 
154 //===----------------------------------------------------------------------===//
155 // Pointer metadata
156 //===----------------------------------------------------------------------===//
157 
158 LogicalResult
160  PtrLikeTypeInterface type) {
161  if (!type.hasPtrMetadata())
162  return emitError() << "the ptr-like type has no metadata";
163  return success();
164 }
static LogicalResult verifyEntries(function_ref< InFlightDiagnostic()> emitError, ArrayRef< DataLayoutEntryInterface > entries, bool allowTypes=true)
Verify entries, with the option to disallow types as keys.
Definition: DLTI.cpp:134
static uint64_t getIndexBitwidth(DataLayoutEntryListRef params)
Returns the bitwidth of the index type if specified in the param list.
static MLIRContext * getContext(OpFoldResult val)
constexpr static const unsigned kDefaultPointerAlignmentBits
Definition: PtrTypes.cpp:25
constexpr static const unsigned kDefaultPointerSizeBits
Definition: PtrTypes.cpp:23
constexpr static const unsigned kBitsInByte
Definition: PtrTypes.cpp:24
static SpecAttr getPointerSpec(DataLayoutEntryListRef params, PtrType type, MemorySpaceAttrInterface defaultMemorySpace)
Searches the data layout for the pointer spec, returns nullptr if it is not found.
Definition: PtrTypes.cpp:29
Attributes are known-constant values of operations.
Definition: Attributes.h:25
The main mechanism for performing data layout queries.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
uint64_t getTypePreferredAlignment(Type t) const
Returns the preferred of the given type in the current scope.
uint64_t getTypeABIAlignment(Type t) const
Returns the required alignment of the given type in the current scope.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
Attribute getDefaultMemorySpace() const
Returns the default memory space used for memory operations.
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:314
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:76
Attribute getDefaultMemorySpace(DataLayoutEntryInterface entry)
Default handler for the default memory space request.
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
::llvm::MapVector<::mlir::StringAttr, ::mlir::DataLayoutEntryInterface > DataLayoutIdentifiedEntryMap
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:423