================
@@ -14983,35 +14985,118 @@ StmtResult 
SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
       FloorIndVars[I] = FloorCntDecl;
     }
 
-    // Iteration variable for the tile (i.e. inner) loop.
+    // Logical iteration variable for the tile loop. Retains the meaning of
+    // the original logical iteration number (floor_iv + tile_cnt) so that
+    // LoopHelper.Updates can derive the original loop variable unchanged.
     {
-      std::string TileCntName =
+      std::string TileIVName =
           (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
 
-      // Reuse the iteration variable created by checkOpenMPLoop. It is also
-      // used by the expressions to derive the original iteration variable's
-      // value from the logical iteration number.
-      auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
-      TileCntDecl->setDeclName(
-          &SemaRef.PP.getIdentifierTable().get(TileCntName));
-      TileIndVars[I] = TileCntDecl;
+      auto *TileIVDecl = cast<VarDecl>(IterVarRef->getDecl());
+      
TileIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(TileIVName));
+      TileIndVars[I] = TileIVDecl;
+    }
+
+    // Loop counter for the rectangular tile loop [0, TileSize).
+    {
+      std::string TileCntName =
+          (Twine(".tile.cnt.") + llvm::utostr(I) + ".iv." + OrigVarName).str();
+      VarDecl *TileCntDecl =
+          buildVarDecl(SemaRef, {}, CntTy, TileCntName, nullptr, OrigCntVar);
+      TileCntVars[I] = TileCntDecl;
     }
 
     addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
                     PreInits);
+
+    // Declare the logical tile IV in PreInits so it is in scope for the
+    // entire loop nest (it will be assigned in each tile loop body).
+    {
+      Decl *TileIVDeclPtr = TileIndVars[I];
+      PreInits.push_back(new (Context) DeclStmt(
+          DeclGroupRef::Create(Context, &TileIVDeclPtr, 1), {}, {}));
+    }
   }
 
   // Once the original iteration values are set, append the innermost body.
   Stmt *Inner = Body;
 
+  // Build a combined validity predicate that guards the innermost body.
+  // For each tiled dimension, check that the logical iteration number
+  // (.tile.iv) is within the original trip count. This is required because the
+  // tile loop now has rectangular (constant) bounds and may overshoot on the
+  // remainder tile. The predicate is: .tile.iv.0 < N0 && .tile.iv.1 < N1 ...
+  //
+  // Optimization: if every dimension's trip count is a compile-time constant
+  // that is evenly divisible by the corresponding tile size (also a constant),
+  // then the remainder tile is empty and the predicate is trivially true.
+  //
+  bool PredicateNeeded = false;
+  for (unsigned I = 0; I < NumLoops; ++I) {
+    Expr *TSExpr = SizesClause->getSizesRefs()[I];
+    Expr *NExpr = LoopHelpers[I].NumIterations;
+    Expr::EvalResult TSResult;
+    Expr::EvalResult NResult;
+    if (TSExpr->EvaluateAsInt(TSResult, Context) &&
+        NExpr->EvaluateAsInt(NResult, Context)) {
+      llvm::APSInt TileVal = TSResult.Val.getInt();
+      llvm::APSInt TripVal = NResult.Val.getInt();
+      if (TileVal.isStrictlyPositive() && TripVal.srem(TileVal).isZero())
+        continue;
+    }
+    PredicateNeeded = true;
+    break;
+  }
+
+  if (PredicateNeeded) {
+    Expr *CombinedPred = nullptr;
+    for (unsigned I = 0; I < NumLoops; ++I) {
+      auto *OrigCntVar = cast<DeclRefExpr>(LoopHelpers[I].Counters[0]);
+      QualType IVTy = LoopHelpers[I].NumIterations->getType();
+      Expr *FloorRef = buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
+                                        OrigCntVar->getExprLoc());
+      Expr *TileCntRef = buildDeclRefExpr(SemaRef, TileCntVars[I], IVTy,
+                                          OrigCntVar->getExprLoc());
+      ExprResult Sum = SemaRef.BuildBinOp(CurScope, OrigCntVar->getExprLoc(),
+                                          BO_Add, FloorRef, TileCntRef);
+      if (!Sum.isUsable())
+        return StmtError();
+      ExprResult DimPred =
+          SemaRef.BuildBinOp(CurScope, OrigCntVar->getExprLoc(), BO_LT,
+                             Sum.get(), LoopHelpers[I].NumIterations);
+      if (!DimPred.isUsable())
+        return StmtError();
+      if (CombinedPred) {
+        ExprResult Combined =
+            SemaRef.BuildBinOp(CurScope, OrigCntVar->getExprLoc(), BO_LAnd,
+                               CombinedPred, DimPred.get());
+        if (!Combined.isUsable())
+          return StmtError();
+        CombinedPred = Combined.get();
+      } else {
+        CombinedPred = DimPred.get();
+      }
+    }
+    // Use the source body's location for the synthetic if-statement and
+    // AttributedStmt so any later diagnostic points at the original body
+    // location.
+    SourceLocation SyntheticLoc =
+        Body ? Body->getBeginLoc() : Inner->getBeginLoc();
+    Stmt *PredIf = IfStmt::Create(
+        Context, SyntheticLoc, IfStatementKind::Ordinary, nullptr, nullptr,
----------------
Meinersbur wrote:

```suggestion
        Context, SyntheticLoc, IfStatementKind::Ordinary, /*Init=*/ nullptr, 
/*varDecl=*/ nullptr,
```

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

Reply via email to