Skip to content

Commit

Permalink
[OPENMP][DEBUG] Set proper address space info if required by target.
Browse files Browse the repository at this point in the history
Arguments, passed to the outlined function, must have correct address
space info for proper Debug info support. Patch sets global address
space for arguments that are mapped and passed by reference.

Also, cuda-gdb does not handle reference types correctly, so reference
arguments are represented as pointers.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@310104 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
alexey-bataev committed Aug 4, 2017
1 parent f4697f3 commit cf45efc
Show file tree
Hide file tree
Showing 10 changed files with 335 additions and 26 deletions.
8 changes: 8 additions & 0 deletions include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2685,6 +2685,14 @@ def OMPCaptureNoInit : InheritableAttr {
let Documentation = [Undocumented];
}

def OMPCaptureKind : Attr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let SemaHandler = 0;
let Args = [UnsignedArgument<"CaptureKind">];
let Documentation = [Undocumented];
}

def OMPDeclareSimdDecl : Attr {
let Spellings = [Pragma<"omp", "declare simd">];
let Subjects = SubjectList<[Function]>;
Expand Down
5 changes: 5 additions & 0 deletions include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -8527,6 +8527,11 @@ class Sema {
/// is performed.
bool isOpenMPPrivateDecl(ValueDecl *D, unsigned Level);

/// Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.)
/// for \p FD based on DSA for the provided corresponding captured declaration
/// \p D.
void setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level);

/// \brief Check if the specified variable is captured by 'target' directive.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
Expand Down
27 changes: 27 additions & 0 deletions lib/CodeGen/CGOpenMPRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,33 @@ class CGOpenMPRuntime {
virtual void emitDoacrossOrdered(CodeGenFunction &CGF,
const OMPDependClause *C);

/// Translates argument of outlined function if this is required for target.
/// \param FD A field for the corresponding captured variable in the captured
/// record.
/// \param NativeParam Native parameter of the outlined function.
virtual const VarDecl *translateParameter(const FieldDecl *FD,
const VarDecl *NativeParam) const {
return NativeParam;
}

typedef llvm::function_ref<void(CodeGenFunction &, const VarDecl *, Address)>
MappingFnType;
/// Maps the native argument to the address of the target-specific argument.
/// \param FD A field for the corresponding captured variable in the captured
/// record.
/// \param NativeParam Native parameter of the outlined function.
/// \param TargetParam Target-specific parameter of the outlined function
/// (provided by the \a CGOpenMPRuntime::translateParameter).
/// \param MapFn Mapping function that maps the address of the \p NativeParam
/// to the address of the \p TargetParam.
virtual void mapParameterAddress(CodeGenFunction &CGF, const FieldDecl *FD,
const VarDecl *NativeParam,
const VarDecl *TargetParam,
const MappingFnType MapFn) const {
assert(NativeParam == TargetParam &&
"native and target args must be the same");
}

/// Emits call of the outlined function with the provided arguments,
/// translating these arguments to correct target-specific arguments.
virtual void
Expand Down
79 changes: 79 additions & 0 deletions lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2238,3 +2238,82 @@ void CGOpenMPRuntimeNVPTX::emitReduction(
CGF.EmitBranch(DefaultBB);
CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
}

const VarDecl *
CGOpenMPRuntimeNVPTX::translateParameter(const FieldDecl *FD,
const VarDecl *NativeParam) const {
if (!NativeParam->getType()->isReferenceType())
return NativeParam;
QualType ArgType = NativeParam->getType();
QualifierCollector QC;
const Type *NonQualTy = QC.strip(ArgType);
QualType PointeeTy = cast<ReferenceType>(NonQualTy)->getPointeeType();
if (const auto *Attr = FD->getAttr<OMPCaptureKindAttr>()) {
if (Attr->getCaptureKind() == OMPC_map) {
PointeeTy = CGM.getContext().getAddrSpaceQualType(PointeeTy,
LangAS::opencl_global);
}
}
ArgType = CGM.getContext().getPointerType(PointeeTy);
QC.addRestrict();
enum { NVPTX_local_addr = 5 };
QC.addAddressSpace(NVPTX_local_addr);
ArgType = QC.apply(CGM.getContext(), ArgType);
return ImplicitParamDecl::Create(
CGM.getContext(), /*DC=*/nullptr, NativeParam->getLocation(),
NativeParam->getIdentifier(), ArgType, ImplicitParamDecl::Other);
}

void CGOpenMPRuntimeNVPTX::mapParameterAddress(
CodeGenFunction &CGF, const FieldDecl *FD, const VarDecl *NativeParam,
const VarDecl *TargetParam,
const CGOpenMPRuntime::MappingFnType MapFn) const {
if (!NativeParam->getType()->isReferenceType() || NativeParam == TargetParam)
return;
assert(NativeParam != TargetParam &&
"Native arg must not be the same as target arg.");
Address LocalAddr = CGF.GetAddrOfLocalVar(TargetParam);
QualType NativeParamType = NativeParam->getType();
QualifierCollector QC;
const Type *NonQualTy = QC.strip(NativeParamType);
QualType NativePointeeTy = cast<ReferenceType>(NonQualTy)->getPointeeType();
unsigned NativePointeeAddrSpace =
NativePointeeTy.getQualifiers().getAddressSpace();
QualType TargetPointeeTy = TargetParam->getType()->getPointeeType();
llvm::Value *TargetAddr = CGF.EmitLoadOfScalar(
LocalAddr, /*Volatile=*/false, TargetPointeeTy, SourceLocation());
// First cast to generic.
TargetAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
TargetAddr, TargetAddr->getType()->getPointerElementType()->getPointerTo(
/*AddrSpace=*/0));
// Cast from generic to native address space.
TargetAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
TargetAddr, TargetAddr->getType()->getPointerElementType()->getPointerTo(
NativePointeeAddrSpace));
Address NativeParamAddr = CGF.CreateMemTemp(NativeParamType);
CGF.EmitStoreOfScalar(TargetAddr, NativeParamAddr, /*Volatile=*/false,
NativeParam->getType());
MapFn(CGF, NativeParam, NativeParamAddr);
}

