diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp index 52cf2d182c4a..9a08ccd0d1ff 100644 --- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp @@ -411,7 +411,7 @@ void CIRGenFunction::buildVarDecl(const VarDecl &D) { } if (D.getType().getAddressSpace() == LangAS::opencl_local) - llvm_unreachable("OpenCL and address space are NYI"); + return CGM.getOpenCLRuntime().buildWorkGroupLocalVarDecl(*this, D); assert(D.hasLocalStorage()); @@ -465,19 +465,19 @@ CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &D, Name = getStaticDeclName(*this, D); mlir::Type LTy = getTypes().convertTypeForMem(Ty); - assert(!MissingFeatures::addressSpace()); + mlir::cir::AddressSpaceAttr AS = + builder.getAddrSpaceAttr(getGlobalVarAddressSpace(&D)); // OpenCL variables in local address space and CUDA shared // variables cannot have an initializer. mlir::Attribute Init = nullptr; - if (Ty.getAddressSpace() == LangAS::opencl_local || - D.hasAttr() || D.hasAttr()) - llvm_unreachable("OpenCL & CUDA are NYI"); - else + if (D.hasAttr() || D.hasAttr()) + llvm_unreachable("CUDA is NYI"); + else if (Ty.getAddressSpace() != LangAS::opencl_local) Init = builder.getZeroInitAttr(getTypes().ConvertType(Ty)); mlir::cir::GlobalOp GV = builder.createVersionedGlobal( - getModule(), getLoc(D.getLocation()), Name, LTy, false, Linkage); + getModule(), getLoc(D.getLocation()), Name, LTy, false, Linkage, AS); // TODO(cir): infer visibility from linkage in global op builder. GV.setVisibility(getMLIRVisibilityFromCIRLinkage(Linkage)); GV.setInitialValueAttr(Init); @@ -492,7 +492,8 @@ CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &D, setGVProperties(GV, &D); // Make sure the result is of the correct type. - assert(!MissingFeatures::addressSpace()); + if (AS != builder.getAddrSpaceAttr(Ty.getAddressSpace())) + llvm_unreachable("address space cast NYI"); // Ensure that the static local gets initialized by making sure the parent // function gets emitted eventually. diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index d5a2ddbc8f19..21792ce41e25 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -165,6 +165,10 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context, builder.getContext(), astCtx.getTargetInfo().getMaxPointerWidth(), /*isSigned=*/true); + if (langOpts.OpenCL) { + createOpenCLRuntime(); + } + mlir::cir::sob::SignedOverflowBehavior sob; switch (langOpts.getSignedOverflowBehavior()) { case clang::LangOptions::SignedOverflowBehaviorTy::SOB_Defined: diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 825735d28717..d4d3339f3fdf 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -15,6 +15,7 @@ #include "CIRGenBuilder.h" #include "CIRGenCall.h" +#include "CIRGenOpenCLRuntime.h" #include "CIRGenTypeCache.h" #include "CIRGenTypes.h" #include "CIRGenVTables.h" @@ -102,6 +103,9 @@ class CIRGenModule : public CIRGenTypeCache { /// Holds information about C++ vtables. CIRGenVTables VTables; + /// Holds the OpenCL runtime + std::unique_ptr openCLRuntime; + /// Holds the OpenMP runtime std::unique_ptr openMPRuntime; @@ -700,6 +704,16 @@ class CIRGenModule : public CIRGenTypeCache { /// Print out an error that codegen doesn't support the specified decl yet. void ErrorUnsupported(const Decl *D, const char *Type); + /// Return a reference to the configured OpenMP runtime. + CIRGenOpenCLRuntime &getOpenCLRuntime() { + assert(openCLRuntime != nullptr); + return *openCLRuntime; + } + + void createOpenCLRuntime() { + openCLRuntime.reset(new CIRGenOpenCLRuntime(*this)); + } + /// Return a reference to the configured OpenMP runtime. CIRGenOpenMPRuntime &getOpenMPRuntime() { assert(openMPRuntime != nullptr); diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenCLRuntime.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenCLRuntime.cpp new file mode 100644 index 000000000000..863caf8629d2 --- /dev/null +++ b/clang/lib/CIR/CodeGen/CIRGenOpenCLRuntime.cpp @@ -0,0 +1,29 @@ +//===-- CIRGenOpenCLRuntime.cpp - Interface to OpenCL Runtimes ------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This provides an abstract class for OpenCL CIR generation. Concrete +// subclasses of this implement code generation for specific OpenCL +// runtime libraries. +// +//===----------------------------------------------------------------------===// + +#include "CIRGenOpenCLRuntime.h" +#include "CIRGenFunction.h" + +#include "clang/CIR/Dialect/IR/CIROpsEnums.h" + +using namespace clang; +using namespace cir; + +CIRGenOpenCLRuntime::~CIRGenOpenCLRuntime() {} + +void CIRGenOpenCLRuntime::buildWorkGroupLocalVarDecl(CIRGenFunction &CGF, + const VarDecl &D) { + return CGF.buildStaticVarDecl(D, + mlir::cir::GlobalLinkageKind::InternalLinkage); +} diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenCLRuntime.h b/clang/lib/CIR/CodeGen/CIRGenOpenCLRuntime.h new file mode 100644 index 000000000000..891b5bb5fb79 --- /dev/null +++ b/clang/lib/CIR/CodeGen/CIRGenOpenCLRuntime.h @@ -0,0 +1,46 @@ +//===-- CIRGenOpenCLRuntime.h - Interface to OpenCL Runtimes -----*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This provides an abstract class for OpenCL CIR generation. Concrete +// subclasses of this implement code generation for specific OpenCL +// runtime libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_CIR_CIRGENOPENCLRUNTIME_H +#define LLVM_CLANG_LIB_CIR_CIRGENOPENCLRUNTIME_H + +namespace clang { + +class VarDecl; + +} // namespace clang + +namespace cir { + +class CIRGenFunction; +class CIRGenModule; + +class CIRGenOpenCLRuntime { +protected: + CIRGenModule &CGM; + +public: + CIRGenOpenCLRuntime(CIRGenModule &CGM) : CGM(CGM) {} + virtual ~CIRGenOpenCLRuntime(); + + /// Emit the IR required for a work-group-local variable declaration, and add + /// an entry to CGF's LocalDeclMap for D. The base class does this using + /// CIRGenFunction::EmitStaticVarDecl to emit an internal global for D. + virtual void buildWorkGroupLocalVarDecl(CIRGenFunction &CGF, + const clang::VarDecl &D); +}; + +} // namespace cir + +#endif // LLVM_CLANG_LIB_CIR_CIRGENOPENCLRUNTIME_H diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt index 552555779d46..97a8ad4f5ea8 100644 --- a/clang/lib/CIR/CodeGen/CMakeLists.txt +++ b/clang/lib/CIR/CodeGen/CMakeLists.txt @@ -31,6 +31,7 @@ add_clang_library(clangCIR CIRGenFunction.cpp CIRGenItaniumCXXABI.cpp CIRGenModule.cpp + CIRGenOpenCLRuntime.cpp CIRGenOpenCL.cpp CIRGenOpenMPRuntime.cpp CIRGenStmt.cpp diff --git a/clang/test/CIR/CodeGen/OpenCL/static-vardecl.cl b/clang/test/CIR/CodeGen/OpenCL/static-vardecl.cl new file mode 100644 index 000000000000..9ad8277012c4 --- /dev/null +++ b/clang/test/CIR/CodeGen/OpenCL/static-vardecl.cl @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -cl-std=CL3.0 -O0 -fclangir -emit-cir -triple spirv64-unknown-unknown %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR +// 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 + +kernel void test_static(int i) { + static global int b = 15; + // CIR-DAG: cir.global "private" internal dsolocal addrspace(offload_global) @test_static.b = #cir.int<15> : !s32i {alignment = 4 : i64} + // LLVM-DAG: @test_static.b = internal addrspace(1) global i32 15 + + local int c; + // CIR-DAG: cir.global "private" internal dsolocal addrspace(offload_local) @test_static.c : !s32i {alignment = 4 : i64} + // LLVM-DAG: @test_static.c = internal addrspace(3) global i32 undef + + // CIR-DAG: %[[#ADDRB:]] = cir.get_global @test_static.b : !cir.ptr + // CIR-DAG: %[[#ADDRC:]] = cir.get_global @test_static.c : !cir.ptr + + c = b; + // CIR: %[[#LOADB:]] = cir.load %[[#ADDRB]] : !cir.ptr, !s32i + // CIR-NEXT: cir.store %[[#LOADB]], %[[#ADDRC]] : !s32i, !cir.ptr + + // LLVM: %[[#LOADB:]] = load i32, ptr addrspace(1) @test_static.b, align 4 + // LLVM-NEXT: store i32 %[[#LOADB]], ptr addrspace(3) @test_static.c, align 4 +}