Skip to content

[OpenMPIRBuilder] Use BuildBuiltins for atomic operations #101966

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: users/meinersbur/llvm_buildbuiltins
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions clang/lib/CodeGen/CGStmtOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6740,16 +6740,18 @@ static void emitOMPAtomicCompareExpr(
R->getType().isVolatileQualified()};
}

llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
CGF.AllocaInsertPt->getParent(), CGF.AllocaInsertPt->getIterator());
if (FailAO == llvm::AtomicOrdering::NotAtomic) {
// fail clause was not mentioned on the
// "#pragma omp atomic compare" construct.
CGF.Builder.restoreIP(OMPBuilder.createAtomicCompare(
CGF.Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
IsPostfixUpdate, IsFailOnly));
CGF.Builder.restoreIP(cantFail(OMPBuilder.createAtomicCompare(
CGF.Builder, AllocaIP, 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));
CGF.Builder.restoreIP(cantFail(OMPBuilder.createAtomicCompare(
CGF.Builder, AllocaIP, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op,
IsXBinopExpr, IsPostfixUpdate, IsFailOnly, FailAO)));
}

static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
Expand Down
36,250 changes: 23,272 additions & 12,978 deletions clang/test/OpenMP/atomic_compare_codegen.cpp

Large diffs are not rendered by default.

68 changes: 36 additions & 32 deletions flang/test/Integration/OpenMP/atomic-capture-complex.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,43 @@
! added to this directory and sub-directories.
!===----------------------------------------------------------------------===!

!RUN: %if x86-registered-target %{ %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fopenmp %s -o - | FileCheck --check-prefixes=CHECK,X86 %s %}
!RUN: %if aarch64-registerd-target %{ %flang_fc1 -triple aarch64-unknown-linux-gnu -emit-llvm -fopenmp %s -o - | FileCheck --check-prefixes=CHECK,AARCH64 %s %}
!RUN: %if x86-registered-target %{ %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fopenmp -mllvm --disable-llvm %s -o - | FileCheck %s %}
!RUN: %if aarch64-registerd-target %{ %flang_fc1 -triple aarch64-unknown-linux-gnu -emit-llvm -fopenmp -mllvm --disable-llvm %s -o - | FileCheck %s %}

!CHECK: %[[X_NEW_VAL:.*]] = alloca { float, float }, align 8
!CHECK: %[[VAL_1:.*]] = alloca { float, float }, i64 1, align 8
!CHECK: %[[ORIG_VAL:.*]] = alloca { float, float }, i64 1, align 8
!CHECK: store { float, float } { float 2.000000e+00, float 2.000000e+00 }, ptr %[[ORIG_VAL]], align 4
!CHECK: br label %entry

!CHECK: entry:
!CHECK: %[[ATOMIC_TEMP_LOAD:.*]] = alloca { float, float }, align 8
!CHECK: call void @__atomic_load(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], i32 0)
!CHECK: %[[PHI_NODE_ENTRY_1:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 8
!CHECK: br label %.atomic.cont

!CHECK: .atomic.cont
!CHECK: %[[VAL_4:.*]] = phi { float, float } [ %[[PHI_NODE_ENTRY_1]], %entry ], [ %{{.*}}, %.atomic.cont ]
!CHECK: %[[VAL_5:.*]] = extractvalue { float, float } %[[VAL_4]], 0
!CHECK: %[[VAL_6:.*]] = extractvalue { float, float } %[[VAL_4]], 1
!CHECK: %[[VAL_7:.*]] = fadd contract float %[[VAL_5]], 1.000000e+00
!CHECK: %[[VAL_8:.*]] = fadd contract float %[[VAL_6]], 1.000000e+00
!CHECK: %[[VAL_9:.*]] = insertvalue { float, float } undef, float %[[VAL_7]], 0
!CHECK: %[[VAL_10:.*]] = insertvalue { float, float } %[[VAL_9]], float %[[VAL_8]], 1
!CHECK: store { float, float } %[[VAL_10]], ptr %[[X_NEW_VAL]], align 4
!CHECK: %[[VAL_11:.*]] = call i1 @__atomic_compare_exchange(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], ptr %[[X_NEW_VAL]],
!i32 2, i32 2)
!CHECK: %[[VAL_12:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 4
!CHECK: br i1 %[[VAL_11]], label %.atomic.exit, label %.atomic.cont

!CHECK: .atomic.exit
!AARCH64: %[[LCSSA:.*]] = phi { float, float } [ %[[VAL_10]], %.atomic.cont ]
!AARCH64: store { float, float } %[[LCSSA]], ptr %[[VAL_1]], align 4
!X86: store { float, float } %[[VAL_10]], ptr %[[VAL_1]], align 4
! CHECK-LABEL: define {{.*}}@_QQmain(
! CHECK-NEXT: %[[DOTATOMIC_ORIG_PTR:.+]] = alloca { float, float }, align 8
! CHECK-NEXT: %[[DOTATOMIC_UPD_PTR:.+]] = alloca { float, float }, align 8
! CHECK-NEXT: %[[TMP1:.+]] = alloca { float, float }, i64 1, align 8
! CHECK-NEXT: %[[TMP2:.+]] = alloca { float, float }, i64 1, align 8
! CHECK-NEXT: store { float, float } { float 2.000000e+00, float 2.000000e+00 }, ptr %[[TMP2]], align 4
! CHECK-NEXT: br label %[[ENTRY:.+]]
! CHECK-EMPTY:
! CHECK-NEXT: [[ENTRY]]:
! CHECK-NEXT: %[[DOTATOMIC_LOAD:.+]] = load atomic i64, ptr %[[TMP2]] monotonic, align 8
! CHECK-NEXT: store i64 %[[DOTATOMIC_LOAD]], ptr %[[DOTATOMIC_ORIG_PTR]], align 8
! CHECK-NEXT: br label %[[DOTATOMIC_RETRY:.+]]
! CHECK-EMPTY:
! CHECK-NEXT: [[DOTATOMIC_RETRY]]:
! CHECK-NEXT: %[[DOTATOMIC_ORIG:.+]] = load { float, float }, ptr %[[DOTATOMIC_ORIG_PTR]], align 4
! CHECK-NEXT: %[[TMP3:.+]] = extractvalue { float, float } %[[DOTATOMIC_ORIG]], 0
! CHECK-NEXT: %[[TMP4:.+]] = extractvalue { float, float } %[[DOTATOMIC_ORIG]], 1
! CHECK-NEXT: %[[TMP5:.+]] = fadd contract float %[[TMP3]], 1.000000e+00
! CHECK-NEXT: %[[TMP6:.+]] = fadd contract float %[[TMP4]], 1.000000e+00
! CHECK-NEXT: %[[TMP7:.+]] = insertvalue { float, float } undef, float %[[TMP5]], 0
! CHECK-NEXT: %[[TMP8:.+]] = insertvalue { float, float } %[[TMP7]], float %[[TMP6]], 1
! CHECK-NEXT: store { float, float } %[[TMP8]], ptr %[[DOTATOMIC_UPD_PTR]], align 4
! CHECK-NEXT: %[[DOTCMPXCHG_EXPECTED:.+]] = load i64, ptr %[[DOTATOMIC_ORIG_PTR]], align 8
! CHECK-NEXT: %[[DOTCMPXCHG_DESIRED:.+]] = load i64, ptr %[[DOTATOMIC_UPD_PTR]], align 8
! CHECK-NEXT: %[[DOTCMPXCHG_PAIR:.+]] = cmpxchg weak ptr %[[TMP2]], i64 %[[DOTCMPXCHG_EXPECTED]], i64 %[[DOTCMPXCHG_DESIRED]] monotonic monotonic, align 8
! CHECK-NEXT: %[[DOTCMPXCHG_PREV:.+]] = extractvalue { i64, i1 } %[[DOTCMPXCHG_PAIR]], 0
! CHECK-NEXT: store i64 %[[DOTCMPXCHG_PREV]], ptr %[[DOTATOMIC_ORIG_PTR]], align 8
! CHECK-NEXT: %[[DOTCMPXCHG_SUCCESS:.+]] = extractvalue { i64, i1 } %[[DOTCMPXCHG_PAIR]], 1
! CHECK-NEXT: br i1 %[[DOTCMPXCHG_SUCCESS]], label %[[DOTATOMIC_DONE:.+]], label %[[DOTATOMIC_RETRY]]
! CHECK-EMPTY:
! CHECK-NEXT: [[DOTATOMIC_DONE]]:
! CHECK-NEXT: store { float, float } %[[TMP8]], ptr %[[TMP1]], align 4
! CHECK-NEXT: ret void
! CHECK-NEXT: }

program main
complex*8 ia, ib
Expand Down
41 changes: 20 additions & 21 deletions llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -3215,7 +3215,6 @@ class OpenMPIRBuilder {

/// Emit atomic update for constructs: X = X BinOp Expr ,or X = Expr BinOp X
/// For complex Operations: X = UpdateOp(X) => CmpExch X, old_X, UpdateOp(X)
/// Only Scalar data types.
///
/// \param AllocaIP The insertion point to be used for alloca
/// instructions.
Expand All @@ -3236,7 +3235,7 @@ class OpenMPIRBuilder {
/// (e.g. true for X = X BinOp Expr)
///
/// \returns A pair of the old value of X before the update, and the value
/// used for the update.
/// after the update.
Expected<std::pair<Value *, Value *>>
emitAtomicUpdate(InsertPointTy AllocaIP, Value *X, Type *XElemTy, Value *Expr,
AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp,
Expand All @@ -3258,7 +3257,7 @@ class OpenMPIRBuilder {
bool IsVolatile = false;
};

/// Emit atomic Read for : V = X --- Only Scalar data types.
/// Emit atomic Read for : V = X.
///
/// \param Loc The insert and source location description.
/// \param X The target pointer to be atomically read
Expand All @@ -3268,9 +3267,9 @@ class OpenMPIRBuilder {
/// instructions.
///
/// \return Insertion point after generated atomic read IR.
InsertPointTy createAtomicRead(const LocationDescription &Loc,
AtomicOpValue &X, AtomicOpValue &V,
AtomicOrdering AO);
InsertPointOrErrorTy createAtomicRead(const LocationDescription &Loc,
AtomicOpValue &X, AtomicOpValue &V,
AtomicOrdering AO);

/// Emit atomic write for : X = Expr --- Only Scalar data types.
///
Expand All @@ -3281,9 +3280,10 @@ class OpenMPIRBuilder {
/// instructions.
///
/// \return Insertion point after generated atomic Write IR.
InsertPointTy createAtomicWrite(const LocationDescription &Loc,
AtomicOpValue &X, Value *Expr,
AtomicOrdering AO);
InsertPointOrErrorTy createAtomicWrite(const LocationDescription &Loc,
InsertPointTy AllocaIP,
AtomicOpValue &X, Value *Expr,
AtomicOrdering AO);

/// Emit atomic update for constructs: X = X BinOp Expr ,or X = Expr BinOp X
/// For complex Operations: X = UpdateOp(X) => CmpExch X, old_X, UpdateOp(X)
Expand Down Expand Up @@ -3392,18 +3392,17 @@ class OpenMPIRBuilder {
/// the case the comparison is '=='.
///
/// \return Insertion point after generated atomic capture IR.
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);
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);
InsertPointOrErrorTy
createAtomicCompare(const LocationDescription &Loc, InsertPointTy AllocaIP,
AtomicOpValue &X, AtomicOpValue &V, AtomicOpValue &R,
Value *E, Value *D, AtomicOrdering AO,
omp::OMPAtomicCompareOp Op, bool IsXBinopExpr,
bool IsPostfixUpdate, bool IsFailOnly);
InsertPointOrErrorTy createAtomicCompare(
const LocationDescription &Loc, InsertPointTy AllocaIP, 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.
///
Expand Down
Loading