Skip to content

Commit 140cb1a

Browse files
committed
[clang] Fix invalid CodeGen for atomic fetch min/max on floating point values
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.
1 parent 3149a77 commit 140cb1a

File tree

2 files changed

+30
-10
lines changed

2 files changed

+30
-10
lines changed

clang/lib/CodeGen/CGAtomic.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -503,24 +503,27 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
503503
/// Duplicate the atomic min/max operation in conventional IR for the builtin
504504
/// variants that return the new rather than the original value.
505505
static llvm::Value *EmitPostAtomicMinMax(CGBuilderTy &Builder,
506-
AtomicExpr::AtomicOp Op,
507-
bool IsSigned,
508-
llvm::Value *OldVal,
506+
AtomicExpr::AtomicOp Op, bool IsInt,
507+
bool IsSigned, llvm::Value *OldVal,
509508
llvm::Value *RHS) {
510-
llvm::CmpInst::Predicate Pred;
509+
llvm::CmpInst::Predicate ICmpPred;
510+
llvm::FCmpInst::Predicate FCmpPred;
511511
switch (Op) {
512512
default:
513513
llvm_unreachable("Unexpected min/max operation");
514514
case AtomicExpr::AO__atomic_max_fetch:
515515
case AtomicExpr::AO__scoped_atomic_max_fetch:
516-
Pred = IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT;
516+
ICmpPred = IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT;
517+
FCmpPred = llvm::FCmpInst::FCMP_UGT;
517518
break;
518519
case AtomicExpr::AO__atomic_min_fetch:
519520
case AtomicExpr::AO__scoped_atomic_min_fetch:
520-
Pred = IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT;
521+
ICmpPred = IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT;
522+
FCmpPred = llvm::FCmpInst::FCMP_ULT;
521523
break;
522524
}
523-
llvm::Value *Cmp = Builder.CreateICmp(Pred, OldVal, RHS, "tst");
525+
llvm::Value *Cmp = IsInt ? Builder.CreateICmp(ICmpPred, OldVal, RHS, "tst")
526+
: Builder.CreateFCmp(FCmpPred, OldVal, RHS, "tst");
524527
return Builder.CreateSelect(Cmp, OldVal, RHS, "newval");
525528
}
526529

@@ -760,9 +763,9 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
760763
// determine the value which was written.
761764
llvm::Value *Result = RMWI;
762765
if (PostOpMinMax)
763-
Result = EmitPostAtomicMinMax(CGF.Builder, E->getOp(),
764-
E->getValueType()->isSignedIntegerType(),
765-
RMWI, LoadVal1);
766+
Result = EmitPostAtomicMinMax(
767+
CGF.Builder, E->getOp(), E->getValueType()->isIntegerType(),
768+
E->getValueType()->isSignedIntegerType(), RMWI, LoadVal1);
766769
else if (PostOp)
767770
Result = CGF.Builder.CreateBinOp((llvm::Instruction::BinaryOps)PostOp, RMWI,
768771
LoadVal1);

clang/test/CodeGen/Atomics.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ signed long long sll;
1212
unsigned long long ull;
1313
__int128 s128;
1414
unsigned __int128 u128;
15+
float f;
1516

1617
void test_op_ignore (void) // CHECK-LABEL: define{{.*}} void @test_op_ignore
1718
{
@@ -318,3 +319,19 @@ void test_atomic(void) {
318319
ui = __atomic_fetch_max(&ui, 5, __ATOMIC_ACQUIRE); // CHECK: atomicrmw umax {{.*}} acquire, align 4
319320
si = __atomic_fetch_max(&si, 5, __ATOMIC_RELEASE); // CHECK: atomicrmw max {{.*}} release, align 4
320321
}
322+
323+
void test_atomic_minmax_fp(void) {
324+
f = __atomic_fetch_min(&f, 5.0f, __ATOMIC_RELAXED);
325+
// CHECK: atomicrmw fmin {{.*}} monotonic, align 4
326+
327+
f = __atomic_fetch_max(&f, 5.0, __ATOMIC_RELAXED);
328+
// CHECK: atomicrmw fmax {{.*}} monotonic, align 4
329+
330+
f = __atomic_min_fetch(&f, 5.0, __ATOMIC_RELAXED);
331+
// CHECK: atomicrmw fmin {{.*}} monotonic, align 4
332+
// CHECK-NEXT: fcmp ult float {{.*}}, {{.*}}
333+
334+
f = __atomic_max_fetch(&f, 5.0, __ATOMIC_RELAXED);
335+
// CHECK: atomicrmw fmax {{.*}} monotonic, align 4
336+
// CHECK-NEXT: fcmp ugt float {{.*}}, {{.*}}
337+
}

0 commit comments

Comments
 (0)