[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