diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index b9ad798d27d0..b857852917aa 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -75,14 +75,18 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return mlir::cir::IntType::get(getContext(), N, true); } - mlir::cir::PointerType getPointerTo(mlir::Type ty, - unsigned addressSpace = 0) { - assert(!addressSpace && "address space is NYI"); - return mlir::cir::PointerType::get(getContext(), ty); + mlir::cir::PointerType + getPointerTo(mlir::Type ty, clang::LangAS langAS = clang::LangAS::Default) { + mlir::cir::AddressSpaceAttr addrSpaceAttr; + if (langAS != clang::LangAS::Default) + addrSpaceAttr = mlir::cir::AddressSpaceAttr::get(getContext(), langAS); + + return mlir::cir::PointerType::get(getContext(), ty, addrSpaceAttr); } - mlir::cir::PointerType getVoidPtrTy(unsigned addressSpace = 0) { - return getPointerTo(::mlir::cir::VoidType::get(getContext()), addressSpace); + mlir::cir::PointerType + getVoidPtrTy(clang::LangAS langAS = clang::LangAS::Default) { + return getPointerTo(::mlir::cir::VoidType::get(getContext()), langAS); } mlir::Value createLoad(mlir::Location loc, mlir::Value ptr, diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 9bb8d105e991..bb6bc6421a0a 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -617,6 +617,143 @@ def DynamicCastInfoAttr }]; } +//===----------------------------------------------------------------------===// +// AddressSpaceAttr +//===----------------------------------------------------------------------===// + +// TODO: other CIR AS cases +def AS_Target : I32EnumAttrCase<"target", 21>; + +def AddressSpaceAttr : CIR_Attr<"AddressSpace", "addrspace"> { + + let summary = "Address space attribute for pointer types"; + let description = [{ + The address space attribute models `clang::LangAS` rather than the LLVM + address space, which means it's not yet converted by the address space map + to carry target-specific semantics. + + The representation is one-to-one except for `LangAS::Default`, which + corresponds to a null attribute instead. + }]; + + let parameters = (ins "int32_t":$value); + + let assemblyFormat = [{ + `<` $value `>` + }]; + + let builders = [ + AttrBuilder<(ins "clang::LangAS":$langAS), [{ + assert(langAS != clang::LangAS::Default && + "Default address space is encoded as null attribute"); + return $_get($_ctxt, getValueFromLangAS(langAS).value()); + }]> + ]; + + let cppNamespace = "::mlir::cir"; + + // The following codes implement these conversions: + // clang::LangAS -> int32_t <-> text-form CIR + + // CIR_PointerType manipulates the parse- and stringify- methods to provide + // simplified assembly format `custom`. + + list langASCases = [ + // TODO: includes all non-target CIR AS cases here + ]; + + I32EnumAttrCase targetASCase = AS_Target; + + let extraClassDeclaration = [{ + static constexpr char kTargetKeyword[] = "}]#targetASCase.symbol#[{"; + static constexpr int32_t kFirstTargetASValue = }]#targetASCase.value#[{; + + bool isLang() const; + bool isTarget() const; + unsigned getTargetValue() const; + + static std::optional parseValueFromString(llvm::StringRef s); + static std::optional getValueFromLangAS(clang::LangAS v); + static std::optional stringifyValue(int32_t v); + }]; + + let extraClassDefinition = [{ + bool $cppClass::isLang() const { + return !isTarget(); + } + + bool $cppClass::isTarget() const { + return getValue() >= kFirstTargetASValue; + } + + unsigned $cppClass::getTargetValue() const { + assert(isTarget() && "Not a target address space"); + return getValue() - kFirstTargetASValue; + } + + std::optional + $cppClass::parseValueFromString(llvm::StringRef str) { + return llvm::StringSwitch<::std::optional>(str) + }] + # + !interleave( + !foreach(case, langASCases, + ".Case(\""#case.symbol# "\", "#case.value # ")\n" + ), + "\n" + ) + # + [{ + // Target address spaces are not parsed here + .Default(std::nullopt); + } + + std::optional + $cppClass::stringifyValue(int32_t value) { + switch (value) { + }] + # + !interleave( + !foreach(case, langASCases, + "case "#case.value + # ": return \""#case.symbol # "\";" ), + "\n" + ) + # + [{ + default: + // Target address spaces are not processed here + return std::nullopt; + } + } + + std::optional + $cppClass::getValueFromLangAS(clang::LangAS langAS) { + assert((langAS == clang::LangAS::Default || + clang::isTargetAddressSpace(langAS)) && + "Language-specific address spaces are not supported"); + switch (langAS) { + }] + # + !interleave( + !foreach(case, langASCases, + "case clang::LangAS::"#case.symbol + # [{: llvm_unreachable("Not Yet Supported");}] ), + "\n" + ) + # + [{ + case clang::LangAS::Default: + // Default address space should be encoded as a null attribute. + return std::nullopt; + default: + // Target address space offset arithmetics + return clang::toTargetAddressSpace(langAS) + kFirstTargetASValue; + } + } + }]; +} + //===----------------------------------------------------------------------===// // AST Wrappers //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h index 37202322eac2..1dba48154b8d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h @@ -20,6 +20,8 @@ #include "clang/CIR/Interfaces/ASTAttrInterfaces.h" +#include "clang/CIR/Dialect/IR/CIROpsEnums.h" + //===----------------------------------------------------------------------===// // CIR StructType // diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 99267a88dc69..47de7623ffce 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -208,24 +208,34 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", `CIR.ptr` is a type returned by any op generating a pointer in C++. }]; - let parameters = (ins "mlir::Type":$pointee, - DefaultValuedParameter<"unsigned", "0">:$addrSpace); + let parameters = (ins + "mlir::Type":$pointee, + // FIXME(cir): Currently unable to directly use AddressSpaceAttr because of + // cyclic dep. Workaround with the top type and verifier. + OptionalParameter<"mlir::Attribute">:$addrSpace + ); let builders = [ TypeBuilderWithInferredContext<(ins - "mlir::Type":$pointee, CArg<"unsigned", "0">:$addrSpace), [{ - return Base::get(pointee.getContext(), pointee, addrSpace); + "mlir::Type":$pointee, + CArg<"mlir::Attribute", "{}">:$addrSpace), [{ + return $_get(pointee.getContext(), pointee, addrSpace); }]>, TypeBuilder<(ins - "mlir::Type":$pointee, CArg<"unsigned", "0">:$addrSpace), [{ - return Base::get($_ctxt, pointee, addrSpace); - }]>, + "mlir::Type":$pointee, + CArg<"mlir::Attribute", "{}">:$addrSpace), [{ + return $_get($_ctxt, pointee, addrSpace); + }]> ]; let assemblyFormat = [{ - `<` $pointee ( `,` `addrspace` `(` $addrSpace^ `)` )? `>` + `<` $pointee ( `,` `addrspace` `(` + custom($addrSpace)^ + `)` )? `>` }]; + let genVerifyDecl = 1; + let skipDefaultBuilders = 1; let extraClassDeclaration = [{ diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 1de2d2d1de53..a88c7acb93dc 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -156,6 +156,7 @@ struct MissingFeatures { static bool constantFoldsToSimpleInteger() { return false; } static bool checkFunctionCallABI() { return false; } static bool zeroInitializer() { return false; } + static bool targetLoweringInfoAddressSpaceMap() { return false; } static bool targetCodeGenInfoIsProtoCallVariadic() { return false; } static bool targetCodeGenInfoGetNullPointer() { return false; } static bool operandBundles() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index 8135fd0b7a95..d4c38430e2e0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -605,9 +605,7 @@ mlir::Type CIRGenTypes::ConvertType(QualType T) { const ReferenceType *RTy = cast(Ty); QualType ETy = RTy->getPointeeType(); auto PointeeType = convertTypeForMem(ETy); - ResultType = ::mlir::cir::PointerType::get( - Builder.getContext(), PointeeType, - Context.getTargetAddressSpace(ETy.getAddressSpace())); + ResultType = Builder.getPointerTo(PointeeType, ETy.getAddressSpace()); assert(ResultType && "Cannot get pointer type?"); break; } @@ -622,9 +620,7 @@ mlir::Type CIRGenTypes::ConvertType(QualType T) { // if (PointeeType->isVoidTy()) // PointeeType = Builder.getI8Type(); - ResultType = ::mlir::cir::PointerType::get( - Builder.getContext(), PointeeType, - Context.getTargetAddressSpace(ETy.getAddressSpace())); + ResultType = Builder.getPointerTo(PointeeType, ETy.getAddressSpace()); assert(ResultType && "Cannot get pointer type?"); break; } diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index 15b23b759d79..88d507363d18 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -45,6 +45,11 @@ parseFuncTypeArgs(mlir::AsmParser &p, llvm::SmallVector ¶ms, static void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, bool isVarArg); +static mlir::ParseResult parsePointerAddrSpace(mlir::AsmParser &p, + mlir::Attribute &addrSpaceAttr); +static void printPointerAddrSpace(mlir::AsmPrinter &p, + mlir::Attribute addrSpaceAttr); + //===----------------------------------------------------------------------===// // Get autogenerated stuff //===----------------------------------------------------------------------===// @@ -873,6 +878,65 @@ llvm::ArrayRef FuncType::getReturnTypes() const { bool FuncType::isVoid() const { return mlir::isa(getReturnType()); } +//===----------------------------------------------------------------------===// +// PointerType Definitions +//===----------------------------------------------------------------------===// + +mlir::LogicalResult +PointerType::verify(llvm::function_ref emitError, + mlir::Type pointee, mlir::Attribute addrSpace) { + if (addrSpace && !mlir::isa(addrSpace)) { + emitError() << "unexpected addrspace attribute type"; + return mlir::failure(); + } + return mlir::success(); +} + +mlir::ParseResult parsePointerAddrSpace(mlir::AsmParser &p, + mlir::Attribute &addrSpaceAttr) { + using mlir::cir::AddressSpaceAttr; + auto attrLoc = p.getCurrentLocation(); + + llvm::StringRef addrSpaceKind; + if (mlir::failed(p.parseOptionalKeyword(&addrSpaceKind))) { + p.emitError(attrLoc, "expected keyword for addrspace kind"); + return mlir::failure(); + } + + if (addrSpaceKind == AddressSpaceAttr::kTargetKeyword) { + int64_t targetValue = -1; + if (p.parseLess() || p.parseInteger(targetValue) || p.parseGreater()) { + return mlir::failure(); + } + addrSpaceAttr = AddressSpaceAttr::get( + p.getContext(), AddressSpaceAttr::kFirstTargetASValue + targetValue); + } else { + std::optional value = + AddressSpaceAttr::parseValueFromString(addrSpaceKind); + // not target AS, must be wrong keyword if no value + if (!value.has_value()) { + p.emitError(attrLoc, "invalid addrspace kind keyword: " + addrSpaceKind); + return mlir::failure(); + } + + addrSpaceAttr = AddressSpaceAttr::get(p.getContext(), *value); + } + + return mlir::success(); +} + +void printPointerAddrSpace(mlir::AsmPrinter &p, + mlir::Attribute rawAddrSpaceAttr) { + using mlir::cir::AddressSpaceAttr; + auto addrSpaceAttr = mlir::cast(rawAddrSpaceAttr); + if (addrSpaceAttr.isTarget()) { + p << AddressSpaceAttr::kTargetKeyword << "<" + << addrSpaceAttr.getTargetValue() << ">"; + } else { + p << AddressSpaceAttr::stringifyValue(addrSpaceAttr.getValue()); + } +} + //===----------------------------------------------------------------------===// // CIR Dialect //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 4ba78ac719e3..ba348f8a25ee 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -3335,8 +3335,20 @@ void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout) { converter.addConversion([&](mlir::cir::PointerType type) -> mlir::Type { // Drop pointee type since LLVM dialect only allows opaque pointers. + + auto addrSpace = + mlir::cast_if_present(type.getAddrSpace()); + // null addrspace attribute indicates the default addrspace + if (!addrSpace) + return mlir::LLVM::LLVMPointerType::get(type.getContext()); + + // TODO(cir): Query the target-specific address space map to lower other ASs + // like `opencl_private`. + assert(!MissingFeatures::targetLoweringInfoAddressSpaceMap()); + assert(addrSpace.isTarget() && "NYI"); + return mlir::LLVM::LLVMPointerType::get(type.getContext(), - type.getAddrSpace()); + addrSpace.getTargetValue()); }); converter.addConversion([&](mlir::cir::DataMemberType type) -> mlir::Type { return mlir::IntegerType::get(type.getContext(), diff --git a/clang/test/CIR/CodeGen/OpenCL/addrspace-alloca.cl b/clang/test/CIR/CodeGen/OpenCL/addrspace-alloca.cl index baa14874765b..7650a08968e4 100644 --- a/clang/test/CIR/CodeGen/OpenCL/addrspace-alloca.cl +++ b/clang/test/CIR/CodeGen/OpenCL/addrspace-alloca.cl @@ -3,10 +3,13 @@ // RUN: %clang_cc1 -cl-std=CL3.0 -O0 -fclangir -emit-llvm -triple spirv64-unknown-unknown %s -o %t.ll // RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM -// CIR: cir.func @func(%arg0: !cir.ptr +// Lowering of language-specific AS not supported +// XFAIL: * + +// CIR: cir.func @func(%arg0: !cir.ptr)> // LLVM: @func(ptr addrspace(3) kernel void func(local int *p) { - // CIR-NEXT: %[[#ALLOCA_P:]] = cir.alloca !cir.ptr, !cir.ptr>, ["p", init] {alignment = 8 : i64} + // CIR-NEXT: %[[#ALLOCA_P:]] = cir.alloca !cir.ptr)>, !cir.ptr)>>, ["p", init] {alignment = 8 : i64} // LLVM-NEXT: %[[#ALLOCA_P:]] = alloca ptr addrspace(3), i64 1, align 8 int x; @@ -14,11 +17,11 @@ kernel void func(local int *p) { // LLVM-NEXT: %[[#ALLOCA_X:]] = alloca i32, i64 1, align 4 global char *b; - // CIR-NEXT: %[[#ALLOCA_B:]] = cir.alloca !cir.ptr, !cir.ptr>, ["b"] {alignment = 8 : i64} + // CIR-NEXT: %[[#ALLOCA_B:]] = cir.alloca !cir.ptr)>, !cir.ptr)>>, ["b"] {alignment = 8 : i64} // LLVM-NEXT: %[[#ALLOCA_B:]] = alloca ptr addrspace(1), i64 1, align 8 // Store of the argument `p` - // CIR-NEXT: cir.store %arg0, %[[#ALLOCA_P]] : !cir.ptr, !cir.ptr> + // CIR-NEXT: cir.store %arg0, %[[#ALLOCA_P]] : !cir.ptr)>, !cir.ptr)>> // LLVM-NEXT: store ptr addrspace(3) %{{[0-9]+}}, ptr %[[#ALLOCA_P]], align 8 return; diff --git a/clang/test/CIR/CodeGen/OpenCL/spirv-target.cl b/clang/test/CIR/CodeGen/OpenCL/spirv-target.cl index 44c59fc3534c..eb6d2028d1ba 100644 --- a/clang/test/CIR/CodeGen/OpenCL/spirv-target.cl +++ b/clang/test/CIR/CodeGen/OpenCL/spirv-target.cl @@ -4,6 +4,9 @@ // RUN: %clang_cc1 -cl-std=CL3.0 -fclangir -emit-llvm -triple spirv64-unknown-unknown %s -o %t_64.ll // RUN: FileCheck --input-file=%t_64.ll %s --check-prefix=LLVM-SPIRV64 +// Lowering of language-specific AS not supported +// XFAIL: * + // CIR-SPIRV64: cir.triple = "spirv64-unknown-unknown" // LLVM-SPIRV64: target triple = "spirv64-unknown-unknown" diff --git a/clang/test/CIR/CodeGen/address-space-conversion.cpp b/clang/test/CIR/CodeGen/address-space-conversion.cpp index 1490a174892a..e618e9ac21fe 100644 --- a/clang/test/CIR/CodeGen/address-space-conversion.cpp +++ b/clang/test/CIR/CodeGen/address-space-conversion.cpp @@ -14,9 +14,9 @@ using ri2_t = int __attribute__((address_space(2))) &; void test_ptr() { pi1_t ptr1; pi2_t ptr2 = (pi2_t)ptr1; - // CIR: %[[#PTR1:]] = cir.load %{{[0-9]+}} : !cir.ptr>, !cir.ptr - // CIR-NEXT: %[[#CAST:]] = cir.cast(address_space, %[[#PTR1]] : !cir.ptr), !cir.ptr - // CIR-NEXT: cir.store %[[#CAST]], %{{[0-9]+}} : !cir.ptr, !cir.ptr> + // CIR: %[[#PTR1:]] = cir.load %{{[0-9]+}} : !cir.ptr)>>, !cir.ptr)> + // CIR-NEXT: %[[#CAST:]] = cir.cast(address_space, %[[#PTR1]] : !cir.ptr)>), !cir.ptr)> + // CIR-NEXT: cir.store %[[#CAST]], %{{[0-9]+}} : !cir.ptr)>, !cir.ptr)>> // LLVM: %[[#PTR1:]] = load ptr addrspace(1), ptr %{{[0-9]+}}, align 8 // LLVM-NEXT: %[[#CAST:]] = addrspacecast ptr addrspace(1) %[[#PTR1]] to ptr addrspace(2) @@ -29,11 +29,11 @@ void test_ref() { pi1_t ptr; ri1_t ref1 = *ptr; ri2_t ref2 = (ri2_t)ref1; - // CIR: %[[#DEREF:]] = cir.load deref %{{[0-9]+}} : !cir.ptr>, !cir.ptr - // CIR-NEXT: cir.store %[[#DEREF]], %[[#ALLOCAREF1:]] : !cir.ptr, !cir.ptr> - // CIR-NEXT: %[[#REF1:]] = cir.load %[[#ALLOCAREF1]] : !cir.ptr>, !cir.ptr - // CIR-NEXT: %[[#CAST:]] = cir.cast(address_space, %[[#REF1]] : !cir.ptr), !cir.ptr - // CIR-NEXT: cir.store %[[#CAST]], %{{[0-9]+}} : !cir.ptr, !cir.ptr> + // CIR: %[[#DEREF:]] = cir.load deref %{{[0-9]+}} : !cir.ptr)>>, !cir.ptr)> + // CIR-NEXT: cir.store %[[#DEREF]], %[[#ALLOCAREF1:]] : !cir.ptr)>, !cir.ptr)>> + // CIR-NEXT: %[[#REF1:]] = cir.load %[[#ALLOCAREF1]] : !cir.ptr)>>, !cir.ptr)> + // CIR-NEXT: %[[#CAST:]] = cir.cast(address_space, %[[#REF1]] : !cir.ptr)>), !cir.ptr)> + // CIR-NEXT: cir.store %[[#CAST]], %{{[0-9]+}} : !cir.ptr)>, !cir.ptr)>> // LLVM: %[[#DEREF:]] = load ptr addrspace(1), ptr %{{[0-9]+}}, align 8 // LLVM-NEXT: store ptr addrspace(1) %[[#DEREF]], ptr %[[#ALLOCAREF1:]], align 8 @@ -47,10 +47,10 @@ void test_ref() { void test_nullptr() { constexpr pi1_t null1 = nullptr; pi2_t ptr = (pi2_t)null1; - // CIR: %[[#NULL1:]] = cir.const #cir.ptr : !cir.ptr - // CIR-NEXT: cir.store %[[#NULL1]], %{{[0-9]+}} : !cir.ptr, !cir.ptr> - // CIR-NEXT: %[[#NULL2:]] = cir.const #cir.ptr : !cir.ptr - // CIR-NEXT: cir.store %[[#NULL2]], %{{[0-9]+}} : !cir.ptr, !cir.ptr> + // CIR: %[[#NULL1:]] = cir.const #cir.ptr : !cir.ptr)> + // CIR-NEXT: cir.store %[[#NULL1]], %{{[0-9]+}} : !cir.ptr)>, !cir.ptr)>> + // CIR-NEXT: %[[#NULL2:]] = cir.const #cir.ptr : !cir.ptr)> + // CIR-NEXT: cir.store %[[#NULL2]], %{{[0-9]+}} : !cir.ptr)>, !cir.ptr)>> // LLVM: store ptr addrspace(1) null, ptr %{{[0-9]+}}, align 8 // LLVM-NEXT: store ptr addrspace(2) null, ptr %{{[0-9]+}}, align 8 @@ -58,9 +58,9 @@ void test_nullptr() { void test_side_effect(pi1_t b) { pi2_t p = (pi2_t)(*b++, (int*)0); - // CIR: %{{[0-9]+}} = cir.ptr_stride(%{{[0-9]+}} : !cir.ptr, %{{[0-9]+}} : !s32i), !cir.ptr - // CIR: %[[#CAST:]] = cir.const #cir.ptr : !cir.ptr - // CIR-NEXT: cir.store %[[#CAST]], %{{[0-9]+}} : !cir.ptr, !cir.ptr> + // CIR: %{{[0-9]+}} = cir.ptr_stride(%{{[0-9]+}} : !cir.ptr)>, %{{[0-9]+}} : !s32i), !cir.ptr)> + // CIR: %[[#CAST:]] = cir.const #cir.ptr : !cir.ptr)> + // CIR-NEXT: cir.store %[[#CAST]], %{{[0-9]+}} : !cir.ptr)>, !cir.ptr)>> // LLVM: %{{[0-9]+}} = getelementptr i32, ptr addrspace(1) %{{[0-9]+}}, i64 1 // LLVM: store ptr addrspace(2) null, ptr %{{[0-9]+}}, align 8 diff --git a/clang/test/CIR/CodeGen/address-space.c b/clang/test/CIR/CodeGen/address-space.c index c743b2b723d6..100cdaaaa753 100644 --- a/clang/test/CIR/CodeGen/address-space.c +++ b/clang/test/CIR/CodeGen/address-space.c @@ -3,8 +3,20 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll // RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM -// CIR: cir.func {{@.*foo.*}}(%arg0: !cir.ptr +// CIR: cir.func {{@.*foo.*}}(%arg0: !cir.ptr)> // LLVM: define void @foo(ptr addrspace(1) %0) void foo(int __attribute__((address_space(1))) *arg) { return; } + +// CIR: cir.func {{@.*bar.*}}(%arg0: !cir.ptr)> +// LLVM: define void @bar(ptr %0) +void bar(int __attribute__((address_space(0))) *arg) { + return; +} + +// CIR: cir.func {{@.*baz.*}}(%arg0: !cir.ptr +// LLVM: define void @baz(ptr %0) +void baz(int *arg) { + return; +} diff --git a/clang/test/CIR/IR/address-space.cir b/clang/test/CIR/IR/address-space.cir index dde39bdd4d73..b7472876f56d 100644 --- a/clang/test/CIR/IR/address-space.cir +++ b/clang/test/CIR/IR/address-space.cir @@ -4,8 +4,13 @@ !s32i = !cir.int module { - // CHECK: @test_addrspace_assembly_format(%arg0: !cir.ptr) - cir.func @test_addrspace_assembly_format(%arg0: !cir.ptr) { + // CHECK: @test_format1(%arg0: !cir.ptr)>) + cir.func @test_format1(%arg0: !cir.ptr)>) { + cir.return + } + + // CHECK: @test_format2(%arg0: !cir.ptr) + cir.func @test_format2(%arg0: !cir.ptr) { cir.return } } diff --git a/clang/test/CIR/IR/cast.cir b/clang/test/CIR/IR/cast.cir index 6511529b32ee..8523439a7c2c 100644 --- a/clang/test/CIR/IR/cast.cir +++ b/clang/test/CIR/IR/cast.cir @@ -17,7 +17,7 @@ module { } cir.func @addrspace_cast(%arg0: !cir.ptr) { - %0 = cir.cast(address_space, %arg0 : !cir.ptr), !cir.ptr + %0 = cir.cast(address_space, %arg0 : !cir.ptr), !cir.ptr)> cir.return } } @@ -30,4 +30,4 @@ module { // CHECK: %0 = cir.cast(bitcast, %arg0 : !cir.ptr), !cir.ptr // CHECK: cir.func @addrspace_cast -// CHECK: %0 = cir.cast(address_space, %arg0 : !cir.ptr), !cir.ptr +// CHECK: %0 = cir.cast(address_space, %arg0 : !cir.ptr), !cir.ptr)> diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index 63a6fd97b4c9..50ee1d3fed34 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -302,16 +302,16 @@ cir.func @cast24(%p : !u32i) { !u32i = !cir.int !u64i = !cir.int -cir.func @cast25(%p : !cir.ptr) { - %0 = cir.cast(address_space, %p : !cir.ptr), !cir.ptr // expected-error {{requires two types differ in addrspace only}} +cir.func @cast25(%p : !cir.ptr)>) { + %0 = cir.cast(address_space, %p : !cir.ptr)>), !cir.ptr)> // expected-error {{requires two types differ in addrspace only}} cir.return } // ----- !u64i = !cir.int -cir.func @cast26(%p : !cir.ptr) { - %0 = cir.cast(address_space, %p : !cir.ptr), !u64i // expected-error {{requires !cir.ptr type for source and result}} +cir.func @cast26(%p : !cir.ptr)>) { + %0 = cir.cast(address_space, %p : !cir.ptr)>), !u64i // expected-error {{requires !cir.ptr type for source and result}} cir.return } @@ -319,7 +319,7 @@ cir.func @cast26(%p : !cir.ptr) { !u64i = !cir.int cir.func @cast27(%p : !u64i) { - %0 = cir.cast(address_space, %p : !u64i), !cir.ptr // expected-error {{requires !cir.ptr type for source and result}} + %0 = cir.cast(address_space, %p : !u64i), !cir.ptr)> // expected-error {{requires !cir.ptr type for source and result}} cir.return } @@ -1143,3 +1143,31 @@ cir.func @bad_goto() -> () { cir.label "label" cir.return } + +// ----- + +!u64i = !cir.int +cir.func @address_space1(%p : !cir.ptr) { // expected-error {{expected keyword for addrspace kind}} + cir.return +} + +// ----- + +!u64i = !cir.int +cir.func @address_space2(%p : !cir.ptr)>) { // expected-error {{expected integer value}} + cir.return +} + +// ----- + +!u64i = !cir.int +cir.func @address_space3(%p : !cir.ptr) { // expected-error {{expected '<'}} + cir.return +} + +// ----- + +!u64i = !cir.int +cir.func @address_space4(%p : !cir.ptr) { // expected-error {{invalid addrspace kind keyword: foobar}} + cir.return +} diff --git a/clang/test/CIR/Lowering/address-space.cir b/clang/test/CIR/Lowering/address-space.cir index c7d5a84829c4..b7328713e9b9 100644 --- a/clang/test/CIR/Lowering/address-space.cir +++ b/clang/test/CIR/Lowering/address-space.cir @@ -12,9 +12,16 @@ module { } // LLVM: define void @bar(ptr addrspace(1) %0) - cir.func @bar(%arg0: !cir.ptr) { + cir.func @bar(%arg0: !cir.ptr)>) { // LLVM-NEXT: alloca ptr addrspace(1) - %0 = cir.alloca !cir.ptr, !cir.ptr>, ["arg", init] {alignment = 8 : i64} + %0 = cir.alloca !cir.ptr)>, !cir.ptr)>>, ["arg", init] {alignment = 8 : i64} + cir.return + } + + // LLVM: define void @baz(ptr %0) + cir.func @baz(%arg0: !cir.ptr)>) { + // LLVM-NEXT: alloca ptr, + %0 = cir.alloca !cir.ptr)>, !cir.ptr)>>, ["arg", init] {alignment = 8 : i64} cir.return } } diff --git a/clang/test/CIR/Transforms/merge-cleanups.cir b/clang/test/CIR/Transforms/merge-cleanups.cir index 9a87ad4b0968..92cf22b1abef 100644 --- a/clang/test/CIR/Transforms/merge-cleanups.cir +++ b/clang/test/CIR/Transforms/merge-cleanups.cir @@ -128,11 +128,11 @@ module { // Should remove redundant address space casts. // CHECK-LABEL: @addrspacecastfold - // CHECK: %[[ARG0:.+]]: !cir.ptr - // CHECK: cir.return %[[ARG0]] : !cir.ptr - cir.func @addrspacecastfold(%arg0: !cir.ptr) -> !cir.ptr { - %0 = cir.cast(address_space, %arg0: !cir.ptr), !cir.ptr - cir.return %0 : !cir.ptr + // CHECK: %[[ARG0:.+]]: !cir.ptr)> + // CHECK: cir.return %[[ARG0]] : !cir.ptr)> + cir.func @addrspacecastfold(%arg0: !cir.ptr)>) -> !cir.ptr)> { + %0 = cir.cast(address_space, %arg0: !cir.ptr)>), !cir.ptr)> + cir.return %0 : !cir.ptr)> } }