[Fixed Point Arithmetic] Fixed Point Constant

This patch proposes an abstract type that represents fixed point numbers, similar to APInt or APSInt that was discussed in https://reviews.llvm.org/D48456#inline-425585. This type holds a value, scale, and saturation and is meant to perform intermediate calculations on constant fixed point values.

Currently this class is used as a way for handling the conversions between fixed point numbers with different sizes and radixes. For example, if I'm casting from a signed _Accum to a saturated unsigned short _Accum, I will need to check the value of the signed _Accum to see if it fits into the short _Accum which involves getting and comparing against the max/min values of the short _Accum. The FixedPointNumber class currently handles the radix shifting and extension when converting to a signed _Accum.

Differential Revision: https://reviews.llvm.org/D48661

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@339028 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Leonard Chan 2018-08-06 16:42:37 +00:00
parent 1d1e4e257b
commit 0fb95938a3
10 changed files with 991 additions and 6 deletions

View File

@ -79,6 +79,7 @@ struct fltSemantics;
namespace clang {
class APFixedPoint;
class APValue;
class ASTMutationListener;
class ASTRecordLayout;
@ -92,6 +93,7 @@ class CXXMethodDecl;
class CXXRecordDecl;
class DiagnosticsEngine;
class Expr;
class FixedPointSemantics;
class MangleContext;
class MangleNumberingContext;
class MaterializeTemporaryExpr;
@ -1961,6 +1963,9 @@ public:
unsigned char getFixedPointScale(QualType Ty) const;
unsigned char getFixedPointIBits(QualType Ty) const;
FixedPointSemantics getFixedPointSemantics(QualType Ty) const;
APFixedPoint getFixedPointMax(QualType Ty) const;
APFixedPoint getFixedPointMin(QualType Ty) const;
DeclarationNameInfo getNameForTemplate(TemplateName Name,
SourceLocation NameLoc) const;

View File

@ -0,0 +1,138 @@
//===- FixedPoint.h - Fixed point constant handling -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// Defines the fixed point number interface.
/// This is a class for abstracting various operations performed on fixed point
/// types described in ISO/IEC JTC1 SC22 WG14 N1169 starting at clause 4.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_FIXEDPOINT_H
#define LLVM_CLANG_BASIC_FIXEDPOINT_H
#include "llvm/ADT/APSInt.h"
namespace clang {
class ASTContext;
class QualType;
/// The fixed point semantics work similarly to llvm::fltSemantics. The width
/// specifies the whole bit width of the underlying scaled integer (with padding
/// if any). The scale represents the number of fractional bits in this type.
/// When HasUnsignedPadding is true and this type is signed, the first bit
/// in the value this represents is treaded as padding.
class FixedPointSemantics {
public:
FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned,
bool IsSaturated, bool HasUnsignedPadding)
: Width(Width), Scale(Scale), IsSigned(IsSigned),
IsSaturated(IsSaturated), HasUnsignedPadding(HasUnsignedPadding) {
assert(Width >= Scale && "Not enough room for the scale");
}
unsigned getWidth() const { return Width; }
unsigned getScale() const { return Scale; }
bool isSigned() const { return IsSigned; }
bool isSaturated() const { return IsSaturated; }
bool hasUnsignedPadding() const { return HasUnsignedPadding; }
void setSaturated(bool Saturated) { IsSaturated = Saturated; }
unsigned getIntegralBits() const {
if (IsSigned || (!IsSigned && HasUnsignedPadding))
return Width - Scale - 1;
else
return Width - Scale;
}
private:
unsigned Width;
unsigned Scale;
bool IsSigned;
bool IsSaturated;
bool HasUnsignedPadding;
};
/// The APFixedPoint class works similarly to APInt/APSInt in that it is a
/// functional replacement for a scaled integer. It is meant to replicate the
/// fixed point types proposed in ISO/IEC JTC1 SC22 WG14 N1169. The class carries
/// info about the fixed point type's width, sign, scale, and saturation, and
/// provides different operations that would normally be performed on fixed point
/// types.
///
/// Semantically this does not represent any existing C type other than fixed
/// point types and should eventually be moved to LLVM if fixed point types gain
/// native IR support.
class APFixedPoint {
public:
APFixedPoint(const llvm::APInt &Val, const FixedPointSemantics &Sema)
: Val(Val, !Sema.isSigned()), Sema(Sema) {
assert(Val.getBitWidth() == Sema.getWidth() &&
"The value should have a bit width that matches the Sema width");
}
APFixedPoint(uint64_t Val, const FixedPointSemantics &Sema)
: APFixedPoint(llvm::APInt(Sema.getWidth(), Val, Sema.isSigned()),
Sema) {}
llvm::APSInt getValue() const { return llvm::APSInt(Val, !Sema.isSigned()); }
inline unsigned getWidth() const { return Sema.getWidth(); }
inline unsigned getScale() const { return Sema.getScale(); }
inline bool isSaturated() const { return Sema.isSaturated(); }
inline bool isSigned() const { return Sema.isSigned(); }
inline bool hasPadding() const { return Sema.hasUnsignedPadding(); }
// Convert this number to match the semantics provided.
APFixedPoint convert(const FixedPointSemantics &DstSema) const;
APFixedPoint shr(unsigned Amt) const {
return APFixedPoint(Val >> Amt, Sema);
}
APFixedPoint shl(unsigned Amt) const {
return APFixedPoint(Val << Amt, Sema);
}
llvm::APSInt getIntPart() const {
if (Val < 0 && Val != -Val) // Cover the case when we have the min val
return -(-Val >> getScale());
else
return Val >> getScale();
}
// If LHS > RHS, return 1. If LHS == RHS, return 0. If LHS < RHS, return -1.
int compare(const APFixedPoint &Other) const;
bool operator==(const APFixedPoint &Other) const {
return compare(Other) == 0;
}
bool operator!=(const APFixedPoint &Other) const {
return compare(Other) != 0;
}
bool operator>(const APFixedPoint &Other) const { return compare(Other) > 0; }
bool operator<(const APFixedPoint &Other) const { return compare(Other) < 0; }
bool operator>=(const APFixedPoint &Other) const {
return compare(Other) >= 0;
}
bool operator<=(const APFixedPoint &Other) const {
return compare(Other) <= 0;
}
static APFixedPoint getMax(const FixedPointSemantics &Sema);
static APFixedPoint getMin(const FixedPointSemantics &Sema);
private:
llvm::APSInt Val;
FixedPointSemantics Sema;
};
} // namespace clang
#endif

