Skip to content

[clang][bytecode] Pass FPOptions to floating point ops #107063

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 3, 2024

Conversation

tbaederr
Copy link
Contributor

@tbaederr tbaederr commented Sep 3, 2024

So we don't have to retrieve them from the InterpFrame, which is slow.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Sep 3, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 3, 2024

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

So we don't have to retrieve them from the InterpFrame, which is slow.


Patch is 22.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/107063.diff

5 Files Affected:

  • (modified) clang/lib/AST/ByteCode/Compiler.cpp (+34-34)
  • (modified) clang/lib/AST/ByteCode/Compiler.h (+4)
  • (modified) clang/lib/AST/ByteCode/Interp.cpp (+5-5)
  • (modified) clang/lib/AST/ByteCode/Interp.h (+44-35)
  • (modified) clang/lib/AST/ByteCode/Opcodes.td (+5-5)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 554e23e272e41c..a831f196abdcb5 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -298,8 +298,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
       return false;
 
     const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
-    llvm::RoundingMode RM = getRoundingMode(CE);
-    return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE);
+    return this->emitCastIntegralFloating(*FromT, TargetSemantics,
+                                          getFPOptions(CE), CE);
   }
 
   case CK_FloatingToBoolean:
@@ -317,12 +317,12 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
 
     if (ToT == PT_IntAP)
       return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(CE->getType()),
-                                              CE);
+                                              getFPOptions(CE), CE);
     if (ToT == PT_IntAPS)
       return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(CE->getType()),
-                                               CE);
+                                               getFPOptions(CE), CE);
 
-    return this->emitCastFloatingIntegral(*ToT, CE);
+    return this->emitCastFloatingIntegral(*ToT, getFPOptions(CE), CE);
   }
 
   case CK_NullToPointer:
@@ -810,21 +810,21 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
     return MaybeCastToBool(this->emitGE(*LT, BO));
   case BO_Sub:
     if (BO->getType()->isFloatingType())
-      return Discard(this->emitSubf(getRoundingMode(BO), BO));
+      return Discard(this->emitSubf(getFPOptions(BO), BO));
     return Discard(this->emitSub(*T, BO));
   case BO_Add:
     if (BO->getType()->isFloatingType())
-      return Discard(this->emitAddf(getRoundingMode(BO), BO));
+      return Discard(this->emitAddf(getFPOptions(BO), BO));
     return Discard(this->emitAdd(*T, BO));
   case BO_Mul:
     if (BO->getType()->isFloatingType())
-      return Discard(this->emitMulf(getRoundingMode(BO), BO));
+      return Discard(this->emitMulf(getFPOptions(BO), BO));
     return Discard(this->emitMul(*T, BO));
   case BO_Rem:
     return Discard(this->emitRem(*T, BO));
   case BO_Div:
     if (BO->getType()->isFloatingType())
-      return Discard(this->emitDivf(getRoundingMode(BO), BO));
+      return Discard(this->emitDivf(getFPOptions(BO), BO));
     return Discard(this->emitDiv(*T, BO));
   case BO_Assign:
     if (DiscardResult)
