Skip to content

Commit 08893cb

Browse files
committed
[CIR] Upstream ComplexType builtin_complex
1 parent 6464066 commit 08893cb

File tree

4 files changed

+67
-1
lines changed

4 files changed

+67
-1
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
5050
}
5151

5252
mlir::Location loc = getLoc(e->getExprLoc());
53-
cgm.errorNYI(loc, "non constant foldable builtin calls");
53+
switch (builtinID) {
54+
case Builtin::BI__builtin_complex: {
55+
mlir::Value real = emitScalarExpr(e->getArg(0));
56+
mlir::Value imag = emitScalarExpr(e->getArg(1));
57+
return RValue::getComplex(real, imag);
58+
}
59+
default:
60+
cgm.errorNYI(loc, "non constant foldable builtin calls");
61+
}
5462
return getUndefRValue(e->getType());
5563
}

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,25 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
1515
explicit ComplexExprEmitter(CIRGenFunction &cgf)
1616
: cgf(cgf), builder(cgf.getBuilder()) {}
1717

18+
//===--------------------------------------------------------------------===//
19+
// Utilities
20+
//===--------------------------------------------------------------------===//
21+
22+
/// Given an expression with complex type that represents a value l-value,
23+
/// this method emits the address of the l-value, then loads and returns the
24+
/// result.
25+
mlir::Value emitLoadOfLValue(const Expr *e) {
26+
return emitLoadOfLValue(cgf.emitLValue(e), e->getExprLoc());
27+
}
28+
29+
mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc);
30+
1831
/// Store the specified real/imag parts into the
1932
/// specified value pointer.
2033
void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv,
2134
bool isInit);
2235

36+
mlir::Value VisitCallExpr(const CallExpr *e);
2337
mlir::Value VisitInitListExpr(InitListExpr *e);
2438
};
2539

@@ -32,6 +46,16 @@ static const ComplexType *getComplexType(QualType type) {
3246
return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
3347
}
3448

49+
mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
50+
SourceLocation loc) {
51+
assert(lv.isSimple() && "non-simple complex l-value?");
52+
if (lv.getType()->isAtomicType())
53+
cgf.cgm.errorNYI("emitLoadOfLValue with Atomic LV");
54+
55+
const Address srcAddr = lv.getAddress();
56+
return builder.createLoad(cgf.getLoc(loc), srcAddr);
57+
}
58+
3559
void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
3660
LValue lv, bool isInit) {
3761
if (lv.getType()->isAtomicType() ||
@@ -44,6 +68,15 @@ void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
4468
builder.createStore(loc, val, destAddr);
4569
}
4670

71+
mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
72+
if (e->getCallReturnType(cgf.getContext())->isReferenceType())
73+
return emitLoadOfLValue(e);
74+
75+
mlir::Location loc = cgf.getLoc(e->getExprLoc());
76+
auto complex = cgf.emitCallExpr(e).getComplexVal();
77+
return builder.createComplexCreate(loc, complex.first, complex.second);
78+
}
79+
4780
mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
4881
mlir::Location loc = cgf.getLoc(e->getExprLoc());
4982
if (e->getNumInits() == 2) {

clang/lib/CIR/CodeGen/CIRGenValue.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class RValue {
9696
er.isVolatile = false;
9797
return er;
9898
}
99+
99100
static RValue getComplex(const std::pair<mlir::Value, mlir::Value> &c) {
100101
return getComplex(c.first, c.second);
101102
}

clang/test/CIR/CodeGen/complex.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,27 @@ void foo7() {
176176
// OGCG: store float %[[TMP_A]], ptr %[[C_REAL_PTR]], align 4
177177
// OGCG: store float 2.000000e+00, ptr %[[C_IMAG_PTR]], align 4
178178

179+
void foo9(double r, double i) {
180+
double _Complex c = __builtin_complex(r, i);
181+
}
182+
183+
// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["c", init]
184+
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.double>, !cir.double
185+
// CIR: %[[TMP_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.double>, !cir.double
186+
// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[TMP_A]], %[[TMP_B]] : !cir.double -> !cir.complex<!cir.double>
187+
// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>
188+
189+
// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8
190+
// LLVM: %[[TMP_A:.*]] = load double, ptr {{.*}}, align 8
191+
// LLVM: %[[TMP_B:.*]] = load double, ptr {{.*}}, align 8
192+
// LLVM: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[TMP_A]], 0
193+
// LLVM: %[[TMP_2:.*]] = insertvalue { double, double } %[[TMP]], double %[[TMP_B]], 1
194+
// LLVM: store { double, double } %[[TMP_2]], ptr %[[COMPLEX]], align 8
195+
196+
// OGCG: %[[COMPLEX]] = alloca { double, double }, align 8
197+
// OGCG: %[[TMP_A:.*]] = load double, ptr {{.*}}, align 8
198+
// OGCG: %[[TMP_B:.*]] = load double, ptr {{.*}}, align 8
199+
// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 0
200+
// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1
201+
// OGCG: store double %[[TMP_A]], ptr %[[C_REAL_PTR]], align 8
202+
// OGCG: store double %[[TMP_B]], ptr %[[C_IMAG_PTR]], align 8

0 commit comments

Comments
 (0)