Skip to content

Commit

Permalink
[clang][Interp] Compound assign operators for FP values
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D140377
  • Loading branch information
tbaederr committed Jan 25, 2023
1 parent c61fe18 commit af3a171
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 7 deletions.
80 changes: 78 additions & 2 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Expand Up @@ -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 =
Expand All @@ -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))
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Expand Up @@ -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;
Expand Down
7 changes: 2 additions & 5 deletions clang/test/AST/Interp/const-fpfeatures.cpp
Expand Up @@ -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 different semantics.
#if 0
constexpr float add_cast_round_down(float x, double y) {
#pragma STDC FENV_ROUND FE_DOWNWARD
float res = x;
Expand All @@ -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
24 changes: 24 additions & 0 deletions clang/test/AST/Interp/floats.cpp
Expand Up @@ -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__, "");
}

0 comments on commit af3a171

Please sign in to comment.