[llvm] [llvm-c] Add LLVMConstFPFromBits() API (PR #164381)

peter mckinna via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 4 01:48:33 PST 2025


https://github.com/demoitem updated https://github.com/llvm/llvm-project/pull/164381

>From 624b310dc7325933e197e7b0218e9b353328d1a7 Mon Sep 17 00:00:00 2001
From: peter mckinna <peter.mckinna at gmail.com>
Date: Tue, 21 Oct 2025 20:31:25 +1100
Subject: [PATCH 1/7] Create a 128 bit floating point constant from 2 64 bit
 values

---
 llvm/include/llvm-c/Core.h | 7 +++++++
 llvm/lib/IR/Core.cpp       | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 4e380d9bd5969..c2f68ce2219ba 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2339,6 +2339,13 @@ LLVM_C_ABI LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy,
                                                      const char *Text,
                                                      unsigned SLen);
 
+/**
+ * Obtain a constant for a floating point FP128 value from 2 64 bit values.
+ * (112 bit mantissa)
+ */
+
+LLVMValueRef LLVMConstFP128(LLVMContextRef C, const uint64_t N[2]);
+
 /**
  * Obtain the zero extended value for an integer constant value.
  *
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 27d8294b01264..6246880f0bec4 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1573,6 +1573,13 @@ LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy, const char Str[],
   return wrap(ConstantFP::get(unwrap(RealTy), StringRef(Str, SLen)));
 }
 
+LLVMValueRef LLVMConstFP128(LLVMContextRef C, const uint64_t N[2]) {
+  Type *Ty = Type::getFP128Ty(*unwrap(C));
+  APInt AI(128, ArrayRef<uint64_t>(N, 2));
+  APFloat Quad(APFloat::IEEEquad(), AI);
+  return wrap(ConstantFP::get(Ty, Quad));
+}
+
 unsigned long long LLVMConstIntGetZExtValue(LLVMValueRef ConstantVal) {
   return unwrap<ConstantInt>(ConstantVal)->getZExtValue();
 }

>From 18e65e20690ce64321a9e7c3b90027534c599eee Mon Sep 17 00:00:00 2001
From: peter mckinna <peter.mckinna at gmail.com>
Date: Thu, 23 Oct 2025 09:37:00 +1100
Subject: [PATCH 2/7] Update after review. Extend the function to accept the
 two 128 bit float types and add a testcase

---
 llvm/include/llvm-c/Core.h          |  4 ++--
 llvm/lib/IR/Core.cpp                |  9 +++++----
 llvm/unittests/IR/ConstantsTest.cpp | 14 ++++++++++++++
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index c2f68ce2219ba..ba7cc56aec6c9 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2341,10 +2341,10 @@ LLVM_C_ABI LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy,
 
 /**
  * Obtain a constant for a floating point FP128 value from 2 64 bit values.
- * (112 bit mantissa)
+ * Only the LLVMFP128Type or LLVMPPCFP128Type are accepted. 
  */
 
