[clang] 1bd6716 - [Clang][CodeGen] Do not promote if complex divisor is real (#131451)

via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 18 23:26:57 PDT 2025


Author: Mészáros Gergely
Date: 2025-03-19T07:26:54+01:00
New Revision: 1bd6716d33e3a4f523058e358a4e84135f64dcf9

URL: https://github.com/llvm/llvm-project/commit/1bd6716d33e3a4f523058e358a4e84135f64dcf9
DIFF: https://github.com/llvm/llvm-project/commit/1bd6716d33e3a4f523058e358a4e84135f64dcf9.diff

LOG: [Clang][CodeGen] Do not promote if complex divisor is real (#131451)

Relates-to: https://github.com/llvm/llvm-project/issues/131129

Added: 
    

Modified: 
    clang/lib/CodeGen/CGExprComplex.cpp
    clang/test/CodeGen/cx-complex-range-real.c

Removed: 
    


################################################################################
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]]
 //


        


More information about the cfe-commits mailing list