[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 - | FileCheck %s --check-prefixes="OMPDialect"
!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 - | 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" !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() subroutine omp_critical()
use omp_lib use omp_lib
integer :: x, y integer :: x, y
!FIRDialect: omp.critical.declare @help hint(contended) !OMPDialect: omp.critical(@help1)
!LLVMDialect: omp.critical.declare @help hint(contended) !LLVMIR: call void @__kmpc_critical_with_hint({{.*}}, {{.*}}, {{.*}} @{{.*}}help1.var, i32 2)
!FIRDialect: omp.critical(@help) !$OMP CRITICAL(help1) HINT(omp_lock_hint_contended)
!LLVMDialect: omp.critical(@help)
!LLVMIR: call void @__kmpc_critical_with_hint({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var, i32 2)
!$OMP CRITICAL(help) HINT(omp_lock_hint_contended)
x = x + y x = x + y
!FIRDialect: omp.terminator !OMPDialect: omp.terminator
!LLVMDialect: omp.terminator !LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}help1.var)
!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var) !$OMP END CRITICAL(help1)
!$OMP END CRITICAL(help)
! Test that the same name can be used again ! Test that the same name can be used again
! Also test with the zero hint expression ! Also test with the zero hint expression
!FIRDialect: omp.critical(@help) !OMPDialect: omp.critical(@help2)
!LLVMDialect: omp.critical(@help) !LLVMIR: call void @__kmpc_critical_with_hint({{.*}}, {{.*}}, {{.*}} @{{.*}}help2.var, i32 0)
!LLVMIR: call void @__kmpc_critical_with_hint({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var, i32 2) !$OMP CRITICAL(help2) HINT(omp_lock_hint_none)
!$OMP CRITICAL(help) HINT(omp_lock_hint_none)
x = x - y x = x - y
!FIRDialect: omp.terminator !OMPDialect: omp.terminator
!LLVMDialect: omp.terminator !LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}help2.var)
!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var) !$OMP END CRITICAL(help2)
!$OMP END CRITICAL(help)
!FIRDialect: omp.critical !OMPDialect: omp.critical
!LLVMDialect: omp.critical
!LLVMIR: call void @__kmpc_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}_.var) !LLVMIR: call void @__kmpc_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}_.var)
!$OMP CRITICAL !$OMP CRITICAL
y = x + y y = x + y
!FIRDialect: omp.terminator !OMPDialect: omp.terminator
!LLVMDialect: omp.terminator
!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}_.var) !LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}_.var)
!$OMP END CRITICAL !$OMP END CRITICAL
end subroutine omp_critical end subroutine omp_critical

View File

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

View File

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

View File

@ -583,6 +583,10 @@ omp.critical.declare @mutex6 hint(contended, nonspeculative)
omp.critical.declare @mutex7 hint(uncontended, speculative) omp.critical.declare @mutex7 hint(uncontended, speculative)
// CHECK: omp.critical.declare @mutex8 hint(contended, speculative) // CHECK: omp.critical.declare @mutex8 hint(contended, speculative)
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 // 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> 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> // 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> 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 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 omp.atomic.write %addr = %val memory_order(relaxed) : memref<i32>, i32
// CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(uncontended, speculative) : 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 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 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 %newval = llvm.icmp "eq" %xval, %exprBool : i1
omp.yield(%newval : 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 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.read %v = %x : memref<i32>
omp.atomic.write %x = %expr : memref<i32>, 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 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 // CHECK-LABEL: @omp_critical
llvm.func @omp_critical(%x : !llvm.ptr<i32>, %xval : i32) -> () { 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_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: br label %omp.critical.region
// CHECK: omp.critical.region // CHECK: omp.critical.region
omp.critical(@mutex) { omp.critical(@mutex_none) {
// CHECK: store // CHECK: store
llvm.store %xval, %x : !llvm.ptr<i32> llvm.store %xval, %x : !llvm.ptr<i32>
omp.terminator 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 llvm.return
} }