Skip to content

Commit 2807a3e

Browse files
authored
[CIR] Backport TargetAddressSpaceAttr and Support both existing Lang AS and target AS attributes in pointer types and Global Ops (#1986)
Bringing the changes we performed at: llvm/llvm-project#161028 down to the incubator isn't as straight-forward as I though. Therefore — this PR might be a bit long but hopefully not too complicated, bare with me :) The main purpose of this is to bring the recent upstreamed `TargetAddressSpaceAttr` and couple it with `PointerType` and `GlobalOp`. The main challenge is that this collides with the already implemented infrastructure related to AS that revolves around our unified enum approach (That handles numeric and lang AS). My main rationale here is that we let our new attribute to coexist with the already existing `cir::AddressSpaceAttr` (renamed now). so that we don't break any tests related to offload-type languages. Considering the above what I'm essentially doing is: 1. Letting `TargetAddressSpaceAttr` handle numeric target AS as it is done upstream. 2. Rename our previous `AddressSpaceAttr` to `LangAdddressSpaceAttr`. 3. Implement `MemorySpaceAttrInterface`for lang and target AS. 4. The current implementation of `LangAddressSpaceAttr`(which handles an enum) will handle language/clang specific AS (CUDA, OpenCL, etc..) it will no longer handle target as it used to! 5. `PointerType` and globalOps will hold a `MemorySpaceAttrInterface`. Similar to the upstream ptr type in the ptr dialect. 6. Adjusted the assembly format for all tests containing any AS attributes to conform with our new format: `lang_address_space(n)`/`clang_address_space(x)`. 7. For the relevant Ops: Default address spaces will now be represented as an empty `MemorySpaceAttrInterface` attribute. 8. Remove any comments that make reference to our old approach regarding AS handling. 9. Updated description where relevant. 10. Bring any extra upstream changes that deviate with what we have here.
1 parent d95a5ff commit 2807a3e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+605
-347
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,23 @@
1111

1212
#include "clang/AST/Decl.h"
1313
#include "clang/AST/Type.h"
14+
#include "clang/Basic/AddressSpaces.h"
1415
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
1516
#include "clang/CIR/Dialect/IR/CIRDialect.h"
1617
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
1718
#include "clang/CIR/Dialect/IR/CIRTypes.h"
1819
#include "clang/CIR/Dialect/IR/FPEnv.h"
1920
#include "clang/CIR/MissingFeatures.h"
2021

22+
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
2123
#include "mlir/IR/Attributes.h"
2224
#include "mlir/IR/Builders.h"
2325
#include "mlir/IR/BuiltinAttributes.h"
2426
#include "mlir/IR/BuiltinOps.h"
2527
#include "mlir/IR/BuiltinTypes.h"
2628
#include "mlir/IR/Location.h"
2729
#include "mlir/IR/Types.h"
30+
#include "mlir/Support/LLVM.h"
2831
#include "llvm/ADT/APSInt.h"
2932
#include "llvm/ADT/ArrayRef.h"
3033
#include "llvm/ADT/FloatingPointMode.h"
@@ -105,20 +108,30 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
105108
return cir::PointerType::get(ty);
106109
}
107110

108-
cir::PointerType getPointerTo(mlir::Type ty, cir::AddressSpace as) {
109-
return cir::PointerType::get(ty, as);
111+
/// Create a pointer type with an address space attribute.
112+
cir::PointerType
113+
getPointerTo(mlir::Type ty, mlir::ptr::MemorySpaceAttrInterface memorySpace) {
114+
if (!memorySpace)
115+
return cir::PointerType::get(ty);
116+
return cir::PointerType::get(ty, memorySpace);
110117
}
111118

112119
cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
113-
return getPointerTo(ty, cir::toCIRAddressSpace(langAS));
120+
if (langAS == clang::LangAS::Default)
121+
return getPointerTo(ty);
122+
123+
mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr =
124+
cir::toCIRLangAddressSpaceAttr(getContext(), langAS);
125+
return getPointerTo(ty, addrSpaceAttr);
114126
}
115127

116128
cir::PointerType getVoidPtrTy(clang::LangAS langAS = clang::LangAS::Default) {
117129
return getPointerTo(cir::VoidType::get(getContext()), langAS);
118130
}
119131

