diff --git a/clang/include/clang/Basic/FixedPoint.h b/clang/include/clang/Basic/FixedPoint.h --- a/clang/include/clang/Basic/FixedPoint.h +++ b/clang/include/clang/Basic/FixedPoint.h @@ -63,8 +63,12 @@ /// precision semantic that can precisely represent the precision and ranges /// of both input values. This does not compute the resulting semantics for a /// given binary operation. + /// Is UnsignedPaddingIsSigned is true, unsigned semantics which would + /// otherwise have been unsigned will be signed instead. This is for codegen + /// purposes. FixedPointSemantics - getCommonSemantics(const FixedPointSemantics &Other) const; + getCommonSemantics(const FixedPointSemantics &Other, + bool UnsignedPaddingIsSigned = false) const; /// Return the FixedPointSemantics for an integer type. static FixedPointSemantics GetIntegerSemantics(unsigned Width, diff --git a/clang/lib/Basic/FixedPoint.cpp b/clang/lib/Basic/FixedPoint.cpp --- a/clang/lib/Basic/FixedPoint.cpp +++ b/clang/lib/Basic/FixedPoint.cpp @@ -124,8 +124,9 @@ return APFixedPoint(Val, Sema); } -FixedPointSemantics FixedPointSemantics::getCommonSemantics( - const FixedPointSemantics &Other) const { +FixedPointSemantics +FixedPointSemantics::getCommonSemantics(const FixedPointSemantics &Other, + bool UnsignedPaddingIsSigned) const { unsigned CommonScale = std::max(getScale(), Other.getScale()); unsigned CommonWidth = std::max(getIntegralBits(), Other.getIntegralBits()) + CommonScale; @@ -139,6 +140,23 @@ Other.hasUnsignedPadding() && !ResultIsSaturated; } + // For codegen purposes, make unsigned with padding semantics signed instead. + // This means that we will generate signed operations. The result from these + // operations is defined, since ending up with a negative result is undefined + // for nonsaturating semantics, and for saturating semantics we will + // perform a clamp-to-zero in the last conversion to result semantics (since + // we are going from saturating signed to saturating unsigned). + // + // This codegen is beneficial for targets which want to use unsigned padding, + // since such targets likely do not have native instructions which can + // implement the wider scale of unpadded unsigned and would prefer to reuse + // their signed operations for this. + if (UnsignedPaddingIsSigned && !ResultIsSigned && + (hasUnsignedPadding() || Other.hasUnsignedPadding())) { + ResultIsSigned = true; + ResultHasUnsignedPadding = false; + } + // If the result is signed, add an extra bit for the sign. Otherwise, if it is // unsigned and has unsigned padding, we only need to add the extra padding // bit back if we are not saturating. diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -3595,7 +3595,7 @@ auto LHSFixedSema = Ctx.getFixedPointSemantics(LHSTy); auto RHSFixedSema = Ctx.getFixedPointSemantics(RHSTy); auto ResultFixedSema = Ctx.getFixedPointSemantics(ResultTy); - auto CommonFixedSema = LHSFixedSema.getCommonSemantics(RHSFixedSema); + auto CommonFixedSema = LHSFixedSema.getCommonSemantics(RHSFixedSema, true); // Convert the operands to the full precision type. Value *FullLHS = EmitFixedPointConversion(LHS, LHSFixedSema, CommonFixedSema, diff --git a/clang/test/Frontend/fixed_point_add.c b/clang/test/Frontend/fixed_point_add.c --- a/clang/test/Frontend/fixed_point_add.c +++ b/clang/test/Frontend/fixed_point_add.c @@ -227,7 +227,8 @@ // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i24 [[USA_EXT]], 8 // CHECK-NEXT: [[UF_EXT:%[a-z0-9]+]] = zext i16 [[UF]] to i24 // CHECK-NEXT: [[SUM:%[0-9]+]] = add i24 [[USA]], [[UF_EXT]] - // CHECK-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8 + // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8 + // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = ashr i24 [[SUM]], 8 // CHECK-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i24 [[RES]] to i16 // CHECK-NEXT: store i16 [[RES_TRUNC]], i16* %usa, align 2 usa = usa + uf; @@ -286,11 +287,11 @@ // SIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8 // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i40 [[USA_EXT]], [[I]] // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16 - // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i39 - // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i39 - // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i39 [[USA_EXT]], [[I]] - // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16 + // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i40 + // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40 + // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 7 + // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i40 [[USA_EXT]], [[I]] + // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16 // CHECK-NEXT: store i16 [[RES]], i16* %usa, align 2 usa = usa + ui; @@ -348,11 +349,10 @@ // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.uadd.sat.i16(i16 [[USA]], i16 [[USA_SAT]]) // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2 - // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15 - // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.uadd.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]]) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16 - // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2 + // UNSIGNED-NEXT: [[SUM:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[USA]], i16 [[USA_SAT]]) + // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]] + // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %usa_sat, align 2 usa_sat = usa + usa_sat; // CHECK: [[UA:%[0-9]+]] = load i32, i32* %ua, align 4 @@ -361,12 +361,12 @@ // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.uadd.sat.i32(i32 [[UA]], i32 [[USA]]) // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4 - // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31 - // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31 - // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.uadd.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]]) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32 - // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4 + // UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[USA]] to i32 + // UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8 + // UNSIGNED-NEXT: [[TMP9:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[UA]], i32 [[UPSCALE]]) + // UNSIGNED-NEXT: [[TMP10:%.*]] = icmp slt i32 [[TMP9]], 0 + // UNSIGNED-NEXT: [[SATMIN1:%.*]] = select i1 [[TMP10]], i32 0, i32 [[TMP9]] + // UNSIGNED-NEXT: store i32 [[SATMIN1]], i32* %ua_sat, align 4 ua_sat = ua + usa_sat; // CHECK: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2 @@ -401,11 +401,10 @@ // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.uadd.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]]) // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2 - // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15 - // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.uadd.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]]) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16 - // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2 + // UNSIGNED-NEXT: [[SUM:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]]) + // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]] + // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %uf_sat, align 2 uf_sat = uf_sat + uf_sat; // CHECK: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2 diff --git a/clang/test/Frontend/fixed_point_comparisons.c b/clang/test/Frontend/fixed_point_comparisons.c --- a/clang/test/Frontend/fixed_point_comparisons.c +++ b/clang/test/Frontend/fixed_point_comparisons.c @@ -108,28 +108,32 @@ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4 // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32 // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8 - // CHECK-NEXT: {{.*}} = icmp ugt i32 [[UPSCALE_A]], [[A2]] + // UNPADDED-NEXT: {{.*}} = icmp ugt i32 [[UPSCALE_A]], [[A2]] + // PADDED-NEXT: {{.*}} = icmp sgt i32 [[UPSCALE_A]], [[A2]] usa >= ua; // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2 // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4 // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32 // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8 - // CHECK-NEXT: {{.*}} = icmp uge i32 [[UPSCALE_A]], [[A2]] + // UNPADDED-NEXT: {{.*}} = icmp uge i32 [[UPSCALE_A]], [[A2]] + // PADDED-NEXT: {{.*}} = icmp sge i32 [[UPSCALE_A]], [[A2]] usa < ua; // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2 // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4 // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32 // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8 - // CHECK-NEXT: {{.*}} = icmp ult i32 [[UPSCALE_A]], [[A2]] + // UNPADDED-NEXT: {{.*}} = icmp ult i32 [[UPSCALE_A]], [[A2]] + // PADDED-NEXT: {{.*}} = icmp slt i32 [[UPSCALE_A]], [[A2]] usa <= ua; // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2 // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4 // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32 // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8 - // CHECK-NEXT: {{.*}} = icmp ule i32 [[UPSCALE_A]], [[A2]] + // UNPADDED-NEXT: {{.*}} = icmp ule i32 [[UPSCALE_A]], [[A2]] + // PADDED-NEXT: {{.*}} = icmp sle i32 [[UPSCALE_A]], [[A2]] } void TestIntComparisons() { @@ -202,10 +206,10 @@ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40 // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8 // UNPADDED-NEXT: {{.*}} = icmp ugt i40 [[RESIZE_A]], [[UPSCALE_I]] - // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39 - // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39 - // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7 - // PADDED-NEXT: {{.*}} = icmp ugt i39 [[RESIZE_A]], [[UPSCALE_I]] + // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40 + // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40 + // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7 + // PADDED-NEXT: {{.*}} = icmp sgt i40 [[RESIZE_A]], [[UPSCALE_I]] usa >= ui; // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2 @@ -214,10 +218,10 @@ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40 // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8 // UNPADDED-NEXT: {{.*}} = icmp uge i40 [[RESIZE_A]], [[UPSCALE_I]] - // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39 - // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39 - // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7 - // PADDED-NEXT: {{.*}} = icmp uge i39 [[RESIZE_A]], [[UPSCALE_I]] + // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40 + // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40 + // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7 + // PADDED-NEXT: {{.*}} = icmp sge i40 [[RESIZE_A]], [[UPSCALE_I]] usa < ui; // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2 @@ -226,10 +230,10 @@ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40 // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8 // UNPADDED-NEXT: {{.*}} = icmp ult i40 [[RESIZE_A]], [[UPSCALE_I]] - // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39 - // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39 - // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7 - // PADDED-NEXT: {{.*}} = icmp ult i39 [[RESIZE_A]], [[UPSCALE_I]] + // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40 + // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40 + // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7 + // PADDED-NEXT: {{.*}} = icmp slt i40 [[RESIZE_A]], [[UPSCALE_I]] usa <= ui; // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2 @@ -238,10 +242,10 @@ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40 // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8 // UNPADDED-NEXT: {{.*}} = icmp ule i40 [[RESIZE_A]], [[UPSCALE_I]] - // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39 - // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39 - // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7 - // PADDED-NEXT: {{.*}} = icmp ule i39 [[RESIZE_A]], [[UPSCALE_I]] + // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40 + // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40 + // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7 + // PADDED-NEXT: {{.*}} = icmp sle i40 [[RESIZE_A]], [[UPSCALE_I]] // Allow for comparisons with other int like types. These are no different // from comparing to an int other than varying sizes. The integer types are @@ -282,10 +286,10 @@ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40 // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8 // UNPADDED-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]] - // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39 - // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39 - // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7 - // PADDED-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]] + // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40 + // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40 + // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7 + // PADDED-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]] } void TestComparisonSignage() { diff --git a/clang/test/Frontend/fixed_point_compound.c b/clang/test/Frontend/fixed_point_compound.c --- a/clang/test/Frontend/fixed_point_compound.c +++ b/clang/test/Frontend/fixed_point_compound.c @@ -200,12 +200,12 @@ // SIGNED-NEXT: [[UPSCALE56:%.*]] = shl i64 [[RESIZE55]], 32 // SIGNED-NEXT: [[TMP49:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[TMP48]], i64 [[UPSCALE56]]) // SIGNED-NEXT: store i64 [[TMP49]], i64* @sula, align 8 -// UNSIGNED-NEXT: [[RESIZE39:%.*]] = trunc i64 [[TMP48]] to i63 -// UNSIGNED-NEXT: [[RESIZE40:%.*]] = zext i32 [[TMP47]] to i63 -// UNSIGNED-NEXT: [[UPSCALE41:%.*]] = shl i63 [[RESIZE40]], 31 -// UNSIGNED-NEXT: [[TMP49:%.*]] = call i63 @llvm.uadd.sat.i63(i63 [[RESIZE39]], i63 [[UPSCALE41]]) -// UNSIGNED-NEXT: [[RESIZE42:%.*]] = zext i63 [[TMP49]] to i64 -// UNSIGNED-NEXT: store i64 [[RESIZE42]], i64* @sula, align 8 +// UNSIGNED-NEXT: [[RESIZE40:%.*]] = zext i32 [[TMP47]] to i64 +// UNSIGNED-NEXT: [[UPSCALE41:%.*]] = shl i64 [[RESIZE40]], 31 +// UNSIGNED-NEXT: [[TMP49:%.*]] = call i64 @llvm.sadd.sat.i64(i64 [[TMP48]], i64 [[UPSCALE41]]) +// UNSIGNED-NEXT: [[TMP52:%.*]] = icmp slt i64 [[TMP49]], 0 +// UNSIGNED-NEXT: [[SATMIN48:%.*]] = select i1 [[TMP52]], i64 0, i64 [[TMP49]] +// UNSIGNED-NEXT: store i64 [[SATMIN48]], i64* @sula, align 8 sula += u; // CHECK: [[TMP50:%.*]] = load i16, i16* @suf, align 2 diff --git a/clang/test/Frontend/fixed_point_div.c b/clang/test/Frontend/fixed_point_div.c --- a/clang/test/Frontend/fixed_point_div.c +++ b/clang/test/Frontend/fixed_point_div.c @@ -230,7 +230,7 @@ // CHECK: [[TMP0:%.*]] = load i16, i16* %usa, align 2 // CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* %usa, align 2 // SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 8) - // UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7) + // UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7) // CHECK-NEXT: store i16 [[TMP2]], i16* %usa, align 2 usa = usa / usa; @@ -239,7 +239,7 @@ // CHECK-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP3]] to i32 // CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8 // SIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.udiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 16) - // UNSIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.udiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15) + // UNSIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15) // CHECK-NEXT: store i32 [[TMP5]], i32* %ua, align 4 ua = usa / ua; @@ -247,7 +247,7 @@ // CHECK-NEXT: [[TMP7:%.*]] = load i8, i8* %usf, align 1 // CHECK-NEXT: [[RESIZE1:%.*]] = zext i8 [[TMP7]] to i16 // SIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 8) - // UNSIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7) + // UNSIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7) // CHECK-NEXT: store i16 [[TMP8]], i16* %usa, align 2 usa = usa / usf; @@ -257,8 +257,9 @@ // CHECK-NEXT: [[UPSCALE3:%.*]] = shl i24 [[RESIZE2]], 8 // CHECK-NEXT: [[RESIZE4:%.*]] = zext i16 [[TMP10]] to i24 // SIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.udiv.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 16) - // UNSIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.udiv.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15) - // CHECK-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP11]], 8 + // SIGNED-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP11]], 8 + // UNSIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.sdiv.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15) + // UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i24 [[TMP11]], 8 // CHECK-NEXT: [[RESIZE5:%.*]] = trunc i24 [[DOWNSCALE]] to i16 // CHECK-NEXT: store i16 [[RESIZE5]], i16* %usa, align 2 usa = usa / uf; @@ -316,11 +317,11 @@ // SIGNED-NEXT: [[UPSCALE13:%.*]] = shl i40 [[RESIZE12]], 8 // SIGNED-NEXT: [[TMP11:%.*]] = call i40 @llvm.udiv.fix.i40(i40 [[RESIZE11]], i40 [[UPSCALE13]], i32 8) // SIGNED-NEXT: [[RESIZE14:%.*]] = trunc i40 [[TMP11]] to i16 - // UNSIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i39 - // UNSIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i39 - // UNSIGNED-NEXT: [[UPSCALE13:%.*]] = shl i39 [[RESIZE12]], 7 - // UNSIGNED-NEXT: [[TMP11:%.*]] = call i39 @llvm.udiv.fix.i39(i39 [[RESIZE11]], i39 [[UPSCALE13]], i32 7) - // UNSIGNED-NEXT: [[RESIZE14:%.*]] = trunc i39 [[TMP11]] to i16 + // UNSIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i40 + // UNSIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i40 + // UNSIGNED-NEXT: [[UPSCALE13:%.*]] = shl i40 [[RESIZE12]], 7 + // UNSIGNED-NEXT: [[TMP11:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[RESIZE11]], i40 [[UPSCALE13]], i32 7) + // UNSIGNED-NEXT: [[RESIZE14:%.*]] = trunc i40 [[TMP11]] to i16 // CHECK-NEXT: store i16 [[RESIZE14]], i16* %usa, align 2 usa = usa / ui; @@ -363,11 +364,11 @@ // SIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i40 // SIGNED-NEXT: [[TMP23:%.*]] = call i40 @llvm.udiv.fix.i40(i40 [[UPSCALE28]], i40 [[RESIZE29]], i32 8) // SIGNED-NEXT: [[RESIZE30:%.*]] = trunc i40 [[TMP23]] to i16 - // UNSIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i39 - // UNSIGNED-NEXT: [[UPSCALE28:%.*]] = shl i39 [[RESIZE27]], 7 - // UNSIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i39 - // UNSIGNED-NEXT: [[TMP23:%.*]] = call i39 @llvm.udiv.fix.i39(i39 [[UPSCALE28]], i39 [[RESIZE29]], i32 7) - // UNSIGNED-NEXT: [[RESIZE30:%.*]] = trunc i39 [[TMP23]] to i16 + // UNSIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i40 + // UNSIGNED-NEXT: [[UPSCALE28:%.*]] = shl i40 [[RESIZE27]], 7 + // UNSIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i40 + // UNSIGNED-NEXT: [[TMP23:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[UPSCALE28]], i40 [[RESIZE29]], i32 7) + // UNSIGNED-NEXT: [[RESIZE30:%.*]] = trunc i40 [[TMP23]] to i16 // CHECK-NEXT: store i16 [[RESIZE30]], i16* %usa, align 2 usa = ui / usa; @@ -412,11 +413,10 @@ // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.udiv.fix.sat.i16(i16 [[USA]], i16 [[USA_SAT]], i32 8) // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2 - // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15 - // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.udiv.fix.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]], i32 7) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16 - // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2 + // UNSIGNED-NEXT: [[SUM:%.*]] = call i16 @llvm.sdiv.fix.sat.i16(i16 [[USA]], i16 [[USA_SAT]], i32 7) + // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]] + // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %usa_sat, align 2 usa_sat = usa / usa_sat; // CHECK: [[UA:%[0-9]+]] = load i32, i32* %ua, align 4 @@ -425,12 +425,12 @@ // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.udiv.fix.sat.i32(i32 [[UA]], i32 [[USA]], i32 16) // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4 - // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31 - // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31 - // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.udiv.fix.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]], i32 15) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32 - // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4 + // UNSIGNED-NEXT: [[USA_EXT:%.*]] = zext i16 [[USA]] to i32 + // UNSIGNED-NEXT: [[USA:%.*]] = shl i32 [[USA_EXT]], 8 + // UNSIGNED-NEXT: [[SUM:%.*]] = call i32 @llvm.sdiv.fix.sat.i32(i32 [[UA]], i32 [[USA]], i32 15) + // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i32 [[SUM]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i32 0, i32 [[SUM]] + // UNSIGNED-NEXT: store i32 [[SATMIN]], i32* %ua_sat, align 4 ua_sat = ua / usa_sat; // CHECK: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2 @@ -465,11 +465,10 @@ // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.udiv.fix.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]], i32 16) // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2 - // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15 - // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.udiv.fix.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]], i32 15) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16 - // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2 + // UNSIGNED-NEXT: [[SUM:%.*]] = call i16 @llvm.sdiv.fix.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]], i32 15) + // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]] + // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %uf_sat, align 2 uf_sat = uf_sat / uf_sat; // CHECK: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2 diff --git a/clang/test/Frontend/fixed_point_mul.c b/clang/test/Frontend/fixed_point_mul.c --- a/clang/test/Frontend/fixed_point_mul.c +++ b/clang/test/Frontend/fixed_point_mul.c @@ -207,7 +207,7 @@ // CHECK: [[TMP0:%.*]] = load i16, i16* %usa, align 2 // CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* %usa, align 2 // SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 8) - // UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7) + // UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7) // CHECK-NEXT: store i16 [[TMP2]], i16* %usa, align 2 usa = usa * usa; @@ -216,7 +216,7 @@ // CHECK-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP3]] to i32 // CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8 // SIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.umul.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 16) - // UNSIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.umul.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15) + // UNSIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15) // CHECK-NEXT: store i32 [[TMP5]], i32* %ua, align 4 ua = usa * ua; @@ -224,7 +224,7 @@ // CHECK-NEXT: [[TMP7:%.*]] = load i8, i8* %usf, align 1 // CHECK-NEXT: [[RESIZE1:%.*]] = zext i8 [[TMP7]] to i16 // SIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 8) - // UNSIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7) + // UNSIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7) // CHECK-NEXT: store i16 [[TMP8]], i16* %usa, align 2 usa = usa * usf; @@ -234,8 +234,9 @@ // CHECK-NEXT: [[UPSCALE3:%.*]] = shl i24 [[RESIZE2]], 8 // CHECK-NEXT: [[RESIZE4:%.*]] = zext i16 [[TMP10]] to i24 // SIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.umul.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 16) - // UNSIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.umul.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15) - // CHECK-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP11]], 8 + // SIGNED-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP11]], 8 + // UNSIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.smul.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15) + // UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i24 [[TMP11]], 8 // CHECK-NEXT: [[RESIZE5:%.*]] = trunc i24 [[DOWNSCALE]] to i16 // CHECK-NEXT: store i16 [[RESIZE5]], i16* %usa, align 2 usa = usa * uf; @@ -293,11 +294,11 @@ // SIGNED-NEXT: [[UPSCALE13:%.*]] = shl i40 [[RESIZE12]], 8 // SIGNED-NEXT: [[TMP11:%.*]] = call i40 @llvm.umul.fix.i40(i40 [[RESIZE11]], i40 [[UPSCALE13]], i32 8) // SIGNED-NEXT: [[RESIZE14:%.*]] = trunc i40 [[TMP11]] to i16 - // UNSIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i39 - // UNSIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i39 - // UNSIGNED-NEXT: [[UPSCALE13:%.*]] = shl i39 [[RESIZE12]], 7 - // UNSIGNED-NEXT: [[TMP11:%.*]] = call i39 @llvm.umul.fix.i39(i39 [[RESIZE11]], i39 [[UPSCALE13]], i32 7) - // UNSIGNED-NEXT: [[RESIZE14:%.*]] = trunc i39 [[TMP11]] to i16 + // UNSIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i40 + // UNSIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i40 + // UNSIGNED-NEXT: [[UPSCALE13:%.*]] = shl i40 [[RESIZE12]], 7 + // UNSIGNED-NEXT: [[TMP11:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[RESIZE11]], i40 [[UPSCALE13]], i32 7) + // UNSIGNED-NEXT: [[RESIZE14:%.*]] = trunc i40 [[TMP11]] to i16 // CHECK-NEXT: store i16 [[RESIZE14]], i16* %usa, align 2 usa = usa * ui; @@ -340,11 +341,11 @@ // SIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i40 // SIGNED-NEXT: [[TMP23:%.*]] = call i40 @llvm.umul.fix.i40(i40 [[UPSCALE28]], i40 [[RESIZE29]], i32 8) // SIGNED-NEXT: [[RESIZE30:%.*]] = trunc i40 [[TMP23]] to i16 - // UNSIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i39 - // UNSIGNED-NEXT: [[UPSCALE28:%.*]] = shl i39 [[RESIZE27]], 7 - // UNSIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i39 - // UNSIGNED-NEXT: [[TMP23:%.*]] = call i39 @llvm.umul.fix.i39(i39 [[UPSCALE28]], i39 [[RESIZE29]], i32 7) - // UNSIGNED-NEXT: [[RESIZE30:%.*]] = trunc i39 [[TMP23]] to i16 + // UNSIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i40 + // UNSIGNED-NEXT: [[UPSCALE28:%.*]] = shl i40 [[RESIZE27]], 7 + // UNSIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i40 + // UNSIGNED-NEXT: [[TMP23:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[UPSCALE28]], i40 [[RESIZE29]], i32 7) + // UNSIGNED-NEXT: [[RESIZE30:%.*]] = trunc i40 [[TMP23]] to i16 // CHECK-NEXT: store i16 [[RESIZE30]], i16* %usa, align 2 usa = ui * usa; @@ -389,25 +390,22 @@ // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.umul.fix.sat.i16(i16 [[USA]], i16 [[USA_SAT]], i32 8) // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2 - // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15 - // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.umul.fix.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]], i32 7) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16 - // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2 + // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.smul.fix.sat.i16(i16 [[USA]], i16 [[USA_SAT]], i32 7) + // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]] + // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %usa_sat, align 2 usa_sat = usa * usa_sat; - // CHECK: [[UA:%[0-9]+]] = load i32, i32* %ua, align 4 - // CHECK-NEXT: [[USA:%[0-9]+]] = load i16, i16* %usa_sat, align 2 - // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i32 - // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8 + // CHECK: [[UA:%[0-9]+]] = load i32, i32* %ua, align 4 + // CHECK-NEXT: [[USA:%[0-9]+]] = load i16, i16* %usa_sat, align 2 + // CHECK-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i32 + // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.umul.fix.sat.i32(i32 [[UA]], i32 [[USA]], i32 16) // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4 - // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31 - // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31 - // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.umul.fix.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]], i32 15) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32 - // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4 + // UNSIGNED-NEXT: [[SUM:%.*]] = call i32 @llvm.smul.fix.sat.i32(i32 [[UA]], i32 [[USA]], i32 15) + // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i32 [[SUM]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i32 0, i32 [[SUM]] + // UNSIGNED-NEXT: store i32 [[SATMIN]], i32* %ua_sat, align 4 ua_sat = ua * usa_sat; // CHECK: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2 @@ -442,11 +440,10 @@ // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.umul.fix.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]], i32 16) // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2 - // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15 - // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.umul.fix.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]], i32 15) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16 - // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2 + // UNSIGNED-NEXT: [[SUM:%.*]] = call i16 @llvm.smul.fix.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]], i32 15) + // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]] + // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %uf_sat, align 2 uf_sat = uf_sat * uf_sat; // CHECK: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2 diff --git a/clang/test/Frontend/fixed_point_sub.c b/clang/test/Frontend/fixed_point_sub.c --- a/clang/test/Frontend/fixed_point_sub.c +++ b/clang/test/Frontend/fixed_point_sub.c @@ -233,7 +233,8 @@ // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i24 [[USA_EXT]], 8 // CHECK-NEXT: [[UF_EXT:%[a-z0-9]+]] = zext i16 [[UF]] to i24 // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i24 [[USA]], [[UF_EXT]] - // CHECK-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8 + // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8 + // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = ashr i24 [[SUM]], 8 // CHECK-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i24 [[RES]] to i16 // CHECK-NEXT: store i16 [[RES_TRUNC]], i16* %usa, align 2 usa = usa - uf; @@ -292,11 +293,11 @@ // SIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8 // SIGNED-NEXT: [[SUM:%[0-9]+]] = sub i40 [[USA_EXT]], [[I]] // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16 - // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i39 - // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i39 - // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = sub i39 [[USA_EXT]], [[I]] - // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16 + // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i40 + // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40 + // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 7 + // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = sub i40 [[USA_EXT]], [[I]] + // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16 // CHECK-NEXT: store i16 [[RES]], i16* %usa, align 2 usa = usa - ui; @@ -354,11 +355,10 @@ // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.usub.sat.i16(i16 [[USA]], i16 [[USA_SAT]]) // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2 - // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15 - // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.usub.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]]) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16 - // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2 + // UNSIGNED-NEXT: [[SUM:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[USA]], i16 [[USA_SAT]]) + // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]] + // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %usa_sat, align 2 usa_sat = usa - usa_sat; // CHECK: [[UA:%[0-9]+]] = load i32, i32* %ua, align 4 @@ -367,12 +367,12 @@ // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.usub.sat.i32(i32 [[UA]], i32 [[USA]]) // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4 - // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31 - // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31 - // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.usub.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]]) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32 - // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4 + // UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[USA]] to i32 + // UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8 + // UNSIGNED-NEXT: [[TMP9:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[UA]], i32 [[UPSCALE]]) + // UNSIGNED-NEXT: [[TMP10:%.*]] = icmp slt i32 [[TMP9]], 0 + // UNSIGNED-NEXT: [[SATMIN1:%.*]] = select i1 [[TMP10]], i32 0, i32 [[TMP9]] + // UNSIGNED-NEXT: store i32 [[SATMIN1]], i32* %ua_sat, align 4 ua_sat = ua - usa_sat; // CHECK: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2 @@ -407,11 +407,10 @@ // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2 // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.usub.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]]) // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2 - // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15 - // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15 - // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.usub.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]]) - // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16 - // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2 + // UNSIGNED-NEXT: [[SUM:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]]) + // UNSIGNED-NEXT: [[USE_MIN:%.*]] = icmp slt i16 [[SUM]], 0 + // UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[USE_MIN]], i16 0, i16 [[SUM]] + // UNSIGNED-NEXT: store i16 [[SATMIN]], i16* %uf_sat, align 2 uf_sat = uf_sat - uf_sat; // CHECK: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2 diff --git a/clang/test/Frontend/fixed_point_unary.c b/clang/test/Frontend/fixed_point_unary.c --- a/clang/test/Frontend/fixed_point_unary.c +++ b/clang/test/Frontend/fixed_point_unary.c @@ -68,28 +68,28 @@ // CHECK: [[TMP18:%.*]] = load i32, i32* @sua, align 4 // SIGNED-NEXT: [[TMP19:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[TMP18]], i32 65536) // SIGNED-NEXT: store i32 [[TMP19]], i32* @sua, align 4 -// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP18]] to i31 -// UNSIGNED-NEXT: [[TMP19:%.*]] = call i31 @llvm.uadd.sat.i31(i31 [[RESIZE]], i31 32768) -// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i31 [[TMP19]] to i32 -// UNSIGNED-NEXT: store i32 [[RESIZE1]], i32* @sua, align 4 +// UNSIGNED-NEXT: [[TMP19:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP18]], i32 32768) +// UNSIGNED-NEXT: [[TMP20:%.*]] = icmp slt i32 [[TMP19]], 0 +// UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP20]], i32 0, i32 [[TMP19]] +// UNSIGNED-NEXT: store i32 [[SATMIN]], i32* @sua, align 4 sua++; // CHECK: [[TMP20:%.*]] = load i16, i16* @susa, align 2 // SIGNED-NEXT: [[TMP21:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[TMP20]], i16 256) // SIGNED-NEXT: store i16 [[TMP21]], i16* @susa, align 2 -// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i16 [[TMP20]] to i15 -// UNSIGNED-NEXT: [[TMP21:%.*]] = call i15 @llvm.uadd.sat.i15(i15 [[RESIZE2]], i15 128) -// UNSIGNED-NEXT: [[RESIZE3:%.*]] = zext i15 [[TMP21]] to i16 -// UNSIGNED-NEXT: store i16 [[RESIZE3]], i16* @susa, align 2 +// UNSIGNED-NEXT: [[TMP22:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[TMP20]], i16 128) +// UNSIGNED-NEXT: [[TMP23:%.*]] = icmp slt i16 [[TMP22]], 0 +// UNSIGNED-NEXT: [[SATMIN1:%.*]] = select i1 [[TMP23]], i16 0, i16 [[TMP22]] +// UNSIGNED-NEXT: store i16 [[SATMIN1]], i16* @susa, align 2 susa++; // CHECK: [[TMP22:%.*]] = load i16, i16* @suf, align 2 // SIGNED-NEXT: [[TMP23:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[TMP22]], i16 -1) // SIGNED-NEXT: store i16 [[TMP23]], i16* @suf, align 2 -// UNSIGNED-NEXT: [[RESIZE4:%.*]] = trunc i16 [[TMP22]] to i15 -// UNSIGNED-NEXT: [[TMP23:%.*]] = call i15 @llvm.uadd.sat.i15(i15 [[RESIZE4]], i15 -1) -// UNSIGNED-NEXT: [[RESIZE5:%.*]] = zext i15 [[TMP23]] to i16 -// UNSIGNED-NEXT: store i16 [[RESIZE5]], i16* @suf, align 2 +// UNSIGNED-NEXT: [[TMP25:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[TMP22]], i16 32767) +// UNSIGNED-NEXT: [[TMP26:%.*]] = icmp slt i16 [[TMP25]], 0 +// UNSIGNED-NEXT: [[SATMIN2:%.*]] = select i1 [[TMP26]], i16 0, i16 [[TMP25]] +// UNSIGNED-NEXT: store i16 [[SATMIN2]], i16* @suf, align 2 suf++; } @@ -146,28 +146,28 @@ // CHECK: [[TMP18:%.*]] = load i32, i32* @sua, align 4 // SIGNED-NEXT: [[TMP19:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[TMP18]], i32 65536) // SIGNED-NEXT: store i32 [[TMP19]], i32* @sua, align 4 -// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP18]] to i31 -// UNSIGNED-NEXT: [[TMP19:%.*]] = call i31 @llvm.usub.sat.i31(i31 [[RESIZE]], i31 32768) -// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i31 [[TMP19]] to i32 -// UNSIGNED-NEXT: store i32 [[RESIZE1]], i32* @sua, align 4 +// UNSIGNED-NEXT: [[TMP19:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[TMP18]], i32 32768) +// UNSIGNED-NEXT: [[TMP20:%.*]] = icmp slt i32 [[TMP19]], 0 +// UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP20]], i32 0, i32 [[TMP19]] +// UNSIGNED-NEXT: store i32 [[SATMIN]], i32* @sua, align 4 sua--; // CHECK: [[TMP20:%.*]] = load i16, i16* @susa, align 2 // SIGNED-NEXT: [[TMP21:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP20]], i16 256) // SIGNED-NEXT: store i16 [[TMP21]], i16* @susa, align 2 -// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i16 [[TMP20]] to i15 -// UNSIGNED-NEXT: [[TMP21:%.*]] = call i15 @llvm.usub.sat.i15(i15 [[RESIZE2]], i15 128) -// UNSIGNED-NEXT: [[RESIZE3:%.*]] = zext i15 [[TMP21]] to i16 -// UNSIGNED-NEXT: store i16 [[RESIZE3]], i16* @susa, align 2 +// UNSIGNED-NEXT: [[TMP22:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP20]], i16 128) +// UNSIGNED-NEXT: [[TMP23:%.*]] = icmp slt i16 [[TMP22]], 0 +// UNSIGNED-NEXT: [[SATMIN1:%.*]] = select i1 [[TMP23]], i16 0, i16 [[TMP22]] +// UNSIGNED-NEXT: store i16 [[SATMIN1]], i16* @susa, align 2 susa--; // CHECK: [[TMP22:%.*]] = load i16, i16* @suf, align 2 // SIGNED-NEXT: [[TMP23:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP22]], i16 -1) // SIGNED-NEXT: store i16 [[TMP23]], i16* @suf, align 2 -// UNSIGNED-NEXT: [[RESIZE4:%.*]] = trunc i16 [[TMP22]] to i15 -// UNSIGNED-NEXT: [[TMP23:%.*]] = call i15 @llvm.usub.sat.i15(i15 [[RESIZE4]], i15 -1) -// UNSIGNED-NEXT: [[RESIZE5:%.*]] = zext i15 [[TMP23]] to i16 -// UNSIGNED-NEXT: store i16 [[RESIZE5]], i16* @suf, align 2 +// UNSIGNED-NEXT: [[TMP25:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP22]], i16 32767) +// UNSIGNED-NEXT: [[TMP26:%.*]] = icmp slt i16 [[TMP25]], 0 +// UNSIGNED-NEXT: [[SATMIN2:%.*]] = select i1 [[TMP26]], i16 0, i16 [[TMP25]] +// UNSIGNED-NEXT: store i16 [[SATMIN2]], i16* @suf, align 2 suf--; } @@ -206,19 +206,19 @@ // CHECK: [[TMP12:%.*]] = load i16, i16* @susa, align 2 // SIGNED-NEXT: [[TMP13:%.*]] = call i16 @llvm.usub.sat.i16(i16 0, i16 [[TMP12]]) // SIGNED-NEXT: store i16 [[TMP13]], i16* @susa, align 2 -// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP12]] to i15 -// UNSIGNED-NEXT: [[TMP13:%.*]] = call i15 @llvm.usub.sat.i15(i15 0, i15 [[RESIZE]]) -// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i15 [[TMP13]] to i16 -// UNSIGNED-NEXT: store i16 [[RESIZE1]], i16* @susa, align 2 +// UNSIGNED-NEXT: [[TMP13:%.*]] = call i16 @llvm.ssub.sat.i16(i16 0, i16 [[TMP12]]) +// UNSIGNED-NEXT: [[TMP14:%.*]] = icmp slt i16 [[TMP13]], 0 +// UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP14]], i16 0, i16 [[TMP13]] +// UNSIGNED-NEXT: store i16 [[SATMIN]], i16* @susa, align 2 susa = -susa; // CHECK: [[TMP14:%.*]] = load i16, i16* @suf, align 2 // SIGNED-NEXT: [[TMP15:%.*]] = call i16 @llvm.usub.sat.i16(i16 0, i16 [[TMP14]]) // SIGNED-NEXT: store i16 [[TMP15]], i16* @suf, align 2 -// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i16 [[TMP14]] to i15 -// UNSIGNED-NEXT: [[TMP15:%.*]] = call i15 @llvm.usub.sat.i15(i15 0, i15 [[RESIZE2]]) -// UNSIGNED-NEXT: [[RESIZE3:%.*]] = zext i15 [[TMP15]] to i16 -// UNSIGNED-NEXT: store i16 [[RESIZE3]], i16* @suf, align 2 +// UNSIGNED-NEXT: [[TMP16:%.*]] = call i16 @llvm.ssub.sat.i16(i16 0, i16 [[TMP14]]) +// UNSIGNED-NEXT: [[TMP17:%.*]] = icmp slt i16 [[TMP16]], 0 +// UNSIGNED-NEXT: [[SATMIN1:%.*]] = select i1 [[TMP17]], i16 0, i16 [[TMP16]] +// UNSIGNED-NEXT: store i16 [[SATMIN1]], i16* @suf, align 2 suf = -suf; }