From 88bb2521b0063f4b1569fd483cb0bf223f839d33 Mon Sep 17 00:00:00 2001 From: Shraiysh Vaishay Date: Thu, 21 Apr 2022 06:52:38 +0530 Subject: [PATCH] [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 --- flang/test/Lower/OpenMP/critical.f90 | 43 ++- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 1 + mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 18 +- mlir/test/Dialect/OpenMP/invalid.mlir | 96 +++++++ mlir/test/Dialect/OpenMP/ops.mlir | 252 ++++++++++++++++++ mlir/test/Target/LLVMIR/openmp-llvm.mlir | 96 ++++++- 6 files changed, 476 insertions(+), 30 deletions(-) diff --git a/flang/test/Lower/OpenMP/critical.f90 b/flang/test/Lower/OpenMP/critical.f90 index 4c052040a318..c6ac818fe21a 100644 --- a/flang/test/Lower/OpenMP/critical.f90 +++ b/flang/test/Lower/OpenMP/critical.f90 @@ -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 diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td index 5556411cb878..39ccb70b4138 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -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(); diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp index 49baf3907ddc..7ba9af22c6e5 100644 --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -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(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(); } diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir index dd684dda83a2..1b391815e6de 100644 --- a/mlir/test/Dialect/OpenMP/invalid.mlir +++ b/mlir/test/Dialect/OpenMP/invalid.mlir @@ -708,6 +708,42 @@ func @omp_atomic_update9(%x: memref, %expr: i32) { // ----- +func @omp_atomic_update(%x: memref, %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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield (%newval : i32) + } + return +} + +// ----- + +func @omp_atomic_update(%x: memref, %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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield (%newval : i32) + } + return +} + +// ----- + +func @omp_atomic_update(%x: memref, %expr: i32) { + // expected-error @below {{invalid_hint is not a valid hint}} + omp.atomic.update hint(invalid_hint) %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield (%newval : i32) + } + return +} + +// ----- + func @omp_atomic_capture(%x: memref, %v: memref, %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, %y: memref, %v: memref, %exp // ----- +func @omp_atomic_capture(%x: memref, %v: memref, %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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + return +} + +// ----- + +func @omp_atomic_capture(%x: memref, %v: memref, %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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + return +} + +// ----- + +func @omp_atomic_capture(%x: memref, %v: memref, %expr: i32) { + // expected-error @below {{invalid_hint is not a valid hint}} + omp.atomic.capture hint(invalid_hint) { + omp.atomic.update %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + return +} + +// ----- + +func @omp_atomic_capture(%x: memref, %v: memref, %expr: i32) { + // expected-error @below {{operations inside capture region must not have hint clause}} + omp.atomic.capture { + omp.atomic.update hint(uncontended) %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + return +} + +// ----- + func @omp_sections(%data_var : memref) -> () { // expected-error @below {{expected equal sizes for allocate and allocator variables}} "omp.sections" (%data_var) ({ diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir index b620afb9c6a8..21b1c232a2b9 100644 --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -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, %x: memref) { omp.atomic.read %v = %x hint(nonspeculative, contended) : memref // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) hint(contended, speculative) : memref omp.atomic.read %v = %x hint(speculative, contended) memory_order(seq_cst) : memref + // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) hint(none) : memref + omp.atomic.read %v = %x hint(none) memory_order(seq_cst) : memref return } @@ -673,6 +679,8 @@ func @omp_atomic_write(%addr : memref, %val : i32) { omp.atomic.write %addr = %val memory_order(relaxed) : memref, i32 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(uncontended, speculative) : memref, i32 omp.atomic.write %addr = %val hint(speculative, uncontended) : memref, i32 + // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(none) : memref, i32 + omp.atomic.write %addr = %val hint(none) : memref, i32 return } @@ -728,6 +736,97 @@ func @omp_atomic_update(%x : memref, %expr : i32, %xBool : memref, %exp %newval = llvm.icmp "eq" %xval, %exprBool : i1 omp.yield(%newval : i1) } + + // CHECK: omp.atomic.update hint(none) %[[X]] : memref + // 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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + + // CHECK: omp.atomic.update hint(uncontended) %[[X]] : memref + // 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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + + // CHECK: omp.atomic.update hint(contended) %[[X]] : memref + // 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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + + // CHECK: omp.atomic.update hint(nonspeculative) %[[X]] : memref + // 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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + + // CHECK: omp.atomic.update hint(speculative) %[[X]] : memref + // 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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + + // CHECK: omp.atomic.update hint(uncontended, nonspeculative) %[[X]] : memref + // 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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + + // CHECK: omp.atomic.update hint(contended, nonspeculative) %[[X]] : memref + // 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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + + // CHECK: omp.atomic.update hint(uncontended, speculative) %[[X]] : memref + // 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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + + // CHECK: omp.atomic.update hint(contended, speculative) %[[X]] : memref + // 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 { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + return } @@ -774,6 +873,159 @@ func @omp_atomic_capture(%v: memref, %x: memref, %expr: i32) { omp.atomic.read %v = %x : memref omp.atomic.write %x = %expr : memref, i32 } + + // CHECK: omp.atomic.capture hint(none) { + // CHECK-NEXT: omp.atomic.update %[[x]] : memref + // 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 + // CHECK-NEXT: } + omp.atomic.capture hint(none) { + omp.atomic.update %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + + // CHECK: omp.atomic.capture hint(uncontended) { + // CHECK-NEXT: omp.atomic.update %[[x]] : memref + // 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 + // CHECK-NEXT: } + omp.atomic.capture hint(uncontended) { + omp.atomic.update %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + + // CHECK: omp.atomic.capture hint(contended) { + // CHECK-NEXT: omp.atomic.update %[[x]] : memref + // 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 + // CHECK-NEXT: } + omp.atomic.capture hint(contended) { + omp.atomic.update %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + + // CHECK: omp.atomic.capture hint(nonspeculative) { + // CHECK-NEXT: omp.atomic.update %[[x]] : memref + // 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 + // CHECK-NEXT: } + omp.atomic.capture hint(nonspeculative) { + omp.atomic.update %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + + // CHECK: omp.atomic.capture hint(speculative) { + // CHECK-NEXT: omp.atomic.update %[[x]] : memref + // 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 + // CHECK-NEXT: } + omp.atomic.capture hint(speculative) { + omp.atomic.update %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + + // CHECK: omp.atomic.capture hint(uncontended, nonspeculative) { + // CHECK-NEXT: omp.atomic.update %[[x]] : memref + // 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 + // CHECK-NEXT: } + omp.atomic.capture hint(uncontended, nonspeculative) { + omp.atomic.update %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + + // CHECK: omp.atomic.capture hint(contended, nonspeculative) { + // CHECK-NEXT: omp.atomic.update %[[x]] : memref + // 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 + // CHECK-NEXT: } + omp.atomic.capture hint(contended, nonspeculative) { + omp.atomic.update %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + + // CHECK: omp.atomic.capture hint(uncontended, speculative) { + // CHECK-NEXT: omp.atomic.update %[[x]] : memref + // 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 + // CHECK-NEXT: } + omp.atomic.capture hint(uncontended, speculative) { + omp.atomic.update %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } + + // CHECK: omp.atomic.capture hint(contended, speculative) { + // CHECK-NEXT: omp.atomic.update %[[x]] : memref + // 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 + // CHECK-NEXT: } + omp.atomic.capture hint(contended, speculative) { + omp.atomic.update %x : memref { + ^bb0(%xval: i32): + %newval = llvm.add %xval, %expr : i32 + omp.yield(%newval : i32) + } + omp.atomic.read %v = %x : memref + } return } diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir b/mlir/test/Target/LLVMIR/openmp-llvm.mlir index 5bf67c834ada..1feb9a40b078 100644 --- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir +++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir @@ -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, %xval : i32) -> () { @@ -905,15 +913,95 @@ llvm.func @omp_critical(%x : !llvm.ptr, %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 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + omp.terminator + } + // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_speculative_contended.var{{.*}}) llvm.return }