Skip to content

Commit d3e1d50

Browse files
committed
[CIR] Upstream ComplexType builtin_complex
1 parent 0058272 commit d3e1d50

File tree

4 files changed

+68
-1
lines changed

4 files changed

+68
-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
mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
@@ -34,6 +48,16 @@ static const ComplexType *getComplexType(QualType type) {
3448
return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
3549
}
3650

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

73+
mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
74+
if (e->getCallReturnType(cgf.getContext())->isReferenceType())
75+
return emitLoadOfLValue(e);
76+
77+
mlir::Location loc = cgf.getLoc(e->getExprLoc());
78+
auto complex = cgf.emitCallExpr(e).getComplexVal();
79+
return builder.createComplexCreate(loc, complex.first, complex.second);
80+
}
81+
4982
mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
5083
mlir::Location loc = cgf.getLoc(e->getExprLoc());
5184
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: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,31 @@ void foo8() {
191191
// OGCG: store double 0.000000e+00, ptr %[[C_REAL_PTR]], align 8
192192
// OGCG: store double 2.000000e+00, ptr %[[C_IMAG_PTR]], align 8
193193

194+
void foo9(double r, double i) {
195+
double _Complex c = __builtin_complex(r, i);
196+
}
197+
198+
// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["c", init]
199+
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.double>, !cir.double
200+
// CIR: %[[TMP_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.double>, !cir.double
201+
// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[TMP_A]], %[[TMP_B]] : !cir.double -> !cir.complex<!cir.double>
202+
// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>
203+
204+
// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8
205+
// LLVM: %[[TMP_A:.*]] = load double, ptr {{.*}}, align 8
206+
// LLVM: %[[TMP_B:.*]] = load double, ptr {{.*}}, align 8
207+
// LLVM: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[TMP_A]], 0
208+
// LLVM: %[[TMP_2:.*]] = insertvalue { double, double } %[[TMP]], double %[[TMP_B]], 1
209+
// LLVM: store { double, double } %[[TMP_2]], ptr %[[COMPLEX]], align 8
210+
211+
// OGCG: %[[COMPLEX]] = alloca { double, double }, align 8
212+
// OGCG: %[[TMP_A:.*]] = load double, ptr {{.*}}, align 8
213+
// OGCG: %[[TMP_B:.*]] = load double, ptr {{.*}}, align 8
214+
// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 0
215+
// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1
216+
// OGCG: store double %[[TMP_A]], ptr %[[C_REAL_PTR]], align 8
217+
// OGCG: store double %[[TMP_B]], ptr %[[C_IMAG_PTR]], align 8
218+
194219
void foo14() {
195220
int _Complex c = 2i;
196221
}

0 commit comments

Comments
 (0)