Skip to content

Commit 149bfdd

Browse files
dtcxzywtru
authored andcommitted
[Clang][CodeGen] Fix type for atomic float incdec operators (#107075)
`llvm::ConstantFP::get(llvm::LLVMContext&, APFloat(float))` always returns a f32 constant. Fix #107054.
1 parent 8a25c60 commit 149bfdd

File tree

3 files changed

+300
-107
lines changed

3 files changed

+300
-107
lines changed

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2833,18 +2833,22 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
28332833
llvm::AtomicOrdering::SequentiallyConsistent);
28342834
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
28352835
}
2836-
// Special case for atomic increment/decrement on floats
2836+
// Special case for atomic increment/decrement on floats.
2837+
// Bail out non-power-of-2-sized floating point types (e.g., x86_fp80).
28372838
if (type->isFloatingType()) {
2838-
llvm::AtomicRMWInst::BinOp aop =
2839-
isInc ? llvm::AtomicRMWInst::FAdd : llvm::AtomicRMWInst::FSub;
2840-
llvm::Instruction::BinaryOps op =
2841-
isInc ? llvm::Instruction::FAdd : llvm::Instruction::FSub;
2842-
llvm::Value *amt = llvm::ConstantFP::get(
2843-
VMContext, llvm::APFloat(static_cast<float>(1.0)));
2844-
llvm::Value *old =
2845-
Builder.CreateAtomicRMW(aop, LV.getAddress(), amt,
2846-
llvm::AtomicOrdering::SequentiallyConsistent);
2847-
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
2839+
llvm::Type *Ty = ConvertType(type);
2840+
if (llvm::has_single_bit(Ty->getScalarSizeInBits())) {
2841+
llvm::AtomicRMWInst::BinOp aop =
2842+
isInc ? llvm::AtomicRMWInst::FAdd : llvm::AtomicRMWInst::FSub;
2843+
llvm::Instruction::BinaryOps op =
2844+
isInc ? llvm::Instruction::FAdd : llvm::Instruction::FSub;
2845+
llvm::Value *amt = llvm::ConstantFP::get(Ty, 1.0);
2846+
llvm::AtomicRMWInst *old = Builder.CreateAtomicRMW(
2847+
aop, LV.getAddress(), amt,
2848+
llvm::AtomicOrdering::SequentiallyConsistent);
2849+
2850+
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
2851+
}
28482852
}
28492853
value = EmitLoadOfLValue(LV, E->getExprLoc());
28502854
input = value;