-LLVMValueRef LLVMConstFP128(LLVMContextRef C, const uint64_t N[2]);
+LLVM_C_ABI LLVMValueRef LLVMConstFP128(LLVMTypeRef Ty, const uint64_t N[2]);
 
 /**
  * Obtain the zero extended value for an integer constant value.
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 6246880f0bec4..da24306d6e263 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1573,11 +1573,12 @@ LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy, const char Str[],
   return wrap(ConstantFP::get(unwrap(RealTy), StringRef(Str, SLen)));
 }
 
-LLVMValueRef LLVMConstFP128(LLVMContextRef C, const uint64_t N[2]) {
-  Type *Ty = Type::getFP128Ty(*unwrap(C));
+LLVMValueRef LLVMConstFP128(LLVMTypeRef Ty, const uint64_t N[2]) {
+  Type *T = unwrap(Ty);
+  assert(T->getPrimitiveSizeInBits() == 128 && "Ty size should be 128");
   APInt AI(128, ArrayRef<uint64_t>(N, 2));
-  APFloat Quad(APFloat::IEEEquad(), AI);
-  return wrap(ConstantFP::get(Ty, Quad));
+  APFloat Quad(T->getFltSemantics(), AI);
+  return wrap(ConstantFP::get(T, Quad));
 }
 
 unsigned long long LLVMConstIntGetZExtValue(LLVMValueRef ConstantVal) {
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 6376165cbe766..4fb847de228cc 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -835,5 +835,19 @@ TEST(ConstantsTest, BlockAddressCAPITest) {
   EXPECT_EQ(&BB, OutBB);
 }
 
+TEST(ConstantsTest, Float128Test) {
+  LLVMTypeRef Ty128 = LLVMFP128TypeInContext(LLVMGetGlobalContext());
+  LLVMTypeRef TyPPC128 = LLVMPPCFP128TypeInContext(LLVMGetGlobalContext());
+  LLVMBuilderRef Builder = LLVMCreateBuilder();
+  uint64_t n[2] = {0x4000000000000000, 0x0}; //+2
+  uint64_t m[2] = {0xC000000000000000, 0x0}; //-2
+  LLVMValueRef val1 = LLVMConstFP128(Ty128, n);
+  LLVMValueRef val2 = LLVMConstFP128(Ty128, m);
+  LLVMValueRef val3 = LLVMBuildFAdd(Builder, val1, val2, "test");
+  EXPECT_TRUE(val3 != nullptr);
+  LLVMValueRef val4 = LLVMConstFP128(TyPPC128, n);
+  EXPECT_TRUE(val4 != nullptr);
+}
+
 } // end anonymous namespace
 } // end namespace llvm

>From 07e834c8ae92dc1abcbce916b8c909eab92d8e5b Mon Sep 17 00:00:00 2001
From: peter mckinna <peter.mckinna at gmail.com>
Date: Thu, 23 Oct 2025 09:57:40 +1100
Subject: [PATCH 3/7] Fix formatting

---
 llvm/include/llvm-c/Core.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index ba7cc56aec6c9..52bb03a605999 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2341,7 +2341,7 @@ LLVM_C_ABI LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy,
 
 /**
  * Obtain a constant for a floating point FP128 value from 2 64 bit values.
- * Only the LLVMFP128Type or LLVMPPCFP128Type are accepted. 
+ * Only the LLVMFP128Type or LLVMPPCFP128Type are accepted.
  */
 
 LLVM_C_ABI LLVMValueRef LLVMConstFP128(LLVMTypeRef Ty, const uint64_t N[2]);

>From c1c5d61634c0c58c79e1d66b5bfc660744090c90 Mon Sep 17 00:00:00 2001
From: peter mckinna <peter.mckinna at gmail.com>
Date: Mon, 3 Nov 2025 13:31:23 +1100
Subject: [PATCH 4/7] Further changes per review

---
 llvm/lib/IR/Core.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index da24306d6e263..de00a4f9c2a39 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1575,8 +1575,9 @@ LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy, const char Str[],
 
 LLVMValueRef LLVMConstFP128(LLVMTypeRef Ty, const uint64_t N[2]) {
   Type *T = unwrap(Ty);
-  assert(T->getPrimitiveSizeInBits() == 128 && "Ty size should be 128");
-  APInt AI(128, ArrayRef<uint64_t>(N, 2));
+  unsigned SB = T->getScalarSizeInBits();
+  assert(SB == 128 && "Ty size should be 128");
+  APInt AI(SB, ArrayRef<uint64_t>(N, divideCeil(SB, 64)));
   APFloat Quad(T->getFltSemantics(), AI);
   return wrap(ConstantFP::get(T, Quad));
 }

>From d0dd613ea0e001d6c77c126961309a822a4f577d Mon Sep 17 00:00:00 2001
From: peter mckinna <peter.mckinna at gmail.com>
Date: Wed, 3 Dec 2025 09:31:45 +1100
Subject: [PATCH 5/7] Further changes after review. Now the input array is
 dyanamic to suit multiple floating point types.

---
 llvm/include/llvm-c/Core.h          |  5 ++---
 llvm/lib/IR/Core.cpp                |  3 +--
 llvm/unittests/IR/ConstantsTest.cpp | 20 +++++++++++++++++---
 3 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 52bb03a605999..9e99ca0da2e72 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2340,11 +2340,10 @@ LLVM_C_ABI LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy,
                                                      unsigned SLen);
 
 /**
- * Obtain a constant for a floating point FP128 value from 2 64 bit values.
- * Only the LLVMFP128Type or LLVMPPCFP128Type are accepted.
+ * Obtain a constant for a floating point value from array of 64 bit values.
  */
 
-LLVM_C_ABI LLVMValueRef LLVMConstFP128(LLVMTypeRef Ty, const uint64_t N[2]);
+LLVM_C_ABI LLVMValueRef LLVMConstFPFromBits(LLVMTypeRef Ty, const uint64_t N[]);
 
 /**
  * Obtain the zero extended value for an integer constant value.
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index de00a4f9c2a39..951a2bdbb6ce1 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1573,10 +1573,9 @@ LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy, const char Str[],
   return wrap(ConstantFP::get(unwrap(RealTy), StringRef(Str, SLen)));
 }
 
-LLVMValueRef LLVMConstFP128(LLVMTypeRef Ty, const uint64_t N[2]) {
+LLVMValueRef LLVMConstFPFromBits(LLVMTypeRef Ty, const uint64_t N[]) {
   Type *T = unwrap(Ty);
   unsigned SB = T->getScalarSizeInBits();
-  assert(SB == 128 && "Ty size should be 128");
   APInt AI(SB, ArrayRef<uint64_t>(N, divideCeil(SB, 64)));
   APFloat Quad(T->getFltSemantics(), AI);
   return wrap(ConstantFP::get(T, Quad));
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 4fb847de228cc..96a2e238e74d6 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -838,15 +838,29 @@ TEST(ConstantsTest, BlockAddressCAPITest) {
 TEST(ConstantsTest, Float128Test) {
   LLVMTypeRef Ty128 = LLVMFP128TypeInContext(LLVMGetGlobalContext());
   LLVMTypeRef TyPPC128 = LLVMPPCFP128TypeInContext(LLVMGetGlobalContext());
+  LLVMTypeRef TyFloat = LLVMFloatTypeInContext(LLVMGetGlobalContext());
+  LLVMTypeRef TyDouble = LLVMDoubleTypeInContext(LLVMGetGlobalContext());
+  LLVMTypeRef TyHalf = LLVMHalfTypeInContext(LLVMGetGlobalContext());
   LLVMBuilderRef Builder = LLVMCreateBuilder();
   uint64_t n[2] = {0x4000000000000000, 0x0}; //+2
   uint64_t m[2] = {0xC000000000000000, 0x0}; //-2
-  LLVMValueRef val1 = LLVMConstFP128(Ty128, n);
-  LLVMValueRef val2 = LLVMConstFP128(Ty128, m);
+  LLVMValueRef val1 = LLVMConstFPFromBits(Ty128, n);
+  EXPECT_TRUE(val1 != nullptr);
+  LLVMValueRef val2 = LLVMConstFPFromBits(Ty128, m);
+  EXPECT_TRUE(val2 != nullptr);
   LLVMValueRef val3 = LLVMBuildFAdd(Builder, val1, val2, "test");
   EXPECT_TRUE(val3 != nullptr);
-  LLVMValueRef val4 = LLVMConstFP128(TyPPC128, n);
+  LLVMValueRef val4 = LLVMConstFPFromBits(TyPPC128, n);
   EXPECT_TRUE(val4 != nullptr);
+  uint64_t p[1] = {0x0000000040000000}; //+2
+  LLVMValueRef val5 = LLVMConstFPFromBits(TyFloat, p);
+  EXPECT_TRUE(val5 != nullptr);
+  uint64_t q[1] = {0x4000000000000000}; //+2
+  LLVMValueRef val6 = LLVMConstFPFromBits(TyDouble, q);
+  EXPECT_TRUE(val6 != nullptr);
+  uint64_t r[1] = {0x0000000000003c00}; //+1
+  LLVMValueRef val7 = LLVMConstFPFromBits(TyHalf, r);
+  EXPECT_TRUE(val7 != nullptr);
 }
 
 } // end anonymous namespace

>From d51ed79d32149e9d031001066ca9456728e8a780 Mon Sep 17 00:00:00 2001
From: peter mckinna <peter.mckinna at gmail.com>
Date: Thu, 4 Dec 2025 13:18:53 +1100
Subject: [PATCH 6/7] Add release note comment and fix context in test.

---
 llvm/docs/ReleaseNotes.md           |  1 +
 llvm/include/llvm-c/Core.h          |  2 ++
 llvm/unittests/IR/ConstantsTest.cpp | 12 +++++++-----
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 9cdd98390d061..4b09fe30eeed7 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -153,6 +153,7 @@ Changes to the C API
 
 * Add `LLVMGetOrInsertFunction` to get or insert a function, replacing the combination of `LLVMGetNamedFunction` and `LLVMAddFunction`.
 * Allow `LLVMGetVolatile` to work with any kind of Instruction.
+* Add `LLVMConstFPFromBits` to get a constant floating-point value from an array of 64 bit values.
 
 Changes to the CodeGen infrastructure
 -------------------------------------
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 9e99ca0da2e72..b96ec4c419a0e 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2341,6 +2341,8 @@ LLVM_C_ABI LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy,
 
 /**
  * Obtain a constant for a floating point value from array of 64 bit values.
+ * The length of the array N must be ceildiv(bits, 64), where bits is the
+ * scalar size in bits of the floating-point type.
  */
 
 LLVM_C_ABI LLVMValueRef LLVMConstFPFromBits(LLVMTypeRef Ty, const uint64_t N[]);
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 96a2e238e74d6..2f12c134d2f0b 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -836,11 +836,12 @@ TEST(ConstantsTest, BlockAddressCAPITest) {
 }
 
 TEST(ConstantsTest, Float128Test) {
-  LLVMTypeRef Ty128 = LLVMFP128TypeInContext(LLVMGetGlobalContext());
-  LLVMTypeRef TyPPC128 = LLVMPPCFP128TypeInContext(LLVMGetGlobalContext());
-  LLVMTypeRef TyFloat = LLVMFloatTypeInContext(LLVMGetGlobalContext());
-  LLVMTypeRef TyDouble = LLVMDoubleTypeInContext(LLVMGetGlobalContext());
-  LLVMTypeRef TyHalf = LLVMHalfTypeInContext(LLVMGetGlobalContext());
+  LLVMContextRef C = LLVMContextCreate();
+  LLVMTypeRef Ty128 = LLVMFP128TypeInContext(C);
+  LLVMTypeRef TyPPC128 = LLVMPPCFP128TypeInContext(C);
+  LLVMTypeRef TyFloat = LLVMFloatTypeInContext(C);
+  LLVMTypeRef TyDouble = LLVMDoubleTypeInContext(C);
+  LLVMTypeRef TyHalf = LLVMHalfTypeInContext(C);
   LLVMBuilderRef Builder = LLVMCreateBuilder();
   uint64_t n[2] = {0x4000000000000000, 0x0}; //+2
   uint64_t m[2] = {0xC000000000000000, 0x0}; //-2
@@ -861,6 +862,7 @@ TEST(ConstantsTest, Float128Test) {
   uint64_t r[1] = {0x0000000000003c00}; //+1
   LLVMValueRef val7 = LLVMConstFPFromBits(TyHalf, r);
   EXPECT_TRUE(val7 != nullptr);
+  LLVMContextDispose(C);
 }
 
 } // end anonymous namespace

