[clang] af3a171 - [clang][Interp] Compound assign operators for FP values

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 25 07:26:16 PST 2023


Author: Timm Bäder
Date: 2023-01-25T16:25:04+01:00
New Revision: af3a171dcffd73837d1debdd81399d51f0a0054a

URL: https://github.com/llvm/llvm-project/commit/af3a171dcffd73837d1debdd81399d51f0a0054a
DIFF: https://github.com/llvm/llvm-project/commit/af3a171dcffd73837d1debdd81399d51f0a0054a.diff

LOG: [clang][Interp] Compound assign operators for FP values

Differential Revision: https://reviews.llvm.org/D140377

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/ByteCodeExprGen.h
    clang/test/AST/Interp/const-fpfeatures.cpp
    clang/test/AST/Interp/floats.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 62ed09f078c1..d7b429c38f10 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -550,9 +550,86 @@ bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral(
   return this->emitConst(E->getValue(), E);
 }
 
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator(
+    const CompoundAssignOperator *E) {
+  assert(E->getType()->isFloatingType());
+
+  const Expr *LHS = E->getLHS();
+  const Expr *RHS = E->getRHS();
+  llvm::RoundingMode RM = getRoundingMode(E);
+  QualType LHSComputationType = E->getComputationLHSType();
+  QualType ResultType = E->getComputationResultType();
+  std::optional<PrimType> LT = classify(LHSComputationType);
+  std::optional<PrimType> RT = classify(ResultType);
+
+  if (!LT || !RT)
+    return false;
+
+  // First, visit LHS.
+  if (!visit(LHS))
+    return false;
+
+  if (!this->emitLoad(*LT, E))
+    return false;
+
+  // If necessary, convert LHS to its computation type.
+  if (LHS->getType() != LHSComputationType) {
+    const auto *TargetSemantics =
+        &Ctx.getASTContext().getFloatTypeSemantics(LHSComputationType);
+
+    if (!this->emitCastFP(TargetSemantics, RM, E))
+      return false;
+  }
+
+  // Now load RHS.
+  if (!visit(RHS))
+    return false;
+
+  switch (E->getOpcode()) {
+  case BO_AddAssign:
+    if (!this->emitAddf(RM, E))
+      return false;
+    break;
+  case BO_SubAssign:
+    if (!this->emitSubf(RM, E))
+      return false;
+    break;
+  case BO_MulAssign:
+    if (!this->emitMulf(RM, E))
+      return false;
+    break;
+  case BO_DivAssign:
+    if (!this->emitDivf(RM, E))
+      return false;
+    break;
+  default:
+    return false;
+  }
+
+  // If necessary, convert result to LHS's type.
+  if (LHS->getType() != ResultType) {
+    const auto *TargetSemantics =
+        &Ctx.getASTContext().getFloatTypeSemantics(LHS->getType());
+
+    if (!this->emitCastFP(TargetSemantics, RM, E))
+      return false;
+  }
+
+  if (DiscardResult)
+    return this->emitStorePop(*LT, E);
+  return this->emitStore(*LT, E);
+}
+
 template <class Emitter>
 bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
     const CompoundAssignOperator *E) {
+
+  // Handle floating point operations separately here, since they
+  // require special care.
+  if (E->getType()->isFloatingType())
+    return VisitFloatCompoundAssignOperator(E);
+
   const Expr *LHS = E->getLHS();
   const Expr *RHS = E->getRHS();
   std::optional<PrimType> LHSComputationT =
@@ -567,8 +644,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
   assert(!E->getType()->isPointerType() &&
          "Support pointer arithmethic in compound assignment operators");
 
-  assert(!E->getType()->isFloatingType() &&
-         "Support floating types in compound assignment operators");
+  assert(!E->getType()->isFloatingType() && "Handled above");
 
   // Get LHS pointer, load its value and get RHS value.
   if (!visit(LHS))

diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 6b82818fe09a..ed33e0285a8f 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -85,6 +85,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
   bool VisitStringLiteral(const StringLiteral *E);
   bool VisitCharacterLiteral(const CharacterLiteral *E);
   bool VisitCompoundAssignOperator(const CompoundAssignOperator *E);
+  bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E);
 
 protected:
   bool visitExpr(const Expr *E) override;

diff  --git a/clang/test/AST/Interp/const-fpfeatures.cpp b/clang/test/AST/Interp/const-fpfeatures.cpp
index 8f5d87291667..e24210810025 100644
--- a/clang/test/AST/Interp/const-fpfeatures.cpp
+++ b/clang/test/AST/Interp/const-fpfeatures.cpp
@@ -50,9 +50,6 @@ float V2 = add_round_up(1.0F, 0x0.000001p0F);
 // CHECK: @V2 = {{.*}} float 0x3FF0000020000000
 
 
-/// FIXME: The following tests need support for compound assign operators
-///   with LHS and RHS of 
diff erent semantics.
-#if 0
 constexpr float add_cast_round_down(float x, double y) {
   #pragma STDC FENV_ROUND FE_DOWNWARD
   float res = x;
@@ -70,5 +67,5 @@ constexpr float add_cast_round_up(float x, double y) {
 float V3 = add_cast_round_down(1.0F, 0x0.000001p0F);
 float V4 = add_cast_round_up(1.0F, 0x0.000001p0F);
 
-
-#endif
+// CHECK: @V3 = {{.*}} float 1.000000e+00
+// CHECK: @V4 = {{.*}} float 0x3FF0000020000000

diff  --git a/clang/test/AST/Interp/floats.cpp b/clang/test/AST/Interp/floats.cpp
index ab5d51ca400d..7b9328c4d118 100644
--- a/clang/test/AST/Interp/floats.cpp
+++ b/clang/test/AST/Interp/floats.cpp
@@ -54,3 +54,27 @@ constexpr int someInt = fm; // ref-error {{must be initialized by a constant exp
                             // ref-note {{is outside the range of representable values}} \
                             // expected-error {{must be initialized by a constant expression}} \
                             // expected-note {{is outside the range of representable values}}
+
+namespace compound {
+  constexpr float f1() {
+    float f = 0;
+    f += 3.0;
+    f -= 3.0f;
+
+    f += 1;
+    f /= 1;
+    f /= 1.0;
+    f *= f;
+
+    f *= 2.0;
+    return f;
+  }
+  static_assert(f1() == 2, "");
+
+  constexpr float f2() {
+    float f = __FLT_MAX__;
+    f += 1.0;
+    return f;
+  }
+  static_assert(f2() == __FLT_MAX__, "");
+}


        


More information about the cfe-commits mailing list