[clang] [clang][bytecode] Implement more binary operators for fixed point types (PR #110423)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 29 05:21:12 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/110423.diff
5 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+6-2)
- (modified) clang/lib/AST/ByteCode/FixedPoint.h (+33-6)
- (modified) clang/lib/AST/ByteCode/Interp.h (+11-1)
- (modified) clang/lib/AST/ByteCode/Opcodes.td (+6-1)
- (modified) clang/test/AST/ByteCode/fixed-point.cpp (+16)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index db5b21f5b1aacd..378a78fb1316e8 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1547,7 +1547,6 @@ bool Compiler<Emitter>::VisitFixedPointBinOp(const BinaryOperator *E) {
return this->emitEQFixedPoint(E);
case BO_NE:
return this->emitNEFixedPoint(E);
-#if 0
case BO_LT:
return this->emitLTFixedPoint(E);
case BO_LE:
@@ -1556,9 +1555,14 @@ bool Compiler<Emitter>::VisitFixedPointBinOp(const BinaryOperator *E) {
return this->emitGTFixedPoint(E);
case BO_GE:
return this->emitGEFixedPoint(E);
-#endif
case BO_Add:
return ConvertResult(this->emitAddFixedPoint(E));
+ case BO_Sub:
+ return ConvertResult(this->emitSubFixedPoint(E));
+ case BO_Mul:
+ return ConvertResult(this->emitMulFixedPoint(E));
+ case BO_Div:
+ return ConvertResult(this->emitDivFixedPoint(E));
default:
return this->emitInvalid(E);
diff --git a/clang/lib/AST/ByteCode/FixedPoint.h b/clang/lib/AST/ByteCode/FixedPoint.h
index c97a42401eaef3..b27ecfadd85146 100644
--- a/clang/lib/AST/ByteCode/FixedPoint.h
+++ b/clang/lib/AST/ByteCode/FixedPoint.h
@@ -58,9 +58,9 @@ class FixedPoint final {
bool isNegative() const { return V.getValue().isNegative(); }
bool isPositive() const { return V.getValue().isNonNegative(); }
bool isMin() const {
- return V.getValue() == APSInt::getMinValue(V.getSemantics().getWidth(),
- !V.getSemantics().isSigned());
+ return V == llvm::APFixedPoint::getMin(V.getSemantics());
}
+ bool isMinusOne() const { return V.isSigned() && V.getValue() == -1; }
FixedPoint truncate(unsigned BitWidth) const { return *this; }
@@ -82,9 +82,12 @@ class FixedPoint final {
}
ComparisonCategoryResult compare(const FixedPoint &Other) const {
- if (Other.V == V)
+ int c = V.compare(Other.V);
+ if (c == 0)
return ComparisonCategoryResult::Equal;
- return ComparisonCategoryResult::Unordered;
+ else if (c < 0)
+ return ComparisonCategoryResult::Less;
+ return ComparisonCategoryResult::Greater;
}
static bool neg(const FixedPoint &A, FixedPoint *R) {
@@ -101,16 +104,40 @@ class FixedPoint final {
}
static bool sub(const FixedPoint A, const FixedPoint B, unsigned Bits,
FixedPoint *R) {
- return true;
+ bool Overflow = false;
+ *R = FixedPoint(A.V.sub(B.V, &Overflow));
+ return Overflow;
}
static bool mul(const FixedPoint A, const FixedPoint B, unsigned Bits,
FixedPoint *R) {
- return true;
+ bool Overflow = false;
+ *R = FixedPoint(A.V.mul(B.V, &Overflow));
+ return Overflow;
}
static bool div(const FixedPoint A, const FixedPoint B, unsigned Bits,
FixedPoint *R) {
+ bool Overflow = false;
+ *R = FixedPoint(A.V.div(B.V, &Overflow));
+ return Overflow;
+ }
+ static bool rem(const FixedPoint A, const FixedPoint B, unsigned Bits,
+ FixedPoint *R) {
+ llvm_unreachable("Rem doesn't exist for fixed point values");
+ return true;
+ }
+ static bool bitAnd(const FixedPoint A, const FixedPoint B, unsigned Bits,
+ FixedPoint *R) {
+ return true;
+ }
+ static bool bitOr(const FixedPoint A, const FixedPoint B, unsigned Bits,
+ FixedPoint *R) {
+ return true;
+ }
+ static bool bitXor(const FixedPoint A, const FixedPoint B, unsigned Bits,
+ FixedPoint *R) {
return true;
}
+
static bool increment(const FixedPoint &A, FixedPoint *R) { return true; }
static bool decrement(const FixedPoint &A, FixedPoint *R) { return true; }
};
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 4d9d460c75174f..62e4917d72b4d1 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -374,10 +374,13 @@ bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
S.Stk.push<T>(Result);
return true;
}
-
// If for some reason evaluation continues, use the truncated results.
S.Stk.push<T>(Result);
+ // Short-circuit fixed-points here since the error handling is easier.
+ if constexpr (std::is_same_v<T, FixedPoint>)
+ return handleFixedPointOverflow(S, OpPC, Result);
+
// Slow path - compute the result using another bit of precision.
APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
@@ -687,6 +690,13 @@ bool Div(InterpState &S, CodePtr OpPC) {
S.Stk.push<T>(Result);
return true;
}
+
+ if constexpr (std::is_same_v<T, FixedPoint>) {
+ if (handleFixedPointOverflow(S, OpPC, Result)) {
+ S.Stk.push<T>(Result);
+ return true;
+ }
+ }
return false;
}
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 601ff95d973a27..e88335e67c19ff 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -84,6 +84,11 @@ def IntegerTypeClass : TypeClass {
Uint32, Sint64, Uint64, IntAP, IntAPS];
}
+def IntegerAndFixedTypeClass : TypeClass {
+ let Types = [Sint8, Uint8, Sint16, Uint16, Sint32,
+ Uint32, Sint64, Uint64, IntAP, IntAPS, FixedPoint];
+}
+
def FixedSizeIntegralTypeClass : TypeClass {
let Types = [Sint8, Uint8, Sint16, Uint16, Sint32,
Uint32, Sint64, Uint64, Bool];
@@ -146,7 +151,7 @@ class FloatOpcode : Opcode {
}
class IntegerOpcode : Opcode {
- let Types = [IntegerTypeClass];
+ let Types = [IntegerAndFixedTypeClass];
let HasGroup = 1;
}
diff --git a/clang/test/AST/ByteCode/fixed-point.cpp b/clang/test/AST/ByteCode/fixed-point.cpp
index 0c5b7c23e2bdef..48673d8be6f601 100644
--- a/clang/test/AST/ByteCode/fixed-point.cpp
+++ b/clang/test/AST/ByteCode/fixed-point.cpp
@@ -50,6 +50,13 @@ namespace BinOps {
static_assert(A + 100000 == 14.0k); // both-error {{is not an integral constant expression}} \
// both-note {{is outside the range of representable values}}
+
+ static_assert((A - A) == 0);
+ constexpr short _Accum mul_ovf1 = 255.0hk * 4.5hk; // both-error {{must be initialized by a constant expression}} \
+ // both-note {{value 123.5 is outside the range of representable values of type 'short _Accum'}}
+ constexpr short _Accum div_ovf1 = 255.0hk / 0.5hk; // both-error {{must be initialized by a constant expression}} \
+ // both-note {{value -2.0 is outside the range of representable values of type 'short _Accum'}}
+
}
namespace FixedPointCasts {
@@ -57,3 +64,12 @@ namespace FixedPointCasts {
constexpr _Accum A = B;
constexpr _Fract C = A;
}
+
+namespace Cmp {
+ constexpr _Accum A = 13.0k;
+ constexpr _Accum B = 14.0k;
+ static_assert(B > A);
+ static_assert(B >= A);
+ static_assert(A < B);
+ static_assert(A <= B);
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/110423
More information about the cfe-commits
mailing list