>From 1d91d9d511c3edcbadc34890d877e27a79f54564 Mon Sep 17 00:00:00 2001
From: peter mckinna <peter.mckinna at gmail.com>
Date: Thu, 4 Dec 2025 20:45:47 +1100
Subject: [PATCH 7/7] add value check test for float and double. No APFloat
 constructors for other floating-point types.

---
 llvm/unittests/IR/ConstantsTest.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 2f12c134d2f0b..86fd6a398cc97 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -855,10 +855,10 @@ TEST(ConstantsTest, Float128Test) {
   EXPECT_TRUE(val4 != nullptr);
   uint64_t p[1] = {0x0000000040000000}; //+2
   LLVMValueRef val5 = LLVMConstFPFromBits(TyFloat, p);
-  EXPECT_TRUE(val5 != nullptr);
+  EXPECT_EQ(APFloat(2.0f), unwrap<ConstantFP>(val5)->getValue());
   uint64_t q[1] = {0x4000000000000000}; //+2
   LLVMValueRef val6 = LLVMConstFPFromBits(TyDouble, q);
-  EXPECT_TRUE(val6 != nullptr);
+  EXPECT_EQ(APFloat(2.0), unwrap<ConstantFP>(val6)->getValue());
   uint64_t r[1] = {0x0000000000003c00}; //+1
   LLVMValueRef val7 = LLVMConstFPFromBits(TyHalf, r);
   EXPECT_TRUE(val7 != nullptr);



More information about the llvm-commits mailing list