diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h index 1984ed8a7f068..eb7ddeb3bfc54 100644 --- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h +++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h @@ -53,6 +53,9 @@ bool isPointerWideType(mlir::Type type); struct Placeholder {}; using ReplacementItem = std::variant; +/// Determines whether \p type is a valid fundamental C++ type in EmitC. +bool isFundamentalType(mlir::Type type); + } // namespace emitc } // namespace mlir diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td index 9ecdb74f4d82e..c66c3824bcacd 100644 --- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td +++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td @@ -43,7 +43,11 @@ class EmitC_UnaryOp traits = []> : let extraClassDeclaration = [{ bool hasSideEffects() { - return false; + // If operand is fundamental type, the operation is pure. + if (isFundamentalType(getOperand().getType())) { + return false; + } + return true; } }]; } @@ -57,7 +61,18 @@ class EmitC_BinaryOp traits = []> : let extraClassDeclaration = [{ bool hasSideEffects() { - return false; + // If both operands are fundamental types, the operation is pure. + if (isFundamentalType(getOperand(0).getType()) + && isFundamentalType(getOperand(1).getType())) { + return false; + } + // Pointer arithmetic operations is pure. + if (isa(getOperand(0).getType()) + && (isFundamentalType(getOperand(1).getType()) || + isa(getOperand(1).getType()))) { + return false; + } + return true; } }]; } diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp index e602210c2dc6c..bb176d5fad808 100644 --- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp +++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp @@ -137,6 +137,11 @@ bool mlir::emitc::isPointerWideType(Type type) { type); } +bool mlir::emitc::isFundamentalType(Type type) { + return llvm::isa(type) || isPointerWideType(type) || + isSupportedIntegerType(type) || isSupportedFloatType(type); +} + /// Check that the type of the initial value is compatible with the operations /// result type. static LogicalResult verifyInitializationAttribute(Operation *op,