diff options
author | Bjorn Pettersson <bjorn.a.pettersson@ericsson.com> | 2018-10-26 16:12:12 +0000 |
---|---|---|
committer | Bjorn Pettersson <bjorn.a.pettersson@ericsson.com> | 2018-10-26 16:12:12 +0000 |
commit | b25340236c089b2ed8dd502c30e12d1500824404 (patch) | |
tree | ee37093d15efde1674b19fc146462268d3bed5ca /clang/lib/CodeGen | |
parent | 672ba25d8b3261699ce21a5b528a6c7265e48dd5 (diff) | |
download | bcm5719-llvm-b25340236c089b2ed8dd502c30e12d1500824404.tar.gz bcm5719-llvm-b25340236c089b2ed8dd502c30e12d1500824404.zip |
[Fixed Point Arithmetic] Refactor fixed point casts
Summary:
- Added names for some emitted values (such as "tobool" for
the result of a cast to boolean).
- Replaced explicit IRBuilder request for doing sext/zext/trunc
by using CreateIntCast instead.
- Simplify code for emitting satuation into one if-statement
for clamping to max, and one if-statement for clamping to min.
Reviewers: leonardchan, ebevhan
Reviewed By: leonardchan
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D53707
llvm-svn: 345398
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 93 |
1 files changed, 38 insertions, 55 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 0351247e94c..c0cb8ad1711 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1029,7 +1029,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, // We do not need to check the padding bit on unsigned types if unsigned // padding is enabled because overflow into this bit is undefined // behavior. - return Builder.CreateIsNotNull(Src); + return Builder.CreateIsNotNull(Src, "tobool"); } llvm_unreachable( @@ -1247,79 +1247,62 @@ Value *ScalarExprEmitter::EmitFixedPointConversion(Value *Src, QualType SrcTy, unsigned DstWidth = DstFPSema.getWidth(); unsigned SrcScale = SrcFPSema.getScale(); unsigned DstScale = DstFPSema.getScale(); - bool IsSigned = SrcFPSema.isSigned(); + bool SrcIsSigned = SrcFPSema.isSigned(); + bool DstIsSigned = DstFPSema.isSigned(); + + llvm::Type *DstIntTy = Builder.getIntNTy(DstWidth); Value *Result = Src; unsigned ResultWidth = SrcWidth; if (!DstFPSema.isSaturated()) { - // Downscale - if (DstScale < SrcScale) { - if (IsSigned) - Result = Builder.CreateAShr(Result, SrcScale - DstScale); - else - Result = Builder.CreateLShr(Result, SrcScale - DstScale); - } + // Downscale. + if (DstScale < SrcScale) + Result = SrcIsSigned ? + Builder.CreateAShr(Result, SrcScale - DstScale, "downscale") : + Builder.CreateLShr(Result, SrcScale - DstScale, "downscale"); - // Resize - llvm::Type *DstIntTy = Builder.getIntNTy(DstWidth); - if (IsSigned) - Result = Builder.CreateSExtOrTrunc(Result, DstIntTy); - else - Result = Builder.CreateZExtOrTrunc(Result, DstIntTy); + // Resize. + Result = Builder.CreateIntCast(Result, DstIntTy, SrcIsSigned, "resize"); - // Upscale + // Upscale. if (DstScale > SrcScale) - Result = Builder.CreateShl(Result, DstScale - SrcScale); + Result = Builder.CreateShl(Result, DstScale - SrcScale, "upscale"); } else { + // Adjust the number of fractional bits. if (DstScale > SrcScale) { - // Need to extend first before scaling up ResultWidth = SrcWidth + DstScale - SrcScale; llvm::Type *UpscaledTy = Builder.getIntNTy(ResultWidth); - - if (IsSigned) - Result = Builder.CreateSExt(Result, UpscaledTy); - else - Result = Builder.CreateZExt(Result, UpscaledTy); - - Result = Builder.CreateShl(Result, DstScale - SrcScale); + Result = Builder.CreateIntCast(Result, UpscaledTy, SrcIsSigned, "resize"); + Result = Builder.CreateShl(Result, DstScale - SrcScale, "upscale"); } else if (DstScale < SrcScale) { - if (IsSigned) - Result = Builder.CreateAShr(Result, SrcScale - DstScale); - else - Result = Builder.CreateLShr(Result, SrcScale - DstScale); + Result = SrcIsSigned ? + Builder.CreateAShr(Result, SrcScale - DstScale, "downscale") : + Builder.CreateLShr(Result, SrcScale - DstScale, "downscale"); } - if (DstFPSema.getIntegralBits() < SrcFPSema.getIntegralBits()) { - auto Max = ConstantInt::get( + // Handle saturation. + bool LessIntBits = DstFPSema.getIntegralBits() < SrcFPSema.getIntegralBits(); + if (LessIntBits) { + Value *Max = ConstantInt::get( CGF.getLLVMContext(), APFixedPoint::getMax(DstFPSema).getValue().extOrTrunc(ResultWidth)); - Value *TooHigh = IsSigned ? Builder.CreateICmpSGT(Result, Max) - : Builder.CreateICmpUGT(Result, Max); - Result = Builder.CreateSelect(TooHigh, Max, Result); - - if (IsSigned) { - // Cannot overflow min to dest type is src is unsigned since all fixed - // point types can cover the unsigned min of 0. - auto Min = ConstantInt::get( - CGF.getLLVMContext(), - APFixedPoint::getMin(DstFPSema).getValue().extOrTrunc(ResultWidth)); - Value *TooLow = Builder.CreateICmpSLT(Result, Min); - Result = Builder.CreateSelect(TooLow, Min, Result); - } - } else if (IsSigned && !DstFPSema.isSigned()) { - llvm::Type *ResultTy = Builder.getIntNTy(ResultWidth); - Value *Zero = ConstantInt::getNullValue(ResultTy); - Value *LTZero = Builder.CreateICmpSLT(Result, Zero); - Result = Builder.CreateSelect(LTZero, Zero, Result); + Value *TooHigh = SrcIsSigned ? Builder.CreateICmpSGT(Result, Max) + : Builder.CreateICmpUGT(Result, Max); + Result = Builder.CreateSelect(TooHigh, Max, Result, "satmax"); + } + // Cannot overflow min to dest type if src is unsigned since all fixed + // point types can cover the unsigned min of 0. + if (SrcIsSigned && (LessIntBits || !DstIsSigned)) { + Value *Min = ConstantInt::get( + CGF.getLLVMContext(), + APFixedPoint::getMin(DstFPSema).getValue().extOrTrunc(ResultWidth)); + Value *TooLow = Builder.CreateICmpSLT(Result, Min); + Result = Builder.CreateSelect(TooLow, Min, Result, "satmin"); } - // Final resizing to dst width - llvm::Type *DstIntTy = Builder.getIntNTy(DstWidth); - if (IsSigned) - Result = Builder.CreateSExtOrTrunc(Result, DstIntTy); - else - Result = Builder.CreateZExtOrTrunc(Result, DstIntTy); + // Resize the integer part to get the final destination size. + Result = Builder.CreateIntCast(Result, DstIntTy, SrcIsSigned, "resize"); } return Result; } |