This is an archive of the discontinued LLVM Phabricator instance.

[clang][Interp] Implement basic support for floating point values
ClosedPublic

Authored by tbaeder on Sep 29 2022, 1:10 AM.

Details

Summary

This only handles floats for now, so 32 bit floating point values.

There are a few things I'm uncertain about, like how to implement Floating<>::truncate() or whether or not Float32 should be part of AluTypeClass.

Diff Detail

Event Timeline

tbaeder created this revision.Sep 29 2022, 1:10 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 29 2022, 1:10 AM
tbaeder requested review of this revision.Sep 29 2022, 1:10 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 29 2022, 1:10 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
tbaeder updated this revision to Diff 463785.Sep 29 2022, 1:11 AM
tbaeder added inline comments.Sep 29 2022, 2:21 AM
clang/lib/AST/Interp/Context.cpp
117
clang/lib/AST/Interp/Floating.h
107

The operations here don't do overflow or UB handling.

tbaeder updated this revision to Diff 463807.Sep 29 2022, 2:29 AM
shafik added inline comments.Sep 29 2022, 5:53 PM
clang/lib/AST/Interp/Floating.h
81

bool isNaN() const { return V != V; }

tbaeder updated this revision to Diff 464156.Sep 30 2022, 12:07 AM
tbaeder marked an inline comment as done.
tbaeder updated this revision to Diff 464161.Sep 30 2022, 12:14 AM
aaron.ballman added a subscriber: jcranmer-intel.

I've not given this a full review yet, but I do have some comments on a partial review. Mostly, I'm concerned we're going to have different semantics when evaluating than we'd get if the evaluation happened at runtime because we're using the host floating-point environment and not the target. I'm also a bit concerned the design won't extend very easily to long double support. We don't have to solve all of this with the initial offering, but I think we want to be sure we're building the float support on a stable base.

Adding @jcranmer-intel for another set of eyes on this code from someone who knows many of the most terrifying parts of floating-point support.

clang/lib/AST/Interp/ByteCodeExprGen.cpp
180

Is there a reason you want to convert to the host float format here instead of passing along the APFloat object so semantics follow the target?

clang/lib/AST/Interp/Floating.h
28–30

Er, how will this extend to long double where the number of bits is rather more difficult?

75–80

Hmm, this is making my spidey senses tingle. For example, negative zero should be negative, but < won't help you with that: https://godbolt.org/z/xonxqPv5r (and it definitely won't help for negative inf or a signed NaN).