@@ -1153,7 +1153,7 @@ bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
       if (!loadComplexValue(RHSIsComplex, true, ElemIndex, RHSOffset, RHS))
         return false;
       if (ResultElemT == PT_Float) {
-        if (!this->emitAddf(getRoundingMode(E), E))
+        if (!this->emitAddf(getFPOptions(E), E))
           return false;
       } else {
         if (!this->emitAdd(ResultElemT, E))
@@ -1167,7 +1167,7 @@ bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
       if (!loadComplexValue(RHSIsComplex, true, ElemIndex, RHSOffset, RHS))
         return false;
       if (ResultElemT == PT_Float) {
-        if (!this->emitSubf(getRoundingMode(E), E))
+        if (!this->emitSubf(getFPOptions(E), E))
           return false;
       } else {
         if (!this->emitSub(ResultElemT, E))
@@ -1182,7 +1182,7 @@ bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
         return false;
 
       if (ResultElemT == PT_Float) {
-        if (!this->emitMulf(getRoundingMode(E), E))
+        if (!this->emitMulf(getFPOptions(E), E))
           return false;
       } else {
         if (!this->emitMul(ResultElemT, E))
@@ -1198,7 +1198,7 @@ bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
         return false;
 
       if (ResultElemT == PT_Float) {
-        if (!this->emitDivf(getRoundingMode(E), E))
+        if (!this->emitDivf(getFPOptions(E), E))
           return false;
       } else {
         if (!this->emitDiv(ResultElemT, E))
@@ -2063,22 +2063,21 @@ bool Compiler<Emitter>::VisitFloatCompoundAssignOperator(
   if (!this->emitGetLocal(*RT, TempOffset, E))
     return false;
 
-  llvm::RoundingMode RM = getRoundingMode(E);
   switch (E->getOpcode()) {
   case BO_AddAssign:
-    if (!this->emitAddf(RM, E))
+    if (!this->emitAddf(getFPOptions(E), E))
       return false;
     break;
   case BO_SubAssign:
-    if (!this->emitSubf(RM, E))
+    if (!this->emitSubf(getFPOptions(E), E))
       return false;
     break;
   case BO_MulAssign:
-    if (!this->emitMulf(RM, E))
+    if (!this->emitMulf(getFPOptions(E), E))
       return false;
     break;
   case BO_DivAssign:
-    if (!this->emitDivf(RM, E))
+    if (!this->emitDivf(getFPOptions(E), E))
       return false;
     break;
   default:
@@ -3325,7 +3324,7 @@ template <class Emitter> bool Compiler<Emitter>::visitBool(const Expr *E) {
 
   // Or Floats.
   if (T == PT_Float)
-    return this->emitCastFloatingIntegralBool(E);
+    return this->emitCastFloatingIntegralBool(getFPOptions(E), E);
 
   // Or anything else we can.
   return this->emitCast(*T, PT_Bool, E);
@@ -5005,8 +5004,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
     }
 
     if (T == PT_Float) {
-      return DiscardResult ? this->emitIncfPop(getRoundingMode(E), E)
-                           : this->emitIncf(getRoundingMode(E), E);
+      return DiscardResult ? this->emitIncfPop(getFPOptions(E), E)
+                           : this->emitIncf(getFPOptions(E), E);
     }
 
     return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E);
@@ -5028,8 +5027,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
     }
 
     if (T == PT_Float) {
-      return DiscardResult ? this->emitDecfPop(getRoundingMode(E), E)
-                           : this->emitDecf(getRoundingMode(E), E);
+      return DiscardResult ? this->emitDecfPop(getFPOptions(E), E)
+                           : this->emitDecf(getFPOptions(E), E);
     }
 
     return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E);
@@ -5056,7 +5055,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
     // Post-inc and pre-inc are the same if the value is to be discarded.
     if (DiscardResult) {
       if (T == PT_Float)
-        return this->emitIncfPop(getRoundingMode(E), E);
+        return this->emitIncfPop(getFPOptions(E), E);
       return this->emitIncPop(*T, E);
     }
 
@@ -5066,7 +5065,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
         return false;
       if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E))
         return false;
-      if (!this->emitAddf(getRoundingMode(E), E))
+      if (!this->emitAddf(getFPOptions(E), E))
         return false;
       if (!this->emitStoreFloat(E))
         return false;
@@ -5105,7 +5104,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
     // Post-dec and pre-dec are the same if the value is to be discarded.
     if (DiscardResult) {
       if (T == PT_Float)
-        return this->emitDecfPop(getRoundingMode(E), E);
+        return this->emitDecfPop(getFPOptions(E), E);
       return this->emitDecPop(*T, E);
     }
 
@@ -5115,7 +5114,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
         return false;
       if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E))
         return false;
-      if (!this->emitSubf(getRoundingMode(E), E))
+      if (!this->emitSubf(getFPOptions(E), E))
         return false;
       if (!this->emitStoreFloat(E))
         return false;
@@ -5579,13 +5578,15 @@ bool Compiler<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
     }
 
     if (ToT == PT_IntAP)
-      return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(ToQT), E);
+      return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(ToQT),
+                                              getFPOptions(E), E);
     if (ToT == PT_IntAPS)
-      return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(ToQT), E);
+      return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(ToQT),
+                                               getFPOptions(E), E);
 
     // Float to integral.
     if (isIntegralType(ToT) || ToT == PT_Bool)
-      return this->emitCastFloatingIntegral(ToT, E);
+      return this->emitCastFloatingIntegral(ToT, getFPOptions(E), E);
   }
 
   if (isIntegralType(FromT) || FromT == PT_Bool) {
@@ -5601,8 +5602,7 @@ bool Compiler<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
     if (ToT == PT_Float) {
       // Integral to floating.
       const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
-      return this->emitCastIntegralFloating(FromT, ToSem, getRoundingMode(E),
-                                            E);
+      return this->emitCastIntegralFloating(FromT, ToSem, getFPOptions(E), E);
     }
   }
 
