Skip to content

Commit 4ea2ec3

Browse files
authored
[CIR] Add support for complex related intrinsics (#748)
This PR adds CIRGen for the following complex related intrinsics: - `__builtin_complex`, - `__builtin_creal`, and - `__builtin_cimag`. The generated CIR does not include any new ops so LLVM IR lowering is already done.
1 parent 3e00be7 commit 4ea2ec3

File tree

3 files changed

+96
-1
lines changed

3 files changed

+96
-1
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,47 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
718718
switch (BuiltinIDIfNoAsmLabel) {
719719
default:
720720
break;
721+
722+
case Builtin::BI__builtin_complex: {
723+
mlir::Value Real = buildScalarExpr(E->getArg(0));
724+
mlir::Value Imag = buildScalarExpr(E->getArg(1));
725+
mlir::Value Complex =
726+
builder.createComplexCreate(getLoc(E->getExprLoc()), Real, Imag);
727+
return RValue::getComplex(Complex);
728+
}
729+
730+
case Builtin::BI__builtin_creal:
731+
case Builtin::BI__builtin_crealf:
732+
case Builtin::BI__builtin_creall:
733+
case Builtin::BIcreal:
734+
case Builtin::BIcrealf:
735+
case Builtin::BIcreall: {
736+
mlir::Value ComplexVal = buildComplexExpr(E->getArg(0));
737+
mlir::Value Real =
738+
builder.createComplexReal(getLoc(E->getExprLoc()), ComplexVal);
739+
return RValue::get(Real);
740+
}
741+
742+
case Builtin::BI__builtin_cimag:
743+
case Builtin::BI__builtin_cimagf:
744+
case Builtin::BI__builtin_cimagl:
745+
case Builtin::BIcimag:
746+
case Builtin::BIcimagf:
747+
case Builtin::BIcimagl: {
748+
mlir::Value ComplexVal = buildComplexExpr(E->getArg(0));
749+
mlir::Value Real =
750+
builder.createComplexImag(getLoc(E->getExprLoc()), ComplexVal);
751+
return RValue::get(Real);
752+
}
753+
754+
case Builtin::BI__builtin_conj:
755+
case Builtin::BI__builtin_conjf:
756+
case Builtin::BI__builtin_conjl:
757+
case Builtin::BIconj:
758+
case Builtin::BIconjf:
759+
case Builtin::BIconjl:
760+
llvm_unreachable("NYI");
761+
721762
case Builtin::BI__builtin___CFStringMakeConstantString:
722763
case Builtin::BI__builtin___NSStringMakeConstantString:
723764
llvm_unreachable("NYI");

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
129129
return buildCast(E->getCastKind(), E->getSubExpr(), E->getType());
130130
}
131131
mlir::Value VisitCastExpr(CastExpr *E) { llvm_unreachable("NYI"); }
132-
mlir::Value VisitCallExpr(const CallExpr *E) { llvm_unreachable("NYI"); }
132+
mlir::Value VisitCallExpr(const CallExpr *E);
133133
mlir::Value VisitStmtExpr(const StmtExpr *E) { llvm_unreachable("NYI"); }
134134

135135
// Operators.
@@ -501,6 +501,13 @@ mlir::Value ComplexExprEmitter::buildCast(CastKind CK, Expr *Op,
501501
llvm_unreachable("unknown cast resulting in complex value");
502502
}
503503

504+
mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
505+
if (E->getCallReturnType(CGF.getContext())->isReferenceType())
506+
return buildLoadOfLValue(E);
507+
508+
return CGF.buildCallExpr(E).getComplexVal();
509+
}
510+
504511
ComplexExprEmitter::BinOpInfo
505512
ComplexExprEmitter::buildBinOps(const BinaryOperator *E, QualType PromotionTy) {
506513
BinOpInfo Ops{CGF.getLoc(E->getExprLoc())};

clang/test/CIR/CodeGen/complex.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ void list_init_2(double r, double i) {
4848
// LLVM-NEXT: store { double, double } %[[#B]], ptr %5, align 8
4949
// LLVM: }
5050

51+
void builtin_init(double r, double i) {
52+
double _Complex c = __builtin_complex(r, i);
53+
}
54+
55+
// C: cir.func @builtin_init
56+
// CPP: cir.func @_Z12builtin_initdd
57+
// CHECK: %{{.+}} = cir.complex.create %{{.+}}, %{{.+}} : !cir.double -> !cir.complex<!cir.double>
58+
// CHECK: }
59+
60+
// LLVM: define void @builtin_init
61+
// LLVM: %[[#A:]] = insertvalue { double, double } undef, double %{{.+}}, 0
62+
// LLVM-NEXT: %[[#B:]] = insertvalue { double, double } %[[#A]], double %{{.+}}, 1
63+
// LLVM-NEXT: store { double, double } %[[#B]], ptr %{{.+}}, align 8
64+
// LLVM: }
65+
5166
void imag_literal() {
5267
c = 3.0i;
5368
ci = 3i;
@@ -116,6 +131,38 @@ void load_store_volatile() {
116131
// LLVM-NEXT: store volatile { i32, i32 } %[[#B]], ptr @vci, align 4
117132
// LLVM: }
118133

134+
void real() {
135+
double r = __builtin_creal(c);
136+
}
137+
138+
// C: cir.func no_proto @real()
139+
// CPP: cir.func @_Z4realv()
140+
// CHECK: %[[#A:]] = cir.get_global @c : !cir.ptr<!cir.complex<!cir.double>>
141+
// CHECK-NEXT: %[[#B:]] = cir.load %[[#A]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
142+
// CHECK-NEXT: %{{.+}} = cir.complex.real %[[#B]] : !cir.complex<!cir.double> -> !cir.double
143+
// CHECK: }
144+
145+
// LLVM: define void @real()
146+
// LLVM: %[[#A:]] = extractvalue { double, double } %{{.+}}, 0
147+
// LLVM-NEXT: store double %[[#A]], ptr %{{.+}}, align 8
148+
// LLVM: }
149+
150+
void imag() {
151+
double i = __builtin_cimag(c);
152+
}
153+
154+
// C: cir.func no_proto @imag()
155+
// CPP: cir.func @_Z4imagv()
156+
// CHECK: %[[#A:]] = cir.get_global @c : !cir.ptr<!cir.complex<!cir.double>>
157+
// CHECK-NEXT: %[[#B:]] = cir.load %[[#A]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
158+
// CHECK-NEXT: %{{.+}} = cir.complex.imag %[[#B]] : !cir.complex<!cir.double> -> !cir.double
159+
// CHECK: }
160+
161+
// LLVM: define void @imag()
162+
// LLVM: %[[#A:]] = extractvalue { double, double } %{{.+}}, 1
163+
// LLVM-NEXT: store double %[[#A]], ptr %{{.+}}, align 8
164+
// LLVM: }
165+
119166
void real_ptr() {
120167
double *r1 = &__real__ c;
121168
int *r2 = &__real__ ci;

0 commit comments

Comments
 (0)