https://github.com/Maetveis updated https://github.com/llvm/llvm-project/pull/131451
From 631db26acc1e5476431e0b60b326c96829d7b824 Mon Sep 17 00:00:00 2001 From: Gergely Meszaros <meszaros.gergel...@gmail.com> Date: Sat, 15 Mar 2025 11:54:12 +0100 Subject: [PATCH] [Clang][CodeGen] Do not promote if complex divisor is real Relates-to: https://github.com/llvm/llvm-project/issues/131129 --- clang/lib/CodeGen/CGExprComplex.cpp | 36 ++++++++------- clang/test/CodeGen/cx-complex-range-real.c | 52 +++++++--------------- 2 files changed, 36 insertions(+), 52 deletions(-) diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index ff7c55be246cc..34f40feac7958 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -286,8 +286,7 @@ class ComplexExprEmitter ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName, const BinOpInfo &Op); - QualType HigherPrecisionTypeForComplexArithmetic(QualType ElementType, - bool IsDivOpCode) { + QualType HigherPrecisionTypeForComplexArithmetic(QualType ElementType) { ASTContext &Ctx = CGF.getContext(); const QualType HigherElementType = Ctx.GetHigherPrecisionFPType(ElementType); @@ -314,7 +313,7 @@ class ComplexExprEmitter } QualType getPromotionType(FPOptionsOverride Features, QualType Ty, - bool IsDivOpCode = false) { + bool IsComplexDivisor) { if (auto *CT = Ty->getAs<ComplexType>()) { QualType ElementType = CT->getElementType(); bool IsFloatingType = ElementType->isFloatingType(); @@ -325,10 +324,9 @@ class ComplexExprEmitter Features.getComplexRangeOverride() == CGF.getLangOpts().getComplexRange(); - if (IsDivOpCode && IsFloatingType && IsComplexRangePromoted && + if (IsComplexDivisor && IsFloatingType && IsComplexRangePromoted && (HasNoComplexRangeOverride || HasMatchingComplexRange)) - return HigherPrecisionTypeForComplexArithmetic(ElementType, - IsDivOpCode); + return HigherPrecisionTypeForComplexArithmetic(ElementType); if (ElementType.UseExcessPrecision(CGF.getContext())) return CGF.getContext().getComplexType(CGF.getContext().FloatTy); } @@ -339,9 +337,10 @@ class ComplexExprEmitter #define HANDLEBINOP(OP) \ ComplexPairTy VisitBin##OP(const BinaryOperator *E) { \ - QualType promotionTy = getPromotionType( \ - E->getStoredFPFeaturesOrDefault(), E->getType(), \ - (E->getOpcode() == BinaryOperatorKind::BO_Div) ? true : false); \ + QualType promotionTy = \ + getPromotionType(E->getStoredFPFeaturesOrDefault(), E->getType(), \ + (E->getOpcode() == BinaryOperatorKind::BO_Div && \ + E->getRHS()->getType()->isAnyComplexType())); \ ComplexPairTy result = EmitBin##OP(EmitBinOps(E, promotionTy)); \ if (!promotionTy.isNull()) \ result = CGF.EmitUnPromotedValue(result, E->getType()); \ @@ -639,7 +638,8 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *E, QualType promotionTy = PromotionType.isNull() ? getPromotionType(E->getStoredFPFeaturesOrDefault(), - E->getSubExpr()->getType()) + E->getSubExpr()->getType(), + /*IsComplexDivisor=*/false) : PromotionType; ComplexPairTy result = VisitPlus(E, promotionTy); if (!promotionTy.isNull()) @@ -661,7 +661,8 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E, QualType promotionTy = PromotionType.isNull() ? getPromotionType(E->getStoredFPFeaturesOrDefault(), - E->getSubExpr()->getType()) + E->getSubExpr()->getType(), + /*IsComplexDivisor=*/false) : PromotionType; ComplexPairTy result = VisitMinus(E, promotionTy); if (!promotionTy.isNull()) @@ -1218,14 +1219,16 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E, // improve codegen a little. QualType PromotionTypeCR; PromotionTypeCR = getPromotionType(E->getStoredFPFeaturesOrDefault(), - E->getComputationResultType()); + E->getComputationResultType(), + /*IsComplexDivisor=*/false); if (PromotionTypeCR.isNull()) PromotionTypeCR = E->getComputationResultType(); OpInfo.Ty = PromotionTypeCR; QualType ComplexElementTy = OpInfo.Ty->castAs<ComplexType>()->getElementType(); - QualType PromotionTypeRHS = getPromotionType( - E->getStoredFPFeaturesOrDefault(), E->getRHS()->getType()); + QualType PromotionTypeRHS = + getPromotionType(E->getStoredFPFeaturesOrDefault(), + E->getRHS()->getType(), /*IsComplexDivisor=*/false); // The RHS should have been converted to the computation type. if (E->getRHS()->getType()->isRealFloatingType()) { @@ -1253,8 +1256,9 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E, // Load from the l-value and convert it. SourceLocation Loc = E->getExprLoc(); - QualType PromotionTypeLHS = getPromotionType( - E->getStoredFPFeaturesOrDefault(), E->getComputationLHSType()); + QualType PromotionTypeLHS = + getPromotionType(E->getStoredFPFeaturesOrDefault(), + E->getComputationLHSType(), /*IsComplexDivisor=*/false); if (LHSTy->isAnyComplexType()) { ComplexPairTy LHSVal = EmitLoadOfLValue(LHS, Loc); if (!PromotionTypeLHS.isNull()) diff --git a/clang/test/CodeGen/cx-complex-range-real.c b/clang/test/CodeGen/cx-complex-range-real.c index 62dbfcdc6fa53..90c37e8669b08 100644 --- a/clang/test/CodeGen/cx-complex-range-real.c +++ b/clang/test/CodeGen/cx-complex-range-real.c @@ -340,18 +340,13 @@ _Complex float mulbf(float a, _Complex float b) { // PRMTD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 // PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 // PRMTD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 -// PRMTD-NEXT: [[EXT:%.*]] = fpext float [[A_REAL]] to double -// PRMTD-NEXT: [[EXT1:%.*]] = fpext float [[A_IMAG]] to double // PRMTD-NEXT: [[TMP0:%.*]] = load float, ptr [[B_ADDR]], align 4 -// PRMTD-NEXT: [[EXT2:%.*]] = fpext float [[TMP0]] to double -// PRMTD-NEXT: [[TMP1:%.*]] = fdiv double [[EXT]], [[EXT2]] -// PRMTD-NEXT: [[TMP2:%.*]] = fdiv double [[EXT1]], [[EXT2]] -// PRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP1]] to float -// PRMTD-NEXT: [[UNPROMOTION3:%.*]] = fptrunc double [[TMP2]] to float +// PRMTD-NEXT: [[TMP1:%.*]] = fdiv float [[A_REAL]], [[TMP0]] +// PRMTD-NEXT: [[TMP2:%.*]] = fdiv float [[A_IMAG]], [[TMP0]] // PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0 // PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 1 -// PRMTD-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4 -// PRMTD-NEXT: store float [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 4 +// PRMTD-NEXT: store float [[TMP1]], ptr [[RETVAL_REALP]], align 4 +// PRMTD-NEXT: store float [[TMP2]], ptr [[RETVAL_IMAGP]], align 4 // PRMTD-NEXT: [[TMP3:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 // PRMTD-NEXT: ret <2 x float> [[TMP3]] // @@ -367,18 +362,13 @@ _Complex float mulbf(float a, _Complex float b) { // PRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 // PRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 // PRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 -// PRMTD_STRICT-NEXT: [[EXT:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[A_REAL]], metadata !"fpexcept.strict") #[[ATTR3]] -// PRMTD_STRICT-NEXT: [[EXT1:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[A_IMAG]], metadata !"fpexcept.strict") #[[ATTR3]] // PRMTD_STRICT-NEXT: [[TMP0:%.*]] = load float, ptr [[B_ADDR]], align 4 -// PRMTD_STRICT-NEXT: [[EXT2:%.*]] = call double @llvm.experimental.constrained.fpext.f64.f32(float [[TMP0]], metadata !"fpexcept.strict") #[[ATTR3]] -// PRMTD_STRICT-NEXT: [[TMP1:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[EXT]], double [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] -// PRMTD_STRICT-NEXT: [[TMP2:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[EXT1]], double [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] -// PRMTD_STRICT-NEXT: [[UNPROMOTION:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP1]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] -// PRMTD_STRICT-NEXT: [[UNPROMOTION3:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] +// PRMTD_STRICT-NEXT: [[TMP1:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[A_REAL]], float [[TMP0]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] +// PRMTD_STRICT-NEXT: [[TMP2:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[A_IMAG]], float [[TMP0]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] // PRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0 // PRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[RETVAL]], i32 0, i32 1 -// PRMTD_STRICT-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4 -// PRMTD_STRICT-NEXT: store float [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 4 +// PRMTD_STRICT-NEXT: store float [[TMP1]], ptr [[RETVAL_REALP]], align 4 +// PRMTD_STRICT-NEXT: store float [[TMP2]], ptr [[RETVAL_IMAGP]], align 4 // PRMTD_STRICT-NEXT: [[TMP3:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 // PRMTD_STRICT-NEXT: ret <2 x float> [[TMP3]] // @@ -539,18 +529,13 @@ void divassignf(_Complex float *a, float b) { // PRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 // PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 1 // PRMTD-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 -// PRMTD-NEXT: [[EXT:%.*]] = fpext double [[A_REAL]] to x86_fp80 -// PRMTD-NEXT: [[EXT1:%.*]] = fpext double [[A_IMAG]] to x86_fp80 // PRMTD-NEXT: [[TMP2:%.*]] = load double, ptr [[B_ADDR]], align 8 -// PRMTD-NEXT: [[EXT2:%.*]] = fpext double [[TMP2]] to x86_fp80 -// PRMTD-NEXT: [[TMP3:%.*]] = fdiv x86_fp80 [[EXT]], [[EXT2]] -// PRMTD-NEXT: [[TMP4:%.*]] = fdiv x86_fp80 [[EXT1]], [[EXT2]] -// PRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc x86_fp80 [[TMP3]] to double -// PRMTD-NEXT: [[UNPROMOTION3:%.*]] = fptrunc x86_fp80 [[TMP4]] to double +// PRMTD-NEXT: [[TMP3:%.*]] = fdiv double [[A_REAL]], [[TMP2]] +// PRMTD-NEXT: [[TMP4:%.*]] = fdiv double [[A_IMAG]], [[TMP2]] // PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0 // PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 1 -// PRMTD-NEXT: store double [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 8 -// PRMTD-NEXT: store double [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 8 +// PRMTD-NEXT: store double [[TMP3]], ptr [[RETVAL_REALP]], align 8 +// PRMTD-NEXT: store double [[TMP4]], ptr [[RETVAL_IMAGP]], align 8 // PRMTD-NEXT: [[TMP5:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 // PRMTD-NEXT: ret { double, double } [[TMP5]] // @@ -569,18 +554,13 @@ void divassignf(_Complex float *a, float b) { // PRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 // PRMTD_STRICT-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 1 // PRMTD_STRICT-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 -// PRMTD_STRICT-NEXT: [[EXT:%.*]] = call x86_fp80 @llvm.experimental.constrained.fpext.f80.f64(double [[A_REAL]], metadata !"fpexcept.strict") #[[ATTR3]] -// PRMTD_STRICT-NEXT: [[EXT1:%.*]] = call x86_fp80 @llvm.experimental.constrained.fpext.f80.f64(double [[A_IMAG]], metadata !"fpexcept.strict") #[[ATTR3]] // PRMTD_STRICT-NEXT: [[TMP2:%.*]] = load double, ptr [[B_ADDR]], align 8 -// PRMTD_STRICT-NEXT: [[EXT2:%.*]] = call x86_fp80 @llvm.experimental.constrained.fpext.f80.f64(double [[TMP2]], metadata !"fpexcept.strict") #[[ATTR3]] -// PRMTD_STRICT-NEXT: [[TMP3:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[EXT]], x86_fp80 [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] -// PRMTD_STRICT-NEXT: [[TMP4:%.*]] = call x86_fp80 @llvm.experimental.constrained.fdiv.f80(x86_fp80 [[EXT1]], x86_fp80 [[EXT2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] -// PRMTD_STRICT-NEXT: [[UNPROMOTION:%.*]] = call double @llvm.experimental.constrained.fptrunc.f64.f80(x86_fp80 [[TMP3]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] -// PRMTD_STRICT-NEXT: [[UNPROMOTION3:%.*]] = call double @llvm.experimental.constrained.fptrunc.f64.f80(x86_fp80 [[TMP4]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] +// PRMTD_STRICT-NEXT: [[TMP3:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A_REAL]], double [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] +// PRMTD_STRICT-NEXT: [[TMP4:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A_IMAG]], double [[TMP2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR3]] // PRMTD_STRICT-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0 // PRMTD_STRICT-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 1 -// PRMTD_STRICT-NEXT: store double [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 8 -// PRMTD_STRICT-NEXT: store double [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 8 +// PRMTD_STRICT-NEXT: store double [[TMP3]], ptr [[RETVAL_REALP]], align 8 +// PRMTD_STRICT-NEXT: store double [[TMP4]], ptr [[RETVAL_IMAGP]], align 8 // PRMTD_STRICT-NEXT: [[TMP5:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 // PRMTD_STRICT-NEXT: ret { double, double } [[TMP5]] // _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits