Skip to content

Commit c0fc5be

Browse files
authored
[Flang][OpenMP] Fix to resolve the crash with SIMD aligned clause. (llvm#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 llvm#149458
1 parent 7bf92f2 commit c0fc5be

File tree

6 files changed

+60
-5
lines changed

6 files changed

+60
-5
lines changed

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -648,10 +648,8 @@ addAlignedClause(lower::AbstractConverter &converter,
648648

649649
// The default alignment for some targets is equal to 0.
650650
// Do not generate alignment assumption if alignment is less than or equal to
651-
// 0.
652-
if (alignment > 0) {
653-
// alignment value must be power of 2
654-
assert((alignment & (alignment - 1)) == 0 && "alignment is not power of 2");
651+
// 0 or not a power of two
652+
if (alignment > 0 && ((alignment & (alignment - 1)) == 0)) {
655653
auto &objects = std::get<omp::ObjectList>(clause.t);
656654
if (!objects.empty())
657655
genObjectList(objects, converter, alignedVars);

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3489,9 +3489,14 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) {
34893489
x.v, llvm::omp::OMPC_aligned, GetContext().clauseSource, context_)) {
34903490
auto &modifiers{OmpGetModifiers(x.v)};
34913491
if (auto *align{OmpGetUniqueModifier<parser::OmpAlignment>(modifiers)}) {
3492-
if (const auto &v{GetIntValue(align->v)}; !v || *v <= 0) {
3492+
const auto &v{GetIntValue(align->v)};
3493+
if (!v || *v <= 0) {
34933494
context_.Say(OmpGetModifierSource(modifiers, align),
34943495
"The alignment value should be a constant positive integer"_err_en_US);
3496+
} else if (((*v) & (*v - 1)) != 0) {
3497+
context_.Warn(common::UsageWarning::OpenMPUsage,
3498+
OmpGetModifierSource(modifiers, align),
3499+
"Alignment is not a power of 2, Aligned clause will be ignored"_warn_en_US);
34953500
}
34963501
}
34973502
}

flang/test/Lower/OpenMP/simd.f90

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,23 @@ subroutine simdloop_aligned_allocatable()
226226
end do
227227
end subroutine
228228

229+
subroutine aligned_non_power_of_two()
230+
integer :: i
231+
integer, allocatable :: A(:)
232+
allocate(A(10))
233+
!CHECK: %[[A_PTR:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "a",
234+
!CHECK-SAME: uniq_name = "_QFaligned_non_power_of_twoEa"}
235+
!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_PTR]] {fortran_attrs = #fir.var_attrs<allocatable>,
236+
!CHECK-SAME: uniq_name = "_QFaligned_non_power_of_twoEa"} :
237+
!CHECK-SAME: (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) ->
238+
!CHECK-SAME: (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
239+
!CHECK: omp.simd private
240+
!$OMP SIMD ALIGNED(A:257)
241+
do i = 1, 10
242+
A(i) = i
243+
end do
244+
end subroutine
245+
229246
!CHECK-LABEL: func @_QPsimd_with_nontemporal_clause
230247
subroutine simd_with_nontemporal_clause(n)
231248
!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFsimd_with_nontemporal_clauseEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)

flang/test/Semantics/OpenMP/simd-aligned.f90

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,16 @@ program omp_simd
6060
!$omp end simd
6161

6262
!ERROR: 'd' in ALIGNED clause must be of type C_PTR, POINTER or ALLOCATABLE
63+
!WARNING: Alignment is not a power of 2, Aligned clause will be ignored [-Wopen-mp-usage]
6364
!$omp simd aligned(d:100)
6465
do i = 1, 100
6566
d(i) = i
6667
end do
6768

69+
!WARNING: Alignment is not a power of 2, Aligned clause will be ignored [-Wopen-mp-usage]
70+
!$omp simd aligned(b:65)
71+
do i = 1, 100
72+
b(i) = i
73+
end do
74+
6875
end program omp_simd

mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2893,6 +2893,12 @@ convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder,
28932893
alignment = builder.getInt64(intAttr.getInt());
28942894
assert(ty->isPointerTy() && "Invalid type for aligned variable");
28952895
assert(alignment && "Invalid alignment value");
2896+
2897+
// Check if the alignment value is not a power of 2. If so, skip emitting
2898+
// alignment.
2899+
if (!intAttr.getValue().isPowerOf2())
2900+
continue;
2901+
28962902
auto curInsert = builder.saveIP();
28972903
builder.SetInsertPoint(sourceBlock);
28982904
llvmVal = builder.CreateLoad(ty, llvmVal);

mlir/test/Target/LLVMIR/openmp-simd-aligned.mlir

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,25 @@ llvm.func @_QPsimd_aligned_allocatable() {
5858
}
5959
llvm.return
6060
}
61+
62+
//CHECK-LABEL: define void @_QPsimd_aligned_non_power_of_two() {
63+
//CHECK: %[[A_ADDR:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, i64 1, align 8
64+
//CHECK: %[[B_ADDR:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, i64 1, align 8
65+
//CHECK: %[[LOAD_B:.*]] = load ptr, ptr %[[B_ADDR]], align 8
66+
//CHECK: call void @llvm.assume(i1 true) [ "align"(ptr %[[LOAD_B]], i64 64) ]
67+
//CHECK-NOT: call void @llvm.assume(i1 true) [ "align"(ptr %{{.*}}, i64 257) ]
68+
llvm.func @_QPsimd_aligned_non_power_of_two() {
69+
%0 = llvm.mlir.constant(1 : i64) : i64
70+
%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
71+
%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
72+
%3 = llvm.mlir.constant(1 : i32) : i32
73+
%4 = llvm.mlir.constant(10 : i32) : i32
74+
%5 = llvm.mlir.constant(1 : i32) : i32
75+
omp.simd aligned(%1 : !llvm.ptr -> 257 : i64, %2 : !llvm.ptr -> 64 : i64) {
76+
omp.loop_nest (%arg0) : i32 = (%3) to (%4) inclusive step (%5) {
77+
omp.yield
78+
}
79+
}
80+
llvm.return
81+
}
82+

0 commit comments

Comments
 (0)