Skip to content

Commit 84d65e9

Browse files
authored
[CIR] Upstream builtin_conj for ComplexType (#149170)
This change adds support for builtin_conj for ComplexType #141365
1 parent 149aa76 commit 84d65e9

File tree

4 files changed

+56
-3
lines changed

4 files changed

+56
-3
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
125125
mlir::Value real = emitScalarExpr(e->getArg(0));
126126
mlir::Value imag = emitScalarExpr(e->getArg(1));
127127
mlir::Value complex = builder.createComplexCreate(loc, real, imag);
128-
return RValue::get(complex);
128+
return RValue::getComplex(complex);
129129
}
130130

131131
case Builtin::BI__builtin_creal:
@@ -150,6 +150,18 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
150150
return RValue::get(imag);
151151
}
152152

153+
case Builtin::BI__builtin_conj:
154+
case Builtin::BI__builtin_conjf:
155+
case Builtin::BI__builtin_conjl:
156+
case Builtin::BIconj:
157+
case Builtin::BIconjf:
158+
case Builtin::BIconjl: {
159+
mlir::Value complex = emitComplexExpr(e->getArg(0));
160+
mlir::Value conj = builder.createUnaryOp(getLoc(e->getExprLoc()),
161+
cir::UnaryOpKind::Not, complex);
162+
return RValue::getComplex(conj);
163+
}
164+
153165
case Builtin::BI__builtin_clrsb:
154166
case Builtin::BI__builtin_clrsbl:
155167
case Builtin::BI__builtin_clrsbll:

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,7 @@ mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) {
231231
mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
232232
if (e->getCallReturnType(cgf.getContext())->isReferenceType())
233233
return emitLoadOfLValue(e);
234-
235-
return cgf.emitCallExpr(e).getValue();
234+
return cgf.emitCallExpr(e).getComplexValue();
236235
}
237236

238237
mlir::Value ComplexExprEmitter::VisitCastExpr(CastExpr *e) {

clang/lib/CIR/CodeGen/CIRGenValue.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ class RValue {
5858
return value;
5959
}
6060

61+
/// Return the value of this complex value.
62+
mlir::Value getComplexValue() const {
63+
assert(isComplex() && "Not a complex!");
64+
return value;
65+
}
66+
6167
/// Return the value of the address of the aggregate.
6268
Address getAggregateAddress() const {
6369
assert(isAggregate() && "Not an aggregate!");

clang/test/CIR/CodeGen/complex-builtins.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,39 @@ void foo3() {
8383
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1
8484
// OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 8
8585
// OGCG: store double %[[A_IMAG]], ptr %[[INIT]], align 8
86+
87+
void foo4() {
88+
float _Complex a;
89+
float _Complex b = __builtin_conjf(a);
90+
}
91+
92+
// CIR: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
93+
// CIR: %[[RESULT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]
94+
// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
95+
// CIR: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.float> -> !cir.float
96+
// CIR: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!cir.float> -> !cir.float
97+
// CIR: %[[IMAG_MINUS:.*]] = cir.unary(minus, %[[IMAG]]) : !cir.float, !cir.float
98+
// CIR: %[[RESULT_VAL:.*]] = cir.complex.create %[[REAL]], %[[IMAG_MINUS]] : !cir.float -> !cir.complex<!cir.float>
99+
// CIR: cir.store{{.*}} %[[RESULT_VAL]], %[[RESULT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
100+
101+
// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4
102+
// LLVM: %[[RESULT:.*]] = alloca { float, float }, i64 1, align 4
103+
// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[COMPLEX]], align 4
104+
// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0
105+
// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1
106+
// LLVM: %[[IMAG_MINUS:.*]] = fneg float %[[IMAG]]
107+
// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL]], 0
108+
// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG_MINUS]], 1
109+
// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[RESULT]], align 4
110+
111+
// OGCG: %[[COMPLEX:.*]] = alloca { float, float }, align 4
112+
// OGCG: %[[RESULT:.*]] = alloca { float, float }, align 4
113+
// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0
114+
// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
115+
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1
116+
// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
117+
// OGCG: %[[A_IMAG_MINUS:.*]] = fneg float %[[A_IMAG]]
118+
// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 0
119+
// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 1
120+
// OGCG: store float %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4
121+
// OGCG: store float %[[A_IMAG_MINUS]], ptr %[[RESULT_IMAG_PTR]], align 4

0 commit comments

Comments
 (0)