Author: Amr Hesham
Date: 2026-06-04T10:21:50+02:00
New Revision: b6599484337145cd03cdc42b30de08939e3f6947

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

LOG: [CIR] Fix Complex Casting with Atomic qualifier (#201424)

Apply Complex Casting with Atomic qualifier fixes from PRs #172210 and
#172163

Issue https://github.com/llvm/llvm-project/issues/192331

Added: 
    

Modified: 
    clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
    clang/test/CIR/CodeGen/complex-atomic-cast.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index c576cb9159f36..2a747fac0c092 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -415,8 +415,12 @@ mlir::Value 
ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val,
     return val;
 
   // Get the src/dest element type.
-  QualType srcElemTy = srcType->castAs<ComplexType>()->getElementType();
-  QualType destElemTy = destType->castAs<ComplexType>()->getElementType();
+  QualType srcElemTy = srcType.getAtomicUnqualifiedType()
+                           ->castAs<ComplexType>()
+                           ->getElementType();
+  QualType destElemTy = destType.getAtomicUnqualifiedType()
+                            ->castAs<ComplexType>()
+                            ->getElementType();
 
   cir::CastKind castOpKind;
   if (srcElemTy->isFloatingType() && destElemTy->isFloatingType())
@@ -452,6 +456,7 @@ mlir::Value 
ComplexExprEmitter::emitScalarToComplexCast(mlir::Value val,
 
 mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
                                          QualType destTy) {
+  destTy = destTy.getAtomicUnqualifiedType();
   switch (ck) {
   case CK_Dependent:
     llvm_unreachable("dependent type must be resolved before the CIR codegen");
@@ -808,16 +813,16 @@ ComplexExprEmitter::emitBinOps(const BinaryOperator *e, 
QualType promotionTy) {
 LValue ComplexExprEmitter::emitCompoundAssignLValue(
     const CompoundAssignOperator *e,
     mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &), RValue &value) 
{
-  QualType lhsTy = e->getLHS()->getType();
-  QualType rhsTy = e->getRHS()->getType();
-  SourceLocation exprLoc = e->getExprLoc();
-  mlir::Location loc = cgf.getLoc(exprLoc);
-
-  if (lhsTy->getAs<AtomicType>()) {
+  if (e->getLHS()->getType()->getAs<AtomicType>()) {
     cgf.cgm.errorNYI("emitCompoundAssignLValue AtmoicType");
     return {};
   }
 
+  QualType lhsTy = e->getLHS()->getType().getAtomicUnqualifiedType();
+  QualType rhsTy = e->getRHS()->getType();
+  SourceLocation exprLoc = e->getExprLoc();
+  mlir::Location loc = cgf.getLoc(exprLoc);
+
   BinOpInfo opInfo{loc};
   opInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
 

diff  --git a/clang/test/CIR/CodeGen/complex-atomic-cast.c 
b/clang/test/CIR/CodeGen/complex-atomic-cast.c
index a15858fcf9711..1a459c63c64b0 100644
--- a/clang/test/CIR/CodeGen/complex-atomic-cast.c
+++ b/clang/test/CIR/CodeGen/complex-atomic-cast.c
@@ -67,3 +67,140 @@ void atomic_complex_to_complex() {
 // OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[B_ADDR]], i32 0, i32 1
 // OGCG: store i32 %[[ATOMIC_TMP_REAL]], ptr %[[B_REAL_PTR]], align 4
 // OGCG: store i32 %[[ATOMIC_TMP_IMAG]], ptr %[[B_IMAG_PTR]], align 4
+
+void explicit_cast_scalar_to_atomic_complex() {
+  _Atomic _Complex float a = (_Atomic _Complex float)2.0f;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a", init]
+// CIR: %[[CONST_2F:.*]] = cir.const #cir.fp<2.000000e+00> : !cir.float
+// CIR: %[[CONST_0F:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
+// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[CONST_2F]], %[[CONST_0F]] : 
!cir.float -> !cir.complex<!cir.float>
+// CIR: cir.store {{.*}} %[[COMPLEX]], %[[A_ADDR]] : !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 8
+// LLVM: store { float, float } { float 2.000000e+00, float 0.000000e+00 }, 
ptr %[[A_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 8
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[A_ADDR]], i32 0, i32 1
+// OGCG: store float 2.000000e+00, ptr %[[A_REAL_PTR]], align 8
+// OGCG: store float 0.000000e+00, ptr %[[A_IMAG_PTR]], align 4
+
+void explicit_cast_atomic_complex_to_complex() {
+  _Atomic _Complex float a = 2.0f;
+  _Complex int b = (_Complex int)a;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["b", init]
+// CIR: %[[ATOMIC_TMP_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["atomic-temp"]
+// CIR: %[[CONST_2F:.*]] = cir.const #cir.fp<2.000000e+00> : !cir.float
+// CIR: %[[CONST_0F:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
+// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[CONST_2F]], %[[CONST_0F]] : 
!cir.float -> !cir.complex<!cir.float>
+// CIR: cir.store {{.*}} %[[COMPLEX]], %[[A_ADDR]] : !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>
+// CIR: %[[A_U64I:.*]] = cir.cast bitcast %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>> -> !cir.ptr<!u64i>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} atomic(seq_cst) %[[A_U64I]] : 
!cir.ptr<!u64i>, !u64i
+// CIR: %[[ATOMIC_TMP_U64I:.*]] = cir.cast bitcast %[[ATOMIC_TMP_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>> -> !cir.ptr<!u64i>
+// CIR: cir.store {{.*}} %[[TMP_A]], %[[ATOMIC_TMP_U64I]] : !u64i, 
!cir.ptr<!u64i>
+// CIR: %[[TMP_ATOMIC:.*]] = cir.load {{.*}} %[[ATOMIC_TMP_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: %[[ATOMIC_TMP_REAL:.*]] = cir.complex.real %[[TMP_ATOMIC]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR: %[[ATOMIC_TMP_IMAG:.*]] = cir.complex.imag %[[TMP_ATOMIC]] : 
!cir.complex<!cir.float> -> !cir.floa
+// CIR: %[[ATOMIC_TMP_REAL_I32:.*]] = cir.cast float_to_int 
%[[ATOMIC_TMP_REAL]] : !cir.float -> !s32i
+// CIR: %[[ATOMIC_TMP_IMAG_I32:.*]] = cir.cast float_to_int 
%[[ATOMIC_TMP_IMAG]] : !cir.float -> !s32i
+// CIR: %[[RESULT:.*]] = cir.complex.create %[[ATOMIC_TMP_REAL_I32]], 
%[[ATOMIC_TMP_IMAG_I32]] : !s32i -> !cir.complex<!s32i>
+// CIR: cir.store {{.*}} %[[RESULT]], %[[B_ADDR]] : !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[ATOMIC_TMP_ADDR:.*]] = alloca { float, float }, i64 1, align 8
+// LLVM: store { float, float } { float 2.000000e+00, float 0.000000e+00 }, 
ptr %[[A_ADDR]], align 8
+// LLVM: %[[TMP_A:.*]] = load atomic i64, ptr %[[A_ADDR]] seq_cst, align 8
+// LLVM: store i64 %[[TMP_A]], ptr %[[ATOMIC_TMP_ADDR]], align 8
+// LLVM: %[[TMP_ATOMIC:.*]] = load { float, float }, ptr %[[ATOMIC_TMP_ADDR]], 
align 8
+// LLVM: %[[ATOMIC_TMP_REAL:.*]] = extractvalue { float, float } 
%[[TMP_ATOMIC]], 0
+// LLVM: %[[ATOMIC_TMP_IMAG:.*]] = extractvalue { float, float } 
%[[TMP_ATOMIC]], 1
+// LLVM: %[[ATOMIC_TMP_REAL_I32:.*]] = fptosi float %[[ATOMIC_TMP_REAL]] to i32
+// LLVM: %[[ATOMIC_TMP_IMAG_I32:.*]] = fptosi float %[[ATOMIC_TMP_IMAG]] to i32
+// LLVM: %[[TMP_RESULT:.*]] = insertvalue { i32, i32 } {{.*}}, i32 
%[[ATOMIC_TMP_REAL_I32]], 0
+// LLVM: %[[RESULT:.*]] = insertvalue { i32, i32 } %[[TMP_RESULT]], i32 
%[[ATOMIC_TMP_IMAG_I32]], 1
+// LLVM: store { i32, i32 } %[[RESULT]], ptr %[[B_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[ATOMIC_TMP_ADDR:.*]] = alloca { float, float }, align 8
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[A_ADDR]], i32 0, i32 1
+// OGCG: store float 2.000000e+00, ptr %[[A_REAL_PTR]], align 8
+// OGCG: store float 0.000000e+00, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[TMP_A:.*]] = load atomic i64, ptr %[[A_ADDR]] seq_cst, align 8
+// OGCG: store i64 %[[TMP_A]], ptr %[[ATOMIC_TMP_ADDR]], align 8
+// OGCG: %[[ATOMIC_TMP_REAL_PTR:.*]] = getelementptr inbounds nuw { float, 
float }, ptr %[[ATOMIC_TMP_ADDR]], i32 0, i32 0
+// OGCG: %[[ATOMIC_TMP_REAL:.*]] = load float, ptr %[[ATOMIC_TMP_REAL_PTR]], 
align 8
+// OGCG: %[[ATOMIC_TMP_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, 
float }, ptr %[[ATOMIC_TMP_ADDR]], i32 0, i32 1
+// OGCG: %[[ATOMIC_TMP_IMAG:.*]] = load float, ptr %[[ATOMIC_TMP_IMAG_PTR]], 
align 4
+// OGCG: %[[RESULT_REAL:.*]] = fptosi float %[[ATOMIC_TMP_REAL]] to i32
+// OGCG: %[[RESULT_IMAG:.*]] = fptosi float %[[ATOMIC_TMP_IMAG]] to i32
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[B_ADDR]], i32 0, i32 0
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[B_ADDR]], i32 0, i32 1
+// OGCG: store i32 %[[RESULT_REAL]], ptr %[[B_REAL_PTR]], align 4
+// OGCG: store i32 %[[RESULT_IMAG]], ptr %[[B_IMAG_PTR]], align 4
+
+void explicit_cast_atomic_complex_to_atomic_complex() {
+  _Atomic _Complex float a = 2.0f;
+  _Atomic _Complex int b = (_Atomic _Complex int)a;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["b", init]
+// CIR: %[[ATOMIC_TMP_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["atomic-temp"]
+// CIR: %[[CONST_2F:.*]] = cir.const #cir.fp<2.000000e+00> : !cir.float
+// CIR: %[[CONST_0F:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
+// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[CONST_2F]], %[[CONST_0F]] : 
!cir.float -> !cir.complex<!cir.float>
+// CIR: cir.store {{.*}} %[[COMPLEX]], %[[A_ADDR]] : !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>
+// CIR: %[[A_U64I:.*]] = cir.cast bitcast %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>> -> !cir.ptr<!u64i>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} atomic(seq_cst) %[[A_U64I]] : 
!cir.ptr<!u64i>, !u64i
+// CIR: %[[ATOMIC_TMP_U64I:.*]] = cir.cast bitcast %[[ATOMIC_TMP_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>> -> !cir.ptr<!u64i>
+// CIR: cir.store {{.*}} %[[TMP_A]], %[[ATOMIC_TMP_U64I]] : !u64i, 
!cir.ptr<!u64i>
+// CIR: %[[TMP_ATOMIC:.*]] = cir.load {{.*}} %[[ATOMIC_TMP_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: %[[ATOMIC_TMP_REAL:.*]] = cir.complex.real %[[TMP_ATOMIC]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR: %[[ATOMIC_TMP_IMAG:.*]] = cir.complex.imag %[[TMP_ATOMIC]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR: %[[ATOMIC_TMP_REAL_I32:.*]] = cir.cast float_to_int 
%[[ATOMIC_TMP_REAL]] : !cir.float -> !s32i
+// CIR: %[[ATOMIC_TMP_IMAG_I32:.*]] = cir.cast float_to_int 
%[[ATOMIC_TMP_IMAG]] : !cir.float -> !s32i
+// CIR: %[[RESULT:.*]] = cir.complex.create %[[ATOMIC_TMP_REAL_I32]], 
%[[ATOMIC_TMP_IMAG_I32]] : !s32i -> !cir.complex<!s32i>
+// CIR: cir.store {{.*}} %[[RESULT]], %[[B_ADDR]] : !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 8
+// LLVM: %[[ATOMIC_TMP_ADDR:.*]] = alloca { float, float }, i64 1, align 8
+// LLVM: store { float, float } { float 2.000000e+00, float 0.000000e+00 }, 
ptr %[[A_ADDR]], align 8
+// LLVM: %[[TMP_A:.*]] = load atomic i64, ptr %[[A_ADDR]] seq_cst, align 8
+// LLVM: store i64 %[[TMP_A]], ptr %[[ATOMIC_TMP_ADDR]], align 8
+// LLVM: %[[TMP_ATOMIC:.*]] = load { float, float }, ptr %[[ATOMIC_TMP_ADDR]], 
align 8
+// LLVM: %[[ATOMIC_TMP_REAL:.*]] = extractvalue { float, float } 
%[[TMP_ATOMIC]], 0
+// LLVM: %[[ATOMIC_TMP_IMAG:.*]] = extractvalue { float, float } 
%[[TMP_ATOMIC]], 1
+// LLVM: %[[ATOMIC_TMP_REAL_I32:.*]] = fptosi float %[[ATOMIC_TMP_REAL]] to i32
+// LLVM: %[[ATOMIC_TMP_IMAG_I32:.*]] = fptosi float %[[ATOMIC_TMP_IMAG]] to i32
+// LLVM: %[[TMP_RESULT:.*]] = insertvalue { i32, i32 } {{.*}}, i32 
%[[ATOMIC_TMP_REAL_I32]], 0
+// LLVM: %[[RESULT:.*]] = insertvalue { i32, i32 } %[[TMP_RESULT]], i32 
%[[ATOMIC_TMP_IMAG_I32]], 1
+// LLVM: store { i32, i32 } %[[RESULT]], ptr %[[B_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca { i32, i32 }, align 8
+// OGCG: %[[ATOMIC_TMP_ADDR:.*]] = alloca { float, float }, align 8
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[A_ADDR]], i32 0, i32 1
+// OGCG: store float 2.000000e+00, ptr %[[A_REAL_PTR]], align 8
+// OGCG: store float 0.000000e+00, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[TMP_A:.*]] = load atomic i64, ptr %[[A_ADDR]] seq_cst, align 8
+// OGCG: store i64 %[[TMP_A]], ptr %[[ATOMIC_TMP_ADDR]], align 8
+// OGCG: %[[ATOMIC_TMP_REAL_PTR:.*]] = getelementptr inbounds nuw { float, 
float }, ptr %[[ATOMIC_TMP_ADDR]], i32 0, i32 0
+// OGCG: %[[ATOMIC_TMP_REAL:.*]] = load float, ptr %[[ATOMIC_TMP_REAL_PTR]], 
align 8
+// OGCG: %[[ATOMIC_TMP_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, 
float }, ptr %[[ATOMIC_TMP_ADDR]], i32 0, i32 1
+// OGCG: %[[ATOMIC_TMP_IMAG:.*]] = load float, ptr %[[ATOMIC_TMP_IMAG_PTR]], 
align 4
+// OGCG: %[[RESULT_REAL:.*]] = fptosi float %[[ATOMIC_TMP_REAL]] to i32
+// OGCG: %[[RESULT_IMAG:.*]] = fptosi float %[[ATOMIC_TMP_IMAG]] to i32
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[B_ADDR]], i32 0, i32 0
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[B_ADDR]], i32 0, i32 1
+// OGCG: store i32 %[[RESULT_REAL]], ptr %[[B_REAL_PTR]], align 8
+// OGCG: store i32 %[[RESULT_IMAG]], ptr %[[B_IMAG_PTR]], align 4


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to