void CGOpenMPRuntimeNVPTX::emitOutlinedFunctionCall(
CodeGenFunction &CGF, llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> Args) const {
SmallVector<llvm::Value *, 4> TargetArgs;
auto *FnType =
cast<llvm::FunctionType>(OutlinedFn->getType()->getPointerElementType());
for (unsigned I = 0, E = Args.size(); I < E; ++I) {
llvm::Type *TargetType = FnType->getParamType(I);
llvm::Value *NativeArg = Args[I];
if (!TargetType->isPointerTy()) {
TargetArgs.emplace_back(NativeArg);
continue;
}
llvm::Value *TargetArg = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
NativeArg, NativeArg->getType()->getPointerElementType()->getPointerTo(
/*AddrSpace=*/0));
TargetArgs.emplace_back(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TargetArg, TargetType));
}
CGOpenMPRuntime::emitOutlinedFunctionCall(CGF, OutlinedFn, TargetArgs);
}
26 changes: 26 additions & 0 deletions lib/CodeGen/CGOpenMPRuntimeNVPTX.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,32 @@ class CGOpenMPRuntimeNVPTX : public CGOpenMPRuntime {
/// \return Specified function.
llvm::Constant *createNVPTXRuntimeFunction(unsigned Function);

/// Translates argument of outlined function if this is required for target.
/// \param FD A field for the corresponding captured variable in the captured
/// record.
/// \param NativeParam Native parameter of the outlined function.
const VarDecl *translateParameter(const FieldDecl *FD,
const VarDecl *NativeParam) const override;

/// Maps the native argument to the address of the target-specific argument.
/// \param FD A field for the corresponding captured variable in the captured
/// record.
/// \param NativeParam Native parameter of the outlined function.
/// \param TargetParam Target-specific parameter of the outlined function
/// (provided by the \a CGOpenMPRuntime::translateParameter).
/// \param MapFn Mapping function that maps the address of the \p NativeParam
/// to the address of the \p TargetParam.
void mapParameterAddress(CodeGenFunction &CGF, const FieldDecl *FD,
const VarDecl *NativeParam,
const VarDecl *TargetParam,
const MappingFnType MapFn) const override;

/// Emits call of the outlined function with the provided arguments,
/// translating these arguments to correct target-specific arguments.
void emitOutlinedFunctionCall(
CodeGenFunction &CGF, llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> Args = llvm::None) const override;

/// Target codegen is specialized based on two programming models: the
/// 'generic' fork-join model of OpenMP, and a more GPU efficient 'spmd'
/// model for constructs like 'target parallel' that support it.
Expand Down
55 changes: 42 additions & 13 deletions lib/CodeGen/CGStmtOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,15 @@ namespace {
bool RegisterCastedArgsOnly = false;
/// Name of the generated function.
StringRef FunctionName;
/// Function that maps given variable declaration to the specified address.
const CGOpenMPRuntime::MappingFnType MapFn;
explicit FunctionOptions(const CapturedStmt *S, bool UIntPtrCastRequired,
bool RegisterCastedArgsOnly,
StringRef FunctionName)
StringRef FunctionName,
const CGOpenMPRuntime::MappingFnType MapFn)
: S(S), UIntPtrCastRequired(UIntPtrCastRequired),
RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
FunctionName(FunctionName) {}
FunctionName(FunctionName), MapFn(MapFn) {}
};
}

Expand All @@ -276,9 +279,13 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
// Build the argument list.
CodeGenModule &CGM = CGF.CGM;
ASTContext &Ctx = CGM.getContext();
FunctionArgList TargetArgs;
bool HasUIntPtrArgs = false;
Args.append(CD->param_begin(),
std::next(CD->param_begin(), CD->getContextParamPosition()));
TargetArgs.append(
CD->param_begin(),
std::next(CD->param_begin(), CD->getContextParamPosition()));
auto I = FO.S->captures().begin();
for (auto *FD : RD->fields()) {
QualType ArgType = FD->getType();
Expand Down Expand Up @@ -308,19 +315,28 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
}
if (ArgType->isVariablyModifiedType())
ArgType = getCanonicalParamType(Ctx, ArgType.getNonReferenceType());
Args.push_back(ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr,
FD->getLocation(), II, ArgType,
ImplicitParamDecl::Other));
auto *Arg =
ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(), II,
ArgType, ImplicitParamDecl::Other);
Args.emplace_back(Arg);
// Do not cast arguments if we emit function with non-original types.
TargetArgs.emplace_back(
FO.UIntPtrCastRequired
? Arg
: CGM.getOpenMPRuntime().translateParameter(FD, Arg));
++I;
}
Args.append(
std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
CD->param_end());
TargetArgs.append(
std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
CD->param_end());

