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
