Skip to content

Commit aa73124

Browse files
authored
Fix complex long double division with -mno-x87. (#133152)
The combination of `-fcomplex-arithmetic=promoted` and `mno-x87` for `double` complex division is leading to a crash. See https://godbolt.org/z/189G957oY This patch fixes that.
1 parent 1ab3a4f commit aa73124

File tree

3 files changed

+91
-2
lines changed

3 files changed

+91
-2
lines changed

clang/lib/CodeGen/CGExprComplex.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,10 @@ class ComplexExprEmitter
303303
// doubles the exponent of SmallerType.LargestFiniteVal)
304304
if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <=
305305
llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
306+
if (!Ctx.getTargetInfo().hasLongDoubleType() &&
307+
HigherElementType.getCanonicalType().getUnqualifiedType() ==
308+
Ctx.LongDoubleTy)
309+
return QualType();
306310
FPHasBeenPromoted = true;
307311
return Ctx.getComplexType(HigherElementType);
308312
} else {

clang/lib/Sema/SemaExpr.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15329,8 +15329,10 @@ static void DetectPrecisionLossInComplexDivision(Sema &S, SourceLocation OpLoc,
1532915329
Ctx.getFloatTypeSemantics(ElementType);
1533015330
const llvm::fltSemantics &HigherElementTypeSemantics =
1533115331
Ctx.getFloatTypeSemantics(HigherElementType);
15332-
if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 >
15333-
llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
15332+
if ((llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 >
15333+
llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) ||
15334+
(HigherElementType == Ctx.LongDoubleTy &&
15335+
!Ctx.getTargetInfo().hasLongDoubleType())) {
1533415336
// Retain the location of the first use of higher precision type.
1533515337
if (!S.LocationOfExcessPrecisionNotSatisfied.isValid())
1533615338
S.LocationOfExcessPrecisionNotSatisfied = OpLoc;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
2+
// RUN: -verify -complex-range=promoted -o - | FileCheck %s
3+
4+
// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
5+
// RUN: -verify=nopromotion -complex-range=promoted -target-feature -x87 \
6+
// RUN: -o - | FileCheck %s --check-prefix=NOX87
7+
8+
// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-windows \
9+
// RUN: -verify=nopromotion -complex-range=promoted -o - \
10+
// RUN: | FileCheck %s --check-prefix=NOX87
11+
12+
// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-windows \
13+
// RUN: -verify=nopromotion -complex-range=promoted -target-feature -x87 \
14+
// RUN: -o - | FileCheck %s --check-prefix=NOX87
15+
16+
17+
18+
// expected-no-diagnostics
19+
20+
// CHECK-LABEL: define dso_local <2 x float> @divd
21+
_Complex float divd(_Complex float a, _Complex float b) {
22+
// CHECK: fpext float {{.*}} to double
23+
// CHECK: fpext float {{.*}} to double
24+
// CHECK: fdiv double
25+
// CHECK: fdiv double
26+
// CHECK: fptrunc double {{.*}} to float
27+
// CHECK: fptrunc double {{.*}} to float
28+
29+
// NOX87: fpext float {{.*}} to double
30+
// NOX87: fpext float {{.*}} to double
31+
// NOX87: fdiv double
32+
// NOX87: fdiv double
33+
// NOX87: fptrunc double {{.*}} to float
34+
// NOX87: fptrunc double {{.*}} to float
35+
36+
return a / b;
37+
}
38+
39+
// CHECK-LABEL: define dso_local { double, double } @divf
40+
_Complex double divf(_Complex double a, _Complex double b) {
41+
// CHECK: fpext double {{.*}} to x86_fp80
42+
// CHECK: fpext double {{.*}} to x86_fp80
43+
// CHECK: fdiv x86_fp80
44+
// CHECK: fdiv x86_fp80
45+
// CHECK: fptrunc x86_fp80
46+
// CHECK: fptrunc x86_fp80
47+
48+
// NOX87: call double @llvm.fabs.f64(double {{.*}})
49+
// NOX87-NEXT: call double @llvm.fabs.f64(double {{.*}})
50+
// NOX87-NEXT: fcmp ugt double %{{.*}}, {{.*}}
51+
// NOX87-NEXT: br i1 {{.*}}, label
52+
// NOX87: abs_rhsr_greater_or_equal_abs_rhsi:
53+
// NOX87-NEXT: fdiv double
54+
// NOX87-NEXT: fmul double
55+
// NOX87-NEXT: fadd double
56+
// NOX87-NEXT: fmul double
57+
// NOX87-NEXT: fadd double
58+
// NOX87-NEXT: fdiv double
59+
// NOX87-NEXT: fmul double
60+
// NOX87-NEXT: fsub double
61+
// NOX87-NEXT: fdiv double
62+
// NOX87-NEXT: br label {{.*}}
63+
// NOX87: abs_rhsr_less_than_abs_rhsi:
64+
// NOX87-NEXT: fdiv double
65+
// NOX87-NEXT: fmul double
66+
// NOX87-NEXT: fadd double
67+
// NOX87-NEXT: fmul double
68+
// NOX87-NEXT: fadd double
69+
// NOX87-NEXT: fdiv double
70+
// NOX87-NEXT: fmul double
71+
// NOX87-NEXT: fsub double
72+
// NOX87-NEXT: fdiv double
73+
// NOX87-NEXT: br label
74+
// NOX87: complex_div:
75+
// NOX87-NEXT: phi double
76+
// NOX87-NEXT: phi double
77+
// NOX87-NEXT: getelementptr inbounds nuw { double, double }, ptr {{.*}}, i32 0, i32 0
78+
// NOX87-NEXT: getelementptr inbounds nuw { double, double }, ptr {{.*}}, i32 0, i32 1
79+
// NOX87-NEXT: store double
80+
// NOX87-NEXT: store double
81+
82+
return a / b; // nopromotion-warning{{excess precision is requested but the target does not support excess precision which may result in observable differences in complex division behavior}}
83+
}

0 commit comments

Comments
 (0)