================
@@ -15783,6 +15828,100 @@ static Expr *makeFloorIVRef(Sema &SemaRef, 
ArrayRef<VarDecl *> FloorIndVars,
                           OrigCntVar->getExprLoc());
 }
 
+/// Whether \p Counter is compiler generated (e.g. a fuse index).
+static bool isGeneratedLoopCounter(const Expr *Counter) {
+  const auto *DRE = dyn_cast<DeclRefExpr>(Counter);
+  const auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
+  return VD && VD->isImplicit() && !isa<OMPCapturedExprDecl>(VD);
+}
+
+/// Wrap \p S so it runs only if every loop in \p Loops has iterations.
+static Stmt *
+guardByLoopPreConds(ASTContext &Context,
+                    ArrayRef<OMPLoopBasedDirective::HelperExprs> Loops,
+                    Stmt *S) {
+  for (const auto &Loop : llvm::reverse(Loops))
+    S = IfStmt::Create(Context, SourceLocation(), IfStatementKind::Ordinary,
+                       nullptr, nullptr, Loop.PreCond, SourceLocation(),
+                       SourceLocation(), S, SourceLocation(), nullptr);
+  return S;
+}
+
+/// Run loop \p I's inits only if all enclosing loops have iterations.
+/// Declarations are left as is.
+static void
+guardNestedLoopInit(ASTContext &Context,
+                    ArrayRef<OMPLoopBasedDirective::HelperExprs> LoopHelpers,
+                    unsigned I, SmallVectorImpl<Stmt *> &OriginalInit) {
+  if (I == 0)
+    return;
+  for (Stmt *&Init : OriginalInit)
+    if (Init && !isa<DeclStmt>(Init))
+      Init = guardByLoopPreConds(Context, LoopHelpers.take_front(I), Init);
+}
+
+/// Build loop variable finalization statement from HelperExprs.Finals.
+/// Each Final runs only if its loop, and with \p IsLoopNest all enclosing
+/// loops, have iterations; \p NestedFinals[I] is emitted with loop I's.
+/// Returns nullptr if there is nothing to finalize.
+/// Compiler-generated counters and class-type iterators are skipped.
+static Stmt *
+buildLoopFinalization(ASTContext &Context,
+                      ArrayRef<OMPLoopBasedDirective::HelperExprs> LoopHelpers,
+                      bool IsLoopNest = false,
+                      ArrayRef<Stmt *> NestedFinals = {}) {
+  auto GetFinals = [](const OMPLoopBasedDirective::HelperExprs &Helper) {
+    SmallVector<Stmt *, 2> Finals;
+    for (auto [Counter, Final] :
+         llvm::zip_equal(Helper.Counters, Helper.Finals)) {
+      if (isGeneratedLoopCounter(Counter))
+        continue;
+      // FIXME: finalize class-type iterators too (random-access arithmetic
+      // is available per the canonical loop form).
+      QualType CounterTy = Counter->getType();
+      if (Final &&
+          (CounterTy->isArithmeticType() || CounterTy->isPointerType()))
+        Finals.push_back(Final);
+    }
+    return Finals;
+  };
+  auto MakeCompound = [&Context](ArrayRef<Stmt *> Stmts) -> Stmt * {
+    return CompoundStmt::Create(Context, Stmts, FPOptionsOverride(),
+                                SourceLocation(), SourceLocation());
+  };
+
+  auto GetNestedFinals = [&](size_t I) -> Stmt * {
+    return I < NestedFinals.size() ? NestedFinals[I] : nullptr;
+  };
+
+  if (IsLoopNest) {
+    // if (P0) { F0; if (P1) { F1; ... } }, built from the innermost loop out.
+    Stmt *Nested = nullptr;
+    for (size_t I = LoopHelpers.size(); I-- > 0;) {
+      SmallVector<Stmt *, 2> Body = GetFinals(LoopHelpers[I]);
+      if (Stmt *F = GetNestedFinals(I))
+        Body.push_back(F);
+      if (Nested)
+        Body.push_back(Nested);
+      if (Body.empty())
+        continue;
+      Nested = guardByLoopPreConds(Context, LoopHelpers[I],
+                                   Body.size() == 1 ? Body.front()
+                                                    : MakeCompound(Body));
+    }
+    return Nested;
+  }
+
+  SmallVector<Stmt *, 8> FinalizationStmts;
+  for (auto [I, Helper] : llvm::enumerate(LoopHelpers)) {
+    for (Stmt *Final : GetFinals(Helper))
+      FinalizationStmts.push_back(guardByLoopPreConds(Context, Helper, Final));
+    if (Stmt *F = GetNestedFinals(I))
+      FinalizationStmts.push_back(F);
+  }
+  return FinalizationStmts.empty() ? nullptr : MakeCompound(FinalizationStmts);
----------------
alexey-bataev wrote:

```suggestion
    // if (P0) { F0; if (P1) { F1; ... } }, built from the innermost loop out.
    Stmt *Nested = nullptr;
    for (size_t I = LoopHelpers.size(); I-- > 0;) {
      SmallVector<Stmt *, 2> Body = GetFinals(LoopHelpers[I]);
      if (Stmt *F = GetNestedFinals(I))
        Body.push_back(F);
      if (Nested)
        Body.push_back(Nested);
      if (Body.empty())
        continue;
      Nested = guardByLoopPreConds(Context, LoopHelpers[I],
                                   Body.size() == 1 ? Body.front()
                                                    : MakeCompound(Body));
    }
    return Nested;
```

https://github.com/llvm/llvm-project/pull/214717
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to