View File

@ -312,6 +312,14 @@ public:
}
}
/// In the event this target uses the same number of fractional bits for its
/// unsigned types as it does with its signed counterparts, there will be
/// exactly one bit of padding.
/// Return true if unsigned fixed point types have padding for this target.
bool doUnsignedFixedPointTypesHavePadding() const {
return PaddingOnUnsignedFixedPoint;
}
/// Return the width (in bits) of the specified integer type enum.
///
/// For example, SignedInt -> getIntWidth().

View File

@ -48,6 +48,7 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/FixedPoint.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
@ -10433,3 +10434,22 @@ unsigned char ASTContext::getFixedPointIBits(QualType Ty) const {
return 0;
}
}
FixedPointSemantics ASTContext::getFixedPointSemantics(QualType Ty) const {
assert(Ty->isFixedPointType());
bool isSigned = Ty->isSignedFixedPointType();
return FixedPointSemantics(
static_cast<unsigned>(getTypeSize(Ty)), getFixedPointScale(Ty), isSigned,
Ty->isSaturatedFixedPointType(),
!isSigned && getTargetInfo().doUnsignedFixedPointTypesHavePadding());
}
APFixedPoint ASTContext::getFixedPointMax(QualType Ty) const {
assert(Ty->isFixedPointType());
return APFixedPoint::getMax(getFixedPointSemantics(Ty));
}
APFixedPoint ASTContext::getFixedPointMin(QualType Ty) const {
assert(Ty->isFixedPointType());
return APFixedPoint::getMin(getFixedPointSemantics(Ty));
}

View File

@ -54,6 +54,7 @@ add_clang_library(clangBasic
DiagnosticOptions.cpp
FileManager.cpp
FileSystemStatCache.cpp
FixedPoint.cpp
IdentifierTable.cpp
LangOptions.cpp
MemoryBufferCache.cpp

115
lib/Basic/FixedPoint.cpp Normal file
View File

@ -0,0 +1,115 @@
//===- FixedPoint.cpp - Fixed point constant handling -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// Defines the implementation for the fixed point number interface.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/Basic/FixedPoint.h"
namespace clang {
APFixedPoint APFixedPoint::convert(const FixedPointSemantics &DstSema) const {
llvm::APSInt NewVal = Val;
unsigned DstWidth = DstSema.getWidth();
unsigned DstScale = DstSema.getScale();
bool Upscaling = DstScale > getScale();
if (Upscaling) {
NewVal = NewVal.extend(NewVal.getBitWidth() + DstScale - getScale());
NewVal <<= (DstScale - getScale());
} else {
NewVal >>= (getScale() - DstScale);
}
if (DstSema.isSaturated()) {
auto Mask = llvm::APInt::getBitsSetFrom(
NewVal.getBitWidth(),
std::min(DstScale + DstSema.getIntegralBits(), NewVal.getBitWidth()));
llvm::APInt Masked(NewVal & Mask);
// Change in the bits above the sign
if (!(Masked == Mask || Masked == 0))
NewVal = NewVal.isNegative() ? Mask : ~Mask;
if (!DstSema.isSigned() && NewVal.isNegative())
NewVal = 0;
}
NewVal = NewVal.extOrTrunc(DstWidth);
NewVal.setIsSigned(DstSema.isSigned());
return APFixedPoint(NewVal, DstSema);
}
int APFixedPoint::compare(const APFixedPoint &Other) const {
llvm::APSInt ThisVal = getValue();
llvm::APSInt OtherVal = Other.getValue();
bool ThisSigned = Val.isSigned();
bool OtherSigned = OtherVal.isSigned();
unsigned OtherScale = Other.getScale();
unsigned OtherWidth = OtherVal.getBitWidth();
unsigned CommonWidth = std::max(Val.getBitWidth(), OtherWidth);
// Prevent overflow in the event the widths are the same but the scales differ
CommonWidth += std::abs(static_cast<int>(getScale() - OtherScale));
ThisVal = ThisVal.extOrTrunc(CommonWidth);
OtherVal = OtherVal.extOrTrunc(CommonWidth);
unsigned CommonScale = std::max(getScale(), OtherScale);
ThisVal = ThisVal.shl(CommonScale - getScale());
OtherVal = OtherVal.shl(CommonScale - OtherScale);
if (ThisSigned && OtherSigned) {
if (ThisVal.sgt(OtherVal))
return 1;
else if (ThisVal.slt(OtherVal))
return -1;
} else if (!ThisSigned && !OtherSigned) {
if (ThisVal.ugt(OtherVal))
return 1;
else if (ThisVal.ult(OtherVal))
return -1;
} else if (ThisSigned && !OtherSigned) {
if (ThisVal.isSignBitSet())
return -1;
else if (ThisVal.ugt(OtherVal))
return 1;
else if (ThisVal.ult(OtherVal))
return -1;
} else {
// !ThisSigned && OtherSigned
if (OtherVal.isSignBitSet())
return 1;
else if (ThisVal.ugt(OtherVal))
return 1;
else if (ThisVal.ult(OtherVal))
return -1;
}
return 0;
}
APFixedPoint APFixedPoint::getMax(const FixedPointSemantics &Sema) {
bool IsUnsigned = !Sema.isSigned();
auto Val = llvm::APSInt::getMaxValue(Sema.getWidth(), IsUnsigned);
if (IsUnsigned && Sema.hasUnsignedPadding())
Val = Val.lshr(1);
return APFixedPoint(Val, Sema);
}
APFixedPoint APFixedPoint::getMin(const FixedPointSemantics &Sema) {
auto Val = llvm::APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned());
return APFixedPoint(Val, Sema);
}
} // namespace clang

