forked from OSchip/llvm-project
[OPENMP 4.0] Use 'declare reduction' constructs in 'reduction' clauses.
OpenMP 4.0 allows to define custom reduction operations using '#pragma omp declare reduction' construct. Patch allows to use this custom defined reduction operations in 'reduction' clauses. llvm-svn: 263701
This commit is contained in:
parent
b59b488e21
commit
a839dddf92
|
@ -7942,7 +7942,10 @@ def warn_omp_loop_64_bit_var : Warning<
|
|||
"OpenMP loop iteration variable cannot have more than 64 bits size and will be narrowed">,
|
||||
InGroup<OpenMPLoopForm>;
|
||||
def err_omp_unknown_reduction_identifier : Error<
|
||||
"incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'">;
|
||||
"incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', "
|
||||
"'&&', '||', 'min' or 'max' or declare reduction for type %0">;
|
||||
def err_omp_not_resolved_reduction_identifier : Error<
|
||||
"unable to resolve declare reduction construct for type %0">;
|
||||
def err_omp_reduction_ref_type_arg : Error<
|
||||
"argument of OpenMP clause 'reduction' must reference the same object in all threads">;
|
||||
def err_omp_clause_not_arithmetic_type_arg : Error<
|
||||
|
|
|
@ -8225,12 +8225,12 @@ public:
|
|||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'reduction' clause.
|
||||
OMPClause *
|
||||
ActOnOpenMPReductionClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation ColonLoc,
|
||||
SourceLocation EndLoc,
|
||||
CXXScopeSpec &ReductionIdScopeSpec,
|
||||
const DeclarationNameInfo &ReductionId);
|
||||
OMPClause *ActOnOpenMPReductionClause(
|
||||
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
|
||||
CXXScopeSpec &ReductionIdScopeSpec,
|
||||
const DeclarationNameInfo &ReductionId,
|
||||
ArrayRef<Expr *> UnresolvedReductions = llvm::None);
|
||||
/// \brief Called on well-formed 'linear' clause.
|
||||
OMPClause *
|
||||
ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
|
||||
|
|
|
@ -622,12 +622,12 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
|
|||
auto &C = CGM.getContext();
|
||||
QualType PtrTy = C.getPointerType(Ty).withRestrict();
|
||||
FunctionArgList Args;
|
||||
ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
|
||||
/*Id=*/nullptr, PtrTy);
|
||||
ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
|
||||
/*Id=*/nullptr, PtrTy);
|
||||
Args.push_back(&OmpInParm);
|
||||
ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
|
||||
/*Id=*/nullptr, PtrTy);
|
||||
Args.push_back(&OmpOutParm);
|
||||
Args.push_back(&OmpInParm);
|
||||
auto &FnInfo =
|
||||
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
|
||||
auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
|
||||
|
@ -635,6 +635,7 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
|
|||
FnTy, llvm::GlobalValue::InternalLinkage,
|
||||
IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
|
||||
CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
|
||||
Fn->addFnAttr(llvm::Attribute::AlwaysInline);
|
||||
CodeGenFunction CGF(CGM);
|
||||
// Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
|
||||
// Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
|
||||
|
@ -688,6 +689,15 @@ void CGOpenMPRuntime::emitUserDefinedReduction(
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<llvm::Function *, llvm::Function *>
|
||||
CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
|
||||
auto I = UDRMap.find(D);
|
||||
if (I != UDRMap.end())
|
||||
return I->second;
|
||||
emitUserDefinedReduction(/*CGF=*/nullptr, D);
|
||||
return UDRMap.lookup(D);
|
||||
}
|
||||
|
||||
// Layout information for ident_t.
|
||||
static CharUnits getIdentAlign(CodeGenModule &CGM) {
|
||||
return CGM.getPointerAlign();
|
||||
|
@ -3596,6 +3606,26 @@ static void EmitOMPAggregateReduction(
|
|||
CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
|
||||
}
|
||||
|
||||
/// Emit reduction combiner. If the combiner is a simple expression emit it as
|
||||
/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
|
||||
/// UDR combiner function.
|
||||
static void emitReductionCombiner(CodeGenFunction &CGF,
|
||||
const Expr *ReductionOp) {
|
||||
if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
|
||||
if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
|
||||
if (auto *DRE =
|
||||
dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
|
||||
if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
|
||||
std::pair<llvm::Function *, llvm::Function *> Reduction =
|
||||
CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
|
||||
RValue Func = RValue::get(Reduction.first);
|
||||
CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
|
||||
CGF.EmitIgnoredExpr(ReductionOp);
|
||||
return;
|
||||
}
|
||||
CGF.EmitIgnoredExpr(ReductionOp);
|
||||
}
|
||||
|
||||
static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
|
||||
llvm::Type *ArgsType,
|
||||
ArrayRef<const Expr *> Privates,
|
||||
|
@ -3667,13 +3697,14 @@ static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
|
|||
// Emit reduction for array section.
|
||||
auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
|
||||
auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
|
||||
EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
|
||||
[=](CodeGenFunction &CGF, const Expr *,
|
||||
const Expr *,
|
||||
const Expr *) { CGF.EmitIgnoredExpr(E); });
|
||||
EmitOMPAggregateReduction(
|
||||
CGF, (*IPriv)->getType(), LHSVar, RHSVar,
|
||||
[=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
|
||||
emitReductionCombiner(CGF, E);
|
||||
});
|
||||
} else
|
||||
// Emit reduction for array subscript or single variable.
|
||||
CGF.EmitIgnoredExpr(E);
|
||||
emitReductionCombiner(CGF, E);
|
||||
++IPriv;
|
||||
++ILHS;
|
||||
++IRHS;
|
||||
|
@ -3740,9 +3771,9 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
|
|||
EmitOMPAggregateReduction(
|
||||
CGF, (*IPriv)->getType(), LHSVar, RHSVar,
|
||||
[=](CodeGenFunction &CGF, const Expr *, const Expr *,
|
||||
const Expr *) { CGF.EmitIgnoredExpr(E); });
|
||||
const Expr *) { emitReductionCombiner(CGF, E); });
|
||||
} else
|
||||
CGF.EmitIgnoredExpr(E);
|
||||
emitReductionCombiner(CGF, E);
|
||||
++IPriv;
|
||||
++ILHS;
|
||||
++IRHS;
|
||||
|
@ -3857,10 +3888,10 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
|
|||
EmitOMPAggregateReduction(
|
||||
CGF, (*IPriv)->getType(), LHSVar, RHSVar,
|
||||
[=](CodeGenFunction &CGF, const Expr *, const Expr *,
|
||||
const Expr *) { CGF.EmitIgnoredExpr(E); });
|
||||
const Expr *) { emitReductionCombiner(CGF, E); });
|
||||
} else
|
||||
// Emit reduction for array subscript or single variable.
|
||||
CGF.EmitIgnoredExpr(E);
|
||||
emitReductionCombiner(CGF, E);
|
||||
++IPriv;
|
||||
++ILHS;
|
||||
++IRHS;
|
||||
|
@ -3962,7 +3993,8 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
|
|||
const Expr *, const Expr *) {
|
||||
emitCriticalRegion(
|
||||
CGF, ".atomic_reduction",
|
||||
[E](CodeGenFunction &CGF) { CGF.EmitIgnoredExpr(E); }, Loc);
|
||||
[=](CodeGenFunction &CGF) { emitReductionCombiner(CGF, E); },
|
||||
Loc);
|
||||
};
|
||||
if ((*IPriv)->getType()->isArrayType()) {
|
||||
auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
|
||||
|
|
|
@ -383,6 +383,9 @@ public:
|
|||
/// Emit code for the specified user defined reduction construct.
|
||||
virtual void emitUserDefinedReduction(CodeGenFunction *CGF,
|
||||
const OMPDeclareReductionDecl *D);
|
||||
/// Get combiner/initializer for the specified user-defined reduction, if any.
|
||||
virtual std::pair<llvm::Function *, llvm::Function *>
|
||||
getUserDefinedReduction(const OMPDeclareReductionDecl *D);
|
||||
/// \brief Emits outlined function for the specified OpenMP parallel directive
|
||||
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
|
||||
/// kmp_int32 BoundID, struct context_vars*).
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/AST/DeclOpenMP.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
using namespace clang;
|
||||
using namespace CodeGen;
|
||||
|
||||
|
@ -310,12 +311,77 @@ void CodeGenFunction::EmitOMPAggregateAssign(
|
|||
EmitBlock(DoneBB, /*IsFinished=*/true);
|
||||
}
|
||||
|
||||
/// Check if the combiner is a call to UDR combiner and if it is so return the
|
||||
/// UDR decl used for reduction.
|
||||
static const OMPDeclareReductionDecl *
|
||||
getReductionInit(const Expr *ReductionOp) {
|
||||
if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
|
||||
if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
|
||||
if (auto *DRE =
|
||||
dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
|
||||
if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
|
||||
return DRD;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
|
||||
const OMPDeclareReductionDecl *DRD,
|
||||
const Expr *InitOp,
|
||||
Address Private, Address Original,
|
||||
QualType Ty) {
|
||||
if (DRD->getInitializer()) {
|
||||
std::pair<llvm::Function *, llvm::Function *> Reduction =
|
||||
CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
|
||||
auto *CE = cast<CallExpr>(InitOp);
|
||||
auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
|
||||
const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
|
||||
const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
|
||||
auto *LHSDRE = cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
|
||||
auto *RHSDRE = cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
|
||||
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
|
||||
PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
|
||||
[=]() -> Address { return Private; });
|
||||
PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
|
||||
[=]() -> Address { return Original; });
|
||||
(void)PrivateScope.Privatize();
|
||||
RValue Func = RValue::get(Reduction.second);
|
||||
CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
|
||||
CGF.EmitIgnoredExpr(InitOp);
|
||||
} else {
|
||||
llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
|
||||
auto *GV = new llvm::GlobalVariable(
|
||||
CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
|
||||
llvm::GlobalValue::PrivateLinkage, Init, ".init");
|
||||
LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
|
||||
RValue InitRVal;
|
||||
switch (CGF.getEvaluationKind(Ty)) {
|
||||
case TEK_Scalar:
|
||||
InitRVal = CGF.EmitLoadOfLValue(LV, SourceLocation());
|
||||
break;
|
||||
case TEK_Complex:
|
||||
InitRVal =
|
||||
RValue::getComplex(CGF.EmitLoadOfComplex(LV, SourceLocation()));
|
||||
break;
|
||||
case TEK_Aggregate:
|
||||
InitRVal = RValue::getAggregate(LV.getAddress());
|
||||
break;
|
||||
}
|
||||
OpaqueValueExpr OVE(SourceLocation(), Ty, VK_RValue);
|
||||
CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
|
||||
CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
|
||||
/*IsInitializer=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Emit initialization of arrays of complex types.
|
||||
/// \param DestAddr Address of the array.
|
||||
/// \param Type Type of array.
|
||||
/// \param Init Initial expression of array.
|
||||
/// \param SrcAddr Address of the original array.
|
||||
static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
|
||||
QualType Type, const Expr *Init) {
|
||||
QualType Type, const Expr *Init,
|
||||
Address SrcAddr = Address::invalid()) {
|
||||
auto *DRD = getReductionInit(Init);
|
||||
// Perform element-by-element initialization.
|
||||
QualType ElementTy;
|
||||
|
||||
|
@ -324,7 +390,13 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
|
|||
auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
|
||||
DestAddr =
|
||||
CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
|
||||
if (DRD)
|
||||
SrcAddr =
|
||||
CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
|
||||
|
||||
llvm::Value *SrcBegin = nullptr;
|
||||
if (DRD)
|
||||
SrcBegin = SrcAddr.getPointer();
|
||||
auto DestBegin = DestAddr.getPointer();
|
||||
// Cast from pointer to array type to pointer to single element.
|
||||
auto DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
|
||||
|
@ -341,6 +413,16 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
|
|||
|
||||
CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
|
||||
|
||||
llvm::PHINode *SrcElementPHI = nullptr;
|
||||
Address SrcElementCurrent = Address::invalid();
|
||||
if (DRD) {
|
||||
SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
|
||||
"omp.arraycpy.srcElementPast");
|
||||
SrcElementPHI->addIncoming(SrcBegin, EntryBB);
|
||||
SrcElementCurrent =
|
||||
Address(SrcElementPHI,
|
||||
SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
|
||||
}
|
||||
llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
|
||||
DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
|
||||
DestElementPHI->addIncoming(DestBegin, EntryBB);
|
||||
|
@ -351,8 +433,19 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
|
|||
// Emit copy.
|
||||
{
|
||||
CodeGenFunction::RunCleanupsScope InitScope(CGF);
|
||||
CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
|
||||
/*IsInitializer=*/false);
|
||||
if (DRD) {
|
||||
emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
|
||||
SrcElementCurrent, ElementTy);
|
||||
} else
|
||||
CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
|
||||
/*IsInitializer=*/false);
|
||||
}
|
||||
|
||||
if (DRD) {
|
||||
// Shift the address forward by one element.
|
||||
auto SrcElementNext = CGF.Builder.CreateConstGEP1_32(
|
||||
SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
|
||||
SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
|
||||
}
|
||||
|
||||
// Shift the address forward by one element.
|
||||
|
@ -752,10 +845,12 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
|
|||
auto ILHS = C->lhs_exprs().begin();
|
||||
auto IRHS = C->rhs_exprs().begin();
|
||||
auto IPriv = C->privates().begin();
|
||||
auto IRed = C->reduction_ops().begin();
|
||||
for (auto IRef : C->varlists()) {
|
||||
auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
|
||||
auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
|
||||
auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());
|
||||
auto *DRD = getReductionInit(*IRed);
|
||||
if (auto *OASE = dyn_cast<OMPArraySectionExpr>(IRef)) {
|
||||
auto *Base = OASE->getBase()->IgnoreParenImpCasts();
|
||||
while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
|
||||
|
@ -779,7 +874,7 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
|
|||
// Emit reduction copy.
|
||||
bool IsRegistered = PrivateScope.addPrivate(
|
||||
OrigVD, [this, OrigVD, PrivateVD, BaseLValue, OASELValueLB,
|
||||
OASELValueUB, OriginalBaseLValue]() -> Address {
|
||||
OASELValueUB, OriginalBaseLValue, DRD, IRed]() -> Address {
|
||||
// Emit VarDecl with copy init for arrays.
|
||||
// Get the address of the original variable captured in current
|
||||
// captured region.
|
||||
|
@ -797,7 +892,9 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
|
|||
auto Emission = EmitAutoVarAlloca(*PrivateVD);
|
||||
auto Addr = Emission.getAllocatedAddress();
|
||||
auto *Init = PrivateVD->getInit();
|
||||
EmitOMPAggregateInit(*this, Addr, PrivateVD->getType(), Init);
|
||||
EmitOMPAggregateInit(*this, Addr, PrivateVD->getType(),
|
||||
DRD ? *IRed : Init,
|
||||
OASELValueLB.getAddress());
|
||||
EmitAutoVarCleanups(Emission);
|
||||
// Emit private VarDecl with reduction init.
|
||||
auto *Offset = Builder.CreatePtrDiff(BaseLValue.getPointer(),
|
||||
|
@ -831,10 +928,17 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
|
|||
// Emit reduction copy.
|
||||
bool IsRegistered = PrivateScope.addPrivate(
|
||||
OrigVD, [this, OrigVD, PrivateVD, BaseLValue, ASELValue,
|
||||
OriginalBaseLValue]() -> Address {
|
||||
OriginalBaseLValue, DRD, IRed]() -> Address {
|
||||
// Emit private VarDecl with reduction init.
|
||||
EmitDecl(*PrivateVD);
|
||||
auto Addr = GetAddrOfLocalVar(PrivateVD);
|
||||
AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD);
|
||||
auto Addr = Emission.getAllocatedAddress();
|
||||
if (DRD) {
|
||||
emitInitWithReductionInitializer(*this, DRD, *IRed, Addr,
|
||||
ASELValue.getAddress(),
|
||||
ASELValue.getType());
|
||||
} else
|
||||
EmitAutoVarInit(Emission);
|
||||
EmitAutoVarCleanups(Emission);
|
||||
auto *Offset = Builder.CreatePtrDiff(BaseLValue.getPointer(),
|
||||
ASELValue.getPointer());
|
||||
auto *Ptr = Builder.CreateGEP(Addr.getPointer(), Offset);
|
||||
|
@ -859,11 +963,11 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
|
|||
CapturedStmtInfo->lookup(OrigVD) != nullptr,
|
||||
IRef->getType(), VK_LValue, IRef->getExprLoc());
|
||||
Address OriginalAddr = EmitLValue(&DRE).getAddress();
|
||||
PrivateScope.addPrivate(LHSVD, [this, OriginalAddr,
|
||||
PrivateScope.addPrivate(LHSVD, [this, &OriginalAddr,
|
||||
LHSVD]() -> Address {
|
||||
return Builder.CreateElementBitCast(
|
||||
OriginalAddr, ConvertTypeForMem(LHSVD->getType()),
|
||||
"lhs.begin");
|
||||
OriginalAddr = Builder.CreateElementBitCast(
|
||||
OriginalAddr, ConvertTypeForMem(LHSVD->getType()), "lhs.begin");
|
||||
return OriginalAddr;
|
||||
});
|
||||
bool IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
|
||||
if (Type->isVariablyModifiedType()) {
|
||||
|
@ -879,7 +983,8 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
|
|||
auto Emission = EmitAutoVarAlloca(*PrivateVD);
|
||||
auto Addr = Emission.getAllocatedAddress();
|
||||
auto *Init = PrivateVD->getInit();
|
||||
EmitOMPAggregateInit(*this, Addr, PrivateVD->getType(), Init);
|
||||
EmitOMPAggregateInit(*this, Addr, PrivateVD->getType(),
|
||||
DRD ? *IRed : Init, OriginalAddr);
|
||||
EmitAutoVarCleanups(Emission);
|
||||
return Emission.getAllocatedAddress();
|
||||
});
|
||||
|
@ -894,18 +999,29 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
|
|||
} else {
|
||||
// Store the address of the original variable associated with the LHS
|
||||
// implicit variable.
|
||||
PrivateScope.addPrivate(LHSVD, [this, OrigVD, IRef]() -> Address {
|
||||
Address OriginalAddr = Address::invalid();
|
||||
PrivateScope.addPrivate(LHSVD, [this, OrigVD, IRef,
|
||||
&OriginalAddr]() -> Address {
|
||||
DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
|
||||
CapturedStmtInfo->lookup(OrigVD) != nullptr,
|
||||
IRef->getType(), VK_LValue, IRef->getExprLoc());
|
||||
return EmitLValue(&DRE).getAddress();
|
||||
OriginalAddr = EmitLValue(&DRE).getAddress();
|
||||
return OriginalAddr;
|
||||
});
|
||||
// Emit reduction copy.
|
||||
bool IsRegistered =
|
||||
PrivateScope.addPrivate(OrigVD, [this, PrivateVD]() -> Address {
|
||||
bool IsRegistered = PrivateScope.addPrivate(
|
||||
OrigVD, [this, PrivateVD, OriginalAddr, DRD, IRed]() -> Address {
|
||||
// Emit private VarDecl with reduction init.
|
||||
EmitDecl(*PrivateVD);
|
||||
return GetAddrOfLocalVar(PrivateVD);
|
||||
AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD);
|
||||
auto Addr = Emission.getAllocatedAddress();
|
||||
if (DRD) {
|
||||
emitInitWithReductionInitializer(*this, DRD, *IRed, Addr,
|
||||
OriginalAddr,
|
||||
PrivateVD->getType());
|
||||
} else
|
||||
EmitAutoVarInit(Emission);
|
||||
EmitAutoVarCleanups(Emission);
|
||||
return Addr;
|
||||
});
|
||||
assert(IsRegistered && "private var already registered as private");
|
||||
// Silence the warning about unused variable.
|
||||
|
@ -918,6 +1034,7 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
|
|||
++ILHS;
|
||||
++IRHS;
|
||||
++IPriv;
|
||||
++IRed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,9 +109,16 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
|
|||
}
|
||||
|
||||
static DeclarationName parseOpenMPReductionId(Parser &P) {
|
||||
const Token Tok = P.getCurToken();
|
||||
Token Tok = P.getCurToken();
|
||||
Sema &Actions = P.getActions();
|
||||
OverloadedOperatorKind OOK = OO_None;
|
||||
// Allow to use 'operator' keyword for C++ operators
|
||||
bool WithOperator = false;
|
||||
if (Tok.is(tok::kw_operator)) {
|
||||
P.ConsumeToken();
|
||||
Tok = P.getCurToken();
|
||||
WithOperator = true;
|
||||
}
|
||||
switch (Tok.getKind()) {
|
||||
case tok::plus: // '+'
|
||||
OOK = OO_Plus;
|
||||
|
@ -138,7 +145,8 @@ static DeclarationName parseOpenMPReductionId(Parser &P) {
|
|||
OOK = OO_PipePipe;
|
||||
break;
|
||||
case tok::identifier: // identifier
|
||||
break;
|
||||
if (!WithOperator)
|
||||
break;
|
||||
default:
|
||||
P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
|
||||
P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
||||
|
@ -181,6 +189,8 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
|
|||
if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
|
||||
return DeclGroupPtrTy();
|
||||
|
||||
IsCorrect = IsCorrect && !Name.isEmpty();
|
||||
|
||||
if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
|
||||
Diag(Tok.getLocation(), diag::err_expected_type);
|
||||
IsCorrect = false;
|
||||
|
@ -1209,9 +1219,10 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
|
|||
// Handle reduction-identifier for reduction clause.
|
||||
if (Kind == OMPC_reduction) {
|
||||
ColonProtectionRAIIObject ColonRAII(*this);
|
||||
if (getLangOpts().CPlusPlus) {
|
||||
ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, nullptr, false);
|
||||
}
|
||||
if (getLangOpts().CPlusPlus)
|
||||
ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec,
|
||||
/*ObjectType=*/nullptr,
|
||||
/*EnteringContext=*/false);
|
||||
InvalidReductionId =
|
||||
ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
|
||||
if (InvalidReductionId) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "TreeTransform.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/ASTMutationListener.h"
|
||||
#include "clang/AST/CXXInheritance.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclOpenMP.h"
|
||||
|
@ -7829,16 +7830,113 @@ public:
|
|||
};
|
||||
} // namespace
|
||||
|
||||
template <typename T>
|
||||
static T filterLookupForUDR(SmallVectorImpl<UnresolvedSet<8>> &Lookups,
|
||||
const llvm::function_ref<T(ValueDecl *)> &Gen) {
|
||||
for (auto &Set : Lookups) {
|
||||
for (auto *D : Set) {
|
||||
if (auto Res = Gen(cast<ValueDecl>(D)))
|
||||
return Res;
|
||||
}
|
||||
}
|
||||
return T();
|
||||
}
|
||||
|
||||
static ExprResult
|
||||
buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
|
||||
Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
|
||||
const DeclarationNameInfo &ReductionId, QualType Ty,
|
||||
CXXCastPath &BasePath, Expr *UnresolvedReduction) {
|
||||
if (ReductionIdScopeSpec.isInvalid())
|
||||
return ExprError();
|
||||
SmallVector<UnresolvedSet<8>, 4> Lookups;
|
||||
if (S) {
|
||||
LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
|
||||
Lookup.suppressDiagnostics();
|
||||
while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
|
||||
auto *D = Lookup.getRepresentativeDecl();
|
||||
do {
|
||||
S = S->getParent();
|
||||
} while (S && !S->isDeclScope(D));
|
||||
if (S)
|
||||
S = S->getParent();
|
||||
Lookups.push_back(UnresolvedSet<8>());
|
||||
Lookups.back().append(Lookup.begin(), Lookup.end());
|
||||
Lookup.clear();
|
||||
}
|
||||
} else if (auto *ULE =
|
||||
cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
|
||||
Lookups.push_back(UnresolvedSet<8>());
|
||||
Decl *PrevD = nullptr;
|
||||
for(auto *D : ULE->decls()) {
|
||||
if (D == PrevD)
|
||||
Lookups.push_back(UnresolvedSet<8>());
|
||||
else if (auto *DRD = cast<OMPDeclareReductionDecl>(D))
|
||||
Lookups.back().addDecl(DRD);
|
||||
PrevD = D;
|
||||
}
|
||||
}
|
||||
if (Ty->isDependentType() || Ty->isInstantiationDependentType() ||
|
||||
Ty->containsUnexpandedParameterPack() ||
|
||||
filterLookupForUDR<bool>(Lookups, [](ValueDecl *D) -> bool {
|
||||
return !D->isInvalidDecl() &&
|
||||
(D->getType()->isDependentType() ||
|
||||
D->getType()->isInstantiationDependentType() ||
|
||||
D->getType()->containsUnexpandedParameterPack());
|
||||
})) {
|
||||
UnresolvedSet<8> ResSet;
|
||||
for (auto &Set : Lookups) {
|
||||
ResSet.append(Set.begin(), Set.end());
|
||||
// The last item marks the end of all declarations at the specified scope.
|
||||
ResSet.addDecl(Set[Set.size() - 1]);
|
||||
}
|
||||
return UnresolvedLookupExpr::Create(
|
||||
SemaRef.Context, /*NamingClass=*/nullptr,
|
||||
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
|
||||
/*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
|
||||
}
|
||||
if (auto *VD = filterLookupForUDR<ValueDecl *>(
|
||||
Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
|
||||
if (!D->isInvalidDecl() &&
|
||||
SemaRef.Context.hasSameType(D->getType(), Ty))
|
||||
return D;
|
||||
return nullptr;
|
||||
}))
|
||||
return SemaRef.BuildDeclRefExpr(VD, Ty, VK_LValue, Loc);
|
||||
if (auto *VD = filterLookupForUDR<ValueDecl *>(
|
||||
Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
|
||||
if (!D->isInvalidDecl() &&
|
||||
SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
|
||||
!Ty.isMoreQualifiedThan(D->getType()))
|
||||
return D;
|
||||
return nullptr;
|
||||
})) {
|
||||
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
|
||||
/*DetectVirtual=*/false);
|
||||
if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
|
||||
if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
|
||||
VD->getType().getUnqualifiedType()))) {
|
||||
if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Ty, Paths.front(),
|
||||
/*DiagID=*/0) !=
|
||||
Sema::AR_inaccessible) {
|
||||
SemaRef.BuildBasePathArray(Paths, BasePath);
|
||||
return SemaRef.BuildDeclRefExpr(VD, Ty, VK_LValue, Loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ReductionIdScopeSpec.isSet()) {
|
||||
SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier) << Range;
|
||||
return ExprError();
|
||||
}
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPReductionClause(
|
||||
ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc, SourceLocation EndLoc,
|
||||
CXXScopeSpec &ReductionIdScopeSpec,
|
||||
const DeclarationNameInfo &ReductionId) {
|
||||
// TODO: Allow scope specification search when 'declare reduction' is
|
||||
// supported.
|
||||
assert(ReductionIdScopeSpec.isEmpty() &&
|
||||
"No support for scoped reduction identifiers yet.");
|
||||
|
||||
CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
|
||||
ArrayRef<Expr *> UnresolvedReductions) {
|
||||
auto DN = ReductionId.getName();
|
||||
auto OOK = DN.getCXXOverloadedOperator();
|
||||
BinaryOperatorKind BOK = BO_Comma;
|
||||
|
@ -7922,16 +8020,9 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
break;
|
||||
}
|
||||
SourceRange ReductionIdRange;
|
||||
if (ReductionIdScopeSpec.isValid()) {
|
||||
if (ReductionIdScopeSpec.isValid())
|
||||
ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
|
||||
}
|
||||
ReductionIdRange.setEnd(ReductionId.getEndLoc());
|
||||
if (BOK == BO_Comma) {
|
||||
// Not allowed reduction identifier is found.
|
||||
Diag(ReductionId.getLocStart(), diag::err_omp_unknown_reduction_identifier)
|
||||
<< ReductionIdRange;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SmallVector<Expr *, 8> Vars;
|
||||
SmallVector<Expr *, 8> Privates;
|
||||
|
@ -7940,6 +8031,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
SmallVector<Expr *, 8> ReductionOps;
|
||||
SmallVector<Decl *, 4> ExprCaptures;
|
||||
SmallVector<Expr *, 4> ExprPostUpdates;
|
||||
auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
|
||||
bool FirstIter = true;
|
||||
for (auto RefExpr : VarList) {
|
||||
assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
|
||||
// OpenMP [2.1, C/C++]
|
||||
|
@ -7949,6 +8042,9 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
// OpenMP [2.14.3.3, Restrictions, p.1]
|
||||
// A variable that is part of another variable (as an array or
|
||||
// structure element) cannot appear in a private clause.
|
||||
if (!FirstIter && IR != ER)
|
||||
++IR;
|
||||
FirstIter = false;
|
||||
SourceLocation ELoc;
|
||||
SourceRange ERange;
|
||||
Expr *SimpleRefExpr = RefExpr;
|
||||
|
@ -7960,7 +8056,19 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
Privates.push_back(nullptr);
|
||||
LHSs.push_back(nullptr);
|
||||
RHSs.push_back(nullptr);
|
||||
ReductionOps.push_back(nullptr);
|
||||
// Try to find 'declare reduction' corresponding construct before using
|
||||
// builtin/overloaded operators.
|
||||
QualType Type = Context.DependentTy;
|
||||
CXXCastPath BasePath;
|
||||
ExprResult DeclareReductionRef = buildDeclareReductionRef(
|
||||
*this, ELoc, ERange, DSAStack->getCurScope(), ReductionIdScopeSpec,
|
||||
ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
|
||||
if (CurContext->isDependentContext() &&
|
||||
(DeclareReductionRef.isUnset() ||
|
||||
isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
|
||||
ReductionOps.push_back(DeclareReductionRef.get());
|
||||
else
|
||||
ReductionOps.push_back(nullptr);
|
||||
}
|
||||
ValueDecl *D = Res.first;
|
||||
if (!D)
|
||||
|
@ -8018,42 +8126,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
}
|
||||
}
|
||||
}
|
||||
// OpenMP [2.14.3.6, reduction clause, Restrictions]
|
||||
// The type of a list item that appears in a reduction clause must be valid
|
||||
// for the reduction-identifier. For a max or min reduction in C, the type
|
||||
// of the list item must be an allowed arithmetic data type: char, int,
|
||||
// float, double, or _Bool, possibly modified with long, short, signed, or
|
||||
// unsigned. For a max or min reduction in C++, the type of the list item
|
||||
// must be an allowed arithmetic data type: char, wchar_t, int, float,
|
||||
// double, or bool, possibly modified with long, short, signed, or unsigned.
|
||||
if ((BOK == BO_GT || BOK == BO_LT) &&
|
||||
!(Type->isScalarType() ||
|
||||
(getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
|
||||
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
|
||||
<< getLangOpts().CPlusPlus;
|
||||
if (!ASE && !OASE) {
|
||||
bool IsDecl = !VD ||
|
||||
VD->isThisDeclarationADefinition(Context) ==
|
||||
VarDecl::DeclarationOnly;
|
||||
Diag(D->getLocation(),
|
||||
IsDecl ? diag::note_previous_decl : diag::note_defined_here)
|
||||
<< D;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
|
||||
!getLangOpts().CPlusPlus && Type->isFloatingType()) {
|
||||
Diag(ELoc, diag::err_omp_clause_floating_type_arg);
|
||||
if (!ASE && !OASE) {
|
||||
bool IsDecl = !VD ||
|
||||
VD->isThisDeclarationADefinition(Context) ==
|
||||
VarDecl::DeclarationOnly;
|
||||
Diag(D->getLocation(),
|
||||
IsDecl ? diag::note_previous_decl : diag::note_defined_here)
|
||||
<< D;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
|
||||
// in a Construct]
|
||||
// Variables with the predetermined data-sharing attributes may not be
|
||||
|
@ -8097,6 +8170,71 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
}
|
||||
}
|
||||
|
||||
// Try to find 'declare reduction' corresponding construct before using
|
||||
// builtin/overloaded operators.
|
||||
CXXCastPath BasePath;
|
||||
ExprResult DeclareReductionRef = buildDeclareReductionRef(
|
||||
*this, ELoc, ERange, DSAStack->getCurScope(), ReductionIdScopeSpec,
|
||||
ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
|
||||
if (DeclareReductionRef.isInvalid())
|
||||
continue;
|
||||
if (CurContext->isDependentContext() &&
|
||||
(DeclareReductionRef.isUnset() ||
|
||||
isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
|
||||
Vars.push_back(RefExpr);
|
||||
Privates.push_back(nullptr);
|
||||
LHSs.push_back(nullptr);
|
||||
RHSs.push_back(nullptr);
|
||||
ReductionOps.push_back(DeclareReductionRef.get());
|
||||
continue;
|
||||
}
|
||||
if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
|
||||
// Not allowed reduction identifier is found.
|
||||
Diag(ReductionId.getLocStart(),
|
||||
diag::err_omp_unknown_reduction_identifier)
|
||||
<< Type << ReductionIdRange;
|
||||
continue;
|
||||
}
|
||||
|
||||
// OpenMP [2.14.3.6, reduction clause, Restrictions]
|
||||
// The type of a list item that appears in a reduction clause must be valid
|
||||
// for the reduction-identifier. For a max or min reduction in C, the type
|
||||
// of the list item must be an allowed arithmetic data type: char, int,
|
||||
// float, double, or _Bool, possibly modified with long, short, signed, or
|
||||
// unsigned. For a max or min reduction in C++, the type of the list item
|
||||
// must be an allowed arithmetic data type: char, wchar_t, int, float,
|
||||
// double, or bool, possibly modified with long, short, signed, or unsigned.
|
||||
if (DeclareReductionRef.isUnset()) {
|
||||
if ((BOK == BO_GT || BOK == BO_LT) &&
|
||||
!(Type->isScalarType() ||
|
||||
(getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
|
||||
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
|
||||
<< getLangOpts().CPlusPlus;
|
||||
if (!ASE && !OASE) {
|
||||
bool IsDecl = !VD ||
|
||||
VD->isThisDeclarationADefinition(Context) ==
|
||||
VarDecl::DeclarationOnly;
|
||||
Diag(D->getLocation(),
|
||||
IsDecl ? diag::note_previous_decl : diag::note_defined_here)
|
||||
<< D;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
|
||||
!getLangOpts().CPlusPlus && Type->isFloatingType()) {
|
||||
Diag(ELoc, diag::err_omp_clause_floating_type_arg);
|
||||
if (!ASE && !OASE) {
|
||||
bool IsDecl = !VD ||
|
||||
VD->isThisDeclarationADefinition(Context) ==
|
||||
VarDecl::DeclarationOnly;
|
||||
Diag(D->getLocation(),
|
||||
IsDecl ? diag::note_previous_decl : diag::note_defined_here)
|
||||
<< D;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
|
||||
auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs",
|
||||
D->hasAttrs() ? &D->getAttrs() : nullptr);
|
||||
|
@ -8123,113 +8261,127 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
D->hasAttrs() ? &D->getAttrs() : nullptr);
|
||||
// Add initializer for private variable.
|
||||
Expr *Init = nullptr;
|
||||
switch (BOK) {
|
||||
case BO_Add:
|
||||
case BO_Xor:
|
||||
case BO_Or:
|
||||
case BO_LOr:
|
||||
// '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
|
||||
if (Type->isScalarType() || Type->isAnyComplexType())
|
||||
Init = ActOnIntegerConstant(ELoc, /*Val=*/0).get();
|
||||
break;
|
||||
case BO_Mul:
|
||||
case BO_LAnd:
|
||||
if (Type->isScalarType() || Type->isAnyComplexType()) {
|
||||
// '*' and '&&' reduction ops - initializer is '1'.
|
||||
Init = ActOnIntegerConstant(ELoc, /*Val=*/1).get();
|
||||
auto *LHSDRE = buildDeclRefExpr(*this, LHSVD, Type, ELoc);
|
||||
auto *RHSDRE = buildDeclRefExpr(*this, RHSVD, Type, ELoc);
|
||||
if (DeclareReductionRef.isUsable()) {
|
||||
auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
|
||||
auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
|
||||
if (DRD->getInitializer()) {
|
||||
Init = DRDRef;
|
||||
RHSVD->setInit(DRDRef);
|
||||
RHSVD->setInitStyle(VarDecl::CallInit);
|
||||
}
|
||||
break;
|
||||
case BO_And: {
|
||||
// '&' reduction op - initializer is '~0'.
|
||||
QualType OrigType = Type;
|
||||
if (auto *ComplexTy = OrigType->getAs<ComplexType>())
|
||||
Type = ComplexTy->getElementType();
|
||||
if (Type->isRealFloatingType()) {
|
||||
llvm::APFloat InitValue =
|
||||
llvm::APFloat::getAllOnesValue(Context.getTypeSize(Type),
|
||||
/*isIEEE=*/true);
|
||||
Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
|
||||
Type, ELoc);
|
||||
} else if (Type->isScalarType()) {
|
||||
auto Size = Context.getTypeSize(Type);
|
||||
QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
|
||||
llvm::APInt InitValue = llvm::APInt::getAllOnesValue(Size);
|
||||
Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
|
||||
}
|
||||
if (Init && OrigType->isAnyComplexType()) {
|
||||
// Init = 0xFFFF + 0xFFFFi;
|
||||
auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
|
||||
Init = CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
|
||||
}
|
||||
Type = OrigType;
|
||||
break;
|
||||
}
|
||||
case BO_LT:
|
||||
case BO_GT: {
|
||||
// 'min' reduction op - initializer is 'Largest representable number in
|
||||
// the reduction list item type'.
|
||||
// 'max' reduction op - initializer is 'Least representable number in
|
||||
// the reduction list item type'.
|
||||
if (Type->isIntegerType() || Type->isPointerType()) {
|
||||
bool IsSigned = Type->hasSignedIntegerRepresentation();
|
||||
auto Size = Context.getTypeSize(Type);
|
||||
QualType IntTy =
|
||||
Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
|
||||
llvm::APInt InitValue =
|
||||
(BOK != BO_LT)
|
||||
? IsSigned ? llvm::APInt::getSignedMinValue(Size)
|
||||
: llvm::APInt::getMinValue(Size)
|
||||
: IsSigned ? llvm::APInt::getSignedMaxValue(Size)
|
||||
: llvm::APInt::getMaxValue(Size);
|
||||
Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
|
||||
if (Type->isPointerType()) {
|
||||
// Cast to pointer type.
|
||||
auto CastExpr = BuildCStyleCastExpr(
|
||||
SourceLocation(), Context.getTrivialTypeSourceInfo(Type, ELoc),
|
||||
SourceLocation(), Init);
|
||||
if (CastExpr.isInvalid())
|
||||
continue;
|
||||
Init = CastExpr.get();
|
||||
} else {
|
||||
switch (BOK) {
|
||||
case BO_Add:
|
||||
case BO_Xor:
|
||||
case BO_Or:
|
||||
case BO_LOr:
|
||||
// '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
|
||||
if (Type->isScalarType() || Type->isAnyComplexType())
|
||||
Init = ActOnIntegerConstant(ELoc, /*Val=*/0).get();
|
||||
break;
|
||||
case BO_Mul:
|
||||
case BO_LAnd:
|
||||
if (Type->isScalarType() || Type->isAnyComplexType()) {
|
||||
// '*' and '&&' reduction ops - initializer is '1'.
|
||||
Init = ActOnIntegerConstant(ELoc, /*Val=*/1).get();
|
||||
}
|
||||
} else if (Type->isRealFloatingType()) {
|
||||
llvm::APFloat InitValue = llvm::APFloat::getLargest(
|
||||
Context.getFloatTypeSemantics(Type), BOK != BO_LT);
|
||||
Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
|
||||
Type, ELoc);
|
||||
break;
|
||||
case BO_And: {
|
||||
// '&' reduction op - initializer is '~0'.
|
||||
QualType OrigType = Type;
|
||||
if (auto *ComplexTy = OrigType->getAs<ComplexType>())
|
||||
Type = ComplexTy->getElementType();
|
||||
if (Type->isRealFloatingType()) {
|
||||
llvm::APFloat InitValue =
|
||||
llvm::APFloat::getAllOnesValue(Context.getTypeSize(Type),
|
||||
/*isIEEE=*/true);
|
||||
Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
|
||||
Type, ELoc);
|
||||
} else if (Type->isScalarType()) {
|
||||
auto Size = Context.getTypeSize(Type);
|
||||
QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
|
||||
llvm::APInt InitValue = llvm::APInt::getAllOnesValue(Size);
|
||||
Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
|
||||
}
|
||||
if (Init && OrigType->isAnyComplexType()) {
|
||||
// Init = 0xFFFF + 0xFFFFi;
|
||||
auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
|
||||
Init = CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
|
||||
}
|
||||
Type = OrigType;
|
||||
break;
|
||||
}
|
||||
case BO_LT:
|
||||
case BO_GT: {
|
||||
// 'min' reduction op - initializer is 'Largest representable number in
|
||||
// the reduction list item type'.
|
||||
// 'max' reduction op - initializer is 'Least representable number in
|
||||
// the reduction list item type'.
|
||||
if (Type->isIntegerType() || Type->isPointerType()) {
|
||||
bool IsSigned = Type->hasSignedIntegerRepresentation();
|
||||
auto Size = Context.getTypeSize(Type);
|
||||
QualType IntTy =
|
||||
Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
|
||||
llvm::APInt InitValue =
|
||||
(BOK != BO_LT)
|
||||
? IsSigned ? llvm::APInt::getSignedMinValue(Size)
|
||||
: llvm::APInt::getMinValue(Size)
|
||||
: IsSigned ? llvm::APInt::getSignedMaxValue(Size)
|
||||
: llvm::APInt::getMaxValue(Size);
|
||||
Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
|
||||
if (Type->isPointerType()) {
|
||||
// Cast to pointer type.
|
||||
auto CastExpr = BuildCStyleCastExpr(
|
||||
SourceLocation(), Context.getTrivialTypeSourceInfo(Type, ELoc),
|
||||
SourceLocation(), Init);
|
||||
if (CastExpr.isInvalid())
|
||||
continue;
|
||||
Init = CastExpr.get();
|
||||
}
|
||||
} else if (Type->isRealFloatingType()) {
|
||||
llvm::APFloat InitValue = llvm::APFloat::getLargest(
|
||||
Context.getFloatTypeSemantics(Type), BOK != BO_LT);
|
||||
Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
|
||||
Type, ELoc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BO_PtrMemD:
|
||||
case BO_PtrMemI:
|
||||
case BO_MulAssign:
|
||||
case BO_Div:
|
||||
case BO_Rem:
|
||||
case BO_Sub:
|
||||
case BO_Shl:
|
||||
case BO_Shr:
|
||||
case BO_LE:
|
||||
case BO_GE:
|
||||
case BO_EQ:
|
||||
case BO_NE:
|
||||
case BO_AndAssign:
|
||||
case BO_XorAssign:
|
||||
case BO_OrAssign:
|
||||
case BO_Assign:
|
||||
case BO_AddAssign:
|
||||
case BO_SubAssign:
|
||||
case BO_DivAssign:
|
||||
case BO_RemAssign:
|
||||
case BO_ShlAssign:
|
||||
case BO_ShrAssign:
|
||||
case BO_Comma:
|
||||
llvm_unreachable("Unexpected reduction operation");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BO_PtrMemD:
|
||||
case BO_PtrMemI:
|
||||
case BO_MulAssign:
|
||||
case BO_Div:
|
||||
case BO_Rem:
|
||||
case BO_Sub:
|
||||
case BO_Shl:
|
||||
case BO_Shr:
|
||||
case BO_LE:
|
||||
case BO_GE:
|
||||
case BO_EQ:
|
||||
case BO_NE:
|
||||
case BO_AndAssign:
|
||||
case BO_XorAssign:
|
||||
case BO_OrAssign:
|
||||
case BO_Assign:
|
||||
case BO_AddAssign:
|
||||
case BO_SubAssign:
|
||||
case BO_DivAssign:
|
||||
case BO_RemAssign:
|
||||
case BO_ShlAssign:
|
||||
case BO_ShrAssign:
|
||||
case BO_Comma:
|
||||
llvm_unreachable("Unexpected reduction operation");
|
||||
}
|
||||
if (Init) {
|
||||
if (Init && DeclareReductionRef.isUnset()) {
|
||||
AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false,
|
||||
/*TypeMayContainAuto=*/false);
|
||||
} else
|
||||
} else if (!Init)
|
||||
ActOnUninitializedDecl(RHSVD, /*TypeMayContainAuto=*/false);
|
||||
if (!RHSVD->hasInit()) {
|
||||
if (RHSVD->isInvalidDecl())
|
||||
continue;
|
||||
if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
|
||||
Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type
|
||||
<< ReductionIdRange;
|
||||
bool IsDecl =
|
||||
|
@ -8244,29 +8396,53 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
// codegen.
|
||||
PrivateVD->setInit(RHSVD->getInit());
|
||||
PrivateVD->setInitStyle(RHSVD->getInitStyle());
|
||||
auto *LHSDRE = buildDeclRefExpr(*this, LHSVD, Type, ELoc);
|
||||
auto *RHSDRE = buildDeclRefExpr(*this, RHSVD, Type, ELoc);
|
||||
auto *PrivateDRE = buildDeclRefExpr(*this, PrivateVD, PrivateTy, ELoc);
|
||||
ExprResult ReductionOp =
|
||||
BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK,
|
||||
LHSDRE, RHSDRE);
|
||||
if (ReductionOp.isUsable()) {
|
||||
if (BOK != BO_LT && BOK != BO_GT) {
|
||||
ReductionOp =
|
||||
BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
|
||||
BO_Assign, LHSDRE, ReductionOp.get());
|
||||
} else {
|
||||
auto *ConditionalOp = new (Context) ConditionalOperator(
|
||||
ReductionOp.get(), SourceLocation(), LHSDRE, SourceLocation(),
|
||||
RHSDRE, Type, VK_LValue, OK_Ordinary);
|
||||
ReductionOp =
|
||||
BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
|
||||
BO_Assign, LHSDRE, ConditionalOp);
|
||||
ExprResult ReductionOp;
|
||||
if (DeclareReductionRef.isUsable()) {
|
||||
QualType RedTy = DeclareReductionRef.get()->getType();
|
||||
QualType PtrRedTy = Context.getPointerType(RedTy);
|
||||
ExprResult LHS = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
|
||||
ExprResult RHS = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
|
||||
if (!BasePath.empty()) {
|
||||
LHS = DefaultLvalueConversion(LHS.get());
|
||||
RHS = DefaultLvalueConversion(RHS.get());
|
||||
LHS = ImplicitCastExpr::Create(Context, PtrRedTy,
|
||||
CK_UncheckedDerivedToBase, LHS.get(),
|
||||
&BasePath, LHS.get()->getValueKind());
|
||||
RHS = ImplicitCastExpr::Create(Context, PtrRedTy,
|
||||
CK_UncheckedDerivedToBase, RHS.get(),
|
||||
&BasePath, RHS.get()->getValueKind());
|
||||
}
|
||||
ReductionOp = ActOnFinishFullExpr(ReductionOp.get());
|
||||
FunctionProtoType::ExtProtoInfo EPI;
|
||||
QualType Params[] = {PtrRedTy, PtrRedTy};
|
||||
QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
|
||||
auto *OVE = new (Context) OpaqueValueExpr(
|
||||
ELoc, Context.getPointerType(FnTy), VK_RValue, OK_Ordinary,
|
||||
DefaultLvalueConversion(DeclareReductionRef.get()).get());
|
||||
Expr *Args[] = {LHS.get(), RHS.get()};
|
||||
ReductionOp = new (Context)
|
||||
CallExpr(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc);
|
||||
} else {
|
||||
ReductionOp = BuildBinOp(DSAStack->getCurScope(),
|
||||
ReductionId.getLocStart(), BOK, LHSDRE, RHSDRE);
|
||||
if (ReductionOp.isUsable()) {
|
||||
if (BOK != BO_LT && BOK != BO_GT) {
|
||||
ReductionOp =
|
||||
BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
|
||||
BO_Assign, LHSDRE, ReductionOp.get());
|
||||
} else {
|
||||
auto *ConditionalOp = new (Context) ConditionalOperator(
|
||||
ReductionOp.get(), SourceLocation(), LHSDRE, SourceLocation(),
|
||||
RHSDRE, Type, VK_LValue, OK_Ordinary);
|
||||
ReductionOp =
|
||||
BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
|
||||
BO_Assign, LHSDRE, ConditionalOp);
|
||||
}
|
||||
ReductionOp = ActOnFinishFullExpr(ReductionOp.get());
|
||||
}
|
||||
if (ReductionOp.isInvalid())
|
||||
continue;
|
||||
}
|
||||
if (ReductionOp.isInvalid())
|
||||
continue;
|
||||
|
||||
DeclRefExpr *Ref = nullptr;
|
||||
Expr *VarsExpr = RefExpr->IgnoreParens();
|
||||
|
@ -9874,10 +10050,14 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
|
|||
PushExpressionEvaluationContext(PotentiallyEvaluated);
|
||||
|
||||
QualType ReductionType = DRD->getType();
|
||||
// Create 'T omp_in;' implicit param.
|
||||
// Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
|
||||
// be replaced by '*omp_parm' during codegen. This required because 'omp_in'
|
||||
// uses semantics of argument handles by value, but it should be passed by
|
||||
// reference. C lang does not support references, so pass all parameters as
|
||||
// pointers.
|
||||
// Create 'T omp_in;' variable.
|
||||
auto *OmpInParm =
|
||||
ImplicitParamDecl::Create(Context, DRD, D->getLocation(),
|
||||
&Context.Idents.get("omp_in"), ReductionType);
|
||||
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
|
||||
// Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
|
||||
// be replaced by '*omp_parm' during codegen. This required because 'omp_out'
|
||||
// uses semantics of argument handles by value, but it should be passed by
|
||||
|
@ -9924,10 +10104,6 @@ void Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
|
|||
PushExpressionEvaluationContext(PotentiallyEvaluated);
|
||||
|
||||
QualType ReductionType = DRD->getType();
|
||||
// Create 'T omp_orig;' implicit param.
|
||||
auto *OmpOrigParm =
|
||||
ImplicitParamDecl::Create(Context, DRD, D->getLocation(),
|
||||
&Context.Idents.get("omp_orig"), ReductionType);
|
||||
// Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
|
||||
// be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
|
||||
// uses semantics of argument handles by value, but it should be passed by
|
||||
|
@ -9936,6 +10112,14 @@ void Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
|
|||
// Create 'T omp_priv;' variable.
|
||||
auto *OmpPrivParm =
|
||||
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
|
||||
// Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
|
||||
// be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
|
||||
// uses semantics of argument handles by value, but it should be passed by
|
||||
// reference. C lang does not support references, so pass all parameters as
|
||||
// pointers.
|
||||
// Create 'T omp_orig;' variable.
|
||||
auto *OmpOrigParm =
|
||||
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
|
||||
if (S != nullptr) {
|
||||
PushOnScopeChains(OmpPrivParm, S);
|
||||
PushOnScopeChains(OmpOrigParm, S);
|
||||
|
|
|
@ -1561,10 +1561,11 @@ public:
|
|||
SourceLocation ColonLoc,
|
||||
SourceLocation EndLoc,
|
||||
CXXScopeSpec &ReductionIdScopeSpec,
|
||||
const DeclarationNameInfo &ReductionId) {
|
||||
const DeclarationNameInfo &ReductionId,
|
||||
ArrayRef<Expr *> UnresolvedReductions) {
|
||||
return getSema().ActOnOpenMPReductionClause(
|
||||
VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, ReductionIdScopeSpec,
|
||||
ReductionId);
|
||||
ReductionId, UnresolvedReductions);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'linear' clause.
|
||||
|
@ -7791,9 +7792,31 @@ TreeTransform<Derived>::TransformOMPReductionClause(OMPReductionClause *C) {
|
|||
if (!NameInfo.getName())
|
||||
return nullptr;
|
||||
}
|
||||
// Build a list of all UDR decls with the same names ranged by the Scopes.
|
||||
// The Scope boundary is a duplication of the previous decl.
|
||||
llvm::SmallVector<Expr *, 16> UnresolvedReductions;
|
||||
for (auto *E : C->reduction_ops()) {
|
||||
// Transform all the decls.
|
||||
if (E) {
|
||||
auto *ULE = cast<UnresolvedLookupExpr>(E);
|
||||
UnresolvedSet<8> Decls;
|
||||
for (auto *D : ULE->decls()) {
|
||||
NamedDecl *InstD =
|
||||
cast<NamedDecl>(getDerived().TransformDecl(E->getExprLoc(), D));
|
||||
Decls.addDecl(InstD, InstD->getAccess());
|
||||
}
|
||||
UnresolvedReductions.push_back(
|
||||
UnresolvedLookupExpr::Create(
|
||||
SemaRef.Context, /*NamingClass=*/nullptr,
|
||||
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context),
|
||||
NameInfo, /*ADL=*/true, ULE->isOverloaded(),
|
||||
Decls.begin(), Decls.end()));
|
||||
} else
|
||||
UnresolvedReductions.push_back(nullptr);
|
||||
}
|
||||
return getDerived().RebuildOMPReductionClause(
|
||||
Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
|
||||
C->getLocEnd(), ReductionIdScopeSpec, NameInfo);
|
||||
C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -x c -emit-llvm %s -triple %itanium_abi_triple -o - -femit-all-decls | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -emit-pch -o %t %s -femit-all-decls
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls | FileCheck --check-prefix=CHECK-LOAD %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -x c -emit-llvm %s -triple %itanium_abi_triple -o - -femit-all-decls -disable-llvm-optzns | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -emit-pch -o %t %s -femit-all-decls -disable-llvm-optzns
|
||||
// RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-optzns | FileCheck --check-prefix=CHECK-LOAD %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls | FileCheck --check-prefix=CHECK-LOAD %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-optzns | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-optzns
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-optzns | FileCheck --check-prefix=CHECK-LOAD %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
|
|
|
@ -59,7 +59,7 @@ class Class2 : public Class1<T> {
|
|||
#pragma omp declare reduction(fun77 : long : omp_out += omp_in) initializer(omp_priv Class2 < int > ()) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp declare reduction(fun8 : long : omp_out += omp_in) initializer(omp_priv 23) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp declare reduction(fun88 : long : omp_out += omp_in) initializer(omp_priv 23)) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{extra tokens at the end of '#pragma omp declare reduction' are ignored}}
|
||||
#pragma omp declare reduction(fun9 : long : omp_out += omp_priv) initializer(omp_in = 23) // expected-error {{use of undeclared identifier 'omp_priv'; did you mean 'omp_in'?}} expected-note {{'omp_in' is an implicit parameter}}
|
||||
#pragma omp declare reduction(fun9 : long : omp_out += omp_priv) initializer(omp_in = 23) // expected-error {{use of undeclared identifier 'omp_priv'; did you mean 'omp_in'?}} expected-note {{'omp_in' declared here}}
|
||||
#pragma omp declare reduction(fun10 : long : omp_out += omp_in) initializer(omp_priv = 23)
|
||||
|
||||
template <typename T>
|
||||
|
@ -75,15 +75,34 @@ T fun(T arg) {
|
|||
|
||||
template <typename T>
|
||||
T foo(T arg) {
|
||||
T i;
|
||||
{
|
||||
#pragma omp declare reduction(red : T : omp_out++)
|
||||
#pragma omp declare reduction(red1 : T : omp_out++) // expected-note {{previous definition is here}}
|
||||
#pragma omp declare reduction(red1 : int : omp_out++) // expected-error {{redefinition of user-defined reduction for type 'int'}}
|
||||
#pragma omp parallel reduction (red : i)
|
||||
{
|
||||
}
|
||||
#pragma omp parallel reduction (red1 : i)
|
||||
{
|
||||
}
|
||||
#pragma omp parallel reduction (red2 : i) // expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
{
|
||||
}
|
||||
}
|
||||
{
|
||||
#pragma omp declare reduction(red1 : int : omp_out++) // expected-note {{previous definition is here}}
|
||||
#pragma omp declare reduction(red : T : omp_out++)
|
||||
#pragma omp declare reduction(red1 : T : omp_out++) // expected-error {{redefinition of user-defined reduction for type 'int'}}
|
||||
#pragma omp parallel reduction (red : i)
|
||||
{
|
||||
}
|
||||
#pragma omp parallel reduction (red1 : i)
|
||||
{
|
||||
}
|
||||
#pragma omp parallel reduction (red2 : i) // expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
{
|
||||
}
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
@ -92,14 +111,13 @@ T foo(T arg) {
|
|||
int main() {
|
||||
Class1<int> c1;
|
||||
int i;
|
||||
// TODO: Add support for scoped reduction identifiers
|
||||
// #pragma omp parallel reduction (::fun : c1)
|
||||
#pragma omp parallel reduction (::fun : c1)
|
||||
{
|
||||
}
|
||||
// #pragma omp parallel reduction (::Class1<int>::fun : c1)
|
||||
#pragma omp parallel reduction (::Class1<int>::fun : c1)
|
||||
{
|
||||
}
|
||||
// #pragma omp parallel reduction (::Class2<int>::fun : i)
|
||||
#pragma omp parallel reduction (::Class2<int>::fun : i) // expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
{
|
||||
}
|
||||
return fun(15) + foo(15); // expected-note {{in instantiation of function template specialization 'foo<int>' requested here}}
|
||||
|
|
|
@ -143,7 +143,7 @@ int foomain(int argc, char **argv) {
|
|||
foo();
|
||||
#pragma omp parallel reduction(+ : i) // expected-note {{defined as reduction}}
|
||||
#pragma omp for firstprivate(i) // expected-error {{firstprivate variable must be shared}}
|
||||
for (i = 0; i < argc; ++i)
|
||||
for (int k = 0; k < argc; ++k)
|
||||
foo();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,980 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
|
||||
// expected-no-diagnostics
|
||||
// REQUIRES: x86-registered-target
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
volatile double g, g_orig;
|
||||
volatile double &g1 = g_orig;
|
||||
|
||||
struct BaseS {
|
||||
int x;
|
||||
};
|
||||
struct BaseS1 {
|
||||
float y;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct S : public BaseS, public BaseS1 {
|
||||
T f;
|
||||
S(T a) : f(a + g) {}
|
||||
S() : f(g) {}
|
||||
~S() {}
|
||||
};
|
||||
void red(BaseS1&, const BaseS1&);
|
||||
void red_plus(BaseS1&, const BaseS1&);
|
||||
void init(BaseS1&, const BaseS1&);
|
||||
void init1(BaseS1&, const BaseS1&);
|
||||
void init2(BaseS1&, const BaseS1&);
|
||||
void init_plus(BaseS1&, const BaseS1&);
|
||||
#pragma omp declare reduction(operator& : BaseS1 : red(omp_out, omp_in)) initializer(init(omp_priv, omp_orig))
|
||||
#pragma omp declare reduction(+ : BaseS1 : red_plus(omp_out, omp_in)) initializer(init_plus(omp_priv, omp_orig))
|
||||
#pragma omp declare reduction(&& : S<float>, S<int> : omp_out.f *= omp_in.f) initializer(init1(omp_priv, omp_orig))
|
||||
|
||||
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { %{{[^,]+}}, %{{[^,]+}}, float }
|
||||
// CHECK-DAG: [[S_INT_TY:%.+]] = type { %{{[^,]+}}, %{{[^,]+}}, i{{[0-9]+}} }
|
||||
// CHECK-DAG: [[ATOMIC_REDUCE_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
|
||||
// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
|
||||
// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
|
||||
// CHECK-DAG: [[REDUCTION_LOCK:@.+]] = common global [8 x i32] zeroinitializer
|
||||
|
||||
#pragma omp declare reduction(operator&& : int : omp_out = 111 & omp_in)
|
||||
template <typename T>
|
||||
T tmain() {
|
||||
T t;
|
||||
S<T> test;
|
||||
T t_var = T(), t_var1;
|
||||
T vec[] = {1, 2};
|
||||
S<T> s_arr[] = {1, 2};
|
||||
S<T> &var = test;
|
||||
S<T> var1;
|
||||
#pragma omp declare reduction(operator& : T : omp_out = 15 + omp_in)
|
||||
#pragma omp declare reduction(operator+ : T : omp_out = 1513 + omp_in) initializer(omp_priv = 321)
|
||||
#pragma omp declare reduction(min : T : omp_out = 47 - omp_in) initializer(omp_priv = 432 / omp_orig)
|
||||
#pragma omp declare reduction(operator&& : S<T> : omp_out.f = 17 * omp_in.f) initializer(init2(omp_priv, omp_orig))
|
||||
#pragma omp declare reduction(operator&& : T : omp_out = 17 * omp_in)
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(+ : t_var) reduction(& : var) reduction(&& : var1) reduction(min : t_var1) nowait
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
vec[i] = t_var;
|
||||
s_arr[i] = var;
|
||||
}
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(&& : t_var)
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
vec[i] = t_var;
|
||||
s_arr[i] = var;
|
||||
}
|
||||
return T();
|
||||
}
|
||||
|
||||
extern S<float> **foo();
|
||||
|
||||
#pragma omp declare reduction(operator- : float, double : omp_out = 333 + omp_in)
|
||||
#pragma omp declare reduction(min : float, double : omp_out = 555 + omp_in)
|
||||
int main() {
|
||||
#pragma omp declare reduction(operator+ : float, double : omp_out = 222 - omp_in) initializer(omp_priv = -1)
|
||||
S<float> test;
|
||||
float t_var = 0, t_var1;
|
||||
int vec[] = {1, 2};
|
||||
S<float> s_arr[] = {1, 2};
|
||||
S<float> &var = test;
|
||||
S<float> var1, arrs[10][4];
|
||||
S<float> **var2 = foo();
|
||||
S<float> vvar2[2];
|
||||
S<float>(&var3)[2] = s_arr;
|
||||
#pragma omp declare reduction(operator+ : int : omp_out = 555 * omp_in) initializer(omp_priv = 888)
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(+ : t_var) reduction(& : var) reduction(&& : var1) reduction(min : t_var1)
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
vec[i] = t_var;
|
||||
s_arr[i] = var;
|
||||
}
|
||||
int arr[10][vec[1]];
|
||||
#pragma omp parallel for reduction(+ : arr[1][ : vec[1]]) reduction(& : arrs[1 : vec[1]][1 : 2])
|
||||
for (int i = 0; i < 10; ++i)
|
||||
++arr[1][i];
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(+ : arr) reduction(& : arrs)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
++arr[1][i];
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(& : var2[0 : 5][1 : 6])
|
||||
for (int i = 0; i < 10; ++i)
|
||||
;
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(& : vvar2[0 : 5])
|
||||
for (int i = 0; i < 10; ++i)
|
||||
;
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(& : var3[1 : 2])
|
||||
for (int i = 0; i < 10; ++i)
|
||||
;
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(& : var3)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
;
|
||||
return tmain<int>();
|
||||
}
|
||||
|
||||
// CHECK: define {{.*}}i{{[0-9]+}} @main()
|
||||
// CHECK: [[TEST:%.+]] = alloca [[S_FLOAT_TY]],
|
||||
// CHECK: call {{.*}} [[S_FLOAT_TY_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
|
||||
// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 6, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, float*, [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]*, float*, [2 x i32]*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK:@.+]] to void
|
||||
// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 5, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, i64, i64, i32*, [2 x i32]*, [10 x [4 x [[S_FLOAT_TY]]]]*)* [[MAIN_MICROTASK1:@.+]] to void
|
||||
// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 4, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, i64, i64, i32*, [10 x [4 x [[S_FLOAT_TY]]]]*)* [[MAIN_MICROTASK2:@.+]] to void
|
||||
// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[S_FLOAT_TY]]***)* [[MAIN_MICROTASK3:@.+]] to void
|
||||
// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK4:@.+]] to void
|
||||
// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK5:@.+]] to void
|
||||
// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK6:@.+]] to void
|
||||
// CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()
|
||||
// CHECK: call {{.*}} [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]*
|
||||
// CHECK: ret
|
||||
//
|
||||
// CHECK: define internal void [[MAIN_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, float* dereferenceable(4) %{{.+}}, [[S_FLOAT_TY]]* dereferenceable(12) %{{.+}}, [[S_FLOAT_TY]]* dereferenceable(12) %{{.+}}, float* dereferenceable(4) %{{.+}}, [2 x i32]* dereferenceable(8) %vec, [2 x [[S_FLOAT_TY]]]* dereferenceable(24) %{{.+}})
|
||||
// CHECK: [[T_VAR_PRIV:%.+]] = alloca float,
|
||||
// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
|
||||
// CHECK: [[VAR1_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
|
||||
// CHECK: [[T_VAR1_PRIV:%.+]] = alloca float,
|
||||
|
||||
// Reduction list for runtime.
|
||||
// CHECK: [[RED_LIST:%.+]] = alloca [4 x i8*],
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// CHECK: [[T_VAR_REF:%.+]] = load float*, float** %
|
||||
// CHECK: [[VAR1_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** %
|
||||
// CHECK: [[T_VAR1_REF:%.+]] = load float*, float** %
|
||||
|
||||
// For + reduction operation initial value of private variable is -1.
|
||||
// CHECK: store float -1.0{{.+}}, float*
|
||||
|
||||
// For & reduction operation initial value of private variable is defined by call of 'init()' function.
|
||||
// CHECK: call {{.*}}void @_Z4initR6BaseS1RKS_(
|
||||
|
||||
// For && reduction operation initial value of private variable is 1.0.
|
||||
// CHECK: call {{.*}}void @_Z5init1R6BaseS1RKS_(
|
||||
|
||||
// For min reduction operation initial value of private variable is largest repesentable value.
|
||||
// CHECK: [[INIT:%.+]] = load float, float* @
|
||||
// CHECK: store float [[INIT]], float* [[T_VAR1_PRIV]],
|
||||
|
||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// Skip checks for internal operations.
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
||||
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
|
||||
|
||||
// CHECK: [[T_VAR_PRIV_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 0
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast float* [[T_VAR_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[T_VAR_PRIV_REF]],
|
||||
// CHECK: [[VAR_PRIV_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 1
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[VAR_PRIV_REF]],
|
||||
// CHECK: [[VAR1_PRIV_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 2
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR1_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[VAR1_PRIV_REF]],
|
||||
// CHECK: [[T_VAR1_PRIV_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 3
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast float* [[T_VAR1_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[T_VAR1_PRIV_REF]],
|
||||
|
||||
// res = __kmpc_reduce(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>);
|
||||
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast [4 x i8*]* [[RED_LIST]] to i8*
|
||||
// CHECK: [[RES:%.+]] = call i32 @__kmpc_reduce(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], i32 4, i64 32, i8* [[BITCAST]], void (i8*, i8*)* [[REDUCTION_FUNC:@.+]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||
|
||||
// switch(res)
|
||||
// CHECK: switch i32 [[RES]], label %[[RED_DONE:.+]] [
|
||||
// CHECK: i32 1, label %[[CASE1:.+]]
|
||||
// CHECK: i32 2, label %[[CASE2:.+]]
|
||||
// CHECK: ]
|
||||
|
||||
// case 1:
|
||||
// t_var += t_var_reduction;
|
||||
// CHECK: fsub float 2.220000e+02, %
|
||||
|
||||
// var = var.operator &(var_reduction);
|
||||
// CHECK: call {{.*}}void @_Z3redR6BaseS1RKS_(
|
||||
|
||||
// var1 = var1.operator &&(var1_reduction);
|
||||
// CHECK: fmul float
|
||||
|
||||
// t_var1 = min(t_var1, t_var1_reduction);
|
||||
// CHECK: fadd float 5.550000e+02, %
|
||||
|
||||
// __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
|
||||
// CHECK: call void @__kmpc_end_reduce(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||
|
||||
// break;
|
||||
// CHECK: br label %[[RED_DONE]]
|
||||
|
||||
// case 2:
|
||||
// t_var += t_var_reduction;
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: fsub float 2.220000e+02, %
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
|
||||
// var = var.operator &(var_reduction);
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: call {{.*}}void @_Z3redR6BaseS1RKS_(
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
|
||||
// var1 = var1.operator &&(var1_reduction);
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: fmul float
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
|
||||
// t_var1 = min(t_var1, t_var1_reduction);
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: fadd float 5.550000e+02, %
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
|
||||
// __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
|
||||
// CHECK: call void @__kmpc_end_reduce(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||
|
||||
// break;
|
||||
// CHECK: br label %[[RED_DONE]]
|
||||
// CHECK: [[RED_DONE]]
|
||||
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
|
||||
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
|
||||
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||
|
||||
// CHECK: ret void
|
||||
|
||||
// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
|
||||
// *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
|
||||
// ...
|
||||
// *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
|
||||
// *(Type<n>-1*)rhs[<n>-1]);
|
||||
// }
|
||||
// CHECK: define internal void [[REDUCTION_FUNC]](i8*, i8*)
|
||||
// t_var_lhs = (float*)lhs[0];
|
||||
// CHECK: [[T_VAR_RHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_RHS:%.+]], i64 0, i64 0
|
||||
// CHECK: [[T_VAR_RHS_VOID:%.+]] = load i8*, i8** [[T_VAR_RHS_REF]],
|
||||
// CHECK: [[T_VAR_RHS:%.+]] = bitcast i8* [[T_VAR_RHS_VOID]] to float*
|
||||
// t_var_rhs = (float*)rhs[0];
|
||||
// CHECK: [[T_VAR_LHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS:%.+]], i64 0, i64 0
|
||||
// CHECK: [[T_VAR_LHS_VOID:%.+]] = load i8*, i8** [[T_VAR_LHS_REF]],
|
||||
// CHECK: [[T_VAR_LHS:%.+]] = bitcast i8* [[T_VAR_LHS_VOID]] to float*
|
||||
|
||||
// var_lhs = (S<float>*)lhs[1];
|
||||
// CHECK: [[VAR_RHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_RHS]], i64 0, i64 1
|
||||
// CHECK: [[VAR_RHS_VOID:%.+]] = load i8*, i8** [[VAR_RHS_REF]],
|
||||
// CHECK: [[VAR_RHS:%.+]] = bitcast i8* [[VAR_RHS_VOID]] to [[S_FLOAT_TY]]*
|
||||
// var_rhs = (S<float>*)rhs[1];
|
||||
// CHECK: [[VAR_LHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS]], i64 0, i64 1
|
||||
// CHECK: [[VAR_LHS_VOID:%.+]] = load i8*, i8** [[VAR_LHS_REF]],
|
||||
// CHECK: [[VAR_LHS:%.+]] = bitcast i8* [[VAR_LHS_VOID]] to [[S_FLOAT_TY]]*
|
||||
|
||||
// var1_lhs = (S<float>*)lhs[2];
|
||||
// CHECK: [[VAR1_RHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_RHS]], i64 0, i64 2
|
||||
// CHECK: [[VAR1_RHS_VOID:%.+]] = load i8*, i8** [[VAR1_RHS_REF]],
|
||||
// CHECK: [[VAR1_RHS:%.+]] = bitcast i8* [[VAR1_RHS_VOID]] to [[S_FLOAT_TY]]*
|
||||
// var1_rhs = (S<float>*)rhs[2];
|
||||
// CHECK: [[VAR1_LHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS]], i64 0, i64 2
|
||||
// CHECK: [[VAR1_LHS_VOID:%.+]] = load i8*, i8** [[VAR1_LHS_REF]],
|
||||
// CHECK: [[VAR1_LHS:%.+]] = bitcast i8* [[VAR1_LHS_VOID]] to [[S_FLOAT_TY]]*
|
||||
|
||||
// t_var1_lhs = (float*)lhs[3];
|
||||
// CHECK: [[T_VAR1_RHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_RHS]], i64 0, i64 3
|
||||
// CHECK: [[T_VAR1_RHS_VOID:%.+]] = load i8*, i8** [[T_VAR1_RHS_REF]],
|
||||
// CHECK: [[T_VAR1_RHS:%.+]] = bitcast i8* [[T_VAR1_RHS_VOID]] to float*
|
||||
// t_var1_rhs = (float*)rhs[3];
|
||||
// CHECK: [[T_VAR1_LHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS]], i64 0, i64 3
|
||||
// CHECK: [[T_VAR1_LHS_VOID:%.+]] = load i8*, i8** [[T_VAR1_LHS_REF]],
|
||||
// CHECK: [[T_VAR1_LHS:%.+]] = bitcast i8* [[T_VAR1_LHS_VOID]] to float*
|
||||
|
||||
// t_var_lhs += t_var_rhs;
|
||||
// CHECK: fsub float 2.220000e+02, %
|
||||
|
||||
// var_lhs = var_lhs.operator &(var_rhs);
|
||||
// CHECK: call {{.*}}void @_Z3redR6BaseS1RKS_(
|
||||
|
||||
// var1_lhs = var1_lhs.operator &&(var1_rhs);
|
||||
// CHECK: fmul float
|
||||
|
||||
// t_var1_lhs = min(t_var1_lhs, t_var1_rhs);
|
||||
// CHECK: fadd float 5.550000e+02, %
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void [[MAIN_MICROTASK1]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, i64 %{{.+}}, i64 %{{.+}}, i32* nonnull %{{.+}}, [2 x i32]* dereferenceable(8) %{{.+}}, [10 x [4 x [[S_FLOAT_TY]]]]* dereferenceable(480) %{{.+}})
|
||||
|
||||
// Reduction list for runtime.
|
||||
// CHECK: [[RED_LIST:%.+]] = alloca [4 x i8*],
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// CHECK: [[IDX1:%.+]] = mul nsw i64 1, %{{.+}}
|
||||
// CHECK: [[LB1:%.+]] = getelementptr inbounds i32, i32* %{{.+}}, i64 [[IDX1]]
|
||||
// CHECK: [[LB1_0:%.+]] = getelementptr inbounds i32, i32* [[LB1]], i64 0
|
||||
// CHECK: [[IDX1:%.+]] = mul nsw i64 1, %{{.+}}
|
||||
// CHECK: [[UB1:%.+]] = getelementptr inbounds i32, i32* %{{.+}}, i64 [[IDX1]]
|
||||
// CHECK: [[UB1_UP:%.+]] = getelementptr inbounds i32, i32* [[UB1]], i64 %
|
||||
// CHECK: [[UB_CAST:%.+]] = ptrtoint i32* [[UB1_UP]] to i64
|
||||
// CHECK: [[LB_CAST:%.+]] = ptrtoint i32* [[LB1_0]] to i64
|
||||
// CHECK: [[DIFF:%.+]] = sub i64 [[UB_CAST]], [[LB_CAST]]
|
||||
// CHECK: [[SIZE_1:%.+]] = sdiv exact i64 [[DIFF]], ptrtoint (i32* getelementptr (i32, i32* null, i32 1) to i64)
|
||||
// CHECK: [[ARR_SIZE:%.+]] = add nuw i64 [[SIZE_1]], 1
|
||||
// CHECK: call i8* @llvm.stacksave()
|
||||
// CHECK: [[ARR_PRIV:%.+]] = alloca i32, i64 [[ARR_SIZE]],
|
||||
|
||||
// Check initialization of private copy.
|
||||
// CHECK: [[END:%.+]] = getelementptr i32, i32* [[ARR_PRIV]], i64 [[ARR_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq i32* [[ARR_PRIV]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi i32*
|
||||
// CHECK: store i32 888, i32* %
|
||||
// CHECK: [[DONE:%.+]] = icmp eq i32* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// CHECK: [[ARRS_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[ARRS_SIZE:%.+]],
|
||||
|
||||
// Check initialization of private copy.
|
||||
// CHECK: [[END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[ARRS_PRIV]], i64 [[ARRS_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[ARRS_PRIV]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi [[S_FLOAT_TY]]*
|
||||
// CHECK: call void @_Z4initR6BaseS1RKS_(%
|
||||
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// Skip checks for internal operations.
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
||||
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
|
||||
|
||||
// CHECK: [[ARR_PRIV_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 0
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast i32* [[ARR_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[ARR_PRIV_REF]],
|
||||
// CHECK: [[ARR_SIZE_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 1
|
||||
// CHECK: [[BITCAST:%.+]] = inttoptr i64 [[ARR_SIZE]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[ARR_SIZE_REF]],
|
||||
// CHECK: [[ARRS_PRIV_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 2
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[ARRS_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[ARRS_PRIV_REF]],
|
||||
// CHECK: [[ARRS_SIZE_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 3
|
||||
// CHECK: [[BITCAST:%.+]] = inttoptr i64 [[ARRS_SIZE]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[ARRS_SIZE_REF]],
|
||||
|
||||
// res = __kmpc_reduce(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>);
|
||||
|
||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast [4 x i8*]* [[RED_LIST]] to i8*
|
||||
// CHECK: [[RES:%.+]] = call i32 @__kmpc_reduce_nowait(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], i32 2, i64 32, i8* [[BITCAST]], void (i8*, i8*)* [[REDUCTION_FUNC:@.+]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||
|
||||
// switch(res)
|
||||
// CHECK: switch i32 [[RES]], label %[[RED_DONE:.+]] [
|
||||
// CHECK: i32 1, label %[[CASE1:.+]]
|
||||
// CHECK: i32 2, label %[[CASE2:.+]]
|
||||
// CHECK: ]
|
||||
|
||||
// case 1:
|
||||
// CHECK: [[CASE1]]
|
||||
|
||||
// arr[:] += arr_reduction[:];
|
||||
// CHECK: [[END:%.+]] = getelementptr i32, i32* [[LB1_0]], i64 [[ARR_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq i32* [[LB1_0]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi i32*
|
||||
// CHECK: [[ADD:%.+]] = mul nsw i32 555, %
|
||||
// CHECK: store i32 [[ADD]], i32* %
|
||||
// CHECK: [[DONE:%.+]] = icmp eq i32* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// arrs[:] = var.operator &(arrs_reduction[:]);
|
||||
// CHECK: [[END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[ARRS_LB:%.+]], i64 [[ARRS_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[ARRS_LB]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi [[S_FLOAT_TY]]*
|
||||
// CHECK: call void @_Z3redR6BaseS1RKS_(%
|
||||
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
|
||||
// CHECK: call void @__kmpc_end_reduce_nowait(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||
|
||||
// break;
|
||||
// CHECK: br label %[[RED_DONE]]
|
||||
|
||||
// case 2:
|
||||
// CHECK: [[CASE2]]
|
||||
|
||||
// arr[:] += arr_reduction[:];
|
||||
// CHECK: [[END:%.+]] = getelementptr i32, i32* [[LB1_0]], i64 [[ARR_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq i32* [[LB1_0]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi i32*
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: [[ADD:%.+]] = mul nsw i32 555, %
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
// CHECK: [[DONE:%.+]] = icmp eq i32* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// arrs[:] = var.operator &(arrs_reduction[:]);
|
||||
// CHECK: [[END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[ARRS_LB:%.+]], i64 [[ARRS_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[ARRS_LB]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi [[S_FLOAT_TY]]*
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: call void @_Z3redR6BaseS1RKS_(%
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// break;
|
||||
// CHECK: br label %[[RED_DONE]]
|
||||
// CHECK: [[RED_DONE]]
|
||||
|
||||
// Check destruction of private copy.
|
||||
// CHECK: [[END:%.+]] = getelementptr inbounds [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[ARRS_PRIV]], i64 [[ARRS_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[ARRS_PRIV]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi [[S_FLOAT_TY]]*
|
||||
// CHECK: call void @_ZN1SIfED1Ev([[S_FLOAT_TY]]* %
|
||||
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[ARRS_PRIV]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
// CHECK: call void @llvm.stackrestore(i8*
|
||||
|
||||
// CHECK: ret void
|
||||
|
||||
// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
|
||||
// *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
|
||||
// ...
|
||||
// *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
|
||||
// *(Type<n>-1*)rhs[<n>-1]);
|
||||
// }
|
||||
// CHECK: define internal void [[REDUCTION_FUNC]](i8*, i8*)
|
||||
// arr_rhs = (int*)rhs[0];
|
||||
// CHECK: [[ARR_RHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_RHS:%.+]], i64 0, i64 0
|
||||
// CHECK: [[ARR_RHS_VOID:%.+]] = load i8*, i8** [[ARR_RHS_REF]],
|
||||
// CHECK: [[ARR_RHS:%.+]] = bitcast i8* [[ARR_RHS_VOID]] to i32*
|
||||
// arr_lhs = (int*)lhs[0];
|
||||
// CHECK: [[ARR_LHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS:%.+]], i64 0, i64 0
|
||||
// CHECK: [[ARR_LHS_VOID:%.+]] = load i8*, i8** [[ARR_LHS_REF]],
|
||||
// CHECK: [[ARR_LHS:%.+]] = bitcast i8* [[ARR_LHS_VOID]] to i32*
|
||||
|
||||
// arr_size = (size_t)lhs[1];
|
||||
// CHECK: [[ARR_SIZE_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS]], i64 0, i64 1
|
||||
// CHECK: [[ARR_SIZE_VOID:%.+]] = load i8*, i8** [[ARR_SIZE_REF]],
|
||||
// CHECK: [[ARR_SIZE:%.+]] = ptrtoint i8* [[ARR_SIZE_VOID]] to i64
|
||||
|
||||
// arrs_rhs = (S<float>*)rhs[2];
|
||||
// CHECK: [[ARRS_RHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_RHS]], i64 0, i64 2
|
||||
// CHECK: [[ARRS_RHS_VOID:%.+]] = load i8*, i8** [[ARRS_RHS_REF]],
|
||||
// CHECK: [[ARRS_RHS:%.+]] = bitcast i8* [[ARRS_RHS_VOID]] to [[S_FLOAT_TY]]*
|
||||
// arrs_lhs = (S<float>*)lhs[2];
|
||||
// CHECK: [[ARRS_LHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS]], i64 0, i64 2
|
||||
// CHECK: [[ARRS_LHS_VOID:%.+]] = load i8*, i8** [[ARRS_LHS_REF]],
|
||||
// CHECK: [[ARRS_LHS:%.+]] = bitcast i8* [[ARRS_LHS_VOID]] to [[S_FLOAT_TY]]*
|
||||
|
||||
// arrs_size = (size_t)lhs[3];
|
||||
// CHECK: [[ARRS_SIZE_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS]], i64 0, i64 3
|
||||
// CHECK: [[ARRS_SIZE_VOID:%.+]] = load i8*, i8** [[ARRS_SIZE_REF]],
|
||||
// CHECK: [[ARRS_SIZE:%.+]] = ptrtoint i8* [[ARRS_SIZE_VOID]] to i64
|
||||
|
||||
// arr_lhs[:] += arr_rhs[:];
|
||||
// CHECK: [[END:%.+]] = getelementptr i32, i32* [[ARR_LHS]], i64 [[ARR_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq i32* [[ARR_LHS]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi i32*
|
||||
// CHECK: [[ADD:%.+]] = mul nsw i32 555, %
|
||||
// CHECK: [[DONE:%.+]] = icmp eq i32* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// arrs_lhs = arrs_lhs.operator &(arrs_rhs);
|
||||
// CHECK: [[END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[ARRS_LB:%.+]], i64 [[ARRS_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[ARRS_LB]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi [[S_FLOAT_TY]]*
|
||||
// CHECK: call void @_Z3redR6BaseS1RKS_(%
|
||||
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void [[MAIN_MICROTASK2]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, i64 %{{.+}}, i64 %{{.+}}, i32* nonnull %{{.+}}, [10 x [4 x [[S_FLOAT_TY]]]]* dereferenceable(480) %{{.+}})
|
||||
|
||||
// CHECK: [[ARRS_PRIV:%.+]] = alloca [10 x [4 x [[S_FLOAT_TY]]]],
|
||||
|
||||
// Reduction list for runtime.
|
||||
// CHECK: [[RED_LIST:%.+]] = alloca [3 x i8*],
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// CHECK: [[ARR_SIZE:%.+]] = mul nuw i64 %{{.+}}, 4
|
||||
// CHECK: call i8* @llvm.stacksave()
|
||||
// CHECK: [[ARR_PRIV:%.+]] = alloca i32, i64 [[ARR_SIZE]],
|
||||
|
||||
// Check initialization of private copy.
|
||||
// CHECK: [[END:%.+]] = getelementptr i32, i32* [[ARR_PRIV]], i64 [[ARR_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq i32* [[ARR_PRIV]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi i32*
|
||||
// CHECK: store i32 888, i32* %
|
||||
// CHECK: [[DONE:%.+]] = icmp eq i32* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// Check initialization of private copy.
|
||||
// CHECK: [[LHS_BEGIN:%.+]] = bitcast [10 x [4 x [[S_FLOAT_TY]]]]* %{{.+}} to [[S_FLOAT_TY]]*
|
||||
// CHECK: [[BEGIN:%.+]] = getelementptr inbounds [10 x [4 x [[S_FLOAT_TY]]]], [10 x [4 x [[S_FLOAT_TY]]]]* [[ARRS_PRIV]], i32 0, i32 0, i32 0
|
||||
// CHECK: [[END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[BEGIN]], i64 40
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[BEGIN]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi [[S_FLOAT_TY]]*
|
||||
// CHECK: call void @_Z4initR6BaseS1RKS_(%
|
||||
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
// CHECK: [[ARRS_PRIV_BEGIN:%.+]] = bitcast [10 x [4 x [[S_FLOAT_TY]]]]* [[ARRS_PRIV]] to [[S_FLOAT_TY]]*
|
||||
|
||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// Skip checks for internal operations.
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
||||
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
|
||||
|
||||
// CHECK: [[ARR_PRIV_REF:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[RED_LIST]], i64 0, i64 0
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast i32* [[ARR_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[ARR_PRIV_REF]],
|
||||
// CHECK: [[ARR_SIZE_REF:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[RED_LIST]], i64 0, i64 1
|
||||
// CHECK: [[BITCAST:%.+]] = inttoptr i64 [[ARR_SIZE]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[ARR_SIZE_REF]],
|
||||
// CHECK: [[ARRS_PRIV_REF:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[RED_LIST]], i64 0, i64 2
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[ARRS_PRIV_BEGIN]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[ARRS_PRIV_REF]],
|
||||
|
||||
// res = __kmpc_reduce(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>);
|
||||
|
||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast [3 x i8*]* [[RED_LIST]] to i8*
|
||||
// CHECK: [[RES:%.+]] = call i32 @__kmpc_reduce(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], i32 2, i64 24, i8* [[BITCAST]], void (i8*, i8*)* [[REDUCTION_FUNC:@.+]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||
|
||||
// switch(res)
|
||||
// CHECK: switch i32 [[RES]], label %[[RED_DONE:.+]] [
|
||||
// CHECK: i32 1, label %[[CASE1:.+]]
|
||||
// CHECK: i32 2, label %[[CASE2:.+]]
|
||||
// CHECK: ]
|
||||
|
||||
// case 1:
|
||||
// CHECK: [[CASE1]]
|
||||
|
||||
// arr[:] += arr_reduction[:];
|
||||
// CHECK: [[END:%.+]] = getelementptr i32, i32* [[LB1_0:%.+]], i64 [[ARR_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq i32* [[LB1_0]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi i32*
|
||||
// CHECK: [[ADD:%[^ ]+]] = mul nsw i32 555, %
|
||||
// CHECK: store i32 [[ADD]], i32* %
|
||||
// CHECK: [[DONE:%.+]] = icmp eq i32* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// arrs[:] = var.operator &(arrs_reduction[:]);
|
||||
// CHECK: [[END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[LHS_BEGIN]], i64 40
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[LHS_BEGIN]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi [[S_FLOAT_TY]]*
|
||||
// CHECK: call void @_Z3redR6BaseS1RKS_(%
|
||||
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
|
||||
// CHECK: call void @__kmpc_end_reduce(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||
|
||||
// break;
|
||||
// CHECK: br label %[[RED_DONE]]
|
||||
|
||||
// case 2:
|
||||
// CHECK: [[CASE2]]
|
||||
|
||||
// arr[:] += arr_reduction[:];
|
||||
// CHECK: [[END:%.+]] = getelementptr i32, i32* [[LB1_0]], i64 [[ARR_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq i32* [[LB1_0]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi i32*
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: [[ADD:%.+]] = mul nsw i32 555, %
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
// CHECK: [[DONE:%.+]] = icmp eq i32* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// arrs[:] = var.operator &(arrs_reduction[:]);
|
||||
// CHECK: [[END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[LHS_BEGIN]], i64 40
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[LHS_BEGIN]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi [[S_FLOAT_TY]]*
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: call void @_Z3redR6BaseS1RKS_(%
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// break;
|
||||
// CHECK: br label %[[RED_DONE]]
|
||||
// CHECK: [[RED_DONE]]
|
||||
|
||||
// Check destruction of private copy.
|
||||
// CHECK: [[BEGIN:%.+]] = getelementptr inbounds [10 x [4 x [[S_FLOAT_TY]]]], [10 x [4 x [[S_FLOAT_TY]]]]* [[ARRS_PRIV]], i32 0, i32 0, i32 0
|
||||
// CHECK: [[END:%.+]] = getelementptr inbounds [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[BEGIN]], i64 40
|
||||
// CHECK: br
|
||||
// CHECK: phi [[S_FLOAT_TY]]*
|
||||
// CHECK: call void @_ZN1SIfED1Ev([[S_FLOAT_TY]]* %
|
||||
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[BEGIN]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
// CHECK: call void @llvm.stackrestore(i8*
|
||||
// CHECK: call void @__kmpc_barrier(
|
||||
|
||||
// CHECK: ret void
|
||||
|
||||
// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
|
||||
// *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
|
||||
// ...
|
||||
// *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
|
||||
// *(Type<n>-1*)rhs[<n>-1]);
|
||||
// }
|
||||
// CHECK: define internal void [[REDUCTION_FUNC]](i8*, i8*)
|
||||
// arr_rhs = (int*)rhs[0];
|
||||
// CHECK: [[ARR_RHS_REF:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[RED_LIST_RHS:%.+]], i64 0, i64 0
|
||||
// CHECK: [[ARR_RHS_VOID:%.+]] = load i8*, i8** [[ARR_RHS_REF]],
|
||||
// CHECK: [[ARR_RHS:%.+]] = bitcast i8* [[ARR_RHS_VOID]] to i32*
|
||||
// arr_lhs = (int*)lhs[0];
|
||||
// CHECK: [[ARR_LHS_REF:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[RED_LIST_LHS:%.+]], i64 0, i64 0
|
||||
// CHECK: [[ARR_LHS_VOID:%.+]] = load i8*, i8** [[ARR_LHS_REF]],
|
||||
// CHECK: [[ARR_LHS:%.+]] = bitcast i8* [[ARR_LHS_VOID]] to i32*
|
||||
|
||||
// arr_size = (size_t)lhs[1];
|
||||
// CHECK: [[ARR_SIZE_REF:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[RED_LIST_LHS]], i64 0, i64 1
|
||||
// CHECK: [[ARR_SIZE_VOID:%.+]] = load i8*, i8** [[ARR_SIZE_REF]],
|
||||
// CHECK: [[ARR_SIZE:%.+]] = ptrtoint i8* [[ARR_SIZE_VOID]] to i64
|
||||
|
||||
// arrs_rhs = (S<float>*)rhs[2];
|
||||
// CHECK: [[ARRS_RHS_REF:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[RED_LIST_RHS]], i64 0, i64 2
|
||||
// CHECK: [[ARRS_RHS_VOID:%.+]] = load i8*, i8** [[ARRS_RHS_REF]],
|
||||
// CHECK: [[ARRS_RHS:%.+]] = bitcast i8* [[ARRS_RHS_VOID]] to [[S_FLOAT_TY]]*
|
||||
// arrs_lhs = (S<float>*)lhs[2];
|
||||
// CHECK: [[ARRS_LHS_REF:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[RED_LIST_LHS]], i64 0, i64 2
|
||||
// CHECK: [[ARRS_LHS_VOID:%.+]] = load i8*, i8** [[ARRS_LHS_REF]],
|
||||
// CHECK: [[ARRS_LHS:%.+]] = bitcast i8* [[ARRS_LHS_VOID]] to [[S_FLOAT_TY]]*
|
||||
|
||||
// arr_lhs[:] += arr_rhs[:];
|
||||
// CHECK: [[END:%.+]] = getelementptr i32, i32* [[ARR_LHS]], i64 [[ARR_SIZE]]
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq i32* [[ARR_LHS]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi i32*
|
||||
// CHECK: [[ADD:%.+]] = mul nsw i32 555, %
|
||||
// CHECK: store i32 [[ADD]], i32* %
|
||||
// CHECK: [[DONE:%.+]] = icmp eq i32* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// arrs_lhs = arrs_lhs.operator &(arrs_rhs);
|
||||
// CHECK: [[END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[ARRS_LB:%.+]], i64 40
|
||||
// CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[ARRS_LB]], [[END]]
|
||||
// CHECK: br i1 [[ISEMPTY]],
|
||||
// CHECK: phi [[S_FLOAT_TY]]*
|
||||
// CHECK: call void @_Z3redR6BaseS1RKS_(%
|
||||
// CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]
|
||||
// CHECK: br i1 [[DONE]],
|
||||
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void [[MAIN_MICROTASK3]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[S_FLOAT_TY]]*** dereferenceable(8) %{{.+}})
|
||||
|
||||
// CHECK: [[VAR2_ORIG_ADDR:%.+]] = alloca [[S_FLOAT_TY]]***,
|
||||
|
||||
// Reduction list for runtime.
|
||||
// CHECK: [[RED_LIST:%.+]] = alloca [2 x i8*],
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
// CHECK: [[VAR2_ORIG:%.+]] = load [[S_FLOAT_TY]]***, [[S_FLOAT_TY]]**** [[VAR2_ORIG_ADDR]],
|
||||
|
||||
// CHECK: load [[S_FLOAT_TY]]**, [[S_FLOAT_TY]]*** [[VAR2_ORIG]],
|
||||
// CHECK: getelementptr inbounds [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** %{{.+}}, i64 0
|
||||
// CHECK: load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** %
|
||||
// CHECK: [[LOW:%.+]] = getelementptr inbounds [[S_FLOAT_TY]], [[S_FLOAT_TY]]* %{{.+}}, i64 1
|
||||
// CHECK: load [[S_FLOAT_TY]]**, [[S_FLOAT_TY]]*** [[VAR2_ORIG]],
|
||||
// CHECK: getelementptr inbounds [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** %{{.+}}, i64 4
|
||||
// CHECK: load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** %
|
||||
// CHECK: getelementptr inbounds [[S_FLOAT_TY]], [[S_FLOAT_TY]]* %{{.+}}, i64 6
|
||||
// CHECK: [[LD:%.+]] = load [[S_FLOAT_TY]]**, [[S_FLOAT_TY]]*** [[VAR2_ORIG]],
|
||||
// CHECK: [[ORIG_START:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[LD]],
|
||||
// CHECK: [[LAST:%.+]] = ptrtoint [[S_FLOAT_TY]]* %{{.+}} to i64
|
||||
// CHECK: [[FIRST:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64
|
||||
// CHECK: [[BYTE_DIF:%.+]] = sub i64 [[LAST]], [[FIRST]]
|
||||
// CHECK: [[DIF:%.+]] = sdiv exact i64 [[BYTE_DIF]], ptrtoint ([[S_FLOAT_TY]]* getelementptr ([[S_FLOAT_TY]], [[S_FLOAT_TY]]* null, i32 1) to i64)
|
||||
// CHECK: [[SIZE:%.+]] = add nuw i64 [[DIF]], 1
|
||||
// CHECK: call i8* @llvm.stacksave()
|
||||
// CHECK: [[VAR2_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]],
|
||||
// CHECK: [[START:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[ORIG_START]] to i64
|
||||
// CHECK: [[LOW_BOUND:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64
|
||||
// CHECK: [[OFFSET_BYTES:%.+]] = sub i64 [[START]], [[LOW_BOUND]]
|
||||
// CHECK: [[OFFSET:%.+]] = sdiv exact i64 [[OFFSET_BYTES]], ptrtoint ([[S_FLOAT_TY]]* getelementptr ([[S_FLOAT_TY]], [[S_FLOAT_TY]]* null, i32 1) to i64)
|
||||
// CHECK: [[PSEUDO_VAR2_PRIV:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[VAR2_PRIV]], i64 [[OFFSET]]
|
||||
// CHECK: store [[S_FLOAT_TY]]** [[REF:.+]], [[S_FLOAT_TY]]*** %
|
||||
// CHECK: store [[S_FLOAT_TY]]* [[PSEUDO_VAR2_PRIV]], [[S_FLOAT_TY]]** [[REF]]
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void [[MAIN_MICROTASK4]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x [[S_FLOAT_TY]]]* dereferenceable(24) %{{.+}})
|
||||
|
||||
// CHECK: [[VVAR2_ORIG_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
|
||||
|
||||
// Reduction list for runtime.
|
||||
// CHECK: [[RED_LIST:%.+]] = alloca [2 x i8*],
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
// CHECK: [[VVAR2_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VVAR2_ORIG_ADDR]],
|
||||
|
||||
// CHECK: [[LOW:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]], i64 0, i64 0
|
||||
// CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]], i64 0, i64 4
|
||||
// CHECK: [[ORIG_START:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]] to [[S_FLOAT_TY]]*
|
||||
// CHECK: [[LAST:%.+]] = ptrtoint [[S_FLOAT_TY]]* %{{.+}} to i64
|
||||
// CHECK: [[FIRST:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64
|
||||
// CHECK: [[BYTE_DIF:%.+]] = sub i64 [[LAST]], [[FIRST]]
|
||||
// CHECK: [[DIF:%.+]] = sdiv exact i64 [[BYTE_DIF]], ptrtoint ([[S_FLOAT_TY]]* getelementptr ([[S_FLOAT_TY]], [[S_FLOAT_TY]]* null, i32 1) to i64)
|
||||
// CHECK: [[SIZE:%.+]] = add nuw i64 [[DIF]], 1
|
||||
// CHECK: call i8* @llvm.stacksave()
|
||||
// CHECK: [[VVAR2_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]],
|
||||
// CHECK: [[START:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[ORIG_START]] to i64
|
||||
// CHECK: [[LOW_BOUND:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64
|
||||
// CHECK: [[OFFSET_BYTES:%.+]] = sub i64 [[START]], [[LOW_BOUND]]
|
||||
// CHECK: [[OFFSET:%.+]] = sdiv exact i64 [[OFFSET_BYTES]], ptrtoint ([[S_FLOAT_TY]]* getelementptr ([[S_FLOAT_TY]], [[S_FLOAT_TY]]* null, i32 1) to i64)
|
||||
// CHECK: [[PSEUDO_VVAR2_PRIV:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[VVAR2_PRIV]], i64 [[OFFSET]]
|
||||
// CHECK: [[VVAR2_PRIV:%.+]] = bitcast [[S_FLOAT_TY]]* [[PSEUDO_VVAR2_PRIV]] to [2 x [[S_FLOAT_TY]]]*
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void [[MAIN_MICROTASK5]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x [[S_FLOAT_TY]]]* dereferenceable(24) %{{.+}})
|
||||
|
||||
// CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
|
||||
|
||||
// Reduction list for runtime.
|
||||
// CHECK: [[RED_LIST:%.+]] = alloca [2 x i8*],
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: [[LOW:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], i64 0, i64 1
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], i64 0, i64 2
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: [[ORIG_START:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*
|
||||
// CHECK: [[LAST:%.+]] = ptrtoint [[S_FLOAT_TY]]* %{{.+}} to i64
|
||||
// CHECK: [[FIRST:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64
|
||||
// CHECK: [[BYTE_DIF:%.+]] = sub i64 [[LAST]], [[FIRST]]
|
||||
// CHECK: [[DIF:%.+]] = sdiv exact i64 [[BYTE_DIF]], ptrtoint ([[S_FLOAT_TY]]* getelementptr ([[S_FLOAT_TY]], [[S_FLOAT_TY]]* null, i32 1) to i64)
|
||||
// CHECK: [[SIZE:%.+]] = add nuw i64 [[DIF]], 1
|
||||
// CHECK: call i8* @llvm.stacksave()
|
||||
// CHECK: [[VAR3_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]],
|
||||
// CHECK: [[START:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[ORIG_START]] to i64
|
||||
// CHECK: [[LOW_BOUND:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64
|
||||
// CHECK: [[OFFSET_BYTES:%.+]] = sub i64 [[START]], [[LOW_BOUND]]
|
||||
// CHECK: [[OFFSET:%.+]] = sdiv exact i64 [[OFFSET_BYTES]], ptrtoint ([[S_FLOAT_TY]]* getelementptr ([[S_FLOAT_TY]], [[S_FLOAT_TY]]* null, i32 1) to i64)
|
||||
// CHECK: [[PSEUDO_VAR3_PRIV:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[VAR3_PRIV]], i64 [[OFFSET]]
|
||||
// CHECK: [[VAR3_PRIV:%.+]] = bitcast [[S_FLOAT_TY]]* [[PSEUDO_VAR3_PRIV]] to [2 x [[S_FLOAT_TY]]]*
|
||||
|
||||
// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], [2 x [[S_FLOAT_TY]]]** %
|
||||
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void [[MAIN_MICROTASK6]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x [[S_FLOAT_TY]]]* dereferenceable(24) %{{.+}})
|
||||
|
||||
// CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
|
||||
// CHECK: [[VAR3_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
|
||||
|
||||
// Reduction list for runtime.
|
||||
// CHECK: [[RED_LIST:%.+]] = alloca [1 x i8*],
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*
|
||||
// CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], i32 0, i32 0
|
||||
// CHECK: getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* %{{.+}}, i64 2
|
||||
|
||||
// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], [2 x [[S_FLOAT_TY]]]** %
|
||||
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]()
|
||||
// CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]],
|
||||
// CHECK: call {{.*}} [[S_INT_TY_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]])
|
||||
// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 6, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, i32*, [[S_INT_TY]]*, [[S_INT_TY]]*, i32*, [2 x i32]*, [2 x [[S_INT_TY]]]*)* [[TMAIN_MICROTASK:@.+]] to void
|
||||
// CHECK: call {{.*}} [[S_INT_TY_DESTR:@.+]]([[S_INT_TY]]*
|
||||
// CHECK: ret
|
||||
//
|
||||
// CHECK: define internal void [[TMAIN_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, i32* dereferenceable(4) %{{.+}}, [[S_INT_TY]]* dereferenceable(12) %{{.+}}, [[S_INT_TY]]* dereferenceable(12) %{{.+}}, i32* dereferenceable(4) %{{.+}}, [2 x i32]* dereferenceable(8) %{{.+}}, [2 x [[S_INT_TY]]]* dereferenceable(24) %{{.+}})
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]],
|
||||
// CHECK: [[VAR1_PRIV:%.+]] = alloca [[S_INT_TY]],
|
||||
// CHECK: [[T_VAR1_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
|
||||
// Reduction list for runtime.
|
||||
// CHECK: [[RED_LIST:%.+]] = alloca [4 x i8*],
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// CHECK: [[T_VAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %
|
||||
// CHECK: [[VAR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** %
|
||||
// CHECK: [[T_VAR1_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %
|
||||
|
||||
// For + reduction operation initial value of private variable is 0.
|
||||
// CHECK: store i32 321, i32* %
|
||||
|
||||
// For & reduction operation initial value of private variable is ones in all bits.
|
||||
// CHECK: call void @_Z4initR6BaseS1RKS_(
|
||||
|
||||
// For && reduction operation initial value of private variable is 1.0.
|
||||
// CHECK: call void @_Z5init2R6BaseS1RKS_(
|
||||
|
||||
// For min reduction operation initial value of private variable is largest repesentable value.
|
||||
// CHECK: sdiv i32 432, %
|
||||
|
||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// Skip checks for internal operations.
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
||||
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
|
||||
|
||||
// CHECK: [[T_VAR_PRIV_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 0
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast i{{[0-9]+}}* [[T_VAR_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[T_VAR_PRIV_REF]],
|
||||
// CHECK: [[VAR_PRIV_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 1
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[VAR_PRIV_REF]],
|
||||
// CHECK: [[VAR1_PRIV_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 2
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR1_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[VAR1_PRIV_REF]],
|
||||
// CHECK: [[T_VAR1_PRIV_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST]], i64 0, i64 3
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast i{{[0-9]+}}* [[T_VAR1_PRIV]] to i8*
|
||||
// CHECK: store i8* [[BITCAST]], i8** [[T_VAR1_PRIV_REF]],
|
||||
|
||||
// res = __kmpc_reduce_nowait(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>);
|
||||
|
||||
// CHECK: [[BITCAST:%.+]] = bitcast [4 x i8*]* [[RED_LIST]] to i8*
|
||||
// CHECK: [[RES:%.+]] = call i32 @__kmpc_reduce_nowait(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], i32 4, i64 32, i8* [[BITCAST]], void (i8*, i8*)* [[REDUCTION_FUNC:@.+]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||
|
||||
// switch(res)
|
||||
// CHECK: switch i32 [[RES]], label %[[RED_DONE:.+]] [
|
||||
// CHECK: i32 1, label %[[CASE1:.+]]
|
||||
// CHECK: i32 2, label %[[CASE2:.+]]
|
||||
// CHECK: ]
|
||||
|
||||
// case 1:
|
||||
// t_var += t_var_reduction;
|
||||
// CHECK: add nsw i32 1513, %
|
||||
|
||||
// var = var.operator &(var_reduction);
|
||||
// CHECK: call void @_Z3redR6BaseS1RKS_(%
|
||||
|
||||
// var1 = var1.operator &&(var1_reduction);
|
||||
// CHECK: mul nsw i32 17, %
|
||||
|
||||
// t_var1 = min(t_var1, t_var1_reduction);
|
||||
// CHECK: sub nsw i32 47, %
|
||||
|
||||
// __kmpc_end_reduce_nowait(<loc>, <gtid>, &<lock>);
|
||||
// CHECK: call void @__kmpc_end_reduce_nowait(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||
|
||||
// break;
|
||||
// CHECK: br label %[[RED_DONE]]
|
||||
|
||||
// case 2:
|
||||
// t_var += t_var_reduction;
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: add nsw i32 1513, %
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
|
||||
// var = var.operator &(var_reduction);
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: call void @_Z3redR6BaseS1RKS_(%
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
|
||||
// var1 = var1.operator &&(var1_reduction);
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: mul nsw i32 17, %
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
|
||||
// t_var1 = min(t_var1, t_var1_reduction);
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
// CHECK: sub nsw i32 47, %
|
||||
// CHECK: call void @__kmpc_end_critical(
|
||||
|
||||
// break;
|
||||
// CHECK: br label %[[RED_DONE]]
|
||||
// CHECK: [[RED_DONE]]
|
||||
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]])
|
||||
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]*
|
||||
// CHECK: ret void
|
||||
|
||||
// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
|
||||
// *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
|
||||
// ...
|
||||
// *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
|
||||
// *(Type<n>-1*)rhs[<n>-1]);
|
||||
// }
|
||||
// CHECK: define internal void [[REDUCTION_FUNC]](i8*, i8*)
|
||||
// t_var_lhs = (i{{[0-9]+}}*)lhs[0];
|
||||
// CHECK: [[T_VAR_RHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_RHS:%.+]], i64 0, i64 0
|
||||
// CHECK: [[T_VAR_RHS_VOID:%.+]] = load i8*, i8** [[T_VAR_RHS_REF]],
|
||||
// CHECK: [[T_VAR_RHS:%.+]] = bitcast i8* [[T_VAR_RHS_VOID]] to i{{[0-9]+}}*
|
||||
// t_var_rhs = (i{{[0-9]+}}*)rhs[0];
|
||||
// CHECK: [[T_VAR_LHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS:%.+]], i64 0, i64 0
|
||||
// CHECK: [[T_VAR_LHS_VOID:%.+]] = load i8*, i8** [[T_VAR_LHS_REF]],
|
||||
// CHECK: [[T_VAR_LHS:%.+]] = bitcast i8* [[T_VAR_LHS_VOID]] to i{{[0-9]+}}*
|
||||
|
||||
// var_lhs = (S<i{{[0-9]+}}>*)lhs[1];
|
||||
// CHECK: [[VAR_RHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_RHS]], i64 0, i64 1
|
||||
// CHECK: [[VAR_RHS_VOID:%.+]] = load i8*, i8** [[VAR_RHS_REF]],
|
||||
// CHECK: [[VAR_RHS:%.+]] = bitcast i8* [[VAR_RHS_VOID]] to [[S_INT_TY]]*
|
||||
// var_rhs = (S<i{{[0-9]+}}>*)rhs[1];
|
||||
// CHECK: [[VAR_LHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS]], i64 0, i64 1
|
||||
// CHECK: [[VAR_LHS_VOID:%.+]] = load i8*, i8** [[VAR_LHS_REF]],
|
||||
// CHECK: [[VAR_LHS:%.+]] = bitcast i8* [[VAR_LHS_VOID]] to [[S_INT_TY]]*
|
||||
|
||||
// var1_lhs = (S<i{{[0-9]+}}>*)lhs[2];
|
||||
// CHECK: [[VAR1_RHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_RHS]], i64 0, i64 2
|
||||
// CHECK: [[VAR1_RHS_VOID:%.+]] = load i8*, i8** [[VAR1_RHS_REF]],
|
||||
// CHECK: [[VAR1_RHS:%.+]] = bitcast i8* [[VAR1_RHS_VOID]] to [[S_INT_TY]]*
|
||||
// var1_rhs = (S<i{{[0-9]+}}>*)rhs[2];
|
||||
// CHECK: [[VAR1_LHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS]], i64 0, i64 2
|
||||
// CHECK: [[VAR1_LHS_VOID:%.+]] = load i8*, i8** [[VAR1_LHS_REF]],
|
||||
// CHECK: [[VAR1_LHS:%.+]] = bitcast i8* [[VAR1_LHS_VOID]] to [[S_INT_TY]]*
|
||||
|
||||
// t_var1_lhs = (i{{[0-9]+}}*)lhs[3];
|
||||
// CHECK: [[T_VAR1_RHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_RHS]], i64 0, i64 3
|
||||
// CHECK: [[T_VAR1_RHS_VOID:%.+]] = load i8*, i8** [[T_VAR1_RHS_REF]],
|
||||
// CHECK: [[T_VAR1_RHS:%.+]] = bitcast i8* [[T_VAR1_RHS_VOID]] to i{{[0-9]+}}*
|
||||
// t_var1_rhs = (i{{[0-9]+}}*)rhs[3];
|
||||
// CHECK: [[T_VAR1_LHS_REF:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[RED_LIST_LHS]], i64 0, i64 3
|
||||
// CHECK: [[T_VAR1_LHS_VOID:%.+]] = load i8*, i8** [[T_VAR1_LHS_REF]],
|
||||
// CHECK: [[T_VAR1_LHS:%.+]] = bitcast i8* [[T_VAR1_LHS_VOID]] to i{{[0-9]+}}*
|
||||
|
||||
// t_var_lhs += t_var_rhs;
|
||||
// CHECK: add nsw i32 1513, %
|
||||
|
||||
// var_lhs = var_lhs.operator &(var_rhs);
|
||||
// CHECK: call void @_Z3redR6BaseS1RKS_(%
|
||||
|
||||
// var1_lhs = var1_lhs.operator &&(var1_rhs);
|
||||
// CHECK: mul nsw i32 17, %
|
||||
|
||||
// t_var1_lhs = min(t_var1_lhs, t_var1_rhs);
|
||||
// CHECK: sub nsw i32 47, %
|
||||
// CHECK: ret void
|
||||
|
||||
#endif
|
||||
|
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -33,7 +33,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -55,9 +55,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable: no known conversion from 'int' to 'S6' for 1st argument}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable: no known conversion from 'int' to 'S6' for 1st argument}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -123,7 +123,7 @@ T tmain(T argc) {
|
|||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp for reduction(foo : argc) // expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
|
@ -135,11 +135,11 @@ T tmain(T argc) {
|
|||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
|
@ -175,7 +175,7 @@ T tmain(T argc) {
|
|||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp for reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
|
@ -187,7 +187,7 @@ T tmain(T argc) {
|
|||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp for reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
|
|
|
@ -147,7 +147,7 @@ int foomain(int argc, char **argv) {
|
|||
foo();
|
||||
#pragma omp parallel reduction(+ : i) // expected-note {{defined as reduction}}
|
||||
#pragma omp for simd firstprivate(i) // expected-error {{firstprivate variable must be shared}}
|
||||
for (i = 0; i < argc; ++i)
|
||||
for (int k = 0; k < argc; ++k)
|
||||
foo();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -56,9 +56,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -122,7 +122,7 @@ T tmain(T argc) {
|
|||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for simd reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp for simd reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
|
@ -134,11 +134,11 @@ T tmain(T argc) {
|
|||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
|
@ -174,7 +174,7 @@ T tmain(T argc) {
|
|||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for simd reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp for simd reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
|
@ -186,7 +186,7 @@ T tmain(T argc) {
|
|||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for simd reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp for simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -56,9 +56,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -111,7 +111,7 @@ T tmain(T argc) {
|
|||
#pragma omp parallel for reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp parallel for reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for reduction(&& : argc)
|
||||
|
@ -120,10 +120,10 @@ T tmain(T argc) {
|
|||
#pragma omp parallel for reduction(^ : T) // expected-error {{'T' does not refer to a value}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
|
@ -150,7 +150,7 @@ T tmain(T argc) {
|
|||
#pragma omp parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp parallel for reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
|
@ -160,7 +160,7 @@ T tmain(T argc) {
|
|||
#pragma omp parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
|
|
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -56,9 +56,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -111,7 +111,7 @@ T tmain(T argc) {
|
|||
#pragma omp parallel for simd reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for simd reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp parallel for simd reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for simd reduction(&& : argc)
|
||||
|
@ -120,10 +120,10 @@ T tmain(T argc) {
|
|||
#pragma omp parallel for simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
|
@ -150,7 +150,7 @@ T tmain(T argc) {
|
|||
#pragma omp parallel for simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for simd reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp parallel for simd reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
|
@ -160,7 +160,7 @@ T tmain(T argc) {
|
|||
#pragma omp parallel for simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for simd reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp parallel for simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -56,9 +56,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -101,15 +101,15 @@ T tmain(T argc) {
|
|||
foo();
|
||||
#pragma omp parallel reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
|
||||
foo();
|
||||
#pragma omp parallel reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp parallel reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
foo();
|
||||
#pragma omp parallel reduction(&& : argc)
|
||||
foo();
|
||||
#pragma omp parallel reduction(^ : T) // expected-error {{'T' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
foo();
|
||||
#pragma omp parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp parallel reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
foo();
|
||||
|
@ -127,14 +127,14 @@ T tmain(T argc) {
|
|||
foo();
|
||||
#pragma omp parallel reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp parallel reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp parallel reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
foo();
|
||||
#pragma omp parallel private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
foo();
|
||||
#pragma omp parallel private(k)
|
||||
#pragma omp parallel reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
foo();
|
||||
#pragma omp parallel reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp parallel reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
foo();
|
||||
#pragma omp parallel reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -56,9 +56,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -121,7 +121,7 @@ T tmain(T argc) {
|
|||
{
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel sections reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp parallel sections reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
{
|
||||
foo();
|
||||
}
|
||||
|
@ -133,11 +133,11 @@ T tmain(T argc) {
|
|||
{
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp parallel sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
{
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp parallel sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
{
|
||||
foo();
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ T tmain(T argc) {
|
|||
{
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel sections reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp parallel sections reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
{
|
||||
foo();
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ T tmain(T argc) {
|
|||
{
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel sections reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp parallel sections reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
{
|
||||
foo();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -56,9 +56,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -132,7 +132,7 @@ T tmain(T argc) {
|
|||
foo();
|
||||
}
|
||||
#pragma omp parallel
|
||||
#pragma omp sections reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp sections reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
{
|
||||
foo();
|
||||
}
|
||||
|
@ -147,12 +147,12 @@ T tmain(T argc) {
|
|||
foo();
|
||||
}
|
||||
#pragma omp parallel
|
||||
#pragma omp sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
{
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel
|
||||
#pragma omp sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
{
|
||||
foo();
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ T tmain(T argc) {
|
|||
foo();
|
||||
}
|
||||
#pragma omp parallel
|
||||
#pragma omp sections reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp sections reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
{
|
||||
foo();
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ T tmain(T argc) {
|
|||
foo();
|
||||
}
|
||||
#pragma omp parallel
|
||||
#pragma omp sections reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp sections reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
{
|
||||
foo();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -56,9 +56,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -111,7 +111,7 @@ T tmain(T argc) {
|
|||
#pragma omp simd reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp simd reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp simd reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp simd reduction(&& : argc)
|
||||
|
@ -120,10 +120,10 @@ T tmain(T argc) {
|
|||
#pragma omp simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
|
@ -150,7 +150,7 @@ T tmain(T argc) {
|
|||
#pragma omp simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp simd reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp simd reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
|
@ -163,7 +163,7 @@ T tmain(T argc) {
|
|||
#pragma omp simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp simd reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -56,9 +56,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -111,7 +111,7 @@ T tmain(T argc) {
|
|||
#pragma omp target parallel for reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp target parallel for reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp target parallel for reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp target parallel for reduction(&& : argc)
|
||||
|
@ -120,10 +120,10 @@ T tmain(T argc) {
|
|||
#pragma omp target parallel for reduction(^ : T) // expected-error {{'T' does not refer to a value}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp target parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp target parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp target parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp target parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp target parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
|
@ -150,7 +150,7 @@ T tmain(T argc) {
|
|||
#pragma omp target parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp target parallel for reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp target parallel for reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp target parallel for private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
|
@ -160,7 +160,7 @@ T tmain(T argc) {
|
|||
#pragma omp target parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp target parallel for reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp target parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp target parallel for reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -56,9 +56,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -101,15 +101,15 @@ T tmain(T argc) {
|
|||
foo();
|
||||
#pragma omp target parallel reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
|
||||
foo();
|
||||
#pragma omp target parallel reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp target parallel reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
foo();
|
||||
#pragma omp target parallel reduction(&& : argc)
|
||||
foo();
|
||||
#pragma omp target parallel reduction(^ : T) // expected-error {{'T' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp target parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp target parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
foo();
|
||||
#pragma omp target parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp target parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp target parallel reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
foo();
|
||||
|
@ -127,14 +127,14 @@ T tmain(T argc) {
|
|||
foo();
|
||||
#pragma omp target parallel reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp target parallel reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp target parallel reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
foo();
|
||||
#pragma omp target parallel private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
foo();
|
||||
#pragma omp parallel private(k)
|
||||
#pragma omp target parallel reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
foo();
|
||||
#pragma omp target parallel reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp target parallel reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
foo();
|
||||
#pragma omp target parallel reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
|
|
|
@ -60,11 +60,10 @@ int foo() {
|
|||
// expected-error@+1 2 {{calling a private constructor of class 'S'}}
|
||||
#pragma omp parallel shared(a, b)
|
||||
++a, ++b;
|
||||
// expected-note@+1 3 {{defined as reduction}}
|
||||
// expected-note@+1 2 {{defined as reduction}}
|
||||
#pragma omp parallel reduction(+ : r)
|
||||
// expected-error@+1 {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}}
|
||||
// expected-error@+1 2 {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}}
|
||||
#pragma omp task firstprivate(r)
|
||||
// expected-error@+1 2 {{reduction variables may not be accessed in an explicit task}}
|
||||
++r;
|
||||
// expected-note@+1 2 {{defined as reduction}}
|
||||
#pragma omp parallel reduction(+ : r)
|
||||
|
@ -77,12 +76,11 @@ int foo() {
|
|||
// expected-error@+1 2 {{reduction variables may not be accessed in an explicit task}}
|
||||
++r;
|
||||
#pragma omp parallel
|
||||
// expected-note@+1 3 {{defined as reduction}}
|
||||
// expected-note@+1 2 {{defined as reduction}}
|
||||
#pragma omp for reduction(+ : r)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
// expected-error@+1 {{argument of a reduction clause of a for construct must not appear in a firstprivate clause on a task construct}}
|
||||
// expected-error@+1 2 {{argument of a reduction clause of a for construct must not appear in a firstprivate clause on a task construct}}
|
||||
#pragma omp task firstprivate(r)
|
||||
// expected-error@+1 2 {{reduction variables may not be accessed in an explicit task}}
|
||||
++r;
|
||||
#pragma omp parallel
|
||||
// expected-note@+1 2 {{defined as reduction}}
|
||||
|
|
|
@ -13,7 +13,7 @@ struct S1; // expected-note {{declared here}} expected-note 4 {{forward declarat
|
|||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
static const float S2sc;
|
||||
};
|
||||
const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
|
||||
S2 b; // expected-note 2 {{'b' defined here}}
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 2 {{'c' defined here}}
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
|
@ -56,9 +56,9 @@ class S5 {
|
|||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 2 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
|
@ -112,7 +112,7 @@ T tmain(T argc) {
|
|||
#pragma omp teams reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
|
||||
foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
#pragma omp teams reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams reduction(&& : argc)
|
||||
|
@ -121,10 +121,10 @@ T tmain(T argc) {
|
|||
#pragma omp teams reduction(^ : T) // expected-error {{'T' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
|
||||
#pragma omp teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
|
||||
foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
#pragma omp teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
|
@ -151,7 +151,7 @@ T tmain(T argc) {
|
|||
#pragma omp teams reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
#pragma omp teams reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
|
@ -161,7 +161,7 @@ T tmain(T argc) {
|
|||
#pragma omp teams reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
|
||||
foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams reduction(+ : p), reduction(+ : p) // expected-error 3 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 3 {{previously referenced here}}
|
||||
#pragma omp teams reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
|
|
Loading…
Reference in New Issue