@@ -5639,7 +5639,7 @@ bool Compiler<Emitter>::emitComplexBoolCast(const Expr *E) {
   if (!this->emitArrayElem(ElemT, 0, E))
     return false;
   if (ElemT == PT_Float) {
-    if (!this->emitCastFloatingIntegral(PT_Bool, E))
+    if (!this->emitCastFloatingIntegral(PT_Bool, getFPOptions(E), E))
       return false;
   } else {
     if (!this->emitCast(ElemT, PT_Bool, E))
@@ -5654,7 +5654,7 @@ bool Compiler<Emitter>::emitComplexBoolCast(const Expr *E) {
   if (!this->emitArrayElemPop(ElemT, 1, E))
     return false;
   if (ElemT == PT_Float) {
-    if (!this->emitCastFloatingIntegral(PT_Bool, E))
+    if (!this->emitCastFloatingIntegral(PT_Bool, getFPOptions(E), E))
       return false;
   } else {
     if (!this->emitCast(ElemT, PT_Bool, E))
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 939cc0dae3546f..b18afacdb2e491 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -341,6 +341,10 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
     return FPO.getRoundingMode();
   }
 
+  uint32_t getFPOptions(const Expr *E) const {
+    return E->getFPFeaturesInEffect(Ctx.getLangOpts()).getAsOpaqueInt();
+  }
+
   bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E);
   PrimType classifyComplexElementType(QualType T) const {
     assert(T->isAnyComplexType());
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 30ccceb42eb374..8f57afcb4dc120 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -756,14 +756,13 @@ bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
 }
 
 bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
-                      APFloat::opStatus Status) {
-  const SourceInfo &E = S.Current->getSource(OpPC);
-
+                      APFloat::opStatus Status, FPOptions FPO) {
   // [expr.pre]p4:
   //   If during the evaluation of an expression, the result is not
   //   mathematically defined [...], the behavior is undefined.
   // FIXME: C++ rules require us to not conform to IEEE 754 here.
   if (Result.isNan()) {
+    const SourceInfo &E = S.Current->getSource(OpPC);
     S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
         << /*NaN=*/true << S.Current->getRange(OpPC);
     return S.noteUndefinedBehavior();
@@ -774,12 +773,11 @@ bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
   if (S.inConstantContext())
     return true;
 
-  FPOptions FPO = E.asExpr()->getFPFeaturesInEffect(S.Ctx.getLangOpts());
-
   if ((Status & APFloat::opInexact) &&
       FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
     // Inexact result means that it depends on rounding mode. If the requested
     // mode is dynamic, the evaluation cannot be made in compile time.
+    const SourceInfo &E = S.Current->getSource(OpPC);
     S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
     return false;
   }
@@ -788,12 +786,14 @@ bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
       (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
        FPO.getExceptionMode() != LangOptions::FPE_Ignore ||
        FPO.getAllowFEnvAccess())) {
+    const SourceInfo &E = S.Current->getSource(OpPC);
     S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
     return false;
   }
 
   if ((Status & APFloat::opStatus::opInvalidOp) &&
       FPO.getExceptionMode() != LangOptions::FPE_Ignore) {
+    const SourceInfo &E = S.Current->getSource(OpPC);
     // There is no usefully definable result.
     S.FFDiag(E);
     return false;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index c1423a060bcb97..2580e81094b1c0 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -246,7 +246,7 @@ bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements,
 /// Checks if the result of a floating-point operation is valid
 /// in the current context.
 bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
-                      APFloat::opStatus Status);
+                      APFloat::opStatus Status, FPOptions FPO);
 
 /// Checks why the given DeclRefExpr is invalid.
 bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR);
@@ -376,14 +376,15 @@ bool Add(InterpState &S, CodePtr OpPC) {
   return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
 }
 
-inline bool Addf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
+inline bool Addf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
   const Floating &RHS = S.Stk.pop<Floating>();
   const Floating &LHS = S.Stk.pop<Floating>();
 
+  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
   Floating Result;
-  auto Status = Floating::add(LHS, RHS, RM, &Result);
+  auto Status = Floating::add(LHS, RHS, FPO.getRoundingMode(), &Result);
   S.Stk.push<Floating>(Result);
-  return CheckFloatResult(S, OpPC, Result, Status);
+  return CheckFloatResult(S, OpPC, Result, Status, FPO);
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
@@ -394,14 +395,15 @@ bool Sub(InterpState &S, CodePtr OpPC) {
   return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
 }
 
-inline bool Subf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
+inline bool Subf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
   const Floating &RHS = S.Stk.pop<Floating>();
   const Floating &LHS = S.Stk.pop<Floating>();
 
+  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
   Floating Result;
-  auto Status = Floating::sub(LHS, RHS, RM, &Result);
+  auto Status = Floating::sub(LHS, RHS, FPO.getRoundingMode(), &Result);
   S.Stk.push<Floating>(Result);
-  return CheckFloatResult(S, OpPC, Result, Status);
+  return CheckFloatResult(S, OpPC, Result, Status, FPO);
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
@@ -412,14 +414,15 @@ bool Mul(InterpState &S, CodePtr OpPC) {
   return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
 }
 
