llvm-project/mlir/test/Target/LLVMIR/openmp-taskloop-no-context-struct.mlir
Jameson Nash 82593722f5
[OMPIRBuilder] Replace getAllocatedType with getAllocationSize (#181844)
Replace size queries using getTypeStoreSize(getAllocatedType()) with
getAllocationSize(DL) in createTaskloop, createTask, emitTargetTask, and
emitTargetTaskProxyFunction. For GEP type arguments in
emitNonContiguousDescriptor and emitOffloadingArrays, use the local
ArrayTy/PointerArrayType variables already in scope instead of
re-querying the alloca.

The store size of a struct is the same as the allocation size, so this
part should be NFC, and removes unnecessary uses of getAllocatedType, in
pursuit of the eventual deprecation of the getAllocatedType interface.

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-24 16:00:22 -05:00

114 lines
7.1 KiB
MLIR

// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
// Regression check for a taskloop with private variables but none of the
// private variables go into the context struct.
omp.private {type = private} @_QFtestEi_private_i32 : i32
omp.private {type = private} @_QFtestEt2_private_i32 : i32
omp.private {type = private} @_QFtestEt1_private_i32 : i32
llvm.func @_QPtest() {
%0 = llvm.mlir.constant(1 : i32) : i32
%1 = llvm.mlir.constant(20 : i32) : i32
%2 = llvm.mlir.constant(1 : i64) : i64
%3 = llvm.alloca %2 x i32 {bindc_name = "t2"} : (i64) -> !llvm.ptr
%4 = llvm.alloca %2 x i32 {bindc_name = "t1"} : (i64) -> !llvm.ptr
%5 = llvm.alloca %2 x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr
omp.taskloop private(@_QFtestEt1_private_i32 %4 -> %arg0, @_QFtestEt2_private_i32 %3 -> %arg1, @_QFtestEi_private_i32 %5 -> %arg2 : !llvm.ptr, !llvm.ptr, !llvm.ptr) {
omp.loop_nest (%arg3) : i32 = (%0) to (%1) inclusive step (%0) {
llvm.store %arg3, %arg2 : i32, !llvm.ptr
omp.yield
}
}
llvm.return
}
// CHECK-LABEL: define void @_QPtest() {
// No task context structure:
// CHECK: %[[STRUCTARG:.*]] = alloca { i64, i64, i64 }, align 8
// CHECK: %[[VAL_0:.*]] = alloca i32, i64 1, align 4
// CHECK: %[[VAL_1:.*]] = alloca i32, i64 1, align 4
// CHECK: %[[VAL_2:.*]] = alloca i32, i64 1, align 4
// CHECK: br label %[[VAL_3:.*]]
// CHECK: entry: ; preds = %[[VAL_4:.*]]
// CHECK: br label %[[VAL_5:.*]]
// CHECK: omp.private.init: ; preds = %[[VAL_3]]
// CHECK: br label %[[VAL_7:.*]]
// CHECK: omp.private.copy: ; preds = %[[VAL_5]]
// CHECK: br label %[[VAL_8:.*]]
// CHECK: omp.taskloop.start: ; preds = %[[VAL_7]]
// CHECK: br label %[[VAL_9:.*]]
// CHECK: codeRepl: ; preds = %[[VAL_8]]
// CHECK: %[[VAL_10:.*]] = getelementptr { i64, i64, i64 }, ptr %[[STRUCTARG]], i32 0, i32 0
// CHECK: store i64 1, ptr %[[VAL_10]], align 4
// CHECK: %[[VAL_11:.*]] = getelementptr { i64, i64, i64 }, ptr %[[STRUCTARG]], i32 0, i32 1
// CHECK: store i64 20, ptr %[[VAL_11]], align 4
// CHECK: %[[VAL_12:.*]] = getelementptr { i64, i64, i64 }, ptr %[[STRUCTARG]], i32 0, i32 2
// CHECK: store i64 1, ptr %[[VAL_12]], align 4
// CHECK: %[[VAL_14:.*]] = call i32 @__kmpc_global_thread_num(ptr @1)
// CHECK: call void @__kmpc_taskgroup(ptr @1, i32 %[[VAL_14]])
// CHECK: %[[VAL_15:.*]] = call ptr @__kmpc_omp_task_alloc(ptr @1, i32 %[[VAL_14]], i32 1, i64 40, i64 24, ptr @_QPtest..omp_par)
// CHECK: %[[VAL_16:.*]] = load ptr, ptr %[[VAL_15]], align 8
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[VAL_16]], ptr align 1 %[[STRUCTARG]], i64 24, i1 false)
// CHECK: %[[VAL_17:.*]] = getelementptr { i64, i64, i64, ptr }, ptr %[[VAL_16]], i32 0, i32 0
// CHECK: %[[VAL_18:.*]] = getelementptr { i64, i64, i64, ptr }, ptr %[[VAL_16]], i32 0, i32 1
// CHECK: %[[VAL_19:.*]] = getelementptr { i64, i64, i64, ptr }, ptr %[[VAL_16]], i32 0, i32 2
// CHECK-NOT: %[[VAL_INVALID:.*]] = getelementptr { i64, i64, i64, ptr }, ptr %[[VAL_16]], i32 0, i32 3
// CHECK: %[[VAL_20:.*]] = load i64, ptr %[[VAL_19]], align 4
// CHECK: call void @__kmpc_taskloop(ptr @1, i32 %[[VAL_14]], ptr %[[VAL_15]], i32 1, ptr %[[VAL_17]], ptr %[[VAL_18]], i64 %[[VAL_20]], i32 1, i32 0, i64 0, ptr null)
// CHECK: call void @__kmpc_end_taskgroup(ptr @1, i32 %[[VAL_14]])
// CHECK: br label %[[VAL_21:.*]]
// CHECK: taskloop.exit: ; preds = %[[VAL_9]]
// CHECK: ret void
// CHECK-LABEL: define internal void @_QPtest..omp_par
// CHECK: taskloop.alloca:
// CHECK: %[[VAL_22:.*]] = load ptr, ptr %[[VAL_23:.*]], align 8
// CHECK: %[[VAL_24:.*]] = getelementptr { i64, i64, i64 }, ptr %[[VAL_22]], i32 0, i32 0
// CHECK: %[[VAL_25:.*]] = load i64, ptr %[[VAL_24]], align 4
// CHECK: %[[VAL_26:.*]] = getelementptr { i64, i64, i64 }, ptr %[[VAL_22]], i32 0, i32 1
// CHECK: %[[VAL_27:.*]] = load i64, ptr %[[VAL_26]], align 4
// CHECK: %[[VAL_28:.*]] = getelementptr { i64, i64, i64 }, ptr %[[VAL_22]], i32 0, i32 2
// CHECK: %[[VAL_29:.*]] = load i64, ptr %[[VAL_28]], align 4
// CHECK: %[[VAL_32:.*]] = alloca i32, align 4
// CHECK: %[[VAL_33:.*]] = alloca i32, align 4
// CHECK: %[[VAL_34:.*]] = alloca i32, align 4
// CHECK: br label %[[VAL_35:.*]]
// CHECK: taskloop.body: ; preds = %[[VAL_36:.*]]
// CHECK: br label %[[VAL_37:.*]]
// CHECK: omp.taskloop.region: ; preds = %[[VAL_35]]
// CHECK: br label %[[VAL_38:.*]]
// CHECK: omp_loop.preheader: ; preds = %[[VAL_37]]
// CHECK: %[[VAL_39:.*]] = sub i64 %[[VAL_27]], %[[VAL_25]]
// CHECK: %[[VAL_40:.*]] = sdiv i64 %[[VAL_39]], 1
// CHECK: %[[VAL_41:.*]] = add i64 %[[VAL_40]], 1
// CHECK: %[[VAL_42:.*]] = trunc i64 %[[VAL_41]] to i32
// CHECK: %[[VAL_43:.*]] = trunc i64 %[[VAL_25]] to i32
// CHECK: br label %[[VAL_44:.*]]
// CHECK: omp_loop.header: ; preds = %[[VAL_45:.*]], %[[VAL_38]]
// CHECK: %[[VAL_46:.*]] = phi i32 [ 0, %[[VAL_38]] ], [ %[[VAL_47:.*]], %[[VAL_45]] ]
// CHECK: br label %[[VAL_48:.*]]
// CHECK: omp_loop.cond: ; preds = %[[VAL_44]]
// CHECK: %[[VAL_49:.*]] = icmp ult i32 %[[VAL_46]], %[[VAL_42]]
// CHECK: br i1 %[[VAL_49]], label %[[VAL_50:.*]], label %[[VAL_51:.*]]
// CHECK: omp_loop.exit: ; preds = %[[VAL_48]]
// CHECK: br label %[[VAL_52:.*]]
// CHECK: omp_loop.after: ; preds = %[[VAL_51]]
// CHECK: br label %[[VAL_53:.*]]
// CHECK: omp.region.cont: ; preds = %[[VAL_52]]
// CHECK: br label %[[VAL_54:.*]]
// CHECK: omp_loop.body: ; preds = %[[VAL_48]]
// CHECK: %[[VAL_55:.*]] = mul i32 %[[VAL_46]], 1
// CHECK: %[[VAL_56:.*]] = add i32 %[[VAL_55]], %[[VAL_43]]
// CHECK: br label %[[VAL_57:.*]]
// CHECK: omp.loop_nest.region: ; preds = %[[VAL_50]]
// CHECK: store i32 %[[VAL_56]], ptr %[[VAL_34]], align 4
// CHECK: br label %[[VAL_58:.*]]
// CHECK: omp.region.cont3: ; preds = %[[VAL_57]]
// CHECK: br label %[[VAL_45]]
// CHECK: omp_loop.inc: ; preds = %[[VAL_58]]
// CHECK: %[[VAL_47]] = add nuw i32 %[[VAL_46]], 1
// CHECK: br label %[[VAL_44]]
// CHECK: taskloop.exit.exitStub: ; preds = %[[VAL_53]]
// CHECK: ret void
// CHECK-NOT: define internal void @omp_taskloop_dup