Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CIR][CodeGen] Set address space for OpenCL static and local-qualified variables #792

Merged
merged 4 commits into from
Aug 15, 2024
Merged
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
17 changes: 9 additions & 8 deletions clang/lib/CIR/CodeGen/CIRGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand Down Expand Up @@ -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<CUDASharedAttr>() || D.hasAttr<LoaderUninitializedAttr>())
llvm_unreachable("OpenCL & CUDA are NYI");
else
if (D.hasAttr<CUDASharedAttr>() || D.hasAttr<LoaderUninitializedAttr>())
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);
Expand All @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "CIRGenBuilder.h"
#include "CIRGenCall.h"
#include "CIRGenOpenCLRuntime.h"
#include "CIRGenTypeCache.h"
#include "CIRGenTypes.h"
#include "CIRGenVTables.h"
Expand Down Expand Up @@ -102,6 +103,9 @@ class CIRGenModule : public CIRGenTypeCache {
/// Holds information about C++ vtables.
CIRGenVTables VTables;

/// Holds the OpenCL runtime
std::unique_ptr<CIRGenOpenCLRuntime> openCLRuntime;

/// Holds the OpenMP runtime
std::unique_ptr<CIRGenOpenMPRuntime> openMPRuntime;

Expand Down Expand Up @@ -697,6 +701,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);
Expand Down
29 changes: 29 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenOpenCLRuntime.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
46 changes: 46 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenOpenCLRuntime.h
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions clang/lib/CIR/CodeGen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ add_clang_library(clangCIR
CIRGenFunction.cpp
CIRGenItaniumCXXABI.cpp
CIRGenModule.cpp
CIRGenOpenCLRuntime.cpp
CIRGenOpenCL.cpp
CIRGenOpenMPRuntime.cpp
CIRGenStmt.cpp
Expand Down
24 changes: 24 additions & 0 deletions clang/test/CIR/CodeGen/OpenCL/static-vardecl.cl
Original file line number Diff line number Diff line change
@@ -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<!s32i, addrspace(offload_global)>
// CIR-DAG: %[[#ADDRC:]] = cir.get_global @test_static.c : !cir.ptr<!s32i, addrspace(offload_local)>

c = b;
// CIR: %[[#LOADB:]] = cir.load %[[#ADDRB]] : !cir.ptr<!s32i, addrspace(offload_global)>, !s32i
// CIR-NEXT: cir.store %[[#LOADB]], %[[#ADDRC]] : !s32i, !cir.ptr<!s32i, addrspace(offload_local)>

// 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
}