Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Clang][CodeGen] Promote in complex compound divassign #131453

Merged
merged 1 commit into from
Mar 19, 2025

Conversation

Maetveis
Copy link
Contributor

When -fcomplex-arithmetic=promoted is set complex divassign /= should
promote to a wider type the same way division (without assignment) does.
Prior to this change, Smith's algorithm would be used for divassign.

Fixes: #131129

@Maetveis Maetveis marked this pull request as ready for review March 15, 2025 12:14
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. labels Mar 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 15, 2025

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Mészáros Gergely (Maetveis)

Changes

When -fcomplex-arithmetic=promoted is set complex divassign /= should
promote to a wider type the same way division (without assignment) does.
Prior to this change, Smith's algorithm would be used for divassign.

Fixes: #131129


Patch is 78.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131453.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/CGExprComplex.cpp (+12-6)
  • (modified) clang/test/CodeGen/cx-complex-range.c (+213-321)
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index a8a65a2f956f8..dc1a34ee82805 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -1212,19 +1212,24 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
   OpInfo.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
   CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, OpInfo.FPFeatures);
 
+  const bool IsComplexDivisor = E->getOpcode() == BO_DivAssign &&
+                                E->getRHS()->getType()->isAnyComplexType();
+
   // Load the RHS and LHS operands.
   // __block variables need to have the rhs evaluated first, plus this should
   // improve codegen a little.
   QualType PromotionTypeCR;
