Skip to content

Commit

Permalink
[CIR] Add support for complex related intrinsics (llvm#748)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Lancern authored Jul 18, 2024
1 parent 3e00be7 commit 4ea2ec3
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 1 deletion.
41 changes: 41 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,47 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
switch (BuiltinIDIfNoAsmLabel) {
default:
break;

case Builtin::BI__builtin_complex: {
mlir::Value Real = buildScalarExpr(E->getArg(0));
mlir::Value Imag = buildScalarExpr(E->getArg(1));
mlir::Value Complex =
builder.createComplexCreate(getLoc(E->getExprLoc()), Real, Imag);
return RValue::getComplex(Complex);
}

case Builtin::BI__builtin_creal:
case Builtin::BI__builtin_crealf:
case Builtin::BI__builtin_creall:
case Builtin::BIcreal:
case Builtin::BIcrealf:
case Builtin::BIcreall: {
mlir::Value ComplexVal = buildComplexExpr(E->getArg(0));
mlir::Value Real =
builder.createComplexReal(getLoc(E->getExprLoc()), ComplexVal);
return RValue::get(Real);
}

case Builtin::BI__builtin_cimag:
case Builtin::BI__builtin_cimagf:
case Builtin::BI__builtin_cimagl:
case Builtin::BIcimag:
case Builtin::BIcimagf:
case Builtin::BIcimagl: {
mlir::Value ComplexVal = buildComplexExpr(E->getArg(0));
mlir::Value Real =
builder.createComplexImag(getLoc(E->getExprLoc()), ComplexVal);
return RValue::get(Real);
}

case Builtin::BI__builtin_conj:
case Builtin::BI__builtin_conjf:
case Builtin::BI__builtin_conjl:
case Builtin::BIconj:
case Builtin::BIconjf:
case Builtin::BIconjl:
llvm_unreachable("NYI");

case Builtin::BI__builtin___CFStringMakeConstantString:
case Builtin::BI__builtin___NSStringMakeConstantString:
llvm_unreachable("NYI");
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
return buildCast(E->getCastKind(), E->getSubExpr(), E->getType());
}
mlir::Value VisitCastExpr(CastExpr *E) { llvm_unreachable("NYI"); }
mlir::Value VisitCallExpr(const CallExpr *E) { llvm_unreachable("NYI"); }
mlir::Value VisitCallExpr(const CallExpr *E);
mlir::Value VisitStmtExpr(const StmtExpr *E) { llvm_unreachable("NYI"); }

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

mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
if (E->getCallReturnType(CGF.getContext())->isReferenceType())
return buildLoadOfLValue(E);

return CGF.buildCallExpr(E).getComplexVal();
}

ComplexExprEmitter::BinOpInfo
ComplexExprEmitter::buildBinOps(const BinaryOperator *E, QualType PromotionTy) {
BinOpInfo Ops{CGF.getLoc(E->getExprLoc())};
Expand Down
47 changes: 47 additions & 0 deletions clang/test/CIR/CodeGen/complex.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ void list_init_2(double r, double i) {
// LLVM-NEXT: store { double, double } %[[#B]], ptr %5, align 8
// LLVM: }

void builtin_init(double r, double i) {
double _Complex c = __builtin_complex(r, i);
}

// C: cir.func @builtin_init
// CPP: cir.func @_Z12builtin_initdd
// CHECK: %{{.+}} = cir.complex.create %{{.+}}, %{{.+}} : !cir.double -> !cir.complex<!cir.double>
// CHECK: }

// LLVM: define void @builtin_init
// LLVM: %[[#A:]] = insertvalue { double, double } undef, double %{{.+}}, 0
// LLVM-NEXT: %[[#B:]] = insertvalue { double, double } %[[#A]], double %{{.+}}, 1
// LLVM-NEXT: store { double, double } %[[#B]], ptr %{{.+}}, align 8
// LLVM: }

void imag_literal() {
c = 3.0i;
ci = 3i;
Expand Down Expand Up @@ -116,6 +131,38 @@ void load_store_volatile() {
// LLVM-NEXT: store volatile { i32, i32 } %[[#B]], ptr @vci, align 4
// LLVM: }

void real() {
double r = __builtin_creal(c);
}

// C: cir.func no_proto @real()
// CPP: cir.func @_Z4realv()
// CHECK: %[[#A:]] = cir.get_global @c : !cir.ptr<!cir.complex<!cir.double>>
// CHECK-NEXT: %[[#B:]] = cir.load %[[#A]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
// CHECK-NEXT: %{{.+}} = cir.complex.real %[[#B]] : !cir.complex<!cir.double> -> !cir.double
// CHECK: }

// LLVM: define void @real()
// LLVM: %[[#A:]] = extractvalue { double, double } %{{.+}}, 0
// LLVM-NEXT: store double %[[#A]], ptr %{{.+}}, align 8
// LLVM: }

void imag() {
double i = __builtin_cimag(c);
}

// C: cir.func no_proto @imag()
// CPP: cir.func @_Z4imagv()
// CHECK: %[[#A:]] = cir.get_global @c : !cir.ptr<!cir.complex<!cir.double>>
// CHECK-NEXT: %[[#B:]] = cir.load %[[#A]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
// CHECK-NEXT: %{{.+}} = cir.complex.imag %[[#B]] : !cir.complex<!cir.double> -> !cir.double
// CHECK: }

// LLVM: define void @imag()
// LLVM: %[[#A:]] = extractvalue { double, double } %{{.+}}, 1
// LLVM-NEXT: store double %[[#A]], ptr %{{.+}}, align 8
// LLVM: }

void real_ptr() {
double *r1 = &__real__ c;
int *r2 = &__real__ ci;
Expand Down

0 comments on commit 4ea2ec3

Please sign in to comment.