[Mlir-commits] [mlir] [mlir][OpenMP] Fix update of linear iteration variables (PR #183800)

Leandro Lupori llvmlistbot at llvm.org
Wed Mar 4 06:53:09 PST 2026


https://github.com/luporl updated https://github.com/llvm/llvm-project/pull/183800

>From e91b2f1f77cad46ec09fdce193657200a79c9c16 Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Fri, 27 Feb 2026 15:32:58 -0300
Subject: [PATCH] [mlir][OpenMP] Fix update of linear iteration variables

The final value of a linear iteration variable must be the loop
limit_value + step. Before this patch it was limit_value.

This fixes the second issue reported in #170784.

TODO add a new test and adapt the failing MLIR tests.
---
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      | 129 ++++++++++++------
 1 file changed, 91 insertions(+), 38 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 571575762d54a..389fe57f477fe 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -143,6 +143,37 @@ class LinearClauseProcessor {
   llvm::BasicBlock *linearFinalizationBB;
   llvm::BasicBlock *linearExitBB;
   llvm::BasicBlock *linearLastIterExitBB;
+  Value linearLoopIV;
+  Value linearLoopIVStart;
+
+  void updateLinearVar(llvm::IRBuilderBase &builder, llvm::Type *varType,
+                       llvm::Value *var, llvm::Value *varStart,
+                       llvm::Value *step, llvm::Value *iv) {
+    if (!iv->getType()->isIntegerTy())
+      llvm_unreachable("OpenMP loop induction variable must be an integer "
+                       "type");
+
+    if (varType->isIntegerTy()) {
+      // Integer path: normalize all arithmetic to linearVarType
+      iv = builder.CreateSExtOrTrunc(iv, varType);
+      step = builder.CreateSExtOrTrunc(step, varType);
+
+      llvm::Value *mulInst = builder.CreateMul(iv, step);
+      llvm::Value *addInst = builder.CreateAdd(varStart, mulInst);
+      builder.CreateStore(addInst, var);
+    } else if (varType->isFloatingPointTy()) {
+      // Float path: perform multiply in integer, then convert to float
+      step = builder.CreateSExtOrTrunc(step, iv->getType());
+
+      llvm::Value *mulInst = builder.CreateMul(iv, step);
+      llvm::Value *mulFp = builder.CreateSIToFP(mulInst, varType);
+      llvm::Value *addInst = builder.CreateFAdd(varStart, mulFp);
+      builder.CreateStore(addInst, var);
+    } else {
+      llvm_unreachable(
+          "Linear variable must be of integer or floating-point type");
+    }
+  }
 
 public:
   // Register type for the linear variables
@@ -182,46 +213,63 @@ class LinearClauseProcessor {
     }
   }
 
+  // Find linear iteration variable and save it for later updates
+  void initLinearIV(omp::SimdOp simdOp) {
+    auto loopOp = cast<omp::LoopNestOp>(simdOp.getWrappedLoop());
+    // NOTE iteration variables can only be linear in non-nested loops.
+    if (loopOp.getIVs().size() != 1)
+      return;
+    // The linear IV is the loop IV's store address.
+    BlockArgument arg = loopOp.getIVs().front();
+    for (const Operation *user : arg.getUsers()) {
+      if (auto storeOp = dyn_cast<LLVM::StoreOp>(user)) {
+        for (Value linearVar : simdOp.getLinearVars()) {
+          if (linearVar == storeOp.getAddr()) {
+            linearLoopIV = linearVar;
+            linearLoopIVStart = loopOp.getLoopLowerBounds().front();
+            break;
+          }
+        }
+      }
+    }
+  }
+
   // Emit IR for updating Linear variables
-  void updateLinearVar(llvm::IRBuilderBase &builder, llvm::BasicBlock *loopBody,
-                       llvm::Value *loopInductionVar) {
+  void updateLinearVars(llvm::IRBuilderBase &builder,
+                        llvm::BasicBlock *loopBody,
+                        llvm::Value *loopInductionVar) {
     builder.SetInsertPoint(loopBody->getTerminator());
     for (size_t index = 0; index < linearPreconditionVars.size(); index++) {
-      llvm::Type *linearVarType = linearVarTypes[index];
-      llvm::Value *iv = loopInductionVar;
-      llvm::Value *step = linearSteps[index];
-
-      if (!iv->getType()->isIntegerTy())
-        llvm_unreachable("OpenMP loop induction variable must be an integer "
-                         "type");
-
-      if (linearVarType->isIntegerTy()) {
-        // Integer path: normalize all arithmetic to linearVarType
-        iv = builder.CreateSExtOrTrunc(iv, linearVarType);
-        step = builder.CreateSExtOrTrunc(step, linearVarType);
-
-        llvm::LoadInst *linearVarStart =
-            builder.CreateLoad(linearVarType, linearPreconditionVars[index]);
-        llvm::Value *mulInst = builder.CreateMul(iv, step);
-        llvm::Value *addInst = builder.CreateAdd(linearVarStart, mulInst);
-        builder.CreateStore(addInst, linearLoopBodyTemps[index]);
-      } else if (linearVarType->isFloatingPointTy()) {
-        // Float path: perform multiply in integer, then convert to float
-        step = builder.CreateSExtOrTrunc(step, iv->getType());
-        llvm::Value *mulInst = builder.CreateMul(iv, step);
-
-        llvm::LoadInst *linearVarStart =
-            builder.CreateLoad(linearVarType, linearPreconditionVars[index]);
-        llvm::Value *mulFp = builder.CreateSIToFP(mulInst, linearVarType);
-        llvm::Value *addInst = builder.CreateFAdd(linearVarStart, mulFp);
-        builder.CreateStore(addInst, linearLoopBodyTemps[index]);
-      } else {
-        llvm_unreachable(
-            "Linear variable must be of integer or floating-point type");
-      }
+      llvm::LoadInst *linearVarStart = builder.CreateLoad(
+          linearVarTypes[index], linearPreconditionVars[index]);
+      updateLinearVar(builder, linearVarTypes[index],
+                      linearLoopBodyTemps[index], linearVarStart,
+                      linearSteps[index], loopInductionVar);
     }
   }
 
+  // Emit IR for updating linear iteration variables on loop exit
+  void updateLinearIV(llvm::IRBuilderBase &builder,
+                      LLVM::ModuleTranslation &moduleTranslation,
+                      llvm::Value *loopIV) {
+    if (!linearLoopIV)
+      return;
+    llvm::Value *linearIV = moduleTranslation.lookupValue(linearLoopIV);
+    llvm::Value *linearIVStart =
+        moduleTranslation.lookupValue(linearLoopIVStart);
+
+    // Find linearIV's index
+    size_t index;
+    for (index = 0; index < linearOrigVal.size(); index++)
+      if (linearIV == linearOrigVal[index])
+        break;
+    if (index == linearOrigVal.size())
+      return;
+
+    updateLinearVar(builder, linearVarTypes[index], linearLoopBodyTemps[index],
+                    linearIVStart, linearSteps[index], loopIV);
+  }
+
   // Linear variable finalization is conditional on the last logical iteration.
   // Create BB splits to manage the same.
   void splitLinearFiniBB(llvm::IRBuilderBase &builder,
@@ -3098,8 +3146,8 @@ convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder,
     if (failed(handleError(afterBarrierIP, *loopOp)))
       return failure();
     builder.restoreIP(*afterBarrierIP);
-    linearClauseProcessor.updateLinearVar(builder, loopInfo->getBody(),
-                                          loopInfo->getIndVar());
+    linearClauseProcessor.updateLinearVars(builder, loopInfo->getBody(),
+                                           loopInfo->getIndVar());
     linearClauseProcessor.splitLinearFiniBB(builder, loopInfo->getExit());
   }
 
@@ -3401,6 +3449,8 @@ convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder,
   // Initialize linear variables and linear step
   LinearClauseProcessor linearClauseProcessor;
 
+  linearClauseProcessor.initLinearIV(simdOp);
+
   if (!simdOp.getLinearVars().empty()) {
     auto linearVarTypes = simdOp.getLinearVarTypes().value();
     for (mlir::Attribute linearVarType : linearVarTypes)
@@ -3498,8 +3548,8 @@ convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder,
     linearClauseProcessor.initLinearVar(builder, moduleTranslation,
                                         loopInfo->getPreheader());
 
-    linearClauseProcessor.updateLinearVar(builder, loopInfo->getBody(),
-                                          loopInfo->getIndVar());
+    linearClauseProcessor.updateLinearVars(builder, loopInfo->getBody(),
+                                           loopInfo->getIndVar());
   }
   builder.SetInsertPoint(*regionBlock, (*regionBlock)->begin());
 
@@ -3509,6 +3559,9 @@ convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder,
                             : nullptr,
                         order, simdlen, safelen);
 
+  linearClauseProcessor.updateLinearIV(builder, moduleTranslation,
+                                       loopInfo->getIndVar());
+
   linearClauseProcessor.emitStoresForLinearVar(builder);
 
   // Check if this SIMD loop contains ordered regions



More information about the Mlir-commits mailing list