-  PromotionTypeCR = getPromotionType(E->getStoredFPFeaturesOrDefault(),
-                                     E->getComputationResultType());
+  PromotionTypeCR =
+      getPromotionType(E->getStoredFPFeaturesOrDefault(),
+                       E->getComputationResultType(), IsComplexDivisor);
   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);
 
   // The RHS should have been converted to the computation type.
   if (E->getRHS()->getType()->isRealFloatingType()) {
@@ -1252,8 +1257,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);
   if (LHSTy->isAnyComplexType()) {
     ComplexPairTy LHSVal = EmitLoadOfLValue(LHS, Loc);
     if (!PromotionTypeLHS.isNull())
diff --git a/clang/test/CodeGen/cx-complex-range.c b/clang/test/CodeGen/cx-complex-range.c
index 06a349fbc2a47..a724e1ca8cb6d 100644
--- a/clang/test/CodeGen/cx-complex-range.c
+++ b/clang/test/CodeGen/cx-complex-range.c
@@ -721,44 +721,32 @@ _Complex float divf(_Complex float a, _Complex float b) {
 // PRMTD-NEXT:    [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4
 // PRMTD-NEXT:    [[B_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 1
 // PRMTD-NEXT:    [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4
+// PRMTD-NEXT:    [[EXT:%.*]] = fpext float [[B_REAL]] to double
+// PRMTD-NEXT:    [[EXT1:%.*]] = fpext float [[B_IMAG]] to double
 // PRMTD-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8
 // PRMTD-NEXT:    [[DOTREALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 0
 // PRMTD-NEXT:    [[DOTREAL:%.*]] = load float, ptr [[DOTREALP]], align 4
 // PRMTD-NEXT:    [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 1
 // PRMTD-NEXT:    [[DOTIMAG:%.*]] = load float, ptr [[DOTIMAGP]], align 4
-// PRMTD-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[B_REAL]])
-// PRMTD-NEXT:    [[TMP2:%.*]] = call float @llvm.fabs.f32(float [[B_IMAG]])
-// PRMTD-NEXT:    [[ABS_CMP:%.*]] = fcmp ugt float [[TMP1]], [[TMP2]]
-// PRMTD-NEXT:    br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]]
-// PRMTD:       abs_rhsr_greater_or_equal_abs_rhsi:
-// PRMTD-NEXT:    [[TMP3:%.*]] = fdiv float [[B_IMAG]], [[B_REAL]]
-// PRMTD-NEXT:    [[TMP4:%.*]] = fmul float [[TMP3]], [[B_IMAG]]
-// PRMTD-NEXT:    [[TMP5:%.*]] = fadd float [[B_REAL]], [[TMP4]]
-// PRMTD-NEXT:    [[TMP6:%.*]] = fmul float [[DOTIMAG]], [[TMP3]]
-// PRMTD-NEXT:    [[TMP7:%.*]] = fadd float [[DOTREAL]], [[TMP6]]
-// PRMTD-NEXT:    [[TMP8:%.*]] = fdiv float [[TMP7]], [[TMP5]]
-// PRMTD-NEXT:    [[TMP9:%.*]] = fmul float [[DOTREAL]], [[TMP3]]
-// PRMTD-NEXT:    [[TMP10:%.*]] = fsub float [[DOTIMAG]], [[TMP9]]
-// PRMTD-NEXT:    [[TMP11:%.*]] = fdiv float [[TMP10]], [[TMP5]]
-// PRMTD-NEXT:    br label [[COMPLEX_DIV:%.*]]
-// PRMTD:       abs_rhsr_less_than_abs_rhsi:
-// PRMTD-NEXT:    [[TMP12:%.*]] = fdiv float [[B_REAL]], [[B_IMAG]]
-// PRMTD-NEXT:    [[TMP13:%.*]] = fmul float [[TMP12]], [[B_REAL]]
-// PRMTD-NEXT:    [[TMP14:%.*]] = fadd float [[B_IMAG]], [[TMP13]]
-// PRMTD-NEXT:    [[TMP15:%.*]] = fmul float [[DOTREAL]], [[TMP12]]
-// PRMTD-NEXT:    [[TMP16:%.*]] = fadd float [[TMP15]], [[DOTIMAG]]
-// PRMTD-NEXT:    [[TMP17:%.*]] = fdiv float [[TMP16]], [[TMP14]]
-// PRMTD-NEXT:    [[TMP18:%.*]] = fmul float [[DOTIMAG]], [[TMP12]]
-// PRMTD-NEXT:    [[TMP19:%.*]] = fsub float [[TMP18]], [[DOTREAL]]
-// PRMTD-NEXT:    [[TMP20:%.*]] = fdiv float [[TMP19]], [[TMP14]]
-// PRMTD-NEXT:    br label [[COMPLEX_DIV]]
-// PRMTD:       complex_div:
-// PRMTD-NEXT:    [[TMP21:%.*]] = phi float [ [[TMP8]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP17]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
-// PRMTD-NEXT:    [[TMP22:%.*]] = phi float [ [[TMP11]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP20]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
-// PRMTD-NEXT:    [[DOTREALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 0
-// PRMTD-NEXT:    [[DOTIMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 1
-// PRMTD-NEXT:    store float [[TMP21]], ptr [[DOTREALP1]], align 4
-// PRMTD-NEXT:    store float [[TMP22]], ptr [[DOTIMAGP2]], align 4
+// PRMTD-NEXT:    [[CONV:%.*]] = fpext float [[DOTREAL]] to double
+// PRMTD-NEXT:    [[CONV2:%.*]] = fpext float [[DOTIMAG]] to double
+// PRMTD-NEXT:    [[TMP1:%.*]] = fmul double [[CONV]], [[EXT]]
+// PRMTD-NEXT:    [[TMP2:%.*]] = fmul double [[CONV2]], [[EXT1]]
+// PRMTD-NEXT:    [[TMP3:%.*]] = fadd double [[TMP1]], [[TMP2]]
+// PRMTD-NEXT:    [[TMP4:%.*]] = fmul double [[EXT]], [[EXT]]
+// PRMTD-NEXT:    [[TMP5:%.*]] = fmul double [[EXT1]], [[EXT1]]
+// PRMTD-NEXT:    [[TMP6:%.*]] = fadd double [[TMP4]], [[TMP5]]
+// PRMTD-NEXT:    [[TMP7:%.*]] = fmul double [[CONV2]], [[EXT]]
+// PRMTD-NEXT:    [[TMP8:%.*]] = fmul double [[CONV]], [[EXT1]]
+// PRMTD-NEXT:    [[TMP9:%.*]] = fsub double [[TMP7]], [[TMP8]]
+// PRMTD-NEXT:    [[TMP10:%.*]] = fdiv double [[TMP3]], [[TMP6]]
+// PRMTD-NEXT:    [[TMP11:%.*]] = fdiv double [[TMP9]], [[TMP6]]
+// PRMTD-NEXT:    [[CONV3:%.*]] = fptrunc double [[TMP10]] to float
+// PRMTD-NEXT:    [[CONV4:%.*]] = fptrunc double [[TMP11]] to float
+// PRMTD-NEXT:    [[DOTREALP5:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 0
+// PRMTD-NEXT:    [[DOTIMAGP6:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 1
+// PRMTD-NEXT:    store float [[CONV3]], ptr [[DOTREALP5]], align 4
+// PRMTD-NEXT:    store float [[CONV4]], ptr [[DOTIMAGP6]], align 4
 // PRMTD-NEXT:    ret void
 //
 // X86WINPRMTD-LABEL: define dso_local void @divassignf(
@@ -772,44 +760,32 @@ _Complex float divf(_Complex float a, _Complex float b) {
 // X86WINPRMTD-NEXT:    [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4
 // X86WINPRMTD-NEXT:    [[B_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 1
 // X86WINPRMTD-NEXT:    [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4
+// X86WINPRMTD-NEXT:    [[EXT:%.*]] = fpext float [[B_REAL]] to double
+// X86WINPRMTD-NEXT:    [[EXT1:%.*]] = fpext float [[B_IMAG]] to double
 // X86WINPRMTD-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8
 // X86WINPRMTD-NEXT:    [[DOTREALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 0
 // X86WINPRMTD-NEXT:    [[DOTREAL:%.*]] = load float, ptr [[DOTREALP]], align 4
 // X86WINPRMTD-NEXT:    [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 1
 // X86WINPRMTD-NEXT:    [[DOTIMAG:%.*]] = load float, ptr [[DOTIMAGP]], align 4
-// X86WINPRMTD-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[B_REAL]])
-// X86WINPRMTD-NEXT:    [[TMP2:%.*]] = call float @llvm.fabs.f32(float [[B_IMAG]])
-// X86WINPRMTD-NEXT:    [[ABS_CMP:%.*]] = fcmp ugt float [[TMP1]], [[TMP2]]
-// X86WINPRMTD-NEXT:    br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]]
-// X86WINPRMTD:       abs_rhsr_greater_or_equal_abs_rhsi:
-// X86WINPRMTD-NEXT:    [[TMP3:%.*]] = fdiv float [[B_IMAG]], [[B_REAL]]
-// X86WINPRMTD-NEXT:    [[TMP4:%.*]] = fmul float [[TMP3]], [[B_IMAG]]
-// X86WINPRMTD-NEXT:    [[TMP5:%.*]] = fadd float [[B_REAL]], [[TMP4]]
-// X86WINPRMTD-NEXT:    [[TMP6:%.*]] = fmul float [[DOTIMAG]], [[TMP3]]
-// X86WINPRMTD-NEXT:    [[TMP7:%.*]] = fadd float [[DOTREAL]], [[TMP6]]
-// X86WINPRMTD-NEXT:    [[TMP8:%.*]] = fdiv float [[TMP7]], [[TMP5]]
-// X86WINPRMTD-NEXT:    [[TMP9:%.*]] = fmul float [[DOTREAL]], [[TMP3]]
-// X86WINPRMTD-NEXT:    [[TMP10:%.*]] = fsub float [[DOTIMAG]], [[TMP9]]
-// X86WINPRMTD-NEXT:    [[TMP11:%.*]] = fdiv float [[TMP10]], [[TMP5]]
-// X86WINPRMTD-NEXT:    br label [[COMPLEX_DIV:%.*]]
-// X86WINPRMTD:       abs_rhsr_less_than_abs_rhsi:
-// X86WINPRMTD-NEXT:    [[TMP12:%.*]] = fdiv float [[B_REAL]], [[B_IMAG]]
-// X86WINPRMTD-NEXT:    [[TMP13:%.*]] = fmul float [[TMP12]], [[B_REAL]]
-// X86WINPRMTD-NEXT:    [[TMP14:%.*]] = fadd float [[B_IMAG]], [[TMP13]]
-// X86WINPRMTD-NEXT:    [[TMP15:%.*]] = fmul float [[DOTREAL]], [[TMP12]]
-// X86WINPRMTD-NEXT:    [[TMP16:%.*]] = fadd float [[TMP15]], [[DOTIMAG]]
-// X86WINPRMTD-NEXT:    [[TMP17:%.*]] = fdiv float [[TMP16]], [[TMP14]]
-// X86WINPRMTD-NEXT:    [[TMP18:%.*]] = fmul float [[DOTIMAG]], [[TMP12]]
-// X86WINPRMTD-NEXT:    [[TMP19:%.*]] = fsub float [[TMP18]], [[DOTREAL]]
-// X86WINPRMTD-NEXT:    [[TMP20:%.*]] = fdiv float [[TMP19]], [[TMP14]]
-// X86WINPRMTD-NEXT:    br label [[COMPLEX_DIV]]
-// X86WINPRMTD:       complex_div:
-// X86WINPRMTD-NEXT:    [[TMP21:%.*]] = phi float [ [[TMP8]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP17]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
-// X86WINPRMTD-NEXT:    [[TMP22:%.*]] = phi float [ [[TMP11]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP20]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
-// X86WINPRMTD-NEXT:    [[DOTREALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 0
-// X86WINPRMTD-NEXT:    [[DOTIMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 1
-// X86WINPRMTD-NEXT:    store float [[TMP21]], ptr [[DOTREALP1]], align 4
-// X86WINPRMTD-NEXT:    store float [[TMP22]], ptr [[DOTIMAGP2]], align 4
+// X86WINPRMTD-NEXT:    [[CONV:%.*]] = fpext float [[DOTREAL]] to double
+// X86WINPRMTD-NEXT:    [[CONV2:%.*]] = fpext float [[DOTIMAG]] to double
+// X86WINPRMTD-NEXT:    [[TMP1:%.*]] = fmul double [[CONV]], [[EXT]]
+// X86WINPRMTD-NEXT:    [[TMP2:%.*]] = fmul double [[CONV2]], [[EXT1]]
+// X86WINPRMTD-NEXT:    [[TMP3:%.*]] = fadd double [[TMP1]], [[TMP2]]
+// X86WINPRMTD-NEXT:    [[TMP4:%.*]] = fmul double [[EXT]], [[EXT]]
+// X86WINPRMTD-NEXT:    [[TMP5:%.*]] = fmul double [[EXT1]], [[EXT1]]
+// X86WINPRMTD-NEXT:    [[TMP6:%.*]] = fadd double [[TMP4]], [[TMP5]]
+// X86WINPRMTD-NEXT:    [[TMP7:%.*]] = fmul double [[CONV2]], [[EXT]]
+// X86WINPRMTD-NEXT:    [[TMP8:%.*]] = fmul double [[CONV]], [[EXT1]]
+// X86WINPRMTD-NEXT:    [[TMP9:%.*]] = fsub double [[TMP7]], [[TMP8]]
+// X86WINPRMTD-NEXT:    [[TMP10:%.*]] = fdiv double [[TMP3]], [[TMP6]]
+// X86WINPRMTD-NEXT:    [[TMP11:%.*]] = fdiv double [[TMP9]], [[TMP6]]
+// X86WINPRMTD-NEXT:    [[CONV3:%.*]] = fptrunc double [[TMP10]] to float
+// X86WINPRMTD-NEXT:    [[CONV4:%.*]] = fptrunc double [[TMP11]] to float
+// X86WINPRMTD-NEXT:    [[DOTREALP5:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 0
+// X86WINPRMTD-NEXT:    [[DOTIMAGP6:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 1
+// X86WINPRMTD-NEXT:    store float [[CONV3]], ptr [[DOTREALP5]], align 4
+// X86WINPRMTD-NEXT:    store float [[CONV4]], ptr [[DOTIMAGP6]], align 4
 // X86WINPRMTD-NEXT:    ret void
 //
 // AVRFP32-LABEL: define dso_local void @divassignf(
@@ -880,44 +856,32 @@ _Complex float divf(_Complex float a, _Complex float b) {
 // AVRFP64-NEXT:    [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 1
 // AVRFP64-NEXT:    [[B_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 1
 // AVRFP64-NEXT:    [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 1
+// AVRFP64-NEXT:    [[EXT:%.*]] = fpext float [[B_REAL]] to double
+// AVRFP64-NEXT:    [[EXT1:%.*]] = fpext float [[B_IMAG]] to double
 // AVRFP64-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 1
 // AVRFP64-NEXT:    [[DOTREALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP2]], i32 0, i32 0
 // AVRFP64-NEXT:    [[DOTREAL:%.*]] = load float, ptr [[DOTREALP]], align 1
 // AVRFP64-NEXT:    [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP2]], i32 0, i32 1
 // AVRFP64-NEXT:    [[DOTIMAG:%.*]] = load float, ptr [[DOTIMAGP]], align 1
-// AVRFP64-NEXT:    [[TMP3:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[B_REAL]])
-// AVRFP64-NEXT:    [[TMP4:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[B_IMAG]])
-// AVRFP64-NEXT:    [[ABS_CMP:%.*]] = fcmp ugt float [[TMP3]], [[TMP4]]
-// AVRFP64-NEXT:    br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]]
-// AVRFP64:       abs_rhsr_greater_or_equal_abs_rhsi:
-// AVRFP64-NEXT:    [[TMP5:%.*]] = fdiv float [[B_IMAG]], [[B_REAL]]
-// AVRFP64-NEXT:    [[TMP6:%.*]] = fmul float [[TMP5]], [[B_IMAG]]
-// AVRFP64-NEXT:    [[TMP7:%.*]] = fadd float [[B_REAL]], [[TMP6]]
-// AVRFP64-NEXT:    [[TMP8:%.*]] = fmul float [[DOTIMAG]], [[TMP5]]
-// AVRFP64-NEXT:    [[TMP9:%.*]] = fadd float [[DOTREAL]], [[TMP8]]
-// AVRFP64-NEXT:    [[TMP10:%.*]] = fdiv float [[TMP9]], [[TMP7]]
-// AVRFP64-NEXT:    [[TMP11:%.*]] = fmul float [[DOTREAL]], [[TMP5]]
-// AVRFP64-NEXT:    [[TMP12:%.*]] = fsub float [[DOTIMAG]], [[TMP11]]
-// AVRFP64-NEXT:    [[TMP13:%.*]] = fdiv float [[TMP12]], [[TMP7]]
-// AVRFP64-NEXT:    br label [[COMPLEX_DIV:%.*]]
-// AVRFP64:       abs_rhsr_less_than_abs_rhsi:
-// AVRFP64-NEXT:    [[TMP14:%.*]] = fdiv float [[B_REAL]], [[B_IMAG]]
-// AVRFP64-NEXT:    [[TMP15:%.*]] = fmul float [[TMP14]], [[B_REAL]]
-// AVRFP64-NEXT:    [[TMP16:%.*]] = fadd float [[B_IMAG]], [[TMP15]]
-// AVRFP64-NEXT:    [[TMP17:%.*]] = fmul float [[DOTREAL]], [[TMP14]]
-// AVRFP64-NEXT:    [[TMP18:%.*]] = fadd float [[TMP17]], [[DOTIMAG]]
-// AVRFP64-NEXT:    [[TMP19:%.*]] = fdiv float [[TMP18]], [[TMP16]]
-// AVRFP64-NEXT:    [[TMP20:%.*]] = fmul float [[DOTIMAG]], [[TMP14]]
-// AVRFP64-NEXT:    [[TMP21:%.*]] = fsub float [[TMP20]], [[DOTREAL]]
-// AVRFP64-NEXT:    [[TMP22:%.*]] = fdiv float [[TMP21]], [[TMP16]]
-// AVRFP64-NEXT:    br label [[COMPLEX_DIV]]
-// AVRFP64:       complex_div:
-// AVRFP64-NEXT:    [[TMP23:%.*]] = phi float [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
-// AVRFP64-NEXT:    [[TMP24:%.*]] = phi float [ [[TMP13]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP22]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ]
-// AVRFP64-NEXT:    [[DOTREALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP2]], i32 0, i32 0
-// AVRFP64-NEXT:    [[DOTIMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP2]], i32 0, i32 1
-// AVRFP64-NEXT:    store float [[TMP23]], ptr [[DOTREALP1]], align 1
-// AVRFP64-NEXT:    store float [[TMP24]], ptr [[DOTIMAGP2]], align 1
+// AVRFP64-NEXT:    [[CONV:%.*]] = fpext float [[DOTREAL]] to double
+// AVRFP64-NEXT:    [[CONV2:%.*]] = fpext float [[DOTIMAG]] to double
+// AVRFP64-NEXT:    [[TMP3:%.*]] = fmul double [[CONV]], [[EXT]]
+// AVRFP64-NEXT:    [[TMP4:%.*]] = fmul double [[CONV2]], [[EXT1]]
+// AVRFP64-NEXT:    [[TMP5:%.*]] = fadd double [[TMP3]], [[TMP4]]
+// AVRFP64-NEXT:    [[TMP6:%.*]] = fmul double [[EXT]], [[EXT]]
+// AVRFP64-NEXT:    [[TMP7:%.*]] = fmul double [[EXT1]], [[EXT1]]
+// AVRFP64-NEXT:    [[TMP8:%.*]] = fadd double [[TMP6]], [[TMP7]]
+// AVRFP64-NEXT:    [[TMP9:%.*]] = fmul double [[CONV2]], [[EXT]]
+// AVRFP64-NEXT:    [[TMP10:%.*]] = fmul double [[CONV]], [[EXT1]]
+// AVRFP64-NEXT:    [[TMP11:%.*]] = fsub double [[TMP9]], [[TMP10]]
+// AVRFP64-NEXT:    [[TMP12:%.*]] = fdiv double [[TMP5]], [[TMP8]]
+// AVRFP64-NEXT:    [[TMP13:%.*]] = fdiv double [[TMP11]], [[TMP8]]
+// AVRFP64-NEXT:    [[CONV3:%.*]] = fptrunc double [[TMP12]] to float
+// AVRFP64-NEXT:    [[CONV4:%.*]] = fptrunc double [[TMP13]] to float
+// AVRFP64-NEXT:    [[DOTREALP5:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP2]], i32 0, i32 0
+// AVRFP64-NEXT:    [[DOTIMAGP6:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP2]], i32 0, i32 1
+// AVRFP64-NEXT:    store float [[CONV3]], ptr [[DOTREALP5]], align 1
+// AVRFP64-NEXT:    store float [[CONV4]], ptr [[DOTIMAGP6]], align 1
 // AVRFP64-NEXT:    ret void
 //
 // BASIC_FAST-LABEL: define dso_local void @divassignf(
@@ -1044,44 +1008,32 @@ _Complex float divf(_Complex float a, _Complex float b) {
 // PRMTD_FAST-NEXT:    [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4
 // PRMTD_FAST-NEXT:    [[B_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 1
 // PRMTD_FAST-NEXT:    [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4
+// PRMTD_FAST-NEXT:    [[EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[B_REAL]] to double
+// PRMTD_FAST-NEXT:    [[EXT1:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[B_IMAG]] to double
 // PRMTD_FAST-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8
 // PRMTD_FAST-NEXT:    [[DOTREALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 0
 // PRMTD_FAST-NEXT:    [[DOTREAL:%.*]] = load float, ptr [[DOTREALP]], align 4
 // PRMTD_FAST-NEXT:    [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 1
 // PRMTD_FAST-NEXT:    [[DOTIMAG:%.*]] = load float, ptr [[DOTIMAGP]], align 4
-// PRMTD_FAST-NEXT:    [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[B_REAL]])
-// PRMTD_FAST-NEXT:    [[TMP2:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[B_IMAG]])
-// PRMTD_FAST-NEXT:    [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt float [[TMP1]], [[TMP2]]
-// PRMTD_FAST-NEXT:    br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]]
-// PRMTD_FAST:       abs_rhsr_greater_or_equal_abs_rhsi:
-// PRMTD_FAST-NEXT:    [[TMP3:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[B_IMAG]], [[B_REAL]]
-// PRMTD_FAST-NEXT:    [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP3]], [[B_IMAG]]
-// PRMTD_FAST-NEXT:    [[TMP5:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[B_REAL]], [[TMP4]]
-// PRMTD_FAST-NEXT:    [[TMP6:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[DOTIMAG]], [[TMP3]]
-// PRMTD_FAST-NEXT:    [[TMP7:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[DOTREAL]], [[TMP6]]
-// PRMTD_FAST-NEXT:    [[TMP8:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP7]], [[TMP5]]
-// PRMTD_FAST-NEXT:    [[TMP9:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[DOTREAL]], [[TMP3]]
-// PRMTD_FAST-NEXT:    [[TMP10:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[DOTIMAG]], [[TMP9]]
-// PRMTD_FAST-NEXT:    [[TMP11:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP10]], [[TMP5]]
-// PRMTD_FAST-NEXT:    br label [[COMPLEX_DIV:%.*]]
-// PRMTD_FAST:       abs_rhsr_less_than_abs_rhsi:
-// PRMTD_FAST-NEXT:    [[TMP12:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[B_REAL]], [[B_IMAG]]
-// PRMTD_FAST-NEXT:    [[TMP13:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP12]], [[B_REAL]]
-// PRMTD_FAST-NEXT:    [[TMP14:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[B_IMAG]], [[TMP13]]
-// PRMTD_FAST-NEXT:    [[TMP15:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[DOTREAL]], [[TMP12]]
-// PRMTD_FAST-NEXT:    [[TMP16:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP15]], [[DOTIMAG]]
-// PRMTD_FAST-NEXT:    [[TM...
[truncated]

@Maetveis Maetveis force-pushed the users/Maetveis/complex-promoted-fix-assign branch from de63899 to 9d50aa0 Compare March 18, 2025 20:10
@Maetveis Maetveis force-pushed the users/Maetveis/complex-promoted-fix-real branch 2 times, most recently from c6e05d7 to 549f55f Compare March 18, 2025 20:40
@Maetveis Maetveis force-pushed the users/Maetveis/complex-promoted-fix-assign branch from 9d50aa0 to f02c8a6 Compare March 18, 2025 20:40
Copy link
Collaborator

@efriedma-quic efriedma-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Maetveis Maetveis force-pushed the users/Maetveis/complex-promoted-fix-real branch from 549f55f to 631db26 Compare March 19, 2025 06:19
@Maetveis Maetveis force-pushed the users/Maetveis/complex-promoted-fix-assign branch from f02c8a6 to 57b488a Compare March 19, 2025 06:19
Copy link
Contributor Author

Maetveis commented Mar 19, 2025

Merge activity

  • Mar 19, 2:22 AM EDT: A user started a stack merge that includes this pull request via Graphite.
  • Mar 19, 2:27 AM EDT: Graphite rebased this pull request as part of a merge.
  • Mar 19, 2:29 AM EDT: A user merged this pull request with Graphite.

@Maetveis Maetveis force-pushed the users/Maetveis/complex-promoted-fix-real branch from 631db26 to 5767414 Compare March 19, 2025 06:23
Base automatically changed from users/Maetveis/complex-promoted-fix-real to main March 19, 2025 06:26
When `-fcomplex-arithmetic=promoted` is set complex divassign `/=` should
promote to a wider type the same way division (without assignment) does.
Prior to this change, Smith's algorithm would be used for divassign.

Fixes: #131129
@Maetveis Maetveis force-pushed the users/Maetveis/complex-promoted-fix-assign branch from 57b488a to f2a2bf5 Compare March 19, 2025 06:27
@Maetveis Maetveis merged commit f017073 into main Mar 19, 2025
6 of 10 checks passed
@Maetveis Maetveis deleted the users/Maetveis/complex-promoted-fix-assign branch March 19, 2025 06:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[clang] Inconsistent codegen when using -fcomplex-arithmetic=promoted
3 participants