Skip to content

Commit 38f95fa

Browse files
committed
- Formatting
- Amended logic to allow Clang to lower to expected intrinsics - Added Sema tests to atomic-ops-fp-minmax.c
1 parent a8043a7 commit 38f95fa

File tree

4 files changed

+76
-69
lines changed

4 files changed

+76
-69
lines changed

clang/lib/CodeGen/CGAtomic.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -507,32 +507,31 @@ static llvm::Value *EmitPostAtomicMinMax(CGBuilderTy &Builder,
507507
bool IsSigned,
508508
llvm::Value *OldVal,
509509
llvm::Value *RHS) {
510-
llvm::Type *ValTy = OldVal->getType();
510+
const bool IsFP = OldVal->getType()->isFloatingPointTy();
511511

512-
llvm::CmpInst::Predicate Pred;
513-
bool IsFP = ValTy->isFloatingPointTy();
512+
if (IsFP) {
513+
llvm::Intrinsic::ID IID = (Op == AtomicExpr::AO__atomic_max_fetch ||
514+
Op == AtomicExpr::AO__scoped_atomic_max_fetch)
515+
? llvm::Intrinsic::maxnum
516+
: llvm::Intrinsic::minnum;
517+
518+
return Builder.CreateBinaryIntrinsic(IID, OldVal, RHS, nullptr, "newval");
519+
}
514520

521+
llvm::CmpInst::Predicate Pred;
515522
switch (Op) {
516523
default:
517524
llvm_unreachable("Unexpected min/max operation");
518-
519525
case AtomicExpr::AO__atomic_max_fetch:
520526
case AtomicExpr::AO__scoped_atomic_max_fetch:
521-
Pred = IsFP ? llvm::CmpInst::FCMP_OGT
522-
: (IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT);
527+
Pred = IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT;
523528
break;
524-
525529
case AtomicExpr::AO__atomic_min_fetch:
526530
case AtomicExpr::AO__scoped_atomic_min_fetch:
527-
Pred = IsFP ? llvm::CmpInst::FCMP_OLT
528-
: (IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT);
531+
Pred = IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT;
529532
break;
530533
}
531-
532-
llvm::Value *Cmp = IsFP
533-
? static_cast<llvm::Value*>(Builder.CreateFCmp(Pred, OldVal, RHS, "tst"))
534-
: static_cast<llvm::Value*>(Builder.CreateICmp(Pred, OldVal, RHS, "tst"));
535-
534+
llvm::Value *Cmp = Builder.CreateICmp(Pred, OldVal, RHS, "tst");
536535
return Builder.CreateSelect(Cmp, OldVal, RHS, "newval");
537536
}
538537

clang/test/CodeGen/AArch64/atomic-ops-float-check-minmax.c

Lines changed: 46 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
2-
// RUN: %clang_cc1 %s -emit-llvm -o - -ffreestanding -triple=aarch64-linux-gnu -pthread -target-feature +bf16 | FileCheck %s
2+
// RUN: %clang_cc1 %s -emit-llvm -o - -ffreestanding -triple=aarch64-linux-gnu -pthread | FileCheck %s
33

