[mlir][OpenMP] Add checks and tests for hint clause and fix empty hint

This patch handles empty hint value for critical and atomic constructs.

This also adds checks and tests for hint clause on atomic constructs.

Reviewed By: peixin, kiranchandramohan, NimishMishra

Differential Revision: https://reviews.llvm.org/D123186
This commit is contained in:
Shraiysh Vaishay 2022-04-21 06:52:38 +05:30
parent 7895c87367
commit 88bb2521b0
6 changed files with 476 additions and 30 deletions

View File

@ -1,41 +1,36 @@
!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s --check-prefix="FIRDialect"
!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefix="LLVMDialect"
!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s --check-prefixes="OMPDialect"
!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefix="OMPDialect"
!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | fir-opt --fir-to-llvm-ir | tco | FileCheck %s --check-prefix="LLVMIR"
!OMPDialect: omp.critical.declare @help2 hint(none)
!OMPDialect: omp.critical.declare @help1 hint(contended)
subroutine omp_critical()
use omp_lib
integer :: x, y
!FIRDialect: omp.critical.declare @help hint(contended)
!LLVMDialect: omp.critical.declare @help hint(contended)
!FIRDialect: omp.critical(@help)
!LLVMDialect: omp.critical(@help)
!LLVMIR: call void @__kmpc_critical_with_hint({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var, i32 2)
!$OMP CRITICAL(help) HINT(omp_lock_hint_contended)
!OMPDialect: omp.critical(@help1)
!LLVMIR: call void @__kmpc_critical_with_hint({{.*}}, {{.*}}, {{.*}} @{{.*}}help1.var, i32 2)
!$OMP CRITICAL(help1) HINT(omp_lock_hint_contended)
x = x + y
!FIRDialect: omp.terminator
!LLVMDialect: omp.terminator
!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var)
!$OMP END CRITICAL(help)
!OMPDialect: omp.terminator
!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}help1.var)
!$OMP END CRITICAL(help1)
! Test that the same name can be used again
! Also test with the zero hint expression
!FIRDialect: omp.critical(@help)
!LLVMDialect: omp.critical(@help)
!LLVMIR: call void @__kmpc_critical_with_hint({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var, i32 2)
!$OMP CRITICAL(help) HINT(omp_lock_hint_none)
!OMPDialect: omp.critical(@help2)
!LLVMIR: call void @__kmpc_critical_with_hint({{.*}}, {{.*}}, {{.*}} @{{.*}}help2.var, i32 0)
!$OMP CRITICAL(help2) HINT(omp_lock_hint_none)
x = x - y
!FIRDialect: omp.terminator
!LLVMDialect: omp.terminator
!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var)
!$OMP END CRITICAL(help)
!OMPDialect: omp.terminator
!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}help2.var)
!$OMP END CRITICAL(help2)
!FIRDialect: omp.critical
!LLVMDialect: omp.critical
!OMPDialect: omp.critical
!LLVMIR: call void @__kmpc_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}_.var)
!$OMP CRITICAL
y = x + y
!FIRDialect: omp.terminator
!LLVMDialect: omp.terminator
!OMPDialect: omp.terminator
!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}_.var)
!$OMP END CRITICAL
end subroutine omp_critical

View File

