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][OpenMP] Initial commit for OpenMP support in CIR #382

Merged
merged 6 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
11 changes: 5 additions & 6 deletions clang/lib/CIR/CodeGen/CIRGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "CIRGenBuilder.h"
#include "CIRGenCstEmitter.h"
#include "CIRGenFunction.h"
#include "CIRGenOpenMPRuntime.h"
#include "EHScopeStack.h"
#include "UnimplementedFeatureGuarding.h"
#include "mlir/IR/Attributes.h"
Expand All @@ -37,13 +38,8 @@ CIRGenFunction::buildAutoVarAlloca(const VarDecl &D) {
// TODO: (|| Ty.getAddressSpace() == LangAS::opencl_private &&
// getLangOpts().OpenCL))
assert(!UnimplementedFeature::openCL());
assert(!UnimplementedFeature::openMP());
assert(Ty.getAddressSpace() == LangAS::Default);
assert(!Ty->isVariablyModifiedType() && "not implemented");
assert(!getContext()
.getLangOpts()
.OpenMP && // !CGF.getLangOpts().OpenMPIRBuilder
"not implemented");
assert(!D.hasAttr<AnnotateAttr>() && "not implemented");

auto loc = getLoc(D.getSourceRange());
Expand All @@ -59,7 +55,10 @@ CIRGenFunction::buildAutoVarAlloca(const VarDecl &D) {

Address address = Address::invalid();
Address allocaAddr = Address::invalid();
Address openMPLocalAddr = Address::invalid();
Address openMPLocalAddr =
getCIRGenModule().getOpenMPRuntime().getAddressOfLocalVariable(*this, &D);
if (getLangOpts().OpenMPIsTargetDevice)
assert(UnimplementedFeature::openMPTarget());
if (getLangOpts().OpenMP && openMPLocalAddr.isValid()) {
llvm_unreachable("NYI");
} else if (Ty->isConstantSizeType()) {
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "CIRGenCstEmitter.h"
#include "CIRGenFunction.h"
#include "CIRGenModule.h"
#include "CIRGenOpenMPRuntime.h"
#include "CIRGenValue.h"
#include "UnimplementedFeatureGuarding.h"

Expand Down Expand Up @@ -759,8 +760,11 @@ LValue CIRGenFunction::buildDeclRefLValue(const DeclRefExpr *E) {
if (auto *FD = LambdaCaptureFields.lookup(VD))
return buildCapturedFieldLValue(*this, FD, CXXABIThisValue);
assert(!UnimplementedFeature::CGCapturedStmtInfo() && "NYI");
llvm_unreachable("NYI");
// TODO[OpenMP]: Find the appropiate captured variable value and return
// it.
// TODO[OpenMP]: Set non-temporal information in the captured LVal.
// LLVM codegen:
assert(!UnimplementedFeature::openMP());
// Address addr = GetAddrOfBlockDecl(VD);
// return MakeAddrLValue(addr, T, AlignmentSource::Decl);
}
Expand Down Expand Up @@ -910,9 +914,9 @@ LValue CIRGenFunction::buildBinaryOperatorLValue(const BinaryOperator *E) {
} else {
buildStoreThroughLValue(RV, LV);
}

assert(!getContext().getLangOpts().OpenMP &&
"last priv cond not implemented");
if (getLangOpts().OpenMP)
CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(*this,
E->getLHS());
return LV;
}

Expand Down
5 changes: 4 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "CIRDataLayout.h"
#include "CIRGenFunction.h"
#include "CIRGenModule.h"
#include "CIRGenOpenMPRuntime.h"
#include "UnimplementedFeatureGuarding.h"

#include "clang/AST/StmtVisitor.h"
Expand Down Expand Up @@ -1805,7 +1806,9 @@ LValue ScalarExprEmitter::buildCompoundAssignLValue(
else
CGF.buildStoreThroughLValue(RValue::get(Result), LHSLV);

assert(!CGF.getLangOpts().OpenMP && "Not implemented");
if (CGF.getLangOpts().OpenMP)
CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF,
E->getLHS());
return LHSLV;
}

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "CIRGenFunction.h"
#include "CIRGenCXXABI.h"
#include "CIRGenModule.h"
#include "CIRGenOpenMPRuntime.h"
#include "UnimplementedFeatureGuarding.h"

#include "clang/AST/ASTLambda.h"
Expand Down Expand Up @@ -974,7 +975,7 @@ void CIRGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
// TODO: prologuecleanupdepth

if (getLangOpts().OpenMP && CurCodeDecl)
llvm_unreachable("NYI");
CGM.getOpenMPRuntime().emitFunctionProlog(*this, CurCodeDecl);

// TODO: buildFunctionProlog

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,9 @@ class CIRGenFunction : public CIRGenTypeCache {
mlir::LogicalResult buildBreakStmt(const clang::BreakStmt &S);
mlir::LogicalResult buildContinueStmt(const clang::ContinueStmt &S);

// OpenMP gen functions:
mlir::LogicalResult buildOMPParallelDirective(const OMPParallelDirective &S);

LValue buildOpaqueValueLValue(const OpaqueValueExpr *e);

/// Emit code to compute a designator that specifies the location
Expand Down
74 changes: 59 additions & 15 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "CIRGenCXXABI.h"
#include "CIRGenCstEmitter.h"
#include "CIRGenFunction.h"
#include "CIRGenOpenMPRuntime.h"
#include "CIRGenTypes.h"
#include "CIRGenValue.h"
#include "TargetInfo.h"
Expand Down Expand Up @@ -103,7 +104,7 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
codeGenOpts(CGO),
theModule{mlir::ModuleOp::create(builder.getUnknownLoc())}, Diags(Diags),
target(astCtx.getTargetInfo()), ABI(createCXXABI(*this)), genTypes{*this},
VTables{*this} {
VTables{*this}, openMPRuntime(new CIRGenOpenMPRuntime(*this)) {

// Initialize CIR signed integer types cache.
SInt8Ty =
Expand Down Expand Up @@ -316,7 +317,18 @@ bool CIRGenModule::MustBeEmitted(const ValueDecl *Global) {
}

bool CIRGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
assert(!langOpts.OpenMP && "NYI");
// In OpenMP 5.0 variables and function may be marked as
// device_type(host/nohost) and we should not emit them eagerly unless we sure
// that they must be emitted on the host/device. To be sure we need to have
// seen a declare target with an explicit mentioning of the function, we know
// we have if the level of the declare target attribute is -1. Note that we
// check somewhere else if we should emit this at all.
if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
OMPDeclareTargetDeclAttr::getActiveAttr(Global);
if (!ActiveAttr || (*ActiveAttr)->getLevel() != (unsigned)-1)
return false;
}

const auto *FD = dyn_cast<FunctionDecl>(Global);
if (FD) {
Expand All @@ -336,6 +348,15 @@ bool CIRGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
ASTContext::InlineVariableDefinitionKind::WeakUnknown &&
"not implemented");

// If OpenMP is enabled and threadprivates must be generated like TLS, delay
// codegen for global variables, because they may be marked as threadprivate.
if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
getASTContext().getTargetInfo().isTLSSupported() &&
isa<VarDecl>(Global) &&
!Global->getType().isConstantStorage(getASTContext(), false, false) &&
!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Global))
return false;

assert((FD || VD) &&
"Only FunctionDecl and VarDecl should hit this path so far.");
return true;
Expand All @@ -347,7 +368,22 @@ void CIRGenModule::buildGlobal(GlobalDecl GD) {
assert(!Global->hasAttr<IFuncAttr>() && "NYI");
assert(!Global->hasAttr<CPUDispatchAttr>() && "NYI");
assert(!langOpts.CUDA && "NYI");
assert(!langOpts.OpenMP && "NYI");

if (langOpts.OpenMP) {
// If this is OpenMP, check if it is legal to emit this global normally.
if (openMPRuntime && openMPRuntime->emitTargetGlobal(GD)) {
assert(!UnimplementedFeature::openMPRuntime());
return;
}
if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Global)) {
assert(!UnimplementedFeature::openMP());
return;
}
if (auto *DMD = dyn_cast<OMPDeclareMapperDecl>(Global)) {
assert(!UnimplementedFeature::openMP());
return;
}
}