Some extra constexpr tests that may be interesting:

  • Constant expressions that produce floating point exceptions other than FE_INEXACT.
  • Subnormal values as operands, as well as operations with normal operands that produce denormal values (i.e., check for DAZ/FTZ, respectively.)
  • qNaN arithmetic
  • sNaN arithmetic
  • different NaN payloads (this can also catch out differences caused by host hardware: there's disagreement as to which NaN payload is used in an fadd, some processors prefer the first one, others prefer the second one).
  • converting infinity, NaN, numbers outside INT_MAX range to integers
  • converting integers to floating-point outside the latter's range--that's only possible with unsigned __int128 and float or uint32_t and half though

Some of these tests relate to things that you haven't implemented yet--and that's fine--but it's worth keeping in mind for future patches.

clang/lib/AST/Interp/Floating.h
28–30

Or half and bfloat, which are both 16-bit floating-point types?

32–34

My gut reaction is that, for floating-point types, you're probably better off using APFloat directly rather than trying to use the float/double platform types directly. Directly using platform types for computation means you potentially have changes based on the how clang itself was compiled--especially if someone decides to compile clang with -ffast-math and now all your constexpr stuff is executing in FTZ/DAZ mode. APFloat may be slower, but it also provides more protection from floating-point chicanery.

83

This is supposed to be capable of returning unordered if *this or RHS is a NaN, right?

107

They also don't support rounding mode. (constexpr evaluation arguably should at least support FENV_ROUND)

tbaeder added inline comments.Oct 1 2022, 6:21 AM
clang/lib/AST/Interp/Floating.h
28–30

I have spent some time with this today and tried to simply always use APFloat instead of a primitive type. Unfortunately that doesn't work because what we put on the stack is not the Floating (or Integral), but the underlying primitive type. So even if we do the final math (in ::add, etc) via APFloat, we need something we can serialize to char[] so we can put it on the stack. Do you think that would work?

jcranmer-intel added inline comments.Oct 3 2022, 1:24 PM
clang/lib/AST/Interp/Floating.h
28–30

I don't know enough about the structure of the bytecode interpreter here to say for sure, but this smells to me like you're baking in an assumption that every primitive target type has a corresponding primitive type on the host. This assumption just doesn't hold when it comes to floating point (only two of the seven types, float and double, are generally portable, and even then, there be dragons in some corner cases).

If you do need to continue down this route, there are two requirements that should be upheld:

  • The representation shouldn't assume that the underlying primitive type exists on host (bfloat16 and float128 are better test cases here).
  • Conversion to/from host primitive types shouldn't be easy to accidentally do.

(Worth repeating again that bit size is insufficient to distinguish floating point types: bfloat and half are both 16-bit, PPC long double and IEEE 754 quad precision are both 128-bit, and x86 long double is 80 bits stored as 96 bits on 32-bit and 128 bits on 64-bit.)

tbaeder added inline comments.Oct 4 2022, 12:29 AM
clang/lib/AST/Interp/Floating.h
28–30

Well, is there a way to convert an APFloat to a char[] that would work instead of going to float/double and storing that? The only thing I see in the docs is convertToHexString() (and the docs don't mention whether the conversion is lossy). If not, do you think adding such a conversion to APFloat and its various implementations is the better way forward?

aaron.ballman added inline comments.Oct 4 2022, 9:11 AM
clang/lib/AST/Interp/Floating.h
28–30

Let's avoid serializing the floats to strings so that we can parse the string to turn it back into a float later; that's going to have poor performance even if we do get all the corner cases correct regarding things like rounding, etc.

APFloat does not have any sort of serialization functionality beyond through strings representing the value. I think you'd have to invent such an interface.

tbaeder added inline comments.Oct 4 2022, 9:33 AM
clang/lib/AST/Interp/Floating.h
28–30

Do you know who I might talk to regrading such an interface, both the implementation as well as general feasibility?

aaron.ballman added inline comments.
clang/lib/AST/Interp/Floating.h
28–30

I think there may be at least two ways to do this: use an APFloat and put the serialization interfaces there, or use an APValue and put the serialization interfaces there.

Because APFloat is an ADT in LLVM, I think it should probably go up on Discourse for broader discussion. @chandlerc is still listed as the code owner for ADTs but he's not been active in quite some time. Instead, I would recommend talking to @dblaikie (he's got a good eye for ADT work in general) and @foad, @RKSimon, and @sepavloff as folks who have recently been touching APFloat.

APValue is a Clang-specific class, and it already has some amount of serialization support, it seems (https://github.com/llvm/llvm-project/blob/main/clang/include/clang/AST/APValue.h#L54). From a quick look, it seems we're already using APValue in a reasonable number of places in the interpreter, so it might make sense to use this object consistently to represent all values in the new interpreter?

jcranmer-intel added inline comments.Oct 4 2022, 10:22 AM
clang/lib/AST/Interp/Floating.h
28–30

Going through APInt is already possible in APFloat, and that might have some methods to go to char arrays.

dblaikie added inline comments.Oct 4 2022, 3:00 PM
clang/lib/AST/Interp/Floating.h
28–30

Yeah - IR gets serialized APFloats somehow (maybe through some layers of indirection) so I'd suggest looking at how, say, a global float named constant gets lowered to bitcode to see how that APFloat is serialized.

If that's not enough of a pointer for you/others to find something helpful, I can look further to see what I can find (I got some of the way - a small example with just extern const float v; const float v = 3.14; and breaking on APFloat's ctor immediately finds the APFLoat being constructed from that literal - then I looked at llvm::GlobalVariable's ctor, which does break on the creation of v, but didn't continue further to figure out how the parsed value gets into the IR constant)

tbaeder added inline comments.Oct 5 2022, 4:17 AM
clang/lib/AST/Interp/Floating.h
28–30

So, I think this is implemented in emitGlobalConstantFP(): https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp#L3206. I now wonder how to implement this, since the number of chunks isn't fixed. And all this seems rather costly given that we'd have to do this every time we access a floating point value on the stack.

dblaikie added inline comments.Oct 5 2022, 10:54 AM
clang/lib/AST/Interp/Floating.h
28–30

That looks like the lowering to assembly - I meant the lowering to LLVM IR bitcode, though perhaps it's similarly complicated.

As for variable length - I expect the strings encoding had variable length too, but either relied on null termination or a length prefix. The APFloat serialization could use a length prefix encoding to specify how many bytes to read/decode (I guess LLVM IR bitcode does something like that - though I think the bitcode records always encode their length, so it might be implicit).

tbaeder updated this revision to Diff 465702.Oct 6 2022, 5:21 AM

Another try, this time without any underlying host type.

There are a few things I'm uncertain about. The tests are obviously not enough, especially now that I had to add another CastFP opcode to cast floats between different semantics.

The general approach seems much saner than before, but I'm sure you'll find enough problem with this one as well :)

