[clang] [clang] Fix invalid CodeGen for atomic fetch min/max on floating point values (PR #162011)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 5 05:50:17 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
Author: Sirui Mu (Lancern)
<details>
<summary>Changes</summary>
CodeGen for the builtin function `__atomic_min_fetch` and `__atomic_max_fetch` would emit an `atomicrmw` instruction followed by an `icmp` instruction on integral arguments. However, for floating point arguments, CodeGen keeps emitting `icmp` instruction instead of `fcmp` instruction.
This patch fixes the issue.
---
Full diff: https://github.com/llvm/llvm-project/pull/162011.diff
2 Files Affected:
- (modified) clang/lib/CodeGen/CGAtomic.cpp (+13-10)
- (modified) clang/test/CodeGen/Atomics.c (+17)
``````````diff
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index 4a3446abcc78f..0a6419476c338 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -503,24 +503,27 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
/// Duplicate the atomic min/max operation in conventional IR for the builtin
/// variants that return the new rather than the original value.
static llvm::Value *EmitPostAtomicMinMax(CGBuilderTy &Builder,
- AtomicExpr::AtomicOp Op,
- bool IsSigned,
- llvm::Value *OldVal,
+ AtomicExpr::AtomicOp Op, bool IsInt,
+ bool IsSigned, llvm::Value *OldVal,
llvm::Value *RHS) {
- llvm::CmpInst::Predicate Pred;
+ llvm::CmpInst::Predicate ICmpPred;
+ llvm::FCmpInst::Predicate FCmpPred;
switch (Op) {
default:
llvm_unreachable("Unexpected min/max operation");
case AtomicExpr::AO__atomic_max_fetch:
case AtomicExpr::AO__scoped_atomic_max_fetch:
- Pred = IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT;
+ ICmpPred = IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT;
+ FCmpPred = llvm::FCmpInst::FCMP_UGT;
break;
case AtomicExpr::AO__atomic_min_fetch:
case AtomicExpr::AO__scoped_atomic_min_fetch:
- Pred = IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT;
+ ICmpPred = IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT;
+ FCmpPred = llvm::FCmpInst::FCMP_ULT;
break;
}
- llvm::Value *Cmp = Builder.CreateICmp(Pred, OldVal, RHS, "tst");
+ llvm::Value *Cmp = IsInt ? Builder.CreateICmp(ICmpPred, OldVal, RHS, "tst")
+ : Builder.CreateFCmp(FCmpPred, OldVal, RHS, "tst");
return Builder.CreateSelect(Cmp, OldVal, RHS, "newval");
}
@@ -760,9 +763,9 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
// determine the value which was written.
llvm::Value *Result = RMWI;
if (PostOpMinMax)
- Result = EmitPostAtomicMinMax(CGF.Builder, E->getOp(),
- E->getValueType()->isSignedIntegerType(),
- RMWI, LoadVal1);
+ Result = EmitPostAtomicMinMax(
+ CGF.Builder, E->getOp(), E->getValueType()->isIntegerType(),
+ E->getValueType()->isSignedIntegerType(), RMWI, LoadVal1);
else if (PostOp)
Result = CGF.Builder.CreateBinOp((llvm::Instruction::BinaryOps)PostOp, RMWI,
LoadVal1);
diff --git a/clang/test/CodeGen/Atomics.c b/clang/test/CodeGen/Atomics.c
index c44f45efacab0..dd5936cf48b46 100644
--- a/clang/test/CodeGen/Atomics.c
+++ b/clang/test/CodeGen/Atomics.c
@@ -12,6 +12,7 @@ signed long long sll;
unsigned long long ull;
__int128 s128;
unsigned __int128 u128;
+float f;
void test_op_ignore (void) // CHECK-LABEL: define{{.*}} void @test_op_ignore
{
@@ -318,3 +319,19 @@ void test_atomic(void) {
ui = __atomic_fetch_max(&ui, 5, __ATOMIC_ACQUIRE); // CHECK: atomicrmw umax {{.*}} acquire, align 4
si = __atomic_fetch_max(&si, 5, __ATOMIC_RELEASE); // CHECK: atomicrmw max {{.*}} release, align 4
}
+
+void test_atomic_minmax_fp(void) {
+ f = __atomic_fetch_min(&f, 5.0f, __ATOMIC_RELAXED);
+ // CHECK: atomicrmw fmin {{.*}} monotonic, align 4
+
+ f = __atomic_fetch_max(&f, 5.0, __ATOMIC_RELAXED);
+ // CHECK: atomicrmw fmax {{.*}} monotonic, align 4
+
+ f = __atomic_min_fetch(&f, 5.0, __ATOMIC_RELAXED);
+ // CHECK: atomicrmw fmin {{.*}} monotonic, align 4
+ // CHECK-NEXT: fcmp ult float {{.*}}, {{.*}}
+
+ f = __atomic_max_fetch(&f, 5.0, __ATOMIC_RELAXED);
+ // CHECK: atomicrmw fmax {{.*}} monotonic, align 4
+ // CHECK-NEXT: fcmp ugt float {{.*}}, {{.*}}
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/162011
More information about the cfe-commits
mailing list