[clang] Fix complex long double division with -mno-x87. (PR #133152)

via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 27 02:50:16 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Zahira Ammarguellat (zahiraam)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/133152.diff


3 Files Affected:

- (modified) clang/lib/CodeGen/CGExprComplex.cpp (+4) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+4-2) 
- (added) clang/test/CodeGen/promoted-complex-div.c (+49) 


``````````diff
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index a7c8b96da6853..184a355734046 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -303,6 +303,10 @@ class ComplexExprEmitter
     // doubles the exponent of SmallerType.LargestFiniteVal)
     if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <=
         llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
+      if (!Ctx.getTargetInfo().hasLongDoubleType() &&
+          HigherElementType.getCanonicalType().getUnqualifiedType() ==
+              Ctx.LongDoubleTy)
+        return QualType();
       FPHasBeenPromoted = true;
       return Ctx.getComplexType(HigherElementType);
     } else {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 3af6d6c23438f..69a13aff14a00 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -15304,8 +15304,10 @@ static void DetectPrecisionLossInComplexDivision(Sema &S, SourceLocation OpLoc,
           Ctx.getFloatTypeSemantics(ElementType);
       const llvm::fltSemantics &HigherElementTypeSemantics =
           Ctx.getFloatTypeSemantics(HigherElementType);
-      if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 >
-          llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
+      if ((llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 >
+           llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) ||
+          (HigherElementType == Ctx.LongDoubleTy &&
+           !Ctx.getTargetInfo().hasLongDoubleType())) {
         // Retain the location of the first use of higher precision type.
         if (!S.LocationOfExcessPrecisionNotSatisfied.isValid())
           S.LocationOfExcessPrecisionNotSatisfied = OpLoc;
diff --git a/clang/test/CodeGen/promoted-complex-div.c b/clang/test/CodeGen/promoted-complex-div.c
new file mode 100644
index 0000000000000..02300126965ed
--- /dev/null
+++ b/clang/test/CodeGen/promoted-complex-div.c
@@ -0,0 +1,49 @@
+// RUN %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
+// RUN -verify -complex-range=promoted -o - | FileCheck %s
+
+// RUN %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
+// RUN -verify=nopromotion -complex-range=promoted -target-feature -x87 -o - | FileCheck %s --check-prefix=X87
+
+// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-windows \
+// RUN: -verify=nopromotion -complex-range=promoted -o - | FileCheck %s --check-prefix=X87
+
+// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-windows \
+// RUN: -verify=nopromotion -complex-range=promoted -target-feature -x87 -o - | FileCheck %s --check-prefix=X87
+
+
+
+// expected-no-diagnostics
+
+// CHECK-LABEL: define dso_local <2 x float> @divd
+_Complex float divd(_Complex float a, _Complex float b) {
+  // CHECK: fpext float {{.*}} to double
+  // CHECK: fpext float {{.*}} to double
+  // CHECK: fdiv double
+  // CHECK: fdiv double
+  // CHECK: fptrunc double {{.*}} to float
+  // CHECK: fptrunc double {{.*}} to float
+
+  // X87: fpext float {{.*}} to double
+  // X87: fpext float {{.*}} to double
+  // X87: fdiv double
+  // X87: fdiv double
+  // X87: fptrunc double {{.*}} to float
+  // X87: fptrunc double {{.*}} to float
+
+  return a / b;
+}
+
+// CHECK-LABEL: define dso_local { double, double } @divf
+_Complex double divf(_Complex double a, _Complex double b) {
+  // CHECK: fpext double {{.*}} to x86_fp80
+  // CHECK: fpext double {{.*}} to x86_fp80
+  // CHECK: fdiv x86_fp80
+  // CHECK: fdiv x86_fp80
+  // CHECK: fptrunc x86_fp80
+  // CHECK: fptrunc x86_fp80
+
+  // X87: fdiv double
+  // X87: fdiv double
+
+  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}}
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/133152


More information about the cfe-commits mailing list