BTW, I feel like there are a lot of comments on this review now, so if you'd like me to split the new version of the patch out into another ticket, I can do that of course.

tbaeder added inline comments.Oct 6 2022, 5:25 AM
clang/lib/AST/Interp/Floating.h
34–35

This is currently commented out, but I think I can get the semantics of the APFloat and ask its semantics for min/max values.

tbaeder updated this revision to Diff 465703.Oct 6 2022, 5:26 AM
tbaeder updated this revision to Diff 465708.Oct 6 2022, 6:03 AM
jcranmer-intel added inline comments.Oct 6 2022, 7:56 AM
clang/lib/AST/Interp/Floating.h
34–35

APFloat::get{Largest,Smallest} will do the trick.

90

FYI, operator== on APFloat requires the two types to have the same semantics. Probably the fastest way to check if it's -1 is either ilogb(F) == 0 && F.isNegative() or F.isExactlyValue(-1.0).

clang/lib/AST/Interp/Interp.cpp
404

FWIW, const llvm::fltSemantics & is the usual way it's used.

tbaeder added inline comments.Oct 6 2022, 8:05 AM
clang/lib/AST/Interp/Interp.cpp
404

I saw, but this is going through a char[] stack a gain and I don't think using a reference works there.

tbaeder updated this revision to Diff 465967.Oct 6 2022, 9:54 PM
tbaeder marked 2 inline comments as done.
tbaeder added inline comments.
clang/lib/AST/Interp/Floating.h
34–35

I only need them for isMin(), so isSmallest() even works, thanks!

tbaeder updated this revision to Diff 465968.Oct 6 2022, 9:59 PM
tbaeder updated this revision to Diff 466027.Oct 7 2022, 3:47 AM
tbaeder marked 10 inline comments as done.Oct 7 2022, 3:52 AM
tbaeder updated this revision to Diff 466031.Oct 7 2022, 3:57 AM

Any other opinions on the new approach?

sepavloff added inline comments.Oct 18 2022, 9:18 AM
clang/lib/AST/Interp/Boolean.h
56

Is there any reason why operator double exists, but operator float does not?

clang/lib/AST/Interp/ByteCodeExprGen.cpp
118

Does this two-stage conversion make sense? In contrast to things like PT_Sint8 PT_Float is not a real type, it designates a set (potentially open) of all floating-point types. What is the meaning of this conversion? Why emitCastFP is not enough?

BTW which classes implement emitCast and emitCastFP? Usually such casts depend on rounding mode, how these methods get it?

695

Should this method get floating-point semantic as a parameter?

clang/lib/AST/Interp/Floating.h
38

This constructor creates a value of particular floating-point type, which generally is not compatible with floating-point values of other types. Does it need a semantic argument?

45

This method requires semantic just as getInf.

55–63

Conversions to integers are bitcasts+truncation but the conversion to bool is different. What semantics have these operations?

tbaeder added inline comments.Oct 18 2022, 11:45 PM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
118

I think we could do this in CastFP, yes. But what happens right now is that we use Floating::from() with, e.g. a int32_t, which just does APFloat(int32_t), which I think results in float semantics. So if we're instead casting from int to double, the CastFP is needed.

CastFP is implemented below in this diff and uses Floating::toSemantics(). Cast is using ToT::from(FromT), so uses Floating::from() to do the cast.

695

Yes I think that would be alright, we could just get the right semantics in this function.

clang/lib/AST/Interp/Floating.h
38

