Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -582,14 +582,17 @@ 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",
"unary operation kind",
[UnaryOpKind_Inc,
UnaryOpKind_Dec,
UnaryOpKind_Plus,
UnaryOpKind_Minus]> {
UnaryOpKind_Minus,
UnaryOpKind_Not,
]> {
let cppNamespace = "::mlir::cir";
}

Expand All @@ -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
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,12 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
return Visit(E->getSubExpr());
}

mlir::Value VisitUnaryNot(const UnaryOperator *E) { llvm_unreachable("NYI"); }
mlir::Value VisitUnaryNot(const UnaryOperator *E) {
Copy link
Member

Choose a reason for hiding this comment

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

Any specific reason on why not following LLVM's codegen? We usually try to match the skeleton as much as possible. Any reason why this wouldn't work?

Value *ScalarExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
  TestAndClearIgnoreResultAssign();
  auto op = Visit(E->getSubExpr());
  // return buildUnaryOp ....
}

TestAndClearIgnoreResultAssign();
mlir::Value op = Visit(E->getSubExpr());
return buildUnaryOp(E, mlir::cir::UnaryOpKind::Not, op);
}

mlir::Value VisitUnaryLNot(const UnaryOperator *E) {
llvm_unreachable("NYI");
}
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
10 changes: 9 additions & 1 deletion clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@
#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"
#include "mlir/Target/LLVMIR/Export.h"
#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"

Expand Down Expand Up @@ -495,6 +496,13 @@ class CIRUnaryOpLowering
op.getInput());
break;
}
case mlir::cir::UnaryOpKind::Not: {
auto MinusOne = rewriter.create<mlir::LLVM::ConstantOp>(
op.getLoc(), type, mlir::IntegerAttr::get(type, -1));
rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, op.getType(), MinusOne,
op.getInput());
break;
}
}

return mlir::LogicalResult::success();
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,13 @@ class CIRUnaryOpLowering : public mlir::OpRewritePattern<mlir::cir::UnaryOp> {
op.getInput());
break;
}
case mlir::cir::UnaryOpKind::Not: {
auto MinusOne = rewriter.create<mlir::arith::ConstantOp>(
op.getLoc(), type, mlir::IntegerAttr::get(type, -1));
rewriter.replaceOpWithNewOp<mlir::arith::XOrIOp>(op, op.getType(),
MinusOne, op.getInput());
break;
}
}

return mlir::LogicalResult::success();
Expand Down
12 changes: 12 additions & 0 deletions clang/test/CIR/CodeGen/unary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <i32>, ["__retval"]
// CHECK: %[[#A:]] = cir.alloca i32, cir.ptr <i32>, ["a", init]
// CHECK: %[[#INPUT:]] = cir.load %[[#A]]
// CHECK: %[[#OUTPUT:]] = cir.unary(not, %[[#INPUT]])
// CHECK: cir.store %[[#OUTPUT]], %[[#RET]]
22 changes: 22 additions & 0 deletions clang/test/CIR/Lowering/unary-not.cir
Original file line number Diff line number Diff line change
@@ -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 <i32>, ["__retval"] {alignment = 4 : i64}
%1 = cir.alloca i32, cir.ptr <i32>, ["a", init] {alignment = 4 : i64}
%2 = cir.cst(1 : i32) : i32
cir.store %2, %1 : i32, cir.ptr <i32>
%3 = cir.load %1 : cir.ptr <i32>, i32
%4 = cir.unary(not, %3) : i32, i32
cir.store %4, %0 : i32, cir.ptr <i32>
%5 = cir.load %0 : cir.ptr <i32>, i32
cir.return %5 : i32
}
}

// MLIR: = llvm.load
// MLIR: = llvm.mlir.constant(-1 : i32)
// MLIR: = llvm.xor

// LLVM: = xor i32 -1, %[[#]]