diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 35bc806182ce..3b25ddd056f7 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -582,6 +582,7 @@ def UnaryOpKind_Inc : I32EnumAttrCase<"Inc", 1, "inc">; def UnaryOpKind_Dec : I32EnumAttrCase<"Dec", 2, "dec">; def UnaryOpKind_Plus : I32EnumAttrCase<"Plus", 3, "plus">; def UnaryOpKind_Minus : I32EnumAttrCase<"Minus", 4, "minus">; +def UnaryOpKind_Not : I32EnumAttrCase<"Not", 5, "not">; def UnaryOpKind : I32EnumAttr< "UnaryOpKind", @@ -589,7 +590,9 @@ def UnaryOpKind : I32EnumAttr< [UnaryOpKind_Inc, UnaryOpKind_Dec, UnaryOpKind_Plus, - UnaryOpKind_Minus]> { + UnaryOpKind_Minus, + UnaryOpKind_Not, + ]> { let cppNamespace = "::mlir::cir"; } @@ -600,7 +603,7 @@ def UnaryOp : CIR_Op<"unary", let summary = "Unary operations"; let description = [{ `cir.unary` performs the unary operation according to - the specified opcode kind: [inc, dec, plus, minus]. + the specified opcode kind: [inc, dec, plus, minus, not]. Note for inc and dec: the operation corresponds only to the addition/subtraction, its input is expect to come from a load diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 05ea5e177088..a477ee6d01bb 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -410,7 +410,12 @@ class ScalarExprEmitter : public StmtVisitor { return Visit(E->getSubExpr()); } - mlir::Value VisitUnaryNot(const UnaryOperator *E) { llvm_unreachable("NYI"); } + mlir::Value VisitUnaryNot(const UnaryOperator *E) { + TestAndClearIgnoreResultAssign(); + mlir::Value op = Visit(E->getSubExpr()); + return buildUnaryOp(E, mlir::cir::UnaryOpKind::Not, op); + } + mlir::Value VisitUnaryLNot(const UnaryOperator *E) { llvm_unreachable("NYI"); } diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index e340c0c1c234..5ca82de90a8a 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -1407,9 +1407,8 @@ LogicalResult UnaryOp::verify() { "to the same address as the input memory load"; } case cir::UnaryOpKind::Plus: - // Nothing to verify. - return success(); case cir::UnaryOpKind::Minus: + case cir::UnaryOpKind::Not: // Nothing to verify. return success(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index afca90a1cb58..4bf907e36a73 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -24,8 +24,8 @@ #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/SCF/Transforms/Passes.h" -#include "mlir/IR/IRMapping.h" #include "mlir/IR/BuiltinDialect.h" +#include "mlir/IR/IRMapping.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h" @@ -33,6 +33,7 @@ #include "mlir/Transforms/DialectConversion.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/Dialect/IR/CIROpsEnums.h" +#include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/Passes.h" #include "llvm/ADT/Sequence.h" @@ -495,6 +496,13 @@ class CIRUnaryOpLowering op.getInput()); break; } + case mlir::cir::UnaryOpKind::Not: { + auto MinusOne = rewriter.create( + op.getLoc(), type, mlir::IntegerAttr::get(type, -1)); + rewriter.replaceOpWithNewOp(op, op.getType(), MinusOne, + op.getInput()); + break; + } } return mlir::LogicalResult::success(); diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp index a622c2616a25..f26f69192596 100644 --- a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp +++ b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp @@ -248,6 +248,13 @@ class CIRUnaryOpLowering : public mlir::OpRewritePattern { op.getInput()); break; } + case mlir::cir::UnaryOpKind::Not: { + auto MinusOne = rewriter.create( + op.getLoc(), type, mlir::IntegerAttr::get(type, -1)); + rewriter.replaceOpWithNewOp(op, op.getType(), + MinusOne, op.getInput()); + break; + } } return mlir::LogicalResult::success(); diff --git a/clang/test/CIR/CodeGen/unary.cpp b/clang/test/CIR/CodeGen/unary.cpp index 8358e5976b46..7af75c6581e9 100644 --- a/clang/test/CIR/CodeGen/unary.cpp +++ b/clang/test/CIR/CodeGen/unary.cpp @@ -24,3 +24,15 @@ unsigned um0() { // CHECK: %[[#INPUT:]] = cir.load %[[#A]] // CHECK: %[[#OUTPUT:]] = cir.unary(minus, %[[#INPUT]]) // CHECK: cir.store %[[#OUTPUT]], %[[#RET]] + +unsigned un0() { + unsigned a = 1; + return ~a; // a ^ -1 , not +} + +// CHECK: cir.func @_Z3un0v() -> i32 { +// CHECK: %[[#RET:]] = cir.alloca i32, cir.ptr , ["__retval"] +// CHECK: %[[#A:]] = cir.alloca i32, cir.ptr , ["a", init] +// CHECK: %[[#INPUT:]] = cir.load %[[#A]] +// CHECK: %[[#OUTPUT:]] = cir.unary(not, %[[#INPUT]]) +// CHECK: cir.store %[[#OUTPUT]], %[[#RET]] diff --git a/clang/test/CIR/Lowering/unary-not.cir b/clang/test/CIR/Lowering/unary-not.cir new file mode 100644 index 000000000000..6ca263907ec2 --- /dev/null +++ b/clang/test/CIR/Lowering/unary-not.cir @@ -0,0 +1,22 @@ +// RUN: cir-tool %s -cir-to-llvm -o - | FileCheck %s -check-prefix=MLIR +// RUN: cir-tool %s -cir-to-llvm -o - | mlir-translate -mlir-to-llvmir | FileCheck %s -check-prefix=LLVM + +module { + cir.func @foo() -> i32 { + %0 = cir.alloca i32, cir.ptr , ["__retval"] {alignment = 4 : i64} + %1 = cir.alloca i32, cir.ptr , ["a", init] {alignment = 4 : i64} + %2 = cir.cst(1 : i32) : i32 + cir.store %2, %1 : i32, cir.ptr + %3 = cir.load %1 : cir.ptr , i32 + %4 = cir.unary(not, %3) : i32, i32 + cir.store %4, %0 : i32, cir.ptr + %5 = cir.load %0 : cir.ptr , i32 + cir.return %5 : i32 + } +} + +// MLIR: = llvm.load +// MLIR: = llvm.mlir.constant(-1 : i32) +// MLIR: = llvm.xor + +// LLVM: = xor i32 -1, %[[#]]