View File

@ -26,6 +26,7 @@
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/FixedPoint.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@ -3363,16 +3364,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
bool isSigned = !Literal.isUnsigned;
unsigned scale = Context.getFixedPointScale(Ty);
unsigned ibits = Context.getFixedPointIBits(Ty);
unsigned bit_width = Context.getTypeInfo(Ty).Width;
llvm::APInt Val(bit_width, 0, isSigned);
bool Overflowed = Literal.GetFixedPointValue(Val, scale);
bool ValIsZero = Val.isNullValue() && !Overflowed;
// Do not use bit_width since some types may have padding like _Fract or
// unsigned _Accums if PaddingOnUnsignedFixedPoint is set.
auto MaxVal = llvm::APInt::getMaxValue(ibits + scale).zextOrSelf(bit_width);
if (Literal.isFract && Val == MaxVal + 1)
auto MaxVal = Context.getFixedPointMax(Ty).getValue();
if (Literal.isFract && Val == MaxVal + 1 && !ValIsZero)
// Clause 6.4.4 - The value of a constant shall be in the range of
// representable values for its type, with exception for constants of a
// fract type with a value of exactly 1; such a constant shall denote

View File

@ -1,5 +1,4 @@
// RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-linux | FileCheck %s
// RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-scei-ps4-ubuntu-fast | FileCheck %s
// Primary fixed point types
signed short _Accum s_short_accum; // CHECK-DAG: @s_short_accum = {{.*}}global i16 0, align 2
@ -111,3 +110,18 @@ long _Fract long_fract_eps = 0x1p-31lr; // CHECK-DAG: @long_
unsigned short _Fract u_short_fract_eps = 0x1p-8uhr; // CHECK-DAG: @u_short_fract_eps = {{.*}}global i8 1, align 1
unsigned _Fract u_fract_eps = 0x1p-16ur; // CHECK-DAG: @u_fract_eps = {{.*}}global i16 1, align 2
unsigned long _Fract u_long_fract_eps = 0x1p-32ulr; // CHECK-DAG: @u_long_fract_eps = {{.*}}global i32 1, align 4
// Zero
short _Accum short_accum_zero = 0.0hk; // CHECK-DAG: @short_accum_zero = {{.*}}global i16 0, align 2
_Accum accum_zero = 0.0k; // CHECK-DAG: @accum_zero = {{.*}}global i32 0, align 4
long _Accum long_accum_zero = 0.0lk; // CHECK-DAG: @long_accum_zero = {{.*}}global i64 0, align 8
unsigned short _Accum u_short_accum_zero = 0.0uhk; // CHECK-DAG: @u_short_accum_zero = {{.*}}global i16 0, align 2
unsigned _Accum u_accum_zero = 0.0uk; // CHECK-DAG: @u_accum_zero = {{.*}}global i32 0, align 4
unsigned long _Accum u_long_accum_zero = 0.0ulk; // CHECK-DAG: @u_long_accum_zero = {{.*}}global i64 0, align 8
short _Fract short_fract_zero = 0.0hr; // CHECK-DAG: @short_fract_zero = {{.*}}global i8 0, align 1
_Fract fract_zero = 0.0r; // CHECK-DAG: @fract_zero = {{.*}}global i16 0, align 2
long _Fract long_fract_zero = 0.0lr; // CHECK-DAG: @long_fract_zero = {{.*}}global i32 0, align 4
unsigned short _Fract u_short_fract_zero = 0.0uhr; // CHECK-DAG: @u_short_fract_zero = {{.*}}global i8 0, align 1
unsigned _Fract u_fract_zero = 0.0ur; // CHECK-DAG: @u_fract_zero = {{.*}}global i16 0, align 2
unsigned long _Fract u_long_fract_zero = 0.0ulr; // CHECK-DAG: @u_long_fract_zero = {{.*}}global i32 0, align 4

