Index: clang/lib/CodeGen/CGExprScalar.cpp =================================================================== --- clang/lib/CodeGen/CGExprScalar.cpp +++ clang/lib/CodeGen/CGExprScalar.cpp @@ -1481,9 +1481,14 @@ // Adjust the number of fractional bits. if (DstScale > SrcScale) { // Compare to DstWidth to prevent resizing twice. - ResultWidth = std::max(SrcWidth + DstScale - SrcScale, DstWidth); - llvm::Type *UpscaledTy = Builder.getIntNTy(ResultWidth); - Result = Builder.CreateIntCast(Result, UpscaledTy, SrcIsSigned, "resize"); + if (ResultWidth != DstWidth) { + // No rescaling is needed if both sides have the same resulting width. + // This would end up with a needless int cast. + ResultWidth = std::max(SrcWidth + DstScale - SrcScale, DstWidth); + llvm::Type *UpscaledTy = Builder.getIntNTy(ResultWidth); + Result = + Builder.CreateIntCast(Result, UpscaledTy, SrcIsSigned, "resize"); + } Result = Builder.CreateShl(Result, DstScale - SrcScale, "upscale"); } else if (DstScale < SrcScale) { Result = SrcIsSigned ? Index: clang/test/Frontend/fixed_point_conversions.c =================================================================== --- clang/test/Frontend/fixed_point_conversions.c +++ clang/test/Frontend/fixed_point_conversions.c @@ -186,14 +186,12 @@ // Accum to Fract, increasing scale sat_lf = sat_a; // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4 - // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = sext i32 [[OLD_ACCUM]] to i48 - // DEFAULT-NEXT: [[FRACT:%[0-9a-z]+]] = shl i48 [[ACCUM]], 16 - // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i48 [[FRACT]], 2147483647 - // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i48 2147483647, i48 [[FRACT]] - // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i48 [[RESULT]], -2147483648 - // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i48 -2147483648, i48 [[RESULT]] - // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i48 [[RESULT2]] to i32 - // DEFAULT-NEXT: store i32 [[RESULT_TRUNC]], i32* %sat_lf, align 4 + // DEFAULT-NEXT: [[FRACT:%[0-9a-z]+]] = shl i32 [[OLD_ACCUM]], 16 + // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[FRACT]], 2147483647 + // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 2147483647, i32 [[FRACT]] + // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], -2147483648 + // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 -2147483648, i32 [[RESULT]] + // DEFAULT-NEXT: store i32 [[RESULT2]], i32* %sat_lf, align 4 // Signed to unsigned, decreasing scale _Sat _Accum sat_a2; @@ -218,12 +216,10 @@ // Signed to unsigned, increasing scale sat_ua = sat_a; // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4 - // DEFAULT-NEXT: [[ACCUM_EXT:%[0-9a-z]+]] = sext i32 [[OLD_ACCUM]] to i33 - // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i33 [[ACCUM_EXT]], 1 - // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i33 [[ACCUM]], 0 - // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i33 0, i33 [[ACCUM]] - // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i33 [[RESULT2]] to i32 - // DEFAULT-NEXT: store i32 [[RESULT_TRUNC]], i32* %sat_ua, align 4 + // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[OLD_ACCUM]], 1 + // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[ACCUM]], 0 + // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[ACCUM]] + // DEFAULT-NEXT: store i32 [[RESULT2]], i32* %sat_ua, align 4 // SAME: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4 // SAME-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[ACCUM]], 0 // SAME-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[ACCUM]]