-inline bool Mulf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
+inline bool Mulf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
   const Floating &RHS = S.Stk.pop<Floating>();
   const Floating &LHS = S.Stk.pop<Floating>();
 
+  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
   Floating Result;
-  auto Status = Floating::mul(LHS, RHS, RM, &Result);
+  auto Status = Floating::mul(LHS, RHS, FPO.getRoundingMode(), &Result);
   S.Stk.push<Floating>(Result);
-  return CheckFloatResult(S, OpPC, Result, Status);
+  return CheckFloatResult(S, OpPC, Result, Status, FPO);
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
@@ -647,17 +650,18 @@ bool Div(InterpState &S, CodePtr OpPC) {
   return false;
 }
 
-inline bool Divf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
+inline bool Divf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
   const Floating &RHS = S.Stk.pop<Floating>();
   const Floating &LHS = S.Stk.pop<Floating>();
 
   if (!CheckDivRem(S, OpPC, LHS, RHS))
     return false;
 
+  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
   Floating Result;
-  auto Status = Floating::div(LHS, RHS, RM, &Result);
+  auto Status = Floating::div(LHS, RHS, FPO.getRoundingMode(), &Result);
   S.Stk.push<Floating>(Result);
-  return CheckFloatResult(S, OpPC, Result, Status);
+  return CheckFloatResult(S, OpPC, Result, Status, FPO);
 }
 
 //===----------------------------------------------------------------------===//
@@ -822,54 +826,55 @@ bool DecPop(InterpState &S, CodePtr OpPC) {
 
 template <IncDecOp Op, PushVal DoPush>
 bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
-                       llvm::RoundingMode RM) {
+                       uint32_t FPOI) {
   Floating Value = Ptr.deref<Floating>();
   Floating Result;
 
   if constexpr (DoPush == PushVal::Yes)
     S.Stk.push<Floating>(Value);
 
+  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
   llvm::APFloat::opStatus Status;
   if constexpr (Op == IncDecOp::Inc)
-    Status = Floating::increment(Value, RM, &Result);
+    Status = Floating::increment(Value, FPO.getRoundingMode(), &Result);
   else
-    Status = Floating::decrement(Value, RM, &Result);
+    Status = Floating::decrement(Value, FPO.getRoundingMode(), &Result);
 
   Ptr.deref<Floating>() = Result;
 
-  return CheckFloatResult(S, OpPC, Result, Status);
+  return CheckFloatResult(S, OpPC, Result, Status, FPO);
 }
 
-inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
+inline bool Incf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
   if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
     return false;
 
-  return IncDecFloatHelper<IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, RM);
+  return IncDecFloatHelper<IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, FPOI);
 }
 
-inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
+inline bool IncfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
   if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
     return false;
 
-  return IncDecFloatHelper<IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, RM);
+  return IncDecFloatHelper<IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, FPOI);
 }
 
-inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
+inline bool Decf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
   if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
     return false;
 
-  return IncDecFloatHelper<IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, RM);
+  return IncDecFloatHelper<IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, FPOI);
 }
 
-inline bool DecfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
+inline bool DecfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
   if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
     return false;
 
-  return IncDecFloatHelper<IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, RM);
+  return IncDecFloatHelper<IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, FPOI);
 }
 
 /// 1) Pops the value from the stack.
@@ -2126,20 +2131,21 @@ bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
 bool CastIntegralFloating(InterpState &S, CodePtr OpPC,
-                          const llvm::fltSemantics *Sem,
-                          llvm::RoundingMode RM) {
+                          const llvm::fltSemantics *Sem, uint32_t FPOI) {
   const T &From = S.Stk.pop<T>();
   APSInt FromAP = From.toAPSInt();
   Floating Result;
 
-  auto Status = Floating::fromIntegral(FromAP, *Sem, RM, Result);
+  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
+  auto Status =
+      Floating::fromIntegral(FromAP, *Sem, FPO.getRoundingMode(), Result);
   S.Stk.push<Floating>(Result);
 
-  return CheckFloatResult(S, OpPC, Result, Status);
+  return CheckFloatResult(S, OpPC, Result, Status, FPO);
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) {
+bool CastFloatingIntegral(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
   const Floating &F = S.Stk.pop<Floating>();
 
   if constexpr (std::is_same_v<T, Boolean>) {
@@ -2163,13 +2169,14 @@ bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) {
       return false;
     }
 
+    FPOptions F...
[truncated]

So we don't have to retrieve them from the InterpFrame, which is slow.
@tbaederr tbaederr merged commit 0f5f440 into llvm:main Sep 3, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants