summaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-11-25 19:07:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-11-25 19:07:40 +0000
commit17c7957f023f02fc2c88f51f8908c19b52609275 (patch)
treec654618ff2d38e26916b49614d89fe01f4a4818d /lib/CodeGen
parentc477790a57f44875b9de2043f2eb47dff2d20133 (diff)
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGExpr.cpp17
-rw-r--r--lib/CodeGen/CGStmt.cpp33
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp61
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp45
-rw-r--r--lib/CodeGen/CodeGenFunction.h33
5 files changed, 166 insertions, 23 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 3e1ae3604f94..5f3b290d8eb1 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -2105,12 +2105,11 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (auto *FD = LambdaCaptureFields.lookup(VD))
return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue);
else if (CapturedStmtInfo) {
- auto it = LocalDeclMap.find(VD);
- if (it != LocalDeclMap.end()) {
- if (auto RefTy = VD->getType()->getAs<ReferenceType>()) {
- return EmitLoadOfReferenceLValue(it->second, RefTy);
- }
- return MakeAddrLValue(it->second, T);
+ auto I = LocalDeclMap.find(VD);
+ if (I != LocalDeclMap.end()) {
+ if (auto RefTy = VD->getType()->getAs<ReferenceType>())
+ return EmitLoadOfReferenceLValue(I->second, RefTy);
+ return MakeAddrLValue(I->second, T);
}
LValue CapLVal =
EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD),
@@ -2249,13 +2248,15 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
return LV;
}
- assert(E->getSubExpr()->getType()->isAnyComplexType());
+ QualType T = ExprTy->castAs<ComplexType>()->getElementType();
Address Component =
(E->getOpcode() == UO_Real
? emitAddrOfRealComponent(LV.getAddress(), LV.getType())
: emitAddrOfImagComponent(LV.getAddress(), LV.getType()));
- return MakeAddrLValue(Component, ExprTy, LV.getAlignmentSource());
+ LValue ElemLV = MakeAddrLValue(Component, T, LV.getAlignmentSource());
+ ElemLV.getQuals().addQualifiers(LV.getQuals());
+ return ElemLV;
}
case UO_PreInc:
case UO_PreDec: {
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 77879021f9af..d815863e929d 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -1323,6 +1323,10 @@ static CSFC_Result CollectStatementsForCase(const Stmt *S,
// Handle this as two cases: we might be looking for the SwitchCase (if so
// the skipped statements must be skippable) or we might already have it.
CompoundStmt::const_body_iterator I = CS->body_begin(), E = CS->body_end();
+ bool StartedInLiveCode = FoundCase;
+ unsigned StartSize = ResultStmts.size();
+
+ // If we've not found the case yet, scan through looking for it.
if (Case) {
// Keep track of whether we see a skipped declaration. The code could be
// using the declaration even if it is skipped, so we can't optimize out
@@ -1332,7 +1336,7 @@ static CSFC_Result CollectStatementsForCase(const Stmt *S,
// If we're looking for the case, just see if we can skip each of the
// substatements.
for (; Case && I != E; ++I) {
- HadSkippedDecl |= isa<DeclStmt>(*I);
+ HadSkippedDecl |= CodeGenFunction::mightAddDeclToScope(*I);
switch (CollectStatementsForCase(*I, Case, FoundCase, ResultStmts)) {
case CSFC_Failure: return CSFC_Failure;
@@ -1368,11 +1372,19 @@ static CSFC_Result CollectStatementsForCase(const Stmt *S,
break;
}
}
+
+ if (!FoundCase)
+ return CSFC_Success;
+
+ assert(!HadSkippedDecl && "fallthrough after skipping decl");
}
// If we have statements in our range, then we know that the statements are
// live and need to be added to the set of statements we're tracking.
+ bool AnyDecls = false;
for (; I != E; ++I) {
+ AnyDecls |= CodeGenFunction::mightAddDeclToScope(*I);
+
switch (CollectStatementsForCase(*I, nullptr, FoundCase, ResultStmts)) {
case CSFC_Failure: return CSFC_Failure;
case CSFC_FallThrough:
@@ -1390,7 +1402,24 @@ static CSFC_Result CollectStatementsForCase(const Stmt *S,
}
}
- return Case ? CSFC_Success : CSFC_FallThrough;
+ // If we're about to fall out of a scope without hitting a 'break;', we
+ // can't perform the optimization if there were any decls in that scope
+ // (we'd lose their end-of-lifetime).
+ if (AnyDecls) {
+ // If the entire compound statement was live, there's one more thing we
+ // can try before giving up: emit the whole thing as a single statement.
+ // We can do that unless the statement contains a 'break;'.
+ // FIXME: Such a break must be at the end of a construct within this one.
+ // We could emit this by just ignoring the BreakStmts entirely.
+ if (StartedInLiveCode && !CodeGenFunction::containsBreak(S)) {
+ ResultStmts.resize(StartSize);
+ ResultStmts.push_back(S);
+ } else {
+ return CSFC_Failure;
+ }
+ }
+
+ return CSFC_FallThrough;
}
// Okay, this is some other statement that we don't handle explicitly, like a
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 26f780fdd7de..8937685fdc7b 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -232,8 +232,15 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
assert(I->capturesVariableArrayType());
II = &getContext().Idents.get("vla");
}
- if (ArgType->isVariablyModifiedType())
- ArgType = getContext().getVariableArrayDecayedType(ArgType);
+ if (ArgType->isVariablyModifiedType()) {
+ bool IsReference = ArgType->isLValueReferenceType();
+ ArgType =
+ getContext().getCanonicalParamType(ArgType.getNonReferenceType());
+ if (IsReference && !ArgType->isPointerType()) {
+ ArgType = getContext().getLValueReferenceType(
+ ArgType, /*SpelledAsLValue=*/false);
+ }
+ }
Args.push_back(ImplicitParamDecl::Create(getContext(), nullptr,
FD->getLocation(), II, ArgType));
++I;
@@ -287,8 +294,14 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
QualType VarTy = Var->getType();
Address ArgAddr = ArgLVal.getAddress();
if (!VarTy->isReferenceType()) {
- ArgAddr = EmitLoadOfReference(
- ArgAddr, ArgLVal.getType()->castAs<ReferenceType>());
+ if (ArgLVal.getType()->isLValueReferenceType()) {
+ ArgAddr = EmitLoadOfReference(
+ ArgAddr, ArgLVal.getType()->castAs<ReferenceType>());
+ } else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) {
+ assert(ArgLVal.getType()->isPointerType());
+ ArgAddr = EmitLoadOfPointer(
+ ArgAddr, ArgLVal.getType()->castAs<PointerType>());
+ }
}
setAddrOfLocalVar(
Var, Address(ArgAddr.getPointer(), getContext().getDeclAlign(Var)));
@@ -1754,9 +1767,17 @@ void CodeGenFunction::EmitOMPOuterLoop(bool DynamicOrOrdered, bool IsMonotonic,
EmitBlock(LoopExit.getBlock());
// Tell the runtime we are done.
- if (!DynamicOrOrdered)
- RT.emitForStaticFinish(*this, S.getLocEnd());
+ SourceLocation ELoc = S.getLocEnd();
+ auto &&CodeGen = [DynamicOrOrdered, ELoc](CodeGenFunction &CGF) {
+ if (!DynamicOrOrdered)
+ CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, ELoc);
+ };
+ CodeGen(*this);
+ OpenMPDirectiveKind DKind = S.getDirectiveKind();
+ if (DKind == OMPD_for || DKind == OMPD_parallel_for ||
+ DKind == OMPD_distribute_parallel_for)
+ OMPCancelStack.back().CodeGen = CodeGen;
}
void CodeGenFunction::EmitOMPForOuterLoop(
@@ -1868,6 +1889,7 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop(
void CodeGenFunction::EmitOMPDistributeParallelForDirective(
const OMPDistributeParallelForDirective &S) {
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPCancelStackRAII CancelRegion(*this);
CGM.getOpenMPRuntime().emitInlinedDirective(
*this, OMPD_distribute_parallel_for,
[&S](CodeGenFunction &CGF, PrePostActionTy &) {
@@ -2060,7 +2082,15 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
[](CodeGenFunction &) {});
EmitBlock(LoopExit.getBlock());
// Tell the runtime we are done.
- RT.emitForStaticFinish(*this, S.getLocStart());
+ SourceLocation ELoc = S.getLocEnd();
+ auto &&CodeGen = [ELoc](CodeGenFunction &CGF) {
+ CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, ELoc);
+ };
+ CodeGen(*this);
+ OpenMPDirectiveKind DKind = S.getDirectiveKind();
+ if (DKind == OMPD_for || DKind == OMPD_parallel_for ||
+ DKind == OMPD_distribute_parallel_for)
+ OMPCancelStack.back().CodeGen = CodeGen;
} else {
const bool IsMonotonic =
Ordered || ScheduleKind.Schedule == OMPC_SCHEDULE_static ||
@@ -2114,6 +2144,7 @@ void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
};
{
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ OMPCancelStackRAII CancelRegion(*this);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen,
S.hasCancel());
}
@@ -2156,6 +2187,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
bool HasLastprivates = false;
auto &&CodeGen = [&S, Stmt, CS, &HasLastprivates](CodeGenFunction &CGF,
PrePostActionTy &) {
+ OMPCancelStackRAII CancelRegion(CGF);
auto &C = CGF.CGM.getContext();
auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
// Emit helper vars inits.
@@ -2250,7 +2282,12 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen,
[](CodeGenFunction &) {});
// Tell the runtime we are done.
- CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocStart());
+ SourceLocation ELoc = S.getLocEnd();
+ auto &&FinalCodeGen = [ELoc](CodeGenFunction &CGF) {
+ CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, ELoc);
+ };
+ FinalCodeGen(CGF);
+ CGF.OMPCancelStack.back().CodeGen = FinalCodeGen;
CGF.EmitOMPReductionClauseFinal(S);
// Emit post-update of the reduction variables if IsLastIter != 0.
emitPostUpdateForReductionClause(
@@ -2375,6 +2412,7 @@ void CodeGenFunction::EmitOMPParallelForDirective(
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'for' directive.
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ OMPCancelStackRAII CancelRegion(CGF);
CGF.EmitOMPWorksharingLoop(S);
};
emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen);
@@ -3377,8 +3415,11 @@ CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
if (Kind == OMPD_parallel || Kind == OMPD_task)
return ReturnBlock;
assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
- Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for);
- return BreakContinueStack.back().BreakBlock;
+ Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
+ Kind == OMPD_distribute_parallel_for);
+ if (!OMPCancelStack.back().ExitBlock.isValid())
+ OMPCancelStack.back().ExitBlock = getJumpDestInCurrentScope("cancel.exit");
+ return OMPCancelStack.back().ExitBlock;
}
// Generate the instructions for '#pragma omp target data' directive.
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 183ee12ea232..11e4ad9ecefa 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
@@ -436,6 +437,23 @@ void CodeGenFunction::EmitMCountInstrumentation() {
EmitNounwindRuntimeCall(MCountFn);
}
+// Returns the address space id that should be produced to the
+// kernel_arg_addr_space metadata. This is always fixed to the ids
+// as specified in the SPIR 2.0 specification in order to differentiate
+// for example in clGetKernelArgInfo() implementation between the address
+// spaces with targets without unique mapping to the OpenCL address spaces
+// (basically all single AS CPUs).
+static unsigned ArgInfoAddressSpace(unsigned LangAS) {
+ switch (LangAS) {
+ case LangAS::opencl_global: return 1;
+ case LangAS::opencl_constant: return 2;
+ case LangAS::opencl_local: return 3;
+ case LangAS::opencl_generic: return 4; // Not in SPIR 2.0 specs.
+ default:
+ return 0; // Assume private.
+ }
+}
+
// OpenCL v1.2 s5.6.4.6 allows the compiler to store kernel argument
// information in the program executable. The argument information stored
// includes the argument name, its type, the address and access qualifiers used.
@@ -476,7 +494,7 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
// Get address qualifier.
addressQuals.push_back(llvm::ConstantAsMetadata::get(Builder.getInt32(
- ASTCtx.getTargetAddressSpace(pointeeTy.getAddressSpace()))));
+ ArgInfoAddressSpace(pointeeTy.getAddressSpace()))));
// Get argument type name.
std::string typeName =
@@ -513,8 +531,7 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
uint32_t AddrSpc = 0;
bool isPipe = ty->isPipeType();
if (ty->isImageType() || isPipe)
- AddrSpc =
- CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
+ AddrSpc = ArgInfoAddressSpace(LangAS::opencl_global);
addressQuals.push_back(
llvm::ConstantAsMetadata::get(Builder.getInt32(AddrSpc)));
@@ -1143,6 +1160,28 @@ bool CodeGenFunction::containsBreak(const Stmt *S) {
return false;
}
+bool CodeGenFunction::mightAddDeclToScope(const Stmt *S) {
+ if (!S) return false;
+
+ // Some statement kinds add a scope and thus never add a decl to the current
+ // scope. Note, this list is longer than the list of statements that might
+ // have an unscoped decl nested within them, but this way is conservatively
+ // correct even if more statement kinds are added.
+ if (isa<IfStmt>(S) || isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
+ isa<DoStmt>(S) || isa<ForStmt>(S) || isa<CompoundStmt>(S) ||
+ isa<CXXForRangeStmt>(S) || isa<CXXTryStmt>(S) ||
+ isa<ObjCForCollectionStmt>(S) || isa<ObjCAtTryStmt>(S))
+ return false;
+
+ if (isa<DeclStmt>(S))
+ return true;
+
+ for (const Stmt *SubStmt : S->children())
+ if (mightAddDeclToScope(SubStmt))
+ return true;
+
+ return false;
+}
/// ConstantFoldsToSimpleInteger - If the specified expression does not fold
/// to a constant, or if it does but contains a label, return false. If it
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 45068fa55444..f61ba69e3a0c 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -965,6 +965,35 @@ private:
};
SmallVector<BreakContinue, 8> BreakContinueStack;
+ /// Data for exit block for proper support of OpenMP cancellation constructs.
+ struct OMPCancel {
+ JumpDest ExitBlock;
+ llvm::function_ref<void(CodeGenFunction &CGF)> CodeGen;
+ OMPCancel() : CodeGen([](CodeGenFunction &CGF) {}) {}
+ };
+ SmallVector<OMPCancel, 8> OMPCancelStack;
+
+ /// Controls insertion of cancellation exit blocks in worksharing constructs.
+ class OMPCancelStackRAII {
+ CodeGenFunction &CGF;
+
+ public:
+ OMPCancelStackRAII(CodeGenFunction &CGF) : CGF(CGF) {
+ CGF.OMPCancelStack.push_back({});
+ }
+ ~OMPCancelStackRAII() {
+ if (CGF.HaveInsertPoint() &&
+ CGF.OMPCancelStack.back().ExitBlock.isValid()) {
+ auto CJD = CGF.getJumpDestInCurrentScope("cancel.cont");
+ CGF.EmitBranchThroughCleanup(CJD);
+ CGF.EmitBlock(CGF.OMPCancelStack.back().ExitBlock.getBlock());
+ CGF.OMPCancelStack.back().CodeGen(CGF);
+ CGF.EmitBranchThroughCleanup(CJD);
+ CGF.EmitBlock(CJD.getBlock());
+ }
+ }
+ };
+
CodeGenPGO PGO;
/// Calculate branch weights appropriate for PGO data
@@ -3163,6 +3192,10 @@ public:
/// If the statement (recursively) contains a switch or loop with a break
/// inside of it, this is fine.
static bool containsBreak(const Stmt *S);
+
+ /// Determine if the given statement might introduce a declaration into the
+ /// current scope, by being a (possibly-labelled) DeclStmt.
+ static bool mightAddDeclToScope(const Stmt *S);
/// ConstantFoldsToSimpleInteger - If the specified expression does not fold
/// to a constant, or if it does but contains a label, return false. If it