clang/test/CodeGen/X86/x86-atomic-double.c

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,14 @@
66
// X64-LABEL: define dso_local double @test_double_post_inc(
77
// X64-SAME: ) #[[ATTR0:[0-9]+]] {
88
// X64-NEXT: entry:
9-
// X64-NEXT: [[RETVAL:%.*]] = alloca double, align 8
10-
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_post_inc.n, float 1.000000e+00 seq_cst, align 8
11-
// X64-NEXT: store float [[TMP0]], ptr [[RETVAL]], align 8
12-
// X64-NEXT: [[TMP1:%.*]] = load double, ptr [[RETVAL]], align 8
13-
// X64-NEXT: ret double [[TMP1]]
9+
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_post_inc.n, double 1.000000e+00 seq_cst, align 8
10+
// X64-NEXT: ret double [[TMP0]]
1411
//
1512
// X86-LABEL: define dso_local double @test_double_post_inc(
1613
// X86-SAME: ) #[[ATTR0:[0-9]+]] {
1714
// X86-NEXT: entry:
18-
// X86-NEXT: [[RETVAL:%.*]] = alloca double, align 4
19-
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_post_inc.n, float 1.000000e+00 seq_cst, align 8
20-
// X86-NEXT: store float [[TMP0]], ptr [[RETVAL]], align 4
21-
// X86-NEXT: [[TMP1:%.*]] = load double, ptr [[RETVAL]], align 4
22-
// X86-NEXT: ret double [[TMP1]]
15+
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_post_inc.n, double 1.000000e+00 seq_cst, align 8
16+
// X86-NEXT: ret double [[TMP0]]
2317
//
2418
double test_double_post_inc()
2519
{
@@ -30,20 +24,14 @@ double test_double_post_inc()
3024
// X64-LABEL: define dso_local double @test_double_post_dc(
3125
// X64-SAME: ) #[[ATTR0]] {
3226
// X64-NEXT: entry:
33-
// X64-NEXT: [[RETVAL:%.*]] = alloca double, align 8
34-
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_post_dc.n, float 1.000000e+00 seq_cst, align 8
35-
// X64-NEXT: store float [[TMP0]], ptr [[RETVAL]], align 8
36-
// X64-NEXT: [[TMP1:%.*]] = load double, ptr [[RETVAL]], align 8
37-
// X64-NEXT: ret double [[TMP1]]
27+
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_post_dc.n, double 1.000000e+00 seq_cst, align 8
28+
// X64-NEXT: ret double [[TMP0]]
3829
//
3930
// X86-LABEL: define dso_local double @test_double_post_dc(
4031
// X86-SAME: ) #[[ATTR0]] {
4132
// X86-NEXT: entry:
42-
// X86-NEXT: [[RETVAL:%.*]] = alloca double, align 4
43-
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_post_dc.n, float 1.000000e+00 seq_cst, align 8
44-
// X86-NEXT: store float [[TMP0]], ptr [[RETVAL]], align 4
45-
// X86-NEXT: [[TMP1:%.*]] = load double, ptr [[RETVAL]], align 4
46-
// X86-NEXT: ret double [[TMP1]]
33+
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_post_dc.n, double 1.000000e+00 seq_cst, align 8
34+
// X86-NEXT: ret double [[TMP0]]
4735
//
4836
double test_double_post_dc()
4937
{
@@ -54,22 +42,16 @@ double test_double_post_dc()
5442
// X64-LABEL: define dso_local double @test_double_pre_dc(
5543
// X64-SAME: ) #[[ATTR0]] {
5644
// X64-NEXT: entry:
57-
// X64-NEXT: [[RETVAL:%.*]] = alloca double, align 8
58-
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_pre_dc.n, float 1.000000e+00 seq_cst, align 8
59-
// X64-NEXT: [[TMP1:%.*]] = fsub float [[TMP0]], 1.000000e+00
60-
// X64-NEXT: store float [[TMP1]], ptr [[RETVAL]], align 8
61-
// X64-NEXT: [[TMP2:%.*]] = load double, ptr [[RETVAL]], align 8
62-
// X64-NEXT: ret double [[TMP2]]
45+
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_pre_dc.n, double 1.000000e+00 seq_cst, align 8
46+
// X64-NEXT: [[TMP1:%.*]] = fsub double [[TMP0]], 1.000000e+00
47+
// X64-NEXT: ret double [[TMP1]]
6348
//
6449
// X86-LABEL: define dso_local double @test_double_pre_dc(
6550
// X86-SAME: ) #[[ATTR0]] {
6651
// X86-NEXT: entry:
67-
// X86-NEXT: [[RETVAL:%.*]] = alloca double, align 4
68-
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_pre_dc.n, float 1.000000e+00 seq_cst, align 8
69-
// X86-NEXT: [[TMP1:%.*]] = fsub float [[TMP0]], 1.000000e+00
70-
// X86-NEXT: store float [[TMP1]], ptr [[RETVAL]], align 4
71-
// X86-NEXT: [[TMP2:%.*]] = load double, ptr [[RETVAL]], align 4
72-
// X86-NEXT: ret double [[TMP2]]
52+
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_pre_dc.n, double 1.000000e+00 seq_cst, align 8
53+
// X86-NEXT: [[TMP1:%.*]] = fsub double [[TMP0]], 1.000000e+00
54+
// X86-NEXT: ret double [[TMP1]]
7355
//
7456
double test_double_pre_dc()
7557
{
@@ -80,25 +62,43 @@ double test_double_pre_dc()
8062
// X64-LABEL: define dso_local double @test_double_pre_inc(
8163
// X64-SAME: ) #[[ATTR0]] {
8264
// X64-NEXT: entry:
83-
// X64-NEXT: [[RETVAL:%.*]] = alloca double, align 8
84-
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_pre_inc.n, float 1.000000e+00 seq_cst, align 8
85-
// X64-NEXT: [[TMP1:%.*]] = fadd float [[TMP0]], 1.000000e+00
86-
// X64-NEXT: store float [[TMP1]], ptr [[RETVAL]], align 8
87-
// X64-NEXT: [[TMP2:%.*]] = load double, ptr [[RETVAL]], align 8
88-
// X64-NEXT: ret double [[TMP2]]
65+
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_pre_inc.n, double 1.000000e+00 seq_cst, align 8
66+
// X64-NEXT: [[TMP1:%.*]] = fadd double [[TMP0]], 1.000000e+00
67+
// X64-NEXT: ret double [[TMP1]]
8968
//
9069
// X86-LABEL: define dso_local double @test_double_pre_inc(
9170
// X86-SAME: ) #[[ATTR0]] {
9271
// X86-NEXT: entry:
93-
// X86-NEXT: [[RETVAL:%.*]] = alloca double, align 4
94-
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_pre_inc.n, float 1.000000e+00 seq_cst, align 8
95-
// X86-NEXT: [[TMP1:%.*]] = fadd float [[TMP0]], 1.000000e+00
96-
// X86-NEXT: store float [[TMP1]], ptr [[RETVAL]], align 4
97-
// X86-NEXT: [[TMP2:%.*]] = load double, ptr [[RETVAL]], align 4
98-
// X86-NEXT: ret double [[TMP2]]
72+
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_pre_inc.n, double 1.000000e+00 seq_cst, align 8
73+
// X86-NEXT: [[TMP1:%.*]] = fadd double [[TMP0]], 1.000000e+00
74+
// X86-NEXT: ret double [[TMP1]]
9975
//
10076
double test_double_pre_inc()
10177
{
10278
static _Atomic double n;
10379
return ++n;
10480
}
81+
82+
// X64-LABEL: define dso_local i32 @pr107054(
83+
// X64-SAME: ) #[[ATTR0]] {
84+
// X64-NEXT: entry:
85+
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @pr107054.n, double 1.000000e+00 seq_cst, align 8
86+
// X64-NEXT: [[TMP1:%.*]] = fadd double [[TMP0]], 1.000000e+00
87+
// X64-NEXT: [[CMP:%.*]] = fcmp oeq double [[TMP1]], 1.000000e+00
88+
// X64-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
89+
// X64-NEXT: ret i32 [[CONV]]
90+
//
91+
// X86-LABEL: define dso_local i32 @pr107054(
92+
// X86-SAME: ) #[[ATTR0]] {
93+
// X86-NEXT: entry:
94+
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @pr107054.n, double 1.000000e+00 seq_cst, align 8
95+
// X86-NEXT: [[TMP1:%.*]] = fadd double [[TMP0]], 1.000000e+00
96+
// X86-NEXT: [[CMP:%.*]] = fcmp oeq double [[TMP1]], 1.000000e+00
97+
// X86-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
98+
// X86-NEXT: ret i32 [[CONV]]
99+
//
100+
int pr107054()
101+
{
102+
static _Atomic double n;
103+
return (++n) == 1;
104+
}

0 commit comments

Comments
 (0)