// Create the function declaration.
FunctionType::ExtInfo ExtInfo;
const CGFunctionInfo &FuncInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, TargetArgs);
llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);

llvm::Function *F =
Expand All @@ -331,16 +347,19 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
F->setDoesNotThrow();

// Generate the function.
CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getLocation(),
CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, TargetArgs, CD->getLocation(),
CD->getBody()->getLocStart());
unsigned Cnt = CD->getContextParamPosition();
I = FO.S->captures().begin();
for (auto *FD : RD->fields()) {
// Do not map arguments if we emit function with non-original types.
CGM.getOpenMPRuntime().mapParameterAddress(CGF, FD, Args[Cnt],
TargetArgs[Cnt], FO.MapFn);
Address LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]);
// If we are capturing a pointer by copy we don't need to do anything, just
// use the value that we get from the arguments.
if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
const VarDecl *CurVD = I->getCapturedVar();
Address LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]);
// If the variable is a reference we need to materialize it here.
if (CurVD->getType()->isReferenceType()) {
Address RefAddr = CGF.CreateMemTemp(
Expand All @@ -357,8 +376,8 @@ static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue(
}

LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
LValue ArgLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(Args[Cnt]),
Args[Cnt]->getType(), BaseInfo);
LValue ArgLVal =
CGF.MakeAddrLValue(LocalAddr, Args[Cnt]->getType(), BaseInfo);
if (FD->hasCapturedVLAType()) {
if (FO.UIntPtrCastRequired) {
ArgLVal = CGF.MakeAddrLValue(castValueFromUintptr(CGF, FD->getType(),
Expand Down Expand Up @@ -428,8 +447,15 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
FunctionArgList Args;
llvm::DenseMap<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
FunctionOptions FO(&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false,
CapturedStmtInfo->getHelperName());
FunctionOptions FO(
&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false,
CapturedStmtInfo->getHelperName(),
[NeedWrapperFunction](CodeGenFunction &CGF, const VarDecl *VD,
Address Addr) {
assert(NeedWrapperFunction && "Function should not be called if "
"wrapper function is not required.");
CGF.setAddrOfLocalVar(VD, Addr);
});
llvm::Function *F;
bool HasUIntPtrArgs;
std::tie(F, HasUIntPtrArgs) = emitOutlinedFunctionPrologue(
Expand All @@ -452,7 +478,10 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
llvm::raw_svector_ostream Out(Buffer);
Out << "__nondebug_wrapper_" << CapturedStmtInfo->getHelperName();
FunctionOptions WrapperFO(&S, /*UIntPtrCastRequired=*/true,
/*RegisterCastedArgsOnly=*/true, Out.str());
/*RegisterCastedArgsOnly=*/true, Out.str(),
[](CodeGenFunction &, const VarDecl *, Address) {
llvm_unreachable("Function should not be called");
});
CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true);
WrapperCGF.disableDebugInfo();
Args.clear();
Expand Down
2 changes: 2 additions & 0 deletions lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14013,6 +14013,8 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
Field->setImplicit(true);
Field->setAccess(AS_private);
RD->addDecl(Field);
if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP)
S.setOpenMPCaptureKind(Field, Var, RSI->OpenMPLevel);

CopyExpr = new (S.Context) DeclRefExpr(Var, RefersToCapturedVariable,
DeclRefType, VK_LValue, Loc);
Expand Down
33 changes: 33 additions & 0 deletions lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1327,6 +1327,39 @@ bool Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level) {
DSAStack->isTaskgroupReductionRef(D, Level));
}

void Sema::setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
D = getCanonicalDecl(D);
OpenMPClauseKind OMPC = OMPC_unknown;
for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
const unsigned NewLevel = I - 1;
if (DSAStack->hasExplicitDSA(D,
[&OMPC](const OpenMPClauseKind K) {
if (isOpenMPPrivate(K)) {
OMPC = K;
return true;
}
return false;
},
NewLevel))
break;
if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
D, NewLevel,
[](OMPClauseMappableExprCommon::MappableExprComponentListRef,
OpenMPClauseKind) { return true; })) {
OMPC = OMPC_map;
break;
}
if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
NewLevel)) {
OMPC = OMPC_firstprivate;
break;
}
}
if (OMPC != OMPC_unknown)
FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, OMPC));
}

bool Sema::isOpenMPTargetCapturedDecl(ValueDecl *D, unsigned Level) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
// Return true if the current level is no longer enclosed in a target region.
Expand Down
Loading

0 comments on commit cf45efc

Please sign in to comment.