Skip to content

Commit dd1105b

Browse files
authored
[CIR] Implement AddOp for ComplexType (#147578)
This change adds support for AddOp for ComplexType #141365
1 parent 8ad384b commit dd1105b

File tree

6 files changed

+356
-0
lines changed

6 files changed

+356
-0
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2521,6 +2521,32 @@ def ComplexImagOp : CIR_Op<"complex.imag", [Pure]> {
25212521
let hasFolder = 1;
25222522
}
25232523

2524+
//===----------------------------------------------------------------------===//
2525+
// ComplexAddOp
2526+
//===----------------------------------------------------------------------===//
2527+
2528+
def ComplexAddOp : CIR_Op<"complex.add", [Pure, SameOperandsAndResultType]> {
2529+
let summary = "Complex addition";
2530+
let description = [{
2531+
The `cir.complex.add` operation takes two complex numbers and returns
2532+
their sum.
2533+
2534+
Example:
2535+
2536+
```mlir
2537+
%2 = cir.complex.add %0, %1 : !cir.complex<!cir.float>
2538+
```
2539+
}];
2540+
2541+
let arguments = (ins CIR_ComplexType:$lhs, CIR_ComplexType:$rhs);
2542+
2543+
let results = (outs CIR_ComplexType:$result);
2544+
2545+
let assemblyFormat = [{
2546+
$lhs `,` $rhs `:` qualified(type($result)) attr-dict
2547+
}];
2548+
}
2549+
25242550
//===----------------------------------------------------------------------===//
25252551
// Bit Manipulation Operations
25262552
//===----------------------------------------------------------------------===//

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,55 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
5757
mlir::Value
5858
VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e);
5959
mlir::Value VisitUnaryDeref(const Expr *e);
60+
61+
struct BinOpInfo {
62+
mlir::Location loc;
63+
mlir::Value lhs{};
64+
mlir::Value rhs{};
65+
QualType ty{}; // Computation Type.
66+
FPOptions fpFeatures{};
67+
};
68+
69+
BinOpInfo emitBinOps(const BinaryOperator *e,
70+
QualType promotionTy = QualType());
71+
72+
mlir::Value emitPromoted(const Expr *e, QualType promotionTy);
73+
74+
mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy);
75+
76+
mlir::Value emitBinAdd(const BinOpInfo &op);
77+
78+
QualType getPromotionType(QualType ty, bool isDivOpCode = false) {
79+
if (auto *complexTy = ty->getAs<ComplexType>()) {
80+
QualType elementTy = complexTy->getElementType();
81+
if (isDivOpCode && elementTy->isFloatingType() &&
82+
cgf.getLangOpts().getComplexRange() ==
83+
LangOptions::ComplexRangeKind::CX_Promoted) {
84+
cgf.cgm.errorNYI("HigherPrecisionTypeForComplexArithmetic");
85+
return QualType();
86+
}
87+
88+
if (elementTy.UseExcessPrecision(cgf.getContext()))
89+
return cgf.getContext().getComplexType(cgf.getContext().FloatTy);
90+
}
91+
92+
if (ty.UseExcessPrecision(cgf.getContext()))
93+
return cgf.getContext().FloatTy;
94+
return QualType();
95+
}
96+
97+
#define HANDLEBINOP(OP) \
98+
mlir::Value VisitBin##OP(const BinaryOperator *e) { \
99+
QualType promotionTy = getPromotionType( \
100+
e->getType(), e->getOpcode() == BinaryOperatorKind::BO_Div); \
101+
mlir::Value result = emitBin##OP(emitBinOps(e, promotionTy)); \
102+
if (!promotionTy.isNull()) \
103+
cgf.cgm.errorNYI("Binop emitUnPromotedValue"); \
104+
return result; \
105+
}
106+
107+
HANDLEBINOP(Add)
108+
#undef HANDLEBINOP
60109
};
61110
} // namespace
62111

@@ -291,6 +340,60 @@ mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) {
291340
return emitLoadOfLValue(e);
292341
}
293342

