return elementType.getIntOrFloatBitWidth();
}
+/// Creates `IntegerAttribute` with all bits set for given type.
+IntegerAttr minusOneIntegerAttribute(Type type, Builder builder) {
+ if (auto vecType = type.dyn_cast<VectorType>()) {
+ auto integerType = vecType.getElementType().cast<IntegerType>();
+ return builder.getIntegerAttr(integerType, -1);
+ }
+ auto integerType = type.cast<IntegerType>();
+ return builder.getIntegerAttr(integerType, -1);
+}
+
//===----------------------------------------------------------------------===//
// Operation conversion
//===----------------------------------------------------------------------===//
}
};
+/// Converts `spv.Not` and `spv.LogicalNot` into LLVM dialect.
+template <typename SPIRVOp>
+class NotPattern : public SPIRVToLLVMConversion<SPIRVOp> {
+public:
+ using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
+
+ LogicalResult
+ matchAndRewrite(SPIRVOp notOp, ArrayRef<Value> operands,
+ ConversionPatternRewriter &rewriter) const override {
+
+ auto srcType = notOp.getType();
+ auto dstType = this->typeConverter.convertType(srcType);
+ if (!dstType)
+ return failure();
+
+ Location loc = notOp.getLoc();
+ IntegerAttr minusOne = minusOneIntegerAttribute(srcType, rewriter);
+ auto mask = srcType.template isa<VectorType>()
+ ? rewriter.create<LLVM::ConstantOp>(
+ loc, dstType,
+ SplatElementsAttr::get(
+ srcType.template cast<VectorType>(), minusOne))
+ : rewriter.create<LLVM::ConstantOp>(loc, dstType, minusOne);
+ rewriter.template replaceOpWithNewOp<LLVM::XOrOp>(notOp, dstType,
+ notOp.operand(), mask);
+ return success();
+ }
+};
+
class ReturnPattern : public SPIRVToLLVMConversion<spirv::ReturnOp> {
public:
using SPIRVToLLVMConversion<spirv::ReturnOp>::SPIRVToLLVMConversion;
DirectConversionPattern<spirv::BitwiseAndOp, LLVM::AndOp>,
DirectConversionPattern<spirv::BitwiseOrOp, LLVM::OrOp>,
DirectConversionPattern<spirv::BitwiseXorOp, LLVM::XOrOp>,
+ NotPattern<spirv::NotOp>,
// Cast ops
DirectConversionPattern<spirv::ConvertFToSOp, LLVM::FPToSIOp>,
DirectConversionPattern<spirv::LogicalOrOp, LLVM::OrOp>,
IComparePattern<spirv::LogicalEqualOp, LLVM::ICmpPredicate::eq>,
IComparePattern<spirv::LogicalNotEqualOp, LLVM::ICmpPredicate::ne>,
+ NotPattern<spirv::LogicalNotOp>,
// Shift ops
ShiftPattern<spirv::ShiftRightArithmeticOp, LLVM::AShrOp>,
%0 = spv.BitwiseXor %arg0, %arg1 : vector<2xi16>
return
}
+
+//===----------------------------------------------------------------------===//
+// spv.Not
+//===----------------------------------------------------------------------===//
+
+func @not__scalar(%arg0: i32) {
+ // CHECK: %[[CONST:.*]] = llvm.mlir.constant(-1 : i32) : !llvm.i32
+ // CHECK: %{{.*}} = llvm.xor %{{.*}}, %[[CONST]] : !llvm.i32
+ %0 = spv.Not %arg0 : i32
+ return
+}
+
+func @not_vector(%arg0: vector<2xi16>) {
+ // CHECK: %[[CONST:.*]] = llvm.mlir.constant(dense<-1> : vector<2xi16>) : !llvm<"<2 x i16>">
+ // CHECK: %{{.*}} = llvm.xor %{{.*}}, %[[CONST]] : !llvm<"<2 x i16>">
+ %0 = spv.Not %arg0 : vector<2xi16>
+ return
+}
}
//===----------------------------------------------------------------------===//
+// spv.LogicalNot
+//===----------------------------------------------------------------------===//
+
+func @logical_not__scalar(%arg0: i1) {
+ // CHECK: %[[CONST:.*]] = llvm.mlir.constant(true) : !llvm.i1
+ // CHECK: %{{.*}} = llvm.xor %{{.*}}, %[[CONST]] : !llvm.i1
+ %0 = spv.LogicalNot %arg0 : i1
+ return
+}
+
+func @logical_not_vector(%arg0: vector<4xi1>) {
+ // CHECK: %[[CONST:.*]] = llvm.mlir.constant(dense<true> : vector<4xi1>) : !llvm<"<4 x i1>">
+ // CHECK: %{{.*}} = llvm.xor %{{.*}}, %[[CONST]] : !llvm<"<4 x i1>">
+ %0 = spv.LogicalNot %arg0 : vector<4xi1>
+ return
+}
+
+//===----------------------------------------------------------------------===//
// spv.LogicalAnd
//===----------------------------------------------------------------------===//