leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.
This patch contains the changes and tests for augmented assignments for primary
fixed point types.
s_accum = 7.5hk;
s_accum2 = 2.0hk;
s_accum += s_accum2;
assert(s_accum == 9.5hk);
s_accum += 2.5k;
assert(s_accum == 12);
This is a parent of https://reviews.llvm.org/D46926
Repository:
rC Clang
https://reviews.llvm.org/D46927
Files:
include/clang/AST/Type.h
lib/AST/Type.cpp
lib/CodeGen/CGExprScalar.cpp
lib/Sema/SemaExpr.cpp
test/Frontend/fixed_point_validation.c
Index: test/Frontend/fixed_point_validation.c
===
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -279,4 +279,35 @@
float laccum_diff = abs(base - 2.333lk);
assert(accum_diff < saccum_diff);
assert(laccum_diff < accum_diff);
+
+ / Auxillary assignments ***/
+
+ s_accum = 7.5hk;
+ s_accum2 = 2.0hk;
+ s_accum += s_accum2;
+ assert(s_accum == 9.5hk);
+ s_accum += 2.5k;
+ assert(s_accum == 12);
+
+ s_accum -= s_accum2;
+ assert(s_accum == 10);
+ s_accum -= 2.5lk;
+ assert(s_accum == 7.5k);
+
+ s_accum2 = 3.0k;
+ s_accum *= s_accum2;
+ assert(s_accum == 22.5k);
+ s_accum *= 0.5r;
+ assert(s_accum == 11.25hk);
+
+ s_accum /= s_accum2;
+ assert(s_accum == 3.75k);
+ s_accum /= 0.5hr;
+ assert(s_accum == 7.5k);
+
+ s_accum <<= 3;
+ assert(s_accum == 60);
+
+ s_accum >>= 3;
+ assert(s_accum == 7.5k);
}
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6057,7 +6057,7 @@
default: llvm_unreachable("Unable to convert from fixed point type");
case Type::STK_Integral: llvm_unreachable("Unimplemented scalar cast from fixed point to int"); // TODO
case Type::STK_Floating: return CK_FixedPointToFloating;
- case Type::STK_FixedPoint: llvm_unreachable("Unimplemented scalar cast from fixed point to fixed point"); // TODO
+ case Type::STK_FixedPoint: return CK_FixedPointCast;
}
}
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -308,6 +308,17 @@
Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
SourceLocation Loc, bool TreatBooleanAsSigned);
+ /// Emit a conversion between fixed point types by moving the radix point.
+ /// This does not take into account resizing of the underlying llvm type
+ /// which should be handled either before or after calling this function.
+ ///
+ /// If the type is being scaled up, this method should be called after
+ /// performing an intcast. If the type is scaled down, this method should be
+ /// called before performing an intcast. This is necessary such that the
+ /// shift operations retain as much of the original data as possible before
+ /// truncation or after extension.
+ Value *EmitFixedPointRadixShift(Value *Src, QualType SrcTy, QualType DstTy);
+
/// Emit a conversion from the specified complex type to the specified
/// destination type, where the destination type is an LLVM scalar type.
Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
@@ -957,6 +968,50 @@
SanitizerHandler::FloatCastOverflow, StaticArgs, OrigSrc);
}
+
+/// Emit a conversion between fixed point types by moving the radix point.
+/// This does not take into account resizing of the underlying llvm type
+/// which should be handled either before or after calling this function.
+///
+/// If the type is being scaled up, this method should be called after
+/// performing an intcast. If the type is scaled down, this method should be
+/// called before performing an intcast. This is necessary such that the
+/// shift operations retain as much of the original data as possible before
+/// truncation or after extension.
+Value *ScalarExprEmitter::EmitFixedPointRadixShift(Value *Src, QualType SrcTy,
+ QualType DstTy) {
+ assert(DstTy->isFixedPointType());
+ assert(SrcTy->isFixedPointType());
+
+ Value* Res = Src;
+
+ // Casting between fixed point types involves separating the integral and
+ // fractional bits, potentially shifting them, then joining back together.
+ unsigned dest_fbits = getFixedPointFBits(DstTy);
+ unsigned src_fbits = getFixedPointFBits(SrcTy);
+ unsigned dest_ibits = getFixedPointIBits(DstTy);
+ unsigned src_ibits = getFixedPointIBits(SrcTy);
+
+ // If the number of integral bits is decreasing, trim off any extra bits while
+ // retaining the sign.
+ if (dest_ibits < src_ibits) {
+Res = Builder.CreateShl(Res, src_ibits - dest_ibits);
+Res = Builder.CreateAShr(Res, src_ibits -