Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[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

Merged

Conversation

AmrDeveloper
Copy link
Member

This change adds support for unary inc/dec operators for ComplexType

#141365

@llvmbotllvmbot added clangClang issues not falling into any other category ClangIRAnything related to the ClangIR project labelsJul 16, 2025
@llvmbot
Copy link
Member

llvmbot commentedJul 16, 2025
edited
Loading

@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-clang

Author: Amr Hesham (AmrDeveloper)

Changes

This change adds support for unary inc/dec operators for ComplexType

#141365


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:

  • (modified) clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp (+49)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+6)
  • (modified) clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp (+2-1)
  • (modified) clang/test/CIR/CodeGen/complex-unary.cpp (+197-1)
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]

Copy link
Contributor

@andykaylorandykaylor left a 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.

Comment on lines 114 to 115
// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4
// LLVM: %[[RESULT:.*]] = alloca { float, float }, i64 1, align 4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
// 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.

@AmrDeveloperAmrDeveloper merged commitb84f72a intollvm:mainJul 17, 2025
9 checks passed
mlir::Value VisitPrePostIncDec(const UnaryOperator *e, bool isInc,
bool isPre);

mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {
Copy link
Contributor

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?

AmrDeveloper reacted with thumbs up emoji
Copy link
MemberAuthor

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

Copy link
MemberAuthor

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

Copy link
Contributor

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?

Copy link
MemberAuthor

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

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@xlaukoxlaukoxlauko left review comments

@andykaylorandykaylorandykaylor approved these changes

@lanzalanzaAwaiting requested review from lanzalanza is a code owner

@bcardosolopesbcardosolopesAwaiting requested review from bcardosolopesbcardosolopes is a code owner

Assignees
No one assigned
Labels
clangClang issues not falling into any other categoryClangIRAnything related to the ClangIR project
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

4 participants
@AmrDeveloper@llvmbot@xlauko@andykaylor

[8]ページ先頭

©2009-2025 Movatter.jp