@ -946,6 +946,7 @@ def AtomicCaptureOp : OpenMP_Op<"atomic.capture",
$region attr-dict
}];
let hasRegionVerifier = 1;
let hasVerifier = 1;
let extraClassDeclaration = [{
/// Returns the first operation in atomic capture region
Operation* getFirstOp();

View File

@ -382,6 +382,10 @@ static ParseResult parseSynchronizationHint(OpAsmParser &parser,
IntegerAttr &hintAttr) {
StringRef hintKeyword;
int64_t hint = 0;
if (succeeded(parser.parseOptionalKeyword("none"))) {
hintAttr = IntegerAttr::get(parser.getBuilder().getI64Type(), 0);
return success();
}
do {
if (failed(parser.parseKeyword(&hintKeyword)))
return failure();
@ -406,8 +410,10 @@ static void printSynchronizationHint(OpAsmPrinter &p, Operation *op,
IntegerAttr hintAttr) {
int64_t hint = hintAttr.getInt();
if (hint == 0)
if (hint == 0) {
p << "none";
return;
}
// Helper function to get n-th bit from the right end of `value`
auto bitn = [](int value, int n) -> bool { return value & (1 << n); };
@ -864,7 +870,7 @@ LogicalResult AtomicUpdateOp::verify() {
"element type is the same as that of the region argument");
}
return success();
return verifySynchronizationHint(*this, hint_val());
}
LogicalResult AtomicUpdateOp::verifyRegions() {
@ -915,6 +921,10 @@ AtomicUpdateOp AtomicCaptureOp::getAtomicUpdateOp() {
return dyn_cast<AtomicUpdateOp>(getSecondOp());
}
LogicalResult AtomicCaptureOp::verify() {
return verifySynchronizationHint(*this, hint_val());
}
LogicalResult AtomicCaptureOp::verifyRegions() {
Block::OpListType &ops = region().front().getOperations();
if (ops.size() != 3)
@ -949,6 +959,10 @@ LogicalResult AtomicCaptureOp::verifyRegions() {
return firstReadStmt.emitError()
<< "captured variable in omp.atomic.read must be updated in "
"second operation";
if (getFirstOp()->getAttr("hint_val") || getSecondOp()->getAttr("hint_val"))
return emitOpError(
"operations inside capture region must not have hint clause");
return success();
}

View File

@ -708,6 +708,42 @@ func @omp_atomic_update9(%x: memref<i32>, %expr: i32) {
// -----
func @omp_atomic_update(%x: memref<i32>, %expr: i32) {
// expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
omp.atomic.update hint(uncontended, contended) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield (%newval : i32)
}
return
}
// -----
func @omp_atomic_update(%x: memref<i32>, %expr: i32) {
// expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined}}
omp.atomic.update hint(nonspeculative, speculative) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield (%newval : i32)
}
return
}
// -----
func @omp_atomic_update(%x: memref<i32>, %expr: i32) {
// expected-error @below {{invalid_hint is not a valid hint}}
omp.atomic.update hint(invalid_hint) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield (%newval : i32)
}
return
}
// -----
func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
// expected-error @below {{expected three operations in omp.atomic.capture region}}
omp.atomic.capture {
@ -848,6 +884,66 @@ func @omp_atomic_capture(%x: memref<i32>, %y: memref<i32>, %v: memref<i32>, %exp
// -----
func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
// expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
omp.atomic.capture hint(contended, uncontended) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
return
}
// -----
func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
// expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined}}
omp.atomic.capture hint(nonspeculative, speculative) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
return
}
// -----
func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
// expected-error @below {{invalid_hint is not a valid hint}}
omp.atomic.capture hint(invalid_hint) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
return
}
// -----
func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
// expected-error @below {{operations inside capture region must not have hint clause}}
omp.atomic.capture {
omp.atomic.update hint(uncontended) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
return
}
// -----
func @omp_sections(%data_var : memref<i32>) -> () {
// expected-error @below {{expected equal sizes for allocate and allocator variables}}
"omp.sections" (%data_var) ({

View File

@ -583,6 +583,10 @@ omp.critical.declare @mutex6 hint(contended, nonspeculative)
omp.critical.declare @mutex7 hint(uncontended, speculative)
// CHECK: omp.critical.declare @mutex8 hint(contended, speculative)
omp.critical.declare @mutex8 hint(contended, speculative)
// CHECK: omp.critical.declare @mutex9 hint(none)
omp.critical.declare @mutex9 hint(none)
// CHECK: omp.critical.declare @mutex10
omp.critical.declare @mutex10
// CHECK-LABEL: omp_critical
@ -657,6 +661,8 @@ func @omp_atomic_read(%v: memref<i32>, %x: memref<i32>) {
omp.atomic.read %v = %x hint(nonspeculative, contended) : memref<i32>
// CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) hint(contended, speculative) : memref<i32>
omp.atomic.read %v = %x hint(speculative, contended) memory_order(seq_cst) : memref<i32>
// CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) hint(none) : memref<i32>
omp.atomic.read %v = %x hint(none) memory_order(seq_cst) : memref<i32>
return
}
@ -673,6 +679,8 @@ func @omp_atomic_write(%addr : memref<i32>, %val : i32) {
omp.atomic.write %addr = %val memory_order(relaxed) : memref<i32>, i32
// CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(uncontended, speculative) : memref<i32>, i32
omp.atomic.write %addr = %val hint(speculative, uncontended) : memref<i32>, i32
// CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(none) : memref<i32>, i32
omp.atomic.write %addr = %val hint(none) : memref<i32>, i32
return
}
@ -728,6 +736,97 @@ func @omp_atomic_update(%x : memref<i32>, %expr : i32, %xBool : memref<i1>, %exp
%newval = llvm.icmp "eq" %xval, %exprBool : i1
omp.yield(%newval : i1)
}
// CHECK: omp.atomic.update hint(none) %[[X]] : memref<i32>
// CHECK-NEXT: (%[[XVAL:.*]]: i32):
// CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
// CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
omp.atomic.update hint(none) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
// CHECK: omp.atomic.update hint(uncontended) %[[X]] : memref<i32>
// CHECK-NEXT: (%[[XVAL:.*]]: i32):
// CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
// CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
omp.atomic.update hint(uncontended) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
// CHECK: omp.atomic.update hint(contended) %[[X]] : memref<i32>
// CHECK-NEXT: (%[[XVAL:.*]]: i32):
// CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
// CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
omp.atomic.update hint(contended) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
// CHECK: omp.atomic.update hint(nonspeculative) %[[X]] : memref<i32>
// CHECK-NEXT: (%[[XVAL:.*]]: i32):
// CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
// CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
omp.atomic.update hint(nonspeculative) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
// CHECK: omp.atomic.update hint(speculative) %[[X]] : memref<i32>
// CHECK-NEXT: (%[[XVAL:.*]]: i32):
// CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
// CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
omp.atomic.update hint(speculative) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
// CHECK: omp.atomic.update hint(uncontended, nonspeculative) %[[X]] : memref<i32>
// CHECK-NEXT: (%[[XVAL:.*]]: i32):
// CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
// CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
omp.atomic.update hint(uncontended, nonspeculative) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
// CHECK: omp.atomic.update hint(contended, nonspeculative) %[[X]] : memref<i32>
// CHECK-NEXT: (%[[XVAL:.*]]: i32):
// CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
// CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
omp.atomic.update hint(contended, nonspeculative) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
// CHECK: omp.atomic.update hint(uncontended, speculative) %[[X]] : memref<i32>
// CHECK-NEXT: (%[[XVAL:.*]]: i32):
// CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
// CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
omp.atomic.update hint(uncontended, speculative) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
// CHECK: omp.atomic.update hint(contended, speculative) %[[X]] : memref<i32>
// CHECK-NEXT: (%[[XVAL:.*]]: i32):
// CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
// CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
omp.atomic.update hint(contended, speculative) %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
return
}
@ -774,6 +873,159 @@ func @omp_atomic_capture(%v: memref<i32>, %x: memref<i32>, %expr: i32) {
omp.atomic.read %v = %x : memref<i32>
omp.atomic.write %x = %expr : memref<i32>, i32
}
// CHECK: omp.atomic.capture hint(none) {
// CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
// CHECK-NEXT: (%[[xval:.*]]: i32):
// CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
// CHECK-NEXT: omp.yield(%[[newval]] : i32)
// CHECK-NEXT: }
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
// CHECK-NEXT: }
omp.atomic.capture hint(none) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
// CHECK: omp.atomic.capture hint(uncontended) {
// CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
// CHECK-NEXT: (%[[xval:.*]]: i32):
// CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
// CHECK-NEXT: omp.yield(%[[newval]] : i32)
// CHECK-NEXT: }
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
// CHECK-NEXT: }
omp.atomic.capture hint(uncontended) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
// CHECK: omp.atomic.capture hint(contended) {
// CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
// CHECK-NEXT: (%[[xval:.*]]: i32):
// CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
// CHECK-NEXT: omp.yield(%[[newval]] : i32)
// CHECK-NEXT: }
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
// CHECK-NEXT: }
omp.atomic.capture hint(contended) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
// CHECK: omp.atomic.capture hint(nonspeculative) {
// CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
// CHECK-NEXT: (%[[xval:.*]]: i32):
// CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
// CHECK-NEXT: omp.yield(%[[newval]] : i32)
// CHECK-NEXT: }
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
// CHECK-NEXT: }
omp.atomic.capture hint(nonspeculative) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
// CHECK: omp.atomic.capture hint(speculative) {
// CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
// CHECK-NEXT: (%[[xval:.*]]: i32):
// CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
// CHECK-NEXT: omp.yield(%[[newval]] : i32)
// CHECK-NEXT: }
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
// CHECK-NEXT: }
omp.atomic.capture hint(speculative) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
// CHECK: omp.atomic.capture hint(uncontended, nonspeculative) {
// CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
// CHECK-NEXT: (%[[xval:.*]]: i32):
// CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
// CHECK-NEXT: omp.yield(%[[newval]] : i32)
// CHECK-NEXT: }
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
// CHECK-NEXT: }
omp.atomic.capture hint(uncontended, nonspeculative) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
// CHECK: omp.atomic.capture hint(contended, nonspeculative) {
// CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
// CHECK-NEXT: (%[[xval:.*]]: i32):
// CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
// CHECK-NEXT: omp.yield(%[[newval]] : i32)
// CHECK-NEXT: }
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
// CHECK-NEXT: }
omp.atomic.capture hint(contended, nonspeculative) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
// CHECK: omp.atomic.capture hint(uncontended, speculative) {
// CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
// CHECK-NEXT: (%[[xval:.*]]: i32):
// CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
// CHECK-NEXT: omp.yield(%[[newval]] : i32)
// CHECK-NEXT: }
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
// CHECK-NEXT: }
omp.atomic.capture hint(uncontended, speculative) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
// CHECK: omp.atomic.capture hint(contended, speculative) {
// CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
// CHECK-NEXT: (%[[xval:.*]]: i32):
// CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
// CHECK-NEXT: omp.yield(%[[newval]] : i32)
// CHECK-NEXT: }
// CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
// CHECK-NEXT: }
omp.atomic.capture hint(contended, speculative) {
omp.atomic.update %x : memref<i32> {
^bb0(%xval: i32):
%newval = llvm.add %xval, %expr : i32
omp.yield(%newval : i32)
}
omp.atomic.read %v = %x : memref<i32>
}
return
}

View File

@ -891,7 +891,15 @@ llvm.func @test_omp_wsloop_dynamic_monotonic_ordered(%lb : i64, %ub : i64, %step
// -----
omp.critical.declare @mutex hint(contended)
omp.critical.declare @mutex_none hint(none) // 0
omp.critical.declare @mutex_uncontended hint(uncontended) // 1
omp.critical.declare @mutex_contended hint(contended) // 2
omp.critical.declare @mutex_nonspeculative hint(nonspeculative) // 4
omp.critical.declare @mutex_nonspeculative_uncontended hint(nonspeculative, uncontended) // 5
omp.critical.declare @mutex_nonspeculative_contended hint(nonspeculative, contended) // 6
omp.critical.declare @mutex_speculative hint(speculative) // 8
omp.critical.declare @mutex_speculative_uncontended hint(speculative, uncontended) // 9
omp.critical.declare @mutex_speculative_contended hint(speculative, contended) // 10
// CHECK-LABEL: @omp_critical
llvm.func @omp_critical(%x : !llvm.ptr<i32>, %xval : i32) -> () {
@ -905,15 +913,95 @@ llvm.func @omp_critical(%x : !llvm.ptr<i32>, %xval : i32) -> () {
}
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_.var{{.*}})
// CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex.var{{.*}}, i32 2)
// CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_none.var{{.*}}, i32 0)
// CHECK: br label %omp.critical.region
// CHECK: omp.critical.region
omp.critical(@mutex) {
omp.critical(@mutex_none) {
// CHECK: store
llvm.store %xval, %x : !llvm.ptr<i32>
omp.terminator
}
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex.var{{.*}})
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_none.var{{.*}})
// CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_uncontended.var{{.*}}, i32 1)
// CHECK: br label %omp.critical.region
// CHECK: omp.critical.region
omp.critical(@mutex_uncontended) {
// CHECK: store
llvm.store %xval, %x : !llvm.ptr<i32>
omp.terminator
}
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_uncontended.var{{.*}})
// CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_contended.var{{.*}}, i32 2)
// CHECK: br label %omp.critical.region
// CHECK: omp.critical.region
omp.critical(@mutex_contended) {
// CHECK: store
llvm.store %xval, %x : !llvm.ptr<i32>
omp.terminator
}
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_contended.var{{.*}})
// CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_nonspeculative.var{{.*}}, i32 4)
// CHECK: br label %omp.critical.region
// CHECK: omp.critical.region
omp.critical(@mutex_nonspeculative) {
// CHECK: store
llvm.store %xval, %x : !llvm.ptr<i32>
omp.terminator
}
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_nonspeculative.var{{.*}})
// CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_nonspeculative_uncontended.var{{.*}}, i32 5)
// CHECK: br label %omp.critical.region
// CHECK: omp.critical.region
omp.critical(@mutex_nonspeculative_uncontended) {
// CHECK: store
llvm.store %xval, %x : !llvm.ptr<i32>
omp.terminator
}
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_nonspeculative_uncontended.var{{.*}})
// CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_nonspeculative_contended.var{{.*}}, i32 6)
// CHECK: br label %omp.critical.region
// CHECK: omp.critical.region
omp.critical(@mutex_nonspeculative_contended) {
// CHECK: store
llvm.store %xval, %x : !llvm.ptr<i32>
omp.terminator
}
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_nonspeculative_contended.var{{.*}})
// CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_speculative.var{{.*}}, i32 8)
// CHECK: br label %omp.critical.region
// CHECK: omp.critical.region
omp.critical(@mutex_speculative) {
// CHECK: store
llvm.store %xval, %x : !llvm.ptr<i32>
omp.terminator
}
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_speculative.var{{.*}})
// CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_speculative_uncontended.var{{.*}}, i32 9)
// CHECK: br label %omp.critical.region
// CHECK: omp.critical.region
omp.critical(@mutex_speculative_uncontended) {
// CHECK: store
llvm.store %xval, %x : !llvm.ptr<i32>
omp.terminator
}
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_speculative_uncontended.var{{.*}})
// CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_speculative_contended.var{{.*}}, i32 10)
// CHECK: br label %omp.critical.region
// CHECK: omp.critical.region
omp.critical(@mutex_speculative_contended) {
// CHECK: store
llvm.store %xval, %x : !llvm.ptr<i32>
omp.terminator
}
// CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_speculative_contended.var{{.*}})
llvm.return
}