[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:
parent
7895c87367
commit
88bb2521b0
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) ({
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue