llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: Sirui Mu (Lancern) <details> <summary>Changes</summary> This patch adds support for atomic-to-non-atomic casts for complex types. The cast is performed with a temporary alloca and a sequence of bitcast operations: 1. The input pointer is first bitcasted to an integer pointer. 2. An integer value whose bit width equals to the complex type's size in bits is loaded atomically. 3. The integer value is stored to the temporary alloca. 4. A complex value is loaded from the temporary alloca and returned. Complex types whose bit width exceeds the maximum bit width of integer types (e.g. `_Complex double`) are not supported. They will be loaded instead by calling library functions, which is beyond the scope of this patch. Related to #<!-- -->192319 . --- Full diff: https://github.com/llvm/llvm-project/pull/200586.diff 3 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenAtomic.cpp (+42-2) - (modified) clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp (+2-6) - (modified) clang/test/CIR/CodeGen/atomic.c (+31) ``````````diff diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp index 3df0cd23d570e..7bce855089fea 100644 --- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp @@ -110,6 +110,10 @@ class AtomicInfo { /// copy the value across. Address convertToAtomicIntPointer(Address addr) const; + /// Turn an atomic-layout object into an r-value. + RValue convertAtomicTempToRValue(Address addr, SourceLocation loc, + bool asValue) const; + /// Converts a rvalue to integer value. mlir::Value convertRValueToInt(RValue rvalue, bool cmpxchg = false) const; @@ -202,6 +206,31 @@ Address AtomicInfo::convertToAtomicIntPointer(Address addr) const { return castToAtomicIntPointer(addr); } +RValue AtomicInfo::convertAtomicTempToRValue(Address addr, SourceLocation loc, + bool asValue) const { + if (lvalue.isSimple()) { + if (evaluationKind == TEK_Aggregate) { + cgf.cgm.errorNYI( + loc, "AtomicInfo::convertAtomicTempToRValue: aggregate lvalue"); + return RValue::get(nullptr); + } + + // Drill into the padding structure if we have one. + if (hasPadding()) { + cgf.cgm.errorNYI(loc, "AtomicInfo::convertAtomicTempToRValue: padding"); + return RValue::get(nullptr); + } + + // Otherwise, just convert the temporary to an r-value using the + // normal conversion routine. + return cgf.convertTempToRValue(addr, getValueType(), loc); + } + + cgf.cgm.errorNYI(loc, + "AtomicInfo::convertAtomicTempToRValue: non-simple lvalue"); + return RValue::get(nullptr); +} + RValue AtomicInfo::emitAtomicLoad(AggValueSlot resultSlot, SourceLocation loc, bool asValue, cir::MemOrder order, bool isVolatile) { @@ -334,8 +363,19 @@ RValue AtomicInfo::convertToValueOrAtomic(mlir::Value intVal, return RValue::get(nullptr); } - cgf.cgm.errorNYI("convertToValueOrAtomic: convert through temp"); - return RValue::get(nullptr); + Address temp = Address::invalid(); + if (asValue && getEvaluationKind() == TEK_Aggregate) { + cgf.cgm.errorNYI(loc, "convertToValueOrAtomic: aggregate result"); + return RValue::get(nullptr); + } else { + temp = createTempAlloca(); + } + + // Slam the integer into the temporary. + Address castTemp = castToAtomicIntPointer(temp); + cgf.getBuilder().createStore(cgf.getLoc(loc), intVal, castTemp); + + return convertAtomicTempToRValue(temp, loc, asValue); } /// Copy an r-value into memory as part of storing to an atomic type. diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index 5f7e616f2f28b..c6ad7504c8873 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -333,7 +333,7 @@ mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv, SourceLocation loc) { assert(lv.isSimple() && "non-simple complex l-value?"); if (lv.getType()->isAtomicType()) - cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV"); + return cgf.emitAtomicLoad(lv, loc).getComplexValue(); const Address srcAddr = lv.getAddress(); return builder.createLoad(cgf.getLoc(loc), srcAddr, lv.isVolatileQualified()); @@ -456,17 +456,13 @@ mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op, // Atomic to non-atomic casts may be more than a no-op for some platforms // and for some types. + case CK_AtomicToNonAtomic: case CK_NonAtomicToAtomic: case CK_NoOp: case CK_LValueToRValue: case CK_UserDefinedConversion: return Visit(op); - case CK_AtomicToNonAtomic: { - cgf.cgm.errorNYI("ComplexExprEmitter::emitCast AtomicToNonAtomic"); - return {}; - } - case CK_LValueBitCast: { LValue origLV = cgf.emitLValue(op); Address addr = diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c index e4f3fe82310a4..3c51a1f19f3dc 100644 --- a/clang/test/CIR/CodeGen/atomic.c +++ b/clang/test/CIR/CodeGen/atomic.c @@ -99,6 +99,37 @@ void atomic_to_non_atomic(_Atomic int *ptr, _Atomic volatile int *vptr) { // OGCG: %{{.+}} = load atomic volatile i32, ptr %{{.+}} seq_cst, align 4 } +void atomic_to_non_atomic_complex(_Atomic _Complex float *fptr) { + // CIR-LABEL: @atomic_to_non_atomic_complex + // LLVM-LABEL: @atomic_to_non_atomic_complex + // OGCG-LABEL: @atomic_to_non_atomic_complex + + _Complex float a = *fptr; + // CIR: %[[PTR:.+]] = cir.load deref align(8) %{{.+}} : !cir.ptr<!cir.ptr<!cir.complex<!cir.float>>>, !cir.ptr<!cir.complex<!cir.float>> + // CIR-NEXT: %[[INT_PTR:.+]] = cir.cast bitcast %[[PTR]] : !cir.ptr<!cir.complex<!cir.float>> -> !cir.ptr<!u64i> + // CIR-NEXT: %[[INT:.+]] = cir.load align(8) atomic(seq_cst) %[[INT_PTR]] : !cir.ptr<!u64i>, !u64i + // CIR-NEXT: %[[OUT_INT_PTR:.+]] = cir.cast bitcast %[[OUT_PTR:.+]] : !cir.ptr<!cir.complex<!cir.float>> -> !cir.ptr<!u64i> + // CIR-NEXT: cir.store align(8) %[[INT]], %[[OUT_INT_PTR]] : !u64i, !cir.ptr<!u64i> + // CIR-NEXT: %{{.+}} = cir.load align(8) %[[OUT_PTR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> + + // LLVM: %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8 + // LLVM-NEXT: %[[VALUE:.+]] = load atomic i64, ptr %[[PTR]] seq_cst, align 8 + // LLVM-NEXT: store i64 %[[VALUE]], ptr %[[OUT_PTR:.+]], align 8 + // LLVM-NEXT: %{{.+}} = load { float, float }, ptr %[[OUT_PTR]], align 8 + + // OGCG: %[[PTR:.+]] = load ptr, ptr %fptr.addr, align 8 + // OGCG-NEXT: %[[VALUE:.+]] = load atomic i64, ptr %[[PTR]] seq_cst, align 8 + // OGCG-NEXT: store i64 %[[VALUE]], ptr %atomic-temp, align 8 + // OGCG-NEXT: %[[REAL_PTR:.+]] = getelementptr inbounds nuw { float, float }, ptr %atomic-temp, i32 0, i32 0 + // OGCG-NEXT: %[[REAL:.+]] = load float, ptr %[[REAL_PTR]], align 8 + // OGCG-NEXT: %[[IMAG_PTR:.+]] = getelementptr inbounds nuw { float, float }, ptr %atomic-temp, i32 0, i32 1 + // OGCG-NEXT: %[[IMAG:.+]] = load float, ptr %[[IMAG_PTR]], align 4 + // OGCG-NEXT: %[[OUT_REAL_PTR:.+]] = getelementptr inbounds nuw { float, float }, ptr %a, i32 0, i32 0 + // OGCG-NEXT: %[[OUT_IMAG_PTR:.+]] = getelementptr inbounds nuw { float, float }, ptr %a, i32 0, i32 1 + // OGCG-NEXT: store float %[[REAL]], ptr %[[OUT_REAL_PTR]], align 4 + // OGCG-NEXT: store float %[[IMAG]], ptr %[[OUT_IMAG_PTR]], align 4 +} + void load(int *ptr) { int x; __atomic_load(ptr, &x, __ATOMIC_RELAXED); `````````` </details> https://github.com/llvm/llvm-project/pull/200586 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