120-
cir::PointerType getVoidPtrTy(cir::AddressSpace as) {
121-
return getPointerTo(cir::VoidType::get(getContext()), as);
132+
cir::PointerType
133+
getVoidPtrTy(mlir::ptr::MemorySpaceAttrInterface memorySpace) {
134+
return getPointerTo(cir::VoidType::get(getContext()), memorySpace);
122135
}
123136

124137
cir::MethodAttr getMethodAttr(cir::MethodType ty, cir::FuncOp methodFuncOp) {
@@ -419,7 +432,8 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
419432
mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global,
420433
bool threadLocal = false) {
421434
return cir::GetGlobalOp::create(
422-
*this, loc, getPointerTo(global.getSymType(), global.getAddrSpace()),
435+
*this, loc,
436+
getPointerTo(global.getSymType(), global.getAddrSpaceAttr()),
423437
global.getName(), threadLocal);
424438
}
425439

clang/include/clang/CIR/Dialect/IR/CIRAttrs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef CLANG_CIR_DIALECT_IR_CIRATTRS_H
1414
#define CLANG_CIR_DIALECT_IR_CIRATTRS_H
1515

16+
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
1617
#include "mlir/IR/Attributes.h"
1718
#include "mlir/IR/BuiltinAttributeInterfaces.h"
1819

clang/include/clang/CIR/Dialect/IR/CIRAttrs.td

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define CLANG_CIR_DIALECT_IR_CIRATTRS_TD
1515

1616
include "mlir/IR/BuiltinAttributeInterfaces.td"
17+
include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
1718
include "clang/CIR/Dialect/IR/CIREnumAttr.td"
1819

1920
include "clang/CIR/Dialect/IR/CIRDialect.td"
@@ -963,43 +964,76 @@ def CIR_DynamicCastInfoAttr : CIR_Attr<"DynamicCastInfo", "dyn_cast_info"> {
963964
// AddressSpaceAttr
964965
//===----------------------------------------------------------------------===//
965966

966-
def CIR_AddressSpaceAttr : CIR_EnumAttr<CIR_AddressSpace, "address_space"> {
967+
def CIR_LangAddressSpaceAttr :
968+
CIR_EnumAttr<CIR_LangAddressSpace, "lang_address_space", [
969+
DeclareAttrInterfaceMethods<MemorySpaceAttrInterface>
970+
]> {
971+
972+
let summary = "Represents a language address space";
973+
let description = [{
974+
Encodes the semantic address spaces defined by the front-end language
975+
(e.g. `__shared__`, `__constant__`, `__local__`). Values are stored using the
976+
`cir::LangAddressSpace` enum, keeping the representation compact while and
977+
preserves the qualifier until it is mapped onto target/LLVM address-space numbers.
978+
979+
Example:
980+
``` mlir
981+
!cir.ptr<!s32i, lang_address_space(offload_local)>
982+
cir.global constant external lang_address_space(offload_constant)
983+
984+
```
985+
}];
986+
967987
let builders = [
968988
AttrBuilder<(ins "clang::LangAS":$langAS), [{
969-
return $_get($_ctxt, cir::toCIRAddressSpace(langAS));
989+
return $_get($_ctxt, cir::toCIRLangAddressSpace(langAS));
970990
}]>
971991
];
972992

973993
let assemblyFormat = [{
974994
`(` custom<AddressSpaceValue>($value) `)`
975995
}];
976996

977-
let defaultValue = "cir::AddressSpace::Default";
997+
let defaultValue = "cir::LangAddressSpace::Default";
978998

979999
let extraClassDeclaration = [{
980-
bool isLang() const;
981-
bool isTarget() const;
982-
unsigned getTargetValue() const;
9831000
unsigned getAsUnsignedValue() const;
9841001
}];
9851002

9861003
let extraClassDefinition = [{
9871004
unsigned $cppClass::getAsUnsignedValue() const {
9881005
return static_cast<unsigned>(getValue());
9891006
}
1007+
}];
1008+
}
9901009

991-
bool $cppClass::isLang() const {
992-
return cir::isLangAddressSpace(getValue());
993-
}
1010+
//===----------------------------------------------------------------------===//
1011+
// TargetAddressSpaceAttr
1012+
//===----------------------------------------------------------------------===//
9941013

995-
bool $cppClass::isTarget() const {
996-
return cir::isTargetAddressSpace(getValue());
997-
}
1014+
def CIR_TargetAddressSpaceAttr : CIR_Attr< "TargetAddressSpace",
1015+
"target_address_space", [
1016+
DeclareAttrInterfaceMethods<MemorySpaceAttrInterface>
1017+
]> {
1018+
let summary = "Represents a target-specific numeric address space";
1019+
let description = [{
1020+
The TargetAddressSpaceAttr represents a target-specific numeric address space,
1021+
corresponding to the LLVM IR `addressspace` qualifier and the clang
1022+
`address_space` attribute.
1023+
1024+
A value of zero represents the default address space. The semantics of non-zero
1025+
address spaces are target-specific.
9981026

999-
unsigned $cppClass::getTargetValue() const {
1000-
return cir::getTargetAddressSpaceValue(getValue());
1001-
}
1027+
Example:
1028+
```mlir
1029+
// Target-specific numeric address spaces
1030+
!cir.ptr<!s32i, target_address_space(1)>
1031+
!cir.ptr<!s32i, target_address_space(1)>
1032+
```
10021033
}];
1034+
1035+
let parameters = (ins "unsigned":$value);
1036+
let assemblyFormat = "`<` `target` `<` $value `>` `>`";
10031037
}
10041038

10051039
//===----------------------------------------------------------------------===//

clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,14 @@ class CIR_DefaultValuedEnumParameter<EnumAttrInfo info, string value = "">
4141
let defaultValue = value;
4242
}
4343

44-
def CIR_AddressSpace : CIR_I32EnumAttr<
45-
"AddressSpace", "address space kind", [
44+
def CIR_LangAddressSpace : CIR_I32EnumAttr<
45+
"LangAddressSpace", "language address space kind", [
4646
I32EnumAttrCase<"Default", 0, "default">,
4747
I32EnumAttrCase<"OffloadPrivate", 1, "offload_private">,
4848
I32EnumAttrCase<"OffloadLocal", 2, "offload_local">,
4949
I32EnumAttrCase<"OffloadGlobal", 3, "offload_global">,
5050
I32EnumAttrCase<"OffloadConstant", 4, "offload_constant">,
51-
I32EnumAttrCase<"OffloadGeneric", 5, "offload_generic">,
52-
I32EnumAttrCase<"Target", 6, "target">
51+
I32EnumAttrCase<"OffloadGeneric", 5, "offload_generic">
5352
]> {
5453
let description = [{
5554
The `address_space` attribute is used to represent address spaces for
@@ -58,7 +57,7 @@ def CIR_AddressSpace : CIR_I32EnumAttr<
5857

5958
The `value` parameter is an extensible enum, which encodes target address
6059
space as an offset to the last language address space. For that reason, the
61-
attribute is implemented as custom AddressSpaceAttr, which provides custom
60+
attribute is implemented as custom LangAddressSpaceAttr, which provides custom
6261
printer and parser for the `value` parameter.
6362
}];
6463

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,10 +2618,7 @@ def CIR_GlobalOp : CIR_Op<"global", [
26182618
OptionalAttr<StrAttr>:$sym_visibility,
26192619
TypeAttr:$sym_type,
26202620
CIR_GlobalLinkageKind:$linkage,
2621-
DefaultValuedAttr<
2622-
CIR_AddressSpaceAttr,
2623-
"AddressSpace::Default"
2624-
>:$addr_space,
2621+
OptionalAttr<MemorySpaceAttrInterface>:$addr_space,
26252622
OptionalAttr<CIR_TLSModel>:$tls_model,
26262623
// Note this can also be a FlatSymbolRefAttr
26272624
OptionalAttr<AnyAttr>:$initial_value,
@@ -2644,7 +2641,7 @@ def CIR_GlobalOp : CIR_Op<"global", [
26442641
(`comdat` $comdat^)?
26452642
($tls_model^)?
26462643
(`dso_local` $dso_local^)?
2647-
(`addrspace` `` $addr_space^)?
2644+
(` ` custom<GlobalAddressSpaceValue>($addr_space)^ )?
26482645
$sym_name
26492646
custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value, $ctorRegion, $dtorRegion)
26502647
($annotations^)?
@@ -2668,7 +2665,7 @@ def CIR_GlobalOp : CIR_Op<"global", [
26682665
// CIR defaults to external linkage.
26692666
CArg<"cir::GlobalLinkageKind",
26702667
"cir::GlobalLinkageKind::ExternalLinkage">:$linkage,
2671-
CArg<"cir::AddressSpace", "cir::AddressSpace::Default">:$addrSpace,
2668+
CArg<"mlir::ptr::MemorySpaceAttrInterface", "{}">:$addrSpace,
26722669
CArg<"llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>",
26732670
"nullptr">:$ctorBuilder,
26742671
CArg<"llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>",

clang/include/clang/CIR/Dialect/IR/CIRTypes.h

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef CLANG_CIR_DIALECT_IR_CIRTYPES_H
1414
#define CLANG_CIR_DIALECT_IR_CIRTYPES_H
1515

16+
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
1617
#include "mlir/IR/BuiltinAttributes.h"
1718
#include "mlir/IR/Types.h"
1819
#include "mlir/Interfaces/DataLayoutInterfaces.h"
@@ -34,37 +35,18 @@ bool isSized(mlir::Type ty);
3435
// AddressSpace helpers
3536
//===----------------------------------------------------------------------===//
3637

37-
cir::AddressSpace toCIRAddressSpace(clang::LangAS langAS);
38+
cir::LangAddressSpace toCIRLangAddressSpace(clang::LangAS langAS);
3839

39-
constexpr unsigned getAsUnsignedValue(cir::AddressSpace as) {
40-
return static_cast<unsigned>(as);
41-
}
42-
43-
inline constexpr unsigned TargetAddressSpaceOffset =
44-
cir::getMaxEnumValForAddressSpace();
45-
46-
// Target address space is used for target-specific address spaces that are not
47-
// part of the enum. Its value is represented as an offset from the maximum
48-
// value of the enum. Make sure that it is always the last enum value.
49-
static_assert(getAsUnsignedValue(cir::AddressSpace::Target) ==
50-
cir::getMaxEnumValForAddressSpace(),
51-
"Target address space must be the last enum value");
52-
53-
constexpr bool isTargetAddressSpace(cir::AddressSpace as) {
54-
return getAsUnsignedValue(as) >= cir::getMaxEnumValForAddressSpace();
55-
}
40+
/// Convert a LangAS to the appropriate address space attribute interface.
41+
/// Returns a MemorySpaceAttrInterface.
42+
mlir::ptr::MemorySpaceAttrInterface
43+
toCIRLangAddressSpaceAttr(mlir::MLIRContext *ctx, clang::LangAS langAS);
5644

57-
constexpr bool isLangAddressSpace(cir::AddressSpace as) {
58-
return !isTargetAddressSpace(as);
59-
}
45+
bool isSupportedCIRMemorySpaceAttr(
46+
mlir::ptr::MemorySpaceAttrInterface memorySpace);
6047

61-
constexpr unsigned getTargetAddressSpaceValue(cir::AddressSpace as) {
62-
assert(isTargetAddressSpace(as) && "expected target address space");
63-
return getAsUnsignedValue(as) - TargetAddressSpaceOffset;
64-
}
65-
66-
constexpr cir::AddressSpace computeTargetAddressSpace(unsigned v) {
67-
return static_cast<cir::AddressSpace>(v + TargetAddressSpaceOffset);
48+
constexpr unsigned getAsUnsignedValue(cir::LangAddressSpace as) {
49+
return static_cast<unsigned>(as);
6850
}
6951

7052
} // namespace cir

clang/include/clang/CIR/Dialect/IR/CIRTypes.td

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
include "clang/CIR/Dialect/IR/CIRDialect.td"
1717
include "clang/CIR/Dialect/IR/CIREnumAttr.td"
1818
include "clang/CIR/Dialect/IR/CIRTypeConstraints.td"
19+
include "clang/CIR/Dialect/IR/CIRAttrConstraints.td"
1920
include "clang/CIR/Interfaces/ASTAttrInterfaces.td"
2021
include "clang/CIR/Interfaces/CIRTypeInterfaces.td"
2122
include "mlir/Interfaces/DataLayoutInterfaces.td"
2223
include "mlir/IR/AttrTypeBase.td"
2324
include "mlir/IR/EnumAttr.td"
25+
include "mlir/IR/CommonAttrConstraints.td"
2426

2527
//===----------------------------------------------------------------------===//
2628
// CIR Types
@@ -231,32 +233,31 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
231233
```
232234
}];
233235

236+
let genVerifyDecl = 1;
237+
234238
let parameters = (ins
235239
"mlir::Type":$pointee,
236-
CIR_DefaultValuedEnumParameter<
237-
CIR_AddressSpace,
238-
"cir::AddressSpace::Default"
239-
>:$addrSpace
240+
OptionalParameter<"mlir::ptr::MemorySpaceAttrInterface">:$addrSpace
240241
);
241242

242243
let skipDefaultBuilders = 1;
243244
let builders = [
244245
TypeBuilderWithInferredContext<(ins
245246
"mlir::Type":$pointee,
246-
CArg<"cir::AddressSpace", "cir::AddressSpace::Default">:$addrSpace), [{
247+
CArg<"mlir::ptr::MemorySpaceAttrInterface", "{}">:$addrSpace), [{
247248
return $_get(pointee.getContext(), pointee, addrSpace);
248249
}]>,
249250
TypeBuilder<(ins
250251
"mlir::Type":$pointee,
251-
CArg<"cir::AddressSpace", "cir::AddressSpace::Default">:$addrSpace), [{
252+
CArg<"mlir::ptr::MemorySpaceAttrInterface", "{}">:$addrSpace), [{
252253
return $_get($_ctxt, pointee, addrSpace);
253254
}]>
254255
];
255256

256257
let assemblyFormat = [{
257258
`<`
258259
$pointee
259-
( `,` `addrspace` `(` `` custom<AddressSpaceValue>($addrSpace)^ `)` )?
260+
( `,` ` ` custom<AddressSpaceValue>($addrSpace)^ )?
260261
`>`
261262
}];
262263

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,8 @@ struct MissingFeatures {
480480
static bool mustProgress() { return false; }
481481

482482
static bool skipTempCopy() { return false; }
483+
484+
static bool dataLayoutPtrHandlingBasedOnLangAS() { return false; }
483485
};
484486

485487
} // namespace cir

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "clang/CIR/Dialect/IR/CIRTypes.h"
2626
#include "clang/CIR/Dialect/IR/FPEnv.h"
2727

28+
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
2829
#include "mlir/IR/Attributes.h"
2930
#include "mlir/IR/Builders.h"
3031
#include "mlir/IR/BuiltinAttributes.h"
@@ -749,7 +750,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
749750
[[nodiscard]] cir::GlobalOp
750751
createGlobal(mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name,
751752
mlir::Type type, bool isConst, cir::GlobalLinkageKind linkage,
752-
cir::AddressSpace addrSpace = cir::AddressSpace::Default) {
753+
mlir::ptr::MemorySpaceAttrInterface addrSpace = {}) {
753754
mlir::OpBuilder::InsertionGuard guard(*this);
754755
setInsertionPointToStart(module.getBody());
755756
return cir::GlobalOp::create(*this, loc, name, type, isConst, linkage,
@@ -759,10 +760,11 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
759760
/// Creates a versioned global variable. If the symbol is already taken, an ID
760761
/// will be appended to the symbol. The returned global must always be queried
761762
/// for its name so it can be referenced correctly.
762-
[[nodiscard]] cir::GlobalOp createVersionedGlobal(
763-
mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name,
764-
mlir::Type type, bool isConst, cir::GlobalLinkageKind linkage,
765-
cir::AddressSpace addrSpace = cir::AddressSpace::Default) {
763+
[[nodiscard]] cir::GlobalOp
764+
createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc,
765+
mlir::StringRef name, mlir::Type type, bool isConst,
766+
cir::GlobalLinkageKind linkage,
767+
mlir::ptr::MemorySpaceAttrInterface addrSpace = {}) {
766768
// Create a unique name if the given name is already taken.
767769
std::string uniqueName;
768770
if (unsigned version = GlobalsVersioning[name.str()]++)

0 commit comments

Comments
 (0)