343+
mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
344+
QualType promotionTy) {
345+
e = e->IgnoreParens();
346+
if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
347+
switch (bo->getOpcode()) {
348+
#define HANDLE_BINOP(OP) \
349+
case BO_##OP: \
350+
return emitBin##OP(emitBinOps(bo, promotionTy));
351+
HANDLE_BINOP(Add)
352+
#undef HANDLE_BINOP
353+
default:
354+
break;
355+
}
356+
} else if (isa<UnaryOperator>(e)) {
357+
cgf.cgm.errorNYI("emitPromoted UnaryOperator");
358+
return {};
359+
}
360+
361+
mlir::Value result = Visit(const_cast<Expr *>(e));
362+
if (!promotionTy.isNull())
363+
cgf.cgm.errorNYI("emitPromoted emitPromotedValue");
364+
365+
return result;
366+
}
367+
368+
mlir::Value
369+
ComplexExprEmitter::emitPromotedComplexOperand(const Expr *e,
370+
QualType promotionTy) {
371+
if (e->getType()->isAnyComplexType()) {
372+
if (!promotionTy.isNull())
373+
return cgf.emitPromotedComplexExpr(e, promotionTy);
374+
return Visit(const_cast<Expr *>(e));
375+
}
376+
377+
cgf.cgm.errorNYI("emitPromotedComplexOperand non-complex type");
378+
return {};
379+
}
380+
381+
ComplexExprEmitter::BinOpInfo
382+
ComplexExprEmitter::emitBinOps(const BinaryOperator *e, QualType promotionTy) {
383+
BinOpInfo binOpInfo{cgf.getLoc(e->getExprLoc())};
384+
binOpInfo.lhs = emitPromotedComplexOperand(e->getLHS(), promotionTy);
385+
binOpInfo.rhs = emitPromotedComplexOperand(e->getRHS(), promotionTy);
386+
binOpInfo.ty = promotionTy.isNull() ? e->getType() : promotionTy;
387+
binOpInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
388+
return binOpInfo;
389+
}
390+
391+
mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {
392+
assert(!cir::MissingFeatures::fastMathFlags());
393+
assert(!cir::MissingFeatures::cgFPOptionsRAII());
394+
return builder.create<cir::ComplexAddOp>(op.loc, op.lhs, op.rhs);
395+
}
396+
294397
LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) {
295398
assert(e->getOpcode() == BO_Assign && "Expected assign op");
296399

@@ -313,3 +416,8 @@ void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v,
313416
LValue dest, bool isInit) {
314417
ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit);
315418
}
419+
420+
mlir::Value CIRGenFunction::emitPromotedComplexExpr(const Expr *e,
421+
QualType promotionType) {
422+
return ComplexExprEmitter(*this).emitPromoted(e, promotionType);
423+
}

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,8 @@ class CIRGenFunction : public CIRGenTypeCache {
886886
void emitInitializerForField(clang::FieldDecl *field, LValue lhs,
887887
clang::Expr *init);
888888

889+
mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
890+
889891
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
890892

891893
/// Emit the computation of the specified expression of scalar type.

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,6 +2048,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
20482048
CIRToLLVMBrOpLowering,
20492049
CIRToLLVMCallOpLowering,
20502050
CIRToLLVMCmpOpLowering,
2051+
CIRToLLVMComplexAddOpLowering,
20512052
CIRToLLVMComplexCreateOpLowering,
20522053
CIRToLLVMComplexImagOpLowering,
20532054
CIRToLLVMComplexRealOpLowering,
@@ -2357,6 +2358,55 @@ mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
23572358
return mlir::success();
23582359
}
23592360

2361+
mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
2362+
cir::ComplexAddOp op, OpAdaptor adaptor,
2363+
mlir::ConversionPatternRewriter &rewriter) const {
2364+
mlir::Value lhs = adaptor.getLhs();
2365+
mlir::Value rhs = adaptor.getRhs();
2366+
mlir::Location loc = op.getLoc();
2367+
2368+
auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
2369+
mlir::Type complexElemTy =
2370+
getTypeConverter()->convertType(complexType.getElementType());
2371+
auto lhsReal =
2372+
rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
2373+
auto lhsImag =
2374+
rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
2375+
auto rhsReal =
2376+
rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
2377+
auto rhsImag =
2378+
rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
2379+
2380+
mlir::Value newReal;
2381+
mlir::Value newImag;
2382+
if (complexElemTy.isInteger()) {
2383+
newReal = rewriter.create<mlir::LLVM::AddOp>(loc, complexElemTy, lhsReal,
2384+
rhsReal);
2385+
newImag = rewriter.create<mlir::LLVM::AddOp>(loc, complexElemTy, lhsImag,
2386+
rhsImag);
2387+
} else {
2388+
assert(!cir::MissingFeatures::fastMathFlags());
2389+
assert(!cir::MissingFeatures::fpConstraints());
2390+
newReal = rewriter.create<mlir::LLVM::FAddOp>(loc, complexElemTy, lhsReal,
2391+
rhsReal);
2392+
newImag = rewriter.create<mlir::LLVM::FAddOp>(loc, complexElemTy, lhsImag,
2393+
rhsImag);
2394+
}
2395+
2396+
mlir::Type complexLLVMTy =
2397+
getTypeConverter()->convertType(op.getResult().getType());
2398+
auto initialComplex =
2399+
rewriter.create<mlir::LLVM::PoisonOp>(op->getLoc(), complexLLVMTy);
2400+
2401+
auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>(
2402+
op->getLoc(), initialComplex, newReal, 0);
2403+
2404+
rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(op, realComplex,
2405+
newImag, 1);
2406+
2407+
return mlir::success();
2408+
}
2409+
23602410
mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
23612411
cir::ComplexCreateOp op, OpAdaptor adaptor,
23622412
mlir::ConversionPatternRewriter &rewriter) const {

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,16 @@ class CIRToLLVMGetBitfieldOpLowering
523523
mlir::ConversionPatternRewriter &) const override;
524524
};
525525

526+
class CIRToLLVMComplexAddOpLowering
527+
: public mlir::OpConversionPattern<cir::ComplexAddOp> {
528+
public:
529+
using mlir::OpConversionPattern<cir::ComplexAddOp>::OpConversionPattern;
530+
531+
mlir::LogicalResult
532+
matchAndRewrite(cir::ComplexAddOp op, OpAdaptor,
533+
mlir::ConversionPatternRewriter &) const override;
534+
};
535+
526536
} // namespace direct
527537
} // namespace cir
528538

0 commit comments

Comments
 (0)