Skip to content

Commit f17b1fb

Browse files
[Clang][CodeGen] Optimised LLVM IR for atomic increments/decrements on floats (#89362)
Fixes #53079
1 parent 171aeb2 commit f17b1fb

File tree

3 files changed

+382
-309
lines changed

3 files changed

+382
-309
lines changed

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2801,6 +2801,19 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
28012801
llvm::AtomicOrdering::SequentiallyConsistent);
28022802
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
28032803
}
2804+
// Special case for atomic increment/decrement on floats
2805+
if (type->isFloatingType()) {
2806+
llvm::AtomicRMWInst::BinOp aop =
2807+
isInc ? llvm::AtomicRMWInst::FAdd : llvm::AtomicRMWInst::FSub;
2808+
llvm::Instruction::BinaryOps op =
2809+
isInc ? llvm::Instruction::FAdd : llvm::Instruction::FSub;
2810+
llvm::Value *amt = llvm::ConstantFP::get(
2811+
VMContext, llvm::APFloat(static_cast<float>(1.0)));
2812+
llvm::Value *old =
2813+
Builder.CreateAtomicRMW(aop, LV.getAddress(CGF), amt,
2814+
llvm::AtomicOrdering::SequentiallyConsistent);
2815+
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
2816+
}
28042817
value = EmitLoadOfLValue(LV, E->getExprLoc());
28052818
input = value;
28062819
// For every other atomic operation, we need to emit a load-op-cmpxchg loop
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
2+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -target-cpu core2 %s -S -emit-llvm -o - | FileCheck -check-prefixes=CHECK,CHECK64 %s
3+
// RUN: %clang_cc1 -triple i686-linux-gnu -target-cpu core2 %s -S -emit-llvm -o - | FileCheck -check-prefixes=CHECK,CHECK32 %s
4+
5+
6+
// CHECK-LABEL: define dso_local i32 @test_int_inc(
7+
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
8+
// CHECK-NEXT: entry:
9+
// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr @test_int_inc.n, i32 1 seq_cst, align 4
10+
// CHECK-NEXT: ret i32 [[TMP0]]
11+
//
12+
int test_int_inc()
13+
{
14+
static _Atomic int n;
15+
return n++;
16+
}
17+
18+
// CHECK-LABEL: define dso_local float @test_float_post_inc(
19+
// CHECK-SAME: ) #[[ATTR0]] {
20+
// CHECK-NEXT: entry:
21+
// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_float_post_inc.n, float 1.000000e+00 seq_cst, align 4
22+
// CHECK-NEXT: ret float [[TMP0]]
23+
//
24+
float test_float_post_inc()
25+
{
26+
static _Atomic float n;
27+
return n++;
28+
}
29+
30+
// CHECK-LABEL: define dso_local float @test_float_post_dc(
31+
// CHECK-SAME: ) #[[ATTR0]] {
32+
// CHECK-NEXT: entry:
33+
// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_float_post_dc.n, float 1.000000e+00 seq_cst, align 4
34+
// CHECK-NEXT: ret float [[TMP0]]
35+
//
36+
float test_float_post_dc()
37+
{
38+
static _Atomic float n;
39+
return n--;
40+
}
41+
42+
// CHECK-LABEL: define dso_local float @test_float_pre_dc(
43+
// CHECK-SAME: ) #[[ATTR0]] {
44+
// CHECK-NEXT: entry:
45+
// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_float_pre_dc.n, float 1.000000e+00 seq_cst, align 4
46+
// CHECK-NEXT: [[TMP1:%.*]] = fsub float [[TMP0]], 1.000000e+00
47+
// CHECK-NEXT: ret float [[TMP1]]
48+
//
49+
float test_float_pre_dc()
50+
{
51+
static _Atomic float n;
52+
return --n;
53+
}
54+
55+
// CHECK-LABEL: define dso_local float @test_float_pre_inc(
56+
// CHECK-SAME: ) #[[ATTR0]] {
57+
// CHECK-NEXT: entry:
58+
// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_float_pre_inc.n, float 1.000000e+00 seq_cst, align 4
59+
// CHECK-NEXT: [[TMP1:%.*]] = fadd float [[TMP0]], 1.000000e+00
60+
// CHECK-NEXT: ret float [[TMP1]]
61+
//
62+
float test_float_pre_inc()
63+
{
64+
static _Atomic float n;
65+
return ++n;
66+
}
67+
//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
68+
// CHECK32: {{.*}}
69+
// CHECK64: {{.*}}

0 commit comments

Comments
 (0)