- Notifications
You must be signed in to change notification settings - Fork14.5k
[CIR] Upstream Unary Inc/Dec for ComplexType#149162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Conversation
llvmbot commentedJul 16, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) ChangesThis change adds support for unary inc/dec operators for ComplexType Patch is 20.30 KiB, truncated to 20.00 KiB below, full version:https://github.com/llvm/llvm-project/pull/149162.diff 4 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cppindex 6663f5ea1e758..3489e6d17332e 100644--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp@@ -56,6 +56,26 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { mlir::Value VisitParenExpr(ParenExpr *e); mlir::Value VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e);++ mlir::Value VisitPrePostIncDec(const UnaryOperator *e, bool isInc,+ bool isPre);++ mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {+ return VisitPrePostIncDec(e, false, false);+ }++ mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {+ return VisitPrePostIncDec(e, true, false);+ }++ mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {+ return VisitPrePostIncDec(e, false, true);+ }++ mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {+ return VisitPrePostIncDec(e, true, true);+ }+ mlir::Value VisitUnaryDeref(const Expr *e); mlir::Value VisitUnaryNot(const UnaryOperator *e);@@ -335,6 +355,12 @@ mlir::Value ComplexExprEmitter::VisitSubstNonTypeTemplateParmExpr( return Visit(e->getReplacement()); }+mlir::Value ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *e,+ bool isInc, bool isPre) {+ LValue lv = cgf.emitLValue(e->getSubExpr());+ return cgf.emitComplexPrePostIncDec(e, lv, isInc, isPre);+}+ mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); }@@ -423,6 +449,29 @@ mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) { return ComplexExprEmitter(*this).Visit(const_cast<Expr *>(e)); }+mlir::Value CIRGenFunction::emitComplexPrePostIncDec(const UnaryOperator *e,+ LValue lv, bool isInc,+ bool isPre) {+ mlir::Value inVal = emitLoadOfComplex(lv, e->getExprLoc());+ mlir::Location loc = getLoc(e->getExprLoc());+ auto opKind = isInc ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;+ mlir::Value incVal = builder.createUnaryOp(loc, opKind, inVal);++ // Store the updated result through the lvalue.+ emitStoreOfComplex(loc, incVal, lv, /*isInit=*/false);++ if (getLangOpts().OpenMP)+ cgm.errorNYI(loc, "emitComplexPrePostIncDec OpenMP");++ // If this is a postinc, return the value read from memory, otherwise use the+ // updated value.+ return isPre ? incVal : inVal;+}++mlir::Value CIRGenFunction::emitLoadOfComplex(LValue src, SourceLocation loc) {+ return ComplexExprEmitter(*this).emitLoadOfLValue(src, loc);+}+ void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit) { ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit);diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.hindex 3baabba5adfe1..9541f4f0725eb 100644--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h@@ -930,6 +930,9 @@ class CIRGenFunction : public CIRGenTypeCache { /// returning the result. mlir::Value emitComplexExpr(const Expr *e);+ mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv,+ bool isInc, bool isPre);+ LValue emitComplexAssignmentLValue(const BinaryOperator *e); void emitCompoundStmt(const clang::CompoundStmt &s);@@ -980,6 +983,9 @@ class CIRGenFunction : public CIRGenTypeCache { RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc);+ /// Load a complex number from the specified l-value.+ mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc);+ /// Given an expression that represents a value lvalue, this method emits /// the address of the lvalue, then loads the result as an rvalue, /// returning the rvalue.diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cppindex c708cf9d9fa61..8f848c7345610 100644--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp@@ -50,7 +50,8 @@ void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) { switch (opKind) { case cir::UnaryOpKind::Inc: case cir::UnaryOpKind::Dec:- llvm_unreachable("Complex unary Inc/Dec NYI");+ resultReal = builder.createUnaryOp(loc, opKind, operandReal);+ resultImag = operandImag; break; case cir::UnaryOpKind::Plus:diff --git a/clang/test/CIR/CodeGen/complex-unary.cpp b/clang/test/CIR/CodeGen/complex-unary.cppindex 33f3c2fa895d3..5f914e29fa142 100644--- a/clang/test/CIR/CodeGen/complex-unary.cpp+++ b/clang/test/CIR/CodeGen/complex-unary.cpp@@ -83,8 +83,204 @@ void foo2() { // OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 // OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1 // OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4-// OGCG: %[[A_IMAG_MINUS:.*]] = fneg float %[[A_IMAG]]+// OGCG: %[[A_IMAG_MINUS:.*]] = fneg float %[[A_IMAG]] // OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 0 // OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 1 // OGCG: store float %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4 // OGCG: store float %[[A_IMAG_MINUS]], ptr %[[RESULT_IMAG_PTR]], align 4++void foo3() {+ float _Complex a;+ float _Complex b = a++;+}++// CIR-BEFORE: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]+// CIR-BEFORE: %[[RESULT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]+// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>+// CIR-BEFORE: %[[COMPLEX_INC:.*]] = cir.unary(inc, %[[TMP]]) : !cir.complex<!cir.float>, !cir.complex<!cir.float>+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_INC]], %[[COMPLEX]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>+// CIR-BEFORE: cir.store{{.*}} %[[TMP]], %[[RESULT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>++// CIR-AFTER: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]+// CIR-AFTER: %[[RESULT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.float> -> !cir.float+// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!cir.float> -> !cir.float+// CIR-AFTER: %[[REAL_INC:.*]] = cir.unary(inc, %[[REAL]]) : !cir.float, !cir.float+// CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_INC]], %[[IMAG]] : !cir.float -> !cir.complex<!cir.float>+// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[COMPLEX]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>+// CIR-AFTER: cir.store{{.*}} %[[TMP]], %[[RESULT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>++// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4+// LLVM: %[[RESULT:.*]] = alloca { float, float }, i64 1, align 4+// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[COMPLEX]], align 4+// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0+// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1+// LLVM: %[[REAL_INC:.*]] = fadd float 1.000000e+00, %[[REAL]]+// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL_INC]], 0+// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG]], 1+// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[COMPLEX]], align 4+// LLVM: store { float, float } %[[TMP]], ptr %[[RESULT]], align 4++// OGCG: %[[COMPLEX:.*]] = alloca { float, float }, align 4+// OGCG: %[[RESULT:.*]] = alloca { float, float }, align 4+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0+// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1+// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4+// OGCG: %[[A_REAL_INC:.*]] = fadd float %[[A_REAL]], 1.000000e+00+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1+// OGCG: store float %[[A_REAL_INC]], ptr %[[A_REAL_PTR]], align 4+// OGCG: store float %[[A_IMAG]], ptr %[[A_IMAG_PTR]], align 4+// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 0+// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 1+// OGCG: store float %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4+// OGCG: store float %[[A_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4++void foo4() {+ float _Complex a;+ float _Complex b = ++a;+}++// CIR-BEFORE: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]+// CIR-BEFORE: %[[RESULT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]+// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>+// CIR-BEFORE: %[[COMPLEX_INC:.*]] = cir.unary(inc, %[[TMP]]) : !cir.complex<!cir.float>, !cir.complex<!cir.float>+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_INC]], %[[COMPLEX]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_INC]], %[[RESULT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>++// CIR-AFTER: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]+// CIR-AFTER: %[[RESULT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.float> -> !cir.float+// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!cir.float> -> !cir.float+// CIR-AFTER: %[[REAL_INC:.*]] = cir.unary(inc, %[[REAL]]) : !cir.float, !cir.float+// CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_INC]], %[[IMAG]] : !cir.float -> !cir.complex<!cir.float>+// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[COMPLEX]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>+// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[RESULT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>++// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4+// LLVM: %[[RESULT:.*]] = alloca { float, float }, i64 1, align 4+// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[COMPLEX]], align 4+// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0+// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1+// LLVM: %[[REAL_INC:.*]] = fadd float 1.000000e+00, %[[REAL]]+// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL_INC]], 0+// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG]], 1+// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[COMPLEX]], align 4+// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[RESULT]], align 4++// OGCG: %[[COMPLEX:.*]] = alloca { float, float }, align 4+// OGCG: %[[RESULT:.*]] = alloca { float, float }, align 4+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0+// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1+// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4+// OGCG: %[[A_REAL_INC:.*]] = fadd float %[[A_REAL]], 1.000000e+00+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1+// OGCG: store float %[[A_REAL_INC]], ptr %[[A_REAL_PTR]], align 4+// OGCG: store float %[[A_IMAG]], ptr %[[A_IMAG_PTR]], align 4+// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 0+// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 1+// OGCG: store float %[[A_REAL_INC]], ptr %[[RESULT_REAL_PTR]], align 4+// OGCG: store float %[[A_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4++void foo5() {+ float _Complex a;+ float _Complex b = a--;+}++// CIR-BEFORE: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]+// CIR-BEFORE: %[[RESULT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]+// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>+// CIR-BEFORE: %[[COMPLEX_DEC:.*]] = cir.unary(dec, %[[TMP]]) : !cir.complex<!cir.float>, !cir.complex<!cir.float>+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_DEC]], %[[COMPLEX]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>+// CIR-BEFORE: cir.store{{.*}} %[[TMP]], %[[RESULT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>++// CIR-AFTER: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]+// CIR-AFTER: %[[RESULT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.float> -> !cir.float+// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!cir.float> -> !cir.float+// CIR-AFTER: %[[REAL_DEC:.*]] = cir.unary(dec, %[[REAL]]) : !cir.float, !cir.float+// CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_DEC]], %[[IMAG]] : !cir.float -> !cir.complex<!cir.float>+// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[COMPLEX]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>+// CIR-AFTER: cir.store{{.*}} %[[TMP]], %[[RESULT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>++// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4+// LLVM: %[[RESULT:.*]] = alloca { float, float }, i64 1, align 4+// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[COMPLEX]], align 4+// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0+// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1+// LLVM: %[[REAL_DEC:.*]] = fadd float -1.000000e+00, %[[REAL]]+// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL_DEC]], 0+// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG]], 1+// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[COMPLEX]], align 4+// LLVM: store { float, float } %[[TMP]], ptr %[[RESULT]], align 4++// OGCG: %[[COMPLEX:.*]] = alloca { float, float }, align 4+// OGCG: %[[RESULT:.*]] = alloca { float, float }, align 4+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0+// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1+// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4+// OGCG: %[[A_REAL_DEC:.*]] = fadd float %[[A_REAL]], -1.000000e+00+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1+// OGCG: store float %[[A_REAL_DEC]], ptr %[[A_REAL_PTR]], align 4+// OGCG: store float %[[A_IMAG]], ptr %[[A_IMAG_PTR]], align 4+// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 0+// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 1+// OGCG: store float %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4+// OGCG: store float %[[A_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4++void foo6() {+ float _Complex a;+ float _Complex b = --a;+}++// CIR-BEFORE: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]+// CIR-BEFORE: %[[RESULT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]+// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>+// CIR-BEFORE: %[[COMPLEX_DEC:.*]] = cir.unary(dec, %[[TMP]]) : !cir.complex<!cir.float>, !cir.complex<!cir.float>+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_DEC]], %[[COMPLEX]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_DEC]], %[[RESULT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>++// CIR-AFTER: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]+// CIR-AFTER: %[[RESULT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init]+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.float> -> !cir.float+// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!cir.float> -> !cir.float+// CIR-AFTER: %[[REAL_DEC:.*]] = cir.unary(dec, %[[REAL]]) : !cir.float, !cir.float+// CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_DEC]], %[[IMAG]] : !cir.float -> !cir.complex<!cir.float>+// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[COMPLEX]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>+// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[RESULT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>++// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4+// LLVM: %[[RESULT:.*]] = alloca { float, float }, i64 1, align 4+// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[COMPLEX]], align 4+// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0+// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1+// LLVM: %[[REAL_DEC:.*]] = fadd float -1.000000e+00, %[[REAL]]+// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL_DEC]], 0+// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG]], 1+// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[COMPLEX]], align 4+// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[RESULT]], align 4++// OGCG: %[[COMPLEX:.*]] = alloca { float, float }, align 4+// OGCG: %[[RESULT:.*]] = alloca { float, float }, align 4+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0+// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1+// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4+// OGCG: %[[A_REAL_DEC:.*]] = fadd float %[[A_REAL]], -1.000000e+00+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1+// OGCG: store float %[[A_REAL_DEC]], ptr %[[A_REAL_PTR]], align 4+// OGCG: store float %[[A_IMAG]], ptr %[[A_IMAG_PTR]], align 4+// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inboun...[truncated] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This looks good, but I'm asking for changes to make the tests more readable.
// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4 | ||
// LLVM: %[[RESULT:.*]] = alloca { float, float }, i64 1, align 4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4 | |
// LLVM: %[[RESULT:.*]] = alloca { float, float }, i64 1, align 4 | |
// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 | |
// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4 |
This, along with other changes this imples, should make the checks more readable. And, of course, I'm suggesting this change throughout the new tests.
b84f72a
intollvm:mainUh oh!
There was an error while loading.Please reload this page.
mlir::Value VisitPrePostIncDec(const UnaryOperator *e, bool isInc, | ||
bool isPre); | ||
mlir::Value VisitUnaryPostDec(const UnaryOperator *e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I know this is already merged, but it would be nicer to passcir::UnaryOpKind
as second argument instead of ambiguous bool.@AmrDeveloper can you fix this in additional PR please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Sure, I will create another PR for it, Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I implemented it locally, but I was thinking that there are no checks on unary op, and anyone can call the function withcir::UnaryOpKind::Not, Minus or Plus
and it will generate CIR code that will crash only when we lower to LLVM 🤔, do you think this is the best option or maybe we should rename the booleans in a better way@xlauko
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
You can assert to expect inc/dec?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
You can assert to expect inc/dec?
Mmmmm, Yes, I will create a PR now
This change adds support for unary inc/dec operators for ComplexType
#141365