44
#include <stdint.h>
55
#include <stdatomic.h>
@@ -15,18 +15,18 @@
1515
// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca double, align 8
1616
// CHECK-NEXT: [[DOTATOMICTMP1:%.*]] = alloca float, align 4
1717
// CHECK-NEXT: [[ATOMIC_TEMP2:%.*]] = alloca float, align 4
18-
// CHECK-NEXT: [[DOTATOMICTMP5:%.*]] = alloca half, align 2
19-
// CHECK-NEXT: [[ATOMIC_TEMP6:%.*]] = alloca half, align 2
20-
// CHECK-NEXT: [[DOTATOMICTMP9:%.*]] = alloca bfloat, align 2
21-
// CHECK-NEXT: [[ATOMIC_TEMP10:%.*]] = alloca bfloat, align 2
22-
// CHECK-NEXT: [[DOTATOMICTMP13:%.*]] = alloca double, align 8
23-
// CHECK-NEXT: [[ATOMIC_TEMP14:%.*]] = alloca double, align 8
24-
// CHECK-NEXT: [[DOTATOMICTMP17:%.*]] = alloca float, align 4
25-
// CHECK-NEXT: [[ATOMIC_TEMP18:%.*]] = alloca float, align 4
26-
// CHECK-NEXT: [[DOTATOMICTMP21:%.*]] = alloca half, align 2
27-
// CHECK-NEXT: [[ATOMIC_TEMP22:%.*]] = alloca half, align 2
28-
// CHECK-NEXT: [[DOTATOMICTMP25:%.*]] = alloca bfloat, align 2
29-
// CHECK-NEXT: [[ATOMIC_TEMP26:%.*]] = alloca bfloat, align 2
18+
// CHECK-NEXT: [[DOTATOMICTMP4:%.*]] = alloca half, align 2
19+
// CHECK-NEXT: [[ATOMIC_TEMP5:%.*]] = alloca half, align 2
20+
// CHECK-NEXT: [[DOTATOMICTMP7:%.*]] = alloca bfloat, align 2
21+
// CHECK-NEXT: [[ATOMIC_TEMP8:%.*]] = alloca bfloat, align 2
22+
// CHECK-NEXT: [[DOTATOMICTMP10:%.*]] = alloca double, align 8
23+
// CHECK-NEXT: [[ATOMIC_TEMP11:%.*]] = alloca double, align 8
24+
// CHECK-NEXT: [[DOTATOMICTMP13:%.*]] = alloca float, align 4
25+
// CHECK-NEXT: [[ATOMIC_TEMP14:%.*]] = alloca float, align 4
26+
// CHECK-NEXT: [[DOTATOMICTMP16:%.*]] = alloca half, align 2
27+
// CHECK-NEXT: [[ATOMIC_TEMP17:%.*]] = alloca half, align 2
28+
// CHECK-NEXT: [[DOTATOMICTMP19:%.*]] = alloca bfloat, align 2
29+
// CHECK-NEXT: [[ATOMIC_TEMP20:%.*]] = alloca bfloat, align 2
3030
// CHECK-NEXT: store ptr [[F32]], ptr [[F32_ADDR]], align 8
3131
// CHECK-NEXT: store ptr [[F16]], ptr [[F16_ADDR]], align 8
3232
// CHECK-NEXT: store ptr [[BF16]], ptr [[BF16_ADDR]], align 8
@@ -35,8 +35,7 @@
3535
// CHECK-NEXT: store double 4.210000e+01, ptr [[DOTATOMICTMP]], align 8
3636
// CHECK-NEXT: [[TMP1:%.*]] = load double, ptr [[DOTATOMICTMP]], align 8
3737
// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw fmax ptr [[TMP0]], double [[TMP1]] release, align 8
38-
// CHECK-NEXT: [[TST:%.*]] = fcmp ogt double [[TMP2]], [[TMP1]]
39-
// CHECK-NEXT: [[NEWVAL:%.*]] = select i1 [[TST]], double [[TMP2]], double [[TMP1]]
38+
// CHECK-NEXT: [[NEWVAL:%.*]] = call double @llvm.maxnum.f64(double [[TMP2]], double [[TMP1]])
4039
// CHECK-NEXT: store double [[NEWVAL]], ptr [[ATOMIC_TEMP]], align 8
4140
// CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[ATOMIC_TEMP]], align 8
4241
// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[F64_ADDR]], align 8
@@ -45,70 +44,63 @@
4544
// CHECK-NEXT: store float 0x40450CCCC0000000, ptr [[DOTATOMICTMP1]], align 4
4645
// CHECK-NEXT: [[TMP6:%.*]] = load float, ptr [[DOTATOMICTMP1]], align 4
4746
// CHECK-NEXT: [[TMP7:%.*]] = atomicrmw fmax ptr [[TMP5]], float [[TMP6]] release, align 4
48-
// CHECK-NEXT: [[TST3:%.*]] = fcmp ogt float [[TMP7]], [[TMP6]]
49-
// CHECK-NEXT: [[NEWVAL4:%.*]] = select i1 [[TST3]], float [[TMP7]], float [[TMP6]]
50-
// CHECK-NEXT: store float [[NEWVAL4]], ptr [[ATOMIC_TEMP2]], align 4
47+
// CHECK-NEXT: [[NEWVAL3:%.*]] = call float @llvm.maxnum.f32(float [[TMP7]], float [[TMP6]])
48+
// CHECK-NEXT: store float [[NEWVAL3]], ptr [[ATOMIC_TEMP2]], align 4
5149
// CHECK-NEXT: [[TMP8:%.*]] = load float, ptr [[ATOMIC_TEMP2]], align 4
5250
// CHECK-NEXT: [[TMP9:%.*]] = load ptr, ptr [[F32_ADDR]], align 8
5351
// CHECK-NEXT: store float [[TMP8]], ptr [[TMP9]], align 4
5452
// CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[F16_ADDR]], align 8
55-
// CHECK-NEXT: store half 0xH5143, ptr [[DOTATOMICTMP5]], align 2
56-
// CHECK-NEXT: [[TMP11:%.*]] = load half, ptr [[DOTATOMICTMP5]], align 2
53+
// CHECK-NEXT: store half 0xH5143, ptr [[DOTATOMICTMP4]], align 2
54+
// CHECK-NEXT: [[TMP11:%.*]] = load half, ptr [[DOTATOMICTMP4]], align 2
5755
// CHECK-NEXT: [[TMP12:%.*]] = atomicrmw fmax ptr [[TMP10]], half [[TMP11]] release, align 2
58-
// CHECK-NEXT: [[TST7:%.*]] = fcmp ogt half [[TMP12]], [[TMP11]]
59-
// CHECK-NEXT: [[NEWVAL8:%.*]] = select i1 [[TST7]], half [[TMP12]], half [[TMP11]]
60-
// CHECK-NEXT: store half [[NEWVAL8]], ptr [[ATOMIC_TEMP6]], align 2
61-
// CHECK-NEXT: [[TMP13:%.*]] = load half, ptr [[ATOMIC_TEMP6]], align 2
56+
// CHECK-NEXT: [[NEWVAL6:%.*]] = call half @llvm.maxnum.f16(half [[TMP12]], half [[TMP11]])
57+
// CHECK-NEXT: store half [[NEWVAL6]], ptr [[ATOMIC_TEMP5]], align 2
58+
// CHECK-NEXT: [[TMP13:%.*]] = load half, ptr [[ATOMIC_TEMP5]], align 2
6259
// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[F16_ADDR]], align 8
6360
// CHECK-NEXT: store half [[TMP13]], ptr [[TMP14]], align 2
6461
// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[BF16_ADDR]], align 8
65-
// CHECK-NEXT: store bfloat 0xR4228, ptr [[DOTATOMICTMP9]], align 2
66-
// CHECK-NEXT: [[TMP16:%.*]] = load bfloat, ptr [[DOTATOMICTMP9]], align 2
62+
// CHECK-NEXT: store bfloat 0xR4228, ptr [[DOTATOMICTMP7]], align 2
63+
// CHECK-NEXT: [[TMP16:%.*]] = load bfloat, ptr [[DOTATOMICTMP7]], align 2
6764
// CHECK-NEXT: [[TMP17:%.*]] = atomicrmw fmax ptr [[TMP15]], bfloat [[TMP16]] release, align 2
68-
// CHECK-NEXT: [[TST11:%.*]] = fcmp ogt bfloat [[TMP17]], [[TMP16]]
69-
// CHECK-NEXT: [[NEWVAL12:%.*]] = select i1 [[TST11]], bfloat [[TMP17]], bfloat [[TMP16]]
70-
// CHECK-NEXT: store bfloat [[NEWVAL12]], ptr [[ATOMIC_TEMP10]], align 2
71-
// CHECK-NEXT: [[TMP18:%.*]] = load bfloat, ptr [[ATOMIC_TEMP10]], align 2
65+
// CHECK-NEXT: [[NEWVAL9:%.*]] = call bfloat @llvm.maxnum.bf16(bfloat [[TMP17]], bfloat [[TMP16]])
66+
// CHECK-NEXT: store bfloat [[NEWVAL9]], ptr [[ATOMIC_TEMP8]], align 2
67+
// CHECK-NEXT: [[TMP18:%.*]] = load bfloat, ptr [[ATOMIC_TEMP8]], align 2
7268
// CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[BF16_ADDR]], align 8
7369
// CHECK-NEXT: store bfloat [[TMP18]], ptr [[TMP19]], align 2
7470
// CHECK-NEXT: [[TMP20:%.*]] = load ptr, ptr [[F64_ADDR]], align 8
75-
// CHECK-NEXT: store double 4.210000e+01, ptr [[DOTATOMICTMP13]], align 8
76-
// CHECK-NEXT: [[TMP21:%.*]] = load double, ptr [[DOTATOMICTMP13]], align 8
71+
// CHECK-NEXT: store double 4.210000e+01, ptr [[DOTATOMICTMP10]], align 8
72+
// CHECK-NEXT: [[TMP21:%.*]] = load double, ptr [[DOTATOMICTMP10]], align 8
7773
// CHECK-NEXT: [[TMP22:%.*]] = atomicrmw fmin ptr [[TMP20]], double [[TMP21]] release, align 8
78-
// CHECK-NEXT: [[TST15:%.*]] = fcmp olt double [[TMP22]], [[TMP21]]
79-
// CHECK-NEXT: [[NEWVAL16:%.*]] = select i1 [[TST15]], double [[TMP22]], double [[TMP21]]
80-
// CHECK-NEXT: store double [[NEWVAL16]], ptr [[ATOMIC_TEMP14]], align 8
81-
// CHECK-NEXT: [[TMP23:%.*]] = load double, ptr [[ATOMIC_TEMP14]], align 8
74+
// CHECK-NEXT: [[NEWVAL12:%.*]] = call double @llvm.minnum.f64(double [[TMP22]], double [[TMP21]])
75+
// CHECK-NEXT: store double [[NEWVAL12]], ptr [[ATOMIC_TEMP11]], align 8
76+
// CHECK-NEXT: [[TMP23:%.*]] = load double, ptr [[ATOMIC_TEMP11]], align 8
8277
// CHECK-NEXT: [[TMP24:%.*]] = load ptr, ptr [[F64_ADDR]], align 8
8378
// CHECK-NEXT: store double [[TMP23]], ptr [[TMP24]], align 8
8479
// CHECK-NEXT: [[TMP25:%.*]] = load ptr, ptr [[F32_ADDR]], align 8
85-
// CHECK-NEXT: store float 0x40450CCCC0000000, ptr [[DOTATOMICTMP17]], align 4
86-
// CHECK-NEXT: [[TMP26:%.*]] = load float, ptr [[DOTATOMICTMP17]], align 4
80+
// CHECK-NEXT: store float 0x40450CCCC0000000, ptr [[DOTATOMICTMP13]], align 4
81+
// CHECK-NEXT: [[TMP26:%.*]] = load float, ptr [[DOTATOMICTMP13]], align 4
8782
// CHECK-NEXT: [[TMP27:%.*]] = atomicrmw fmin ptr [[TMP25]], float [[TMP26]] release, align 4
88-
// CHECK-NEXT: [[TST19:%.*]] = fcmp olt float [[TMP27]], [[TMP26]]
89-
// CHECK-NEXT: [[NEWVAL20:%.*]] = select i1 [[TST19]], float [[TMP27]], float [[TMP26]]
90-
// CHECK-NEXT: store float [[NEWVAL20]], ptr [[ATOMIC_TEMP18]], align 4
91-
// CHECK-NEXT: [[TMP28:%.*]] = load float, ptr [[ATOMIC_TEMP18]], align 4
83+
// CHECK-NEXT: [[NEWVAL15:%.*]] = call float @llvm.minnum.f32(float [[TMP27]], float [[TMP26]])
84+
// CHECK-NEXT: store float [[NEWVAL15]], ptr [[ATOMIC_TEMP14]], align 4
85+
// CHECK-NEXT: [[TMP28:%.*]] = load float, ptr [[ATOMIC_TEMP14]], align 4
9286
// CHECK-NEXT: [[TMP29:%.*]] = load ptr, ptr [[F32_ADDR]], align 8
9387
// CHECK-NEXT: store float [[TMP28]], ptr [[TMP29]], align 4
9488
// CHECK-NEXT: [[TMP30:%.*]] = load ptr, ptr [[F16_ADDR]], align 8
95-
// CHECK-NEXT: store half 0xH5143, ptr [[DOTATOMICTMP21]], align 2
96-
// CHECK-NEXT: [[TMP31:%.*]] = load half, ptr [[DOTATOMICTMP21]], align 2
89+
// CHECK-NEXT: store half 0xH5143, ptr [[DOTATOMICTMP16]], align 2
90+
// CHECK-NEXT: [[TMP31:%.*]] = load half, ptr [[DOTATOMICTMP16]], align 2
9791
// CHECK-NEXT: [[TMP32:%.*]] = atomicrmw fmin ptr [[TMP30]], half [[TMP31]] release, align 2
98-
// CHECK-NEXT: [[TST23:%.*]] = fcmp olt half [[TMP32]], [[TMP31]]
99-
// CHECK-NEXT: [[NEWVAL24:%.*]] = select i1 [[TST23]], half [[TMP32]], half [[TMP31]]
100-
// CHECK-NEXT: store half [[NEWVAL24]], ptr [[ATOMIC_TEMP22]], align 2
101-
// CHECK-NEXT: [[TMP33:%.*]] = load half, ptr [[ATOMIC_TEMP22]], align 2
92+
// CHECK-NEXT: [[NEWVAL18:%.*]] = call half @llvm.minnum.f16(half [[TMP32]], half [[TMP31]])
93+
// CHECK-NEXT: store half [[NEWVAL18]], ptr [[ATOMIC_TEMP17]], align 2
94+
// CHECK-NEXT: [[TMP33:%.*]] = load half, ptr [[ATOMIC_TEMP17]], align 2
10295
// CHECK-NEXT: [[TMP34:%.*]] = load ptr, ptr [[F16_ADDR]], align 8
10396
// CHECK-NEXT: store half [[TMP33]], ptr [[TMP34]], align 2
10497
// CHECK-NEXT: [[TMP35:%.*]] = load ptr, ptr [[BF16_ADDR]], align 8
105-
// CHECK-NEXT: store bfloat 0xR4228, ptr [[DOTATOMICTMP25]], align 2
106-
// CHECK-NEXT: [[TMP36:%.*]] = load bfloat, ptr [[DOTATOMICTMP25]], align 2
98+
// CHECK-NEXT: store bfloat 0xR4228, ptr [[DOTATOMICTMP19]], align 2
99+
// CHECK-NEXT: [[TMP36:%.*]] = load bfloat, ptr [[DOTATOMICTMP19]], align 2
107100
// CHECK-NEXT: [[TMP37:%.*]] = atomicrmw fmin ptr [[TMP35]], bfloat [[TMP36]] release, align 2
108-
// CHECK-NEXT: [[TST27:%.*]] = fcmp olt bfloat [[TMP37]], [[TMP36]]
109-
// CHECK-NEXT: [[NEWVAL28:%.*]] = select i1 [[TST27]], bfloat [[TMP37]], bfloat [[TMP36]]
110-
// CHECK-NEXT: store bfloat [[NEWVAL28]], ptr [[ATOMIC_TEMP26]], align 2
111-
// CHECK-NEXT: [[TMP38:%.*]] = load bfloat, ptr [[ATOMIC_TEMP26]], align 2
101+
// CHECK-NEXT: [[NEWVAL21:%.*]] = call bfloat @llvm.minnum.bf16(bfloat [[TMP37]], bfloat [[TMP36]])
102+
// CHECK-NEXT: store bfloat [[NEWVAL21]], ptr [[ATOMIC_TEMP20]], align 2
103+
// CHECK-NEXT: [[TMP38:%.*]] = load bfloat, ptr [[ATOMIC_TEMP20]], align 2
112104
// CHECK-NEXT: [[TMP39:%.*]] = load ptr, ptr [[BF16_ADDR]], align 8
113105
// CHECK-NEXT: store bfloat [[TMP38]], ptr [[TMP39]], align 2
114106
// CHECK-NEXT: ret void
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %clang_cc1 -verify -ffreestanding -triple=aarch64-linux-gnu %s
2+
// REQUIRES: aarch64-registered-target
3+
4+
#include <stdatomic.h>
5+
6+
void memory_checks(_Float16 *p16, __bf16 *pbf, float *pf, double *pd) {
7+
(void)__atomic_fetch_min(p16, (_Float16)1.0f, memory_order_relaxed);
8+
(void)__atomic_fetch_max(pbf, (__bf16)2.0f, memory_order_acquire);
9+
(void)__atomic_fetch_min(pf, 3.0f, memory_order_release);
10+
(void)__atomic_fetch_max(pd, 4.0, memory_order_seq_cst);
11+
}
12+
13+
void nullPointerWarning(void) {
14+
(void)__atomic_fetch_min((volatile float*)0, 42.0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
15+
(void)__atomic_fetch_max((float*)0, 42.0, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
16+
}

clang/test/Sema/atomic-ops.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ void nullPointerWarning(void) {
827827
(void)__atomic_fetch_min((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
828828
(void)__atomic_fetch_max((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
829829
(void)__atomic_fetch_max((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
830-
830+
831831
// These don't warn: the "desired" parameter is passed by value. Even for
832832
// atomic pointers the "desired" result can be NULL.
833833
__c11_atomic_init(&vai, 0);

0 commit comments

Comments
 (0)