From 64c5e30342f76cd34ad50ba526ac38148435d8fc Mon Sep 17 00:00:00 2001 From: Sualeh Asif Date: Tue, 2 Mar 2021 21:46:32 -0500 Subject: [PATCH 01/64] committing recent changes. --- .gitignore | 4 ++++ cheetah | 1 + cilktools | 1 + 3 files changed, 6 insertions(+) create mode 160000 cheetah create mode 160000 cilktools diff --git a/.gitignore b/.gitignore index dfeba61ddba1..bd6eb1dd27b5 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,7 @@ autoconf/autom4te.cache .vs # clangd index .clangd + + +cheetah/* + diff --git a/cheetah b/cheetah new file mode 160000 index 000000000000..28b3801ee37e --- /dev/null +++ b/cheetah @@ -0,0 +1 @@ +Subproject commit 28b3801ee37e0f9340b782a9ada455c74fe9524b diff --git a/cilktools b/cilktools new file mode 160000 index 000000000000..185ad32ea06d --- /dev/null +++ b/cilktools @@ -0,0 +1 @@ +Subproject commit 185ad32ea06dc842dd6dc4c0d1e6e71ea659269f From a2025a696ab0a2c4005c6f41e2e6faaab51ade0c Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 2 Mar 2021 20:49:40 -0500 Subject: [PATCH 02/64] move some boilerplate over from parse --- clang/lib/Parse/ParseCilk.cpp | 124 +++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 46 deletions(-) diff --git a/clang/lib/Parse/ParseCilk.cpp b/clang/lib/Parse/ParseCilk.cpp index 8945205e0751..13eb7d93cd1e 100644 --- a/clang/lib/Parse/ParseCilk.cpp +++ b/clang/lib/Parse/ParseCilk.cpp @@ -97,11 +97,11 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { ExprResult Value; - bool ForEach = false, ForRange = false; + bool ForEach = false; StmtResult FirstPart; Sema::ConditionResult SecondPart; ExprResult Collection; - ForRangeInit ForRangeInit; + ForRangeInfo ForRangeInfo; FullExprArg ThirdPart(Actions); if (Tok.is(tok::code_completion)) { @@ -113,6 +113,8 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); + SourceLocation EmptyInitStmtSemiLoc; + // Parse the first part of the for specifier. if (Tok.is(tok::semi)) { // _Cilk_for (; ProhibitAttributes(attrs); @@ -126,20 +128,19 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { SourceLocation Loc = ConsumeToken(); MaybeParseCXX11Attributes(attrs); - ForRangeInit.ColonLoc = ConsumeToken(); + ForRangeInfo.ColonLoc = ConsumeToken(); if (Tok.is(tok::l_brace)) - ForRangeInit.RangeExpr = ParseBraceInitializer(); + ForRangeInfo.RangeExpr = ParseBraceInitializer(); else - ForRangeInit.RangeExpr = ParseExpression(); + ForRangeInfo.RangeExpr = ParseExpression(); Diag(Loc, diag::err_for_range_identifier) << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17) ? FixItHint::CreateInsertion(Loc, "auto &&") : FixItHint()); - FirstPart = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name, + ForRangeInfo.LoopVar = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name, attrs, attrs.Range.getEnd()); - ForRange = true; } else if (isForInitDeclaration()) { // _Cilk_for (int X = 4; // Parse declaration, which eats the ';'. if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? @@ -152,13 +153,13 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy DG = ParseSimpleDeclaration( DeclaratorContext::ForContext, DeclEnd, attrs, false, - MightBeForRangeStmt ? &ForRangeInit : nullptr); + MightBeForRangeStmt ? &ForRangeInfo : nullptr); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); - if (ForRangeInit.ParsedForRangeDecl()) { - Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus11 ? + if (ForRangeInfo.ParsedForRangeDecl()) { + Diag(ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_for_range : diag::ext_for_range); - - ForRange = true; + ForRangeInfo.LoopVar = FirstPart; + FirstPart = StmtResult(); } else if (Tok.is(tok::semi)) { // for (int x = 4; ConsumeToken(); } else if ((ForEach = isTokIdentifier_in())) { @@ -185,8 +186,16 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { if (!Value.isInvalid()) { if (ForEach) FirstPart = Actions.ActOnForEachLValueExpr(Value.get()); - else - FirstPart = Actions.ActOnExprStmt(Value); + else { + // We already know this is not an init-statement within a for loop, so + // if we are parsing a C++11 range-based for loop, we should treat this + // expression statement as being a discarded value expression because + // we will err below. This way we do not warn on an unused expression + // that was an error in the first place, like with: for (expr : expr); + bool IsRangeBasedFor = + getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon); + FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor); + } } if (Tok.is(tok::semi)) { @@ -221,7 +230,7 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { // Parse the second part of the for specifier. getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope); - if (!ForEach && !ForRange && !SecondPart.isInvalid()) { + if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() && !SecondPart.isInvalid()) { // Parse the second part of the for specifier. if (Tok.is(tok::semi)) { // for (...;; // no second part. @@ -232,10 +241,29 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { Diag(Tok, diag::err_cilk_for_missing_condition) << FirstPart.get()->getSourceRange(); } else { - if (getLangOpts().CPlusPlus) + if (getLangOpts().CPlusPlus) { + // C++2a: We've parsed an init-statement; we might have a + // for-range-declaration next. + bool MightBeForRangeStmt = !ForRangeInfo.ParsedForRangeDecl(); + ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); SecondPart = ParseCXXCondition(nullptr, ForLoc, Sema::ConditionKind::Boolean); - else { + + if (ForRangeInfo.ParsedForRangeDecl()) { + Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc() + : ForRangeInfo.ColonLoc, + getLangOpts().CPlusPlus2a + ? diag::warn_cxx17_compat_for_range_init_stmt + : diag::ext_for_range_init_stmt) + << (FirstPart.get() ? FirstPart.get()->getSourceRange() + : SourceRange()); + if (EmptyInitStmtSemiLoc.isValid()) { + Diag(EmptyInitStmtSemiLoc, diag::warn_empty_init_statement) + << /*for-loop*/ 2 + << FixItHint::CreateRemoval(EmptyInitStmtSemiLoc); + } + } + } else { ExprResult SecondExpr = ParseExpression(); if (SecondExpr.isInvalid()) SecondPart = Sema::ConditionError(); @@ -246,27 +274,29 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { } } - if (Tok.isNot(tok::semi)) { - if (!SecondPart.isInvalid()) - Diag(Tok, diag::err_expected_semi_for); - else - // Skip until semicolon or rparen, don't consume it. - SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch); - } + if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) { + if (Tok.isNot(tok::semi)) { + if (!SecondPart.isInvalid()) + Diag(Tok, diag::err_expected_semi_for); + else + // Skip until semicolon or rparen, don't consume it. + SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch); + } - if (Tok.is(tok::semi)) { - ConsumeToken(); - } + if (Tok.is(tok::semi)) { + ConsumeToken(); + } - // Parse the third part of the _Cilk_for specifier. - if (Tok.isNot(tok::r_paren)) { // for (...;...;) - ExprResult Third = ParseExpression(); - // FIXME: The C++11 standard doesn't actually say that this is a - // discarded-value expression, but it clearly should be. - ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.get()); - } else - Diag(Tok, diag::err_cilk_for_missing_increment) - << FirstPart.get()->getSourceRange(); + // Parse the third part of the _Cilk_for specifier. + if (Tok.isNot(tok::r_paren)) { // for (...;...;) + ExprResult Third = ParseExpression(); + // FIXME: The C++11 standard doesn't actually say that this is a + // discarded-value expression, but it clearly should be. + ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.get()); + } else + Diag(Tok, diag::err_cilk_for_missing_increment) + << FirstPart.get()->getSourceRange(); + } } // Match the ')'. T.consumeClose(); @@ -281,18 +311,19 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { // // We need to perform most of the semantic analysis for a C++0x for-range // // statememt before parsing the body, in order to be able to deduce the type // // of an auto-typed loop variable. - // StmtResult ForRangeStmt; + StmtResult ForRangeStmt; // StmtResult ForEachStmt; // TODO: Extend _Cilk_for to support these. - if (ForRange) { + if (ForRangeInfo.ParsedForRangeDecl()) { Diag(ForLoc, diag::err_cilk_for_forrange_loop_not_supported); - // ExprResult CorrectedRange = - // Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get()); - // ForRangeStmt = Actions.ActOnCXXForRangeStmt( - // getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), - // ForRangeInit.ColonLoc, CorrectedRange.get(), - // T.getCloseLocation(), Sema::BFRK_Build); + ExprResult CorrectedRange = + Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get()); + // TODO(arvid): uncomment this +// ForRangeStmt = Actions.ActIsRangeBasedForOnCXXForRangeStmt( +// getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), +// ForRangeInit.ColonLoc, CorrectedRange.get(), +// T.getCloseLocation(), Sema::BFRK_Build); // Similarly, we need to do the semantic analysis for a for-range @@ -349,8 +380,9 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { // return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(), // Body.get()); - // if (ForRange) - // return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); + // TODO(arvid): uncomment this +// if (ForRangeInfo.ParsedForRangeDecl()) +// return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); return Actions.ActOnCilkForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), nullptr, Sema::ConditionResult(), nullptr, From 9fc0a3271515c65e56fa4e7153f7852fa135fd67 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 2 Mar 2021 21:42:57 -0500 Subject: [PATCH 03/64] cilkforrange working but only cxxforrange --- clang/include/clang/Sema/Sema.h | 6 ++++++ clang/lib/Parse/ParseCilk.cpp | 12 ++++++------ clang/lib/Sema/SemaStmt.cpp | 20 ++++++++++++++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a26bfa7820d3..7fb1c96d7758 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12093,6 +12093,12 @@ class Sema final { ConstructorDestructor, BuiltinFunction }; + StmtResult ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, + Stmt *InitStmt, Stmt *First, + SourceLocation ColonLoc, Expr *Range, + SourceLocation RParenLoc, + BuildForRangeKind Kind); + StmtResult FinishCilkForRangeStmt(Stmt *S, Stmt *B); }; /// RAII object that enters a new expression evaluation context. diff --git a/clang/lib/Parse/ParseCilk.cpp b/clang/lib/Parse/ParseCilk.cpp index 13eb7d93cd1e..2e9c5ec259e5 100644 --- a/clang/lib/Parse/ParseCilk.cpp +++ b/clang/lib/Parse/ParseCilk.cpp @@ -320,10 +320,10 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { ExprResult CorrectedRange = Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get()); // TODO(arvid): uncomment this -// ForRangeStmt = Actions.ActIsRangeBasedForOnCXXForRangeStmt( -// getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), -// ForRangeInit.ColonLoc, CorrectedRange.get(), -// T.getCloseLocation(), Sema::BFRK_Build); + ForRangeStmt = Actions.ActOnCilkForRangeStmt( + getCurScope(), ForLoc, FirstPart.get(), + ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(), + T.getCloseLocation(), Sema::BFRK_Build); // Similarly, we need to do the semantic analysis for a for-range @@ -381,8 +381,8 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { // Body.get()); // TODO(arvid): uncomment this -// if (ForRangeInfo.ParsedForRangeDecl()) -// return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); + if (ForRangeInfo.ParsedForRangeDecl()) + return Actions.FinishCilkForRangeStmt(ForRangeStmt.get(), Body.get()); return Actions.ActOnCilkForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), nullptr, Sema::ConditionResult(), nullptr, diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 04cbf8dfa6d1..a645d92f6ab8 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3496,6 +3496,26 @@ static void SearchForReturnInStmt(Sema &Self, Stmt *S) { } } +// TODO: add comment +StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { + return this->FinishCXXForRangeStmt(S, B); +} + +StmtResult Sema::ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, Stmt *InitStmt, + Stmt *First, SourceLocation ColonLoc, + Expr *Range, SourceLocation RParenLoc, + BuildForRangeKind Kind) { + // we wrap the for range! + SourceLocation EmptyCoawaitLoc; + StmtResult ForRangeStmt = this->ActOnCXXForRangeStmt( + getCurScope(), ForLoc, EmptyCoawaitLoc, InitStmt, + First, ColonLoc, Range, + RParenLoc, Kind); + + return ForRangeStmt; +} + + StmtResult Sema::ActOnCilkForStmt(SourceLocation CilkForLoc, SourceLocation LParenLoc, Stmt *First, DeclStmt *Limit, ConditionResult InitCond, From 56606b512b94fa3316acf76a435011c99e041639 Mon Sep 17 00:00:00 2001 From: Sualeh Asif Date: Wed, 3 Mar 2021 00:29:26 -0500 Subject: [PATCH 04/64] implement cilkforrangestmt --- clang/include/clang/AST/RecursiveASTVisitor.h | 1 + clang/include/clang/AST/StmtCilk.h | 22 +++++++++++++++++++ clang/include/clang/Basic/StmtNodes.td | 1 + .../include/clang/Serialization/ASTBitCodes.h | 1 + clang/lib/AST/StmtCXX.cpp | 9 +++++++- clang/lib/AST/StmtPrinter.cpp | 14 ++++++++++++ clang/lib/AST/StmtProfile.cpp | 4 ++++ clang/lib/Sema/SemaStmt.cpp | 2 +- clang/lib/Serialization/ASTReaderStmt.cpp | 5 +++++ clang/lib/Serialization/ASTWriterStmt.cpp | 6 +++++ 10 files changed, 63 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 56b507fc641f..96000dd1fe29 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2669,6 +2669,7 @@ DEF_TRAVERSE_STMT(CilkSpawnStmt, {}) DEF_TRAVERSE_STMT(CilkSpawnExpr, {}) DEF_TRAVERSE_STMT(CilkSyncStmt, {}) DEF_TRAVERSE_STMT(CilkForStmt, {}) +DEF_TRAVERSE_STMT(CilkForRangeStmt, {}) // These operators (all of them) do not need any action except // iterating over the children. diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 6f10b70b98b2..84288e827dd5 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -84,6 +84,28 @@ class CilkSyncStmt : public Stmt { } }; +class CilkForRangeStmt : public Stmt { + enum { FORRANGE, END }; + Stmt* SubExprs[END]; + +public: + CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange); + + /// \brief Build an empty for range statement. + explicit CilkForRangeStmt(EmptyShell Empty) : Stmt(CilkForRangeStmtClass, Empty) { } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CilkForRangeStmtClass; + } + + CXXForRangeStmt* getCXXForRangeStmt() { + return cast_or_null(SubExprs[FORRANGE]); + } + + void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } + +}; + /// CilkForStmt - This represents a '_Cilk_for(init;cond;inc)' stmt. class CilkForStmt : public Stmt { SourceLocation CilkForLoc; diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 9acb503579b5..c7820efc4aa1 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -215,6 +215,7 @@ def CilkSyncStmt : StmtNode; def CilkSpawnStmt : StmtNode; def CilkSpawnExpr : StmtNode; def CilkForStmt : StmtNode; +def CilkForRangeStmt: StmtNode; // OpenMP Directives. def OMPExecutableDirective : StmtNode; diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 0c08bedc0137..6e68983e0b07 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1877,6 +1877,7 @@ namespace serialization { EXPR_CILKSPAWN, STMT_CILKSYNC, STMT_CILKFOR, + STMT_CILKFORRANGE, }; /// The kinds of designators that can occur in a diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index 060d090fc06a..a033da9e2824 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -11,7 +11,8 @@ //===----------------------------------------------------------------------===// #include "clang/AST/StmtCXX.h" - +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCilk.h" #include "clang/AST/ASTContext.h" using namespace clang; @@ -125,3 +126,9 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) std::copy(Args.ParamMoves.begin(), Args.ParamMoves.end(), const_cast(getParamMoves().data())); } + +CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange) + : Stmt(CilkForRangeStmtClass) +{ + SubExprs[FORRANGE] = ForRange; +} \ No newline at end of file diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index b6b679b806f3..dea7759be134 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -2562,6 +2562,20 @@ void StmtPrinter::VisitCilkForStmt(CilkForStmt *Node) { Indent() << "}"; } +void StmtPrinter::VisitCilkForRangeStmt(CilkForRangeStmt *Node) { + Indent() << "_Cilk_for ("; + if (Node->getCXXForRangeStmt()->getInit()) + PrintInitStmt(Node->getCXXForRangeStmt()->getInit(), 5); + PrintingPolicy SubPolicy(Policy); + SubPolicy.SuppressInitializers = true; + Node->getCXXForRangeStmt()->getLoopVariable()->print(OS, SubPolicy, IndentLevel); + OS << " : "; + PrintExpr(Node->getCXXForRangeStmt()->getRangeInit()); + OS << ")"; + PrintControlledStmt(Node->getCXXForRangeStmt()->getBody()); + +} + //===----------------------------------------------------------------------===// // Stmt method implementations //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 0d8be5709fb9..144d8bb0deda 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1982,6 +1982,10 @@ void StmtProfiler::VisitCilkForStmt(const CilkForStmt *S) { VisitStmt(S); } +void StmtProfiler::VisitCilkForRangeStmt(const CilkForRangeStmt *S) { + VisitStmt(S); +} + void StmtProfiler::VisitCilkSpawnStmt(const CilkSpawnStmt *S) { VisitStmt(S); } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index a645d92f6ab8..057024b62461 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3508,7 +3508,7 @@ StmtResult Sema::ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, Stmt *In // we wrap the for range! SourceLocation EmptyCoawaitLoc; StmtResult ForRangeStmt = this->ActOnCXXForRangeStmt( - getCurScope(), ForLoc, EmptyCoawaitLoc, InitStmt, + S, ForLoc, EmptyCoawaitLoc, InitStmt, First, ColonLoc, Range, RParenLoc, Kind); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index d484b6ed24de..49fa36ff1ab6 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2573,6 +2573,11 @@ void ASTStmtReader::VisitCilkForStmt(CilkForStmt *S) { S->setRParenLoc(readSourceLocation()); } +void ASTStmtReader::VisitCilkForRangeStmt(CilkForRangeStmt *S) { + VisitStmt(S); + S->setForRange(Record.readSubStmt()); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index e0c4b3119c59..f71903e4e19e 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2025,6 +2025,12 @@ void ASTStmtWriter::VisitCilkForStmt(CilkForStmt *S) { Code = serialization::STMT_CILKFOR; } +void ASTStmtWriter::VisitCilkForRangeStmt(CilkForRangeStmt *S) { + VisitStmt(S); + Record.AddStmt(S->getCXXForRangeStmt()); + Code = serialization::STMT_CILKFORRANGE; +} + //===----------------------------------------------------------------------===// // Microsoft Expressions and Statements. //===----------------------------------------------------------------------===// From 3244de720d24938b018c1bf6a0851f4ea3ed8393 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 01:50:32 -0500 Subject: [PATCH 05/64] implement tree transform i think --- clang/include/clang/Sema/Sema.h | 1 + clang/lib/Sema/SemaStmt.cpp | 8 ++++++-- clang/lib/Sema/TreeTransform.h | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7fb1c96d7758..72e9d0be9639 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12098,6 +12098,7 @@ class Sema final { SourceLocation ColonLoc, Expr *Range, SourceLocation RParenLoc, BuildForRangeKind Kind); + StmtResult BuildCilkForRangeStmt(CXXForRangeStmt *S); StmtResult FinishCilkForRangeStmt(Stmt *S, Stmt *B); }; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 057024b62461..f9555b02eed0 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3507,12 +3507,16 @@ StmtResult Sema::ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, Stmt *In BuildForRangeKind Kind) { // we wrap the for range! SourceLocation EmptyCoawaitLoc; - StmtResult ForRangeStmt = this->ActOnCXXForRangeStmt( + StmtResult ForRangeStmt = ActOnCXXForRangeStmt( S, ForLoc, EmptyCoawaitLoc, InitStmt, First, ColonLoc, Range, RParenLoc, Kind); - return ForRangeStmt; + return BuildCilkForRangeStmt(ForRangeStmt); +} + +StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { + return new (Context) CilkForRangeStmt(Context, ForRange); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index ab49046140c2..57f38cf08b48 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1368,6 +1368,14 @@ class TreeTransform { RParenLoc, Body, LoopVar); } + // Builds a new Cilk for range statement. + // TODO: this feels very hacky + StmtResult RebuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { + // we don't reconstruct the for range into its constituent parts, + // but rather let the ForRange handle it for us + return getSema().BuildCilkForRangeStmt(ForRange); + } + /// Build a new goto statement. /// /// By default, performs semantic analysis to build the new statement. @@ -13861,6 +13869,16 @@ TreeTransform::TransformCilkForStmt(CilkForStmt *S) { LoopVar, Body.get()); } +template +StmtResult +TreeTransform::TransformCilkForRangeStmt(CilkForRangeStmt *S) { + CXXForRangeStmt ForRange = getDerived().TransformStmt(S->getCXXForRangeStmt()); + if (ForRange.isInvalid()) + return StmtError(); + + return getDerived().RebuildCilkForRangeStmt(ForRange.get()); +} + } // end namespace clang #endif // LLVM_CLANG_LIB_SEMA_TREETRANSFORM_H From 299df3cf7df3bc5470486bb7ab083818183ec8f1 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 02:05:15 -0500 Subject: [PATCH 06/64] potentially fix treetransform --- clang/lib/Sema/TreeTransform.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 57f38cf08b48..4bd9380bf96f 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1370,10 +1370,10 @@ class TreeTransform { // Builds a new Cilk for range statement. // TODO: this feels very hacky - StmtResult RebuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { + StmtResult RebuildCilkForRangeStmt(Stmt *ForRange) { // we don't reconstruct the for range into its constituent parts, // but rather let the ForRange handle it for us - return getSema().BuildCilkForRangeStmt(ForRange); + return getSema().BuildCilkForRangeStmt(cast_or_null(ForRange)); } /// Build a new goto statement. @@ -13872,7 +13872,7 @@ TreeTransform::TransformCilkForStmt(CilkForStmt *S) { template StmtResult TreeTransform::TransformCilkForRangeStmt(CilkForRangeStmt *S) { - CXXForRangeStmt ForRange = getDerived().TransformStmt(S->getCXXForRangeStmt()); + StmtResult ForRange = getDerived().TransformStmt(S->getCXXForRangeStmt()); if (ForRange.isInvalid()) return StmtError(); From 347e3670848222e1c4e536e7dde74c3c488eb554 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 02:08:38 -0500 Subject: [PATCH 07/64] add reqd beginloc and endloc --- clang/include/clang/AST/StmtCilk.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 84288e827dd5..db16f5e3d446 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -98,12 +98,17 @@ class CilkForRangeStmt : public Stmt { return T->getStmtClass() == CilkForRangeStmtClass; } - CXXForRangeStmt* getCXXForRangeStmt() { + CXXForRangeStmt* getCXXForRangeStmt() const { return cast_or_null(SubExprs[FORRANGE]); } void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } + SourceLocation getBeginLoc() const LLVM_READONLY { return getCXXForRangeStmt()->getBeginLoc(); } + SourceLocation getEndLoc() const LLVM_READONLY { + return getCXXForRangeStmt()->getEndLoc(); + } + }; /// CilkForStmt - This represents a '_Cilk_for(init;cond;inc)' stmt. From 0980963ebfc395fd4a168d4803e492b9a14d30da Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 02:29:58 -0500 Subject: [PATCH 08/64] move getbeginloc and getendloc implementations to .cpp file --- clang/include/clang/AST/StmtCilk.h | 6 ++---- clang/lib/AST/Stmt.cpp | 4 ++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index db16f5e3d446..90ad26b90a11 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -104,10 +104,8 @@ class CilkForRangeStmt : public Stmt { void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } - SourceLocation getBeginLoc() const LLVM_READONLY { return getCXXForRangeStmt()->getBeginLoc(); } - SourceLocation getEndLoc() const LLVM_READONLY { - return getCXXForRangeStmt()->getEndLoc(); - } + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; }; diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 2cfd714c340a..0f3fdef159da 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1401,3 +1401,7 @@ void CilkForStmt::setLoopVariable(const ASTContext &C, VarDecl *V) { SubExprs[LOOPVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); } +SourceLocation CilkForRangeStmt::getBeginLoc() const LLVM_READONLY { return getCXXForRangeStmt()->getBeginLoc(); } +SourceLocation CilkForRangeStmt::getEndLoc() const LLVM_READONLY { + return getCXXForRangeStmt()->getEndLoc(); +} From 3e6803312ab86102cfac5e4ed5f881660f8f5995 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 02:32:28 -0500 Subject: [PATCH 09/64] move more things into .cpp instead of .h --- clang/include/clang/AST/StmtCilk.h | 4 +--- clang/lib/AST/Stmt.cpp | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 90ad26b90a11..cafea7020773 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -98,9 +98,7 @@ class CilkForRangeStmt : public Stmt { return T->getStmtClass() == CilkForRangeStmtClass; } - CXXForRangeStmt* getCXXForRangeStmt() const { - return cast_or_null(SubExprs[FORRANGE]); - } + CXXForRangeStmt* getCXXForRangeStmt() const; void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 0f3fdef159da..64caf3f46fcd 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1401,6 +1401,10 @@ void CilkForStmt::setLoopVariable(const ASTContext &C, VarDecl *V) { SubExprs[LOOPVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); } + +CXXForRangeStmt* CilkForRangeStmt::getCXXForRangeStmt() const { + return cast_or_null(SubExprs[FORRANGE]); +} SourceLocation CilkForRangeStmt::getBeginLoc() const LLVM_READONLY { return getCXXForRangeStmt()->getBeginLoc(); } SourceLocation CilkForRangeStmt::getEndLoc() const LLVM_READONLY { return getCXXForRangeStmt()->getEndLoc(); From 6bf77ca79f72158e6f1925239875dbcc397a714e Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 02:35:20 -0500 Subject: [PATCH 10/64] handle cilkforrange in astreaderstmt --- clang/lib/Serialization/ASTReaderStmt.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 49fa36ff1ab6..54b3d9cb8a0d 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2793,6 +2793,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) CilkForStmt(Empty); break; + case STMT_CILKFORRANGE: + S = new (Context) CilkForRangeStmt(Empty); + break; + case EXPR_PREDEFINED: S = PredefinedExpr::CreateEmpty( Context, From 9938405353e2ce2915cf1bdcd886d6c903517ffe Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 02:41:26 -0500 Subject: [PATCH 11/64] fix bugs hopefully --- clang/include/clang/AST/StmtCilk.h | 10 ++++++++-- clang/lib/CodeGen/CGStmt.cpp | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index cafea7020773..67923b49c4a8 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_AST_STMTCILK_H #include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" #include "clang/Basic/SourceLocation.h" namespace clang { @@ -102,8 +103,13 @@ class CilkForRangeStmt : public Stmt { void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } - SourceLocation getBeginLoc() const LLVM_READONLY; - SourceLocation getEndLoc() const LLVM_READONLY; + SourceLocation getBeginLoc() const; + SourceLocation getEndLoc() const; + + // Iterators + child_range children() { + return child_range(&SubExprs[0], &SubExprs[END]); + } }; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index c01f746baca2..4c222bdc347d 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -165,6 +165,10 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) { case Stmt::CilkForStmtClass: EmitCilkForStmt(cast(*S), Attrs); break; + case Stmt::CilkForRangeStmtClass: + // TODO(cilkforrange): emit the right thing here! + EmitCXXForRangeStmt(cast(*S)->getCXXForRangeStmt(), Attrs); + break; case Stmt::ObjCAtTryStmtClass: EmitObjCAtTryStmt(cast(*S)); break; From 499de40ecff5a2e12329143ef4f0d2b412adec8c Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 02:43:32 -0500 Subject: [PATCH 12/64] do some casting things --- clang/lib/CodeGen/CGStmt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 4c222bdc347d..2639c670fc5b 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -167,7 +167,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) { break; case Stmt::CilkForRangeStmtClass: // TODO(cilkforrange): emit the right thing here! - EmitCXXForRangeStmt(cast(*S)->getCXXForRangeStmt(), Attrs); + EmitCXXForRangeStmt(*cast(*S).getCXXForRangeStmt(), Attrs); break; case Stmt::ObjCAtTryStmtClass: EmitObjCAtTryStmt(cast(*S)); From 373a389bd3127f720baf308dcd6407b5bf6c801e Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 02:49:24 -0500 Subject: [PATCH 13/64] casting in a better way --- clang/include/clang/AST/StmtCilk.h | 4 ++-- clang/lib/AST/Stmt.cpp | 4 ++-- clang/lib/Sema/SemaExceptionSpec.cpp | 1 + clang/lib/Sema/SemaStmt.cpp | 5 ++++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 67923b49c4a8..3de1e13c00ee 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -103,8 +103,8 @@ class CilkForRangeStmt : public Stmt { void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } - SourceLocation getBeginLoc() const; - SourceLocation getEndLoc() const; + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; // Iterators child_range children() { diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 64caf3f46fcd..9eb16c34a896 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1405,7 +1405,7 @@ void CilkForStmt::setLoopVariable(const ASTContext &C, VarDecl *V) { CXXForRangeStmt* CilkForRangeStmt::getCXXForRangeStmt() const { return cast_or_null(SubExprs[FORRANGE]); } -SourceLocation CilkForRangeStmt::getBeginLoc() const LLVM_READONLY { return getCXXForRangeStmt()->getBeginLoc(); } -SourceLocation CilkForRangeStmt::getEndLoc() const LLVM_READONLY { +SourceLocation CilkForRangeStmt::getBeginLoc() const { return getCXXForRangeStmt()->getBeginLoc(); } +SourceLocation CilkForRangeStmt::getEndLoc() const { return getCXXForRangeStmt()->getEndLoc(); } diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 5e926046ae59..24b27c07b9d4 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1483,6 +1483,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) { case Stmt::CilkSpawnStmtClass: case Stmt::CilkSyncStmtClass: case Stmt::CilkForStmtClass: + case Stmt::CilkForRangeStmtClass: return canSubStmtsThrow(*this, S); case Stmt::DeclStmtClass: { diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index f9555b02eed0..25134fb7ceed 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3512,7 +3512,10 @@ StmtResult Sema::ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, Stmt *In First, ColonLoc, Range, RParenLoc, Kind); - return BuildCilkForRangeStmt(ForRangeStmt); + if (ForRangeStmt.isInvalid()) + return ForRangeStmt; + + return BuildCilkForRangeStmt(cast_or_null(ForRangeStmt.get())); } StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { From 93bb184d4dfb4a8391de7486e16e72b20a1b5b84 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 03:17:14 -0500 Subject: [PATCH 14/64] more for range where it should be --- clang/include/clang-c/Index.h | 6 +++++- clang/tools/libclang/CXCursor.cpp | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index e35ceb8527a1..00e4a3c88cd4 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2590,7 +2590,11 @@ enum CXCursorKind { */ CXCursor_CilkForStmt = 289, - CXCursor_LastStmt = CXCursor_CilkForStmt, + /** A _Cilk_for range statement. + */ + CXCursor_CilkForRangeStmt = 290, + + CXCursor_LastStmt = CXCursor_CilkForRangeStmt, /** * Cursor that represents the translation unit itself. diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 2c8c114efcf3..3e9754437ca8 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -266,6 +266,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, K = CXCursor_CilkForStmt; break; + case Stmt::CilkForRangeStmtClass: + K = CXCursor_CilkForRangeStmt; + break; + case Stmt::ArrayTypeTraitExprClass: case Stmt::AsTypeExprClass: case Stmt::AtomicExprClass: From 58e37509b452506d0999b1b53946f679f397e937 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 03:22:14 -0500 Subject: [PATCH 15/64] do correct casting --- clang/lib/Sema/SemaStmt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 25134fb7ceed..7ffac1064749 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3498,7 +3498,7 @@ static void SearchForReturnInStmt(Sema &Self, Stmt *S) { // TODO: add comment StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { - return this->FinishCXXForRangeStmt(S, B); + return FinishCXXForRangeStmt(cast(S)->getCXXForRangeStmt(), B); } StmtResult Sema::ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, Stmt *InitStmt, From 78115021cd7e8a8fc5ce4f5719a3ea42d94524a6 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 03:31:36 -0500 Subject: [PATCH 16/64] add warning that forrange support is experimental --- clang/include/clang/Basic/DiagnosticParseKinds.td | 5 +++-- clang/lib/Parse/ParseCilk.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 5a094c7acfec..c054058153e6 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1221,8 +1221,6 @@ def err_cilk_for_missing_increment: Error< "missing loop increment expression in '_Cilk_for'">; def err_cilk_for_missing_semi: Error< "expected ';' in '_Cilk_for'">; -def err_cilk_for_forrange_loop_not_supported: Error< - "'_Cilk_for' not supported on for-range loops">; def err_cilk_for_foreach_loop_not_supported: Error< "'_Cilk_for' not supported on for-each loops">; def err_pragma_cilk_invalid_option : Error< @@ -1235,6 +1233,9 @@ def warn_cilk_for_following_grainsize: Warning< def warn_pragma_cilk_grainsize_equals: Warning< "'#pragma cilk grainsize' no longer requires '='">, InGroup; +def warn_cilk_for_forrange_loop_experimental: Warning< + "'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!">, + InGroup; // OpenMP support. def warn_pragma_omp_ignored : Warning< diff --git a/clang/lib/Parse/ParseCilk.cpp b/clang/lib/Parse/ParseCilk.cpp index 2e9c5ec259e5..3744d27ffc6e 100644 --- a/clang/lib/Parse/ParseCilk.cpp +++ b/clang/lib/Parse/ParseCilk.cpp @@ -316,7 +316,7 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { // TODO: Extend _Cilk_for to support these. if (ForRangeInfo.ParsedForRangeDecl()) { - Diag(ForLoc, diag::err_cilk_for_forrange_loop_not_supported); + Diag(ForLoc, diag::warn_cilk_for_forrange_loop_experimental); ExprResult CorrectedRange = Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get()); // TODO(arvid): uncomment this From 0ea1aee880cccefee23192d46e79390d8807b7af Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 03:34:03 -0500 Subject: [PATCH 17/64] add more cases to switch statements --- clang/tools/libclang/CIndex.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 245334779199..edda06583776 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -5584,6 +5584,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("CilkSyncStmt"); case CXCursor_CilkForStmt: return cxstring::createRef("CilkForStmt"); + case CXCursor_CilkForRangeStmt: + return cxstring::createRef("CilkForRangeStmt"); } llvm_unreachable("Unhandled CXCursorKind"); From a550c6dc62f0d644d46a0cba8655810f8d6e6e4b Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 3 Mar 2021 03:41:38 -0500 Subject: [PATCH 18/64] actually wrap the cxxforrangestmt --- clang/lib/Sema/SemaStmt.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 7ffac1064749..f00e488759c4 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3498,7 +3498,12 @@ static void SearchForReturnInStmt(Sema &Self, Stmt *S) { // TODO: add comment StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { - return FinishCXXForRangeStmt(cast(S)->getCXXForRangeStmt(), B); + CilkForRangeStmt *CilkForRange = cast(S); + StmtResult ForRange = FinishCXXForRangeStmt(CilkForRange->getCXXForRangeStmt(), B); + if (ForRange.isInvalid()) + return StmtError(); + CilkForRange->setForRange(ForRange.get()); + return CilkForRange; } StmtResult Sema::ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, Stmt *InitStmt, From db7f02bd89d5f633c2b5eb3230c0ced4338c7cf1 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Mon, 8 Mar 2021 22:15:45 -0500 Subject: [PATCH 19/64] implement first version of emitcilkforrange --- clang/lib/CodeGen/CGCilk.cpp | 270 ++++++++++++++++++++++++++++ clang/lib/CodeGen/CGStmt.cpp | 3 +- clang/lib/CodeGen/CodeGenFunction.h | 2 + 3 files changed, 273 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index 7abc0235f2b4..1c075be91165 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -817,3 +817,273 @@ void CodeGenFunction::EmitCilkForStmt(const CilkForStmt &S, if (TempInvokeDest->use_empty()) delete TempInvokeDest; } + +void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, + ArrayRef ForAttrs) { + JumpDest LoopExit = getJumpDestInCurrentScope("pfor.end"); + + PushSyncRegion(); + llvm::Instruction *SyncRegion = EmitSyncRegionStart(); + CurSyncRegion->setSyncRegionStart(SyncRegion); + + llvm::BasicBlock *TempInvokeDest = createBasicBlock("temp.invoke.dest"); + + LexicalScope ForScope(*this, S.getSourceRange()); + + const CXXForRangeStmt &ForRange = *S.getCXXForRangeStmt(); + + // Evaluate the first part before the loop. + if (ForRange.getInit()) + EmitStmt(ForRange.getInit()); + + llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); + + EmitStmt(ForRange.getRangeStmt()); + EmitStmt(ForRange.getBeginStmt()); + EmitStmt(ForRange.getEndStmt()); + + // Start the loop with a block that tests the condition. If there's an + // increment, the continue scope will be overwritten later. + JumpDest Continue = getJumpDestInCurrentScope("pfor.cond"); + llvm::BasicBlock *CondBlock = Continue.getBlock(); + EmitBlock(CondBlock); + + LoopStack.setSpawnStrategy(LoopAttributes::DAC); + const SourceRange &R = S.getSourceRange(); + LoopStack.push(CondBlock, CGM.getContext(), ForAttrs, + SourceLocToDebugLoc(R.getBegin()), + SourceLocToDebugLoc(R.getEnd())); + + const Expr *Inc = ForRange.getInc(); + assert(Inc && "_Cilk_for range loop has no increment"); + Continue = getJumpDestInCurrentScope("pfor.inc"); + + // Ensure that the _Cilk_for loop iterations are synced on exit from the loop. + EHStack.pushCleanup(NormalCleanup, SyncRegion); + + // Create a cleanup scope for the condition variable cleanups. + LexicalScope ConditionScope(*this, S.getSourceRange()); + + // Variables to store the old alloca insert point. + llvm::AssertingVH OldAllocaInsertPt; + // Variables to store the old EH state. + llvm::BasicBlock *OldEHResumeBlock; + llvm::Value *OldExceptionSlot; + llvm::AllocaInst *OldEHSelectorSlot; + Address OldNormalCleanupDest = Address::invalid(); + + const VarDecl *LoopVar = ForRange.getLoopVariable(); + RValue LoopVarInitRV; + llvm::BasicBlock *DetachBlock; + llvm::BasicBlock *ForBodyEntry; + llvm::BasicBlock *ForBody; + llvm::DetachInst *Detach; + { + // FIXME: Figure out if there is a way to support condition variables in + // Cilk. + // + // // If the for statement has a condition scope, emit the local variable + // // declaration. + // if (S.getConditionVariable()) { + // EmitAutoVarDecl(*S.getConditionVariable()); + // } + + // If there are any cleanups between here and the loop-exit scope, + // create a block to stage a loop exit along. + if (ForScope.requiresCleanups()) + ExitBlock = createBasicBlock("pfor.cond.cleanup"); + + // As long as the condition is true, iterate the loop. + DetachBlock = createBasicBlock("pfor.detach"); + // Emit extra entry block for detached body, to ensure that this detached + // entry block has just one predecessor. + ForBodyEntry = createBasicBlock("pfor.body.entry"); + ForBody = createBasicBlock("pfor.body"); + + EmitBranch(DetachBlock); + + EmitBlockAfterUses(DetachBlock); + + // Get the value of the loop variable initialization before we emit the + // detach. + if (LoopVar) + LoopVarInitRV = EmitAnyExprToTemp(LoopVar->getInit()); + + Detach = Builder.CreateDetach(ForBodyEntry, Continue.getBlock(), + SyncRegion); + // Save the old alloca insert point. + OldAllocaInsertPt = AllocaInsertPt; + // Save the old EH state. + OldEHResumeBlock = EHResumeBlock; + OldExceptionSlot = ExceptionSlot; + OldEHSelectorSlot = EHSelectorSlot; + OldNormalCleanupDest = NormalCleanupDest; + + // Create a new alloca insert point. + llvm::Value *Undef = llvm::UndefValue::get(Int32Ty); + AllocaInsertPt = new llvm::BitCastInst(Undef, Int32Ty, "", ForBodyEntry); + + // Push a cleanup to make sure any exceptional exit from the loop is + // terminated by a detached.rethrow. + EHStack.pushCleanup( + static_cast(EHCleanup | LifetimeMarker | TaskExit), + SyncRegion, TempInvokeDest); + + // Set up nested EH state. + EHResumeBlock = nullptr; + ExceptionSlot = nullptr; + EHSelectorSlot = nullptr; + NormalCleanupDest = Address::invalid(); + + EmitBlock(ForBodyEntry); + } + + RunCleanupsScope DetachCleanupsScope(*this); + + // Set up a nested sync region for the loop body, and ensure it has an + // implicit sync. + PushSyncRegion()->addImplicitSync(); + + // Store the blocks to use for break and continue. + JumpDest Preattach = getJumpDestInCurrentScope("pfor.preattach"); + BreakContinueStack.push_back(BreakContinue(Preattach, Preattach)); + + // Inside the detached block, create the loop variable, setting its value to + // the saved initialization value. + if (LoopVar) { + AutoVarEmission LVEmission = EmitAutoVarAlloca(*LoopVar); + QualType type = LoopVar->getType(); + Address Loc = LVEmission.getObjectAddress(*this); + LValue LV = MakeAddrLValue(Loc, type); + LV.setNonGC(true); + EmitStoreThroughLValue(LoopVarInitRV, LV, true); + EmitAutoVarCleanups(LVEmission); + } + + Builder.CreateBr(ForBody); + + EmitBlock(ForBody); + + incrementProfileCounter(&S); + + { + // Create a separate cleanup scope for the body, in case it is not + // a compound statement. + RunCleanupsScope BodyScope(*this); + + SyncedScopeRAII SyncedScp(*this); + if (isa(ForRange.getBody())) + ScopeIsSynced = true; + EmitStmt(ForRange.getBody()); + + if (HaveInsertPoint()) + Builder.CreateBr(Preattach.getBlock()); + } + + // Finish detached body and emit the reattach. + { + EmitBlock(Preattach.getBlock()); + // The design of the exception-handling mechanism means we need to cleanup + // the scope before popping the sync region. + DetachCleanupsScope.ForceCleanup(); + PopSyncRegion(); + // Pop the detached.rethrow cleanup. + PopCleanupBlock(); + Builder.CreateReattach(Continue.getBlock(), SyncRegion); + } + + // Restore CGF state after detached region. + llvm::BasicBlock *NestedEHResumeBlock; + { + // Restore the alloca insertion point. + llvm::Instruction *Ptr = AllocaInsertPt; + AllocaInsertPt = OldAllocaInsertPt; + Ptr->eraseFromParent(); + + // Restore the EH state. + NestedEHResumeBlock = EHResumeBlock; + EHResumeBlock = OldEHResumeBlock; + ExceptionSlot = OldExceptionSlot; + EHSelectorSlot = OldEHSelectorSlot; + NormalCleanupDest = OldNormalCleanupDest; + } + + // An invocation of the detached.rethrow intrinsic marks the end of an + // exceptional return from the parallel-loop body. That invoke needs a valid + // landinpad as its unwind destination. We create that unwind destination + // here. + llvm::BasicBlock *InvokeDest = nullptr; + if (!TempInvokeDest->use_empty()) { + InvokeDest = getInvokeDest(); + if (InvokeDest) + TempInvokeDest->replaceAllUsesWith(InvokeDest); + else { + InvokeDest = TempInvokeDest; + EmitTrivialLandingPad(*this, TempInvokeDest); + } + } + + // If invocations in the parallel task led to the creation of EHResumeBlock, + // we need to create for outside the task. In particular, the new + // EHResumeBlock must use an ExceptionSlot and EHSelectorSlot allocated + // outside of the task. + if (NestedEHResumeBlock) { + if (!NestedEHResumeBlock->use_empty()) { + // Translate the nested EHResumeBlock into an appropriate EHResumeBlock in + // the outer scope. + NestedEHResumeBlock->replaceAllUsesWith( + getEHResumeBlock( + isa(NestedEHResumeBlock->getTerminator()))); + } + delete NestedEHResumeBlock; + } + + // Emit the increment next. + EmitBlockAfterUses(Continue.getBlock()); + EmitStmt(Inc); + + { + // If the detached-rethrow handler is used, add an unwind destination to the + // detach. + if (InvokeDest) { + CGBuilderTy::InsertPoint SavedIP = Builder.saveIP(); + Builder.SetInsertPoint(DetachBlock); + // Create the new detach instruction. + llvm::DetachInst *NewDetach = Builder.CreateDetach( + ForBodyEntry, Continue.getBlock(), InvokeDest, + SyncRegion); + // Remove the old detach. + Detach->eraseFromParent(); + Detach = NewDetach; + Builder.restoreIP(SavedIP); + } + } + + BreakContinueStack.pop_back(); + + ConditionScope.ForceCleanup(); + + EmitStopPoint(&S); + + // C99 6.8.5p2/p4: The first substatement is executed if the expression + // compares unequal to 0. The condition must be a scalar type. + llvm::Value *BoolCondVal = EvaluateExprAsBool(ForRange.getCond()); + Builder.CreateCondBr( + BoolCondVal, CondBlock, ExitBlock, + createProfileWeightsForLoop(ForRange.getCond(), getProfileCount(ForRange.getBody()))); + + if (ExitBlock != LoopExit.getBlock()) { + EmitBlock(ExitBlock); + EmitBranchThroughCleanup(LoopExit); + } + + ForScope.ForceCleanup(); + + LoopStack.pop(); + // Emit the fall-through block. + EmitBlock(LoopExit.getBlock(), true); + PopSyncRegion(); + + if (TempInvokeDest->use_empty()) + delete TempInvokeDest; +} diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 2639c670fc5b..68cb17726a40 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -166,8 +166,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) { EmitCilkForStmt(cast(*S), Attrs); break; case Stmt::CilkForRangeStmtClass: - // TODO(cilkforrange): emit the right thing here! - EmitCXXForRangeStmt(*cast(*S).getCXXForRangeStmt(), Attrs); + EmitCilkForRangeStmt(cast(*S), Attrs); break; case Stmt::ObjCAtTryStmtClass: EmitObjCAtTryStmt(cast(*S)); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 145367ad9386..8267b27c5f70 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4934,6 +4934,8 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmitX86CpuSupports(uint64_t Mask); llvm::Value *EmitX86CpuInit(); llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO); + void EmitCilkForRangeStmt(const CilkForRangeStmt &S, + ArrayRef ForAttrs); }; inline DominatingLLVMValue::saved_type From 4d8670f08475c569292162fc088e7520a5d360cc Mon Sep 17 00:00:00 2001 From: Sualeh Asif Date: Sun, 14 Mar 2021 15:40:42 -0400 Subject: [PATCH 20/64] updated everything to use difference type instead. --- clang/include/clang/AST/StmtCilk.h | 7 +++- .../clang/Basic/DiagnosticSemaKinds.td | 10 ++++- clang/lib/CodeGen/CGCilk.cpp | 6 +++ clang/lib/CodeGen/CodeGenFunction.h | 4 +- clang/lib/Sema/SemaStmt.cpp | 42 ++++++++++++++++++- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 3de1e13c00ee..83409d3cc2c3 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -86,11 +86,11 @@ class CilkSyncStmt : public Stmt { }; class CilkForRangeStmt : public Stmt { - enum { FORRANGE, END }; + enum { FORRANGE, LOOPVAR, COND, END }; Stmt* SubExprs[END]; public: - CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange); + CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopVar); /// \brief Build an empty for range statement. explicit CilkForRangeStmt(EmptyShell Empty) : Stmt(CilkForRangeStmtClass, Empty) { } @@ -103,6 +103,9 @@ class CilkForRangeStmt : public Stmt { void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } + VarDecl *getLoopVariable() const; + void setLoopVariable(const ASTContext &C, VarDecl *V); + SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1a04adef8e49..06da308a128e 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9487,6 +9487,7 @@ def note_cilk_for_loop_control_var_declared_here: Note< def warn_empty_cilk_for_body : Warning< "Cilk for loop has empty body">, InGroup; + def note_constant_stride: Note< "constant stride is %0">; def warn_cilk_for_cond_user_defined_conv: Warning< @@ -9519,7 +9520,13 @@ def note_exits_cilk_for : Note< "jump exits the scope of a '_Cilk_for'">; def err_jump_out_of_cilk_for : Error< "cannot jump out of '_Cilk_for' statement">; -} // end of Cilk category + +// Cilk For Range errors + +def err_cilk_for_range_begin_minus_end : Error< + "Cannot determine length with '__begin - __end'. Please use a random access iterator.">; +} +// end of Cilk category let CategoryName = "OpenMP Issue" in { // OpenMP support. @@ -10509,5 +10516,4 @@ def warn_sycl_kernel_num_of_function_params : Warning< def warn_sycl_kernel_return_type : Warning< "function template with 'sycl_kernel' attribute must have a 'void' return type">, InGroup; - } // end of sema component. diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index 1c075be91165..750992ed7656 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -838,6 +838,12 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); + // TODO: emit difference variable instead of beginstmt and endstmt + // plan: + // 1. add difference variable and emit it, check + // 2. make loop condition depend on the difference variable instead, check + // 3. finally, don't mutate beginstmt and instead do begin=begin+inductionvar + EmitStmt(ForRange.getRangeStmt()); EmitStmt(ForRange.getBeginStmt()); EmitStmt(ForRange.getEndStmt()); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 8267b27c5f70..35acdcdbb3d4 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3441,6 +3441,8 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitCilkSyncStmt(const CilkSyncStmt &S); void EmitCilkForStmt(const CilkForStmt &S, ArrayRef Attrs = None); + void EmitCilkForRangeStmt(const CilkForRangeStmt &S, + ArrayRef Attrs = None); LValue EmitCilkSpawnExprLValue(const CilkSpawnExpr *E); void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S); @@ -4934,8 +4936,6 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmitX86CpuSupports(uint64_t Mask); llvm::Value *EmitX86CpuInit(); llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO); - void EmitCilkForRangeStmt(const CilkForRangeStmt &S, - ArrayRef ForAttrs); }; inline DominatingLLVMValue::saved_type diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index f00e488759c4..aedeb2e3a314 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3524,7 +3524,47 @@ StmtResult Sema::ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, Stmt *In } StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { - return new (Context) CilkForRangeStmt(Context, ForRange); + Scope *S = getCurScope(); + + // buld up the difference type + // create an end - begin stmt + // that will be the loop var stmt + VarDecl *BeginVar = cast(ForRange->getBeginStmt()->getSingleDecl()); + QualType BeginType = BeginVar->getType(); + const QualType BeginRefNonRefType = BeginType.getNonReferenceType(); + ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, + VK_LValue, ForRange->getColonLoc()); + + VarDecl *EndVar = cast(ForRange->getEndStmt()->getSingleDecl()); + QualType EndType = EndVar->getType(); + const QualType EndRefNonRefType = EndType.getNonReferenceType(); + ExprResult EndRef = BuildDeclRefExpr(EndVar, EndRefNonRefType, + VK_LValue, ForRange->getColonLoc()); + ExprResult LoopBoundExpr = ActOnBinOp(S, ForRange->getColonLoc(), tok::minus, EndRef.get(), BeginRef.get()); + if (!LoopBoundExpr.isInvalid()) { + // give warning about for range only supporting random access! + Diag(ForRange->getForLoc(), diag::err_cilk_for_range_begin_minus_end); + return StmtError(); + } + +// TODO: different loc??? + SourceLocation RangeLoc = ForRange->getBeginLoc(); + VarDecl *LoopVar = BuildForRangeVarDecl(*this, RangeLoc, LoopBoundExpr.get()->getType(), std::string("__cilk_loopvar")); + AddInitializerToDecl(LoopVar, ActOnIntegerConstant(RangeLoc, 0).get(), + /*DirectInit=*/false); + FinalizeDeclaration(LoopVar); + CurContext->addHiddenDecl(LoopVar); + + ExprResult LoopVarRef = BuildDeclRefExpr(LoopVar, LoopVar->getType(), VK_LValue, + RangeLoc); + ExprResult Cond; + Cond = ActOnBinOp(S, RangeLoc, tok::exclaimequal, LoopVarRef.get(), + LoopBoundExpr.get()); + if (Cond.isInvalid()) + return StmtError(); + + + return new (Context) CilkForRangeStmt(Context, ForRange, LoopVar, Cond); } From 7df2dc8efb84464c2b719d9dbbcbbdc691230aeb Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Mon, 15 Mar 2021 22:32:48 -0400 Subject: [PATCH 21/64] fix things --- clang/include/clang/AST/StmtCilk.h | 2 +- clang/lib/AST/Stmt.cpp | 8 -------- clang/lib/AST/StmtCXX.cpp | 33 ++++++++++++++++++++++++++++-- clang/lib/Sema/SemaStmt.cpp | 4 ++-- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 83409d3cc2c3..eaa5eb76f7fa 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -90,7 +90,7 @@ class CilkForRangeStmt : public Stmt { Stmt* SubExprs[END]; public: - CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopVar); + CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopVar, Expr *Cond); /// \brief Build an empty for range statement. explicit CilkForRangeStmt(EmptyShell Empty) : Stmt(CilkForRangeStmtClass, Empty) { } diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 9eb16c34a896..2cfd714c340a 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1401,11 +1401,3 @@ void CilkForStmt::setLoopVariable(const ASTContext &C, VarDecl *V) { SubExprs[LOOPVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); } - -CXXForRangeStmt* CilkForRangeStmt::getCXXForRangeStmt() const { - return cast_or_null(SubExprs[FORRANGE]); -} -SourceLocation CilkForRangeStmt::getBeginLoc() const { return getCXXForRangeStmt()->getBeginLoc(); } -SourceLocation CilkForRangeStmt::getEndLoc() const { - return getCXXForRangeStmt()->getEndLoc(); -} diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index a033da9e2824..854180897ce5 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -127,8 +127,37 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) const_cast(getParamMoves().data())); } -CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange) +CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, + VarDecl *LoopVar, Expr *Cond) : Stmt(CilkForRangeStmtClass) { SubExprs[FORRANGE] = ForRange; -} \ No newline at end of file + setLoopVariable(C, LoopVar); + SubExprs[COND] = Cond; +} +VarDecl *CilkForStmt::getLoopVariable() const { + if (!SubExprs[LOOPVAR]) + return nullptr; + + DeclStmt *DS = cast(SubExprs[LOOPVAR]); + return cast(DS->getSingleDecl()); +} + +void CilkForStmt::setLoopVariable(const ASTContext &C, VarDecl *V) { + if (!V) { + SubExprs[LOOPVAR] = nullptr; + return; + } + + SourceRange VarRange = V->getSourceRange(); + SubExprs[LOOPVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), + VarRange.getEnd()); +} + +CXXForRangeStmt* CilkForRangeStmt::getCXXForRangeStmt() const { + return cast_or_null(SubExprs[FORRANGE]); +} +SourceLocation CilkForRangeStmt::getBeginLoc() const { return getCXXForRangeStmt()->getBeginLoc(); } +SourceLocation CilkForRangeStmt::getEndLoc() const { + return getCXXForRangeStmt()->getEndLoc(); +} diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index aedeb2e3a314..4a84fab204ad 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3562,9 +3562,9 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { LoopBoundExpr.get()); if (Cond.isInvalid()) return StmtError(); - - return new (Context) CilkForRangeStmt(Context, ForRange, LoopVar, Cond); + + return new (Context) CilkForRangeStmt(Context, ForRange, LoopVar, Cond.get()); } From 5479509e3c322fc1add4d00be59cdf12b5aec1fa Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Mon, 15 Mar 2021 22:45:26 -0400 Subject: [PATCH 22/64] stupid --- clang/lib/AST/StmtCXX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index 854180897ce5..2306736cbafb 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -135,7 +135,7 @@ CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRang setLoopVariable(C, LoopVar); SubExprs[COND] = Cond; } -VarDecl *CilkForStmt::getLoopVariable() const { +VarDecl *CilkForRangeStmt::getLoopVariable() const { if (!SubExprs[LOOPVAR]) return nullptr; @@ -143,7 +143,7 @@ VarDecl *CilkForStmt::getLoopVariable() const { return cast(DS->getSingleDecl()); } -void CilkForStmt::setLoopVariable(const ASTContext &C, VarDecl *V) { +void CilkForRangeStmt::setLoopVariable(const ASTContext &C, VarDecl *V) { if (!V) { SubExprs[LOOPVAR] = nullptr; return; From 9500c4ed9d6cc1cd8574503bd26359c66681a4c4 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Mon, 15 Mar 2021 23:00:18 -0400 Subject: [PATCH 23/64] stupid again --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 ++-- clang/lib/Sema/SemaStmt.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 06da308a128e..8a19cb3f552b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9523,8 +9523,8 @@ def err_jump_out_of_cilk_for : Error< // Cilk For Range errors -def err_cilk_for_range_begin_minus_end : Error< - "Cannot determine length with '__begin - __end'. Please use a random access iterator.">; +def err_cilk_for_range_end_minus_begin : Error< + "Cannot determine length with '__end - __begin'. Please use a random access iterator.">; } // end of Cilk category diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 4a84fab204ad..fd16d295c23b 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3541,9 +3541,9 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { ExprResult EndRef = BuildDeclRefExpr(EndVar, EndRefNonRefType, VK_LValue, ForRange->getColonLoc()); ExprResult LoopBoundExpr = ActOnBinOp(S, ForRange->getColonLoc(), tok::minus, EndRef.get(), BeginRef.get()); - if (!LoopBoundExpr.isInvalid()) { + if (LoopBoundExpr.isInvalid()) { // give warning about for range only supporting random access! - Diag(ForRange->getForLoc(), diag::err_cilk_for_range_begin_minus_end); + Diag(ForRange->getForLoc(), diag::err_cilk_for_range_end_minus_begin); return StmtError(); } From 52aa9a9fefc2d099620d8bd41159860d8857ea9b Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Mon, 15 Mar 2021 23:32:15 -0400 Subject: [PATCH 24/64] should work --- clang/include/clang/AST/StmtCilk.h | 8 +++---- clang/lib/AST/StmtCXX.cpp | 16 ++++++------- clang/lib/Sema/SemaStmt.cpp | 37 ++++++++++++++++++++++++------ 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index eaa5eb76f7fa..b1583b89bb90 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -86,11 +86,11 @@ class CilkSyncStmt : public Stmt { }; class CilkForRangeStmt : public Stmt { - enum { FORRANGE, LOOPVAR, COND, END }; + enum { FORRANGE, LOOPINDEX, COND, END }; Stmt* SubExprs[END]; public: - CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopVar, Expr *Cond); + CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopIndex, Expr *Cond); /// \brief Build an empty for range statement. explicit CilkForRangeStmt(EmptyShell Empty) : Stmt(CilkForRangeStmtClass, Empty) { } @@ -103,8 +103,8 @@ class CilkForRangeStmt : public Stmt { void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } - VarDecl *getLoopVariable() const; - void setLoopVariable(const ASTContext &C, VarDecl *V); + VarDecl *getLoopIndex() const; + void setLoopIndex(const ASTContext &C, VarDecl *V); SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index 2306736cbafb..416efe3a929f 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -128,29 +128,29 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) } CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, - VarDecl *LoopVar, Expr *Cond) + VarDecl *LoopIndex, Expr *Cond) : Stmt(CilkForRangeStmtClass) { SubExprs[FORRANGE] = ForRange; - setLoopVariable(C, LoopVar); + setLoopIndex(C, LoopIndex); SubExprs[COND] = Cond; } -VarDecl *CilkForRangeStmt::getLoopVariable() const { - if (!SubExprs[LOOPVAR]) +VarDecl *CilkForRangeStmt::getLoopIndex() const { + if (!SubExprs[LOOPINDEX]) return nullptr; - DeclStmt *DS = cast(SubExprs[LOOPVAR]); + DeclStmt *DS = cast(SubExprs[LOOPINDEX]); return cast(DS->getSingleDecl()); } -void CilkForRangeStmt::setLoopVariable(const ASTContext &C, VarDecl *V) { +void CilkForRangeStmt::setLoopIndex(const ASTContext &C, VarDecl *V) { if (!V) { - SubExprs[LOOPVAR] = nullptr; + SubExprs[LOOPINDEX] = nullptr; return; } SourceRange VarRange = V->getSourceRange(); - SubExprs[LOOPVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), + SubExprs[LOOPINDEX] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index fd16d295c23b..0ec8b0f23a89 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3499,10 +3499,33 @@ static void SearchForReturnInStmt(Sema &Self, Stmt *S) { // TODO: add comment StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { CilkForRangeStmt *CilkForRange = cast(S); + StmtResult ForRange = FinishCXXForRangeStmt(CilkForRange->getCXXForRangeStmt(), B); if (ForRange.isInvalid()) return StmtError(); CilkForRange->setForRange(ForRange.get()); + + CXXForRangeStmt *CXXForRange = cast(ForRange.get()); + + VarDecl *BeginVar = cast(CXXForRange->getBeginStmt()->getSingleDecl()); + QualType BeginType = BeginVar->getType(); + const QualType BeginRefNonRefType = BeginType.getNonReferenceType(); + ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, + VK_LValue, CXXForRange->getColonLoc()); + + VarDecl *LoopIndex = CilkForRange->getLoopIndex(); + QualType LoopIndexType = LoopIndex->getType(); + const QualType LoopIndexRefNonRefType = LoopIndexType.getNonReferenceType(); + ExprResult LoopIndexRef = BuildDeclRefExpr(BeginVar, LoopIndexRefNonRefType, + VK_LValue, CXXForRange->getColonLoc()); + + + VarDecl *LoopVar = CXXForRange->getLoopVariable(); + SourceLocation LoopVarLoc = LoopVar->getBeginLoc(); + ExprResult NewLoopVarInit = + ActOnBinOp(getCurScope(), LoopVarLoc, tok::plus, BeginRef.get(), LoopIndexRef.get()); + AddInitializerToDecl(LoopVar, NewLoopVarInit.get(), /*DirectInit=*/false); + return CilkForRange; } @@ -3549,22 +3572,22 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { // TODO: different loc??? SourceLocation RangeLoc = ForRange->getBeginLoc(); - VarDecl *LoopVar = BuildForRangeVarDecl(*this, RangeLoc, LoopBoundExpr.get()->getType(), std::string("__cilk_loopvar")); - AddInitializerToDecl(LoopVar, ActOnIntegerConstant(RangeLoc, 0).get(), + VarDecl *LoopIndex = BuildForRangeVarDecl(*this, RangeLoc, LoopBoundExpr.get()->getType(), std::string("__cilk_loopindex")); + AddInitializerToDecl(LoopIndex, ActOnIntegerConstant(RangeLoc, 0).get(), /*DirectInit=*/false); - FinalizeDeclaration(LoopVar); - CurContext->addHiddenDecl(LoopVar); + FinalizeDeclaration(LoopIndex); + CurContext->addHiddenDecl(LoopIndex); - ExprResult LoopVarRef = BuildDeclRefExpr(LoopVar, LoopVar->getType(), VK_LValue, + ExprResult LoopIndexRef = BuildDeclRefExpr(LoopIndex, LoopIndex->getType(), VK_LValue, RangeLoc); ExprResult Cond; - Cond = ActOnBinOp(S, RangeLoc, tok::exclaimequal, LoopVarRef.get(), + Cond = ActOnBinOp(S, RangeLoc, tok::exclaimequal, LoopIndexRef.get(), LoopBoundExpr.get()); if (Cond.isInvalid()) return StmtError(); - return new (Context) CilkForRangeStmt(Context, ForRange, LoopVar, Cond.get()); + return new (Context) CilkForRangeStmt(Context, ForRange, LoopIndexRef, Cond.get()); } From fb7b08c9550ff32040f63fd0f62e27e8fe74f380 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Mon, 15 Mar 2021 23:40:02 -0400 Subject: [PATCH 25/64] should work 2 --- clang/include/clang/AST/StmtCilk.h | 4 ++-- clang/lib/AST/StmtCXX.cpp | 3 ++- clang/lib/Sema/SemaStmt.cpp | 8 +++++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index b1583b89bb90..b0b56b397498 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -86,11 +86,11 @@ class CilkSyncStmt : public Stmt { }; class CilkForRangeStmt : public Stmt { - enum { FORRANGE, LOOPINDEX, COND, END }; + enum { FORRANGE, LOOPINDEX, COND, INC, END }; Stmt* SubExprs[END]; public: - CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopIndex, Expr *Cond); + CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopIndex, Expr *Cond, Expr *Inc); /// \brief Build an empty for range statement. explicit CilkForRangeStmt(EmptyShell Empty) : Stmt(CilkForRangeStmtClass, Empty) { } diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index 416efe3a929f..cea19153a93f 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -128,12 +128,13 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) } CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, - VarDecl *LoopIndex, Expr *Cond) + VarDecl *LoopIndex, Expr *Cond, Expr *Inc) : Stmt(CilkForRangeStmtClass) { SubExprs[FORRANGE] = ForRange; setLoopIndex(C, LoopIndex); SubExprs[COND] = Cond; + SubExprs[INC] = Inc; } VarDecl *CilkForRangeStmt::getLoopIndex() const { if (!SubExprs[LOOPINDEX]) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 0ec8b0f23a89..575bae3be187 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3586,8 +3586,14 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { if (Cond.isInvalid()) return StmtError(); + // Create a new increment operation on the new beginning variable, and add it + // to the existing increment operation. + SourceLocation IncLoc = RangeLoc; + ExprResult NewInc = ActOnUnaryOp(S, IncLoc, tok::plusplus, LoopIndexRef.get()); + if (NewInc.isInvalid()) + return StmtError(); - return new (Context) CilkForRangeStmt(Context, ForRange, LoopIndexRef, Cond.get()); + return new (Context) CilkForRangeStmt(Context, ForRange, LoopIndex, Cond.get(), NewInc.get()); } From b95bd6ef739d05d04ee0ea08bf24bec41d79806a Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 16 Mar 2021 22:03:58 -0400 Subject: [PATCH 26/64] dereference --- clang/lib/Sema/SemaStmt.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 575bae3be187..2230c261e335 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3524,7 +3524,15 @@ StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { SourceLocation LoopVarLoc = LoopVar->getBeginLoc(); ExprResult NewLoopVarInit = ActOnBinOp(getCurScope(), LoopVarLoc, tok::plus, BeginRef.get(), LoopIndexRef.get()); - AddInitializerToDecl(LoopVar, NewLoopVarInit.get(), /*DirectInit=*/false); + + ExprResult DerefExpr = ActOnUnaryOp(S, LoopVarLoc, tok::star, NewLoopVarInit.get()); + if (DerefExpr.isInvalid()) { + Diag(LoopVarLoc, diag::note_for_range_invalid_iterator) + << LoopVarLoc << 1 << NewLoopVarInit.get()->getType(); + return StmtError(); + } + + AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false); return CilkForRange; } From 12f98d225b2ea8df5426126724acddbaf619afc2 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 16 Mar 2021 22:07:01 -0400 Subject: [PATCH 27/64] fix things --- clang/lib/Sema/SemaStmt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 2230c261e335..9b840f0c5dd6 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3525,7 +3525,7 @@ StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { ExprResult NewLoopVarInit = ActOnBinOp(getCurScope(), LoopVarLoc, tok::plus, BeginRef.get(), LoopIndexRef.get()); - ExprResult DerefExpr = ActOnUnaryOp(S, LoopVarLoc, tok::star, NewLoopVarInit.get()); + ExprResult DerefExpr = ActOnUnaryOp(getCurScope(), LoopVarLoc, tok::star, NewLoopVarInit.get()); if (DerefExpr.isInvalid()) { Diag(LoopVarLoc, diag::note_for_range_invalid_iterator) << LoopVarLoc << 1 << NewLoopVarInit.get()->getType(); From 073cdb301c6a75c3ca5c3b11e48adf68bf713e7d Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 16 Mar 2021 22:20:18 -0400 Subject: [PATCH 28/64] test --- clang/include/clang/AST/StmtCilk.h | 3 +++ clang/lib/CodeGen/CGCilk.cpp | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index b0b56b397498..081be4b9b150 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -106,6 +106,9 @@ class CilkForRangeStmt : public Stmt { VarDecl *getLoopIndex() const; void setLoopIndex(const ASTContext &C, VarDecl *V); + Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } + Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } + SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index 750992ed7656..77ce61bc53c6 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -912,8 +912,11 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // Get the value of the loop variable initialization before we emit the // detach. - if (LoopVar) + if (LoopVar) { + LoopVar->dump(); + LoopVar->dumpColor(); LoopVarInitRV = EmitAnyExprToTemp(LoopVar->getInit()); + } Detach = Builder.CreateDetach(ForBodyEntry, Continue.getBlock(), SyncRegion); From ee4419c52bb272b249b4a9285d217ce1e71dfef6 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 16 Mar 2021 22:31:15 -0400 Subject: [PATCH 29/64] test --- clang/lib/Sema/SemaStmt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 9b840f0c5dd6..547ae143cc03 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3516,7 +3516,7 @@ StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { VarDecl *LoopIndex = CilkForRange->getLoopIndex(); QualType LoopIndexType = LoopIndex->getType(); const QualType LoopIndexRefNonRefType = LoopIndexType.getNonReferenceType(); - ExprResult LoopIndexRef = BuildDeclRefExpr(BeginVar, LoopIndexRefNonRefType, + ExprResult LoopIndexRef = BuildDeclRefExpr(LoopIndex, LoopIndexRefNonRefType, VK_LValue, CXXForRange->getColonLoc()); From 9d3b9dda6f864b889af6d47db11f3d8056658abc Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 16 Mar 2021 22:51:00 -0400 Subject: [PATCH 30/64] test --- clang/include/clang/AST/StmtCilk.h | 7 +++++-- clang/lib/AST/StmtCXX.cpp | 3 ++- clang/lib/CodeGen/CGCilk.cpp | 1 + clang/lib/Sema/SemaStmt.cpp | 8 +++++++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 081be4b9b150..6d33ce52c093 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -86,11 +86,11 @@ class CilkSyncStmt : public Stmt { }; class CilkForRangeStmt : public Stmt { - enum { FORRANGE, LOOPINDEX, COND, INC, END }; + enum { FORRANGE, LOOPINDEX, LOOPINDEXSTMT, COND, INC, END }; Stmt* SubExprs[END]; public: - CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopIndex, Expr *Cond, Expr *Inc); + CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopIndex, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt); /// \brief Build an empty for range statement. explicit CilkForRangeStmt(EmptyShell Empty) : Stmt(CilkForRangeStmtClass, Empty) { } @@ -103,6 +103,9 @@ class CilkForRangeStmt : public Stmt { void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } + DeclStmt *getLoopIndexStmt() { + return cast_or_null(SubExprs[LOOPINDEXSTMT]); + } VarDecl *getLoopIndex() const; void setLoopIndex(const ASTContext &C, VarDecl *V); diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index cea19153a93f..d314b3f0a6a8 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -128,13 +128,14 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) } CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, - VarDecl *LoopIndex, Expr *Cond, Expr *Inc) + VarDecl *LoopIndex, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt) : Stmt(CilkForRangeStmtClass) { SubExprs[FORRANGE] = ForRange; setLoopIndex(C, LoopIndex); SubExprs[COND] = Cond; SubExprs[INC] = Inc; + SubExprs[LOOPINDEXSTMT] = LoopIndexStmt; } VarDecl *CilkForRangeStmt::getLoopIndex() const { if (!SubExprs[LOOPINDEX]) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index 77ce61bc53c6..f8aab6c9393d 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -847,6 +847,7 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, EmitStmt(ForRange.getRangeStmt()); EmitStmt(ForRange.getBeginStmt()); EmitStmt(ForRange.getEndStmt()); + EmitStmt(S.getLoopIndexStmt()); // Start the loop with a block that tests the condition. If there's an // increment, the continue scope will be overwritten later. diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 547ae143cc03..ff48bf4a06b7 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3586,6 +3586,12 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { FinalizeDeclaration(LoopIndex); CurContext->addHiddenDecl(LoopIndex); + DeclGroupPtrTy LoopIndexGroup = + BuildDeclaratorGroup(MutableArrayRef((Decl **)&LoopIndex, 1)); + StmtResult LoopIndexStmt = ActOnDeclStmt(LoopIndexGroup, RangeLoc, RangeLoc); + if (LoopIndexStmt.isInvalid()) + return StmtError(); + ExprResult LoopIndexRef = BuildDeclRefExpr(LoopIndex, LoopIndex->getType(), VK_LValue, RangeLoc); ExprResult Cond; @@ -3601,7 +3607,7 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { if (NewInc.isInvalid()) return StmtError(); - return new (Context) CilkForRangeStmt(Context, ForRange, LoopIndex, Cond.get(), NewInc.get()); + return new (Context) CilkForRangeStmt(Context, ForRange, LoopIndexStmt.get(), Cond.get(), NewInc.get(), cast(LoopIndexStmt.get())); } From d8ce9ea0ab62281bc10168cab4cd46b5594ad484 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 16 Mar 2021 22:56:59 -0400 Subject: [PATCH 31/64] test --- clang/include/clang/AST/StmtCilk.h | 4 ++++ clang/lib/Sema/SemaStmt.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 6d33ce52c093..b8d5198e91c2 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -112,6 +112,10 @@ class CilkForRangeStmt : public Stmt { Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } + const DeclStmt *getLoopIndexStmt() const { + return cast_or_null(SubExprs[LOOPINDEXSTMT]); + } + SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index ff48bf4a06b7..7ac3b4711e73 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3607,7 +3607,7 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { if (NewInc.isInvalid()) return StmtError(); - return new (Context) CilkForRangeStmt(Context, ForRange, LoopIndexStmt.get(), Cond.get(), NewInc.get(), cast(LoopIndexStmt.get())); + return new (Context) CilkForRangeStmt(Context, ForRange, LoopIndex, Cond.get(), NewInc.get(), cast(LoopIndexStmt.get())); } From 5b04bbd5f9e060b5ef6d94a6e62353f05e6350e2 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 16 Mar 2021 23:12:36 -0400 Subject: [PATCH 32/64] test --- clang/include/clang/AST/StmtCilk.h | 2 ++ clang/lib/CodeGen/CGCilk.cpp | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index b8d5198e91c2..56464db6c339 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -112,6 +112,8 @@ class CilkForRangeStmt : public Stmt { Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } + const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} + const Expr *getInc() const { return reinterpret_cast(SubExprs[INC]); } const DeclStmt *getLoopIndexStmt() const { return cast_or_null(SubExprs[LOOPINDEXSTMT]); } diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index f8aab6c9393d..b74144638a5b 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -861,7 +861,7 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, SourceLocToDebugLoc(R.getBegin()), SourceLocToDebugLoc(R.getEnd())); - const Expr *Inc = ForRange.getInc(); + const Expr *Inc = S.getInc(); assert(Inc && "_Cilk_for range loop has no increment"); Continue = getJumpDestInCurrentScope("pfor.inc"); @@ -1077,10 +1077,10 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // C99 6.8.5p2/p4: The first substatement is executed if the expression // compares unequal to 0. The condition must be a scalar type. - llvm::Value *BoolCondVal = EvaluateExprAsBool(ForRange.getCond()); + llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); Builder.CreateCondBr( BoolCondVal, CondBlock, ExitBlock, - createProfileWeightsForLoop(ForRange.getCond(), getProfileCount(ForRange.getBody()))); + createProfileWeightsForLoop(S.getCond(), getProfileCount(ForRange.getBody()))); if (ExitBlock != LoopExit.getBlock()) { EmitBlock(ExitBlock); From e4100bdabcc1f20b3891962c21a177b71aa2c214 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 16 Mar 2021 23:17:27 -0400 Subject: [PATCH 33/64] remove dumps --- clang/lib/CodeGen/CGCilk.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index b74144638a5b..64da25aed4da 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -914,8 +914,6 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // Get the value of the loop variable initialization before we emit the // detach. if (LoopVar) { - LoopVar->dump(); - LoopVar->dumpColor(); LoopVarInitRV = EmitAnyExprToTemp(LoopVar->getInit()); } From c676f92f74c46be6d719036be9c87bcfa67ebed0 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Mon, 22 Mar 2021 20:56:24 -0400 Subject: [PATCH 34/64] potentially fix o1 --- clang/include/clang/AST/StmtCilk.h | 10 ++++++++-- clang/lib/AST/StmtCXX.cpp | 3 ++- clang/lib/CodeGen/CGCilk.cpp | 1 + clang/lib/Sema/SemaStmt.cpp | 28 ++++++++++++++++++++-------- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 56464db6c339..03b0502f6b3e 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -86,11 +86,11 @@ class CilkSyncStmt : public Stmt { }; class CilkForRangeStmt : public Stmt { - enum { FORRANGE, LOOPINDEX, LOOPINDEXSTMT, COND, INC, END }; + enum { FORRANGE, LOOPINDEX, LOOPINDEXSTMT, LIMIT, COND, INC, END }; Stmt* SubExprs[END]; public: - CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopIndex, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt); + CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopIndex, DeclStmt *Limit, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt); /// \brief Build an empty for range statement. explicit CilkForRangeStmt(EmptyShell Empty) : Stmt(CilkForRangeStmtClass, Empty) { } @@ -111,12 +111,18 @@ class CilkForRangeStmt : public Stmt { Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } + DeclStmt *getLimitStmt() { + return cast_or_null(SubExprs[LIMIT]); + } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} const Expr *getInc() const { return reinterpret_cast(SubExprs[INC]); } const DeclStmt *getLoopIndexStmt() const { return cast_or_null(SubExprs[LOOPINDEXSTMT]); } + const DeclStmt *getLimitStmt() const { + return cast_or_null(SubExprs[LIMIT]); + } SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index d314b3f0a6a8..0137f6ef53e8 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -128,7 +128,7 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) } CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, - VarDecl *LoopIndex, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt) + VarDecl *LoopIndex, DeclStmt *Limit, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt) : Stmt(CilkForRangeStmtClass) { SubExprs[FORRANGE] = ForRange; @@ -136,6 +136,7 @@ CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRang SubExprs[COND] = Cond; SubExprs[INC] = Inc; SubExprs[LOOPINDEXSTMT] = LoopIndexStmt; + SubExprs[LIMIT] = Limit; } VarDecl *CilkForRangeStmt::getLoopIndex() const { if (!SubExprs[LOOPINDEX]) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index 64da25aed4da..5b288fcc7671 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -848,6 +848,7 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, EmitStmt(ForRange.getBeginStmt()); EmitStmt(ForRange.getEndStmt()); EmitStmt(S.getLoopIndexStmt()); + EmitStmt(S.getLimitStmt()); // Start the loop with a block that tests the condition. If there's an // increment, the continue scope will be overwritten later. diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 7ac3b4711e73..c3c2b92ec0b2 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3571,16 +3571,26 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { const QualType EndRefNonRefType = EndType.getNonReferenceType(); ExprResult EndRef = BuildDeclRefExpr(EndVar, EndRefNonRefType, VK_LValue, ForRange->getColonLoc()); - ExprResult LoopBoundExpr = ActOnBinOp(S, ForRange->getColonLoc(), tok::minus, EndRef.get(), BeginRef.get()); - if (LoopBoundExpr.isInvalid()) { + ExprResult LimitExpr = ActOnBinOp(S, ForRange->getColonLoc(), tok::minus, EndRef.get(), BeginRef.get()); + if (LimitExpr.isInvalid()) { // give warning about for range only supporting random access! Diag(ForRange->getForLoc(), diag::err_cilk_for_range_end_minus_begin); return StmtError(); } - -// TODO: different loc??? SourceLocation RangeLoc = ForRange->getBeginLoc(); - VarDecl *LoopIndex = BuildForRangeVarDecl(*this, RangeLoc, LoopBoundExpr.get()->getType(), std::string("__cilk_loopindex")); + VarDecl *Limit = BuildForRangeVarDecl(*this, RangeLoc, LimitExpr.get()->getType(), std::string("__cilk_looplimit")); + AddInitializerToDecl(Limit, LimitExpr.get(), + /*DirectInit=*/false); + FinalizeDeclaration(Limit); + CurContext->addHiddenDecl(Limit); + + DeclGroupPtrTy LimitGroup = + BuildDeclaratorGroup(MutableArrayRef((Decl **)&Limit, 1)); + StmtResult LimitStmt = ActOnDeclStmt(LimitGroup, RangeLoc, RangeLoc); + if (LimitStmt.isInvalid()) + return StmtError(); + + VarDecl *LoopIndex = BuildForRangeVarDecl(*this, RangeLoc, LimitExpr.get()->getType(), std::string("__cilk_loopindex")); AddInitializerToDecl(LoopIndex, ActOnIntegerConstant(RangeLoc, 0).get(), /*DirectInit=*/false); FinalizeDeclaration(LoopIndex); @@ -3592,11 +3602,13 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { if (LoopIndexStmt.isInvalid()) return StmtError(); - ExprResult LoopIndexRef = BuildDeclRefExpr(LoopIndex, LoopIndex->getType(), VK_LValue, + ExprResult LimitRef = BuildDeclRefExpr(Limit, Limit->getType(), VK_LValue, RangeLoc); + ExprResult LoopIndexRef = BuildDeclRefExpr(LoopIndex, LoopIndex->getType(), VK_LValue, + RangeLoc); ExprResult Cond; Cond = ActOnBinOp(S, RangeLoc, tok::exclaimequal, LoopIndexRef.get(), - LoopBoundExpr.get()); + LimitRef.get()); if (Cond.isInvalid()) return StmtError(); @@ -3607,7 +3619,7 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { if (NewInc.isInvalid()) return StmtError(); - return new (Context) CilkForRangeStmt(Context, ForRange, LoopIndex, Cond.get(), NewInc.get(), cast(LoopIndexStmt.get())); + return new (Context) CilkForRangeStmt(Context, ForRange, LoopIndex, cast(LimitStmt.get()), Cond.get(), NewInc.get(), cast(LoopIndexStmt.get())); } From b08119d5688d252c2100cf346d604b9467cabc13 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Mon, 22 Mar 2021 20:59:25 -0400 Subject: [PATCH 35/64] fix non random access bug hopefully --- clang/lib/Sema/SemaStmt.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index c3c2b92ec0b2..f16e780ba2ea 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3498,6 +3498,9 @@ static void SearchForReturnInStmt(Sema &Self, Stmt *S) { // TODO: add comment StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { + if (!S || !B) + return StmtError(); + CilkForRangeStmt *CilkForRange = cast(S); StmtResult ForRange = FinishCXXForRangeStmt(CilkForRange->getCXXForRangeStmt(), B); From 75889f6341ddebb09ebca0b3753b44b7500d677b Mon Sep 17 00:00:00 2001 From: Sualeh Asif Date: Thu, 25 Mar 2021 07:37:38 -0400 Subject: [PATCH 36/64] reformatted StmtCilk.h' --- clang/include/clang/AST/StmtCilk.h | 37 ++++++++++++++++++------------ 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 03b0502f6b3e..ca6352f4b9ae 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -85,21 +85,31 @@ class CilkSyncStmt : public Stmt { } }; +/// CilkForRangeStmt - This represents a '_Cilk_for(range-declarator : +/// range-expression)' or 'for (init-statement range-declarator : +/// range-expression)'.) based on a CXXForRangeStmt which is a C++0x +/// [stmt.ranged]'s ranged for stmt +/// +/// This is stored as a FORRANGE stmt embedded inside a CILKFORRANGE with some +/// other necessary semantic compenents. class CilkForRangeStmt : public Stmt { enum { FORRANGE, LOOPINDEX, LOOPINDEXSTMT, LIMIT, COND, INC, END }; - Stmt* SubExprs[END]; + Stmt *SubExprs[END]; public: - CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, VarDecl *LoopIndex, DeclStmt *Limit, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt); + CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, + VarDecl *LoopIndex, DeclStmt *Limit, Expr *Cond, Expr *Inc, + DeclStmt *LoopIndexStmt); /// \brief Build an empty for range statement. - explicit CilkForRangeStmt(EmptyShell Empty) : Stmt(CilkForRangeStmtClass, Empty) { } + explicit CilkForRangeStmt(EmptyShell Empty) + : Stmt(CilkForRangeStmtClass, Empty) {} static bool classof(const Stmt *T) { return T->getStmtClass() == CilkForRangeStmtClass; } - CXXForRangeStmt* getCXXForRangeStmt() const; + CXXForRangeStmt *getCXXForRangeStmt() const; void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } @@ -109,14 +119,14 @@ class CilkForRangeStmt : public Stmt { VarDecl *getLoopIndex() const; void setLoopIndex(const ASTContext &C, VarDecl *V); - Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } - Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } - DeclStmt *getLimitStmt() { - return cast_or_null(SubExprs[LIMIT]); - } + Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } + Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } + DeclStmt *getLimitStmt() { return cast_or_null(SubExprs[LIMIT]); } - const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} - const Expr *getInc() const { return reinterpret_cast(SubExprs[INC]); } + const Expr *getCond() const { + return reinterpret_cast(SubExprs[COND]); + } + const Expr *getInc() const { return reinterpret_cast(SubExprs[INC]); } const DeclStmt *getLoopIndexStmt() const { return cast_or_null(SubExprs[LOOPINDEXSTMT]); } @@ -128,10 +138,7 @@ class CilkForRangeStmt : public Stmt { SourceLocation getEndLoc() const LLVM_READONLY; // Iterators - child_range children() { - return child_range(&SubExprs[0], &SubExprs[END]); - } - + child_range children() { return child_range(&SubExprs[0], &SubExprs[END]); } }; /// CilkForStmt - This represents a '_Cilk_for(init;cond;inc)' stmt. From 9c73d9614b5336e493e4e617172937eecaf0c287 Mon Sep 17 00:00:00 2001 From: Sualeh Asif Date: Thu, 25 Mar 2021 10:39:34 -0400 Subject: [PATCH 37/64] reformatted and refactored StmtCXX --- clang/lib/AST/StmtCXX.cpp | 27 +++++++++++++++++++-------- clang/lib/AST/StmtPrinter.cpp | 8 ++++++-- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index 0137f6ef53e8..c66d08604a99 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -127,10 +127,13 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) const_cast(getParamMoves().data())); } -CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, - VarDecl *LoopIndex, DeclStmt *Limit, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt) - : Stmt(CilkForRangeStmtClass) -{ +/// Constructor for the CilkForRangeStmt +CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, + CXXForRangeStmt *ForRange, + VarDecl *LoopIndex, DeclStmt *Limit, + Expr *Cond, Expr *Inc, + DeclStmt *LoopIndexStmt) + : Stmt(CilkForRangeStmtClass) { SubExprs[FORRANGE] = ForRange; setLoopIndex(C, LoopIndex); SubExprs[COND] = Cond; @@ -138,6 +141,9 @@ CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRang SubExprs[LOOPINDEXSTMT] = LoopIndexStmt; SubExprs[LIMIT] = Limit; } + +/// Gets the LOOPINDEX as a VarDecl. +/// LOOPINDEX is stored as a DeclStmt for the purpose of clean manipulation. VarDecl *CilkForRangeStmt::getLoopIndex() const { if (!SubExprs[LOOPINDEX]) return nullptr; @@ -153,14 +159,19 @@ void CilkForRangeStmt::setLoopIndex(const ASTContext &C, VarDecl *V) { } SourceRange VarRange = V->getSourceRange(); - SubExprs[LOOPINDEX] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), - VarRange.getEnd()); + SubExprs[LOOPINDEX] = + new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); } -CXXForRangeStmt* CilkForRangeStmt::getCXXForRangeStmt() const { +/// returns the FORRANGE stmt embedded in the CilkForRange. (May be null.) +CXXForRangeStmt *CilkForRangeStmt::getCXXForRangeStmt() const { return cast_or_null(SubExprs[FORRANGE]); } -SourceLocation CilkForRangeStmt::getBeginLoc() const { return getCXXForRangeStmt()->getBeginLoc(); } + +SourceLocation CilkForRangeStmt::getBeginLoc() const { + return getCXXForRangeStmt()->getBeginLoc(); +} + SourceLocation CilkForRangeStmt::getEndLoc() const { return getCXXForRangeStmt()->getEndLoc(); } diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index dea7759be134..5542181ad65b 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -2564,16 +2564,20 @@ void StmtPrinter::VisitCilkForStmt(CilkForStmt *Node) { void StmtPrinter::VisitCilkForRangeStmt(CilkForRangeStmt *Node) { Indent() << "_Cilk_for ("; + if (Node->getCXXForRangeStmt()->getInit()) PrintInitStmt(Node->getCXXForRangeStmt()->getInit(), 5); + PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressInitializers = true; - Node->getCXXForRangeStmt()->getLoopVariable()->print(OS, SubPolicy, IndentLevel); + Node->getCXXForRangeStmt()->getLoopVariable()->print(OS, SubPolicy, + IndentLevel); + OS << " : "; PrintExpr(Node->getCXXForRangeStmt()->getRangeInit()); OS << ")"; - PrintControlledStmt(Node->getCXXForRangeStmt()->getBody()); + PrintControlledStmt(Node->getCXXForRangeStmt()->getBody()); } //===----------------------------------------------------------------------===// From 623e81b80b83179982cfba91b6c644956c128e67 Mon Sep 17 00:00:00 2001 From: Sualeh Asif Date: Thu, 25 Mar 2021 11:06:43 -0400 Subject: [PATCH 38/64] cleaned up codegen for cilkforrange --- clang/lib/CodeGen/CGCilk.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index 5b288fcc7671..c708f6a1d7f0 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -818,10 +818,12 @@ void CodeGenFunction::EmitCilkForStmt(const CilkForStmt &S, delete TempInvokeDest; } -void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, - ArrayRef ForAttrs) { +void +CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, + ArrayRef ForAttrs) { JumpDest LoopExit = getJumpDestInCurrentScope("pfor.end"); + // Setup the sync region PushSyncRegion(); llvm::Instruction *SyncRegion = EmitSyncRegionStart(); CurSyncRegion->setSyncRegionStart(SyncRegion); @@ -830,6 +832,7 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, LexicalScope ForScope(*this, S.getSourceRange()); + // Get the ForRange stmt which has all the important semantics. const CXXForRangeStmt &ForRange = *S.getCXXForRangeStmt(); // Evaluate the first part before the loop. @@ -838,10 +841,9 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); - // TODO: emit difference variable instead of beginstmt and endstmt - // plan: - // 1. add difference variable and emit it, check - // 2. make loop condition depend on the difference variable instead, check + // We will now emit a difference variable instead of beginstmt and endstmt + // 1. add difference variable and emit it + // 2. make loop condition depend on the difference variable instead // 3. finally, don't mutate beginstmt and instead do begin=begin+inductionvar EmitStmt(ForRange.getRangeStmt()); @@ -918,8 +920,8 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, LoopVarInitRV = EmitAnyExprToTemp(LoopVar->getInit()); } - Detach = Builder.CreateDetach(ForBodyEntry, Continue.getBlock(), - SyncRegion); + Detach = + Builder.CreateDetach(ForBodyEntry, Continue.getBlock(), SyncRegion); // Save the old alloca insert point. OldAllocaInsertPt = AllocaInsertPt; // Save the old EH state. @@ -1040,9 +1042,8 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, if (!NestedEHResumeBlock->use_empty()) { // Translate the nested EHResumeBlock into an appropriate EHResumeBlock in // the outer scope. - NestedEHResumeBlock->replaceAllUsesWith( - getEHResumeBlock( - isa(NestedEHResumeBlock->getTerminator()))); + NestedEHResumeBlock->replaceAllUsesWith(getEHResumeBlock( + isa(NestedEHResumeBlock->getTerminator()))); } delete NestedEHResumeBlock; } @@ -1059,8 +1060,7 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, Builder.SetInsertPoint(DetachBlock); // Create the new detach instruction. llvm::DetachInst *NewDetach = Builder.CreateDetach( - ForBodyEntry, Continue.getBlock(), InvokeDest, - SyncRegion); + ForBodyEntry, Continue.getBlock(), InvokeDest, SyncRegion); // Remove the old detach. Detach->eraseFromParent(); Detach = NewDetach; @@ -1077,9 +1077,9 @@ void CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // C99 6.8.5p2/p4: The first substatement is executed if the expression // compares unequal to 0. The condition must be a scalar type. llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); - Builder.CreateCondBr( - BoolCondVal, CondBlock, ExitBlock, - createProfileWeightsForLoop(S.getCond(), getProfileCount(ForRange.getBody()))); + Builder.CreateCondBr(BoolCondVal, CondBlock, ExitBlock, + createProfileWeightsForLoop( + S.getCond(), getProfileCount(ForRange.getBody()))); if (ExitBlock != LoopExit.getBlock()) { EmitBlock(ExitBlock); From 8fc1d9cc3679745e3f588bc9365ca38637a8365b Mon Sep 17 00:00:00 2001 From: Sualeh Asif Date: Thu, 25 Mar 2021 11:20:38 -0400 Subject: [PATCH 39/64] reformatted partsing --- clang/lib/Parse/ParseCilk.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/clang/lib/Parse/ParseCilk.cpp b/clang/lib/Parse/ParseCilk.cpp index 3744d27ffc6e..4d868ce344f8 100644 --- a/clang/lib/Parse/ParseCilk.cpp +++ b/clang/lib/Parse/ParseCilk.cpp @@ -57,6 +57,10 @@ StmtResult Parser::ParseCilkSpawnStatement() { /// cilk_for-statement: /// '_Cilk_for' '(' expr ';' expr ';' expr ')' statement /// '_Cilk_for' '(' declaration expr ';' expr ';' expr ')' statement +/// [C++0x] '_Cilk_for' +/// '(' for-range-declaration ':' for-range-initializer ')' +/// statement + StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { assert(Tok.is(tok::kw__Cilk_for) && "Not a _Cilk_for stmt!"); SourceLocation ForLoc = ConsumeToken(); // eat the '_Cilk_for'. @@ -253,8 +257,8 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc() : ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus2a - ? diag::warn_cxx17_compat_for_range_init_stmt - : diag::ext_for_range_init_stmt) + ? diag::warn_cxx17_compat_for_range_init_stmt + : diag::ext_for_range_init_stmt) << (FirstPart.get() ? FirstPart.get()->getSourceRange() : SourceRange()); if (EmptyInitStmtSemiLoc.isValid()) { @@ -309,25 +313,25 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { // } // // We need to perform most of the semantic analysis for a C++0x for-range - // // statememt before parsing the body, in order to be able to deduce the type + // // statememt before parsing the body, in order to be able to deduce the + // type // // of an auto-typed loop variable. - StmtResult ForRangeStmt; + StmtResult ForRangeStmt; // StmtResult ForEachStmt; // TODO: Extend _Cilk_for to support these. if (ForRangeInfo.ParsedForRangeDecl()) { Diag(ForLoc, diag::warn_cilk_for_forrange_loop_experimental); - ExprResult CorrectedRange = - Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get()); + ExprResult CorrectedRange = + Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get()); // TODO(arvid): uncomment this - ForRangeStmt = Actions.ActOnCilkForRangeStmt( - getCurScope(), ForLoc, FirstPart.get(), - ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(), - T.getCloseLocation(), Sema::BFRK_Build); - + ForRangeStmt = Actions.ActOnCilkForRangeStmt( + getCurScope(), ForLoc, FirstPart.get(), ForRangeInfo.LoopVar.get(), + ForRangeInfo.ColonLoc, CorrectedRange.get(), T.getCloseLocation(), + Sema::BFRK_Build); - // Similarly, we need to do the semantic analysis for a for-range - // statement immediately in order to close over temporaries correctly. + // Similarly, we need to do the semantic analysis for a for-range + // statement immediately in order to close over temporaries correctly. } else if (ForEach) { Diag(ForLoc, diag::err_cilk_for_foreach_loop_not_supported); // ForEachStmt = Actions.ActOnObjCForCollectionStmt(ForLoc, From 04f717c159e30c5fe90d50ef5382d923d3dce976 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 21:34:56 -0400 Subject: [PATCH 40/64] cargo-cult some more --- clang/lib/Parse/ParseCilk.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/clang/lib/Parse/ParseCilk.cpp b/clang/lib/Parse/ParseCilk.cpp index 4d868ce344f8..31122e3f3900 100644 --- a/clang/lib/Parse/ParseCilk.cpp +++ b/clang/lib/Parse/ParseCilk.cpp @@ -60,6 +60,12 @@ StmtResult Parser::ParseCilkSpawnStatement() { /// [C++0x] '_Cilk_for' /// '(' for-range-declaration ':' for-range-initializer ')' /// statement +/// +/// [C++0x] for-range-declaration: +/// [C++0x] attribute-specifier-seq[opt] type-specifier-seq declarator +/// [C++0x] for-range-initializer: +/// [C++0x] expression +/// [C++0x] braced-init-list StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { assert(Tok.is(tok::kw__Cilk_for) && "Not a _Cilk_for stmt!"); From acb7069e325c52c24df7698b4ce9ede615cbc640 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 21:37:36 -0400 Subject: [PATCH 41/64] remove comments --- clang/lib/Parse/ParseCilk.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/clang/lib/Parse/ParseCilk.cpp b/clang/lib/Parse/ParseCilk.cpp index 31122e3f3900..755e37a4f4e3 100644 --- a/clang/lib/Parse/ParseCilk.cpp +++ b/clang/lib/Parse/ParseCilk.cpp @@ -318,19 +318,16 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { // CoawaitLoc = SourceLocation(); // } - // // We need to perform most of the semantic analysis for a C++0x for-range - // // statememt before parsing the body, in order to be able to deduce the - // type - // // of an auto-typed loop variable. + // We need to perform most of the semantic analysis for a C++0x for-range + // statement before parsing the body, in order to be able to deduce the type + // of an auto-typed loop variable. StmtResult ForRangeStmt; // StmtResult ForEachStmt; - // TODO: Extend _Cilk_for to support these. if (ForRangeInfo.ParsedForRangeDecl()) { Diag(ForLoc, diag::warn_cilk_for_forrange_loop_experimental); ExprResult CorrectedRange = Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get()); - // TODO(arvid): uncomment this ForRangeStmt = Actions.ActOnCilkForRangeStmt( getCurScope(), ForLoc, FirstPart.get(), ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(), T.getCloseLocation(), From d2c17a6e46e448d768ca6ffee5047f1458597428 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 21:39:36 -0400 Subject: [PATCH 42/64] more consistency --- clang/include/clang/AST/StmtCilk.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index ca6352f4b9ae..6b6351fd387e 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -86,12 +86,12 @@ class CilkSyncStmt : public Stmt { }; /// CilkForRangeStmt - This represents a '_Cilk_for(range-declarator : -/// range-expression)' or 'for (init-statement range-declarator : -/// range-expression)'.) based on a CXXForRangeStmt which is a C++0x +/// range-expression)' or a '_Cilk_for (init-statement range-declarator : +/// range-expression)', based on a CXXForRangeStmt which is a C++0x /// [stmt.ranged]'s ranged for stmt /// /// This is stored as a FORRANGE stmt embedded inside a CILKFORRANGE with some -/// other necessary semantic compenents. +/// other necessary semantic components. class CilkForRangeStmt : public Stmt { enum { FORRANGE, LOOPINDEX, LOOPINDEXSTMT, LIMIT, COND, INC, END }; Stmt *SubExprs[END]; From 1c210246c8574abdd27dadc09d7d6cf8b23c8e6a Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 21:58:41 -0400 Subject: [PATCH 43/64] dont make any lasting changes to gitignore --- .gitignore | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitignore b/.gitignore index bd6eb1dd27b5..dfeba61ddba1 100644 --- a/.gitignore +++ b/.gitignore @@ -54,7 +54,3 @@ autoconf/autom4te.cache .vs # clangd index .clangd - - -cheetah/* - From b565060e06008a163bbb779f7ce8da4abff33076 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 22:02:18 -0400 Subject: [PATCH 44/64] remove submodules --- cheetah | 1 - cilktools | 1 - 2 files changed, 2 deletions(-) delete mode 160000 cheetah delete mode 160000 cilktools diff --git a/cheetah b/cheetah deleted file mode 160000 index 28b3801ee37e..000000000000 --- a/cheetah +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 28b3801ee37e0f9340b782a9ada455c74fe9524b diff --git a/cilktools b/cilktools deleted file mode 160000 index 185ad32ea06d..000000000000 --- a/cilktools +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 185ad32ea06dc842dd6dc4c0d1e6e71ea659269f From 455009f84ace248d2fa4140650597753a912d1da Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 22:09:57 -0400 Subject: [PATCH 45/64] whitespaces --- clang/include/clang/AST/StmtCilk.h | 8 ++++---- clang/include/clang/Basic/DiagnosticSemaKinds.td | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 6b6351fd387e..df9b51795fef 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -101,7 +101,7 @@ class CilkForRangeStmt : public Stmt { VarDecl *LoopIndex, DeclStmt *Limit, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt); - /// \brief Build an empty for range statement. + /// \brief Build an empty cilk for range statement. explicit CilkForRangeStmt(EmptyShell Empty) : Stmt(CilkForRangeStmtClass, Empty) {} @@ -113,14 +113,14 @@ class CilkForRangeStmt : public Stmt { void setForRange(Stmt *S) { SubExprs[FORRANGE] = S; } - DeclStmt *getLoopIndexStmt() { - return cast_or_null(SubExprs[LOOPINDEXSTMT]); - } VarDecl *getLoopIndex() const; void setLoopIndex(const ASTContext &C, VarDecl *V); Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } + DeclStmt *getLoopIndexStmt() { + return cast_or_null(SubExprs[LOOPINDEXSTMT]); + } DeclStmt *getLimitStmt() { return cast_or_null(SubExprs[LIMIT]); } const Expr *getCond() const { diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8a19cb3f552b..4f93af9f1f7b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9487,7 +9487,6 @@ def note_cilk_for_loop_control_var_declared_here: Note< def warn_empty_cilk_for_body : Warning< "Cilk for loop has empty body">, InGroup; - def note_constant_stride: Note< "constant stride is %0">; def warn_cilk_for_cond_user_defined_conv: Warning< From c65e3ce109500686403ad53988dddf14d53a8c41 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 22:10:34 -0400 Subject: [PATCH 46/64] whitespace --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4f93af9f1f7b..98d2903cb137 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10509,6 +10509,7 @@ def warn_sycl_kernel_num_of_template_params : Warning< def warn_sycl_kernel_invalid_template_param_type : Warning< "template parameter of a function template with the 'sycl_kernel' attribute" " cannot be a non-type template parameter">, InGroup; + def warn_sycl_kernel_num_of_function_params : Warning< "function template with 'sycl_kernel' attribute must have a single parameter">, InGroup; From 5c6764cc04629545599db1e653fe77ce7570c101 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 22:17:42 -0400 Subject: [PATCH 47/64] more formatting --- .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Sema/SemaStmt.cpp | 83 ++++++++++--------- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 98d2903cb137..7d9965b99fe6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10509,7 +10509,7 @@ def warn_sycl_kernel_num_of_template_params : Warning< def warn_sycl_kernel_invalid_template_param_type : Warning< "template parameter of a function template with the 'sycl_kernel' attribute" " cannot be a non-type template parameter">, InGroup; - + def warn_sycl_kernel_num_of_function_params : Warning< "function template with 'sycl_kernel' attribute must have a single parameter">, InGroup; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index f16e780ba2ea..be7fc272cfb5 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3496,21 +3496,22 @@ static void SearchForReturnInStmt(Sema &Self, Stmt *S) { } } -// TODO: add comment StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { if (!S || !B) return StmtError(); CilkForRangeStmt *CilkForRange = cast(S); - StmtResult ForRange = FinishCXXForRangeStmt(CilkForRange->getCXXForRangeStmt(), B); + StmtResult ForRange = + FinishCXXForRangeStmt(CilkForRange->getCXXForRangeStmt(), B); if (ForRange.isInvalid()) return StmtError(); CilkForRange->setForRange(ForRange.get()); CXXForRangeStmt *CXXForRange = cast(ForRange.get()); - VarDecl *BeginVar = cast(CXXForRange->getBeginStmt()->getSingleDecl()); + VarDecl *BeginVar = + cast(CXXForRange->getBeginStmt()->getSingleDecl()); QualType BeginType = BeginVar->getType(); const QualType BeginRefNonRefType = BeginType.getNonReferenceType(); ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, @@ -3519,16 +3520,16 @@ StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { VarDecl *LoopIndex = CilkForRange->getLoopIndex(); QualType LoopIndexType = LoopIndex->getType(); const QualType LoopIndexRefNonRefType = LoopIndexType.getNonReferenceType(); - ExprResult LoopIndexRef = BuildDeclRefExpr(LoopIndex, LoopIndexRefNonRefType, - VK_LValue, CXXForRange->getColonLoc()); - + ExprResult LoopIndexRef = BuildDeclRefExpr( + LoopIndex, LoopIndexRefNonRefType, VK_LValue, CXXForRange->getColonLoc()); VarDecl *LoopVar = CXXForRange->getLoopVariable(); SourceLocation LoopVarLoc = LoopVar->getBeginLoc(); - ExprResult NewLoopVarInit = - ActOnBinOp(getCurScope(), LoopVarLoc, tok::plus, BeginRef.get(), LoopIndexRef.get()); + ExprResult NewLoopVarInit = ActOnBinOp(getCurScope(), LoopVarLoc, tok::plus, + BeginRef.get(), LoopIndexRef.get()); - ExprResult DerefExpr = ActOnUnaryOp(getCurScope(), LoopVarLoc, tok::star, NewLoopVarInit.get()); + ExprResult DerefExpr = + ActOnUnaryOp(getCurScope(), LoopVarLoc, tok::star, NewLoopVarInit.get()); if (DerefExpr.isInvalid()) { Diag(LoopVarLoc, diag::note_for_range_invalid_iterator) << LoopVarLoc << 1 << NewLoopVarInit.get()->getType(); @@ -3540,50 +3541,54 @@ StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { return CilkForRange; } -StmtResult Sema::ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, Stmt *InitStmt, - Stmt *First, SourceLocation ColonLoc, - Expr *Range, SourceLocation RParenLoc, - BuildForRangeKind Kind) { - // we wrap the for range! +StmtResult Sema::ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, + Stmt *InitStmt, Stmt *First, + SourceLocation ColonLoc, Expr *Range, + SourceLocation RParenLoc, + BuildForRangeKind Kind) { + // We wrap the CXXForRange, in an attempt to reduce code copying. SourceLocation EmptyCoawaitLoc; - StmtResult ForRangeStmt = ActOnCXXForRangeStmt( - S, ForLoc, EmptyCoawaitLoc, InitStmt, - First, ColonLoc, Range, - RParenLoc, Kind); + StmtResult ForRangeStmt = + ActOnCXXForRangeStmt(S, ForLoc, EmptyCoawaitLoc, InitStmt, First, + ColonLoc, Range, RParenLoc, Kind); if (ForRangeStmt.isInvalid()) return ForRangeStmt; - return BuildCilkForRangeStmt(cast_or_null(ForRangeStmt.get())); + return BuildCilkForRangeStmt( + cast_or_null(ForRangeStmt.get())); } StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { Scope *S = getCurScope(); - // buld up the difference type - // create an end - begin stmt - // that will be the loop var stmt + // 1. Build an induction variable of type difference_type + // 2. Create an end - begin stmt, the end value of the induction variable. + VarDecl *BeginVar = cast(ForRange->getBeginStmt()->getSingleDecl()); QualType BeginType = BeginVar->getType(); const QualType BeginRefNonRefType = BeginType.getNonReferenceType(); ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, - VK_LValue, ForRange->getColonLoc()); + VK_LValue, ForRange->getColonLoc()); VarDecl *EndVar = cast(ForRange->getEndStmt()->getSingleDecl()); QualType EndType = EndVar->getType(); const QualType EndRefNonRefType = EndType.getNonReferenceType(); - ExprResult EndRef = BuildDeclRefExpr(EndVar, EndRefNonRefType, - VK_LValue, ForRange->getColonLoc()); - ExprResult LimitExpr = ActOnBinOp(S, ForRange->getColonLoc(), tok::minus, EndRef.get(), BeginRef.get()); + ExprResult EndRef = BuildDeclRefExpr(EndVar, EndRefNonRefType, VK_LValue, + ForRange->getColonLoc()); + ExprResult LimitExpr = ActOnBinOp(S, ForRange->getColonLoc(), tok::minus, + EndRef.get(), BeginRef.get()); if (LimitExpr.isInvalid()) { - // give warning about for range only supporting random access! + // CilkForRange currently only supports random access iterators. Diag(ForRange->getForLoc(), diag::err_cilk_for_range_end_minus_begin); return StmtError(); } SourceLocation RangeLoc = ForRange->getBeginLoc(); - VarDecl *Limit = BuildForRangeVarDecl(*this, RangeLoc, LimitExpr.get()->getType(), std::string("__cilk_looplimit")); + VarDecl *Limit = + BuildForRangeVarDecl(*this, RangeLoc, LimitExpr.get()->getType(), + std::string("__cilk_looplimit")); AddInitializerToDecl(Limit, LimitExpr.get(), - /*DirectInit=*/false); + /*DirectInit=*/false); FinalizeDeclaration(Limit); CurContext->addHiddenDecl(Limit); @@ -3593,7 +3598,9 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { if (LimitStmt.isInvalid()) return StmtError(); - VarDecl *LoopIndex = BuildForRangeVarDecl(*this, RangeLoc, LimitExpr.get()->getType(), std::string("__cilk_loopindex")); + VarDecl *LoopIndex = + BuildForRangeVarDecl(*this, RangeLoc, LimitExpr.get()->getType(), + std::string("__cilk_loopindex")); AddInitializerToDecl(LoopIndex, ActOnIntegerConstant(RangeLoc, 0).get(), /*DirectInit=*/false); FinalizeDeclaration(LoopIndex); @@ -3605,10 +3612,10 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { if (LoopIndexStmt.isInvalid()) return StmtError(); - ExprResult LimitRef = BuildDeclRefExpr(Limit, Limit->getType(), VK_LValue, - RangeLoc); - ExprResult LoopIndexRef = BuildDeclRefExpr(LoopIndex, LoopIndex->getType(), VK_LValue, - RangeLoc); + ExprResult LimitRef = + BuildDeclRefExpr(Limit, Limit->getType(), VK_LValue, RangeLoc); + ExprResult LoopIndexRef = + BuildDeclRefExpr(LoopIndex, LoopIndex->getType(), VK_LValue, RangeLoc); ExprResult Cond; Cond = ActOnBinOp(S, RangeLoc, tok::exclaimequal, LoopIndexRef.get(), LimitRef.get()); @@ -3618,14 +3625,16 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { // Create a new increment operation on the new beginning variable, and add it // to the existing increment operation. SourceLocation IncLoc = RangeLoc; - ExprResult NewInc = ActOnUnaryOp(S, IncLoc, tok::plusplus, LoopIndexRef.get()); + ExprResult NewInc = + ActOnUnaryOp(S, IncLoc, tok::plusplus, LoopIndexRef.get()); if (NewInc.isInvalid()) return StmtError(); - return new (Context) CilkForRangeStmt(Context, ForRange, LoopIndex, cast(LimitStmt.get()), Cond.get(), NewInc.get(), cast(LoopIndexStmt.get())); + return new (Context) CilkForRangeStmt( + Context, ForRange, LoopIndex, cast(LimitStmt.get()), Cond.get(), + NewInc.get(), cast(LoopIndexStmt.get())); } - StmtResult Sema::ActOnCilkForStmt(SourceLocation CilkForLoc, SourceLocation LParenLoc, Stmt *First, DeclStmt *Limit, ConditionResult InitCond, From fd33a6342a4c2eb0d7011954b17edfc3ec3d8901 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 22:20:37 -0400 Subject: [PATCH 48/64] treetransform --- clang/lib/Sema/TreeTransform.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 4bd9380bf96f..2a2bcf1f93cb 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1368,12 +1368,16 @@ class TreeTransform { RParenLoc, Body, LoopVar); } - // Builds a new Cilk for range statement. - // TODO: this feels very hacky + /// Build a new Cilk for range statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. StmtResult RebuildCilkForRangeStmt(Stmt *ForRange) { - // we don't reconstruct the for range into its constituent parts, - // but rather let the ForRange handle it for us - return getSema().BuildCilkForRangeStmt(cast_or_null(ForRange)); + // We don't reconstruct the for range from its constituent parts, + // but rather let the CXXForRange do the rebuild, and then recompute + // all our fields by building it again. + return getSema().BuildCilkForRangeStmt( + cast_or_null(ForRange)); } /// Build a new goto statement. From 01e1f172a123a99bcf368fb8ec77550dfbf8c5fa Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 22:22:13 -0400 Subject: [PATCH 49/64] fix whitespace again --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 7d9965b99fe6..0ac7125f7849 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10509,11 +10509,11 @@ def warn_sycl_kernel_num_of_template_params : Warning< def warn_sycl_kernel_invalid_template_param_type : Warning< "template parameter of a function template with the 'sycl_kernel' attribute" " cannot be a non-type template parameter">, InGroup; - def warn_sycl_kernel_num_of_function_params : Warning< "function template with 'sycl_kernel' attribute must have a single parameter">, InGroup; def warn_sycl_kernel_return_type : Warning< "function template with 'sycl_kernel' attribute must have a 'void' return type">, InGroup; + } // end of sema component. From b79b20575441a192bb717576e765bb992d4832ad Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 22:22:40 -0400 Subject: [PATCH 50/64] fix whitespace again --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0ac7125f7849..06fa958a190a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10515,5 +10515,5 @@ def warn_sycl_kernel_num_of_function_params : Warning< def warn_sycl_kernel_return_type : Warning< "function template with 'sycl_kernel' attribute must have a 'void' return type">, InGroup; - + } // end of sema component. From 077501a608b1e987cac5419af4471efe750d18e3 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 6 Apr 2021 22:24:34 -0400 Subject: [PATCH 51/64] whitespaceeee --- clang/lib/Parse/ParseCilk.cpp | 48 ++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/clang/lib/Parse/ParseCilk.cpp b/clang/lib/Parse/ParseCilk.cpp index 755e37a4f4e3..dd65dec83ed1 100644 --- a/clang/lib/Parse/ParseCilk.cpp +++ b/clang/lib/Parse/ParseCilk.cpp @@ -69,7 +69,7 @@ StmtResult Parser::ParseCilkSpawnStatement() { StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { assert(Tok.is(tok::kw__Cilk_for) && "Not a _Cilk_for stmt!"); - SourceLocation ForLoc = ConsumeToken(); // eat the '_Cilk_for'. + SourceLocation ForLoc = ConsumeToken(); // eat the '_Cilk_for'. // SourceLocation CoawaitLoc; // if (Tok.is(tok::kw_co_await)) @@ -81,8 +81,8 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { return StmtError(); } - bool C99orCXXorObjC = getLangOpts().C99 || getLangOpts().CPlusPlus || - getLangOpts().ObjC; + bool C99orCXXorObjC = + getLangOpts().C99 || getLangOpts().CPlusPlus || getLangOpts().ObjC; // A _Cilk_for statement is a block. Start the loop scope. // @@ -126,7 +126,7 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { SourceLocation EmptyInitStmtSemiLoc; // Parse the first part of the for specifier. - if (Tok.is(tok::semi)) { // _Cilk_for (; + if (Tok.is(tok::semi)) { // _Cilk_for (; ProhibitAttributes(attrs); // We disallow this syntax for now. Diag(Tok, diag::err_cilk_for_missing_control_variable) << ";"; @@ -145,15 +145,15 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { ForRangeInfo.RangeExpr = ParseExpression(); Diag(Loc, diag::err_for_range_identifier) - << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17) - ? FixItHint::CreateInsertion(Loc, "auto &&") - : FixItHint()); + << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17) + ? FixItHint::CreateInsertion(Loc, "auto &&") + : FixItHint()); - ForRangeInfo.LoopVar = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name, - attrs, attrs.Range.getEnd()); - } else if (isForInitDeclaration()) { // _Cilk_for (int X = 4; + ForRangeInfo.LoopVar = Actions.ActOnCXXForRangeIdentifier( + getCurScope(), Loc, Name, attrs, attrs.Range.getEnd()); + } else if (isForInitDeclaration()) { // _Cilk_for (int X = 4; // Parse declaration, which eats the ';'. - if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? + if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); // In C++0x, "for (T NS:a" might not be a typo for :: @@ -166,11 +166,12 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { MightBeForRangeStmt ? &ForRangeInfo : nullptr); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); if (ForRangeInfo.ParsedForRangeDecl()) { - Diag(ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_for_range : diag::ext_for_range); + Diag(ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_for_range + : diag::ext_for_range); ForRangeInfo.LoopVar = FirstPart; FirstPart = StmtResult(); - } else if (Tok.is(tok::semi)) { // for (int x = 4; + } else if (Tok.is(tok::semi)) { // for (int x = 4; ConsumeToken(); } else if ((ForEach = isTokIdentifier_in())) { Actions.ActOnForEachDeclStmt(DG); @@ -219,11 +220,12 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { return StmtError(); } Collection = ParseExpression(); - } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::colon) && FirstPart.get()) { + } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::colon) && + FirstPart.get()) { // User tried to write the reasonable, but ill-formed, for-range-statement // for (expr : expr) { ... } Diag(Tok, diag::err_for_range_expected_decl) - << FirstPart.get()->getSourceRange(); + << FirstPart.get()->getSourceRange(); SkipUntil(tok::r_paren, StopBeforeMatch); SecondPart = Sema::ConditionError(); } else { @@ -240,16 +242,17 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { // Parse the second part of the for specifier. getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope); - if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() && !SecondPart.isInvalid()) { + if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() && + !SecondPart.isInvalid()) { // Parse the second part of the for specifier. - if (Tok.is(tok::semi)) { // for (...;; + if (Tok.is(tok::semi)) { // for (...;; // no second part. Diag(Tok, diag::err_cilk_for_missing_condition) - << FirstPart.get()->getSourceRange(); + << FirstPart.get()->getSourceRange(); } else if (Tok.is(tok::r_paren)) { // missing both semicolons. Diag(Tok, diag::err_cilk_for_missing_condition) - << FirstPart.get()->getSourceRange(); + << FirstPart.get()->getSourceRange(); } else { if (getLangOpts().CPlusPlus) { // C++2a: We've parsed an init-statement; we might have a @@ -387,9 +390,8 @@ StmtResult Parser::ParseCilkForStatement(SourceLocation *TrailingElseLoc) { // return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(), // Body.get()); - // TODO(arvid): uncomment this - if (ForRangeInfo.ParsedForRangeDecl()) - return Actions.FinishCilkForRangeStmt(ForRangeStmt.get(), Body.get()); + if (ForRangeInfo.ParsedForRangeDecl()) + return Actions.FinishCilkForRangeStmt(ForRangeStmt.get(), Body.get()); return Actions.ActOnCilkForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), nullptr, Sema::ConditionResult(), nullptr, From 5832b5559a146750f434a1c9c84387267d8f3fa3 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 13 Apr 2021 23:33:57 -0400 Subject: [PATCH 52/64] simplify loopvar emission --- clang/lib/CodeGen/CGCilk.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index c708f6a1d7f0..bcc373212db0 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -882,8 +882,8 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, llvm::AllocaInst *OldEHSelectorSlot; Address OldNormalCleanupDest = Address::invalid(); - const VarDecl *LoopVar = ForRange.getLoopVariable(); - RValue LoopVarInitRV; +// const VarDecl *LoopVar = ForRange.getLoopVariable(); +// RValue LoopVarInitRV; llvm::BasicBlock *DetachBlock; llvm::BasicBlock *ForBodyEntry; llvm::BasicBlock *ForBody; @@ -916,9 +916,9 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // Get the value of the loop variable initialization before we emit the // detach. - if (LoopVar) { - LoopVarInitRV = EmitAnyExprToTemp(LoopVar->getInit()); - } +// if (LoopVar) { +// LoopVarInitRV = EmitAnyExprToTemp(LoopVar->getInit()); +// } Detach = Builder.CreateDetach(ForBodyEntry, Continue.getBlock(), SyncRegion); @@ -961,15 +961,16 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // Inside the detached block, create the loop variable, setting its value to // the saved initialization value. - if (LoopVar) { - AutoVarEmission LVEmission = EmitAutoVarAlloca(*LoopVar); - QualType type = LoopVar->getType(); - Address Loc = LVEmission.getObjectAddress(*this); - LValue LV = MakeAddrLValue(Loc, type); - LV.setNonGC(true); - EmitStoreThroughLValue(LoopVarInitRV, LV, true); - EmitAutoVarCleanups(LVEmission); - } +// if (LoopVar) { +// AutoVarEmission LVEmission = EmitAutoVarAlloca(*LoopVar); +// QualType type = LoopVar->getType(); +// Address Loc = LVEmission.getObjectAddress(*this); +// LValue LV = MakeAddrLValue(Loc, type); +// LV.setNonGC(true); +// EmitStoreThroughLValue(LoopVarInitRV, LV, true); +// EmitAutoVarCleanups(LVEmission); +// } +// EmitStmt(S.getLoopVarStmt()); Builder.CreateBr(ForBody); @@ -985,6 +986,7 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, SyncedScopeRAII SyncedScp(*this); if (isa(ForRange.getBody())) ScopeIsSynced = true; + EmitStmt(ForRange.getLoopVarStmt()); EmitStmt(ForRange.getBody()); if (HaveInsertPoint()) From 1cc96642839075060bfeeec48c2d636aac076e48 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 13 Apr 2021 23:48:02 -0400 Subject: [PATCH 53/64] always create a scope --- clang/lib/CodeGen/CGCilk.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index bcc373212db0..ae0b49b7a97d 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -981,11 +981,14 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, { // Create a separate cleanup scope for the body, in case it is not // a compound statement. - RunCleanupsScope BodyScope(*this); - - SyncedScopeRAII SyncedScp(*this); - if (isa(ForRange.getBody())) - ScopeIsSynced = true; + // NO! Instead, always create a new lexical scope because we want to emit + // the loop var stmt and then the body, so it doesn't matter if the + // body is a compound statement or not. + LexicalScope BodyScope(*this, ForRange.getSourceRange()); + +// SyncedScopeRAII SyncedScp(*this); +// if (isa(ForRange.getBody())) +// ScopeIsSynced = true; EmitStmt(ForRange.getLoopVarStmt()); EmitStmt(ForRange.getBody()); From 947800d472ac989e40c1fdc3ba9da55b7494ed9d Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 13 Apr 2021 23:57:01 -0400 Subject: [PATCH 54/64] im just trying anything right now --- clang/lib/CodeGen/CGCilk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index ae0b49b7a97d..9511fe1e3fa2 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -986,9 +986,9 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // body is a compound statement or not. LexicalScope BodyScope(*this, ForRange.getSourceRange()); -// SyncedScopeRAII SyncedScp(*this); + SyncedScopeRAII SyncedScp(*this); // if (isa(ForRange.getBody())) -// ScopeIsSynced = true; + ScopeIsSynced = true; EmitStmt(ForRange.getLoopVarStmt()); EmitStmt(ForRange.getBody()); From 950b6e69091a645a05cb7adf1897dd0512fbbcd1 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 14 Apr 2021 00:16:52 -0400 Subject: [PATCH 55/64] try 33 --- clang/lib/CodeGen/CGCilk.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index 9511fe1e3fa2..d47ffbf828e1 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -970,7 +970,7 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // EmitStoreThroughLValue(LoopVarInitRV, LV, true); // EmitAutoVarCleanups(LVEmission); // } -// EmitStmt(S.getLoopVarStmt()); + EmitStmt(ForRange.getLoopVarStmt()); Builder.CreateBr(ForBody); @@ -984,12 +984,12 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // NO! Instead, always create a new lexical scope because we want to emit // the loop var stmt and then the body, so it doesn't matter if the // body is a compound statement or not. - LexicalScope BodyScope(*this, ForRange.getSourceRange()); + RunCleanupsScope BodyScope(*this); SyncedScopeRAII SyncedScp(*this); -// if (isa(ForRange.getBody())) + if (isa(ForRange.getBody())) ScopeIsSynced = true; - EmitStmt(ForRange.getLoopVarStmt()); +// EmitStmt(ForRange.getLoopVarStmt()); EmitStmt(ForRange.getBody()); if (HaveInsertPoint()) From 9d47aa46af10b50c7e6ab7b29c6bb828ad263f2a Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 14 Apr 2021 00:29:06 -0400 Subject: [PATCH 56/64] comments --- clang/lib/CodeGen/CGCilk.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index d47ffbf828e1..98e60342aecb 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -970,6 +970,8 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // EmitStoreThroughLValue(LoopVarInitRV, LV, true); // EmitAutoVarCleanups(LVEmission); // } + // TODO: create a cleanup scope here? + // TODO: performance problems when emitting everything here? EmitStmt(ForRange.getLoopVarStmt()); Builder.CreateBr(ForBody); @@ -981,14 +983,12 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, { // Create a separate cleanup scope for the body, in case it is not // a compound statement. - // NO! Instead, always create a new lexical scope because we want to emit - // the loop var stmt and then the body, so it doesn't matter if the - // body is a compound statement or not. RunCleanupsScope BodyScope(*this); SyncedScopeRAII SyncedScp(*this); if (isa(ForRange.getBody())) ScopeIsSynced = true; + // TODO: why does the cleanup crash if we emit the loop var stmt here? // EmitStmt(ForRange.getLoopVarStmt()); EmitStmt(ForRange.getBody()); From 1d0c2fc374ca948da228544bfbf1943098d8de2c Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 21 Apr 2021 09:50:39 -0400 Subject: [PATCH 57/64] add local loop index to sema; behavior should be unchanged --- clang/include/clang/AST/StmtCilk.h | 6 ++++-- clang/lib/AST/StmtCXX.cpp | 10 ++++++++++ clang/lib/Sema/SemaStmt.cpp | 18 +++++++++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index df9b51795fef..c460c1d13c50 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -93,12 +93,12 @@ class CilkSyncStmt : public Stmt { /// This is stored as a FORRANGE stmt embedded inside a CILKFORRANGE with some /// other necessary semantic components. class CilkForRangeStmt : public Stmt { - enum { FORRANGE, LOOPINDEX, LOOPINDEXSTMT, LIMIT, COND, INC, END }; + enum { FORRANGE, LOOPINDEX, LOOPINDEXSTMT, LOCALLOOPINDEX, LIMIT, COND, INC, END }; Stmt *SubExprs[END]; public: CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, - VarDecl *LoopIndex, DeclStmt *Limit, Expr *Cond, Expr *Inc, + VarDecl *LoopIndex, DeclStmt *LocalLoopIndex, DeclStmt *Limit, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt); /// \brief Build an empty cilk for range statement. @@ -122,6 +122,7 @@ class CilkForRangeStmt : public Stmt { return cast_or_null(SubExprs[LOOPINDEXSTMT]); } DeclStmt *getLimitStmt() { return cast_or_null(SubExprs[LIMIT]); } + DeclStmt *getLocalLoopIndexStmt() { return cast(SubExprs[LOCALLOOPINDEX]); } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]); @@ -133,6 +134,7 @@ class CilkForRangeStmt : public Stmt { const DeclStmt *getLimitStmt() const { return cast_or_null(SubExprs[LIMIT]); } + const DeclStmt *getLocalLoopIndexStmt() const { return cast(SubExprs[LOCALLOOPINDEX]); } SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index c66d08604a99..14b869982801 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -163,6 +163,16 @@ void CilkForRangeStmt::setLoopIndex(const ASTContext &C, VarDecl *V) { new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); } +VarDecl *CilkForRangeStmt::getLocalLoopIndex() { + Decl *LV = cast(getLocalLoopIndexStmt())->getSingleDecl(); + assert(LV && "No local loop index in CilkForRangeStmt"); + return cast(LV); +} + +const VarDecl *CilkForRangeStmt::getLocalLoopIndex() const { + return const_cast(this)->getLocalLoopIndex(); +} + /// returns the FORRANGE stmt embedded in the CilkForRange. (May be null.) CXXForRangeStmt *CilkForRangeStmt::getCXXForRangeStmt() const { return cast_or_null(SubExprs[FORRANGE]); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index be7fc272cfb5..46f722c311b5 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3517,6 +3517,7 @@ StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, VK_LValue, CXXForRange->getColonLoc()); +// VarDecl *LoopIndex = CilkForRange->getLocalLoopIndex(); VarDecl *LoopIndex = CilkForRange->getLoopIndex(); QualType LoopIndexType = LoopIndex->getType(); const QualType LoopIndexRefNonRefType = LoopIndexType.getNonReferenceType(); @@ -3612,6 +3613,7 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { if (LoopIndexStmt.isInvalid()) return StmtError(); + ExprResult LimitRef = BuildDeclRefExpr(Limit, Limit->getType(), VK_LValue, RangeLoc); ExprResult LoopIndexRef = @@ -3622,6 +3624,20 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { if (Cond.isInvalid()) return StmtError(); + VarDecl *LocalLoopIndex = + BuildForRangeVarDecl(*this, RangeLoc, LimitExpr.get()->getType(), + std::string("__local_loopindex")); + AddInitializerToDecl(LocalLoopIndex, LoopIndexRef.get(), + /*DirectInit=*/false); + FinalizeDeclaration(LocalLoopIndex); + CurContext->addHiddenDecl(LocalLoopIndex); + + DeclGroupPtrTy LocalLoopIndexGroup = + BuildDeclaratorGroup(MutableArrayRef((Decl **)&LocalLoopIndex, 1)); + StmtResult LocalLoopIndexStmt = ActOnDeclStmt(LocalLoopIndexGroup, RangeLoc, RangeLoc); + if (LocalLoopIndexStmt.isInvalid()) + return StmtError(); + // Create a new increment operation on the new beginning variable, and add it // to the existing increment operation. SourceLocation IncLoc = RangeLoc; @@ -3631,7 +3647,7 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { return StmtError(); return new (Context) CilkForRangeStmt( - Context, ForRange, LoopIndex, cast(LimitStmt.get()), Cond.get(), + Context, ForRange, LoopIndex, cast(LocalLoopIndexStmt.get()), cast(LimitStmt.get()), Cond.get(), NewInc.get(), cast(LoopIndexStmt.get())); } From 5c7fcb62a253b28bda5077c27ce3ed100d557712 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 21 Apr 2021 09:57:21 -0400 Subject: [PATCH 58/64] fix compile errors --- clang/include/clang/AST/StmtCilk.h | 3 +++ clang/lib/AST/StmtCXX.cpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index c460c1d13c50..06d2bb83c190 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -116,6 +116,9 @@ class CilkForRangeStmt : public Stmt { VarDecl *getLoopIndex() const; void setLoopIndex(const ASTContext &C, VarDecl *V); + VarDecl *getLocalLoopIndex(); + const VarDecl *getLocalLoopIndex() const; + Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } DeclStmt *getLoopIndexStmt() { diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index 14b869982801..b48023a454ca 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -130,12 +130,13 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) /// Constructor for the CilkForRangeStmt CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, - VarDecl *LoopIndex, DeclStmt *Limit, + VarDecl *LoopIndex, DeclStmt *LocalLoopIndex, DeclStmt *Limit, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt) : Stmt(CilkForRangeStmtClass) { SubExprs[FORRANGE] = ForRange; setLoopIndex(C, LoopIndex); + SubExprs[LOCALLOOPINDEX] = LocalLoopIndex; SubExprs[COND] = Cond; SubExprs[INC] = Inc; SubExprs[LOOPINDEXSTMT] = LoopIndexStmt; From f6defc9ce1eb954a64a18c0b6430d54465b64551 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 21 Apr 2021 10:12:44 -0400 Subject: [PATCH 59/64] do the actual thing --- clang/lib/CodeGen/CGCilk.cpp | 30 ++++++++++++++---------------- clang/lib/Sema/SemaStmt.cpp | 4 ++-- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index 98e60342aecb..fe2b3cb4148c 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -882,8 +882,8 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, llvm::AllocaInst *OldEHSelectorSlot; Address OldNormalCleanupDest = Address::invalid(); -// const VarDecl *LoopVar = ForRange.getLoopVariable(); -// RValue LoopVarInitRV; + const VarDecl *LocalLoopIndex = S.getLocalLoopIndex(); + RValue LocalLoopIndexInitRV; llvm::BasicBlock *DetachBlock; llvm::BasicBlock *ForBodyEntry; llvm::BasicBlock *ForBody; @@ -916,9 +916,9 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // Get the value of the loop variable initialization before we emit the // detach. -// if (LoopVar) { -// LoopVarInitRV = EmitAnyExprToTemp(LoopVar->getInit()); -// } + if (LocalLoopIndex) { + LocalLoopIndexInitRV = EmitAnyExprToTemp(LocalLoopIndex->getInit()); + } Detach = Builder.CreateDetach(ForBodyEntry, Continue.getBlock(), SyncRegion); @@ -961,17 +961,15 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, // Inside the detached block, create the loop variable, setting its value to // the saved initialization value. -// if (LoopVar) { -// AutoVarEmission LVEmission = EmitAutoVarAlloca(*LoopVar); -// QualType type = LoopVar->getType(); -// Address Loc = LVEmission.getObjectAddress(*this); -// LValue LV = MakeAddrLValue(Loc, type); -// LV.setNonGC(true); -// EmitStoreThroughLValue(LoopVarInitRV, LV, true); -// EmitAutoVarCleanups(LVEmission); -// } - // TODO: create a cleanup scope here? - // TODO: performance problems when emitting everything here? + if (LocalLoopIndex) { + AutoVarEmission LVEmission = EmitAutoVarAlloca(*LocalLoopIndex); + QualType type = LocalLoopIndex->getType(); + Address Loc = LVEmission.getObjectAddress(*this); + LValue LV = MakeAddrLValue(Loc, type); + LV.setNonGC(true); + EmitStoreThroughLValue(LocalLoopIndexInitRV, LV, true); + EmitAutoVarCleanups(LVEmission); + } EmitStmt(ForRange.getLoopVarStmt()); Builder.CreateBr(ForBody); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 46f722c311b5..007d05113cda 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3517,8 +3517,8 @@ StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, VK_LValue, CXXForRange->getColonLoc()); -// VarDecl *LoopIndex = CilkForRange->getLocalLoopIndex(); - VarDecl *LoopIndex = CilkForRange->getLoopIndex(); + VarDecl *LoopIndex = CilkForRange->getLocalLoopIndex(); +// VarDecl *LoopIndex = CilkForRange->getLoopIndex(); QualType LoopIndexType = LoopIndex->getType(); const QualType LoopIndexRefNonRefType = LoopIndexType.getNonReferenceType(); ExprResult LoopIndexRef = BuildDeclRefExpr( From b63a19f9f3d5f62e27d3531e2bc54dcf5f81da35 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 21 Apr 2021 10:26:24 -0400 Subject: [PATCH 60/64] cleanup --- clang/include/clang/AST/StmtCilk.h | 22 ++++++++++++++++++---- clang/lib/AST/StmtCXX.cpp | 4 ++-- clang/lib/CodeGen/CGCilk.cpp | 2 -- clang/lib/Sema/SemaStmt.cpp | 16 ++++++++-------- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/AST/StmtCilk.h b/clang/include/clang/AST/StmtCilk.h index 06d2bb83c190..9f2b3c5ad54e 100644 --- a/clang/include/clang/AST/StmtCilk.h +++ b/clang/include/clang/AST/StmtCilk.h @@ -93,12 +93,22 @@ class CilkSyncStmt : public Stmt { /// This is stored as a FORRANGE stmt embedded inside a CILKFORRANGE with some /// other necessary semantic components. class CilkForRangeStmt : public Stmt { - enum { FORRANGE, LOOPINDEX, LOOPINDEXSTMT, LOCALLOOPINDEX, LIMIT, COND, INC, END }; + enum { + FORRANGE, + LOOPINDEX, + LOOPINDEXSTMT, + LOCALLOOPINDEX, + LIMIT, + COND, + INC, + END + }; Stmt *SubExprs[END]; public: CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, - VarDecl *LoopIndex, DeclStmt *LocalLoopIndex, DeclStmt *Limit, Expr *Cond, Expr *Inc, + VarDecl *LoopIndex, DeclStmt *LocalLoopIndex, + DeclStmt *Limit, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt); /// \brief Build an empty cilk for range statement. @@ -125,7 +135,9 @@ class CilkForRangeStmt : public Stmt { return cast_or_null(SubExprs[LOOPINDEXSTMT]); } DeclStmt *getLimitStmt() { return cast_or_null(SubExprs[LIMIT]); } - DeclStmt *getLocalLoopIndexStmt() { return cast(SubExprs[LOCALLOOPINDEX]); } + DeclStmt *getLocalLoopIndexStmt() { + return cast(SubExprs[LOCALLOOPINDEX]); + } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]); @@ -137,7 +149,9 @@ class CilkForRangeStmt : public Stmt { const DeclStmt *getLimitStmt() const { return cast_or_null(SubExprs[LIMIT]); } - const DeclStmt *getLocalLoopIndexStmt() const { return cast(SubExprs[LOCALLOOPINDEX]); } + const DeclStmt *getLocalLoopIndexStmt() const { + return cast(SubExprs[LOCALLOOPINDEX]); + } SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index b48023a454ca..190c37ff1084 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -130,8 +130,8 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) /// Constructor for the CilkForRangeStmt CilkForRangeStmt::CilkForRangeStmt(const ASTContext &C, CXXForRangeStmt *ForRange, - VarDecl *LoopIndex, DeclStmt *LocalLoopIndex, DeclStmt *Limit, - Expr *Cond, Expr *Inc, + VarDecl *LoopIndex, DeclStmt *LocalLoopIndex, + DeclStmt *Limit, Expr *Cond, Expr *Inc, DeclStmt *LoopIndexStmt) : Stmt(CilkForRangeStmtClass) { SubExprs[FORRANGE] = ForRange; diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index fe2b3cb4148c..4524545d7238 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -986,8 +986,6 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, SyncedScopeRAII SyncedScp(*this); if (isa(ForRange.getBody())) ScopeIsSynced = true; - // TODO: why does the cleanup crash if we emit the loop var stmt here? -// EmitStmt(ForRange.getLoopVarStmt()); EmitStmt(ForRange.getBody()); if (HaveInsertPoint()) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 007d05113cda..7436a1efa950 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3518,7 +3518,6 @@ StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { VK_LValue, CXXForRange->getColonLoc()); VarDecl *LoopIndex = CilkForRange->getLocalLoopIndex(); -// VarDecl *LoopIndex = CilkForRange->getLoopIndex(); QualType LoopIndexType = LoopIndex->getType(); const QualType LoopIndexRefNonRefType = LoopIndexType.getNonReferenceType(); ExprResult LoopIndexRef = BuildDeclRefExpr( @@ -3613,7 +3612,6 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { if (LoopIndexStmt.isInvalid()) return StmtError(); - ExprResult LimitRef = BuildDeclRefExpr(Limit, Limit->getType(), VK_LValue, RangeLoc); ExprResult LoopIndexRef = @@ -3628,13 +3626,14 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { BuildForRangeVarDecl(*this, RangeLoc, LimitExpr.get()->getType(), std::string("__local_loopindex")); AddInitializerToDecl(LocalLoopIndex, LoopIndexRef.get(), - /*DirectInit=*/false); + /*DirectInit=*/false); FinalizeDeclaration(LocalLoopIndex); CurContext->addHiddenDecl(LocalLoopIndex); - DeclGroupPtrTy LocalLoopIndexGroup = - BuildDeclaratorGroup(MutableArrayRef((Decl **)&LocalLoopIndex, 1)); - StmtResult LocalLoopIndexStmt = ActOnDeclStmt(LocalLoopIndexGroup, RangeLoc, RangeLoc); + DeclGroupPtrTy LocalLoopIndexGroup = BuildDeclaratorGroup( + MutableArrayRef((Decl **)&LocalLoopIndex, 1)); + StmtResult LocalLoopIndexStmt = + ActOnDeclStmt(LocalLoopIndexGroup, RangeLoc, RangeLoc); if (LocalLoopIndexStmt.isInvalid()) return StmtError(); @@ -3647,8 +3646,9 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { return StmtError(); return new (Context) CilkForRangeStmt( - Context, ForRange, LoopIndex, cast(LocalLoopIndexStmt.get()), cast(LimitStmt.get()), Cond.get(), - NewInc.get(), cast(LoopIndexStmt.get())); + Context, ForRange, LoopIndex, cast(LocalLoopIndexStmt.get()), + cast(LimitStmt.get()), Cond.get(), NewInc.get(), + cast(LoopIndexStmt.get())); } StmtResult From 01b6eb95164b1edf6054e992e975bf83eb393317 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 21 Apr 2021 10:31:15 -0400 Subject: [PATCH 61/64] add comments --- clang/lib/CodeGen/CGCilk.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index 4524545d7238..c2d02bb17b0b 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -914,8 +914,11 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, EmitBlockAfterUses(DetachBlock); - // Get the value of the loop variable initialization before we emit the - // detach. + // Get the value of the loop index before we emit the detach. + // This avoids a race condition on cilk_loopindex with -O0. + // Note that the ordinary cilk_for code emits the value of the loop var; + // that does not work for us, since our loop var may be any complicated + // type, and emitting to temp RV only works for simple types. if (LocalLoopIndex) { LocalLoopIndexInitRV = EmitAnyExprToTemp(LocalLoopIndex->getInit()); } @@ -959,8 +962,8 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, JumpDest Preattach = getJumpDestInCurrentScope("pfor.preattach"); BreakContinueStack.push_back(BreakContinue(Preattach, Preattach)); - // Inside the detached block, create the loop variable, setting its value to - // the saved initialization value. + // Inside the detached block, create the loop index, setting its value to + // the saved initialization value. This avoids a race condition. if (LocalLoopIndex) { AutoVarEmission LVEmission = EmitAutoVarAlloca(*LocalLoopIndex); QualType type = LocalLoopIndex->getType(); @@ -970,6 +973,7 @@ CodeGenFunction::EmitCilkForRangeStmt(const CilkForRangeStmt &S, EmitStoreThroughLValue(LocalLoopIndexInitRV, LV, true); EmitAutoVarCleanups(LVEmission); } + // Emit the loop var stmt, which will use the local loop index emitted above. EmitStmt(ForRange.getLoopVarStmt()); Builder.CreateBr(ForBody); From df3edbeed414c36f2cc38219873aa0709f78f5e0 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 2 Jun 2021 10:14:00 -0400 Subject: [PATCH 62/64] Regression tests (#10) * add range loop test * add * frewrite-includes * fix range loop test * addworkingalmostrangelooptest * address some warnings * add more expected warnings and notes * ignore notes * cilkforrange ir * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * fix * add more isinvalid checks * add more errors * add more errors * add more errors * add more errors * add more errors * add more errors * idk * idk * idk * idk * idk * vector mock * better vector mock * dont actually malloc * fix? * fix? * fix? * fix? * fix? * rangelooptest all mocked out * pragma allowed for forrange too * pragma cilk allowed too * fix ir * ir fix * ir fix * fix ir * fix ir * bug * bug * regexify * regexify * more tests * fix name mangling * fix test * auto test * name mangling * final test * name mangling * clang format Co-authored-by: --- clang/lib/Sema/SemaStmt.cpp | 27 ++- clang/lib/Sema/SemaStmtAttr.cpp | 8 +- clang/lib/Sema/TreeTransform.h | 11 +- clang/test/Cilk/cilkforrange-ir.cpp | 267 ++++++++++++++++++++++++++++ clang/test/Cilk/rangelooptest.cpp | 149 ++++++++++++++++ 5 files changed, 456 insertions(+), 6 deletions(-) create mode 100644 clang/test/Cilk/cilkforrange-ir.cpp create mode 100644 clang/test/Cilk/rangelooptest.cpp diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 7436a1efa950..6d6db35a2b3d 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3510,23 +3510,39 @@ StmtResult Sema::FinishCilkForRangeStmt(Stmt *S, Stmt *B) { CXXForRangeStmt *CXXForRange = cast(ForRange.get()); + if (isa(CXXForRange->getBody())) { + Diag(CXXForRange->getForLoc(), diag::warn_empty_cilk_for_body); + getCurCompoundScope().setHasEmptyLoopBodies(); + } + + SearchForReturnInStmt(*this, CXXForRange->getBody()); + + if (BreakContinueFinder(*this, CXXForRange->getBody()).BreakFound()) + Diag(CXXForRange->getForLoc(), diag::err_cilk_for_cannot_break); + VarDecl *BeginVar = cast(CXXForRange->getBeginStmt()->getSingleDecl()); QualType BeginType = BeginVar->getType(); const QualType BeginRefNonRefType = BeginType.getNonReferenceType(); ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, VK_LValue, CXXForRange->getColonLoc()); + if (BeginRef.isInvalid()) + return StmtError(); VarDecl *LoopIndex = CilkForRange->getLocalLoopIndex(); QualType LoopIndexType = LoopIndex->getType(); const QualType LoopIndexRefNonRefType = LoopIndexType.getNonReferenceType(); ExprResult LoopIndexRef = BuildDeclRefExpr( LoopIndex, LoopIndexRefNonRefType, VK_LValue, CXXForRange->getColonLoc()); + if (LoopIndexRef.isInvalid()) + return StmtError(); VarDecl *LoopVar = CXXForRange->getLoopVariable(); SourceLocation LoopVarLoc = LoopVar->getBeginLoc(); ExprResult NewLoopVarInit = ActOnBinOp(getCurScope(), LoopVarLoc, tok::plus, BeginRef.get(), LoopIndexRef.get()); + if (NewLoopVarInit.isInvalid()) + return StmtError(); ExprResult DerefExpr = ActOnUnaryOp(getCurScope(), LoopVarLoc, tok::star, NewLoopVarInit.get()); @@ -3555,8 +3571,9 @@ StmtResult Sema::ActOnCilkForRangeStmt(Scope *S, SourceLocation ForLoc, if (ForRangeStmt.isInvalid()) return ForRangeStmt; - return BuildCilkForRangeStmt( - cast_or_null(ForRangeStmt.get())); + CXXForRangeStmt *ForRange = cast_or_null(ForRangeStmt.get()); + + return BuildCilkForRangeStmt(ForRange); } StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { @@ -3570,12 +3587,18 @@ StmtResult Sema::BuildCilkForRangeStmt(CXXForRangeStmt *ForRange) { const QualType BeginRefNonRefType = BeginType.getNonReferenceType(); ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, VK_LValue, ForRange->getColonLoc()); + if (BeginRef.isInvalid()) { + return StmtError(); + } VarDecl *EndVar = cast(ForRange->getEndStmt()->getSingleDecl()); QualType EndType = EndVar->getType(); const QualType EndRefNonRefType = EndType.getNonReferenceType(); ExprResult EndRef = BuildDeclRefExpr(EndVar, EndRefNonRefType, VK_LValue, ForRange->getColonLoc()); + if (EndRef.isInvalid()) { + return StmtError(); + } ExprResult LimitExpr = ActOnBinOp(S, ForRange->getColonLoc(), tok::minus, EndRef.get(), BeginRef.get()); if (LimitExpr.isInvalid()) { diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index a6f84605431c..0522db45e6d4 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -87,9 +87,10 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, .Default("clang loop"); if ((PragmaName == "cilk") && - (St->getStmtClass() != Stmt::CilkForStmtClass)) { + (St->getStmtClass() != Stmt::CilkForStmtClass && + St->getStmtClass() != Stmt::CilkForRangeStmtClass)) { S.Diag(St->getBeginLoc(), diag::err_pragma_cilk_precedes_noncilk) - << "#pragma cilk"; + << "#pragma cilk"; return nullptr; } @@ -97,7 +98,8 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, St->getStmtClass() != Stmt::ForStmtClass && St->getStmtClass() != Stmt::CXXForRangeStmtClass && St->getStmtClass() != Stmt::WhileStmtClass && - St->getStmtClass() != Stmt::CilkForStmtClass) { + St->getStmtClass() != Stmt::CilkForStmtClass && + St->getStmtClass() != Stmt::CilkForRangeStmtClass) { std::string Pragma = "#pragma " + std::string(PragmaName); S.Diag(St->getBeginLoc(), diag::err_pragma_loop_precedes_nonloop) << Pragma; return nullptr; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 2a2bcf1f93cb..93a7f801b69f 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1379,6 +1379,9 @@ class TreeTransform { return getSema().BuildCilkForRangeStmt( cast_or_null(ForRange)); } + StmtResult FinishCilkForRangeStmt(Stmt *ForRange, Stmt *Body) { + return getSema().FinishCilkForRangeStmt(ForRange, Body); + } /// Build a new goto statement. /// @@ -13880,7 +13883,13 @@ TreeTransform::TransformCilkForRangeStmt(CilkForRangeStmt *S) { if (ForRange.isInvalid()) return StmtError(); - return getDerived().RebuildCilkForRangeStmt(ForRange.get()); + StmtResult CilkForRange = + getDerived().RebuildCilkForRangeStmt(ForRange.get()); + if (CilkForRange.isInvalid()) + return StmtError(); + + return getDerived().FinishCilkForRangeStmt( + CilkForRange.get(), cast(ForRange.get())->getBody()); } } // end namespace clang diff --git a/clang/test/Cilk/cilkforrange-ir.cpp b/clang/test/Cilk/cilkforrange-ir.cpp new file mode 100644 index 000000000000..196128ec3d01 --- /dev/null +++ b/clang/test/Cilk/cilkforrange-ir.cpp @@ -0,0 +1,267 @@ +// RUN: %clang_cc1 %s -std=c++11 -triple x86_64-unknown-linux-gnu -fopencilk -ftapir=none -verify -S -emit-llvm -o - | FileCheck %s +// +// useful command: +// ./clang++ -std=c++11 -fopencilk -ftapir=none -S -emit-llvm ../opencilk-project/clang/test/Cilk/cilkforrange-ir.cpp +// cat cilkforrange-ir.ll | grep Z2upN1 -C 50 + +namespace X { +struct C { + C(); + struct It { + int value; + int operator-(It &); + It operator+(int); + It operator++(); + It operator--(); + int &operator*(); + bool operator!=(It &); + }; + It begin(); + It end(); +}; + +} // namespace X + +void bar(int i); + +void iterate(X::C c) { + _Cilk_for(int x + : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + bar(x); +} + +// CHECK-LABEL: define void @_Z7iterateN1X1CE( + +// CHECK: %[[C:.+]] = alloca %"struct.X::C", align 1 +// CHECK-NEXT: %syncreg = call token @llvm.syncregion.start() +// CHECK-NEXT: %[[RANGE:.+]] = alloca %"struct.X::C"*, align 8 +// CHECK-NEXT: %[[BEGIN:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: %[[END:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: %[[CILKLOOPINDEX:.+]] = alloca i32, align 4 +// CHECK-NEXT: %[[CILKLOOPLIMIT:.+]] = alloca i32, align 4 +// CHECK-NEXT: store %"struct.X::C"* %[[C]], %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[CONTAINER:.+]] = load %"struct.X::C"*, %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[BEGINCALL:.+]] = call i32 @_ZN1X1C5beginEv(%"struct.X::C"* %[[CONTAINER]]) +// CHECK-NEXT: %[[BEGINCOERCE:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[BEGIN]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[BEGINCALL]], i32* %[[BEGINCOERCE]], align 4 +// CHECK-NEXT: %[[CONTAINERAGAIN:.+]] = load %"struct.X::C"*, %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[ENDCALL:.+]] = call i32 @_ZN1X1C3endEv(%"struct.X::C"* %[[CONTAINERAGAIN]]) +// CHECK-NEXT: %[[ENDCOERCE:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[END]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[ENDCALL]], i32* %[[ENDCOERCE]], align 4 +// CHECK-NEXT: store i32 0, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONTAINERLENGTH:.+]] = call i32 @_ZN1X1C2ItmiERS1_(%"struct.X::C::It"* %[[END]], %"struct.X::C::It"* dereferenceable(4) %[[BEGIN]]) +// CHECK-NEXT: store i32 %[[CONTAINERLENGTH]], i32* %[[CILKLOOPLIMIT]], align 4 +// CHECK-NEXT: br label %[[PFORCOND:.+]] + +// CHECK: [[PFORCOND]]: +// CHECK-NEXT: br label %[[PFORDETACH:.+]] + +// CHECK: [[PFORDETACH]]: +// CHECK-NEXT: %[[INITITER:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: detach within %[[SYNCREG:.+]], label %[[DETACHED:.+]], label %[[PFORINC:.+]] + +// CHECK: [[DETACHED]]: +// CHECK-NEXT: %__local_loopindex = alloca i32, align 4 +// CHECK-NEXT: %[[X:.+]] = alloca i32, align 4 +// CHECK-NEXT: %[[ITER:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: store i32 %[[INITITER]], i32* %__local_loopindex, align 4 +// CHECK-NEXT: %[[LOOPINDEXCOPY:.+]] = load i32, i32* %__local_loopindex, align 4 +// CHECK-NEXT: %[[ITERREF:.+]] = call i32 @_ZN1X1C2ItplEi(%"struct.X::C::It"* %[[BEGIN]], i32 %[[LOOPINDEXCOPY]]) +// CHECK-NEXT: %[[ITER2:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[ITER]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[ITERREF]], i32* %[[ITER2]], align 4 +// CHECK-NEXT: %[[ELEM:.+]] = call dereferenceable(4) i32* @_ZN1X1C2ItdeEv(%"struct.X::C::It"* %[[ITER]]) +// CHECK-NEXT: %[[ELEMVAL:.+]] = load i32, i32* %[[ELEM]], align 4 +// CHECK-NEXT: store i32 %[[ELEMVAL]], i32* %[[X]], align 4 + +// CHECK: [[PFORINC]]: +// CHECK-NEXT: %[[INCBEGIN:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[INC:.+]] = add nsw i32 %[[INCBEGIN]], 1 +// CHECK-NEXT: store i32 %[[INC]], i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONDBEGIN:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONDEND:.+]] = load i32, i32* %[[CILKLOOPLIMIT]], align 4 +// CHECK-NEXT: %[[COND:.+]] = icmp ne i32 %[[CONDBEGIN]], %[[CONDEND]] +// CHECK-NEXT: br i1 %[[COND]], label %{{.+}}, label %[[PFORCONDCLEANUP:.+]], !llvm.loop ![[LOOPMD:.+]] + +// CHECK: [[PFORCONDCLEANUP]]: +// CHECK-NEXT: sync within %[[SYNCREG]] + +void iterate_ref(X::C c) { + _Cilk_for(int &x + : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + bar(x); +} + +// CHECK-LABEL: define void @_Z11iterate_refN1X1CE( + +// CHECK: %[[C:.+]] = alloca %"struct.X::C", align 1 +// CHECK-NEXT: %syncreg = call token @llvm.syncregion.start() +// CHECK-NEXT: %[[RANGE:.+]] = alloca %"struct.X::C"*, align 8 +// CHECK-NEXT: %[[BEGIN:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: %[[END:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: %[[CILKLOOPINDEX:.+]] = alloca i32, align 4 +// CHECK-NEXT: %[[CILKLOOPLIMIT:.+]] = alloca i32, align 4 +// CHECK-NEXT: store %"struct.X::C"* %[[C]], %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[CONTAINER:.+]] = load %"struct.X::C"*, %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[BEGINCALL:.+]] = call i32 @_ZN1X1C5beginEv(%"struct.X::C"* %[[CONTAINER]]) +// CHECK-NEXT: %[[BEGINCOERCE:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[BEGIN]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[BEGINCALL]], i32* %[[BEGINCOERCE]], align 4 +// CHECK-NEXT: %[[CONTAINERAGAIN:.+]] = load %"struct.X::C"*, %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[ENDCALL:.+]] = call i32 @_ZN1X1C3endEv(%"struct.X::C"* %[[CONTAINERAGAIN]]) +// CHECK-NEXT: %[[ENDCOERCE:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[END]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[ENDCALL]], i32* %[[ENDCOERCE]], align 4 +// CHECK-NEXT: store i32 0, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONTAINERLENGTH:.+]] = call i32 @_ZN1X1C2ItmiERS1_(%"struct.X::C::It"* %[[END]], %"struct.X::C::It"* dereferenceable(4) %[[BEGIN]]) +// CHECK-NEXT: store i32 %[[CONTAINERLENGTH]], i32* %[[CILKLOOPLIMIT]], align 4 +// CHECK-NEXT: br label %[[PFORCOND:.+]] + +// CHECK: [[PFORCOND]]: +// CHECK-NEXT: br label %[[PFORDETACH:.+]] + +// CHECK: [[PFORDETACH]]: +// CHECK-NEXT: %[[INITITER:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: detach within %[[SYNCREG:.+]], label %[[DETACHED:.+]], label %[[PFORINC:.+]] + +// CHECK: [[DETACHED]]: +// CHECK-NEXT: %__local_loopindex = alloca i32, align 4 +// CHECK-NEXT: %[[X:.+]] = alloca i32*, align 8 +// CHECK-NEXT: %[[ITER:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: store i32 %[[INITITER]], i32* %__local_loopindex, align 4 +// CHECK-NEXT: %[[LOOPINDEXCOPY:.+]] = load i32, i32* %__local_loopindex, align 4 +// CHECK-NEXT: %[[ITERREF:.+]] = call i32 @_ZN1X1C2ItplEi(%"struct.X::C::It"* %[[BEGIN]], i32 %[[LOOPINDEXCOPY]]) +// CHECK-NEXT: %[[ITER2:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[ITER]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[ITERREF]], i32* %[[ITER2]], align 4 +// CHECK-NEXT: %[[ELEM:.+]] = call dereferenceable(4) i32* @_ZN1X1C2ItdeEv(%"struct.X::C::It"* %[[ITER]]) +// CHECK-NEXT: store i32* %[[ELEM]], i32** %[[X]], align 8 + +// CHECK: [[PFORINC]]: +// CHECK-NEXT: %[[INCBEGIN:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[INC:.+]] = add nsw i32 %[[INCBEGIN]], 1 +// CHECK-NEXT: store i32 %[[INC]], i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONDBEGIN:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONDEND:.+]] = load i32, i32* %[[CILKLOOPLIMIT]], align 4 +// CHECK-NEXT: %[[COND:.+]] = icmp ne i32 %[[CONDBEGIN]], %[[CONDEND]] +// CHECK-NEXT: br i1 %[[COND]], label %{{.+}}, label %[[PFORCONDCLEANUP:.+]], !llvm.loop ![[LOOPMD:.+]] + +// CHECK: [[PFORCONDCLEANUP]]: +// CHECK-NEXT: sync within %[[SYNCREG]] + +void iterate_auto(X::C c) { + _Cilk_for(auto x + : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + bar(x); +} + +// CHECK-LABEL: define void @_Z12iterate_autoN1X1CE( + +// CHECK: %[[C:.+]] = alloca %"struct.X::C", align 1 +// CHECK-NEXT: %syncreg = call token @llvm.syncregion.start() +// CHECK-NEXT: %[[RANGE:.+]] = alloca %"struct.X::C"*, align 8 +// CHECK-NEXT: %[[BEGIN:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: %[[END:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: %[[CILKLOOPINDEX:.+]] = alloca i32, align 4 +// CHECK-NEXT: %[[CILKLOOPLIMIT:.+]] = alloca i32, align 4 +// CHECK-NEXT: store %"struct.X::C"* %[[C]], %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[CONTAINER:.+]] = load %"struct.X::C"*, %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[BEGINCALL:.+]] = call i32 @_ZN1X1C5beginEv(%"struct.X::C"* %[[CONTAINER]]) +// CHECK-NEXT: %[[BEGINCOERCE:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[BEGIN]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[BEGINCALL]], i32* %[[BEGINCOERCE]], align 4 +// CHECK-NEXT: %[[CONTAINERAGAIN:.+]] = load %"struct.X::C"*, %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[ENDCALL:.+]] = call i32 @_ZN1X1C3endEv(%"struct.X::C"* %[[CONTAINERAGAIN]]) +// CHECK-NEXT: %[[ENDCOERCE:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[END]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[ENDCALL]], i32* %[[ENDCOERCE]], align 4 +// CHECK-NEXT: store i32 0, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONTAINERLENGTH:.+]] = call i32 @_ZN1X1C2ItmiERS1_(%"struct.X::C::It"* %[[END]], %"struct.X::C::It"* dereferenceable(4) %[[BEGIN]]) +// CHECK-NEXT: store i32 %[[CONTAINERLENGTH]], i32* %[[CILKLOOPLIMIT]], align 4 +// CHECK-NEXT: br label %[[PFORCOND:.+]] + +// CHECK: [[PFORCOND]]: +// CHECK-NEXT: br label %[[PFORDETACH:.+]] + +// CHECK: [[PFORDETACH]]: +// CHECK-NEXT: %[[INITITER:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: detach within %[[SYNCREG:.+]], label %[[DETACHED:.+]], label %[[PFORINC:.+]] + +// CHECK: [[DETACHED]]: +// CHECK-NEXT: %__local_loopindex = alloca i32, align 4 +// CHECK-NEXT: %[[X:.+]] = alloca i32, align 4 +// CHECK-NEXT: %[[ITER:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: store i32 %[[INITITER]], i32* %__local_loopindex, align 4 +// CHECK-NEXT: %[[LOOPINDEXCOPY:.+]] = load i32, i32* %__local_loopindex, align 4 +// CHECK-NEXT: %[[ITERREF:.+]] = call i32 @_ZN1X1C2ItplEi(%"struct.X::C::It"* %[[BEGIN]], i32 %[[LOOPINDEXCOPY]]) +// CHECK-NEXT: %[[ITER2:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[ITER]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[ITERREF]], i32* %[[ITER2]], align 4 +// CHECK-NEXT: %[[ELEM:.+]] = call dereferenceable(4) i32* @_ZN1X1C2ItdeEv(%"struct.X::C::It"* %[[ITER]]) +// CHECK-NEXT: %[[ELEMVAL:.+]] = load i32, i32* %[[ELEM]], align 4 +// CHECK-NEXT: store i32 %[[ELEMVAL]], i32* %[[X]], align 4 + +// CHECK: [[PFORINC]]: +// CHECK-NEXT: %[[INCBEGIN:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[INC:.+]] = add nsw i32 %[[INCBEGIN]], 1 +// CHECK-NEXT: store i32 %[[INC]], i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONDBEGIN:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONDEND:.+]] = load i32, i32* %[[CILKLOOPLIMIT]], align 4 +// CHECK-NEXT: %[[COND:.+]] = icmp ne i32 %[[CONDBEGIN]], %[[CONDEND]] +// CHECK-NEXT: br i1 %[[COND]], label %{{.+}}, label %[[PFORCONDCLEANUP:.+]], !llvm.loop ![[LOOPMD:.+]] + +// CHECK: [[PFORCONDCLEANUP]]: +// CHECK-NEXT: sync within %[[SYNCREG]] + +void iterate_autoref(X::C c) { + _Cilk_for(auto &x + : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + bar(x); +} + +// CHECK-LABEL: define void @_Z15iterate_autorefN1X1CE( + +// CHECK: %[[C:.+]] = alloca %"struct.X::C", align 1 +// CHECK-NEXT: %syncreg = call token @llvm.syncregion.start() +// CHECK-NEXT: %[[RANGE:.+]] = alloca %"struct.X::C"*, align 8 +// CHECK-NEXT: %[[BEGIN:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: %[[END:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: %[[CILKLOOPINDEX:.+]] = alloca i32, align 4 +// CHECK-NEXT: %[[CILKLOOPLIMIT:.+]] = alloca i32, align 4 +// CHECK-NEXT: store %"struct.X::C"* %[[C]], %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[CONTAINER:.+]] = load %"struct.X::C"*, %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[BEGINCALL:.+]] = call i32 @_ZN1X1C5beginEv(%"struct.X::C"* %[[CONTAINER]]) +// CHECK-NEXT: %[[BEGINCOERCE:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[BEGIN]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[BEGINCALL]], i32* %[[BEGINCOERCE]], align 4 +// CHECK-NEXT: %[[CONTAINERAGAIN:.+]] = load %"struct.X::C"*, %"struct.X::C"** %[[RANGE]], align 8 +// CHECK-NEXT: %[[ENDCALL:.+]] = call i32 @_ZN1X1C3endEv(%"struct.X::C"* %[[CONTAINERAGAIN]]) +// CHECK-NEXT: %[[ENDCOERCE:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[END]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[ENDCALL]], i32* %[[ENDCOERCE]], align 4 +// CHECK-NEXT: store i32 0, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONTAINERLENGTH:.+]] = call i32 @_ZN1X1C2ItmiERS1_(%"struct.X::C::It"* %[[END]], %"struct.X::C::It"* dereferenceable(4) %[[BEGIN]]) +// CHECK-NEXT: store i32 %[[CONTAINERLENGTH]], i32* %[[CILKLOOPLIMIT]], align 4 +// CHECK-NEXT: br label %[[PFORCOND:.+]] + +// CHECK: [[PFORCOND]]: +// CHECK-NEXT: br label %[[PFORDETACH:.+]] + +// CHECK: [[PFORDETACH]]: +// CHECK-NEXT: %[[INITITER:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: detach within %[[SYNCREG:.+]], label %[[DETACHED:.+]], label %[[PFORINC:.+]] + +// CHECK: [[DETACHED]]: +// CHECK-NEXT: %__local_loopindex = alloca i32, align 4 +// CHECK-NEXT: %[[X:.+]] = alloca i32*, align 8 +// CHECK-NEXT: %[[ITER:.+]] = alloca %"struct.X::C::It", align 4 +// CHECK-NEXT: store i32 %[[INITITER]], i32* %__local_loopindex, align 4 +// CHECK-NEXT: %[[LOOPINDEXCOPY:.+]] = load i32, i32* %__local_loopindex, align 4 +// CHECK-NEXT: %[[ITERREF:.+]] = call i32 @_ZN1X1C2ItplEi(%"struct.X::C::It"* %[[BEGIN]], i32 %[[LOOPINDEXCOPY]]) +// CHECK-NEXT: %[[ITER2:.+]] = getelementptr inbounds %"struct.X::C::It", %"struct.X::C::It"* %[[ITER]], i32 0, i32 0 +// CHECK-NEXT: store i32 %[[ITERREF]], i32* %[[ITER2]], align 4 +// CHECK-NEXT: %[[ELEM:.+]] = call dereferenceable(4) i32* @_ZN1X1C2ItdeEv(%"struct.X::C::It"* %[[ITER]]) +// CHECK-NEXT: store i32* %[[ELEM]], i32** %[[X]], align 8 + +// CHECK: [[PFORINC]]: +// CHECK-NEXT: %[[INCBEGIN:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[INC:.+]] = add nsw i32 %[[INCBEGIN]], 1 +// CHECK-NEXT: store i32 %[[INC]], i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONDBEGIN:.+]] = load i32, i32* %[[CILKLOOPINDEX]], align 4 +// CHECK-NEXT: %[[CONDEND:.+]] = load i32, i32* %[[CILKLOOPLIMIT]], align 4 +// CHECK-NEXT: %[[COND:.+]] = icmp ne i32 %[[CONDBEGIN]], %[[CONDEND]] +// CHECK-NEXT: br i1 %[[COND]], label %{{.+}}, label %[[PFORCONDCLEANUP:.+]], !llvm.loop ![[LOOPMD:.+]] + +// CHECK: [[PFORCONDCLEANUP]]: +// CHECK-NEXT: sync within %[[SYNCREG]] diff --git a/clang/test/Cilk/rangelooptest.cpp b/clang/test/Cilk/rangelooptest.cpp new file mode 100644 index 000000000000..8f428b096987 --- /dev/null +++ b/clang/test/Cilk/rangelooptest.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -std=c++17 -verify -verify-ignore-unexpected=note %s + +namespace StdMock { +template +struct Vector { + T *arr; + Vector(int n) { + // malloc + } + struct It { + T value; + int operator-(It &); + It operator+(int); + It operator++(); + It operator--(); + T &operator*(); + bool operator!=(It &); + }; + It begin(); + It end(); + T &operator[](int i) { + return arr[i]; + } +}; +template +struct Set { + T *set; + Set(int n) { + // malloc + } + struct It { + T value; + It operator++(); + It operator--(); + T &operator*(); + bool operator!=(It &); + }; + It begin(); + It end(); +}; +struct Empty {}; +template +struct Pair { + T first; + U second; +}; +} // namespace StdMock + +int foo(int n); + +int Cilk_for_range_tests(int n) { + StdMock::Vector v(n); + for (int i = 0; i < n; i++) + v[i] = i; + + _Cilk_for(auto x + : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(auto &x + : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int x + : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(StdMock::Empty x + : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-error {{no viable conversion from 'int' to 'StdMock::Empty'}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + + // Pairs are aggregate types, which initially had a bug. Assert that they work + StdMock::Vector> vp(n); + for (int i = 0; i < n; i++) { + vp[i] = {i, i + 1}; + } + _Cilk_for(auto p + : vp) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + continue; + _Cilk_for(auto &p + : vp) { // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + continue; + } + + int a[5]; + _Cilk_for(int x + : a) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + continue; + + StdMock::Set s(n); + _Cilk_for(int x + : s); // expected-error {{Cannot determine length with '__end - __begin'. Please use a random access iterator.}} expected-error {{invalid operands to binary expression ('StdMock::Set::It' and 'StdMock::Set::It')}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + + // Check for return statements, which cannot appear anywhere in the body of a + // _Cilk_for loop. + _Cilk_for(int i + : v) return 7; // expected-error{{cannot return}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int i + : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + for (int j = 1; j < i; ++j) return 7; // expected-error{{cannot return}} + + // Check for illegal break statements, which cannot bind to the scope of a + // _Cilk_for loop, but can bind to loops nested within. + _Cilk_for(int i + : v) break; // expected-error{{cannot break}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int i + : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + for (int j = 1; j < i; ++j) break; + + return 0; +} + +int range_pragma_tests(int n) { + StdMock::Vector v(n); + for (int i = 0; i < n; i++) + v[i] = i; + +#pragma clang loop unroll_count(4) + _Cilk_for(auto i + : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + foo(i); + +#pragma cilk grainsize(4) + _Cilk_for(int i + : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + foo(i); + +#pragma cilk grainsize 4 + _Cilk_for(auto i + : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + foo(i); + +#pragma cilk grainsize = 4 + // expected-warning{{'#pragma cilk grainsize' no longer requires '='}} + _Cilk_for(int i + : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + foo(i); + + return 0; +} + +int range_scope_tests(int n) { + StdMock::Vector v(n); + for (int i = 0; i < n; i++) + v[i] = i; + int A[5]; + _Cilk_for(int i + : v) { // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + int A[5]; + A[i % 5] = i; + } + for (int i : v) { + A[i % 5] = i % 5; + } + return 0; +} From 274e6b27a726a7d73373241dc2d8ed589fb79086 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 2 Jun 2021 10:31:30 -0400 Subject: [PATCH 63/64] undo clang format errors --- clang/test/Cilk/cilkforrange-ir.cpp | 12 ++---- clang/test/Cilk/rangelooptest.cpp | 57 +++++++++++------------------ 2 files changed, 25 insertions(+), 44 deletions(-) diff --git a/clang/test/Cilk/cilkforrange-ir.cpp b/clang/test/Cilk/cilkforrange-ir.cpp index 196128ec3d01..1f7ac22f576d 100644 --- a/clang/test/Cilk/cilkforrange-ir.cpp +++ b/clang/test/Cilk/cilkforrange-ir.cpp @@ -25,8 +25,7 @@ struct C { void bar(int i); void iterate(X::C c) { - _Cilk_for(int x - : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int x : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} bar(x); } @@ -86,8 +85,7 @@ void iterate(X::C c) { // CHECK-NEXT: sync within %[[SYNCREG]] void iterate_ref(X::C c) { - _Cilk_for(int &x - : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int &x : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} bar(x); } @@ -146,8 +144,7 @@ void iterate_ref(X::C c) { // CHECK-NEXT: sync within %[[SYNCREG]] void iterate_auto(X::C c) { - _Cilk_for(auto x - : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(auto x : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} bar(x); } @@ -207,8 +204,7 @@ void iterate_auto(X::C c) { // CHECK-NEXT: sync within %[[SYNCREG]] void iterate_autoref(X::C c) { - _Cilk_for(auto &x - : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(auto &x : c) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} bar(x); } diff --git a/clang/test/Cilk/rangelooptest.cpp b/clang/test/Cilk/rangelooptest.cpp index 8f428b096987..f0a35b08359f 100644 --- a/clang/test/Cilk/rangelooptest.cpp +++ b/clang/test/Cilk/rangelooptest.cpp @@ -53,52 +53,42 @@ int Cilk_for_range_tests(int n) { for (int i = 0; i < n; i++) v[i] = i; - _Cilk_for(auto x - : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} - _Cilk_for(auto &x - : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} - _Cilk_for(int x - : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} - _Cilk_for(StdMock::Empty x - : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-error {{no viable conversion from 'int' to 'StdMock::Empty'}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(auto x : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(auto &x : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int x : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(StdMock::Empty x : v); // expected-warning {{range-based for loop has empty body}} expected-warning {{Cilk for loop has empty body}} expected-error {{no viable conversion from 'int' to 'StdMock::Empty'}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} // Pairs are aggregate types, which initially had a bug. Assert that they work StdMock::Vector> vp(n); for (int i = 0; i < n; i++) { vp[i] = {i, i + 1}; } - _Cilk_for(auto p - : vp) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(auto p : vp) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} continue; - _Cilk_for(auto &p - : vp) { // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(auto &p : vp) { // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} continue; } int a[5]; - _Cilk_for(int x - : a) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int x : a) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} continue; StdMock::Set s(n); - _Cilk_for(int x - : s); // expected-error {{Cannot determine length with '__end - __begin'. Please use a random access iterator.}} expected-error {{invalid operands to binary expression ('StdMock::Set::It' and 'StdMock::Set::It')}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int x : s); // expected-error {{Cannot determine length with '__end - __begin'. Please use a random access iterator.}} expected-error {{invalid operands to binary expression ('StdMock::Set::It' and 'StdMock::Set::It')}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} // Check for return statements, which cannot appear anywhere in the body of a // _Cilk_for loop. - _Cilk_for(int i - : v) return 7; // expected-error{{cannot return}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} - _Cilk_for(int i - : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} - for (int j = 1; j < i; ++j) return 7; // expected-error{{cannot return}} + _Cilk_for(int i : v) return 7; // expected-error{{cannot return}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int i : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + for (int j = 1; j < i; ++j) + return 7; // expected-error{{cannot return}} // Check for illegal break statements, which cannot bind to the scope of a // _Cilk_for loop, but can bind to loops nested within. - _Cilk_for(int i - : v) break; // expected-error{{cannot break}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} - _Cilk_for(int i - : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} - for (int j = 1; j < i; ++j) break; + _Cilk_for(int i : v) break; // expected-error{{cannot break}} expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int i : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + for (int j = 1; j < i; ++j) + break; return 0; } @@ -109,24 +99,20 @@ int range_pragma_tests(int n) { v[i] = i; #pragma clang loop unroll_count(4) - _Cilk_for(auto i - : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(auto i : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} foo(i); #pragma cilk grainsize(4) - _Cilk_for(int i - : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int i : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} foo(i); #pragma cilk grainsize 4 - _Cilk_for(auto i - : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(auto i : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} foo(i); #pragma cilk grainsize = 4 // expected-warning{{'#pragma cilk grainsize' no longer requires '='}} - _Cilk_for(int i - : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int i : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} foo(i); return 0; @@ -137,8 +123,7 @@ int range_scope_tests(int n) { for (int i = 0; i < n; i++) v[i] = i; int A[5]; - _Cilk_for(int i - : v) { // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} + _Cilk_for(int i : v) { // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} int A[5]; A[i % 5] = i; } From 87ce260a89bb7827f7899e160b13a54caf0eb3a3 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Wed, 2 Jun 2021 10:35:27 -0400 Subject: [PATCH 64/64] more cleanup from clang format --- clang/test/Cilk/rangelooptest.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/test/Cilk/rangelooptest.cpp b/clang/test/Cilk/rangelooptest.cpp index f0a35b08359f..17d0fd11bdb7 100644 --- a/clang/test/Cilk/rangelooptest.cpp +++ b/clang/test/Cilk/rangelooptest.cpp @@ -110,8 +110,7 @@ int range_pragma_tests(int n) { _Cilk_for(auto i : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} foo(i); -#pragma cilk grainsize = 4 - // expected-warning{{'#pragma cilk grainsize' no longer requires '='}} +#pragma cilk grainsize = 4 // expected-warning{{'#pragma cilk grainsize' no longer requires '='}} _Cilk_for(int i : v) // expected-warning {{'_Cilk_for' support for for-range loops is currently EXPERIMENTAL only!}} foo(i);