Skip to content

Commit 546da18

Browse files
committed
Use RT destroy task args mechanism instead of appending destroy code at the end of the task.
- An inner task using shared() needs to have alive data of the outer task until it finishes. Closes llvm#68
1 parent 45b0cb5 commit 546da18

File tree

2 files changed

+151
-72
lines changed

2 files changed

+151
-72
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*--------------------------------------------------------------------
2+
(C) Copyright 2006-2013 Barcelona Supercomputing Center
3+
Centro Nacional de Supercomputacion
4+
5+
This file is part of Mercurium C/C++ source-to-source compiler.
6+
7+
See AUTHORS file in the top level directory for information
8+
regarding developers and contributors.
9+
10+
This library is free software; you can redistribute it and/or
11+
modify it under the terms of the GNU Lesser General Public
12+
License as published by the Free Software Foundation; either
13+
version 3 of the License, or (at your option) any later version.
14+
15+
Mercurium C/C++ source-to-source compiler is distributed in the hope
16+
that it will be useful, but WITHOUT ANY WARRANTY; without even the
17+
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
18+
PURPOSE. See the GNU Lesser General Public License for more
19+
details.
20+
21+
You should have received a copy of the GNU Lesser General Public
22+
License along with Mercurium C/C++ source-to-source compiler; if
23+
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
24+
Cambridge, MA 02139, USA.
25+
--------------------------------------------------------------------*/
26+
27+
// RUN: %oss-cxx-compile-and-run
28+
// RUN: %oss-cxx-O2-compile-and-run
29+
30+
// Test if the RT keeps alive outer task non-pod data until
31+
// inner task finishes
32+
33+
#include <assert.h>
34+
35+
struct S {
36+
enum {
37+
NOT_INITIALIZED = -1,
38+
ALIVE = 0,
39+
DEAD = 1
40+
};
41+
int x = NOT_INITIALIZED;
42+
S() : x(ALIVE) {}
43+
~S() { x = DEAD; }
44+
};
45+
46+
int main() {
47+
S s;
48+
#pragma oss task firstprivate(s)
49+
{
50+
#pragma oss task shared(s) // Points to parent's data
51+
{
52+
assert(s.x == 0);
53+
}
54+
}
55+
#pragma oss taskwait
56+
}

llvm/lib/Transforms/OmpSs/OmpSsTransform.cpp

Lines changed: 95 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,74 @@ struct OmpSs : public ModulePass {
305305
BBBuilder.CreateCall(TaskInfoRegisterFuncCallee, TaskInfoVar);
306306
}
307307

