https://github.com/loopacino created 
https://github.com/llvm/llvm-project/pull/225612

`collapse` used to build both a 32-bit and a 64-bit trip-count, then keep one.

This patch does the same in `checkOpenMPLoop`:

If we know 32-bit is enough, build only 32-bit.
Else build 64-bit first.
Build 32-bit only when the product is a compile-time constant and fits.

Origin: `flatten` already builds only the width it keeps. 

>From 3a6a435bfa37bcb9676c61debc99899745a1eae3 Mon Sep 17 00:00:00 2001
From: amtiwari <[email protected]>
Date: Wed, 23 Sep 2026 02:55:31 -0400
Subject: [PATCH] optimize bit-width

---
 clang/lib/Sema/SemaOpenMP.cpp                 | 102 +++++++++---------
 .../test/OpenMP/collapse_iv_width_codegen.cpp |  52 +++++++++
 2 files changed, 105 insertions(+), 49 deletions(-)
 create mode 100644 clang/test/OpenMP/collapse_iv_width_codegen.cpp

diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 88b642b73895f..865da6f5aa0fd 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -10363,29 +10363,10 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr 
*CollapseLoopCountExpr,
   // Precondition tests if there is at least one iteration (all conditions are
   // true).
   auto PreCond = ExprResult(IterSpaces[0].PreCond);
-  Expr *N0 = IterSpaces[0].NumIterations;
-  ExprResult LastIteration32 = widenIterationCount(
-      /*Bits=*/32,
-      SemaRef
-          .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
-                                     AssignmentAction::Converting,
-                                     /*AllowExplicit=*/true)
-          .get(),
-      SemaRef);
-  ExprResult LastIteration64 = widenIterationCount(
-      /*Bits=*/64,
-      SemaRef
-          .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
-                                     AssignmentAction::Converting,
-                                     /*AllowExplicit=*/true)
-          .get(),
-      SemaRef);
-
-  if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
-    return NestedLoopCount;
-
   ASTContext &C = SemaRef.Context;
-  bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
+  unsigned FirstCountBits =
+      C.getTypeSize(IterSpaces[0].NumIterations->getType());
+  bool AllCountsNeedLessThan32Bits = FirstCountBits < 32;
 
   Scope *CurScope = DSA.getCurScope();
   for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
@@ -10395,37 +10376,63 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr 
*CollapseLoopCountExpr,
                              PreCond.get(), IterSpaces[Cnt].PreCond);
     }
     Expr *N = IterSpaces[Cnt].NumIterations;
-    SourceLocation Loc = N->getExprLoc();
     AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
-    if (LastIteration32.isUsable())
-      LastIteration32 = SemaRef.BuildBinOp(
-          CurScope, Loc, BO_Mul, LastIteration32.get(),
-          SemaRef
-              .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
-                                         AssignmentAction::Converting,
-                                         /*AllowExplicit=*/true)
-              .get());
-    if (LastIteration64.isUsable())
-      LastIteration64 = SemaRef.BuildBinOp(
-          CurScope, Loc, BO_Mul, LastIteration64.get(),
+  }
+
+  auto BuildLastIteration = [&](unsigned Bits) -> ExprResult {
+    ExprResult Result;
+    for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
+      Expr *N = IterSpaces[Cnt].NumIterations;
+      ExprResult Count = widenIterationCount(
+          Bits,
           SemaRef
               .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
                                          AssignmentAction::Converting,
                                          /*AllowExplicit=*/true)
-              .get());
-  }
+              .get(),
+          SemaRef);
+      if (!Count.isUsable())
+        return ExprError();
+      if (Cnt == 0)
+        Result = Count;
+      else
+        Result = SemaRef.BuildBinOp(CurScope, N->getExprLoc(), BO_Mul,
+                                    Result.get(), Count.get());
+      if (!Result.isUsable())
+        return ExprError();
+    }
+    return Result;
+  };
 
-  // Choose either the 32-bit or 64-bit version.
-  ExprResult LastIteration = LastIteration64;
+  // Build the 32-bit tree immediately only when it is always selected.
+  // Otherwise, build the 64-bit tree first and build the 32-bit tree only when
+  // the constant product may fit.
+  ExprResult LastIteration;
   if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
