diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h | 7 | ||||
-rw-r--r-- | clang/include/clang/CIR/Dialect/IR/CIROps.td | 10 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenAtomic.cpp | 20 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 20 | ||||
-rw-r--r-- | clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 13 | ||||
-rw-r--r-- | clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 15 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/complex.cpp | 16 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/struct.cpp | 28 |
8 files changed, 98 insertions, 31 deletions
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 93d81e3..569491a 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -178,9 +178,10 @@ public: } mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) { - auto operandTy = mlir::cast<cir::ComplexType>(operand.getType()); - return cir::ComplexImagOp::create(*this, loc, operandTy.getElementType(), - operand); + auto resultType = operand.getType(); + if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType)) + resultType = complexResultType.getElementType(); + return cir::ComplexImagOp::create(*this, loc, resultType, operand); } cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr, diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 7f2e55d..c81f64d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3308,18 +3308,20 @@ def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> { def CIR_ComplexImagOp : CIR_Op<"complex.imag", [Pure]> { let summary = "Extract the imaginary part of a complex value"; let description = [{ - `cir.complex.imag` operation takes an operand of `!cir.complex` type and - yields the imaginary part of it. + `cir.complex.imag` operation takes an operand of `!cir.complex`, `!cir.int` + or `!cir.float`. If the operand is `!cir.complex`, the imag part of it will + be returned, otherwise a zero value will be returned. Example: ```mlir - %1 = cir.complex.imag %0 : !cir.complex<!cir.float> -> !cir.float + %imag = cir.complex.imag %complex : !cir.complex<!cir.float> -> !cir.float + %imag = cir.complex.imag %scalar : !cir.float -> !cir.float ``` }]; let results = (outs CIR_AnyIntOrFloatType:$result); - let arguments = (ins CIR_ComplexType:$operand); + let arguments = (ins CIR_AnyComplexOrIntOrFloatType:$operand); let assemblyFormat = [{ $operand `:` qualified(type($operand)) `->` qualified(type($result)) diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp index e943b02..0f4d6d2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp @@ -718,10 +718,26 @@ void CIRGenFunction::emitAtomicInit(Expr *init, LValue dest) { return; } - case cir::TEK_Aggregate: - cgm.errorNYI(init->getSourceRange(), "emitAtomicInit: aggregate type"); + case cir::TEK_Aggregate: { + // Fix up the destination if the initializer isn't an expression + // of atomic type. + bool zeroed = false; + if (!init->getType()->isAtomicType()) { + zeroed = atomics.emitMemSetZeroIfNecessary(); + dest = atomics.projectValue(); + } + + // Evaluate the expression directly into the destination. + assert(!cir::MissingFeatures::aggValueSlotGC()); + AggValueSlot slot = AggValueSlot::forLValue( + dest, AggValueSlot::IsNotDestructed, AggValueSlot::IsNotAliased, + AggValueSlot::DoesNotOverlap, + zeroed ? AggValueSlot::IsZeroed : AggValueSlot::IsNotZeroed); + + emitAggExpr(init, slot); return; } + } llvm_unreachable("bad evaluation kind"); } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 500007f..768d75d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -2159,16 +2159,16 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e, // __imag on a scalar returns zero. Emit the subexpr to ensure side // effects are evaluated, but not the actual value. - if (op->isGLValue()) - cgf.emitLValue(op); - else if (!promotionTy.isNull()) - cgf.emitPromotedScalarExpr(op, promotionTy); - else - cgf.emitScalarExpr(op); - - mlir::Type valueTy = - cgf.convertType(promotionTy.isNull() ? e->getType() : promotionTy); - return builder.getNullValue(valueTy, loc); + mlir::Value operand; + if (op->isGLValue()) { + operand = cgf.emitLValue(op).getPointer(); + operand = cir::LoadOp::create(builder, loc, operand); + } else if (!promotionTy.isNull()) { + operand = cgf.emitPromotedScalarExpr(op, promotionTy); + } else { + operand = cgf.emitScalarExpr(op); + } + return builder.createComplexImag(loc, operand); } /// Return the size or alignment of the type of argument of the sizeof diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index fba094f..cdd4e3c 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2402,9 +2402,8 @@ OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) { LogicalResult cir::ComplexRealOp::verify() { mlir::Type operandTy = getOperand().getType(); - if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) { + if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) operandTy = complexOperandTy.getElementType(); - } if (getType() != operandTy) { emitOpError() << ": result type does not match operand type"; @@ -2431,14 +2430,22 @@ OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) { //===----------------------------------------------------------------------===// LogicalResult cir::ComplexImagOp::verify() { - if (getType() != getOperand().getType().getElementType()) { + mlir::Type operandTy = getOperand().getType(); + if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) + operandTy = complexOperandTy.getElementType(); + + if (getType() != operandTy) { emitOpError() << ": result type does not match operand type"; return failure(); } + return success(); } OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) { + if (!mlir::isa<cir::ComplexType>(getOperand().getType())) + return nullptr; + if (auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>()) return complexCreateOp.getOperand(1); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index bfb1262..1ff8cc5 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -3061,8 +3061,19 @@ mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite( cir::ComplexImagOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType()); - rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>( - op, resultLLVMTy, adaptor.getOperand(), llvm::ArrayRef<std::int64_t>{1}); + mlir::Value operand = adaptor.getOperand(); + mlir::Location loc = op.getLoc(); + + if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) { + operand = mlir::LLVM::ExtractValueOp::create( + rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1}); + } else { + mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy); + operand = + mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr); + } + + rewriter.replaceOp(op, operand); return mlir::success(); } diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index a9ab87e..3524b8b 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -1160,8 +1160,9 @@ void imag_on_scalar_glvalue() { // CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"] // CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init] -// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float -// CIR: cir.store{{.*}} %[[CONST_ZERO]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> +// CIR: %[[TMP_A:.*]] = cir.load %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float +// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.float -> !cir.float +// CIR: cir.store{{.*}} %[[A_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> // LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4 // LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4 @@ -1205,9 +1206,10 @@ void imag_on_scalar_with_type_promotion() { // CIR: %[[A_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["a"] // CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init] -// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float -// CIR: %[[CONST_ZERO_F16:.*]] = cir.cast floating %[[CONST_ZERO]] : !cir.float -> !cir.f16 -// CIR: cir.store{{.*}} %[[CONST_ZERO_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16> +// CIR: %[[TMP_A:.*]] = cir.load %[[A_ADDR]] : !cir.ptr<!cir.f16>, !cir.f16 +// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.f16 -> !cir.f16 +// CIR: %[[A_IMAG_F16:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.f16 +// CIR: cir.store{{.*}} %[[A_IMAG_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16> // LLVM: %[[A_ADDR:.*]] = alloca half, i64 1, align 2 // LLVM: %[[B_ADDR:.*]] = alloca half, i64 1, align 2 @@ -1225,8 +1227,8 @@ void imag_on_const_scalar() { // CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"] // CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init] // CIR: %[[CONST_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float -// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float -// CIR: cir.store{{.*}} %[[CONST_ZERO]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> +// CIR: %[[CONST_IMAG:.*]] = cir.complex.imag %[[CONST_ONE]] : !cir.float -> !cir.float +// CIR: cir.store{{.*}} %[[CONST_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> // LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4 // LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4 diff --git a/clang/test/CIR/CodeGen/struct.cpp b/clang/test/CIR/CodeGen/struct.cpp index 52367bd..c68f742 100644 --- a/clang/test/CIR/CodeGen/struct.cpp +++ b/clang/test/CIR/CodeGen/struct.cpp @@ -184,6 +184,34 @@ void generic_selection() { // OGCG: %[[D_ADDR:.*]] = alloca %struct.CompleteS, align 4 // OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[D_ADDR]], ptr align 4 %[[A_ADDR]], i64 8, i1 false) +void atomic_init() { + _Atomic CompleteS a; + __c11_atomic_init(&a, {}); +} + +// CIR: cir.func{{.*}} @_Z11atomic_initv() +// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a"] +// CIR: %[[ELEM_0_PTR:.*]] = cir.get_member %[[A_ADDR]][0] {name = "a"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s32i> +// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s32i +// CIR: cir.store{{.*}} %[[CONST_0]], %[[ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i> +// CIR: %[[ELEM_1_PTR:.*]] = cir.get_member %[[A_ADDR]][1] {name = "b"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s8i> +// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s8i +// CIR: cir.store{{.*}} %[[CONST_0]], %[[ELEM_1_PTR]] : !s8i, !cir.ptr<!s8i> + +// LLVM: define{{.*}} void @_Z11atomic_initv() +// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 8 +// LLVM: %[[ELEM_0_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0 +// LLVM: store i32 0, ptr %[[ELEM_0_PTR]], align 8 +// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1 +// LLVM: store i8 0, ptr %[[ELEM_1_PTR]], align 4 + +// OGCG: define{{.*}} void @_Z11atomic_initv() +// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 8 +// OGCG: %[[ELEM_0_PTR:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: store i32 0, ptr %[[ELEM_0_PTR]], align 8 +// OGCG: %[[ELEM_1_PTR:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store i8 0, ptr %[[ELEM_1_PTR]], align 4 + void unary_extension() { CompleteS a = __extension__ CompleteS(); } |