308+
void unpackDestroyArgsAndRewrite(
309+
Module &M, const TaskInfo &TI, Function *F,
310+
const MapVector<Value *, size_t> &StructToIdxMap) {
311+
312+
BasicBlock::Create(M.getContext(), "entry", F);
313+
BasicBlock &Entry = F->getEntryBlock();
314+
IRBuilder<> IRB(&Entry);
315+
316+
for (Value *V : TI.DSAInfo.Private) {
317+
// Call custom destructor in clang in non-pods
318+
auto It = TI.NonPODsInfo.Deinits.find(V);
319+
if (It != TI.NonPODsInfo.Deinits.end()) {
320+
Type *Ty = V->getType()->getPointerElementType();
321+
// Compute num elements
322+
Value *NSize = ConstantInt::get(IRB.getInt64Ty(), 1);
323+
if (isa<ArrayType>(Ty)) {
324+
while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
325+
// Constant array
326+
Value *NumElems = ConstantInt::get(IRB.getInt64Ty(),
327+
ArrTy->getNumElements());
328+
NSize = IRB.CreateNUWMul(NSize, NumElems);
329+
Ty = ArrTy->getElementType();
330+
}
331+
} else if (TI.VLADimsInfo.count(V)) {
332+
for (Value *Dim : TI.VLADimsInfo.lookup(V))
333+
NSize = IRB.CreateNUWMul(NSize, F->getArg(StructToIdxMap.lookup(Dim)));
334+
}
335+
336+
// Regular arrays have types like [10 x %struct.S]*
337+
// Cast to %struct.S*
338+
Value *FArg = IRB.CreateBitCast(F->getArg(StructToIdxMap.lookup(V)), Ty->getPointerTo());
339+
340+
llvm::Function *Func = cast<Function>(It->second);
341+
IRB.CreateCall(Func, ArrayRef<Value*>{FArg, NSize});
342+
}
343+
}
344+
for (Value *V : TI.DSAInfo.Firstprivate) {
345+
// Call custom destructor in clang in non-pods
346+
auto It = TI.NonPODsInfo.Deinits.find(V);
347+
if (It != TI.NonPODsInfo.Deinits.end()) {
348+
Type *Ty = V->getType()->getPointerElementType();
349+
// Compute num elements
350+
Value *NSize = ConstantInt::get(IRB.getInt64Ty(), 1);
351+
if (isa<ArrayType>(Ty)) {
352+
while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
353+
// Constant array
354+
Value *NumElems = ConstantInt::get(IRB.getInt64Ty(),
355+
ArrTy->getNumElements());
356+
NSize = IRB.CreateNUWMul(NSize, NumElems);
357+
Ty = ArrTy->getElementType();
358+
}
359+
} else if (TI.VLADimsInfo.count(V)) {
360+
for (Value *Dim : TI.VLADimsInfo.lookup(V))
361+
NSize = IRB.CreateNUWMul(NSize, F->getArg(StructToIdxMap.lookup(Dim)));
362+
}
363+
364+
// Regular arrays have types like [10 x %struct.S]*
365+
// Cast to %struct.S*
366+
Value *FArg = IRB.CreateBitCast(F->getArg(StructToIdxMap.lookup(V)), Ty->getPointerTo());
367+
368+
llvm::Function *Func = cast<Function>(It->second);
369+
IRB.CreateCall(Func, ArrayRef<Value*>{FArg, NSize});
370+
}
371+
}
372+
IRB.CreateRetVoid();
373+
}
374+
375+
308376
void unpackDepsAndRewrite(Module &M, const TaskInfo &TI,
309377
Function *F,
310378
const MapVector<Value *, size_t> &StructToIdxMap) {
@@ -861,6 +929,30 @@ struct OmpSs : public ModulePass {
861929
SmallVector<Type *, 4> TaskExtraTypeList;
862930
SmallVector<StringRef, 4> TaskExtraNameList;
863931

932+
// nanos6_unpacked_destroy_* START
933+
TaskExtraTypeList.clear();
934+
TaskExtraNameList.clear();
935+
936+
Function *UnpackDestroyArgsFuncVar
937+
= createUnpackOlFunction(M, F,
938+
("nanos6_unpacked_destroy_" + F.getName() + Twine(taskNum)).str(),
939+
TaskTypeList, TaskNameList,
940+
TaskExtraTypeList, TaskExtraNameList);
941+
unpackDestroyArgsAndRewrite(M, TI, UnpackDestroyArgsFuncVar, TaskArgsToStructIdxMap);
942+
943+
// nanos6_unpacked_destroy_* END
944+
945+
// nanos6_ol_destroy_* START
946+
947+
Function *OlDestroyArgsFuncVar
948+
= createUnpackOlFunction(M, F,
949+
("nanos6_ol_destroy_" + F.getName() + Twine(taskNum)).str(),
950+
{TaskArgsTy->getPointerTo()}, {"task_args"},
951+
TaskExtraTypeList, TaskExtraNameList);
952+
olCallToUnpack(M, TI, TaskArgsToStructIdxMap, OlDestroyArgsFuncVar, UnpackDestroyArgsFuncVar);
953+
954+
// nanos6_ol_destroy_* END
955+
864956
// void *device_env
865957
TaskExtraTypeList.push_back(Type::getInt8PtrTy(M.getContext()));
866958
TaskExtraNameList.push_back("device_env");
@@ -1057,6 +1149,7 @@ struct OmpSs : public ModulePass {
10571149
[&M, &F, &TI, &OlDepsFuncVar,
10581150
&OlPriorityFuncVar,
10591151
&TaskImplInfoVar,
1152+
&OlDestroyArgsFuncVar,
10601153
&TaskRedInitsVar, &TaskRedCombsVar,
10611154
&taskNum] {
10621155
GlobalVariable *GV = new GlobalVariable(M, Nanos6TaskInfo::getInstance(M).getType(),
@@ -1072,7 +1165,7 @@ struct OmpSs : public ModulePass {
10721165
: ConstantPointerNull::get(cast<PointerType>(Nanos6TaskInfo::getInstance(M).getType()->getElementType(2))),
10731166
ConstantInt::get(Nanos6TaskInfo::getInstance(M).getType()->getElementType(3), 1),
10741167
ConstantExpr::getPointerCast(TaskImplInfoVar, Nanos6TaskInfo::getInstance(M).getType()->getElementType(4)),
1075-
ConstantPointerNull::get(cast<PointerType>(Nanos6TaskInfo::getInstance(M).getType()->getElementType(5))),
1168+
ConstantExpr::getPointerCast(OlDestroyArgsFuncVar, cast<PointerType>(Nanos6TaskInfo::getInstance(M).getType()->getElementType(5))),
10761169
ConstantPointerNull::get(cast<PointerType>(Nanos6TaskInfo::getInstance(M).getType()->getElementType(6))),
10771170
ConstantExpr::getPointerCast(TaskRedInitsVar, cast<PointerType>(Nanos6TaskInfo::getInstance(M).getType()->getElementType(7))),
10781171
ConstantExpr::getPointerCast(TaskRedCombsVar, cast<PointerType>(Nanos6TaskInfo::getInstance(M).getType()->getElementType(8))),
@@ -1313,7 +1406,7 @@ struct OmpSs : public ModulePass {
13131406
GEP = IRB.CreateBitCast(GEP, Ty->getPointerTo());
13141407
V = IRB.CreateBitCast(V, Ty->getPointerTo());
13151408

1316-
llvm::Function *Func = cast<Function>(It->second);
1409+
llvm::Function *Func = cast<Function>(It->second);
13171410
IRB.CreateCall(Func, ArrayRef<Value*>{/*Src=*/V, /*Dst=*/GEP, NSize});
13181411
} else {
13191412
unsigned SizeB = M.getDataLayout().getTypeAllocSize(Ty);
@@ -1364,76 +1457,6 @@ struct OmpSs : public ModulePass {
13641457
CodeExtractorAnalysisCache CEAC(F);
13651458
CodeExtractor CE(TaskBBs.getArrayRef(), rewriteUsesBrAndGetOmpSsUnpackFunc, emitOmpSsCaptureAndSubmitTask);
13661459
CE.extractCodeRegion(CEAC);
1367-
1368-
// Call Dtors
1369-
// Find 'ret' instr.
1370-
// TODO: We assume there will be only one
1371-
Instruction *RetI = nullptr;
1372-
for (auto I = inst_begin(UnpackTaskFuncVar); I != inst_end(UnpackTaskFuncVar); ++I) {
1373-
if (isa<ReturnInst>(*I)) {
1374-
RetI = &*I;
1375-
break;
1376-
}
1377-
}
1378-
assert(RetI && "UnpackTaskFunc does not have a terminator 'ret'");
1379-
1380-
IRBuilder<> IRB(RetI);
1381-
for (Value *V : TI.DSAInfo.Private) {
1382-
// Call custom destructor in clang in non-pods
1383-
auto It = TI.NonPODsInfo.Deinits.find(V);
1384-
if (It != TI.NonPODsInfo.Deinits.end()) {
1385-
Type *Ty = V->getType()->getPointerElementType();
1386-
// Compute num elements
1387-
Value *NSize = ConstantInt::get(IRB.getInt64Ty(), 1);
1388-
if (isa<ArrayType>(Ty)) {
1389-
while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
1390-
// Constant array
1391-
Value *NumElems = ConstantInt::get(IRB.getInt64Ty(),
1392-
ArrTy->getNumElements());
1393-
NSize = IRB.CreateNUWMul(NSize, NumElems);
1394-
Ty = ArrTy->getElementType();
1395-
}
1396-
} else if (TI.VLADimsInfo.count(V)) {
1397-
for (Value *const &Dim : TI.VLADimsInfo[V])
1398-
NSize = IRB.CreateNUWMul(NSize, UnpackTaskFuncVar->getArg(TaskArgsToStructIdxMap[Dim]));
1399-
}
1400-
1401-
// Regular arrays have types like [10 x %struct.S]*
1402-
// Cast to %struct.S*
1403-
Value *FArg = IRB.CreateBitCast(UnpackTaskFuncVar->getArg(TaskArgsToStructIdxMap[V]), Ty->getPointerTo());
1404-
1405-
llvm::Function *Func = cast<Function>(It->second);
1406-
IRB.CreateCall(Func, ArrayRef<Value*>{FArg, NSize});
1407-
}
1408-
}
1409-
for (Value *V : TI.DSAInfo.Firstprivate) {
1410-
// Call custom destructor in clang in non-pods
1411-
auto It = TI.NonPODsInfo.Deinits.find(V);
1412-
if (It != TI.NonPODsInfo.Deinits.end()) {
1413-
Type *Ty = V->getType()->getPointerElementType();
1414-
// Compute num elements
1415-
Value *NSize = ConstantInt::get(IRB.getInt64Ty(), 1);
1416-
if (isa<ArrayType>(Ty)) {
1417-
while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
1418-
// Constant array
1419-
Value *NumElems = ConstantInt::get(IRB.getInt64Ty(),
1420-
ArrTy->getNumElements());
1421-
NSize = IRB.CreateNUWMul(NSize, NumElems);
1422-
Ty = ArrTy->getElementType();
1423-
}
1424-
} else if (TI.VLADimsInfo.count(V)) {
1425-
for (Value *const &Dim : TI.VLADimsInfo[V])
1426-
NSize = IRB.CreateNUWMul(NSize, UnpackTaskFuncVar->getArg(TaskArgsToStructIdxMap[Dim]));
1427-
}
1428-
1429-
// Regular arrays have types like [10 x %struct.S]*
1430-
// Cast to %struct.S*
1431-
Value *FArg = IRB.CreateBitCast(UnpackTaskFuncVar->getArg(TaskArgsToStructIdxMap[V]), Ty->getPointerTo());
1432-
1433-
llvm::Function *Func = cast<Function>(It->second);
1434-
IRB.CreateCall(Func, ArrayRef<Value*>{FArg, NSize});
1435-
}
1436-
}
14371460
}
14381461

14391462
void buildNanos6Types(Module &M) {

0 commit comments

Comments
 (0)