[clang] [PowerPC][Clang] fix IEEE f128 complex div/mul use IBM f128 libcalls on powerpc (PR #218151)

via cfe-commits cfe-commits at lists.llvm.org
Sat Aug 22 11:53:18 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-codegen

Author: Folkert de Vries (folkertdev)

<details>
<summary>Changes</summary>

fixes https://github.com/llvm/llvm-project/issues/216820

Previously the IBM f128 libcall was used also for IEEE f128 complex mul/div.

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


3 Files Affected:

- (modified) clang/docs/ReleaseNotes.md (+1) 
- (modified) clang/lib/CodeGen/CGExprComplex.cpp (+8-4) 
- (modified) clang/test/CodeGen/fp128_complex.c (+31-3) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index aa741bbf961e2..18a785abadd63 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -412,6 +412,7 @@ features cannot lower the translation-unit ABI level;
 - Fixed a crash when checking scalar type with excess braces. (#GH69213), (#GH137845), (#GH198767), (#GH207566), (#GH106180)
 - Fixed an assertion crash when instantiating a nested requirement with an invalid constraint. (#GH213575)
 - Clang now defines the GCC-compatible predefined macro `__SIG_ATOMIC_TYPE__`. (#GH213895)
+- Fixed IEEE f128 complex mul/div using the IBM f128 libcalls on powerpc. (#GH216820)
 - Fixed an ICE that occurred when a structured binding pack is expanded outside the lambda where it was declared. (#GH214160)
 - Fixed a bug where a stray closing curley brace in an OpenMP/OpenACC pragma could cause pragma parsing issues when inside of a member function. (#GH214195)
 
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 350cbd18c7ed7..30d693fb371cb 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -798,7 +798,8 @@ ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName,
 
 /// Lookup the libcall name for a given floating point type complex
 /// multiply.
-static StringRef getComplexMultiplyLibCallName(llvm::Type *Ty) {
+static StringRef getComplexMultiplyLibCallName(const llvm::Triple &T,
+                                               llvm::Type *Ty) {
   switch (Ty->getTypeID()) {
   default:
     llvm_unreachable("Unsupported floating point type!");
@@ -813,7 +814,7 @@ static StringRef getComplexMultiplyLibCallName(llvm::Type *Ty) {
   case llvm::Type::X86_FP80TyID:
     return "__mulxc3";
   case llvm::Type::FP128TyID:
-    return "__multc3";
+    return T.isPPC() ? "__mulkc3" : "__multc3";
   }
 }
 
@@ -880,8 +881,9 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
       // Now emit the libcall on this slowest of the slow paths.
       CGF.EmitBlock(LibCallBB);
       Value *LibCallR, *LibCallI;
+      llvm::Triple Triple = CGF.getTarget().getTriple();
       std::tie(LibCallR, LibCallI) = EmitComplexBinOpLibCall(
-          getComplexMultiplyLibCallName(Op.LHS.first->getType()), Op);
+          getComplexMultiplyLibCallName(Triple, Op.LHS.first->getType()), Op);
       Builder.CreateBr(ContBB);
 
       // Finally continue execution by phi-ing together the different
@@ -1078,7 +1080,9 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
       case llvm::Type::X86_FP80TyID:
         return EmitComplexBinOpLibCall("__divxc3", LibCallOp);
       case llvm::Type::FP128TyID:
-        return EmitComplexBinOpLibCall("__divtc3", LibCallOp);
+        return EmitComplexBinOpLibCall(
+            CGF.getTarget().getTriple().isPPC() ? "__divkc3" : "__divtc3",
+            LibCallOp);
       }
     } else {
       return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi);
diff --git a/clang/test/CodeGen/fp128_complex.c b/clang/test/CodeGen/fp128_complex.c
index d1593fae9c9bc..0cd3b59bf3615 100644
--- a/clang/test/CodeGen/fp128_complex.c
+++ b/clang/test/CodeGen/fp128_complex.c
@@ -1,9 +1,37 @@
-// RUN: %clang --target=aarch64 %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang --target=aarch64 %s -S -emit-llvm -o - | FileCheck %s --check-prefix=TC3
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-feature +float128 -DTEST_PPC128 -emit-llvm -o - %s \
+// RUN:   | FileCheck %s --check-prefixes=IBM,PPC
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-feature +float128 -DTEST_PPC128 -mabi=ieeelongdouble -emit-llvm -o - %s \
+// RUN:   | FileCheck %s --check-prefixes=KC3,PPC
 
 _Complex long double a, b, c, d;
 void test_fp128_compound_assign(void) {
-  // CHECK: call { fp128, fp128 } @__multc3
+  // TC3: call { fp128, fp128 } @__multc3
+  // IBM: call { ppc_fp128, ppc_fp128 } @__multc3
+  // KC3: call { fp128, fp128 } @__mulkc3
   a *= b;
-  // CHECK: call { fp128, fp128 } @__divtc3
+  // TC3: call { fp128, fp128 } @__divtc3
+  // IBM: call { ppc_fp128, ppc_fp128 } @__divtc3
+  // KC3: call { fp128, fp128 } @__divkc3
   c /= d;
 }
+
+#ifdef __FLOAT128__
+_Complex __float128 e, f, g, h;
+void test_float128_compound_assign(void) {
+  // PPC: call { fp128, fp128 } @__mulkc3
+  e *= f;
+  // PPC: call { fp128, fp128 } @__divkc3
+  g /= h;
+}
+#endif
+
+#ifdef __powerpc__
+_Complex __ibm128 i, j, k, l;
+void test_ibm128_compound_assign(void) {
+  // PPC: call { ppc_fp128, ppc_fp128 } @__multc3
+  i *= j;
+  // PPC: call { ppc_fp128, ppc_fp128 } @__divtc3
+  k /= l;
+}
+#endif

``````````

</details>


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


More information about the cfe-commits mailing list