That's a good question. I think generally you're right but I don't know where this constructor is used at all right now. Might just be dead code.

55–63

They are basically used for casting. I didn't mean to make the bool implementation different, just seemed to make sense to me to do it this way.

sepavloff added inline comments.Oct 19 2022, 2:32 AM
clang/lib/AST/Interp/Floating.h
55–63

If they are used for casting, they need to preserve value, that is conversion float->int32 should transform 1.0->0x00000001. The method toAPSInt uses bitcast, so it converts 1.0->0x3f800000. APFloat::convertToInteger should be used to make value-preverving conversion but it requires knowledge of rounding mode.

tbaeder added inline comments.Oct 19 2022, 6:43 AM
clang/lib/AST/Interp/Floating.h
55–63

That's good to know, thanks. I've already used TowardZero in Floating::toSemantics(), but that was more a guess.

Is the rounding mode I'm supposed to use simply LangOptions::getDefaultRoundingMode()?

sepavloff added inline comments.Oct 19 2022, 9:18 AM
clang/lib/AST/Interp/Floating.h
55–63

Rounding mode is stored in AST node, a call to Expr::getFPFeaturesInEffect may be used to extract various FP features in the form of FPOptions. LangOptions::getDefaultRoundingMode() returns the default rounding mode, which may be changed using #pragma STDC FENV_ROUND.

tbaeder updated this revision to Diff 469166.Oct 20 2022, 4:57 AM

Another (and even longer) version.

Introduce special opcodes for floating point operations and pass the rounding mode to them. Also create special int->float and float->int casts so we can handle that properly.

This makes clang/tests/SemaCXX/rouding-math.cpp work. I've only enabled one of the two RUN lines though. The other one fails because we don't handle CXXNewExprs yet.

tbaeder updated this revision to Diff 469173.Oct 20 2022, 5:11 AM
tbaeder updated this revision to Diff 469527.Oct 21 2022, 3:14 AM
tbaeder marked 5 inline comments as done.
tbaeder added inline comments.Oct 21 2022, 5:23 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
695

I left the implementation of this out since visitZeroInitializer() is dead code right now anyway and the patch is already large enough.

sepavloff added inline comments.Oct 27 2022, 5:25 AM
clang/lib/AST/Interp/PrimType.h
39

In contrast to other members of this enumeration, PT_Float does not designate a concrete type, and it must creates problems. For example, how function primSize(PrimType Type) can be implemented?

tbaeder added inline comments.Oct 27 2022, 5:48 AM
clang/lib/AST/Interp/PrimType.h
39

Yes, floats are a bit special, see also the special case in getCtorPrim() in Descriptor.cpp. But I don't think it's a problem for primSize() since that only uses sizeof().

sepavloff added inline comments.Oct 27 2022, 9:06 AM
clang/lib/AST/Interp/PrimType.h
39

sizeof in primSize() would return sizeof(clang::interp::Floating), which is sizeof(APFloat). This value is not the same as sizeof(float) or sizeof(double).

tbaeder added inline comments.Oct 27 2022, 11:22 PM
clang/lib/AST/Interp/PrimType.h
39

I am aware, but primSize() is not used to implement sizeof() or anything like that, it's used on the host side to do memory allocation, e.g. Descriptor uses it to allocate NumElems * primSize(T) bytes for primitive arrays.

tbaeder updated this revision to Diff 471565.Oct 28 2022, 8:34 AM
tbaeder updated this revision to Diff 471814.Oct 29 2022, 11:32 PM

Moved the tests to their own file and moved the isConstantContext() changes to InterpState to their own NFC commit.

tbaeder updated this revision to Diff 471816.Oct 30 2022, 12:05 AM
jcranmer-intel added inline comments.Nov 4 2022, 1:01 PM
clang/lib/AST/Interp/Interp.cpp
481

Not sure I understand the conditions that cause S.inConstantContext() to be true, which gives me some cause for concern. Additionally, there's no tests covering the checks in the function.

clang/lib/AST/Interp/Opcodes.td
515

Integer-to-floating point conversion is dependent on rounding mode--consider (float)UINT_MAX.

tbaeder added inline comments.Nov 5 2022, 12:37 AM
clang/lib/AST/Interp/Interp.cpp
481

This function is almost copy/paste from checkFloatingPointResult in ExprConstant.cpp: https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/ExprConstant.cpp#L2581

