diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index d6b7e7e6453e..19c0eff2165c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1100,7 +1100,7 @@ RValue CIRGenFunction::buildBuiltinExpr(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(!MissingFeatures::addressSpace()); - auto AAS = builder.getAddrSpaceAttr(getASTAllocaAddressSpace()); + auto AAS = getCIRAllocaAddressSpace(); auto EAS = builder.getAddrSpaceAttr( E->getType()->getPointeeType().getAddressSpace()); if (EAS != AAS) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 0aace0ec1d98..c4ebe55a7edc 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -2752,7 +2752,10 @@ mlir::Value CIRGenFunction::buildAlloca(StringRef name, mlir::Type ty, mlir::Location loc, CharUnits alignment, mlir::OpBuilder::InsertPoint ip, mlir::Value arraySize) { - auto localVarPtrTy = mlir::cir::PointerType::get(builder.getContext(), ty); + // CIR uses its own alloca AS rather than follow the target data layout like + // original CodeGen. The data layout awareness should be done in the lowering + // pass instead. + auto localVarPtrTy = builder.getPointerTo(ty, getCIRAllocaAddressSpace()); auto alignIntAttr = CGM.getSize(alignment); mlir::Value addr; @@ -2977,7 +2980,9 @@ Address CIRGenFunction::CreateTempAlloca(mlir::Type Ty, CharUnits Align, // be different from the type defined by the language. For example, // in C++ the auto variables are in the default address space. Therefore // cast alloca to the default address space when necessary. - if (getASTAllocaAddressSpace() != LangAS::Default) { + if (auto ASTAS = + builder.getAddrSpaceAttr(CGM.getLangTempAllocaAddressSpace()); + getCIRAllocaAddressSpace() != ASTAS) { llvm_unreachable("Requires address space cast which is NYI"); } return Address(V, Ty, Align); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 7f1a868d93eb..72a4d55f8582 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -159,7 +159,7 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context, AllocaInt8PtrTy = UInt8PtrTy; // TODO: GlobalsInt8PtrTy // TODO: ConstGlobalsPtrTy - ASTAllocaAddressSpace = getTargetCIRGenInfo().getASTAllocaAddressSpace(); + CIRAllocaAddressSpace = getTargetCIRGenInfo().getCIRAllocaAddressSpace(); PtrDiffTy = ::mlir::cir::IntType::get( builder.getContext(), astCtx.getTargetInfo().getMaxPointerWidth(), @@ -1403,6 +1403,16 @@ LangAS CIRGenModule::getGlobalConstantAddressSpace() const { return LangAS::Default; } +// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen. +LangAS CIRGenModule::getLangTempAllocaAddressSpace() const { + if (getLangOpts().OpenCL) + return LangAS::opencl_private; + if (getLangOpts().SYCLIsDevice || getLangOpts().CUDAIsDevice || + (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice)) + llvm_unreachable("NYI"); + return LangAS::Default; +} + static mlir::cir::GlobalOp generateStringLiteral(mlir::Location loc, mlir::TypedAttr C, mlir::cir::GlobalLinkageKind LT, CIRGenModule &CGM, diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 52704261110d..b46befcc949a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -335,6 +335,12 @@ class CIRGenModule : public CIRGenTypeCache { /// in AST is always in default address space. LangAS getGlobalConstantAddressSpace() const; + /// Returns the address space for temporary allocations in the language. This + /// ensures that the allocated variable's address space matches the + /// expectations of the AST, rather than using the target's allocation address + /// space, which may lead to type mismatches in other parts of the IR. + LangAS getLangTempAllocaAddressSpace() const; + /// Set attributes which are common to any form of a global definition (alias, /// Objective-C method, function, global variable). /// diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h index 0930b17d55e3..e07e46be68e5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h +++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h @@ -18,6 +18,7 @@ #include "clang/AST/CharUnits.h" #include "clang/Basic/AddressSpaces.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/MissingFeatures.h" namespace cir { @@ -108,7 +109,7 @@ struct CIRGenTypeCache { // unsigned char SizeAlignInBytes; // }; - clang::LangAS ASTAllocaAddressSpace; + mlir::cir::AddressSpaceAttr CIRAllocaAddressSpace; // clang::CharUnits getSizeSize() const { // return clang::CharUnits::fromQuantity(SizeSizeInBytes); @@ -123,13 +124,8 @@ struct CIRGenTypeCache { return clang::CharUnits::fromQuantity(PointerAlignInBytes); } - clang::LangAS getASTAllocaAddressSpace() const { - // Address spaces are not yet fully supported, but the usage of the default - // alloca address space can be used for now only for comparison with the - // default address space. - assert(!MissingFeatures::addressSpace()); - assert(ASTAllocaAddressSpace == clang::LangAS::Default); - return ASTAllocaAddressSpace; + mlir::cir::AddressSpaceAttr getCIRAllocaAddressSpace() const { + return CIRAllocaAddressSpace; } }; diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp index ba81ad88c435..0016f2200b37 100644 --- a/clang/lib/CIR/CodeGen/TargetInfo.cpp +++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp @@ -263,6 +263,12 @@ class CommonSPIRTargetCIRGenInfo : public TargetCIRGenInfo { CommonSPIRTargetCIRGenInfo(std::unique_ptr ABIInfo) : TargetCIRGenInfo(std::move(ABIInfo)) {} + mlir::cir::AddressSpaceAttr getCIRAllocaAddressSpace() const override { + return mlir::cir::AddressSpaceAttr::get( + &getABIInfo().CGT.getMLIRContext(), + mlir::cir::AddressSpaceAttr::Kind::offload_private); + } + unsigned getOpenCLKernelCallingConv() const override { return llvm::CallingConv::SPIR_KERNEL; } diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h index 21cf9b78d35e..1b4dbea110fc 100644 --- a/clang/lib/CIR/CodeGen/TargetInfo.h +++ b/clang/lib/CIR/CodeGen/TargetInfo.h @@ -62,9 +62,11 @@ class TargetCIRGenInfo { std::vector &ResultRegDests, std::string &AsmString, unsigned NumOutputs) const {} - /// Get the AST address space for alloca. - virtual clang::LangAS getASTAllocaAddressSpace() const { - return clang::LangAS::Default; + /// Get the CIR address space for alloca. + virtual mlir::cir::AddressSpaceAttr getCIRAllocaAddressSpace() const { + // Return the null attribute, which means the target does not care about the + // alloca address space. + return {}; } /// Perform address space cast of an expression of pointer type. diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 0c512492a825..46cc8e69636e 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -881,7 +881,8 @@ class CIRAllocaLowering typeConverter->convertType(rewriter.getIndexType()), rewriter.getIntegerAttr(rewriter.getIndexType(), 1)); auto elementTy = getTypeConverter()->convertType(op.getAllocaType()); - auto resultTy = mlir::LLVM::LLVMPointerType::get(getContext()); + auto resultTy = getTypeConverter()->convertType(op.getResult().getType()); + // TODO: Verification between the CIR alloca AS and the one from data layout rewriter.replaceOpWithNewOp( op, resultTy, elementTy, size, op.getAlignmentAttr().getInt()); return mlir::success(); diff --git a/clang/test/CIR/CodeGen/OpenCL/addrspace-alloca.cl b/clang/test/CIR/CodeGen/OpenCL/addrspace-alloca.cl index 58edf5c2791e..c64b5015f369 100644 --- a/clang/test/CIR/CodeGen/OpenCL/addrspace-alloca.cl +++ b/clang/test/CIR/CodeGen/OpenCL/addrspace-alloca.cl @@ -7,20 +7,28 @@ // 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, addrspace(offload_private)>, ["p", init] {alignment = 8 : i64} // LLVM-NEXT: %[[#ALLOCA_P:]] = alloca ptr addrspace(3), i64 1, align 8 int x; - // CIR-NEXT: %[[#ALLOCA_X:]] = cir.alloca !s32i, !cir.ptr, ["x"] {alignment = 4 : i64} + // CIR-NEXT: %[[#ALLOCA_X:]] = cir.alloca !s32i, !cir.ptr, ["x"] {alignment = 4 : i64} // 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, addrspace(offload_private)>, ["b"] {alignment = 8 : i64} // LLVM-NEXT: %[[#ALLOCA_B:]] = alloca ptr addrspace(1), i64 1, align 8 + private int *ptr; + // CIR-NEXT: %[[#ALLOCA_PTR:]] = cir.alloca !cir.ptr, !cir.ptr, addrspace(offload_private)>, ["ptr"] {alignment = 8 : i64} + // LLVM-NEXT: %[[#ALLOCA_PTR:]] = alloca ptr, 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, addrspace(offload_private)> // LLVM-NEXT: store ptr addrspace(3) %{{[0-9]+}}, ptr %[[#ALLOCA_P]], align 8 + ptr = &x; + // CIR-NEXT: cir.store %[[#ALLOCA_X]], %[[#ALLOCA_PTR]] : !cir.ptr, !cir.ptr, addrspace(offload_private)> + // LLVM-NEXT: store ptr %[[#ALLOCA_X]], ptr %[[#ALLOCA_PTR]] + return; }