// Ignore declarations, they will be emitted on their first use.
if (const auto *FD = dyn_cast<FunctionDecl>(Global)) {
Expand All @@ -371,7 +407,13 @@ void CIRGenModule::buildGlobal(GlobalDecl GD) {
assert(VD->isFileVarDecl() && "Cannot emit local var decl as global.");
if (VD->isThisDeclarationADefinition() != VarDecl::Definition &&
!astCtx.isMSStaticDataMemberInlineDefinition(VD)) {
assert(!getLangOpts().OpenMP && "not implemented");
if (langOpts.OpenMP) {
// Emit declaration of the must-be-emitted declare target variable.
if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
assert(0 && "OMPDeclareTargetDeclAttr NYI");
}
}
// If this declaration may have caused an inline variable definition
// to change linkage, make sure that it's emitted.
// TODO(cir): probably use GetAddrOfGlobalVar(VD) below?
Expand Down Expand Up @@ -576,8 +618,8 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef MangledName, mlir::Type Ty,
!D->hasAttr<clang::DLLExportAttr>())
assert(!UnimplementedFeature::setDLLStorageClass() && "NYI");

if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && D)
assert(0 && "not implemented");
if (langOpts.OpenMP && !langOpts.OpenMPSimd && D)
getOpenMPRuntime().registerTargetGlobalVariable(D, Entry);

// TODO(cir): check TargetAS matches Entry address space
if (Entry.getSymType() == Ty &&
Expand Down Expand Up @@ -647,10 +689,9 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef MangledName, mlir::Type Ty,
}

