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 @@ -148,9 +148,10 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
}

mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());
return cir::ComplexRealOp::create(*this, loc, operandTy.getElementType(),
operand);
auto resultType = operand.getType();
if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
resultType = complexResultType.getElementType();
return cir::ComplexRealOp::create(*this, loc, resultType, operand);
}

mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
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 @@ -3260,18 +3260,20 @@ def CIR_ComplexCreateOp : CIR_Op<"complex.create", [Pure, SameTypeOperands]> {
def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> {
let summary = "Extract the real part of a complex value";
let description = [{
`cir.complex.real` operation takes an operand of `!cir.complex` type and
yields the real part of it.
`cir.complex.real` operation takes an operand of `!cir.complex`, `!cir.int`
or `!cir.float`. If the operand is `!cir.complex`, the real part of it will
be returned, otherwise the value returned unmodified.

Example:

```mlir
%1 = cir.complex.real %0 : !cir.complex<!cir.float> -> !cir.float
%real = cir.complex.real %complex : !cir.complex<!cir.float> -> !cir.float
%real = cir.complex.real %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
6 changes: 6 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ def CIR_AnyIntOrFloatType : AnyTypeOf<[CIR_AnyFloatType, CIR_AnyIntType],

def CIR_AnyComplexType : CIR_TypeBase<"::cir::ComplexType", "complex type">;

def CIR_AnyComplexOrIntOrFloatType : AnyTypeOf<[
CIR_AnyComplexType, CIR_AnyFloatType, CIR_AnyIntType
], "complex, integer or floating point type"> {
let cppFunctionName = "isComplexOrIntegerOrFloatingPointType";
}

//===----------------------------------------------------------------------===//
// Array Type predicates
//===----------------------------------------------------------------------===//
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2151,8 +2151,10 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e,
}

if (e->getOpcode() == UO_Real) {
return promotionTy.isNull() ? Visit(op)
: cgf.emitPromotedScalarExpr(op, promotionTy);
mlir::Value operand = promotionTy.isNull()
? Visit(op)
: cgf.emitPromotedScalarExpr(op, promotionTy);
return builder.createComplexReal(loc, operand);
}

// __imag on a scalar returns zero. Emit the subexpr to ensure side
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2388,14 +2388,23 @@ OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
//===----------------------------------------------------------------------===//

LogicalResult cir::ComplexRealOp::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::ComplexRealOp::fold(FoldAdaptor adaptor) {
if (!mlir::isa<cir::ComplexType>(getOperand().getType()))
return nullptr;

if (auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
return complexCreateOp.getOperand(0);

Expand Down
9 changes: 7 additions & 2 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2999,8 +2999,13 @@ mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
cir::ComplexRealOp 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>{0});
mlir::Value operand = adaptor.getOperand();
if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
operand = mlir::LLVM::ExtractValueOp::create(
rewriter, op.getLoc(), resultLLVMTy, operand,
llvm::ArrayRef<std::int64_t>{0});
}
rewriter.replaceOp(op, operand);
return mlir::success();
}

Expand Down
14 changes: 9 additions & 5 deletions clang/test/CIR/CodeGen/complex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,8 @@ void real_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: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float
// CIR: cir.store{{.*}} %[[TMP_A]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.float -> !cir.float
// CIR: cir.store{{.*}} %[[A_REAL]], %[[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 @@ -1179,7 +1180,8 @@ void real_on_scalar_with_type_promotion() {
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init]
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.f16>, !cir.f16
// CIR: %[[TMP_A_F32:.*]] = cir.cast floating %[[TMP_A]] : !cir.f16 -> !cir.float
// CIR: %[[TMP_A_F16:.*]] = cir.cast floating %[[TMP_A_F32]] : !cir.float -> !cir.f16
// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A_F32]] : !cir.float -> !cir.float
// CIR: %[[TMP_A_F16:.*]] = cir.cast floating %[[A_REAL]] : !cir.float -> !cir.f16
// CIR: cir.store{{.*}} %[[TMP_A_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>

// LLVM: %[[A_ADDR:.*]] = alloca half, i64 1, align 2
Expand Down Expand Up @@ -1248,7 +1250,8 @@ void real_on_scalar_from_real_with_type_promotion() {
// CIR: %[[A_IMAG_F32:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.float
// CIR: %[[A_COMPLEX_F32:.*]] = cir.complex.create %[[A_REAL_F32]], %[[A_IMAG_F32]] : !cir.float -> !cir.complex<!cir.float>
// CIR: %[[A_REAL_F32:.*]] = cir.complex.real %[[A_COMPLEX_F32]] : !cir.complex<!cir.float> -> !cir.float
// CIR: %[[A_REAL_F16:.*]] = cir.cast floating %[[A_REAL_F32]] : !cir.float -> !cir.f16
// CIR: %[[A_REAL:.*]] = cir.complex.real %[[A_REAL_F32]] : !cir.float -> !cir.float
// CIR: %[[A_REAL_F16:.*]] = cir.cast floating %[[A_REAL]] : !cir.float -> !cir.f16
// CIR: cir.store{{.*}} %[[A_REAL_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>

// LLVM: %[[A_ADDR:.*]] = alloca { half, half }, i64 1, align 2
Expand Down Expand Up @@ -1285,8 +1288,9 @@ void real_on_scalar_from_imag_with_type_promotion() {
// CIR: %[[A_IMAG_F32:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.float
// CIR: %[[A_COMPLEX_F32:.*]] = cir.complex.create %[[A_REAL_F32]], %[[A_IMAG_F32]] : !cir.float -> !cir.complex<!cir.float>
// CIR: %[[A_IMAG_F32:.*]] = cir.complex.imag %[[A_COMPLEX_F32]] : !cir.complex<!cir.float> -> !cir.float
// CIR: %[[A_IMAG_F16:.*]] = cir.cast floating %[[A_IMAG_F32]] : !cir.float -> !cir.f16
// CIR: cir.store{{.*}} %[[A_IMAG_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>
// CIR: %[[A_REAL_F32:.*]] = cir.complex.real %[[A_IMAG_F32]] : !cir.float -> !cir.float
// CIR: %[[A_REAL_F16:.*]] = cir.cast floating %[[A_REAL_F32]] : !cir.float -> !cir.f16
// CIR: cir.store{{.*}} %[[A_REAL_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>

// LLVM: %[[A_ADDR:.*]] = alloca { half, half }, i64 1, align 2
// LLVM: %[[B_ADDR]] = alloca half, i64 1, align 2
Expand Down