[llvm] [LoopUnroll] Enhance the use of Optimization Remarks and `LLVM_DEBUG` (PR #178476)

Ryotaro Kasuga via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 29 04:05:34 PST 2026


================
@@ -798,57 +812,127 @@ static std::optional<unsigned>
 shouldPragmaUnroll(Loop *L, const PragmaInfo &PInfo,
                    const unsigned TripMultiple, const unsigned TripCount,
                    unsigned MaxTripCount, const UnrollCostEstimator UCE,
-                   const TargetTransformInfo::UnrollingPreferences &UP) {
+                   const TargetTransformInfo::UnrollingPreferences &UP,
+                   OptimizationRemarkEmitter *ORE) {
 
   // Using unroll pragma
   // 1st priority is unroll count set by "unroll-count" option.
 
   if (PInfo.UserUnrollCount) {
     if (UP.AllowRemainder &&
-        UCE.getUnrolledLoopSize(UP, (unsigned)UnrollCount) < UP.Threshold)
+        UCE.getUnrolledLoopSize(UP, (unsigned)UnrollCount) < UP.Threshold) {
+      LLVM_DEBUG(dbgs() << "  Unrolling with user-specified count: "
+                        << UnrollCount << "\n");
       return (unsigned)UnrollCount;
+    }
+    LLVM_DEBUG(dbgs() << "  Not unrolling with user count " << UnrollCount
+                      << ": "
+                      << (!UP.AllowRemainder ? "remainder not allowed"
+                                             : "exceeds threshold")
+                      << ".\n");
   }
 
   // 2nd priority is unroll count set by pragma.
   if (PInfo.PragmaCount > 0) {
-    if ((UP.AllowRemainder || (TripMultiple % PInfo.PragmaCount == 0)))
+    if ((UP.AllowRemainder || (TripMultiple % PInfo.PragmaCount == 0))) {
+      LLVM_DEBUG(dbgs() << "  Unrolling with pragma count: "
+                        << PInfo.PragmaCount << "\n");
       return PInfo.PragmaCount;
+    }
+    LLVM_DEBUG(dbgs() << "  Not unrolling with pragma count "
+                      << PInfo.PragmaCount
+                      << ": remainder not allowed, count does not divide trip "
+                      << "multiple " << TripMultiple << ".\n");
+    ORE->emit([&]() {
+      return OptimizationRemarkMissed(DEBUG_TYPE, "PragmaUnrollCountRejected",
+                                      L->getStartLoc(), L->getHeader())
+             << "unable to unroll loop with count "
+             << ore::NV("PragmaCount", PInfo.PragmaCount)
+             << ": remainder loop is restricted and count does not divide "
+                "trip multiple "
+             << ore::NV("TripMultiple", TripMultiple);
+    });
   }
 
-  if (PInfo.PragmaFullUnroll && TripCount != 0) {
-    // Certain cases with UBSAN can cause trip count to be calculated as
-    // INT_MAX, Block full unrolling at a reasonable limit so that the compiler
-    // doesn't hang trying to unroll the loop. See PR77842
-    if (TripCount > PragmaUnrollFullMaxIterations) {
-      LLVM_DEBUG(dbgs() << "Won't unroll; trip count is too large\n");
-      return std::nullopt;
-    }
+  if (PInfo.PragmaFullUnroll) {
+    if (TripCount != 0) {
+      // Certain cases with UBSAN can cause trip count to be calculated as
+      // INT_MAX, Block full unrolling at a reasonable limit so that the
+      // compiler doesn't hang trying to unroll the loop. See PR77842
+      if (TripCount > PragmaUnrollFullMaxIterations) {
+        LLVM_DEBUG(dbgs() << "  Won't unroll; trip count is too large.\n");
+        ORE->emit([&]() {
+          return OptimizationRemarkMissed(DEBUG_TYPE,
+                                          "PragmaFullUnrollTripCountTooLarge",
+                                          L->getStartLoc(), L->getHeader())
+                 << "unable to fully unroll loop: trip count "
+                 << ore::NV("TripCount", TripCount) << " exceeds limit "
+                 << ore::NV("Limit", PragmaUnrollFullMaxIterations);
+        });
+        return std::nullopt;
+      }
 
-    return TripCount;
+      LLVM_DEBUG(dbgs() << "  Fully unrolling with trip count: " << TripCount
+                        << "\n");
+      return TripCount;
+    }
+    // Note: ORE for unknown trip count is emitted later in computeUnrollCount
+    // after we've exhausted all strategies.
+    LLVM_DEBUG(dbgs() << "  Not fully unrolling: unknown trip count.\n");
   }
 
   if (PInfo.PragmaEnableUnroll && !TripCount && MaxTripCount &&
-      MaxTripCount <= UP.MaxUpperBound)
+      MaxTripCount <= UP.MaxUpperBound) {
+    LLVM_DEBUG(dbgs() << "  Unrolling with max trip count: " << MaxTripCount
+                      << "\n");
     return MaxTripCount;
+  }
 
-  // if didn't return until here, should continue to other priorties
+  // if didn't return until here, should continue to other priorities
   return std::nullopt;
 }
 
 static std::optional<unsigned> shouldFullUnroll(
     Loop *L, const TargetTransformInfo &TTI, DominatorTree &DT,
     ScalarEvolution &SE, const SmallPtrSetImpl<const Value *> &EphValues,
     const unsigned FullUnrollTripCount, const UnrollCostEstimator UCE,
-    const TargetTransformInfo::UnrollingPreferences &UP) {
+    const TargetTransformInfo::UnrollingPreferences &UP,
+    OptimizationRemarkEmitter *ORE, bool ExplicitUnroll,
+    bool IsUpperBound = false) {
----------------
kasuga-fj wrote:

IMHO adding three arguments just for remarks/debug messages seems a bit painful. I'd prefer to define a new class to bundle these variables.

https://github.com/llvm/llvm-project/pull/178476


More information about the llvm-commits mailing list