clang/lib/AST/Interp/Opcodes.td
515

This test succeeds here, whether I use -frounding-math or not:

constexpr float f = (float)4294967295;
static_assert(f == (float)4.2949673E+9);

How can I test this behavior?

tbaeder updated this revision to Diff 473404.Nov 5 2022, 12:41 AM
sepavloff added inline comments.Nov 5 2022, 1:48 AM
clang/lib/AST/Interp/Opcodes.td
515

You can use #pragma STDC FENV_ROUND. See clang/test/AST/const-fpfeatures.c as an example.

tbaeder updated this revision to Diff 473409.Nov 5 2022, 2:37 AM

Added a const-fpfeatures.cpp test and added semantics converstion to ::add as an example.

tbaeder added inline comments.Nov 7 2022, 1:13 AM
clang/lib/AST/Interp/Opcodes.td
515

Why does it work here to compare both f and f2 to the same value? https://godbolt.org/z/zdsf1sK7r

tbaeder updated this revision to Diff 473595.Nov 7 2022, 1:37 AM

Return opStatus from convertToInteger as well, and add a test case to floats.cpp that tests float-to-integer conversion.

tbaeder updated this revision to Diff 473608.Nov 7 2022, 2:38 AM

Report overflows when converting floats to integers.

jcranmer-intel added inline comments.Nov 8 2022, 12:59 PM
clang/lib/AST/Interp/Opcodes.td
515

