[clang] 49ee8b5 - [OpenMP] atomic compare fail : Codegen support (#75709)

via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 2 09:16:08 PST 2024


Author: SunilKuravinakop
Date: 2024-01-02T22:46:02+05:30
New Revision: 49ee8b53ef39c158d40d76128828379dd34ea61f

URL: https://github.com/llvm/llvm-project/commit/49ee8b53ef39c158d40d76128828379dd34ea61f
DIFF: https://github.com/llvm/llvm-project/commit/49ee8b53ef39c158d40d76128828379dd34ea61f.diff

LOG: [OpenMP] atomic compare fail : Codegen support (#75709)

This is a continuation of https://reviews.llvm.org/D123235 ([OpenMP]
atomic compare fail : Parser & AST support). In this branch Support for
codegen support for atomic compare fail is being added.

---------

Co-authored-by: Sunil Kuravinakop

Added: 
    

Modified: 
    clang/lib/CodeGen/CGStmtOpenMP.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/test/OpenMP/atomic_compare_codegen.cpp
    llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
    llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index ed426098ac6915..e362c9da51fe31 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -6406,13 +6406,11 @@ static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF,
   }
 }
 
-static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF,
-                                     llvm::AtomicOrdering AO, const Expr *X,
-                                     const Expr *V, const Expr *R,
-                                     const Expr *E, const Expr *D,
-                                     const Expr *CE, bool IsXBinopExpr,
-                                     bool IsPostfixUpdate, bool IsFailOnly,
-                                     SourceLocation Loc) {
+static void emitOMPAtomicCompareExpr(
+    CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
+    const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *D,
+    const Expr *CE, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly,
+    SourceLocation Loc) {
   llvm::OpenMPIRBuilder &OMPBuilder =
       CGF.CGM.getOpenMPRuntime().getOMPBuilder();
 
@@ -6477,13 +6475,21 @@ static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF,
               R->getType().isVolatileQualified()};
   }
 
-  CGF.Builder.restoreIP(OMPBuilder.createAtomicCompare(
-      CGF.Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
-      IsPostfixUpdate, IsFailOnly));
+  if (FailAO == llvm::AtomicOrdering::NotAtomic) {
+    // fail clause was not mentionend on the
+    // "#pragma omp atomic compare" construct.
+    CGF.Builder.restoreIP(OMPBuilder.createAtomicCompare(
+        CGF.Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
+        IsPostfixUpdate, IsFailOnly));
+  } else
+    CGF.Builder.restoreIP(OMPBuilder.createAtomicCompare(
+        CGF.Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
+        IsPostfixUpdate, IsFailOnly, FailAO));
 }
 
 static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
-                              llvm::AtomicOrdering AO, bool IsPostfixUpdate,
+                              llvm::AtomicOrdering AO,
+                              llvm::AtomicOrdering FailAO, bool IsPostfixUpdate,
                               const Expr *X, const Expr *V, const Expr *R,
                               const Expr *E, const Expr *UE, const Expr *D,
                               const Expr *CE, bool IsXLHSInRHSPart,
@@ -6504,12 +6510,8 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
                              IsXLHSInRHSPart, Loc);
     break;
   case OMPC_compare: {
-    emitOMPAtomicCompareExpr(CGF, AO, X, V, R, E, D, CE, IsXLHSInRHSPart,
-                             IsPostfixUpdate, IsFailOnly, Loc);
-    break;
-  }
-  case OMPC_fail: {
-    //TODO
+    emitOMPAtomicCompareExpr(CGF, AO, FailAO, X, V, R, E, D, CE,
+                             IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly, Loc);
     break;
   }
   default:
@@ -6519,6 +6521,8 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
 
 void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
   llvm::AtomicOrdering AO = llvm::AtomicOrdering::Monotonic;
+  // Fail Memory Clause Ordering.
+  llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
   bool MemOrderingSpecified = false;
   if (S.getSingleClause<OMPSeqCstClause>()) {
     AO = llvm::AtomicOrdering::SequentiallyConsistent;
@@ -6572,12 +6576,27 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
     }
   }
 
+  if (KindsEncountered.contains(OMPC_compare) &&
+      KindsEncountered.contains(OMPC_fail)) {
+    Kind = OMPC_compare;
+    const auto *FailClause = S.getSingleClause<OMPFailClause>();
+    if (FailClause) {
+      OpenMPClauseKind FailParameter = FailClause->getFailParameter();
+      if (FailParameter == llvm::omp::OMPC_relaxed)
+        FailAO = llvm::AtomicOrdering::Monotonic;
+      else if (FailParameter == llvm::omp::OMPC_acquire)
+        FailAO = llvm::AtomicOrdering::Acquire;
+      else if (FailParameter == llvm::omp::OMPC_seq_cst)
+        FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
+    }
+  }
+
   LexicalScope Scope(*this, S.getSourceRange());
   EmitStopPoint(S.getAssociatedStmt());