// Handle things which are present even on external declarations.
auto &LangOpts = getLangOpts();
if (D) {
if (LangOpts.OpenMP && !LangOpts.OpenMPSimd)
assert(0 && "not implemented");
if (langOpts.OpenMP && !langOpts.OpenMPSimd && D)
getOpenMPRuntime().registerTargetGlobalVariable(D, Entry);

// FIXME: This code is overly simple and should be merged with other global
// handling.
Expand Down Expand Up @@ -2022,8 +2063,11 @@ mlir::cir::FuncOp CIRGenModule::GetOrCreateCIRFunction(
// Any attempts to use a MultiVersion function should result in retrieving the
// iFunc instead. Name mangling will handle the rest of the changes.
if (const auto *FD = cast_or_null<FunctionDecl>(D)) {
if (getLangOpts().OpenMP)
llvm_unreachable("open MP NYI");
// For the device mark the function as one that should be emitted.
if (getLangOpts().OpenMPIsTargetDevice && FD->isDefined() && !DontDefer &&
!IsForDefinition) {
assert(0 && "OpenMP target functions NYI");
}
if (FD->isMultiVersion())
llvm_unreachable("NYI");
}
Expand Down Expand Up @@ -2261,9 +2305,9 @@ void CIRGenModule::buildGlobalDecl(clang::GlobalDecl &D) {
}

// If this is OpenMP, check if it is legal to emit this global normally.
if (getLangOpts().OpenMP) {
llvm_unreachable("NYI");
}
if (getLangOpts().OpenMP && openMPRuntime &&
openMPRuntime->emitTargetGlobal(D))
return;

// Otherwise, emit the definition and move on to the next one.
buildGlobalDefinition(D, Op);
Expand All @@ -2272,7 +2316,7 @@ void CIRGenModule::buildGlobalDecl(clang::GlobalDecl &D) {
void CIRGenModule::buildDeferred(unsigned recursionLimit) {
// Emit deferred declare target declarations
if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd)
llvm_unreachable("NYI");
getOpenMPRuntime().emitDeferredTargetDecls();

// Emit code for any potentially referenced deferred decls. Since a previously
// unused static decl may become used during the generation of code for a
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ namespace cir {
class CIRGenFunction;
class CIRGenCXXABI;
class TargetCIRGenInfo;
class CIRGenOpenMPRuntime;

enum ForDefinition_t : bool { NotForDefinition = false, ForDefinition = true };

Expand Down Expand Up @@ -100,6 +101,9 @@ class CIRGenModule : public CIRGenTypeCache {
/// Holds information about C++ vtables.
CIRGenVTables VTables;

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

/// Per-function codegen information. Updated everytime buildCIR is called
/// for FunctionDecls's.
CIRGenFunction *CurCGF = nullptr;
Expand Down Expand Up @@ -626,6 +630,12 @@ 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.
CIRGenOpenMPRuntime &getOpenMPRuntime() {
assert(openMPRuntime != nullptr);
return *openMPRuntime;
}

private:
// An ordered map of canonical GlobalDecls to their mangled names.
llvm::MapVector<clang::GlobalDecl, llvm::StringRef> MangledDeclNames;
Expand Down
54 changes: 54 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//===--- CIRGenStmtOpenMP.cpp - Interface to OpenMP 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 a class for OpenMP runtime MLIR code generation.
//
//===----------------------------------------------------------------------===//

#include "CIRGenOpenMPRuntime.h"
#include "CIRGenFunction.h"
#include "CIRGenModule.h"

using namespace cir;
using namespace clang;

CIRGenOpenMPRuntime::CIRGenOpenMPRuntime(CIRGenModule &CGM) : CGM(CGM) {}

Address CIRGenOpenMPRuntime::getAddressOfLocalVariable(CIRGenFunction &CGF,
const VarDecl *VD) {
assert(!UnimplementedFeature::openMPRuntime());
return Address::invalid();
}

void CIRGenOpenMPRuntime::checkAndEmitLastprivateConditional(
CIRGenFunction &CGF, const Expr *LHS) {
assert(!UnimplementedFeature::openMPRuntime());
return;
}

void CIRGenOpenMPRuntime::registerTargetGlobalVariable(
const clang::VarDecl *VD, mlir::cir::GlobalOp globalOp) {
assert(!UnimplementedFeature::openMPRuntime());
return;
}

void CIRGenOpenMPRuntime::emitDeferredTargetDecls() const {
assert(!UnimplementedFeature::openMPRuntime());
return;
}

void CIRGenOpenMPRuntime::emitFunctionProlog(CIRGenFunction &CGF,
const clang::Decl *D) {
assert(!UnimplementedFeature::openMPRuntime());
return;
}

bool CIRGenOpenMPRuntime::emitTargetGlobal(clang::GlobalDecl &GD) {
assert(!UnimplementedFeature::openMPRuntime());
return false;
}
Loading
Loading