Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
Expand Down Expand Up @@ -105,20 +106,35 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return cir::PointerType::get(ty);
}

cir::PointerType getPointerTo(mlir::Type ty, cir::AddressSpace as) {
return cir::PointerType::get(ty, as);
/// Create a pointer type with an address space attribute.
/// Either a cir::ClangAddressSpaceAttr or cir::TargetAddressSpaceAttr is
/// expected.
cir::PointerType getPointerTo(mlir::Type ty, mlir::Attribute addrSpaceAttr) {
if (!addrSpaceAttr)
return cir::PointerType::get(ty);

assert((mlir::isa<cir::ClangAddressSpaceAttr>(addrSpaceAttr) ||
mlir::isa<cir::TargetAddressSpaceAttr>(addrSpaceAttr)) &&
"expected address space attribute");

return cir::PointerType::get(ty, addrSpaceAttr);
}

cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
return getPointerTo(ty, cir::toCIRAddressSpace(langAS));
if (langAS == clang::LangAS::Default)
return getPointerTo(ty);

mlir::Attribute addrSpaceAttr =
cir::toCIRClangAddressSpaceAttr(getContext(), langAS);
return getPointerTo(ty, addrSpaceAttr);
}

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

cir::PointerType getVoidPtrTy(cir::AddressSpace as) {
return getPointerTo(cir::VoidType::get(getContext()), as);
cir::PointerType getVoidPtrTy(mlir::Attribute addrSpaceAttr) {
return getPointerTo(cir::VoidType::get(getContext()), addrSpaceAttr);
}

cir::MethodAttr getMethodAttr(cir::MethodType ty, cir::FuncOp methodFuncOp) {
Expand Down
20 changes: 20 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,24 @@ def CIR_AnyTBAAAttr : AnyAttrOf<[
string cppType = "::mlir::Attribute";
}

//===----------------------------------------------------------------------===//
// AddressSpaceAttr constraints
//===----------------------------------------------------------------------===//

// NOTE: We might end up using this only for GlobalOps, as we cannot apply constraints
// to types.
def CIR_AddressSpaceAttrConstraint
: CIR_AttrConstraint<"::cir::ClangAddressSpaceAttr", "clang address space attribute">;

def CIR_TargetAddressSpaceAttrConstraint
: CIR_AttrConstraint<"::cir::TargetAddressSpaceAttr", "target address space attribute">;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a plan to eventually merge these two? I feel it's weird to have two different attributes for it, I wonder if it would be more clean if there's a base AddressSpaceAttr and these two different ones are just specializations - using CIR_AnyAddressSpaceAttr for this only work for constraints and it would be nice if in general to pass things around in the terms of the generic version. If so, maybe doing it as part of this PR is a good time.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure if specializations for attributes can be done in MLIR (I might need to research!).

What we could do is to add MemorySpaceAttrInterface to PointerType as a paremeter (Similar to how it's done in the ptr dialect:

let parameters = (ins "MemorySpaceAttrInterface":$memorySpace);
). This interface would be implemented by both Target and Clang address spaces. This last thing I intended to do in a different PR, but I agree It's not entirely correct in its current state.

If the above makes sense I'll work on it soon.


def CIR_AnyAddressSpaceAttr : AnyAttrOf<[
CIR_AddressSpaceAttrConstraint,
CIR_TargetAddressSpaceAttrConstraint
]> {
string cppType = "::mlir::Attribute";
let constBuilderCall = "nullptr";
}

#endif // CLANG_CIR_DIALECT_IR_CIRATTRCONSTRAINTS_TD
58 changes: 43 additions & 15 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -963,43 +963,71 @@ def CIR_DynamicCastInfoAttr : CIR_Attr<"DynamicCastInfo", "dyn_cast_info"> {
// AddressSpaceAttr
//===----------------------------------------------------------------------===//

def CIR_AddressSpaceAttr : CIR_EnumAttr<CIR_AddressSpace, "address_space"> {
def CIR_ClangAddressSpaceAttr : CIR_EnumAttr<CIR_ClangAddressSpace, "clang_address_space"> {

let summary = "Represents a language/Clang-level address space";
let description = [{
Encodes the semantic address spaces defined by the front-end language
(e.g. `__shared__`, `__constant__`, `__local__`). Values are stored using the
`cir::ClangAddressSpace` enum, keeping the representation compact while and
preserves the qualifier until it is mapped onto target/LLVM address-space numbers.

Example:
``` mlir
!cir.ptr<!s32i, clang_address_space(offload_local)>
cir.global constant external clang_address_space(offload_constant)

```
}];

let builders = [
AttrBuilder<(ins "clang::LangAS":$langAS), [{
return $_get($_ctxt, cir::toCIRAddressSpace(langAS));
return $_get($_ctxt, cir::toCIRClangAddressSpace(langAS));
}]>
];

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

let defaultValue = "cir::AddressSpace::Default";
let defaultValue = "cir::ClangAddressSpace::Default";

let extraClassDeclaration = [{
bool isLang() const;
bool isTarget() const;
unsigned getTargetValue() const;
unsigned getAsUnsignedValue() const;
}];

let extraClassDefinition = [{
unsigned $cppClass::getAsUnsignedValue() const {
return static_cast<unsigned>(getValue());
}
}];
}

bool $cppClass::isLang() const {
return cir::isLangAddressSpace(getValue());
}
//===----------------------------------------------------------------------===//
// TargetAddressSpaceAttr
//===----------------------------------------------------------------------===//

bool $cppClass::isTarget() const {
return cir::isTargetAddressSpace(getValue());
}
def CIR_TargetAddressSpaceAttr : CIR_Attr< "TargetAddressSpace",
"target_address_space"> {
let summary = "Represents a target-specific numeric address space";
let description = [{
The TargetAddressSpaceAttr represents a target-specific numeric address space,
corresponding to the LLVM IR `addressspace` qualifier and the clang
`address_space` attribute.

A value of zero represents the default address space. The semantics of non-zero
address spaces are target-specific.

unsigned $cppClass::getTargetValue() const {
return cir::getTargetAddressSpaceValue(getValue());
}
Example:
```mlir
// Target-specific numeric address spaces
!cir.ptr<!s32i, target_address_space(1)>
!cir.ptr<!s32i, target_address_space(1)>
```
}];

let parameters = (ins "unsigned":$value);
let assemblyFormat = "`<` `target` `<` $value `>` `>`";
}

//===----------------------------------------------------------------------===//
Expand Down
7 changes: 3 additions & 4 deletions clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,14 @@ class CIR_DefaultValuedEnumParameter<EnumAttrInfo info, string value = "">
let defaultValue = value;
}

def CIR_AddressSpace : CIR_I32EnumAttr<
"AddressSpace", "address space kind", [
def CIR_ClangAddressSpace : CIR_I32EnumAttr<
"ClangAddressSpace", "clang address space kind", [
I32EnumAttrCase<"Default", 0, "default">,
I32EnumAttrCase<"OffloadPrivate", 1, "offload_private">,
I32EnumAttrCase<"OffloadLocal", 2, "offload_local">,
I32EnumAttrCase<"OffloadGlobal", 3, "offload_global">,
I32EnumAttrCase<"OffloadConstant", 4, "offload_constant">,
I32EnumAttrCase<"OffloadGeneric", 5, "offload_generic">,
I32EnumAttrCase<"Target", 6, "target">
I32EnumAttrCase<"OffloadGeneric", 5, "offload_generic">
]> {
let description = [{
The `address_space` attribute is used to represent address spaces for
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -2617,8 +2617,8 @@ def CIR_GlobalOp : CIR_Op<"global", [
TypeAttr:$sym_type,
CIR_GlobalLinkageKind:$linkage,
DefaultValuedAttr<
CIR_AddressSpaceAttr,
"AddressSpace::Default"
CIR_AnyAddressSpaceAttr,
"{}"
>:$addr_space,
OptionalAttr<CIR_TLSModel>:$tls_model,
// Note this can also be a FlatSymbolRefAttr
Expand All @@ -2642,7 +2642,7 @@ def CIR_GlobalOp : CIR_Op<"global", [
(`comdat` $comdat^)?
($tls_model^)?
(`dso_local` $dso_local^)?
(`addrspace` `` $addr_space^)?
(` ` custom<GlobalAddressSpaceValue>($addr_space)^ )?
$sym_name
custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value, $ctorRegion, $dtorRegion)
($annotations^)?
Expand All @@ -2666,7 +2666,7 @@ def CIR_GlobalOp : CIR_Op<"global", [
// CIR defaults to external linkage.
CArg<"cir::GlobalLinkageKind",
"cir::GlobalLinkageKind::ExternalLinkage">:$linkage,
CArg<"cir::AddressSpace", "cir::AddressSpace::Default">:$addrSpace,
CArg<"mlir::Attribute", "{}">:$addrSpace,
CArg<"llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>",
"nullptr">:$ctorBuilder,
CArg<"llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>",
Expand Down
37 changes: 8 additions & 29 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,37 +34,16 @@ bool isSized(mlir::Type ty);
// AddressSpace helpers
//===----------------------------------------------------------------------===//

cir::AddressSpace toCIRAddressSpace(clang::LangAS langAS);
cir::ClangAddressSpace toCIRClangAddressSpace(clang::LangAS langAS);

constexpr unsigned getAsUnsignedValue(cir::AddressSpace as) {
return static_cast<unsigned>(as);
}

inline constexpr unsigned TargetAddressSpaceOffset =
cir::getMaxEnumValForAddressSpace();

// Target address space is used for target-specific address spaces that are not
// part of the enum. Its value is represented as an offset from the maximum
// value of the enum. Make sure that it is always the last enum value.
static_assert(getAsUnsignedValue(cir::AddressSpace::Target) ==
cir::getMaxEnumValForAddressSpace(),
"Target address space must be the last enum value");

constexpr bool isTargetAddressSpace(cir::AddressSpace as) {
return getAsUnsignedValue(as) >= cir::getMaxEnumValForAddressSpace();
}
/// Convert a LangAS to the appropriate address space attribute.
/// Returns ClangAddressSpaceAttr for clang/language-specific address spaces,
/// or TargetAddressSpaceAttr for target-specific address spaces.
mlir::Attribute toCIRClangAddressSpaceAttr(mlir::MLIRContext *ctx,
clang::LangAS langAS);

constexpr bool isLangAddressSpace(cir::AddressSpace as) {
return !isTargetAddressSpace(as);
}

constexpr unsigned getTargetAddressSpaceValue(cir::AddressSpace as) {
assert(isTargetAddressSpace(as) && "expected target address space");
return getAsUnsignedValue(as) - TargetAddressSpaceOffset;
}

constexpr cir::AddressSpace computeTargetAddressSpace(unsigned v) {
return static_cast<cir::AddressSpace>(v + TargetAddressSpaceOffset);
constexpr unsigned getAsUnsignedValue(cir::ClangAddressSpace as) {
return static_cast<unsigned>(as);
}

} // namespace cir
Expand Down
15 changes: 8 additions & 7 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
include "clang/CIR/Dialect/IR/CIRDialect.td"
include "clang/CIR/Dialect/IR/CIREnumAttr.td"
include "clang/CIR/Dialect/IR/CIRTypeConstraints.td"
include "clang/CIR/Dialect/IR/CIRAttrConstraints.td"
include "clang/CIR/Interfaces/ASTAttrInterfaces.td"
include "clang/CIR/Interfaces/CIRTypeInterfaces.td"
include "mlir/Interfaces/DataLayoutInterfaces.td"
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/EnumAttr.td"
include "mlir/IR/CommonAttrConstraints.td"

//===----------------------------------------------------------------------===//
// CIR Types
Expand Down Expand Up @@ -231,32 +233,31 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
```
}];

let genVerifyDecl = 1;

let parameters = (ins
"mlir::Type":$pointee,
CIR_DefaultValuedEnumParameter<
CIR_AddressSpace,
"cir::AddressSpace::Default"
>:$addrSpace
OptionalParameter<"mlir::Attribute">:$addrSpace
);

let skipDefaultBuilders = 1;
let builders = [
TypeBuilderWithInferredContext<(ins
"mlir::Type":$pointee,
CArg<"cir::AddressSpace", "cir::AddressSpace::Default">:$addrSpace), [{
CArg<"mlir::Attribute", "{}">:$addrSpace), [{
return $_get(pointee.getContext(), pointee, addrSpace);
}]>,
TypeBuilder<(ins
"mlir::Type":$pointee,
CArg<"cir::AddressSpace", "cir::AddressSpace::Default">:$addrSpace), [{
CArg<"mlir::Attribute", "{}">:$addrSpace), [{
return $_get($_ctxt, pointee, addrSpace);
}]>
];

let assemblyFormat = [{
`<`
$pointee
( `,` `addrspace` `(` `` custom<AddressSpaceValue>($addrSpace)^ `)` )?
( `,` ` ` custom<AddressSpaceValue>($addrSpace)^ )?
`>`
}];

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,8 @@ struct MissingFeatures {
static bool mustProgress() { return false; }

static bool skipTempCopy() { return false; }

static bool dataLayoutPtrHandlingBasedOnLangAS() { return false; }
};

} // namespace cir
Expand Down
11 changes: 6 additions & 5 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
[[nodiscard]] cir::GlobalOp
createGlobal(mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name,
mlir::Type type, bool isConst, cir::GlobalLinkageKind linkage,
cir::AddressSpace addrSpace = cir::AddressSpace::Default) {
mlir::Attribute addrSpace = {}) {
mlir::OpBuilder::InsertionGuard guard(*this);
setInsertionPointToStart(module.getBody());
return cir::GlobalOp::create(*this, loc, name, type, isConst, linkage,
Expand All @@ -759,10 +759,11 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
/// Creates a versioned global variable. If the symbol is already taken, an ID
/// will be appended to the symbol. The returned global must always be queried
/// for its name so it can be referenced correctly.
[[nodiscard]] cir::GlobalOp createVersionedGlobal(
mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name,
mlir::Type type, bool isConst, cir::GlobalLinkageKind linkage,
cir::AddressSpace addrSpace = cir::AddressSpace::Default) {
[[nodiscard]] cir::GlobalOp
createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc,
mlir::StringRef name, mlir::Type type, bool isConst,
cir::GlobalLinkageKind linkage,
mlir::Attribute addrSpace = {}) {
// Create a unique name if the given name is already taken.
std::string uniqueName;
if (unsigned version = GlobalsVersioning[name.str()]++)
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "clang/Frontend/FrontendDiagnostic.h"

#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Value.h"
#include "mlir/Support/LLVM.h"
Expand Down Expand Up @@ -1727,9 +1728,9 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// the AST level this is handled within CreateTempAlloca et al., but for the
// builtin / dynamic alloca we have to handle it here.
assert(!cir::MissingFeatures::addressSpace());
cir::AddressSpace AAS = getCIRAllocaAddressSpace();
cir::AddressSpace EAS = cir::toCIRAddressSpace(
E->getType()->getPointeeType().getAddressSpace());
mlir::Attribute AAS = getCIRAllocaAddressSpace();
mlir::Attribute EAS = cir::toCIRClangAddressSpaceAttr(
&getMLIRContext(), E->getType()->getPointeeType().getAddressSpace());
if (EAS != AAS) {
assert(false && "Non-default address space for alloca NYI");
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ mlir::Operation *CIRGenNVCUDARuntime::getKernelHandle(cir::FuncOp fn,
return CIRGenModule::createGlobalOp(
cgm, fn->getLoc(), globalName,
builder.getPointerTo(fn.getFunctionType()), true,
cir::AddressSpace::Default,
/*addrSpace=*/{},
/*insertPoint=*/nullptr);
});

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,8 @@ CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &D,
Name = getStaticDeclName(*this, D);

mlir::Type LTy = getTypes().convertTypeForMem(Ty);
cir::AddressSpace AS = cir::toCIRAddressSpace(getGlobalVarAddressSpace(&D));
mlir::Attribute AS = cir::toCIRClangAddressSpaceAttr(
&getMLIRContext(), getGlobalVarAddressSpace(&D));

// OpenCL variables in local address space and CUDA shared
// variables cannot have an initializer.
Expand Down
Loading