[Mlir-commits] [flang] [mlir] [mlir][OpenMP] Verify private clause operands (PR #193715)

Tom Eccles llvmlistbot at llvm.org
Thu Apr 23 04:09:55 PDT 2026


https://github.com/tblah created https://github.com/llvm/llvm-project/pull/193715

Add `verifyPrivateVarList` coverage to the OpenMP operations that support private clauses but were not validating the contents of the clause.

Keep `SectionsOp` and `SingleOp` unchanged because those operations do not fully support the private clause yet.

The flang tests started failing because the IR verifier is now stricter.

Assisted-by: Codex

>From 0fd4f196939c8c0c5063807eb672b93fa29d62b1 Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Thu, 23 Apr 2026 11:50:41 +0100
Subject: [PATCH] [mlir][OpenMP] Verify private clause operands

Add `verifyPrivateVarList` coverage to the OpenMP operations that support
private clauses but were not validating the contents of the clause.

Keep `SectionsOp` and `SingleOp` unchanged because those operations do not
fully support the private clause yet.

The flang tests started failing because the IR verifier is now stricter.

Assisted-by: Codex
---
 .../OpenMP/function-filtering-host-ops.mlir   |   5 +
 flang/test/Transforms/licm.fir                |   2 +
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  |  39 +-
 mlir/test/Dialect/OpenMP/invalid.mlir         | 437 +++++++++++++++++-
 4 files changed, 477 insertions(+), 6 deletions(-)

diff --git a/flang/test/Transforms/OpenMP/function-filtering-host-ops.mlir b/flang/test/Transforms/OpenMP/function-filtering-host-ops.mlir
index 9be258dc800d9..45a1306df122d 100644
--- a/flang/test/Transforms/OpenMP/function-filtering-host-ops.mlir
+++ b/flang/test/Transforms/OpenMP/function-filtering-host-ops.mlir
@@ -471,6 +471,11 @@ module attributes {omp.is_target_device = true} {
     return
   }
 
+  omp.private {type = firstprivate} @boxchar_firstprivatizer : !fir.boxchar<1> copy {
+  ^bb0(%arg0: !fir.boxchar<1>, %arg1: !fir.boxchar<1>):
+    omp.yield(%arg0 : !fir.boxchar<1>)
+  }
+
   // CHECK-LABEL: func.func @hlfir_storage
   func.func @hlfir_storage(%i : index) {
     // CHECK-NEXT: %[[PLACEHOLDER:.*]] = fir.alloca i1
diff --git a/flang/test/Transforms/licm.fir b/flang/test/Transforms/licm.fir
index 41626b8d49b44..5b49934a5e7ad 100644
--- a/flang/test/Transforms/licm.fir
+++ b/flang/test/Transforms/licm.fir
@@ -1332,6 +1332,7 @@ func.func @_QPtest_dummy_scalar_pointer_optional(%arg0: !fir.ref<!fir.array<?xi3
 // CHECK: omp.parallel
 // CHECK-NEXT: omp.wsloop
 // CHECK-NEXT: omp.loop_nest
+omp.private {type = private} @_QFtest_omp_loop_wrapperEi_private_i32 : i32
 func.func @_QPtest_omp_loop_wrapper(%arg0: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a"}) {
   %c10_i32 = arith.constant 10 : i32
   %c1_i32 = arith.constant 1 : i32
@@ -2405,6 +2406,7 @@ func.func @test_acc_loop_nested_canMoveOutOf(%arg0: !fir.ref<!fir.array<10xf32>>
 // CHECK-NEXT:        omp.loop_nest
 // CHECK:               scf.if
 // CHECK:                 fir.convert %[[ARG0]]
+omp.private {type = private} @_QFtestEi_private_i32 : i32
 func.func @test_omp_wsloop_nested_canMoveFromDescendant(%arg0: !fir.ref<!fir.array<10xf32>>) {
   %cst = arith.constant 1.000000e+00 : f32
   %c10_i32 = arith.constant 10 : i32
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 691793b50d33d..7acc939988b74 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2218,6 +2218,9 @@ static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars) {
   return success();
 }
 
+template <typename OpType>
+static LogicalResult verifyPrivateVarList(OpType &op);
+
 static LogicalResult verifyPrivateVarsMapping(TargetOp targetOp) {
   std::optional<DenseI64ArrayAttr> privateMapIndices =
       targetOp.getPrivateMapsAttr();
@@ -2397,6 +2400,9 @@ LogicalResult TargetOp::verify() {
   if (failed(verifyMapClause(*this, getMapVars())))
     return failure();
 
+  if (failed(verifyPrivateVarList(*this)))
+    return failure();
+
   return verifyPrivateVarsMapping(*this);
 }
 
@@ -2847,6 +2853,9 @@ LogicalResult TeamsOp::verify() {
     return emitError(
         "expected equal sizes for allocate and allocator variables");
 
+  if (failed(verifyPrivateVarList(*this)))
+    return failure();
+
   return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
                                 getReductionByref());
 }
@@ -2995,6 +3004,9 @@ void LoopOp::build(OpBuilder &builder, OperationState &state,
 }
 
 LogicalResult LoopOp::verify() {
+  if (failed(verifyPrivateVarList(*this)))
+    return failure();
+
   return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
                                 getReductionByref());
 }
@@ -3050,6 +3062,10 @@ LogicalResult WsloopOp::verify() {
   if (getLinearVars().size() &&
       getLinearVarTypes().value().size() != getLinearVars().size())
     return emitError() << "Ill-formed type attributes for linear variables";
+
+  if (failed(verifyPrivateVarList(*this)))
+    return failure();
+
   return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
                                 getReductionByref());
 }
@@ -3144,6 +3160,9 @@ LogicalResult SimdOp::verify() {
     }
   }
 
+  if (failed(verifyPrivateVarList(*this)))
+    return failure();
+
   if (getLinearVars().size() &&
       getLinearVarTypes().value().size() != getLinearVars().size())
     return emitError() << "Ill-formed type attributes for linear variables";
@@ -3180,6 +3199,9 @@ LogicalResult DistributeOp::verify() {
     return emitError(
         "expected equal sizes for allocate and allocator variables");
 
+  if (failed(verifyPrivateVarList(*this)))
+    return failure();
+
   return success();
 }
 
@@ -3334,11 +3356,14 @@ LogicalResult TaskOp::verify() {
   LogicalResult verifyDependVars =
       verifyDependVarList(*this, getDependKinds(), getDependVars(),
                           getDependIteratedKinds(), getDependIterated());
-  return failed(verifyDependVars)
-             ? verifyDependVars
-             : verifyReductionVarList(*this, getInReductionSyms(),
-                                      getInReductionVars(),
-                                      getInReductionByref());
+  if (failed(verifyDependVars))
+    return verifyDependVars;
+
+  if (failed(verifyPrivateVarList(*this)))
+    return failure();
+
+  return verifyReductionVarList(*this, getInReductionSyms(),
+                                getInReductionVars(), getInReductionByref());
 }
 
 //===----------------------------------------------------------------------===//
@@ -3392,6 +3417,10 @@ LogicalResult TaskloopContextOp::verify() {
   if (getAllocateVars().size() != getAllocatorVars().size())
     return emitError(
         "expected equal sizes for allocate and allocator variables");
+
+  if (failed(verifyPrivateVarList(*this)))
+    return failure();
+
   if (failed(verifyReductionVarList(*this, getReductionSyms(),
                                     getReductionVars(), getReductionByref())) ||
       failed(verifyReductionVarList(*this, getInReductionSyms(),
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 2a7a7827ca6fa..daf80411cb65b 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -2791,6 +2791,436 @@ func.func @byref_in_private(%arg0: index) {
   return
 }
 
+// -----
+func.func @loop_undefined_privatizer(%lb : index, %ub : index, %step : index,
+                                     %arg0 : index) {
+  // expected-error @below {{failed to lookup privatizer op with symbol: '@missing.privatizer'}}
+  omp.loop private(@missing.privatizer %arg0 -> %arg1 : index) {
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }
+
+  return
+}
+
+// -----
+omp.private {type = private} @target.var1.privatizer : index init {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+func.func @target_private_type_mismatch(%arg0: index) {
+  // expected-error @below {{type mismatch between a private variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.target private(@target.var1.privatizer %arg0 -> %arg1 : index) {
+    omp.terminator
+  }
+
+  return
+}
+
+func.func @wsloop_private_count_mismatch(%lb : index, %ub : index, %step : index,
+                                         %arg0 : !llvm.ptr) {
+  // expected-error @below {{inconsistent number of private variables and privatizer op symbols, private vars: 1 vs. privatizer op symbols: 2}}
+  "omp.wsloop"(%arg0) ({
+  ^bb0(%arg1 : !llvm.ptr):
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 1, 0, 0>,
+       private_syms = [@x.privatizer, @y.privatizer]} : (!llvm.ptr) -> ()
+
+  return
+}
+
+// -----
+omp.private {type = private} @teams.private.type_mismatch.privatizer : index init {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+omp.private {type = firstprivate} @teams.firstprivate.type_mismatch.privatizer : index copy {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+func.func @teams_private_type_mismatch(%arg0: index) {
+  // expected-error @below {{type mismatch between a private variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.teams private(@teams.private.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.terminator
+  }
+  return
+}
+
+func.func @teams_firstprivate_type_mismatch(%arg0: index) {
+  // expected-error @below {{type mismatch between a firstprivate variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.teams private(@teams.firstprivate.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.terminator
+  }
+  return
+}
+
+func.func @teams_undefined_privatizer(%arg0: index) {
+  // expected-error @below {{failed to lookup privatizer op with symbol: '@missing.teams.privatizer'}}
+  omp.teams private(@missing.teams.privatizer %arg0 -> %arg1 : index) {
+    omp.terminator
+  }
+  return
+}
+
+func.func @teams_private_count_mismatch(%arg0: !llvm.ptr) {
+  // expected-error @below {{inconsistent number of private variables and privatizer op symbols, private vars: 1 vs. privatizer op symbols: 2}}
+  "omp.teams"(%arg0) ({
+  ^bb0(%arg1 : !llvm.ptr):
+    omp.terminator
+  }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 1, 0, 0>,
+       private_syms = [@x.privatizer, @y.privatizer]} : (!llvm.ptr) -> ()
+  return
+}
+
+// -----
+omp.private {type = private} @loop.private.type_mismatch.privatizer : index init {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+omp.private {type = firstprivate} @loop.firstprivate.type_mismatch.privatizer : index copy {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+func.func @loop_private_type_mismatch(%lb : index, %ub : index, %step : index,
+                                      %arg0 : index) {
+  // expected-error @below {{type mismatch between a private variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.loop private(@loop.private.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }
+
+  return
+}
+
+func.func @loop_firstprivate_type_mismatch(%lb : index, %ub : index, %step : index,
+                                           %arg0 : index) {
+  // expected-error @below {{type mismatch between a firstprivate variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.loop private(@loop.firstprivate.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }
+
+  return
+}
+
+func.func @loop_private_count_mismatch(%lb : index, %ub : index, %step : index,
+                                       %arg0 : !llvm.ptr) {
+  // expected-error @below {{inconsistent number of private variables and privatizer op symbols, private vars: 1 vs. privatizer op symbols: 2}}
+  "omp.loop"(%arg0) ({
+  ^bb0(%arg1 : !llvm.ptr):
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }) {operandSegmentSizes = array<i32: 1, 0>,
+       private_syms = [@x.privatizer, @y.privatizer]} : (!llvm.ptr) -> ()
+
+  return
+}
+
+// -----
+omp.private {type = firstprivate} @target.firstprivate.type_mismatch.privatizer : index copy {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+func.func @target_firstprivate_type_mismatch(%arg0: index) {
+  // expected-error @below {{type mismatch between a firstprivate variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.target private(@target.firstprivate.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.terminator
+  }
+
+  return
+}
+
+func.func @target_undefined_privatizer(%arg0: index) {
+  // expected-error @below {{failed to lookup privatizer op with symbol: '@missing.target.privatizer'}}
+  omp.target private(@missing.target.privatizer %arg0 -> %arg1 : index) {
+    omp.terminator
+  }
+
+  return
+}
+
+func.func @target_private_count_mismatch(%arg0: !llvm.ptr) {
+  // expected-error @below {{inconsistent number of private variables and privatizer op symbols, private vars: 1 vs. privatizer op symbols: 2}}
+  "omp.target"(%arg0) ({
+  ^bb0(%arg1 : !llvm.ptr):
+    omp.terminator
+  }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0>,
+       private_syms = [@x.privatizer, @y.privatizer]} : (!llvm.ptr) -> ()
+  return
+}
+
+// -----
+omp.private {type = private} @wsloop.private.type_mismatch.privatizer : index init {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+omp.private {type = firstprivate} @wsloop.firstprivate.type_mismatch.privatizer : index copy {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+func.func @wsloop_private_type_mismatch(%lb : index, %ub : index, %step : index,
+                                        %arg0 : index) {
+  // expected-error @below {{type mismatch between a private variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.wsloop private(@wsloop.private.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }
+
+  return
+}
+
+func.func @wsloop_firstprivate_type_mismatch(%lb : index, %ub : index, %step : index,
+                                             %arg0 : index) {
+  // expected-error @below {{type mismatch between a firstprivate variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.wsloop private(@wsloop.firstprivate.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }
+
+  return
+}
+
+func.func @wsloop_undefined_privatizer(%lb : index, %ub : index, %step : index,
+                                       %arg0 : index) {
+  // expected-error @below {{failed to lookup privatizer op with symbol: '@missing.wsloop.privatizer'}}
+  omp.wsloop private(@missing.wsloop.privatizer %arg0 -> %arg1 : index) {
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }
+
+  return
+}
+
+// -----
+omp.private {type = private} @simd.private.type_mismatch.privatizer : index init {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+omp.private {type = private} @simd.count_mismatch.x.privatizer : !llvm.ptr
+omp.private {type = private} @simd.count_mismatch.y.privatizer : !llvm.ptr
+
+func.func @simd_private_type_mismatch(%lb : index, %ub : index, %step : index,
+                                      %arg0 : index) {
+  // expected-error @below {{type mismatch between a private variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.simd private(@simd.private.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }
+
+  return
+}
+
+func.func @simd_private_count_mismatch(%lb : index, %ub : index, %step : index,
+                                       %arg0 : !llvm.ptr) {
+  // expected-error @below {{inconsistent number of private variables and privatizer op symbols, private vars: 1 vs. privatizer op symbols: 2}}
+  "omp.simd"(%arg0) ({
+  ^bb0(%arg1 : !llvm.ptr):
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 1, 0>,
+       private_syms = [@simd.count_mismatch.x.privatizer, @simd.count_mismatch.y.privatizer]} : (!llvm.ptr) -> ()
+
+  return
+}
+
+// -----
+omp.private {type = private} @distribute.private.type_mismatch.privatizer : index init {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+omp.private {type = firstprivate} @distribute.firstprivate.type_mismatch.privatizer : index copy {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+func.func @distribute_private_type_mismatch(%lb : index, %ub : index, %step : index,
+                                            %arg0 : index) {
+  // expected-error @below {{type mismatch between a private variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.distribute private(@distribute.private.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }
+
+  return
+}
+
+func.func @distribute_firstprivate_type_mismatch(%lb : index, %ub : index, %step : index,
+                                                 %arg0 : index) {
+  // expected-error @below {{type mismatch between a firstprivate variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.distribute private(@distribute.firstprivate.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }
+
+  return
+}
+
+func.func @distribute_undefined_privatizer(%lb : index, %ub : index, %step : index,
+                                           %arg0 : index) {
+  // expected-error @below {{failed to lookup privatizer op with symbol: '@missing.distribute.privatizer'}}
+  omp.distribute private(@missing.distribute.privatizer %arg0 -> %arg1 : index) {
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }
+
+  return
+}
+
+func.func @distribute_private_count_mismatch(%lb : index, %ub : index, %step : index,
+                                             %arg0 : !llvm.ptr) {
+  // expected-error @below {{inconsistent number of private variables and privatizer op symbols, private vars: 1 vs. privatizer op symbols: 2}}
+  "omp.distribute"(%arg0) ({
+  ^bb0(%arg1 : !llvm.ptr):
+    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+      omp.yield
+    }
+  }) {operandSegmentSizes = array<i32: 0, 0, 0, 1>,
+       private_syms = [@x.privatizer, @y.privatizer]} : (!llvm.ptr) -> ()
+
+  return
+}
+
+// -----
+omp.private {type = private} @task.private.type_mismatch.privatizer : index init {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+omp.private {type = firstprivate} @task.firstprivate.type_mismatch.privatizer : index copy {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+func.func @task_private_type_mismatch(%arg0 : index) {
+  // expected-error @below {{type mismatch between a private variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.task private(@task.private.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.terminator
+  }
+
+  return
+}
+
+func.func @task_firstprivate_type_mismatch(%arg0 : index) {
+  // expected-error @below {{type mismatch between a firstprivate variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.task private(@task.firstprivate.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.terminator
+  }
+
+  return
+}
+
+func.func @task_undefined_privatizer(%arg0 : index) {
+  // expected-error @below {{failed to lookup privatizer op with symbol: '@missing.task.privatizer'}}
+  omp.task private(@missing.task.privatizer %arg0 -> %arg1 : index) {
+    omp.terminator
+  }
+
+  return
+}
+
+func.func @task_private_count_mismatch(%arg0 : !llvm.ptr) {
+  // expected-error @below {{inconsistent number of private variables and privatizer op symbols, private vars: 1 vs. privatizer op symbols: 2}}
+  "omp.task"(%arg0) ({
+  ^bb0(%arg1 : !llvm.ptr):
+    omp.terminator
+  }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0>,
+       private_syms = [@x.privatizer, @y.privatizer]} : (!llvm.ptr) -> ()
+  return
+}
+
+// -----
+omp.private {type = private} @taskloop.private.type_mismatch.privatizer : index init {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+omp.private {type = firstprivate} @taskloop.firstprivate.type_mismatch.privatizer : index copy {
+^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
+  omp.yield(%arg0 : !llvm.ptr)
+}
+
+func.func @taskloop_private_type_mismatch(%lb : index, %ub : index, %step : index,
+                                          %arg0 : index) {
+  // expected-error @below {{type mismatch between a private variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.taskloop.context private(@taskloop.private.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.taskloop.wrapper {
+      omp.loop_nest (%i) : index = (%lb) to (%ub) step (%step) {
+        omp.yield
+      }
+    }
+    omp.terminator
+  }
+  return
+}
+
+func.func @taskloop_firstprivate_type_mismatch(%lb : index, %ub : index, %step : index,
+                                               %arg0 : index) {
+  // expected-error @below {{type mismatch between a firstprivate variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
+  omp.taskloop.context private(@taskloop.firstprivate.type_mismatch.privatizer %arg0 -> %arg1 : index) {
+    omp.taskloop.wrapper {
+      omp.loop_nest (%i) : index = (%lb) to (%ub) step (%step) {
+        omp.yield
+      }
+    }
+    omp.terminator
+  }
+  return
+}
+
+func.func @taskloop_undefined_privatizer(%lb : index, %ub : index, %step : index,
+                                         %arg0 : index) {
+  // expected-error @below {{failed to lookup privatizer op with symbol: '@missing.taskloop.privatizer'}}
+  omp.taskloop.context private(@missing.taskloop.privatizer %arg0 -> %arg1 : index) {
+    omp.taskloop.wrapper {
+      omp.loop_nest (%i) : index = (%lb) to (%ub) step (%step) {
+        omp.yield
+      }
+    }
+    omp.terminator
+  }
+  return
+}
+
+func.func @taskloop_private_count_mismatch(%lb : index, %ub : index, %step : index,
+                                           %arg0 : !llvm.ptr) {
+  // expected-error @below {{inconsistent number of private variables and privatizer op symbols, private vars: 1 vs. privatizer op symbols: 2}}
+  "omp.taskloop.context"(%arg0) ({
+  ^bb0(%arg1 : !llvm.ptr):
+    omp.taskloop.wrapper {
+      omp.loop_nest (%i) : index = (%lb) to (%ub) step (%step) {
+        omp.yield
+      }
+    }
+    omp.terminator
+  }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 1, 0>,
+       private_syms = [@x.privatizer, @y.privatizer]} : (!llvm.ptr) -> ()
+  return
+}
+
 // -----
 func.func @masked_arg_type_mismatch(%arg0: f32) {
   // expected-error @below {{'omp.masked' op operand #0 must be integer or index, but got 'f32'}}
@@ -3041,10 +3471,15 @@ omp.private {type = private} @taskloop.bound.privatizer : index init {
 }
 
 // -----
+omp.private {type = private} @taskloop.bound.local.privatizer : index init {
+^bb0(%arg0: index, %arg1: index):
+  omp.yield(%arg0 : index)
+}
+
 func.func @omp_taskloop_local_loop_bounds_from_block_arg(%arg0: index) {
   %c1 = arith.constant 1 : index
   // expected-error @below {{'omp.taskloop.context' op expects loop bounds and steps to be defined outside of the taskloop.context region or by pure, regionless operations that do not depend on block arguments}}
-  omp.taskloop.context private(@taskloop.bound.privatizer %arg0 -> %arg1 : index) {
+  omp.taskloop.context private(@taskloop.bound.local.privatizer %arg0 -> %arg1 : index) {
     %lb = arith.addi %arg1, %c1 : index
     %ub = arith.constant 10 : index
     %step = arith.constant 1 : index



More information about the Mlir-commits mailing list