-  emitOMPAtomicExpr(*this, Kind, AO, S.isPostfixUpdate(), S.getX(), S.getV(),
-                    S.getR(), S.getExpr(), S.getUpdateExpr(), S.getD(),
-                    S.getCondExpr(), S.isXLHSInRHSPart(), S.isFailOnly(),
-                    S.getBeginLoc());
+  emitOMPAtomicExpr(*this, Kind, AO, FailAO, S.isPostfixUpdate(), S.getX(),
+                    S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
+                    S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
+                    S.isFailOnly(), S.getBeginLoc());
 }
 
 static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 3826994ef2126c..f34d2959dc6191 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -12683,7 +12683,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
       break;
     }
     case OMPC_fail: {
-      if (AtomicKind != OMPC_compare) {
+      if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
         Diag(C->getBeginLoc(), diag::err_omp_atomic_fail_no_compare)
             << SourceRange(C->getBeginLoc(), C->getEndLoc());
         return StmtError();

diff  --git a/clang/test/OpenMP/atomic_compare_codegen.cpp b/clang/test/OpenMP/atomic_compare_codegen.cpp
index 43607cc65ad9b5..03e5081a5c1d8a 100644
--- a/clang/test/OpenMP/atomic_compare_codegen.cpp
+++ b/clang/test/OpenMP/atomic_compare_codegen.cpp
@@ -13806,6 +13806,64 @@ double dxevd() {
   return dv;
 }
 
+
+double fail_dxevd() {
+  double dx, dv, de, dd;
+
+#pragma omp atomic compare capture relaxed fail(relaxed)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture acquire fail(relaxed)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture release fail(relaxed)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture acq_rel fail(relaxed)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture seq_cst fail(relaxed)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture relaxed fail(acquire)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture acquire fail(acquire)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture release fail(acquire)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture acq_rel fail(acquire)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture seq_cst fail(acquire)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture relaxed fail(seq_cst)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture acquire fail(seq_cst)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture release fail(seq_cst)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture acq_rel fail(seq_cst)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare capture seq_cst fail(seq_cst)
+  {if(dx == de) { dx = dv; } else { dd = dx; }}
+
+#pragma omp atomic compare seq_cst fail(acquire)
+  dx = dx < de ? de : dx;
+
+#pragma omp atomic compare relaxed fail(seq_cst)
+  dx = dx > de ? de : dx;
+
+  return dx;
+}
+
 #endif
 // CHECK-LABEL: @foo(
 // CHECK-NEXT:  entry:
@@ -61966,3 +62024,89 @@ double dxevd() {
 // SIMD-ONLY0-NEXT:    [[TMP180:%.*]] = load double, ptr [[DV]], align 8
 // SIMD-ONLY0-NEXT:    ret double [[TMP180]]
 //
+// CHECK-LABEL: {{.+}}fail_dxevd{{.+}}
+// CHECK-NEXT:  entry:
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:    {{.+}}cmpxchg ptr {{.+}} monotonic monotonic{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} acquire monotonic{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} release monotonic{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} acq_rel monotonic{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}}cmpxchg ptr {{.+}} seq_cst monotonic{{.+}}
+// CHECK:    {{.+}}__kmpc_flush{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} monotonic acquire{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} acquire acquire{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} release acquire{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} acq_rel acquire{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} seq_cst acquire{{.+}}
+// CHECK:    {{.+}}__kmpc_flush{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} monotonic seq_cst{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} acquire seq_cst{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} release seq_cst{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} acq_rel seq_cst{{.+}}
+// CHECK:       {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK-NEXT:  {{.+}} bitcast double{{.+}}
+// CHECK:    {{.+}}cmpxchg ptr {{.+}} seq_cst seq_cst{{.+}}
+// CHECK:    call void {{.+}}__kmpc_flush{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} atomicrmw fmax {{.+}} seq_cst{{.+}}
+// CHECK-NEXT:  call void {{.+}}__kmpc_flush{{.+}}
+// CHECK-NEXT:  {{.+}} load double,{{.+}}
+// CHECK-NEXT:  {{.+}} atomicrmw fmin {{.+}} monotonic{{.+}}
+// CHECK:    ret double {{.+}}

diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index abbef03d02cb10..669104307fa0e2 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -2562,6 +2562,13 @@ class OpenMPIRBuilder {
                       AtomicOpValue &V, AtomicOpValue &R, Value *E, Value *D,
                       AtomicOrdering AO, omp::OMPAtomicCompareOp Op,
                       bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly);
+  InsertPointTy createAtomicCompare(const LocationDescription &Loc,
+                                    AtomicOpValue &X, AtomicOpValue &V,
+                                    AtomicOpValue &R, Value *E, Value *D,
+                                    AtomicOrdering AO,
+                                    omp::OMPAtomicCompareOp Op,
+                                    bool IsXBinopExpr, bool IsPostfixUpdate,
+                                    bool IsFailOnly, AtomicOrdering Failure);
 
   /// Create the control flow structure of a canonical OpenMP loop.
   ///

diff  --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index ce428f78dc843e..f6cf358119fb71 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -6026,6 +6026,17 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
     omp::OMPAtomicCompareOp Op, bool IsXBinopExpr, bool IsPostfixUpdate,
     bool IsFailOnly) {
 
+  AtomicOrdering Failure = AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
+  return createAtomicCompare(Loc, X, V, R, E, D, AO, Op, IsXBinopExpr,
+                             IsPostfixUpdate, IsFailOnly, Failure);
+}
+
+OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
+    const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V,
+    AtomicOpValue &R, Value *E, Value *D, AtomicOrdering AO,
+    omp::OMPAtomicCompareOp Op, bool IsXBinopExpr, bool IsPostfixUpdate,
+    bool IsFailOnly, AtomicOrdering Failure) {
+
   if (!updateToLocation(Loc))
     return Loc.IP;
 
@@ -6040,7 +6051,6 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
   bool IsInteger = E->getType()->isIntegerTy();
 
   if (Op == OMPAtomicCompareOp::EQ) {
-    AtomicOrdering Failure = AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
     AtomicCmpXchgInst *Result = nullptr;
     if (!IsInteger) {
       IntegerType *IntCastTy =


        


More information about the cfe-commits mailing list