Skip to content

Commit 8e383e2

Browse files
authored
[CIR] Implement Complex real & imag for non scalar GLValue (llvm#159931)
This change implements Complex real & imag for non-scalar GLValue Issue: llvm#141365
1 parent e80a207 commit 8e383e2

File tree

2 files changed

+74
-15
lines changed

2 files changed

+74
-15
lines changed

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2125,26 +2125,19 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e,
21252125
"Invalid UnaryOp kind for ComplexType Real or Imag");
21262126

21272127
Expr *op = e->getSubExpr();
2128+
mlir::Location loc = cgf.getLoc(e->getExprLoc());
21282129
if (op->getType()->isAnyComplexType()) {
21292130
// If it's an l-value, load through the appropriate subobject l-value.
21302131
// Note that we have to ask `e` because `op` might be an l-value that
2131-
// this won't work for, e.g. an Obj-C property.
2132-
if (e->isGLValue()) {
2133-
mlir::Location loc = cgf.getLoc(e->getExprLoc());
2134-
mlir::Value complex = cgf.emitComplexExpr(op);
2135-
if (!promotionTy.isNull()) {
2136-
complex = cgf.emitPromotedValue(complex, promotionTy);
2137-
}
2138-
2139-
return e->getOpcode() == clang::UO_Real
2140-
? builder.createComplexReal(loc, complex)
2141-
: builder.createComplexImag(loc, complex);
2132+
// this won't work for, e.g. an Obj-C property
2133+
mlir::Value complex = cgf.emitComplexExpr(op);
2134+
if (e->isGLValue() && !promotionTy.isNull()) {
2135+
complex = cgf.emitPromotedValue(complex, promotionTy);
21422136
}
21432137

2144-
// Otherwise, calculate and project.
2145-
cgf.cgm.errorNYI(e->getSourceRange(),
2146-
"VisitRealImag calculate and project");
2147-
return {};
2138+
return e->getOpcode() == clang::UO_Real
2139+
? builder.createComplexReal(loc, complex)
2140+
: builder.createComplexImag(loc, complex);
21482141
}
21492142

21502143
// __real or __imag on a scalar returns zero. Emit the subexpr to ensure side

clang/test/CIR/CodeGen/complex.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,3 +1027,69 @@ void foo37() {
10271027
// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1
10281028
// OGCG: store float %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4
10291029
// OGCG: store float %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4
1030+
1031+
void real_on_non_glvalue() {
1032+
float _Complex a;
1033+
float b = __real__(+a);
1034+
}
1035+
1036+
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
1037+
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]
1038+
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
1039+
// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float
1040+
// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float
1041+
// CIR: %[[A_REAL_PLUS:.*]] = cir.unary(plus, %[[A_REAL]]) : !cir.float, !cir.float
1042+
// CIR: %[[A_IMAG_PLUS:.*]] = cir.unary(plus, %[[A_IMAG]]) : !cir.float, !cir.float
1043+
// CIR: %[[RESULT:.*]] = cir.complex.create %[[A_REAL_PLUS]], %[[A_IMAG_PLUS]] : !cir.float -> !cir.complex<!cir.float>
1044+
// CIR: %[[RESULT_REAL:.*]] = cir.complex.real %[[RESULT]] : !cir.complex<!cir.float> -> !cir.float
1045+
// CIR: cir.store{{.*}} %[[RESULT_REAL]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
1046+
1047+
// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
1048+
// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4
1049+
// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
1050+
// LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0
1051+
// LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1
1052+
// LLVM: %[[TMP_RESULT:.*]] = insertvalue { float, float } {{.*}}, float %[[A_REAL]], 0
1053+
// LLVM: %[[RESULT:.*]] = insertvalue { float, float } %[[TMP_RESULT]], float %[[A_IMAG]], 1
1054+
// LLVM: store float %[[A_REAL]], ptr %[[B_ADDR]], align 4
1055+
1056+
// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
1057+
// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
1058+
// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
1059+
// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
1060+
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
1061+
// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
1062+
// OGCG: store float %[[A_REAL]], ptr %[[B_ADDR]], align 4
1063+
1064+
void imag_on_non_glvalue() {
1065+
float _Complex a;
1066+
float b = __imag__(+a);
1067+
}
1068+
1069+
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
1070+
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]
1071+
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
1072+
// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float
1073+
// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float
1074+
// CIR: %[[A_REAL_PLUS:.*]] = cir.unary(plus, %[[A_REAL]]) : !cir.float, !cir.float
1075+
// CIR: %[[A_IMAG_PLUS:.*]] = cir.unary(plus, %[[A_IMAG]]) : !cir.float, !cir.float
1076+
// CIR: %[[RESULT:.*]] = cir.complex.create %[[A_REAL_PLUS]], %[[A_IMAG_PLUS]] : !cir.float -> !cir.complex<!cir.float>
1077+
// CIR: %[[RESULT_IMAG:.*]] = cir.complex.imag %[[RESULT]] : !cir.complex<!cir.float> -> !cir.float
1078+
// CIR: cir.store{{.*}} %[[RESULT_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
1079+
1080+
// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
1081+
// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4
1082+
// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
1083+
// LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0
1084+
// LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1
1085+
// LLVM: %[[TMP_RESULT:.*]] = insertvalue { float, float } {{.*}}, float %[[A_REAL]], 0
1086+
// LLVM: %[[RESULT:.*]] = insertvalue { float, float } %[[TMP_RESULT]], float %[[A_IMAG]], 1
1087+
// LLVM: store float %[[A_IMAG]], ptr %[[B_ADDR]], align 4
1088+
1089+
// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
1090+
// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
1091+
// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
1092+
// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
1093+
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
1094+
// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
1095+
// OGCG: store float %[[A_IMAG]], ptr %[[B_ADDR]], align 4

0 commit comments

Comments
 (0)