// -----
-def SPV_UDivOp : SPV_ArithmeticBinaryOp<"UDiv", SPV_Integer, []> {
+def SPV_UDivOp : SPV_ArithmeticBinaryOp<"UDiv", SPV_Integer, [UnsignedOp]> {
let summary = "Unsigned-integer division of Operand 1 divided by Operand 2.";
let description = [{
// -----
-def SPV_UModOp : SPV_ArithmeticBinaryOp<"UMod", SPV_Integer> {
+def SPV_UModOp : SPV_ArithmeticBinaryOp<"UMod", SPV_Integer, [UnsignedOp]> {
let summary = "Unsigned modulo operation of Operand 1 modulo Operand 2.";
let description = [{
// -----
-def SPV_AtomicUMaxOp : SPV_AtomicUpdateWithValueOp<"AtomicUMax", []> {
+def SPV_AtomicUMaxOp : SPV_AtomicUpdateWithValueOp<"AtomicUMax", [UnsignedOp]> {
let summary = [{
Perform the following steps atomically with respect to any other atomic
accesses within Scope to the same location:
// -----
-def SPV_AtomicUMinOp : SPV_AtomicUpdateWithValueOp<"AtomicUMin", []> {
+def SPV_AtomicUMinOp : SPV_AtomicUpdateWithValueOp<"AtomicUMin", [UnsignedOp]> {
let summary = [{
Perform the following steps atomically with respect to any other atomic
accesses within Scope to the same location:
"op must appear in a module-like op's block",
CPred<"isDirectInModuleLikeOp($_op.getParentOp())">>;
+def UnsignedOp : NativeOpTrait<"spirv::UnsignedOp">;
+
//===----------------------------------------------------------------------===//
// SPIR-V opcode specification
//===----------------------------------------------------------------------===//
// -----
-def SPV_BitFieldUExtractOp : SPV_BitFieldExtractOp<"BitFieldUExtract", []> {
+def SPV_BitFieldUExtractOp : SPV_BitFieldExtractOp<"BitFieldUExtract",
+ [UnsignedOp]> {
let summary = "Extract a bit field from an object, without sign extension.";
let description = [{
// -----
-def SPV_ConvertUToFOp : SPV_CastOp<"ConvertUToF", SPV_Float, SPV_Integer, []> {
+def SPV_ConvertUToFOp : SPV_CastOp<"ConvertUToF",
+ SPV_Float,
+ SPV_Integer,
+ [UnsignedOp]> {
let summary = [{
Convert value numerically from unsigned integer to floating point.
}];
// -----
-def SPV_UConvertOp : SPV_CastOp<"UConvert", SPV_Integer, SPV_Integer, []> {
+def SPV_UConvertOp : SPV_CastOp<"UConvert",
+ SPV_Integer,
+ SPV_Integer,
+ [UnsignedOp]> {
let summary = [{
Convert unsigned width. This is either a truncate or a zero extend.
}];
// -----
-def SPV_UGreaterThanOp : SPV_LogicalBinaryOp<"UGreaterThan", SPV_Integer, []> {
+def SPV_UGreaterThanOp : SPV_LogicalBinaryOp<"UGreaterThan",
+ SPV_Integer,
+ [UnsignedOp]> {
let summary = [{
Unsigned-integer comparison if Operand 1 is greater than Operand 2.
}];
// -----
-def SPV_UGreaterThanEqualOp : SPV_LogicalBinaryOp<"UGreaterThanEqual", SPV_Integer, []> {
+def SPV_UGreaterThanEqualOp : SPV_LogicalBinaryOp<"UGreaterThanEqual",
+ SPV_Integer,
+ [UnsignedOp]> {
let summary = [{
Unsigned-integer comparison if Operand 1 is greater than or equal to
Operand 2.
// -----
-def SPV_ULessThanOp : SPV_LogicalBinaryOp<"ULessThan", SPV_Integer, []> {
+def SPV_ULessThanOp : SPV_LogicalBinaryOp<"ULessThan",
+ SPV_Integer,
+ [UnsignedOp]> {
let summary = [{
Unsigned-integer comparison if Operand 1 is less than Operand 2.
}];
// -----
def SPV_ULessThanEqualOp :
- SPV_LogicalBinaryOp<"ULessThanEqual", SPV_Integer, []> {
+ SPV_LogicalBinaryOp<"ULessThanEqual", SPV_Integer, [UnsignedOp]> {
let summary = [{
Unsigned-integer comparison if Operand 1 is less than or equal to
Operand 2.
// -----
def SPV_GroupNonUniformUMaxOp :
- SPV_GroupNonUniformArithmeticOp<"GroupNonUniformUMax", SPV_Integer, []> {
+ SPV_GroupNonUniformArithmeticOp<"GroupNonUniformUMax",
+ SPV_Integer,
+ [UnsignedOp]> {
let summary = [{
An unsigned integer maximum group operation of all Value operands
contributed by active invocations in the group.
// -----
def SPV_GroupNonUniformUMinOp :
- SPV_GroupNonUniformArithmeticOp<"GroupNonUniformUMin", SPV_Integer, []> {
+ SPV_GroupNonUniformArithmeticOp<"GroupNonUniformUMin",
+ SPV_Integer,
+ [UnsignedOp]> {
let summary = [{
An unsigned integer minimum group operation of all Value operands
contributed by active invocations in the group.
--- /dev/null
+//===- SPIRVOps.h - MLIR SPIR-V operation traits ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares C++ classes for some of operation traits in the SPIR-V
+// dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_SPIRV_IR_SPIRVOPTRAITS_H_
+#define MLIR_DIALECT_SPIRV_IR_SPIRVOPTRAITS_H_
+
+#include "mlir/IR/OpDefinition.h"
+
+namespace mlir {
+namespace OpTrait {
+namespace spirv {
+
+template <typename ConcreteType>
+class UnsignedOp : public TraitBase<ConcreteType, UnsignedOp> {};
+
+} // namespace spirv
+} // namespace OpTrait
+} // namespace mlir
+
+#endif // MLIR_DIALECT_SPIRV_IR_SPIRVOPTRAITS_H_
#ifndef MLIR_DIALECT_SPIRV_IR_SPIRVOPS_H_
#define MLIR_DIALECT_SPIRV_IR_SPIRVOPS_H_
+#include "mlir/Dialect/SPIRV/IR/SPIRVOpTraits.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVTypes.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
offset);
}
-/// Returns true if the operator is operating on unsigned integers.
-/// TODO: Have a TreatOperandsAsUnsignedInteger trait and bake the information
-/// to the ops themselves.
-template <typename SPIRVOp>
-bool isUnsignedOp() {
- return false;
-}
-
-#define CHECK_UNSIGNED_OP(SPIRVOp) \
- template <> \
- bool isUnsignedOp<SPIRVOp>() { \
- return true; \
- }
-
-CHECK_UNSIGNED_OP(spirv::AtomicUMaxOp)
-CHECK_UNSIGNED_OP(spirv::AtomicUMinOp)
-CHECK_UNSIGNED_OP(spirv::BitFieldUExtractOp)
-CHECK_UNSIGNED_OP(spirv::ConvertUToFOp)
-CHECK_UNSIGNED_OP(spirv::GroupNonUniformUMaxOp)
-CHECK_UNSIGNED_OP(spirv::GroupNonUniformUMinOp)
-CHECK_UNSIGNED_OP(spirv::UConvertOp)
-CHECK_UNSIGNED_OP(spirv::UDivOp)
-CHECK_UNSIGNED_OP(spirv::UGreaterThanEqualOp)
-CHECK_UNSIGNED_OP(spirv::UGreaterThanOp)
-CHECK_UNSIGNED_OP(spirv::ULessThanEqualOp)
-CHECK_UNSIGNED_OP(spirv::ULessThanOp)
-CHECK_UNSIGNED_OP(spirv::UModOp)
-
-#undef CHECK_UNSIGNED_OP
-
/// Returns true if the allocations of type `t` can be lowered to SPIR-V.
static bool isAllocationSupported(MemRefType t) {
// Currently only support workgroup local memory allocations with static
auto dstType = this->typeConverter.convertType(operation.getType());
if (!dstType)
return failure();
- if (isUnsignedOp<SPIRVOp>() && dstType != operation.getType()) {
+ if (SPIRVOp::template hasTrait<OpTrait::spirv::UnsignedOp>() &&
+ dstType != operation.getType()) {
return operation.emitError(
"bitwidth emulation is not implemented yet on unsigned op");
}
switch (cmpIOp.getPredicate()) {
#define DISPATCH(cmpPredicate, spirvOp) \
case cmpPredicate: \
- if (isUnsignedOp<spirvOp>() && \
+ if (spirvOp::template hasTrait<OpTrait::spirv::UnsignedOp>() && \
operandType != this->typeConverter.convertType(operandType)) { \
return cmpIOp.emitError( \
"bitwidth emulation is not implemented yet on unsigned op"); \