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 = _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits