[OPENMP]Fix PR44133: Emit definitions of used constructors/functions.

Need to fully rebuild the initializer/combiner when instatiating the
declare reduction constrcut to properly emit used functions.
This commit is contained in:
Alexey Bataev 2019-12-02 13:04:30 -05:00
parent 9ec6d71211
commit 478541a6da
2 changed files with 47 additions and 80 deletions

View File

@ -3070,20 +3070,11 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
} else { } else {
SubstReductionType = D->getType(); SubstReductionType = D->getType();
} }
Expr *Combiner = D->getCombiner();
Expr *Init = D->getInitializer();
const bool CombinerRequiresInstantiation =
Combiner &&
(Combiner->isValueDependent() || Combiner->isInstantiationDependent() ||
Combiner->isTypeDependent() ||
Combiner->containsUnexpandedParameterPack());
const bool InitRequiresInstantiation =
Init &&
(Init->isValueDependent() || Init->isInstantiationDependent() ||
Init->isTypeDependent() || Init->containsUnexpandedParameterPack());
if (SubstReductionType.isNull()) if (SubstReductionType.isNull())
return nullptr; return nullptr;
bool IsCorrect = !SubstReductionType.isNull(); Expr *Combiner = D->getCombiner();
Expr *Init = D->getInitializer();
bool IsCorrect = true;
// Create instantiated copy. // Create instantiated copy.
std::pair<QualType, SourceLocation> ReductionTypes[] = { std::pair<QualType, SourceLocation> ReductionTypes[] = {
std::make_pair(SubstReductionType, D->getLocation())}; std::make_pair(SubstReductionType, D->getLocation())};
@ -3098,79 +3089,53 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
PrevDeclInScope); PrevDeclInScope);
auto *NewDRD = cast<OMPDeclareReductionDecl>(DRD.get().getSingleDecl()); auto *NewDRD = cast<OMPDeclareReductionDecl>(DRD.get().getSingleDecl());
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDRD); SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDRD);
if (!RequiresInstantiation && !CombinerRequiresInstantiation &&
!InitRequiresInstantiation) {
if (Combiner) {
NewDRD->setCombinerData(D->getCombinerIn(), D->getCombinerOut());
NewDRD->setCombiner(Combiner);
if (Init) {
NewDRD->setInitializerData(D->getInitOrig(), D->getInitPriv());
NewDRD->setInitializer(Init, D->getInitializerKind());
}
}
(void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd(
/*S=*/nullptr, DRD, IsCorrect && !D->isInvalidDecl());
return NewDRD;
}
Expr *SubstCombiner = nullptr; Expr *SubstCombiner = nullptr;
Expr *SubstInitializer = nullptr; Expr *SubstInitializer = nullptr;
// Combiners instantiation sequence. // Combiners instantiation sequence.
if (Combiner) { if (Combiner) {
if (!CombinerRequiresInstantiation) { SemaRef.ActOnOpenMPDeclareReductionCombinerStart(
NewDRD->setCombinerData(D->getCombinerIn(), D->getCombinerOut()); /*S=*/nullptr, NewDRD);
NewDRD->setCombiner(Combiner); SemaRef.CurrentInstantiationScope->InstantiatedLocal(
} else { cast<DeclRefExpr>(D->getCombinerIn())->getDecl(),
SemaRef.ActOnOpenMPDeclareReductionCombinerStart( cast<DeclRefExpr>(NewDRD->getCombinerIn())->getDecl());
/*S=*/nullptr, NewDRD); SemaRef.CurrentInstantiationScope->InstantiatedLocal(
SemaRef.CurrentInstantiationScope->InstantiatedLocal( cast<DeclRefExpr>(D->getCombinerOut())->getDecl(),
cast<DeclRefExpr>(D->getCombinerIn())->getDecl(), cast<DeclRefExpr>(NewDRD->getCombinerOut())->getDecl());
cast<DeclRefExpr>(NewDRD->getCombinerIn())->getDecl()); auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
SemaRef.CurrentInstantiationScope->InstantiatedLocal( Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(),
cast<DeclRefExpr>(D->getCombinerOut())->getDecl(), ThisContext);
cast<DeclRefExpr>(NewDRD->getCombinerOut())->getDecl()); SubstCombiner = SemaRef.SubstExpr(Combiner, TemplateArgs).get();
auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner); SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner);
Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(),
ThisContext);
SubstCombiner = SemaRef.SubstExpr(Combiner, TemplateArgs).get();
SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner);
}
} }
// Initializers instantiation sequence. // Initializers instantiation sequence.
if (Init) { if (Init) {
if (!InitRequiresInstantiation) { VarDecl *OmpPrivParm = SemaRef.ActOnOpenMPDeclareReductionInitializerStart(
NewDRD->setInitializerData(D->getInitOrig(), D->getInitPriv()); /*S=*/nullptr, NewDRD);
NewDRD->setInitializer(Init, D->getInitializerKind()); SemaRef.CurrentInstantiationScope->InstantiatedLocal(
cast<DeclRefExpr>(D->getInitOrig())->getDecl(),
cast<DeclRefExpr>(NewDRD->getInitOrig())->getDecl());
SemaRef.CurrentInstantiationScope->InstantiatedLocal(
cast<DeclRefExpr>(D->getInitPriv())->getDecl(),
cast<DeclRefExpr>(NewDRD->getInitPriv())->getDecl());
if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) {
SubstInitializer = SemaRef.SubstExpr(Init, TemplateArgs).get();
} else { } else {
VarDecl *OmpPrivParm = auto *OldPrivParm =
SemaRef.ActOnOpenMPDeclareReductionInitializerStart( cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl());
/*S=*/nullptr, NewDRD); IsCorrect = IsCorrect && OldPrivParm->hasInit();
SemaRef.CurrentInstantiationScope->InstantiatedLocal( if (IsCorrect)
cast<DeclRefExpr>(D->getInitOrig())->getDecl(), SemaRef.InstantiateVariableInitializer(OmpPrivParm, OldPrivParm,
cast<DeclRefExpr>(NewDRD->getInitOrig())->getDecl()); TemplateArgs);
SemaRef.CurrentInstantiationScope->InstantiatedLocal(
cast<DeclRefExpr>(D->getInitPriv())->getDecl(),
cast<DeclRefExpr>(NewDRD->getInitPriv())->getDecl());
if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) {
SubstInitializer = SemaRef.SubstExpr(Init, TemplateArgs).get();
} else {
auto *OldPrivParm =
cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl());
IsCorrect = IsCorrect && OldPrivParm->hasInit();
if (IsCorrect)
SemaRef.InstantiateVariableInitializer(OmpPrivParm, OldPrivParm,
TemplateArgs);
}
SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(
NewDRD, SubstInitializer, OmpPrivParm);
} }
SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(NewDRD, SubstInitializer,
OmpPrivParm);
} }
IsCorrect = IsCorrect && (!CombinerRequiresInstantiation || SubstCombiner) && IsCorrect = IsCorrect && SubstCombiner &&
(!InitRequiresInstantiation || (!Init ||
(!Init || (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit &&
(D->getInitializerKind() == OMPDeclareReductionDecl::CallInit && SubstInitializer) ||
SubstInitializer) || (D->getInitializerKind() != OMPDeclareReductionDecl::CallInit &&
(D->getInitializerKind() != OMPDeclareReductionDecl::CallInit && !SubstInitializer));
!SubstInitializer)));
(void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd( (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd(
/*S=*/nullptr, DRD, IsCorrect && !D->isInvalidDecl()); /*S=*/nullptr, DRD, IsCorrect && !D->isInvalidDecl());

View File

@ -85,9 +85,8 @@ SSS<int> d;
// CHECK-NEXT: ret void // CHECK-NEXT: ret void
// CHECK-NEXT: } // CHECK-NEXT: }
// CHECK: define {{.*}}void [[INIT:@[^(]+]]([[SSS_INT]]* template <typename T>
// CHECK-LOAD: define {{.*}}void [[INIT:@[^(]+]]([[SSS_INT]]* void init(T &lhs, T &rhs) {}
void init(SSS<int> &lhs, SSS<int> &rhs) {}
#pragma omp declare reduction(fun : SSS < int > : omp_out = omp_in) initializer(init(omp_priv, omp_orig)) #pragma omp declare reduction(fun : SSS < int > : omp_out = omp_in) initializer(init(omp_priv, omp_orig))
// CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias %0, [[SSS_INT]]* noalias %1) // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias %0, [[SSS_INT]]* noalias %1)
@ -95,7 +94,7 @@ void init(SSS<int> &lhs, SSS<int> &rhs) {}
// CHECK-NEXT: ret void // CHECK-NEXT: ret void
// CHECK-NEXT: } // CHECK-NEXT: }
// CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias %0, [[SSS_INT]]* noalias %1) // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias %0, [[SSS_INT]]* noalias %1)
// CHECK: call {{.*}}void [[INIT]]( // CHECK: call {{.*}}void @_Z4initI3SSSIiEEvRT_S3_(
// CHECK-NEXT: ret void // CHECK-NEXT: ret void
// CHECK-NEXT: } // CHECK-NEXT: }
@ -104,10 +103,13 @@ void init(SSS<int> &lhs, SSS<int> &rhs) {}
// CHECK-LOAD-NEXT: ret void // CHECK-LOAD-NEXT: ret void
// CHECK-LOAD-NEXT: } // CHECK-LOAD-NEXT: }
// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias %0, [[SSS_INT]]* noalias %1) // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias %0, [[SSS_INT]]* noalias %1)
// CHECK-LOAD: call {{.*}}void [[INIT]]( // CHECK-LOAD: call {{.*}}void @_Z4initI3SSSIiEEvRT_S3_(
// CHECK-LOAD-NEXT: ret void // CHECK-LOAD-NEXT: ret void
// CHECK-LOAD-NEXT: } // CHECK-LOAD-NEXT: }
// CHECK: define {{.*}}void @_Z4initI3SSSIiEEvRT_S3_(%struct.SSS* {{.+}}, %struct.SSS* {{.+}})
// CHECK-LOAD: define {{.*}}void @_Z4initI3SSSIiEEvRT_S3_(%struct.SSS* {{.+}}, %struct.SSS* {{.+}})
template <typename T> template <typename T>
T foo(T a) { T foo(T a) {
#pragma omp declare reduction(fun : T : omp_out += omp_in) initializer(omp_priv = 15 * omp_orig) #pragma omp declare reduction(fun : T : omp_out += omp_in) initializer(omp_priv = 15 * omp_orig)