-      (LastIteration32.isUsable() &&
-       C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
-       (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
-        fitsInto(
-            /*Bits=*/32,
-            LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
-            LastIteration64.get(), SemaRef))))
-    LastIteration = LastIteration32;
+      AllCountsNeedLessThan32Bits ||
+      (NestedLoopCount == 1 && FirstCountBits == 32)) {
+    LastIteration = BuildLastIteration(/*Bits=*/32);
+  } else {
+    ExprResult LastIteration64 = BuildLastIteration(/*Bits=*/64);
+    if (!LastIteration64.isUsable())
+      return NestedLoopCount;
+    LastIteration = LastIteration64;
+    if (LastIteration64.get()->isIntegerConstantExpr(C)) {
+      ExprResult LastIteration32 = BuildLastIteration(/*Bits=*/32);
+      if (LastIteration32.isUsable() &&
+          C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
+          fitsInto(
+              /*Bits=*/32,
+              LastIteration32.get()
+                  ->getType()
+                  ->hasSignedIntegerRepresentation(),
+              LastIteration64.get(), SemaRef))
+        LastIteration = LastIteration32;
+    }
+  }
+  if (!LastIteration.isUsable())
+    return NestedLoopCount;
+
   QualType VType = LastIteration.get()->getType();
   QualType RealVType = VType;
   QualType StrideVType = VType;
@@ -10436,9 +10443,6 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr 
*CollapseLoopCountExpr,
         SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
   }
 
-  if (!LastIteration.isUsable())
-    return 0;
-
   // Save the number of iterations.
   ExprResult NumIterations = LastIteration;
   {
diff --git a/clang/test/OpenMP/collapse_iv_width_codegen.cpp 
b/clang/test/OpenMP/collapse_iv_width_codegen.cpp
new file mode 100644
index 0000000000000..3e1e5c93a4da0
--- /dev/null
+++ b/clang/test/OpenMP/collapse_iv_width_codegen.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++20 -Wno-bit-int-extension \
+// RUN:   -emit-llvm %s -o - | FileCheck %s
+
+// expected-no-diagnostics
+
+void one_i32(unsigned n) {
+#pragma omp parallel for collapse(1)
+  for (unsigned i = 0; i < n; ++i)
+    ;
+}
+
+// CHECK-LABEL: define internal void @_Z7one_i32j.omp_outlined(
+// CHECK: call void @__kmpc_for_static_init_4u(
+
+void one_i40(_BitInt(40) n) {
+#pragma omp parallel for collapse(1)
+  for (_BitInt(40) i = 0; i < n; ++i)
+    ;
+}
+
+// CHECK-LABEL: define internal void @_Z7one_i40DB40_.omp_outlined(
+// CHECK: call void @__kmpc_for_static_init_8(
+
+void dynamic_two(unsigned n, unsigned m) {
+#pragma omp parallel for collapse(2)
+  for (unsigned i = 0; i < n; ++i)
+    for (unsigned j = 0; j < m; ++j)
+      ;
+}
+
+// CHECK-LABEL: define internal void @_Z11dynamic_twojj.omp_outlined(
+// CHECK: call void @__kmpc_for_static_init_8(
+
+void fit_constant() {
+#pragma omp parallel for collapse(2)
+  for (int i = 0; i < 100; ++i)
+    for (int j = 0; j < 100; ++j)
+      ;
+}
+
+// CHECK-LABEL: define internal void @_Z12fit_constantv.omp_outlined(
+// CHECK: call void @__kmpc_for_static_init_4(
+
+void wide_constant() {
+#pragma omp parallel for collapse(2)
+  for (int i = 0; i < 100000; ++i)
+    for (int j = 0; j < 100000; ++j)
+      ;
+}
+
+// CHECK-LABEL: define internal void @_Z13wide_constantv.omp_outlined(
+// CHECK: call void @__kmpc_for_static_init_8(

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

Reply via email to