View File

@ -6,6 +6,7 @@ add_clang_unittest(BasicTests
CharInfoTest.cpp
DiagnosticTest.cpp
FileManagerTest.cpp
FixedPointTest.cpp
MemoryBufferCacheTest.cpp
SourceManagerTest.cpp
VirtualFileSystemTest.cpp
@ -13,6 +14,7 @@ add_clang_unittest(BasicTests
target_link_libraries(BasicTests
PRIVATE
clangAST
clangBasic
clangLex
)

View File

@ -0,0 +1,683 @@
//===- unittests/Basic/FixedPointTest.cpp -- fixed point number tests -----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/FixedPoint.h"
#include "llvm/ADT/APSInt.h"
#include "gtest/gtest.h"
using clang::APFixedPoint;
using clang::FixedPointSemantics;
using llvm::APInt;
using llvm::APSInt;
namespace {
FixedPointSemantics Saturated(FixedPointSemantics Sema) {
Sema.setSaturated(true);
return Sema;
}
FixedPointSemantics getSAccumSema() {
return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/true,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getAccumSema() {
return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/true,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getLAccumSema() {
return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/true,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getSFractSema() {
return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/true,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getFractSema() {
return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/true,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getLFractSema() {
return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/true,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getUSAccumSema() {
return FixedPointSemantics(/*width=*/16, /*scale=*/8, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getUAccumSema() {
return FixedPointSemantics(/*width=*/32, /*scale=*/16, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getULAccumSema() {
return FixedPointSemantics(/*width=*/64, /*scale=*/32, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getUSFractSema() {
return FixedPointSemantics(/*width=*/8, /*scale=*/8, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getUFractSema() {
return FixedPointSemantics(/*width=*/16, /*scale=*/16, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getULFractSema() {
return FixedPointSemantics(/*width=*/32, /*scale=*/32, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/false);
}
FixedPointSemantics getPadUSAccumSema() {
return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/true);
}
FixedPointSemantics getPadUAccumSema() {
return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/true);
}
FixedPointSemantics getPadULAccumSema() {
return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/true);
}
FixedPointSemantics getPadUSFractSema() {
return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/true);
}
FixedPointSemantics getPadUFractSema() {
return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/true);
}
FixedPointSemantics getPadULFractSema() {
return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/false,
/*isSaturated=*/false,
/*hasUnsignedPadding=*/true);
}
void CheckUnpaddedMax(const FixedPointSemantics &Sema) {
ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()));
}
void CheckPaddedMax(const FixedPointSemantics &Sema) {
ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()) >> 1);
}
void CheckMin(const FixedPointSemantics &Sema) {
ASSERT_EQ(APFixedPoint::getMin(Sema).getValue(),
APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned()));
}
TEST(FixedPointTest, getMax) {
CheckUnpaddedMax(getSAccumSema());
CheckUnpaddedMax(getAccumSema());
CheckUnpaddedMax(getLAccumSema());
CheckUnpaddedMax(getUSAccumSema());
CheckUnpaddedMax(getUAccumSema());
CheckUnpaddedMax(getULAccumSema());
CheckUnpaddedMax(getSFractSema());
CheckUnpaddedMax(getFractSema());
CheckUnpaddedMax(getLFractSema());
CheckUnpaddedMax(getUSFractSema());
CheckUnpaddedMax(getUFractSema());
CheckUnpaddedMax(getULFractSema());
CheckPaddedMax(getPadUSAccumSema());
CheckPaddedMax(getPadUAccumSema());
CheckPaddedMax(getPadULAccumSema());
CheckPaddedMax(getPadUSFractSema());
CheckPaddedMax(getPadUFractSema());
CheckPaddedMax(getPadULFractSema());
}
TEST(FixedPointTest, getMin) {
CheckMin(getSAccumSema());
CheckMin(getAccumSema());
CheckMin(getLAccumSema());
CheckMin(getUSAccumSema());
CheckMin(getUAccumSema());
CheckMin(getULAccumSema());
CheckMin(getSFractSema());
CheckMin(getFractSema());
CheckMin(getLFractSema());
CheckMin(getUSFractSema());
CheckMin(getUFractSema());
CheckMin(getULFractSema());
CheckMin(getPadUSAccumSema());
CheckMin(getPadUAccumSema());
CheckMin(getPadULAccumSema());
CheckMin(getPadUSFractSema());
CheckMin(getPadUFractSema());
CheckMin(getPadULFractSema());
}
void CheckIntPart(const FixedPointSemantics &Sema, int64_t IntPart) {
unsigned Scale = Sema.getScale();
// Value with a fraction
APFixedPoint ValWithFract(APInt(Sema.getWidth(),
(IntPart << Scale) + (1ULL << (Scale - 1)),
Sema.isSigned()),
Sema);
ASSERT_EQ(ValWithFract.getIntPart(), IntPart);
// Just fraction
APFixedPoint JustFract(
APInt(Sema.getWidth(), (1ULL << (Scale - 1)), Sema.isSigned()), Sema);
ASSERT_EQ(JustFract.getIntPart(), 0);
// Whole number
APFixedPoint WholeNum(
APInt(Sema.getWidth(), (IntPart << Scale), Sema.isSigned()), Sema);
ASSERT_EQ(WholeNum.getIntPart(), IntPart);
// Negative
if (Sema.isSigned()) {
APFixedPoint Negative(
APInt(Sema.getWidth(), (IntPart << Scale), Sema.isSigned()), Sema);
ASSERT_EQ(Negative.getIntPart(), IntPart);
}
}
void CheckIntPartMin(const FixedPointSemantics &Sema, int64_t Expected) {
ASSERT_EQ(APFixedPoint::getMin(Sema).getIntPart(), Expected);
}
void CheckIntPartMax(const FixedPointSemantics &Sema, uint64_t Expected) {
ASSERT_EQ(APFixedPoint::getMax(Sema).getIntPart(), Expected);
}
TEST(FixedPoint, getIntPart) {
// Normal values
CheckIntPart(getSAccumSema(), 2);
CheckIntPart(getAccumSema(), 2);
CheckIntPart(getLAccumSema(), 2);
CheckIntPart(getUSAccumSema(), 2);
CheckIntPart(getUAccumSema(), 2);
CheckIntPart(getULAccumSema(), 2);
// Zero
CheckIntPart(getSAccumSema(), 0);
CheckIntPart(getAccumSema(), 0);
CheckIntPart(getLAccumSema(), 0);
CheckIntPart(getUSAccumSema(), 0);
CheckIntPart(getUAccumSema(), 0);
CheckIntPart(getULAccumSema(), 0);
CheckIntPart(getSFractSema(), 0);
CheckIntPart(getFractSema(), 0);
CheckIntPart(getLFractSema(), 0);
CheckIntPart(getUSFractSema(), 0);
CheckIntPart(getUFractSema(), 0);
CheckIntPart(getULFractSema(), 0);
// Min
CheckIntPartMin(getSAccumSema(), -256);
CheckIntPartMin(getAccumSema(), -65536);
CheckIntPartMin(getLAccumSema(), -4294967296);
CheckIntPartMin(getSFractSema(), -1);
CheckIntPartMin(getFractSema(), -1);
CheckIntPartMin(getLFractSema(), -1);
// Max
CheckIntPartMax(getSAccumSema(), 255);
CheckIntPartMax(getAccumSema(), 65535);
CheckIntPartMax(getLAccumSema(), 4294967295);
CheckIntPartMax(getUSAccumSema(), 255);
CheckIntPartMax(getUAccumSema(), 65535);
CheckIntPartMax(getULAccumSema(), 4294967295);
CheckIntPartMax(getSFractSema(), 0);
CheckIntPartMax(getFractSema(), 0);
CheckIntPartMax(getLFractSema(), 0);
CheckIntPartMax(getUSFractSema(), 0);
CheckIntPartMax(getUFractSema(), 0);
CheckIntPartMax(getULFractSema(), 0);
// Padded
// Normal Values
CheckIntPart(getPadUSAccumSema(), 2);
CheckIntPart(getPadUAccumSema(), 2);
CheckIntPart(getPadULAccumSema(), 2);
// Zero
CheckIntPart(getPadUSAccumSema(), 0);
CheckIntPart(getPadUAccumSema(), 0);
CheckIntPart(getPadULAccumSema(), 0);
CheckIntPart(getPadUSFractSema(), 0);
CheckIntPart(getPadUFractSema(), 0);
CheckIntPart(getPadULFractSema(), 0);
// Max
CheckIntPartMax(getPadUSAccumSema(), 255);
CheckIntPartMax(getPadUAccumSema(), 65535);
CheckIntPartMax(getPadULAccumSema(), 4294967295);
CheckIntPartMax(getPadUSFractSema(), 0);
CheckIntPartMax(getPadUFractSema(), 0);
CheckIntPartMax(getPadULFractSema(), 0);
}
TEST(FixedPoint, compare) {
// Equality
// With fractional part (2.5)
// Across sizes
ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
APFixedPoint(81920, getAccumSema()));
ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
APFixedPoint(5368709120, getLAccumSema()));
ASSERT_EQ(APFixedPoint(0, getSAccumSema()), APFixedPoint(0, getLAccumSema()));
// Across types (0.5)
ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
APFixedPoint(64, getSFractSema()));
ASSERT_EQ(APFixedPoint(16384, getAccumSema()),
APFixedPoint(16384, getFractSema()));
ASSERT_EQ(APFixedPoint(1073741824, getLAccumSema()),
APFixedPoint(1073741824, getLFractSema()));
// Across widths and types (0.5)
ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
APFixedPoint(16384, getFractSema()));
ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
APFixedPoint(1073741824, getLFractSema()));
// Across saturation
ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
APFixedPoint(81920, Saturated(getAccumSema())));
// Across signs
ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
APFixedPoint(640, getUSAccumSema()));
ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),
APFixedPoint(-81920, getAccumSema()));
// Across padding
ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
APFixedPoint(320, getPadUSAccumSema()));
ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),
APFixedPoint(320, getPadUSAccumSema()));
// Less than
ASSERT_LT(APFixedPoint(-1, getSAccumSema()), APFixedPoint(0, getAccumSema()));
ASSERT_LT(APFixedPoint(-1, getSAccumSema()),
APFixedPoint(0, getUAccumSema()));
ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getAccumSema()));
ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getUAccumSema()));
ASSERT_LT(APFixedPoint(0, getUSAccumSema()), APFixedPoint(1, getAccumSema()));
ASSERT_LT(APFixedPoint(0, getUSAccumSema()),
APFixedPoint(1, getUAccumSema()));
// Greater than
ASSERT_GT(APFixedPoint(0, getAccumSema()), APFixedPoint(-1, getSAccumSema()));
ASSERT_GT(APFixedPoint(0, getUAccumSema()),
APFixedPoint(-1, getSAccumSema()));
ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getSAccumSema()));
ASSERT_GT(APFixedPoint(1, getUAccumSema()), APFixedPoint(0, getSAccumSema()));
ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getUSAccumSema()));
ASSERT_GT(APFixedPoint(1, getUAccumSema()),
APFixedPoint(0, getUSAccumSema()));
}
// Check that a fixed point value in one sema is the same in another sema
void CheckUnsaturatedConversion(FixedPointSemantics Src,
FixedPointSemantics Dst, int64_t TestVal) {
int64_t ScaledVal = TestVal;
if (Dst.getScale() > Src.getScale()) {
ScaledVal <<= (Dst.getScale() - Src.getScale());
} else {
ScaledVal >>= (Src.getScale() - Dst.getScale());
}
APFixedPoint Fixed(TestVal, Src);
APFixedPoint Expected(ScaledVal, Dst);
ASSERT_EQ(Fixed.convert(Dst), Expected);
}
// Check the value in a given fixed point sema overflows to the saturated min
// for another sema
void CheckSaturatedConversionMin(FixedPointSemantics Src,
FixedPointSemantics Dst, int64_t TestVal) {
APFixedPoint Fixed(TestVal, Src);
ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMin(Dst));
}
// Check the value in a given fixed point sema overflows to the saturated max
// for another sema
void CheckSaturatedConversionMax(FixedPointSemantics Src,
FixedPointSemantics Dst, int64_t TestVal) {
APFixedPoint Fixed(TestVal, Src);
ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMax(Dst));
}
// Check one signed _Accum sema converted to other sema for different values.
void CheckSignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
int64_t OneVal) {
int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
int64_t HalfVal = (OneVal / 2); // 0.5
// +Accums to Accums
CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);
// -Accums to Accums
CheckUnsaturatedConversion(Src, getSAccumSema(), -NormalVal);
CheckUnsaturatedConversion(Src, getAccumSema(), -NormalVal);
CheckUnsaturatedConversion(Src, getLAccumSema(), -NormalVal);
CheckSaturatedConversionMin(Src, Saturated(getUSAccumSema()), -NormalVal);
CheckSaturatedConversionMin(Src, Saturated(getUAccumSema()), -NormalVal);
CheckSaturatedConversionMin(Src, Saturated(getULAccumSema()), -NormalVal);
CheckSaturatedConversionMin(Src, Saturated(getPadUSAccumSema()), -NormalVal);
CheckSaturatedConversionMin(Src, Saturated(getPadUAccumSema()), -NormalVal);
CheckSaturatedConversionMin(Src, Saturated(getPadULAccumSema()), -NormalVal);
// +Accums to Fracts
CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);
// -Accums to Fracts
CheckUnsaturatedConversion(Src, getSFractSema(), -HalfVal);
CheckUnsaturatedConversion(Src, getFractSema(), -HalfVal);
CheckUnsaturatedConversion(Src, getLFractSema(), -HalfVal);
CheckSaturatedConversionMin(Src, Saturated(getUSFractSema()), -HalfVal);
CheckSaturatedConversionMin(Src, Saturated(getUFractSema()), -HalfVal);
CheckSaturatedConversionMin(Src, Saturated(getULFractSema()), -HalfVal);
CheckSaturatedConversionMin(Src, Saturated(getPadUSFractSema()), -HalfVal);
CheckSaturatedConversionMin(Src, Saturated(getPadUFractSema()), -HalfVal);
CheckSaturatedConversionMin(Src, Saturated(getPadULFractSema()), -HalfVal);
// 0 to Accums
CheckUnsaturatedConversion(Src, getSAccumSema(), 0);
CheckUnsaturatedConversion(Src, getAccumSema(), 0);
CheckUnsaturatedConversion(Src, getLAccumSema(), 0);
CheckUnsaturatedConversion(Src, getUSAccumSema(), 0);
CheckUnsaturatedConversion(Src, getUAccumSema(), 0);
CheckUnsaturatedConversion(Src, getULAccumSema(), 0);
CheckUnsaturatedConversion(Src, getPadUSAccumSema(), 0);
CheckUnsaturatedConversion(Src, getPadUAccumSema(), 0);
CheckUnsaturatedConversion(Src, getPadULAccumSema(), 0);
// 0 to Fracts
CheckUnsaturatedConversion(Src, getSFractSema(), 0);
CheckUnsaturatedConversion(Src, getFractSema(), 0);
CheckUnsaturatedConversion(Src, getLFractSema(), 0);
CheckUnsaturatedConversion(Src, getUSFractSema(), 0);
CheckUnsaturatedConversion(Src, getUFractSema(), 0);
CheckUnsaturatedConversion(Src, getULFractSema(), 0);
CheckUnsaturatedConversion(Src, getPadUSFractSema(), 0);
CheckUnsaturatedConversion(Src, getPadUFractSema(), 0);
CheckUnsaturatedConversion(Src, getPadULFractSema(), 0);
}
// Check one unsigned _Accum sema converted to other sema for different
// values.
void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
int64_t OneVal) {
int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
int64_t HalfVal = (OneVal / 2); // 0.5
// +UAccums to Accums
CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);
CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);
// +UAccums to Fracts
CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);
CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);
}
TEST(FixedPoint, AccumConversions) {
// Normal conversions
CheckSignedAccumConversionsAgainstOthers(getSAccumSema(), 128);
CheckUnsignedAccumConversionsAgainstOthers(getUSAccumSema(), 256);
CheckSignedAccumConversionsAgainstOthers(getAccumSema(), 32768);
CheckUnsignedAccumConversionsAgainstOthers(getUAccumSema(), 65536);
CheckSignedAccumConversionsAgainstOthers(getLAccumSema(), 2147483648);
CheckUnsignedAccumConversionsAgainstOthers(getULAccumSema(), 4294967296);
CheckUnsignedAccumConversionsAgainstOthers(getPadUSAccumSema(), 128);
CheckUnsignedAccumConversionsAgainstOthers(getPadUAccumSema(), 32768);
CheckUnsignedAccumConversionsAgainstOthers(getPadULAccumSema(), 2147483648);
}
TEST(FixedPoint, AccumConversionOverflow) {
// To SAccum max limit (65536)
CheckSaturatedConversionMax(getLAccumSema(), Saturated(getAccumSema()),
140737488355328);
CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUAccumSema()),
140737488355328);
CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUAccumSema()),
140737488355328);
CheckSaturatedConversionMax(getULAccumSema(), Saturated(getAccumSema()),
281474976710656);
CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUAccumSema()),
281474976710656);
CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUAccumSema()),
281474976710656);
CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getAccumSema()),
140737488355328);
CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUAccumSema()),
140737488355328);
CheckSaturatedConversionMax(getPadULAccumSema(),
Saturated(getPadUAccumSema()), 140737488355328);
// To SAccum min limit (-65536)
CheckSaturatedConversionMin(getLAccumSema(), Saturated(getAccumSema()),
-140737488355328);
CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUAccumSema()),
-140737488355328);
CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUAccumSema()),
-140737488355328);
}
TEST(FixedPoint, SAccumConversionOverflow) {
// To SAccum max limit (256)
CheckSaturatedConversionMax(getAccumSema(), Saturated(getSAccumSema()),
8388608);
CheckSaturatedConversionMax(getAccumSema(), Saturated(getUSAccumSema()),
8388608);
CheckSaturatedConversionMax(getAccumSema(), Saturated(getPadUSAccumSema()),
8388608);
CheckSaturatedConversionMax(getUAccumSema(), Saturated(getSAccumSema()),
16777216);
CheckSaturatedConversionMax(getUAccumSema(), Saturated(getUSAccumSema()),
16777216);
CheckSaturatedConversionMax(getUAccumSema(), Saturated(getPadUSAccumSema()),
16777216);
CheckSaturatedConversionMax(getLAccumSema(), Saturated(getSAccumSema()),
549755813888);
CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUSAccumSema()),
549755813888);
CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUSAccumSema()),
549755813888);
CheckSaturatedConversionMax(getULAccumSema(), Saturated(getSAccumSema()),
1099511627776);
CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUSAccumSema()),
1099511627776);
CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUSAccumSema()),
1099511627776);
CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getSAccumSema()),
8388608);
CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getUSAccumSema()),
8388608);
CheckSaturatedConversionMax(getPadUAccumSema(),
Saturated(getPadUSAccumSema()), 8388608);
CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getSAccumSema()),
549755813888);
CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUSAccumSema()),
549755813888);
CheckSaturatedConversionMax(getPadULAccumSema(),
Saturated(getPadUSAccumSema()), 549755813888);
// To SAccum min limit (-256)
CheckSaturatedConversionMin(getAccumSema(), Saturated(getSAccumSema()),
-8388608);
CheckSaturatedConversionMin(getAccumSema(), Saturated(getUSAccumSema()),
-8388608);
CheckSaturatedConversionMin(getAccumSema(), Saturated(getPadUSAccumSema()),
-8388608);
CheckSaturatedConversionMin(getLAccumSema(), Saturated(getSAccumSema()),
-549755813888);
CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUSAccumSema()),
-549755813888);
CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUSAccumSema()),
-549755813888);
}
void CheckSaturatedConversionToFractMax(FixedPointSemantics Src,
int64_t OneVal) {
CheckSaturatedConversionMax(Src, Saturated(getSFractSema()), OneVal);
CheckSaturatedConversionMax(Src, Saturated(getFractSema()), OneVal);
CheckSaturatedConversionMax(Src, Saturated(getLFractSema()), OneVal);
CheckSaturatedConversionMax(Src, Saturated(getUSFractSema()), OneVal);
CheckSaturatedConversionMax(Src, Saturated(getUFractSema()), OneVal);
CheckSaturatedConversionMax(Src, Saturated(getPadULFractSema()), OneVal);
CheckSaturatedConversionMax(Src, Saturated(getPadUSFractSema()), OneVal);
CheckSaturatedConversionMax(Src, Saturated(getPadUFractSema()), OneVal);
CheckSaturatedConversionMax(Src, Saturated(getPadULFractSema()), OneVal);
}
void CheckSaturatedConversionToFractMin(FixedPointSemantics Src,
int64_t MinusOneVal) {
CheckSaturatedConversionMin(Src, Saturated(getSFractSema()), MinusOneVal);
CheckSaturatedConversionMin(Src, Saturated(getFractSema()), MinusOneVal);
CheckSaturatedConversionMin(Src, Saturated(getLFractSema()), MinusOneVal);
CheckSaturatedConversionMin(Src, Saturated(getUSFractSema()), MinusOneVal);
CheckSaturatedConversionMin(Src, Saturated(getUFractSema()), MinusOneVal);
CheckSaturatedConversionMin(Src, Saturated(getPadULFractSema()), MinusOneVal);
CheckSaturatedConversionMin(Src, Saturated(getPadUSFractSema()), MinusOneVal);
CheckSaturatedConversionMin(Src, Saturated(getPadUFractSema()), MinusOneVal);
CheckSaturatedConversionMin(Src, Saturated(getPadULFractSema()), MinusOneVal);
}
TEST(FixedPoint, OverflowConversionsToFract) {
CheckSaturatedConversionToFractMax(getSAccumSema(), 128);
CheckSaturatedConversionToFractMin(getSAccumSema(), -128);
CheckSaturatedConversionToFractMax(getAccumSema(), 32768);
CheckSaturatedConversionToFractMin(getAccumSema(), -32768);
CheckSaturatedConversionToFractMax(getLAccumSema(), 2147483648);
CheckSaturatedConversionToFractMin(getLAccumSema(), -2147483648);
// Unsigned
CheckSaturatedConversionToFractMax(getUSAccumSema(), 256);
CheckSaturatedConversionToFractMax(getUAccumSema(), 65536);
CheckSaturatedConversionToFractMax(getULAccumSema(), 4294967296);
// Padded unsigned
CheckSaturatedConversionToFractMax(getPadUSAccumSema(), 128);
CheckSaturatedConversionToFractMax(getPadUAccumSema(), 32768);
CheckSaturatedConversionToFractMax(getPadULAccumSema(), 2147483648);
}
TEST(FixedPoint, GetValueSignAfterConversion) {
APFixedPoint Fixed(255 << 7, getSAccumSema());
ASSERT_TRUE(Fixed.getValue().isSigned());
APFixedPoint UFixed = Fixed.convert(getUSAccumSema());
ASSERT_TRUE(UFixed.getValue().isUnsigned());
ASSERT_EQ(UFixed.getValue(), APSInt::getUnsigned(255 << 8).extOrTrunc(16));
}
TEST(FixedPoint, ModularWrapAround) {
// Positive to negative
APFixedPoint Val = APFixedPoint(1ULL << 7, getSAccumSema());
ASSERT_EQ(Val.convert(getLFractSema()).getValue(), -(1ULL << 31));
Val = APFixedPoint(1ULL << 23, getAccumSema());
ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), -(1ULL << 15));
Val = APFixedPoint(1ULL << 47, getLAccumSema());
ASSERT_EQ(Val.convert(getAccumSema()).getValue(), -(1ULL << 31));
// Negative to positive
Val = APFixedPoint(/*-1.5*/ -192, getSAccumSema());
ASSERT_EQ(Val.convert(getLFractSema()).getValue(), 1ULL << 30);
Val = APFixedPoint(-(257 << 15), getAccumSema());
ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), 255 << 7);
Val = APFixedPoint(-(65537ULL << 31), getLAccumSema());
ASSERT_EQ(Val.convert(getAccumSema()).getValue(), 65535 << 15);
// Signed to unsigned
Val = APFixedPoint(-(1 << 7), getSAccumSema());
ASSERT_EQ(Val.convert(getUSAccumSema()).getValue(), 255 << 8);
Val = APFixedPoint(-(1 << 15), getAccumSema());
ASSERT_EQ(Val.convert(getUAccumSema()).getValue(), 65535ULL << 16);
Val = APFixedPoint(-(1ULL << 31), getLAccumSema());
ASSERT_EQ(Val.convert(getULAccumSema()).getValue().getZExtValue(),
4294967295ULL << 32);
}
} // namespace