This revision was automatically updated to reflect the committed changes. Closed by commit rG338c2489f63e: [clang][Interp] Implement inc/dec operators for floats (authored by tbaeder).
Changed prior to commit: https://reviews.llvm.org/D149634?vs=518642&id=519365#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D149634/new/ https://reviews.llvm.org/D149634 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/Floating.h clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Opcodes.td clang/test/AST/Interp/floats.cpp
Index: clang/test/AST/Interp/floats.cpp =================================================================== --- clang/test/AST/Interp/floats.cpp +++ clang/test/AST/Interp/floats.cpp @@ -1,6 +1,15 @@ // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s // RUN: %clang_cc1 -verify=ref %s + +constexpr void assert(bool C) { + if (C) + return; + // Invalid in constexpr. + (void)(1 / 0); // expected-warning {{undefined}} \ + // ref-warning {{undefined}} +} + constexpr int i = 2; constexpr float f = 1.0f; static_assert(f == 1.0f, ""); @@ -79,6 +88,30 @@ static_assert(f2() == __FLT_MAX__, ""); } +namespace unary { + constexpr float a() { + float f = 0.0; + assert(++f == 1.0); + assert(f == 1.0); + ++f; + f++; + assert(f == 3.0); + --f; + f--; + assert(f == 1.0); + return 1.0; + } + static_assert(a() == 1.0); + + constexpr float b() { + float f = __FLT_MAX__; + f++; + return f; + } + static_assert(b() == __FLT_MAX__); +} + + namespace ZeroInit { template<typename FloatT> struct A { Index: clang/lib/AST/Interp/Opcodes.td =================================================================== --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -499,11 +499,18 @@ let HasGroup = 1; } +// Increment and decrement. def Inc: IntegerOpcode; def IncPop : IntegerOpcode; def Dec: IntegerOpcode; def DecPop: IntegerOpcode; +// Float increment and decrement. +def Incf: FloatOpcode; +def IncfPop : FloatOpcode; +def Decf: FloatOpcode; +def DecfPop : FloatOpcode; + // [Real] -> [Real] def Neg: Opcode { let Types = [NonPtrTypeClass]; Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -540,6 +540,50 @@ return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr); } +template <IncDecOp Op, PushVal DoPush> +bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr, + llvm::RoundingMode RM) { + Floating Value = Ptr.deref<Floating>(); + Floating Result; + + if constexpr (DoPush == PushVal::Yes) + S.Stk.push<Floating>(Value); + + llvm::APFloat::opStatus Status; + if constexpr (Op == IncDecOp::Inc) + Status = Floating::increment(Value, RM, &Result); + else + Status = Floating::decrement(Value, RM, &Result); + + Ptr.deref<Floating>() = Result; + + return CheckFloatResult(S, OpPC, Status); +} + +inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + // FIXME: Check initialization of Ptr + const Pointer &Ptr = S.Stk.pop<Pointer>(); + return IncDecFloatHelper<IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, RM); +} + +inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + // FIXME: Check initialization of Ptr + const Pointer &Ptr = S.Stk.pop<Pointer>(); + return IncDecFloatHelper<IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, RM); +} + +inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + // FIXME: Check initialization of Ptr + const Pointer &Ptr = S.Stk.pop<Pointer>(); + return IncDecFloatHelper<IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, RM); +} + +inline bool DecfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + // FIXME: Check initialization of Ptr + const Pointer &Ptr = S.Stk.pop<Pointer>(); + return IncDecFloatHelper<IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, RM); +} + /// 1) Pops the value from the stack. /// 2) Pushes the bitwise complemented value on the stack (~V). template <PrimType Name, class T = typename PrimConv<Name>::T> Index: clang/lib/AST/Interp/Floating.h =================================================================== --- clang/lib/AST/Interp/Floating.h +++ clang/lib/AST/Interp/Floating.h @@ -111,12 +111,26 @@ return R->F.add(B.F, RM); } + static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM, + Floating *R) { + APFloat One(A.F.getSemantics(), 1); + *R = Floating(A.F); + return R->F.add(One, RM); + } + static APFloat::opStatus sub(Floating A, Floating B, llvm::RoundingMode RM, Floating *R) { *R = Floating(A.F); return R->F.subtract(B.F, RM); } + static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM, + Floating *R) { + APFloat One(A.F.getSemantics(), 1); + *R = Floating(A.F); + return R->F.subtract(One, RM); + } + static APFloat::opStatus mul(Floating A, Floating B, llvm::RoundingMode RM, Floating *R) { *R = Floating(A.F); Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1776,6 +1776,11 @@ return DiscardResult ? this->emitPopPtr(E) : true; } + if (T == PT_Float) { + return DiscardResult ? this->emitIncfPop(getRoundingMode(E), E) + : this->emitIncf(getRoundingMode(E), E); + } + return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E); } case UO_PostDec: { // x-- @@ -1789,6 +1794,11 @@ return DiscardResult ? this->emitPopPtr(E) : true; } + if (T == PT_Float) { + return DiscardResult ? this->emitDecfPop(getRoundingMode(E), E) + : this->emitDecf(getRoundingMode(E), E); + } + return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E); } case UO_PreInc: { // ++x @@ -1803,9 +1813,19 @@ } // Post-inc and pre-inc are the same if the value is to be discarded. - if (DiscardResult) + if (DiscardResult) { + if (T == PT_Float) + return this->emitIncfPop(getRoundingMode(E), E); return this->emitIncPop(*T, E); + } + if (T == PT_Float) { + const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType()); + this->emitLoadFloat(E); + this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E); + this->emitAddf(getRoundingMode(E), E); + return this->emitStoreFloat(E); + } this->emitLoad(*T, E); this->emitConst(1, E); this->emitAdd(*T, E); @@ -1823,9 +1843,19 @@ } // Post-dec and pre-dec are the same if the value is to be discarded. - if (DiscardResult) + if (DiscardResult) { + if (T == PT_Float) + return this->emitDecfPop(getRoundingMode(E), E); return this->emitDecPop(*T, E); + } + if (T == PT_Float) { + const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType()); + this->emitLoadFloat(E); + this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E); + this->emitSubf(getRoundingMode(E), E); + return this->emitStoreFloat(E); + } this->emitLoad(*T, E); this->emitConst(1, E); this->emitSub(*T, E);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits