-
Notifications
You must be signed in to change notification settings - Fork 13.8k
[CIR] Upstream ComplexImagPtrOp for ComplexType #144236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/amrdeveloper/cir-upstream-complex-real-ptr
Are you sure you want to change the base?
[CIR] Upstream ComplexImagPtrOp for ComplexType #144236
Conversation
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
@llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) ChangesFull diff: https://github.com/llvm/llvm-project/pull/144236.diff 7 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 17279f0a9985a..f90784c99602c 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2414,4 +2414,33 @@ def ComplexRealPtrOp : CIR_Op<"complex.real_ptr", [Pure]> {
let hasVerifier = 1;
}
+//===----------------------------------------------------------------------===//
+// ComplexImagPtrOp
+//===----------------------------------------------------------------------===//
+
+def ComplexImagPtrOp : CIR_Op<"complex.imag_ptr", [Pure]> {
+ let summary = "Derive a pointer to the imaginary part of a complex value";
+ let description = [{
+ `cir.complex.imag_ptr` operation takes a pointer operand that points to a
+ complex value of type `!cir.complex` and yields a pointer to the imaginary
+ part of the operand.
+
+ Example:
+
+ ```mlir
+ %1 = cir.complex.imag_ptr %0 : !cir.ptr<!cir.complex<!cir.double>> -> !cir.ptr<!cir.double>
+ ```
+ }];
+
+ let results = (outs CIR_PtrToIntOrFloatType:$result);
+ let arguments = (ins CIR_PtrToComplexType:$operand);
+
+ let assemblyFormat = [{
+ $operand `:`
+ qualified(type($operand)) `->` qualified(type($result)) attr-dict
+ }];
+
+ let hasVerifier = 1;
+}
+
#endif // CLANG_CIR_DIALECT_IR_CIROPS_TD
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 3f7ea5bccb6d5..df3f4d65610a6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -379,6 +379,20 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return Address{createRealPtr(loc, addr.getPointer()), addr.getAlignment()};
}
+ /// Create a cir.complex.imag_ptr operation that derives a pointer to the
+ /// imaginary part of the complex value pointed to by the specified pointer
+ /// value.
+ mlir::Value createImagPtr(mlir::Location loc, mlir::Value value) {
+ auto srcPtrTy = mlir::cast<cir::PointerType>(value.getType());
+ auto srcComplexTy = mlir::cast<cir::ComplexType>(srcPtrTy.getPointee());
+ return create<cir::ComplexImagPtrOp>(
+ loc, getPointerTo(srcComplexTy.getElementType()), value);
+ }
+
+ Address createImagPtr(mlir::Location loc, Address addr) {
+ return Address{createImagPtr(loc, addr.getPointer()), addr.getAlignment()};
+ }
+
/// Create a cir.ptr_stride operation to get access to an array element.
/// \p idx is the index of the element to access, \p shouldDecay is true if
/// the result should decay to a pointer to the element type.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index a682586562e04..8e3d9ab620621 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -541,11 +541,6 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) {
}
case UO_Real:
case UO_Imag: {
- if (op == UO_Imag) {
- cgm.errorNYI(e->getSourceRange(), "UnaryOp real/imag");
- return LValue();
- }
-
LValue lv = emitLValue(e->getSubExpr());
assert(lv.isSimple() && "real/imag on non-ordinary l-value");
@@ -560,7 +555,9 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) {
QualType exprTy = getContext().getCanonicalType(e->getSubExpr()->getType());
QualType elemTy = exprTy->castAs<clang::ComplexType>()->getElementType();
mlir::Location loc = getLoc(e->getExprLoc());
- Address component = builder.createRealPtr(loc, lv.getAddress());
+ Address component = op == UO_Real
+ ? builder.createRealPtr(loc, lv.getAddress())
+ : builder.createImagPtr(loc, lv.getAddress());
LValue elemLV = makeAddrLValue(component, elemTy);
elemLV.getQuals().addQualifiers(lv.getQuals());
return elemLV;
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 99ae4dd59120a..40488f6af5676 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1794,6 +1794,25 @@ LogicalResult cir::ComplexRealPtrOp::verify() {
return success();
}
+//===----------------------------------------------------------------------===//
+// ComplexImagPtrOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult cir::ComplexImagPtrOp::verify() {
+ mlir::Type resultPointeeTy = getType().getPointee();
+ cir::PointerType operandPtrTy = getOperand().getType();
+ auto operandPointeeTy =
+ mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
+
+ if (resultPointeeTy != operandPointeeTy.getElementType()) {
+ emitOpError()
+ << "cir.complex.imag_ptr result type does not match operand type";
+ return failure();
+ }
+
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index c11992a4bdc61..35f334e3c8e78 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1837,7 +1837,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
CIRToLLVMVecShuffleDynamicOpLowering,
CIRToLLVMVecTernaryOpLowering,
CIRToLLVMComplexCreateOpLowering,
- CIRToLLVMComplexRealPtrOpLowering
+ CIRToLLVMComplexRealPtrOpLowering,
+ CIRToLLVMComplexImagPtrOpLowering
// clang-format on
>(converter, patterns.getContext());
@@ -2158,6 +2159,23 @@ mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
return mlir::success();
}
+mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
+ cir::ComplexImagPtrOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ cir::PointerType operandTy = op.getOperand().getType();
+ mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
+ mlir::Type elementLLVMTy =
+ getTypeConverter()->convertType(operandTy.getPointee());
+
+ mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
+ mlir::LLVM::GEPNoWrapFlags inboundsNuw =
+ mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
+ rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
+ op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
+ inboundsNuw);
+ return mlir::success();
+}
+
std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
return std::make_unique<ConvertCIRToLLVMPass>();
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index caee3e9cd6980..531cd42f1e270 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -428,6 +428,16 @@ class CIRToLLVMComplexRealPtrOpLowering
mlir::ConversionPatternRewriter &) const override;
};
+class CIRToLLVMComplexImagPtrOpLowering
+ : public mlir::OpConversionPattern<cir::ComplexImagPtrOp> {
+public:
+ using mlir::OpConversionPattern<cir::ComplexImagPtrOp>::OpConversionPattern;
+
+ mlir::LogicalResult
+ matchAndRewrite(cir::ComplexImagPtrOp op, OpAdaptor,
+ mlir::ConversionPatternRewriter &) const override;
+};
+
} // namespace direct
} // namespace cir
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index 182673a69be90..4bccf65cceb13 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -189,3 +189,17 @@ void foo10() {
// OGCG: %[[COMPLEX:.*]] = alloca { double, double }, align 8
// OGCG: %[[REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 0
+
+void foo11() {
+ double _Complex c;
+ double *imagPtr = &__imag__ c;
+}
+
+// CIR: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["c"]
+// CIR: %[[IMAG_PTR:.*]] = cir.complex.imag_ptr %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.double>> -> !cir.ptr<!cir.double>
+
+// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1
+
+// OGCG: %[[COMPLEX:.*]] = alloca { double, double }, align 8
+// OGCG: %[[IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1
|
This change adds support for ComplexImagPtrOp for ComplexType
#141365