Skip to content

Commit eccf7fc

Browse files
committed
[AST] Add fixed-point subtraction constant evaluation.
Reviewers: rjmccall, leonardchan Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D73185
1 parent 6fafde0 commit eccf7fc

File tree

4 files changed

+87
-4
lines changed

4 files changed

+87
-4
lines changed

clang/include/clang/Basic/FixedPoint.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ class QualType;
2828
/// The fixed point semantics work similarly to llvm::fltSemantics. The width
2929
/// specifies the whole bit width of the underlying scaled integer (with padding
3030
/// if any). The scale represents the number of fractional bits in this type.
31-
/// When HasUnsignedPadding is true and this type is signed, the first bit
32-
/// in the value this represents is treaded as padding.
31+
/// When HasUnsignedPadding is true and this type is unsigned, the first bit
32+
/// in the value this represents is treated as padding.
3333
class FixedPointSemantics {
3434
public:
3535
FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned,
@@ -125,9 +125,10 @@ class APFixedPoint {
125125

126126
// Perform binary operations on a fixed point type. The resulting fixed point
127127
// value will be in the common, full precision semantics that can represent
128-
// the precision and ranges os both input values. See convert() for an
128+
// the precision and ranges of both input values. See convert() for an
129129
// explanation of the Overflow parameter.
130130
APFixedPoint add(const APFixedPoint &Other, bool *Overflow = nullptr) const;
131+
APFixedPoint sub(const APFixedPoint &Other, bool *Overflow = nullptr) const;
131132

132133
/// Perform a unary negation (-X) on this fixed point type, taking into
133134
/// account saturation if applicable.

clang/lib/AST/ExprConstant.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12924,7 +12924,16 @@ bool FixedPointExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
1292412924
case BO_Add: {
1292512925
bool AddOverflow, ConversionOverflow;
1292612926
APFixedPoint Result = LHSFX.add(RHSFX, &AddOverflow)
12927-
.convert(ResultFXSema, &ConversionOverflow);
12927+
.convert(ResultFXSema, &ConversionOverflow);
12928+
if ((AddOverflow || ConversionOverflow) &&
12929+
!HandleOverflow(Info, E, Result, E->getType()))
12930+
return false;
12931+
return Success(Result, E);
12932+
}
12933+
case BO_Sub: {
12934+
bool AddOverflow, ConversionOverflow;
12935+
APFixedPoint Result = LHSFX.sub(RHSFX, &AddOverflow)
12936+
.convert(ResultFXSema, &ConversionOverflow);
1292812937
if ((AddOverflow || ConversionOverflow) &&
1292912938
!HandleOverflow(Info, E, Result, E->getType()))
1293012939
return false;

clang/lib/Basic/FixedPoint.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,30 @@ APFixedPoint APFixedPoint::add(const APFixedPoint &Other,
173173
return APFixedPoint(Result, CommonFXSema);
174174
}
175175

176+
APFixedPoint APFixedPoint::sub(const APFixedPoint &Other,
177+
bool *Overflow) const {
178+
auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());
179+
APFixedPoint ConvertedThis = convert(CommonFXSema);
180+
APFixedPoint ConvertedOther = Other.convert(CommonFXSema);
181+
llvm::APSInt ThisVal = ConvertedThis.getValue();
182+
llvm::APSInt OtherVal = ConvertedOther.getValue();
183+
bool Overflowed = false;
184+
185+
llvm::APSInt Result;
186+
if (CommonFXSema.isSaturated()) {
187+
Result = CommonFXSema.isSigned() ? ThisVal.ssub_sat(OtherVal)
188+
: ThisVal.usub_sat(OtherVal);
189+
} else {
190+
Result = ThisVal.isSigned() ? ThisVal.ssub_ov(OtherVal, Overflowed)
191+
: ThisVal.usub_ov(OtherVal, Overflowed);
192+
}
193+
194+
if (Overflow)
195+
*Overflow = Overflowed;
196+
197+
return APFixedPoint(Result, CommonFXSema);
198+
}
199+
176200
void APFixedPoint::toString(llvm::SmallVectorImpl<char> &Str) const {
177201
llvm::APSInt Val = getValue();
178202
unsigned Scale = getScale();

clang/test/Frontend/fixed_point_sub.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,55 @@
11
// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
22
// RUN: %clang_cc1 -ffixed-point -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED
33

4+
// Subtraction between different fixed point types
5+
short _Accum sa_const = 1.0hk - 2.0hk; // CHECK-DAG: @sa_const = {{.*}}global i16 -128, align 2
6+
_Accum a_const = 1.0hk - 2.0k; // CHECK-DAG: @a_const = {{.*}}global i32 -32768, align 4
7+
long _Accum la_const = 1.0hk - 2.0lk; // CHECK-DAG: @la_const = {{.*}}global i64 -2147483648, align 8
8+
short _Accum sa_const2 = 0.5hr - 2.0hk; // CHECK-DAG: @sa_const2 = {{.*}}global i16 -192, align 2
9+
short _Accum sa_const3 = 0.5r - 2.0hk; // CHECK-DAG: @sa_const3 = {{.*}}global i16 -192, align 2
10+
short _Accum sa_const4 = 0.5lr - 2.0hk; // CHECK-DAG: @sa_const4 = {{.*}}global i16 -192, align 2
11+
short _Accum sa_const5 = 2.0hk - 0.5lr; // CHECK-DAG: @sa_const5 = {{.*}}global i16 192, align 2
12+
13+
// Unsigned subtraction
14+
unsigned short _Accum usa_const = 3.0uhk - 2.0uhk;
15+
// CHECK-SIGNED-DAG: @usa_const = {{.*}}global i16 768, align 2
16+
// CHECK-UNSIGNED-DAG: @usa_const = {{.*}}global i16 384, align 2
17+
18+
// Unsigned - signed
19+
short _Accum sa_const6 = 1.0uhk - 2.0hk;
20+
// CHECK-DAG: @sa_const6 = {{.*}}global i16 -128, align 2
21+
22+
// Subtraction with negative number
23+
short _Accum sa_const7 = 0.5hr - (-2.0hk);
24+
// CHECK-DAG: @sa_const7 = {{.*}}global i16 320, align 2
25+
26+
// Int subtraction
27+
unsigned short _Accum usa_const2 = 2 - 0.5uhk;
28+
// CHECK-SIGNED-DAG: @usa_const2 = {{.*}}global i16 640, align 2
29+
// CHECK-UNSIGNED-DAG: @usa_const2 = {{.*}}global i16 320, align 2
30+
short _Accum sa_const8 = 2 - (-0.5hk); // CHECK-DAG: @sa_const8 = {{.*}}global i16 320, align 2
31+
short _Accum sa_const9 = 257 - 2.0hk; // CHECK-DAG: @sa_const9 = {{.*}}global i16 32640, align 2
32+
long _Fract lf_const = 0.5lr - 1; // CHECK-DAG: @lf_const = {{.*}}global i32 -1073741824, align 4
33+
34+
// Saturated subtraction
35+
_Sat short _Accum sat_sa_const = (_Sat short _Accum)128.0hk - (-128.0hk);
36+
// CHECK-DAG: @sat_sa_const = {{.*}}global i16 32767, align 2
37+
_Sat unsigned short _Accum sat_usa_const = (_Sat unsigned short _Accum)128.0uhk - (-128.0uhk);
38+
// CHECK-SIGNED-DAG: @sat_usa_const = {{.*}}global i16 65535, align 2
39+
// CHECK-UNSIGNED-DAG: @sat_usa_const = {{.*}}global i16 32767, align 2
40+
_Sat short _Accum sat_sa_const2 = (_Sat short _Accum)128.0hk - (-128);
41+
// CHECK-DAG: @sat_sa_const2 = {{.*}}global i16 32767, align 2
42+
_Sat unsigned short _Accum sat_usa_const2 = (_Sat unsigned short _Accum)128.0uhk - (-128);
43+
// CHECK-SIGNED-DAG: @sat_usa_const2 = {{.*}}global i16 65535, align 2
44+
// CHECK-UNSIGNED-DAG: @sat_usa_const2 = {{.*}}global i16 32767, align 2
45+
_Sat unsigned short _Accum sat_usa_const3 = (_Sat unsigned short _Accum)0.5uhk - 2;
46+
// CHECK-DAG: @sat_usa_const3 = {{.*}}global i16 0, align 2
47+
_Sat short _Accum sat_sa_const3 = (_Sat short _Accum)-128.0hk - 128;
48+
// CHECK-DAG: @sat_sa_const3 = {{.*}}global i16 -32768, align 2
49+
_Sat short _Accum sat_sa_const4 = (_Sat short _Accum)-150.0hk - 130.0lk;
50+
// CHECK-DAG: @sat_sa_const4 = {{.*}}global i16 -32768, align 2
51+
52+
453
void SignedSubtraction() {
554
// CHECK-LABEL: SignedSubtraction
655
short _Accum sa;

0 commit comments

Comments
 (0)