FENV_ROUND is a new feature of C2x, so it doesn't look like it's properly handled in gcc or clang yet. (It's for sure not handled in clang--the code to convert a floating-point literal into an APFloat hardcodes default rounding mode in its call.)

Dynamic rounding mode shows you the difference: https://godbolt.org/z/856xM8KTh

tbaeder added inline comments.Nov 9 2022, 1:24 AM
clang/lib/AST/Interp/Opcodes.td
515

So I can't test this at all because it first needs work in clang to do the float->APFloat conversion correctly?

Patch https://reviews.llvm.org/D137719 fixed int->float conversion.

tbaeder updated this revision to Diff 474551.Nov 10 2022, 8:07 AM
tbaeder marked an inline comment as done.Nov 10 2022, 8:12 AM
tbaeder updated this revision to Diff 474676.Nov 11 2022, 12:42 AM

Added the int-to-float conversion tests from https://reviews.llvm.org/D137719

FYI, I noticed the way the floating values are serialized doesn't work if the APFloat heap-allocated anything; those values aren't preserved through (de)serialization of course.

Reproducer:

constexpr double foo() {
  return __LDBL_MIN__;
}

FYI, I noticed the way the floating values are serialized doesn't work if the APFloat heap-allocated anything; those values aren't preserved through (de)serialization of course.

Reproducer:

constexpr double foo() {
  return __LDBL_MIN__;
}

The return statement returns a value of type long double while the function returns double. If long double is wider than double, truncation occurs, may be this is the reason?

FYI, I noticed the way the floating values are serialized doesn't work if the APFloat heap-allocated anything; those values aren't preserved through (de)serialization of course.

Reproducer:

constexpr double foo() {
  return __LDBL_MIN__;
}

The return statement returns a value of type long double while the function returns double. If long double is wider than double, truncation occurs, may be this is the reason?

It also happens when the function returns a long double.

I tracked the problem down to the way we emit byte code into a std::vector. It's simply reintepret_cast'ed to const char *, so that won't work for APFloat.

This change seems to fix the problem:

diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
index ff2136d34872..61e9662013c3 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -163,8 +163,15 @@ static void emit(Program &P, std::vector<char> &Code, const T &Val,
   }

   if constexpr (!std::is_pointer_v<T>) {
-    const char *Data = reinterpret_cast<const char *>(&Val);
-    Code.insert(Code.end(), Data, Data + Size);
+     if constexpr (std::is_trivially_copyable_v<T>) {
+      const char *Data = reinterpret_cast<const char *>(&Val);
+      Code.insert(Code.end(), Data, Data + Size);
+     } else {
+       // Construct the value directly into our storage vector.
+       size_t ValPos = Code.size();
+       Code.resize(Code.size() + Size);
+       new (Code.data() + ValPos) T(Val);
+     }
   } else {
     uint32_t ID = P.getOrCreateNativePointer(Val);
     const char *Data = reinterpret_cast<const char *>(&ID);
tbaeder updated this revision to Diff 477862.Nov 24 2022, 11:45 PM
tbaeder marked 10 inline comments as done.

Remove some questionable (but unused) Floating API that didn't take floating-point semantics into account.

sepavloff added inline comments.Nov 30 2022, 11:47 PM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
123

According to C standard (6.3.1.4p1):

When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero).

So the conversion should not depend on rounding mode. The same applies to the conversion to boolean (6.3.1.2p1):

When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.
594

This and some subsequent operations also should depend on rounding mode?

clang/lib/AST/Interp/Floating.h
110

Do we really need this check? In AST operands of addition always have the same type.

clang/lib/AST/Interp/Interp.cpp
477–478

This comment is not exact. In a context context rounding mode may be affected by #pragma STDC FENV_ROUND.

clang/lib/AST/Interp/Interp.h
1263

Integral::canRepresent is suitable only for integral-to-intergal conversions. With loss of precision the floating-point numbers can represent wider range of integers.

tbaeder added inline comments.Dec 1 2022, 3:35 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
123

So this is a difference between C and C++?

594

Yes, I did add as an example, the others will have to follow.

clang/lib/AST/Interp/Floating.h
110

In https://godbolt.org/z/s4n75jc4h, the LHS of the CompoundAssignOperator is float while the RHS is double

sepavloff added inline comments.Dec 1 2022, 5:15 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
123

No, C++ behaves similarly ([conv.fpint]):

A prvalue of a floating-point type can be converted to a prvalue of an integer type. The conversion truncates;
that is, the fractional part is discarded.

and [conv.bool]:

A prvalue of arithmetic, unscoped enumeration, pointer, or pointer-to-member type can be converted to a
prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false;
any other value is converted to true.

Theses conversions do not depend on rounding mode.

tbaeder added inline comments.Dec 1 2022, 5:58 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
123

Ah ok, thanks for the explanation. That explains why the current interpeter hardcodes rmTowardZero there. The rounding mode in Floating::convertToInteger was unused for that reason.

tbaeder updated this revision to Diff 479262.Dec 1 2022, 6:01 AM
sepavloff added inline comments.Dec 7 2022, 9:34 AM
clang/lib/AST/Interp/Floating.h
110

The case of CompoundAssignOperator cannot be implemented using the same function as for BinaryOperator. The operation float += double implies three operations:

  1. float value is converted to double,
  2. addition of double values is made,
  3. double result is converted to float.

The conversions 1 and 3 are not represented by ImplicitCasts, as demonstrated by your code snippet.

tbaeder updated this revision to Diff 481190.Dec 8 2022, 1:10 AM

Remove conversion in Floating::add() and tests that relied on it. Compound assignment operators can be properly implemented later.

sepavloff added inline comments.Dec 15 2022, 9:06 PM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
592

As discussed previously, compound assign operator cannot be implemented with the same function as corresponding binary operator in general case.

clang/lib/AST/Interp/Interp.h
1258

Conversion to boolean can be made with APFloat::isNonZero. It would correctly handle all values including NaNs/Infs. convertToInteger may leave Result unchanged if Status is invalid.

1263

I was wrong, this is float-to-integer conversion. Would it be easier to detect overflow (as well as other cases, like NaN) by checking that Status==opInvalidOp && F.isFinite()?

tbaeder marked 5 inline comments as done.Dec 17 2022, 10:02 PM
tbaeder added inline comments.
clang/lib/AST/Interp/ByteCodeExprGen.cpp
592

I left this in so at least one of the test cases in const-fpfeatures.cpp would work. But it seems like using res = res + y instead works as well and breaks if the #pragma before is commented-out, so I can use that instead.

clang/lib/AST/Interp/Interp.h
1263

That seems to work, yes. I switched to that and added an overflow test case to`floats.cpp`.

tbaeder updated this revision to Diff 483802.Dec 17 2022, 10:02 PM
tbaeder marked 2 inline comments as done.
This revision is now accepted and ready to land.Dec 19 2022, 2:40 AM
This revision was landed with ongoing or failed builds.Jan 25 2023, 5:42 AM
This revision was automatically updated to reflect the committed changes.