[clang] [CIR] Upstream ComplexType builtin_complex (PR #144225)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sat Jun 14 07:22:58 PDT 2025
https://github.com/AmrDeveloper created https://github.com/llvm/llvm-project/pull/144225
This change adds support for builtin_complex
https://github.com/llvm/llvm-project/issues/141365
>From 08893cb4bc8613a455dc2ee21ae6fe6c3e3138a1 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Sat, 14 Jun 2025 16:21:20 +0200
Subject: [PATCH] [CIR] Upstream ComplexType builtin_complex
---
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 10 ++++++-
clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp | 33 +++++++++++++++++++++
clang/lib/CIR/CodeGen/CIRGenValue.h | 1 +
clang/test/CIR/CodeGen/complex.cpp | 24 +++++++++++++++
4 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index c59ac78210f81..b1b2e9080af45 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -50,6 +50,14 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
}
mlir::Location loc = getLoc(e->getExprLoc());
- cgm.errorNYI(loc, "non constant foldable builtin calls");
+ switch (builtinID) {
+ case Builtin::BI__builtin_complex: {
+ mlir::Value real = emitScalarExpr(e->getArg(0));
+ mlir::Value imag = emitScalarExpr(e->getArg(1));
+ return RValue::getComplex(real, imag);
+ }
+ default:
+ cgm.errorNYI(loc, "non constant foldable builtin calls");
+ }
return getUndefRValue(e->getType());
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 2ffe75a388e98..0c7c5c382267c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -15,11 +15,25 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
explicit ComplexExprEmitter(CIRGenFunction &cgf)
: cgf(cgf), builder(cgf.getBuilder()) {}
+ //===--------------------------------------------------------------------===//
+ // Utilities
+ //===--------------------------------------------------------------------===//
+
+ /// Given an expression with complex type that represents a value l-value,
+ /// this method emits the address of the l-value, then loads and returns the
+ /// result.
+ mlir::Value emitLoadOfLValue(const Expr *e) {
+ return emitLoadOfLValue(cgf.emitLValue(e), e->getExprLoc());
+ }
+
+ mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc);
+
/// Store the specified real/imag parts into the
/// specified value pointer.
void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv,
bool isInit);
+ mlir::Value VisitCallExpr(const CallExpr *e);
mlir::Value VisitInitListExpr(InitListExpr *e);
};
@@ -32,6 +46,16 @@ static const ComplexType *getComplexType(QualType type) {
return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
}
+mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
+ SourceLocation loc) {
+ assert(lv.isSimple() && "non-simple complex l-value?");
+ if (lv.getType()->isAtomicType())
+ cgf.cgm.errorNYI("emitLoadOfLValue with Atomic LV");
+
+ const Address srcAddr = lv.getAddress();
+ return builder.createLoad(cgf.getLoc(loc), srcAddr);
+}
+
void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
LValue lv, bool isInit) {
if (lv.getType()->isAtomicType() ||
@@ -44,6 +68,15 @@ void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
builder.createStore(loc, val, destAddr);
}
+mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
+ if (e->getCallReturnType(cgf.getContext())->isReferenceType())
+ return emitLoadOfLValue(e);
+
+ mlir::Location loc = cgf.getLoc(e->getExprLoc());
+ auto complex = cgf.emitCallExpr(e).getComplexVal();
+ return builder.createComplexCreate(loc, complex.first, complex.second);
+}
+
mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
mlir::Location loc = cgf.getLoc(e->getExprLoc());
if (e->getNumInits() == 2) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h
index c1e08ba1e9b67..ca932382c5150 100644
--- a/clang/lib/CIR/CodeGen/CIRGenValue.h
+++ b/clang/lib/CIR/CodeGen/CIRGenValue.h
@@ -96,6 +96,7 @@ class RValue {
er.isVolatile = false;
return er;
}
+
static RValue getComplex(const std::pair<mlir::Value, mlir::Value> &c) {
return getComplex(c.first, c.second);
}
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index d193b9f32efbc..8319a7ddecb1d 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -176,3 +176,27 @@ void foo7() {
// OGCG: store float %[[TMP_A]], ptr %[[C_REAL_PTR]], align 4
// OGCG: store float 2.000000e+00, ptr %[[C_IMAG_PTR]], align 4
+void foo9(double r, double i) {
+ double _Complex c = __builtin_complex(r, i);
+}
+
+// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["c", init]
+// CIR: %[[TMP_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.double>, !cir.double
+// CIR: %[[TMP_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.double>, !cir.double
+// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[TMP_A]], %[[TMP_B]] : !cir.double -> !cir.complex<!cir.double>
+// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>
+
+// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[TMP_A:.*]] = load double, ptr {{.*}}, align 8
+// LLVM: %[[TMP_B:.*]] = load double, ptr {{.*}}, align 8
+// LLVM: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[TMP_A]], 0
+// LLVM: %[[TMP_2:.*]] = insertvalue { double, double } %[[TMP]], double %[[TMP_B]], 1
+// LLVM: store { double, double } %[[TMP_2]], ptr %[[COMPLEX]], align 8
+
+// OGCG: %[[COMPLEX]] = alloca { double, double }, align 8
+// OGCG: %[[TMP_A:.*]] = load double, ptr {{.*}}, align 8
+// OGCG: %[[TMP_B:.*]] = load double, ptr {{.*}}, align 8
+// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 0
+// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1
+// OGCG: store double %[[TMP_A]], ptr %[[C_REAL_PTR]], align 8
+// OGCG: store double %[[TMP_B]], ptr %[[C_IMAG_PTR]], align 8
More information about the cfe-commits
mailing list