Skip to content

Conversation

@demoitem
Copy link
Contributor

This change adds the ability to create a 128 bit floating point value from 2 64 bit integer values.
Some language frontends have already parsed a floating point string into a proper 128 bit quad value
and need to get the llvm value directly.

@demoitem demoitem requested a review from nikic as a code owner October 21, 2025 09:47
@llvmbot
Copy link
Member

llvmbot commented Oct 21, 2025

@llvm/pr-subscribers-llvm-ir

Author: peter mckinna (demoitem)

Changes

This change adds the ability to create a 128 bit floating point value from 2 64 bit integer values.
Some language frontends have already parsed a floating point string into a proper 128 bit quad value
and need to get the llvm value directly.


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

2 Files Affected:

  • (modified) llvm/include/llvm-c/Core.h (+7)
  • (modified) llvm/lib/IR/Core.cpp (+7)
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();
 }

@nikic nikic changed the title Create a 128 bit floating point constant from 2 64 bit values [llvm-c] Create a 128 bit floating point constant from 2 64 bit values Oct 21, 2025
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs tests.

I also think it would make more sense to make this a generic bitwise initializer for FP constants, rather than specific to fp128. That will also work for things like ppc_fp128, and generally to more reliably create specific FP values, even if they're special. (Like, I wouldn't expect the API taking a double to reliably create an sNaN with a specific payload.)

@demoitem
Copy link
Contributor Author

I'm not sure where to place these tests, ie Core.cpp tests in general.

I agree a generic initializer would make more sense but that kind of C++ expertise is a bit beyond me I'm afraid.

@nikic
Copy link
Contributor

nikic commented Oct 21, 2025

I'm not sure where to place these tests, ie Core.cpp tests in general.

In this case probably https://github.com/llvm/llvm-project/blob/main/llvm/unittests/IR/ConstantsTest.cpp.

I agree a generic initializer would make more sense but that kind of C++ expertise is a bit beyond me I'm afraid.

I think it would look similar to what you have now, but accept the type as an argument and call getFltSemantics() on it instead of hardcoding APFloat::IEEEquad().


/**
* Obtain a constant for a floating point FP128 value from 2 64 bit values.
* (112 bit mantissa)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation should probably state the endianness of the values.

@github-actions
Copy link

github-actions bot commented Oct 22, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@demoitem
Copy link
Contributor Author

I have changed the function to what I think you have in mind. And added a testcase. It only really
applies to the two 128 bit floating point types, so I added an assert. To cope with the 80 bit float type
probably needs another function and a discussion about how to deliver the bits.
As for the endianness comment, I am not sure what to do. The IEEE 754 standard doesnt really mention
endianness. Please advise.

@demoitem
Copy link
Contributor Author

ping


LLVMValueRef LLVMConstFP128(LLVMTypeRef Ty, const uint64_t N[2]) {
Type *T = unwrap(Ty);
assert(T->getPrimitiveSizeInBits() == 128 && "Ty size should be 128");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert(T->getPrimitiveSizeInBits() == 128 && "Ty size should be 128");
assert(T->getScalarSizeInBits() == 128 && "Ty size should be 128");

To allow vector of float.

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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than hardcoding 128 here, we can use the size of the float (e.g. via getScalarSizeInBits). The corresponding size of the array would be divideCeil(SizeInBits, 64). Then this would work for all sizes of floats.

@demoitem
Copy link
Contributor Author

demoitem commented Nov 3, 2025

Changed the function as per your comments. Any other tweaks?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants