Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,10 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
}

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,
Expand Down
10 changes: 6 additions & 4 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -3291,18 +3291,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))
Expand Down
20 changes: 10 additions & 10 deletions clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 10 additions & 3 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2389,9 +2389,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";
Expand All @@ -2418,14 +2417,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);

Expand Down
15 changes: 13 additions & 2 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3062,8 +3062,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();
}

Expand Down
16 changes: 9 additions & 7 deletions clang/test/CIR/CodeGen/complex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down