@@ -7876,8 +7876,9 @@ class NoLoopStepChecker final : public ConstStmtVisitor<NoLoopStepChecker> {
7876
7876
// / red_var
7877
7877
class XteamRedExprChecker final : public ConstStmtVisitor<XteamRedExprChecker> {
7878
7878
public:
7879
- XteamRedExprChecker (const CodeGenModule::XteamRedVarMap &RVM)
7880
- : RedMap(RVM), IsSupported(true ) {}
7879
+ XteamRedExprChecker (CodeGenModule &CGM,
7880
+ const CodeGenModule::XteamRedVarMap &RVM)
7881
+ : CGM(CGM), RedMap(RVM), IsSupported(true ) {}
7881
7882
XteamRedExprChecker () = delete ;
7882
7883
7883
7884
bool isSupported () const { return IsSupported; }
@@ -7886,18 +7887,6 @@ class XteamRedExprChecker final : public ConstStmtVisitor<XteamRedExprChecker> {
7886
7887
if (!S)
7887
7888
return ;
7888
7889
7889
- auto isExprXteamRedVar = [this ](const Expr *E) {
7890
- if (!isa<DeclRefExpr>(E))
7891
- return false ;
7892
- auto *Decl = cast<DeclRefExpr>(E)->getDecl ();
7893
- if (!isa<VarDecl>(Decl))
7894
- return false ;
7895
- auto *VD = cast<VarDecl>(Decl);
7896
- if (RedMap.find (VD) != RedMap.end ())
7897
- return true ;
7898
- return false ;
7899
- };
7900
-
7901
7890
if (isa<BinaryOperator>(S)) {
7902
7891
const BinaryOperator *BinOpExpr = cast<BinaryOperator>(S);
7903
7892
// Even though we filtered out everything except the sum reduction
@@ -7908,51 +7897,77 @@ class XteamRedExprChecker final : public ConstStmtVisitor<XteamRedExprChecker> {
7908
7897
// We punt on anything more complex.
7909
7898
7910
7899
const Expr *LHS = BinOpExpr->getLHS ()->IgnoreImpCasts ();
7911
- if (isExprXteamRedVar (LHS)) {
7912
- auto BinOpExprOp = BinOpExpr->getOpcode ();
7913
- if (BinOpExprOp != BO_Assign && BinOpExprOp != BO_AddAssign &&
7914
- BinOpExprOp != BO_Add) {
7915
- IsSupported = false ;
7916
- return ;
7917
- }
7918
- // We only need to further examine the assignment case.
7919
- // If += or +, Codegen will extract the rhs.
7920
- if (BinOpExpr->getOpcode () == BO_Assign) {
7900
+ auto BinOpExprOp = BinOpExpr->getOpcode ();
7901
+ // Get the reduction variable, if any, from the LHS.
7902
+ const VarDecl *RedVarDecl = CGM.getXteamRedVarDecl (LHS, RedMap);
7903
+ if (RedVarDecl != nullptr ) {
7904
+ if (BinOpExprOp == BO_Assign || BinOpExprOp == BO_AddAssign) {
7921
7905
const Expr *RHS = BinOpExpr->getRHS ()->IgnoreImpCasts ();
7922
- if (!isa<BinaryOperator>(RHS)) {
7923
- IsSupported = false ;
7924
- return ;
7925
- }
7926
- const BinaryOperator *BinOpRHS = cast<BinaryOperator>(RHS);
7927
- if (BinOpRHS->getOpcode () != BO_Add) {
7928
- IsSupported = false ;
7929
- return ;
7930
- }
7931
- const Expr *LHSBinOpRHS = BinOpRHS->getLHS ()->IgnoreImpCasts ();
7932
- const Expr *RHSBinOpRHS = BinOpRHS->getRHS ()->IgnoreImpCasts ();
7933
- if (!isExprXteamRedVar (LHSBinOpRHS) &&
7934
- !isExprXteamRedVar (RHSBinOpRHS)) {
7935
- IsSupported = false ;
7936
- return ;
7906
+ // If operator +=, reject if RHS accesses any reduction variable.
7907
+ if (BinOpExprOp == BO_AddAssign) {
7908
+ ValidateChildren (RHS);
7909
+ if (!IsSupported)
7910
+ return ;
7911
+ } else { // BinOpExprOp == BO_Assign
7912
+ if (isa<BinaryOperator>(RHS)) {
7913
+ const BinaryOperator *BinOpRHS = cast<BinaryOperator>(RHS);
7914
+ if (BinOpRHS->getOpcode () == BO_Add) {
7915
+ const Expr *LHSBinOpRHS = BinOpRHS->getLHS ()->IgnoreImpCasts ();
7916
+ const Expr *RHSBinOpRHS = BinOpRHS->getRHS ()->IgnoreImpCasts ();
7917
+ // If LHS is the reduction variable, the RHS must not access any
7918
+ // reduction variable. Similarly, vice-versa for RHS.
7919
+ if (CGM.isXteamRedVarExpr (LHSBinOpRHS, RedVarDecl))
7920
+ ValidateChildren (RHSBinOpRHS);
7921
+ else if (CGM.isXteamRedVarExpr (RHSBinOpRHS, RedVarDecl))
7922
+ ValidateChildren (LHSBinOpRHS);
7923
+ else // Neither LHS nor RHS is the reduction variable.
7924
+ IsSupported = false ;
7925
+ if (!IsSupported)
7926
+ return ;
7927
+ } else { // Not an add binary operator.
7928
+ IsSupported = false ;
7929
+ return ;
7930
+ }
7931
+ } else { // RHS is not a binary operator for assignment.
7932
+ IsSupported = false ;
7933
+ return ;
7934
+ }
7937
7935
}
7936
+ } else { // Binary operator is neither +=, nor =.
7937
+ IsSupported = false ;
7938
+ return ;
7938
7939
}
7940
+ } else { // LHS of binary operator does not access any reduction variable.
7941
+ // Ensure that RHS does not access any reduction variable either.
7942
+ ValidateChildren (S);
7943
+ if (!IsSupported)
7944
+ return ;
7939
7945
}
7940
- } else if (isa<UnaryOperator>(S)) {
7941
- const Expr *UnaryOpExpr =
7942
- cast<UnaryOperator>(S)->getSubExpr ()->IgnoreImpCasts ();
7943
- // Xteam reduction does not handle unary operators currently.
7944
- if (isExprXteamRedVar (UnaryOpExpr)) {
7946
+ } else if (isa<DeclRefExpr>(S)) {
7947
+ // Not a binary operator, so not supported at this point. So ensure no
7948
+ // reduction variable is accessed.
7949
+ if (CGM.hasXteamRedVar (cast<DeclRefExpr>(S), RedMap)) {
7945
7950
IsSupported = false ;
7946
7951
return ;
7947
7952
}
7953
+ } else {
7954
+ // Recursively check the children.
7955
+ ValidateChildren (S);
7956
+ if (!IsSupported)
7957
+ return ;
7948
7958
}
7949
-
7950
- for (const Stmt *Child : S->children ())
7951
- if (Child)
7959
+ }
7960
+ void ValidateChildren (const Stmt *S) {
7961
+ for (auto Child : S->children ())
7962
+ if (Child) {
7952
7963
Visit (Child);
7964
+ if (!IsSupported)
7965
+ return ;
7966
+ }
7953
7967
}
7954
7968
7955
7969
private:
7970
+ CodeGenModule &CGM;
7956
7971
// / Map of reduction variables for this directive.
7957
7972
const CodeGenModule::XteamRedVarMap &RedMap;
7958
7973
// / Set to false if codegen does not support the reduction expression.
@@ -8438,7 +8453,7 @@ CodeGenModule::getXteamRedForStmtStatus(const OMPExecutableDirective &D,
8438
8453
// the directive
8439
8454
const ForStmt *FStmt = getSingleForStmt (OMPStmt);
8440
8455
assert (FStmt != nullptr && " Unexpected missing For Stmt" );
8441
- XteamRedExprChecker Chk (RVM);
8456
+ XteamRedExprChecker Chk (* this , RVM);
8442
8457
Chk.Visit (FStmt);
8443
8458
if (!Chk.isSupported ())
8444
8459
return std::make_pair (NxUnsupportedRedExpr, HasNestedGenericCall);
@@ -8620,6 +8635,45 @@ CodeGenModule::collectXteamRedVars(const OptKernelNestDirectives &NestDirs) {
8620
8635
return std::make_pair (NxSuccess, std::make_pair (VarMap, VarVec));
8621
8636
}
8622
8637
8638
+ bool CodeGenModule::hasXteamRedVar (const Expr *E,
8639
+ const XteamRedVarMap &RedMap) const {
8640
+ assert (E && " Unexpected null expression" );
8641
+ if (!isa<DeclRefExpr>(E))
8642
+ return false ;
8643
+ auto *Decl = cast<DeclRefExpr>(E)->getDecl ();
8644
+ if (!isa<VarDecl>(Decl))
8645
+ return false ;
8646
+ auto *VD = cast<VarDecl>(Decl);
8647
+ if (RedMap.find (VD) != RedMap.end ())
8648
+ return true ;
8649
+ return false ;
8650
+ }
8651
+
8652
+ const VarDecl *
8653
+ CodeGenModule::getXteamRedVarDecl (const Expr *E,
8654
+ const XteamRedVarMap &RedMap) const {
8655
+ if (!isa<DeclRefExpr>(E))
8656
+ return nullptr ;
8657
+ const ValueDecl *ValDecl = cast<DeclRefExpr>(E)->getDecl ();
8658
+ if (!isa<VarDecl>(ValDecl))
8659
+ return nullptr ;
8660
+ const VarDecl *VD = cast<VarDecl>(ValDecl);
8661
+ if (RedMap.find (VD) == RedMap.end ())
8662
+ return nullptr ;
8663
+ return VD;
8664
+ }
8665
+
8666
+ bool CodeGenModule::isXteamRedVarExpr (const Expr *E,
8667
+ const VarDecl *RedVarDecl) const {
8668
+ if (!isa<DeclRefExpr>(E))
8669
+ return false ;
8670
+ const ValueDecl *ValDecl = cast<DeclRefExpr>(E)->getDecl ();
8671
+ if (!isa<VarDecl>(ValDecl))
8672
+ return false ;
8673
+ const VarDecl *VD = cast<VarDecl>(ValDecl);
8674
+ return VD == RedVarDecl;
8675
+ }
8676
+
8623
8677
const OMPExecutableDirective *
8624
8678
getNestedDirective (const OMPExecutableDirective &D) {
8625
8679
const Stmt *AssocStmt = D.getAssociatedStmt ();
0 commit comments