[Mlir-commits] [mlir] c0fc5be - [Flang][OpenMP] Fix to resolve the crash with SIMD aligned clause. (#150612)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Aug 28 23:18:28 PDT 2025


Author: Kaviya Rajendiran
Date: 2025-08-29T11:48:24+05:30
New Revision: c0fc5be60fd74babaf1a0b3dd3a44eeb9f3d73dc

URL: https://github.com/llvm/llvm-project/commit/c0fc5be60fd74babaf1a0b3dd3a44eeb9f3d73dc
DIFF: https://github.com/llvm/llvm-project/commit/c0fc5be60fd74babaf1a0b3dd3a44eeb9f3d73dc.diff

LOG: [Flang][OpenMP] Fix to resolve the crash with SIMD aligned clause. (#150612)

**Issue:**
When SIMD aligned clause has a alignment value which is not a power of
2, compiler crashes with error Assertion (alignment & (alignment - 1))
== 0 && "alignment is not power of 2"

**Fix:**
According to LLVM Language Reference manual
[[link]](https://llvm.org/docs/LangRef.html#assume-opbundles), the
alignment value may be non-power-of-two. In that case, the pointer value
must be a null pointer otherwise the behavior is undefined.

So instead of emitting `llvm.assume` intrinsic function with a null
pointer having the specified alignment, modified the implementation
which ignores the aligned clause which has an alignment value which is
not a power of 2. This patch also emits a warning indicating that the aligned clause is ignored if the alignment value is not a power of two.

It fixes the issue https://github.com/llvm/llvm-project/issues/149458

Added: 
    

Modified: 
    flang/lib/Lower/OpenMP/ClauseProcessor.cpp
    flang/lib/Semantics/check-omp-structure.cpp
    flang/test/Lower/OpenMP/simd.f90
    flang/test/Semantics/OpenMP/simd-aligned.f90
    mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
    mlir/test/Target/LLVMIR/openmp-simd-aligned.mlir

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index bedcb2a267d92..6b9bd6640b393 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -648,10 +648,8 @@ addAlignedClause(lower::AbstractConverter &converter,
 
   // The default alignment for some targets is equal to 0.
   // Do not generate alignment assumption if alignment is less than or equal to
-  // 0.
-  if (alignment > 0) {
-    // alignment value must be power of 2
-    assert((alignment & (alignment - 1)) == 0 && "alignment is not power of 2");
+  // 0 or not a power of two
+  if (alignment > 0 && ((alignment & (alignment - 1)) == 0)) {
     auto &objects = std::get<omp::ObjectList>(clause.t);
     if (!objects.empty())
       genObjectList(objects, converter, alignedVars);

diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 7ca385792177a..742b58ce7e741 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3489,9 +3489,14 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) {
           x.v, llvm::omp::OMPC_aligned, GetContext().clauseSource, context_)) {
     auto &modifiers{OmpGetModifiers(x.v)};
     if (auto *align{OmpGetUniqueModifier<parser::OmpAlignment>(modifiers)}) {
-      if (const auto &v{GetIntValue(align->v)}; !v || *v <= 0) {
+      const auto &v{GetIntValue(align->v)};
+      if (!v || *v <= 0) {
         context_.Say(OmpGetModifierSource(modifiers, align),
             "The alignment value should be a constant positive integer"_err_en_US);
+      } else if (((*v) & (*v - 1)) != 0) {
+        context_.Warn(common::UsageWarning::OpenMPUsage,
+            OmpGetModifierSource(modifiers, align),
+            "Alignment is not a power of 2, Aligned clause will be ignored"_warn_en_US);
       }
     }
   }

diff  --git a/flang/test/Lower/OpenMP/simd.f90 b/flang/test/Lower/OpenMP/simd.f90
index d815474b84b31..7655c786573e3 100644
--- a/flang/test/Lower/OpenMP/simd.f90
+++ b/flang/test/Lower/OpenMP/simd.f90
@@ -226,6 +226,23 @@ subroutine simdloop_aligned_allocatable()
   end do
 end subroutine
 
+subroutine aligned_non_power_of_two()
+  integer :: i
+  integer, allocatable :: A(:)
+  allocate(A(10))
+!CHECK: %[[A_PTR:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "a",
+!CHECK-SAME: uniq_name = "_QFaligned_non_power_of_twoEa"}
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_PTR]] {fortran_attrs = #fir.var_attrs<allocatable>,
+!CHECK-SAME: uniq_name = "_QFaligned_non_power_of_twoEa"} :
+!CHECK-SAME: (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) ->
+!CHECK-SAME: (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
+!CHECK: omp.simd private
+  !$OMP SIMD ALIGNED(A:257)
+  do i = 1, 10
+    A(i) = i
+  end do
+end subroutine
+
 !CHECK-LABEL: func @_QPsimd_with_nontemporal_clause
 subroutine simd_with_nontemporal_clause(n)
   !CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFsimd_with_nontemporal_clauseEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)

diff  --git a/flang/test/Semantics/OpenMP/simd-aligned.f90 b/flang/test/Semantics/OpenMP/simd-aligned.f90
index 0a9f95833e22e..4c410a7c4631b 100644
--- a/flang/test/Semantics/OpenMP/simd-aligned.f90
+++ b/flang/test/Semantics/OpenMP/simd-aligned.f90
@@ -60,9 +60,16 @@ program omp_simd
   !$omp end simd
 
   !ERROR: 'd' in ALIGNED clause must be of type C_PTR, POINTER or ALLOCATABLE
+  !WARNING: Alignment is not a power of 2, Aligned clause will be ignored [-Wopen-mp-usage]
   !$omp simd aligned(d:100)
   do i = 1, 100
     d(i) = i
   end do
 
+  !WARNING: Alignment is not a power of 2, Aligned clause will be ignored [-Wopen-mp-usage]
+  !$omp simd aligned(b:65)
+  do i = 1, 100
+    b(i) = i
+  end do
+
 end program omp_simd

diff  --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 6694de8383534..769065cef6f5c 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -2893,6 +2893,12 @@ convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder,
     alignment = builder.getInt64(intAttr.getInt());
     assert(ty->isPointerTy() && "Invalid type for aligned variable");
     assert(alignment && "Invalid alignment value");
+
+    // Check if the alignment value is not a power of 2. If so, skip emitting
+    // alignment.
+    if (!intAttr.getValue().isPowerOf2())
+      continue;
+
     auto curInsert = builder.saveIP();
     builder.SetInsertPoint(sourceBlock);
     llvmVal = builder.CreateLoad(ty, llvmVal);

diff  --git a/mlir/test/Target/LLVMIR/openmp-simd-aligned.mlir b/mlir/test/Target/LLVMIR/openmp-simd-aligned.mlir
index 234604e4b664a..902548cb31d20 100644
--- a/mlir/test/Target/LLVMIR/openmp-simd-aligned.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-simd-aligned.mlir
@@ -58,3 +58,25 @@ llvm.func @_QPsimd_aligned_allocatable() {
   }
   llvm.return
 }
+
+//CHECK-LABEL: define void @_QPsimd_aligned_non_power_of_two() {
+//CHECK:   %[[A_ADDR:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, i64 1, align 8
+//CHECK:   %[[B_ADDR:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, i64 1, align 8
+//CHECK:   %[[LOAD_B:.*]] = load ptr, ptr %[[B_ADDR]], align 8
+//CHECK:   call void @llvm.assume(i1 true) [ "align"(ptr %[[LOAD_B]], i64 64) ]
+//CHECK-NOT:   call void @llvm.assume(i1 true) [ "align"(ptr %{{.*}}, i64 257) ]
+llvm.func @_QPsimd_aligned_non_power_of_two() {
+  %0 = llvm.mlir.constant(1 : i64) : i64
+  %1 = llvm.alloca %0 x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> {bindc_name = "a"} : (i64) -> !llvm.ptr
+  %2 = llvm.alloca %0 x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> {bindc_name = "b"} : (i64) -> !llvm.ptr
+  %3 = llvm.mlir.constant(1 : i32) : i32
+  %4 = llvm.mlir.constant(10 : i32) : i32
+  %5 = llvm.mlir.constant(1 : i32) : i32
+  omp.simd aligned(%1 : !llvm.ptr -> 257 : i64, %2 : !llvm.ptr -> 64 : i64) {
+    omp.loop_nest (%arg0) : i32 = (%3) to (%4) inclusive step (%5) {
+      omp.yield
+    }
+  }
+  llvm.return
+}
+


        


More information about the Mlir-commits mailing list