MLIR  21.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 #include "llvm/ADT/TypeSwitch.h"
16 
17 using namespace mlir;
18 using namespace mlir::ptr;
19 
20 //===----------------------------------------------------------------------===//
21 // Pointer type
22 //===----------------------------------------------------------------------===//
23 
24 constexpr const static unsigned kDefaultPointerSizeBits = 64;
25 constexpr const static unsigned kBitsInByte = 8;
26 constexpr const static unsigned kDefaultPointerAlignmentBits = 8;
27 
28 /// Searches the data layout for the pointer spec, returns nullptr if it is not
29 /// found.
30 static SpecAttr getPointerSpec(DataLayoutEntryListRef params, PtrType type,
31  MemorySpaceAttrInterface defaultMemorySpace) {
32  for (DataLayoutEntryInterface entry : params) {
33  if (!entry.isTypeEntry())
34  continue;
35  if (cast<PtrType>(cast<Type>(entry.getKey())).getMemorySpace() ==
36  type.getMemorySpace()) {
37  if (auto spec = dyn_cast<SpecAttr>(entry.getValue()))
38  return spec;
39  }
40  }
41  // If not found, and this is the pointer to the default memory space or if
42  // `defaultMemorySpace` is null, assume 64-bit pointers. `defaultMemorySpace`
43  // might be null if the data layout doesn't define the default memory space.
44  if (type.getMemorySpace() == defaultMemorySpace ||
45  defaultMemorySpace == nullptr)
46  return SpecAttr::get(type.getContext(), kDefaultPointerSizeBits,
49  return nullptr;
50 }
51 
52 bool PtrType::areCompatible(DataLayoutEntryListRef oldLayout,
53  DataLayoutEntryListRef newLayout,
54  DataLayoutSpecInterface newSpec,
55  const DataLayoutIdentifiedEntryMap &map) const {
56  for (DataLayoutEntryInterface newEntry : newLayout) {
57  if (!newEntry.isTypeEntry())
58  continue;
59  uint32_t size = kDefaultPointerSizeBits;
60  uint32_t abi = kDefaultPointerAlignmentBits;
61  auto newType = llvm::cast<PtrType>(llvm::cast<Type>(newEntry.getKey()));
62  const auto *it =
63  llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
64  if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
65  return llvm::cast<PtrType>(type).getMemorySpace() ==
66  newType.getMemorySpace();
67  }
68  return false;
69  });
70  if (it == oldLayout.end()) {
72  map.lookup(newSpec.getDefaultMemorySpaceIdentifier(getContext())));
73  it = llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
74  if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
75  auto ptrTy = llvm::cast<PtrType>(type);
76  return ptrTy.getMemorySpace() == defaultMemorySpace;
77  }
78  return false;
79  });
80  }
81  if (it != oldLayout.end()) {
82  auto spec = llvm::cast<SpecAttr>(*it);
83  size = spec.getSize();
84  abi = spec.getAbi();
85  }
86 
87  auto newSpec = llvm::cast<SpecAttr>(newEntry.getValue());
88  uint32_t newSize = newSpec.getSize();
89  uint32_t newAbi = newSpec.getAbi();
90  if (size != newSize || abi < newAbi || abi % newAbi != 0)
91  return false;
92  }
93  return true;
94 }
95 
96 uint64_t PtrType::getABIAlignment(const DataLayout &dataLayout,
97  DataLayoutEntryListRef params) const {
98  auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
99  dataLayout.getDefaultMemorySpace());
100  if (SpecAttr spec = getPointerSpec(params, *this, defaultMemorySpace))
101  return spec.getAbi() / kBitsInByte;
102 
103  return dataLayout.getTypeABIAlignment(get(defaultMemorySpace));
104 }
105 
106 std::optional<uint64_t>
107 PtrType::getIndexBitwidth(const DataLayout &dataLayout,
108  DataLayoutEntryListRef params) const {
109  auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
110  dataLayout.getDefaultMemorySpace());
111  if (SpecAttr spec = getPointerSpec(params, *this, defaultMemorySpace)) {
112  return spec.getIndex() == SpecAttr::kOptionalSpecValue ? spec.getSize()
113  : spec.getIndex();
114  }
115 
116  return dataLayout.getTypeIndexBitwidth(get(defaultMemorySpace));
117 }
118 
119 llvm::TypeSize PtrType::getTypeSizeInBits(const DataLayout &dataLayout,
120  DataLayoutEntryListRef params) const {
121  auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
122  dataLayout.getDefaultMemorySpace());
123  if (SpecAttr spec = getPointerSpec(params, *this, defaultMemorySpace))
124  return llvm::TypeSize::getFixed(spec.getSize());
125 
126  // For other memory spaces, use the size of the pointer to the default memory
127  // space.
128  return dataLayout.getTypeSizeInBits(get(defaultMemorySpace));
129 }
130 
131 uint64_t PtrType::getPreferredAlignment(const DataLayout &dataLayout,
132  DataLayoutEntryListRef params) const {
133  auto defaultMemorySpace = llvm::cast_if_present<MemorySpaceAttrInterface>(
134  dataLayout.getDefaultMemorySpace());
135  if (SpecAttr spec = getPointerSpec(params, *this, defaultMemorySpace))
136  return spec.getPreferred() / kBitsInByte;
137 
138  return dataLayout.getTypePreferredAlignment(get(defaultMemorySpace));
139 }
140 
141 LogicalResult PtrType::verifyEntries(DataLayoutEntryListRef entries,
142  Location loc) const {
143  for (DataLayoutEntryInterface entry : entries) {
144  if (!entry.isTypeEntry())
145  continue;
146  auto key = llvm::cast<Type>(entry.getKey());
147  if (!llvm::isa<SpecAttr>(entry.getValue())) {
148  return emitError(loc) << "expected layout attribute for " << key
149  << " to be a #ptr.spec attribute";
150  }
151  }
152  return success();
153 }
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:136
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:26
constexpr static const unsigned kDefaultPointerSizeBits
Definition: PtrTypes.cpp:24
constexpr static const unsigned kBitsInByte
Definition: PtrTypes.cpp:25
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:30
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 defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:66
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...