- Notifications
You must be signed in to change notification settings - Fork14.5k
[CIR] Upstream unary not for ComplexType#148857
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
@llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) ChangesUpstream unary not for ComplexType Full diff:https://github.com/llvm/llvm-project/pull/148857.diff 5 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.hindex 277c278fd38b7..25baf278bba38 100644--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h@@ -129,6 +129,22 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); } cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); }+ mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,+ mlir::Value imag) {+ auto resultComplexTy = cir::ComplexType::get(real.getType());+ return create<cir::ComplexCreateOp>(loc, resultComplexTy, real, imag);+ }++ mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {+ auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());+ return create<cir::ComplexRealOp>(loc, operandTy.getElementType(), operand);+ }++ mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {+ auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());+ return create<cir::ComplexImagOp>(loc, operandTy.getElementType(), operand);+ }+ mlir::Value createNot(mlir::Value value) { return create<cir::UnaryOp>(value.getLoc(), value.getType(), cir::UnaryOpKind::Not, value);@@ -169,6 +185,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return create<cir::ContinueOp>(loc); }+ mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind,+ mlir::Value operand) {+ return create<cir::UnaryOp>(loc, kind, operand);+ }+ mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) { return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value)); }diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.hindex 5bd53ebc52ab5..f855bdad2d7c3 100644--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h@@ -348,22 +348,6 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return CIRBaseBuilderTy::createStore(loc, val, dst.getPointer(), align); }- mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,- mlir::Value imag) {- auto resultComplexTy = cir::ComplexType::get(real.getType());- return create<cir::ComplexCreateOp>(loc, resultComplexTy, real, imag);- }-- mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {- auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());- return create<cir::ComplexRealOp>(loc, operandTy.getElementType(), operand);- }-- mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {- auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());- return create<cir::ComplexImagOp>(loc, operandTy.getElementType(), operand);- }- /// Create a cir.complex.real_ptr operation that derives a pointer to the real /// part of the complex value pointed to by the specified pointer value. mlir::Value createComplexRealPtr(mlir::Location loc, mlir::Value value) {diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cppindex 3273d9000771a..6663f5ea1e758 100644--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp@@ -57,6 +57,7 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { mlir::Value VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e); mlir::Value VisitUnaryDeref(const Expr *e);+ mlir::Value VisitUnaryNot(const UnaryOperator *e); struct BinOpInfo { mlir::Location loc;@@ -338,6 +339,11 @@ mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); }+mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) {+ mlir::Value op = Visit(e->getSubExpr());+ return builder.createNot(op);+}+ mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e, QualType promotionTy) { e = e->IgnoreParens();diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cppindex 5493b86a0a321..788817006baa5 100644--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp@@ -8,7 +8,9 @@ #include "PassDetail.h" #include "clang/AST/ASTContext.h"+#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h" #include "clang/CIR/Dialect/IR/CIRDialect.h"+#include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/Passes.h" #include <memory>@@ -22,15 +24,68 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { void runOnOperation() override; void runOnOp(Operation *op);+ void lowerUnaryOp(UnaryOp op); }; } // namespace-void LoweringPreparePass::runOnOp(Operation *op) {}+void LoweringPreparePass::lowerUnaryOp(UnaryOp op) {+ mlir::Type ty = op.getType();+ if (!mlir::isa<cir::ComplexType>(ty))+ return;++ mlir::Location loc = op.getLoc();+ cir::UnaryOpKind opKind = op.getKind();++ CIRBaseBuilderTy builder(getContext());+ builder.setInsertionPointAfter(op);++ mlir::Value operand = op.getInput();+ mlir::Value operandReal = builder.createComplexReal(loc, operand);+ mlir::Value operandImag = builder.createComplexImag(loc, operand);++ mlir::Value resultReal;+ mlir::Value resultImag;++ switch (opKind) {+ case cir::UnaryOpKind::Inc:+ case cir::UnaryOpKind::Dec:+ llvm_unreachable("Complex unary Inc/Dec NYI");+ break;++ case cir::UnaryOpKind::Plus:+ case cir::UnaryOpKind::Minus:+ llvm_unreachable("Complex unary Plus/Minus NYI");+ break;++ case cir::UnaryOpKind::Not:+ resultReal = operandReal;+ resultImag =+ builder.createUnaryOp(loc, cir::UnaryOpKind::Minus, operandImag);+ break;+ }++ auto result = builder.createComplexCreate(loc, resultReal, resultImag);+ op.replaceAllUsesWith(result);+ op.erase();+}++void LoweringPreparePass::runOnOp(Operation *op) {+ if (auto unary = dyn_cast<UnaryOp>(op)) {+ lowerUnaryOp(unary);+ }+} void LoweringPreparePass::runOnOperation() {+ mlir::Operation *op = getOperation();+ llvm::SmallVector<Operation *> opsToTransform;+ op->walk([&](Operation *op) {+ if (isa<UnaryOp>(op))+ opsToTransform.push_back(op);+ });+ for (auto *o : opsToTransform) runOnOp(o); }diff --git a/clang/test/CIR/CodeGen/complex-unary.cpp b/clang/test/CIR/CodeGen/complex-unary.cppnew file mode 100644index 0000000000000..463c4dde47ed6--- /dev/null+++ b/clang/test/CIR/CodeGen/complex-unary.cpp@@ -0,0 +1,48 @@+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE %s+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-lowering-prepare -o %t.cir %s 2>&1 | FileCheck --check-prefixes=CIR-AFTER %s+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG++void foo() {+ int _Complex a;+ int _Complex b = ~a;+}++// CIR-BEFORE: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"]+// CIR-BEFORE: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]+// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>+// CIR-BEFORE: %[[COMPLEX_NOT:.*]] = cir.unary(not, %[[TMP]]) : !cir.complex<!s32i>, !cir.complex<!s32i>+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_NOT]], %[[RESULT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>++// CIR-AFTER: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"]+// CIR-AFTER: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!s32i> -> !s32i+// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!s32i> -> !s32i+// CIR-AFTER: %[[IMAG_MINUS:.*]] = cir.unary(minus, %[[IMAG]]) : !s32i, !s32i+// CIR-AFTER: %[[RESULT_VAL:.*]] = cir.complex.create %[[REAL]], %[[IMAG_MINUS]] : !s32i -> !cir.complex<!s32i>+// CIR-AFTER: cir.store{{.*}} %[[RESULT_VAL]], %[[RESULT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>++// LLVM: %[[COMPLEX:.*]] = alloca { i32, i32 }, i64 1, align 4+// LLVM: %[[RESULT:.*]] = alloca { i32, i32 }, i64 1, align 4+// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[COMPLEX]], align 4+// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %[[TMP]], 0+// LLVM: %[[IMAG:.*]] = extractvalue { i32, i32 } %[[TMP]], 1+// LLVM: %[[IMAG_MINUS:.*]] = sub i32 0, %[[IMAG]]+// LLVM: %[[RESULT_TMP:.*]] = insertvalue { i32, i32 } {{.*}}, i32 %[[REAL]], 0+// LLVM: %[[RESULT_VAL:.*]] = insertvalue { i32, i32 } %[[RESULT_TMP]], i32 %[[IMAG_MINUS]], 1+// LLVM: store { i32, i32 } %[[RESULT_VAL]], ptr %[[RESULT]], align 4++// OGCG: %[[COMPLEX:.*]] = alloca { i32, i32 }, align 4+// OGCG: %[[RESULT:.*]] = alloca { i32, i32 }, align 4+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 0+// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 1+// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4+// OGCG: %[[A_IMAG_MINUS:.*]] = sub i32 0, %[[A_IMAG]]+// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 0+// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 1+// OGCG: store i32 %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4+// OGCG: store i32 %[[A_IMAG_MINUS]], ptr %[[RESULT_IMAG_PTR]], align 4 |
@llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) ChangesUpstream unary not for ComplexType Full diff:https://github.com/llvm/llvm-project/pull/148857.diff 5 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.hindex 277c278fd38b7..25baf278bba38 100644--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h@@ -129,6 +129,22 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); } cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); }+ mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,+ mlir::Value imag) {+ auto resultComplexTy = cir::ComplexType::get(real.getType());+ return create<cir::ComplexCreateOp>(loc, resultComplexTy, real, imag);+ }++ mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {+ auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());+ return create<cir::ComplexRealOp>(loc, operandTy.getElementType(), operand);+ }++ mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {+ auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());+ return create<cir::ComplexImagOp>(loc, operandTy.getElementType(), operand);+ }+ mlir::Value createNot(mlir::Value value) { return create<cir::UnaryOp>(value.getLoc(), value.getType(), cir::UnaryOpKind::Not, value);@@ -169,6 +185,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return create<cir::ContinueOp>(loc); }+ mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind,+ mlir::Value operand) {+ return create<cir::UnaryOp>(loc, kind, operand);+ }+ mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) { return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value)); }diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.hindex 5bd53ebc52ab5..f855bdad2d7c3 100644--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h@@ -348,22 +348,6 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return CIRBaseBuilderTy::createStore(loc, val, dst.getPointer(), align); }- mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,- mlir::Value imag) {- auto resultComplexTy = cir::ComplexType::get(real.getType());- return create<cir::ComplexCreateOp>(loc, resultComplexTy, real, imag);- }-- mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {- auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());- return create<cir::ComplexRealOp>(loc, operandTy.getElementType(), operand);- }-- mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {- auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());- return create<cir::ComplexImagOp>(loc, operandTy.getElementType(), operand);- }- /// Create a cir.complex.real_ptr operation that derives a pointer to the real /// part of the complex value pointed to by the specified pointer value. mlir::Value createComplexRealPtr(mlir::Location loc, mlir::Value value) {diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cppindex 3273d9000771a..6663f5ea1e758 100644--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp@@ -57,6 +57,7 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { mlir::Value VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e); mlir::Value VisitUnaryDeref(const Expr *e);+ mlir::Value VisitUnaryNot(const UnaryOperator *e); struct BinOpInfo { mlir::Location loc;@@ -338,6 +339,11 @@ mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); }+mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) {+ mlir::Value op = Visit(e->getSubExpr());+ return builder.createNot(op);+}+ mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e, QualType promotionTy) { e = e->IgnoreParens();diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cppindex 5493b86a0a321..788817006baa5 100644--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp@@ -8,7 +8,9 @@ #include "PassDetail.h" #include "clang/AST/ASTContext.h"+#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h" #include "clang/CIR/Dialect/IR/CIRDialect.h"+#include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/Passes.h" #include <memory>@@ -22,15 +24,68 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { void runOnOperation() override; void runOnOp(Operation *op);+ void lowerUnaryOp(UnaryOp op); }; } // namespace-void LoweringPreparePass::runOnOp(Operation *op) {}+void LoweringPreparePass::lowerUnaryOp(UnaryOp op) {+ mlir::Type ty = op.getType();+ if (!mlir::isa<cir::ComplexType>(ty))+ return;++ mlir::Location loc = op.getLoc();+ cir::UnaryOpKind opKind = op.getKind();++ CIRBaseBuilderTy builder(getContext());+ builder.setInsertionPointAfter(op);++ mlir::Value operand = op.getInput();+ mlir::Value operandReal = builder.createComplexReal(loc, operand);+ mlir::Value operandImag = builder.createComplexImag(loc, operand);++ mlir::Value resultReal;+ mlir::Value resultImag;++ switch (opKind) {+ case cir::UnaryOpKind::Inc:+ case cir::UnaryOpKind::Dec:+ llvm_unreachable("Complex unary Inc/Dec NYI");+ break;++ case cir::UnaryOpKind::Plus:+ case cir::UnaryOpKind::Minus:+ llvm_unreachable("Complex unary Plus/Minus NYI");+ break;++ case cir::UnaryOpKind::Not:+ resultReal = operandReal;+ resultImag =+ builder.createUnaryOp(loc, cir::UnaryOpKind::Minus, operandImag);+ break;+ }++ auto result = builder.createComplexCreate(loc, resultReal, resultImag);+ op.replaceAllUsesWith(result);+ op.erase();+}++void LoweringPreparePass::runOnOp(Operation *op) {+ if (auto unary = dyn_cast<UnaryOp>(op)) {+ lowerUnaryOp(unary);+ }+} void LoweringPreparePass::runOnOperation() {+ mlir::Operation *op = getOperation();+ llvm::SmallVector<Operation *> opsToTransform;+ op->walk([&](Operation *op) {+ if (isa<UnaryOp>(op))+ opsToTransform.push_back(op);+ });+ for (auto *o : opsToTransform) runOnOp(o); }diff --git a/clang/test/CIR/CodeGen/complex-unary.cpp b/clang/test/CIR/CodeGen/complex-unary.cppnew file mode 100644index 0000000000000..463c4dde47ed6--- /dev/null+++ b/clang/test/CIR/CodeGen/complex-unary.cpp@@ -0,0 +1,48 @@+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE %s+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-lowering-prepare -o %t.cir %s 2>&1 | FileCheck --check-prefixes=CIR-AFTER %s+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG++void foo() {+ int _Complex a;+ int _Complex b = ~a;+}++// CIR-BEFORE: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"]+// CIR-BEFORE: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]+// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>+// CIR-BEFORE: %[[COMPLEX_NOT:.*]] = cir.unary(not, %[[TMP]]) : !cir.complex<!s32i>, !cir.complex<!s32i>+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_NOT]], %[[RESULT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>++// CIR-AFTER: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"]+// CIR-AFTER: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init]+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!s32i> -> !s32i+// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!s32i> -> !s32i+// CIR-AFTER: %[[IMAG_MINUS:.*]] = cir.unary(minus, %[[IMAG]]) : !s32i, !s32i+// CIR-AFTER: %[[RESULT_VAL:.*]] = cir.complex.create %[[REAL]], %[[IMAG_MINUS]] : !s32i -> !cir.complex<!s32i>+// CIR-AFTER: cir.store{{.*}} %[[RESULT_VAL]], %[[RESULT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>++// LLVM: %[[COMPLEX:.*]] = alloca { i32, i32 }, i64 1, align 4+// LLVM: %[[RESULT:.*]] = alloca { i32, i32 }, i64 1, align 4+// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[COMPLEX]], align 4+// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %[[TMP]], 0+// LLVM: %[[IMAG:.*]] = extractvalue { i32, i32 } %[[TMP]], 1+// LLVM: %[[IMAG_MINUS:.*]] = sub i32 0, %[[IMAG]]+// LLVM: %[[RESULT_TMP:.*]] = insertvalue { i32, i32 } {{.*}}, i32 %[[REAL]], 0+// LLVM: %[[RESULT_VAL:.*]] = insertvalue { i32, i32 } %[[RESULT_TMP]], i32 %[[IMAG_MINUS]], 1+// LLVM: store { i32, i32 } %[[RESULT_VAL]], ptr %[[RESULT]], align 4++// OGCG: %[[COMPLEX:.*]] = alloca { i32, i32 }, align 4+// OGCG: %[[RESULT:.*]] = alloca { i32, i32 }, align 4+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 0+// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX]], i32 0, i32 1+// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4+// OGCG: %[[A_IMAG_MINUS:.*]] = sub i32 0, %[[A_IMAG]]+// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 0+// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 1+// OGCG: store i32 %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4+// OGCG: store i32 %[[A_IMAG_MINUS]], ptr %[[RESULT_IMAG_PTR]], align 4 |
}; | ||
} // namespace | ||
void LoweringPreparePass::runOnOp(Operation *op) {} | ||
void LoweringPreparePass::lowerUnaryOp(UnaryOp op) { |
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.
voidLoweringPreparePass::lowerUnaryOp(UnaryOp op) { | |
voidLoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) { |
op.erase(); | ||
} | ||
void LoweringPreparePass::runOnOp(Operation *op) { |
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.
voidLoweringPreparePass::runOnOp(Operation *op) { | |
voidLoweringPreparePass::runOnOp(mlir::Operation *op) { |
if (auto unary = dyn_cast<UnaryOp>(op)) { | ||
lowerUnaryOp(unary); | ||
} |
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.
if (auto unary = dyn_cast<UnaryOp>(op)) { | |
lowerUnaryOp(unary); | |
} | |
if (auto unary = mlir::dyn_cast<cir::UnaryOp>(op)) | |
lowerUnaryOp(unary); |
llvm::SmallVector<Operation *> opsToTransform; | ||
op->walk([&](Operation *op) { | ||
if (isa<UnaryOp>(op)) |
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.
if (isa<UnaryOp>(op)) | |
if (mlir::isa<cir::UnaryOp>(op)) |
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.
lgtm, with one nit about the test
// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[COMPLEX]], align 4 | ||
// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %[[TMP]], 0 | ||
// LLVM: %[[IMAG:.*]] = extractvalue { i32, i32 } %[[TMP]], 1 | ||
// LLVM: %[[IMAG_MINUS:.*]] = sub i32 0, %[[IMAG]] |
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.
Can you add a test case forfloat _Complex
(or even just replace this one)? For floating point types, we should get anfneg
rather thanfsub 0, i
here. It's a subtle but important difference.
bd0f9dd
intollvm:mainUh oh!
There was an error while loading.Please reload this page.
Upstream unary not for ComplexType
#141365