brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.1 KiB · fcf4eb6 Raw
297 lines · cpp
1//===- CastOps.cpp - MLIR SPIR-V Cast Ops  --------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Defines the cast and conversion operations in the SPIR-V dialect.10//11//===----------------------------------------------------------------------===//12 13#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"14 15#include "SPIRVOpUtils.h"16#include "SPIRVParsingUtils.h"17 18#include "llvm/ADT/TypeSwitch.h"19 20using namespace mlir::spirv::AttrNames;21 22namespace mlir::spirv {23 24static LogicalResult verifyCastOp(Operation *op,25                                  bool requireSameBitWidth = true,26                                  bool skipBitWidthCheck = false) {27  // Some CastOps have no limit on bit widths for result and operand type.28  if (skipBitWidthCheck)29    return success();30 31  Type operandType = op->getOperand(0).getType();32  Type resultType = op->getResult(0).getType();33 34  // ODS checks that result type and operand type have the same shape. Check35  // that composite types match and extract the element types, if any.36  using TypePair = std::pair<Type, Type>;37  auto [operandElemTy, resultElemTy] =38      TypeSwitch<Type, TypePair>(operandType)39          .Case<VectorType, spirv::CooperativeMatrixType>(40              [resultType](auto concreteOperandTy) -> TypePair {41                if (auto concreteResultTy =42                        dyn_cast<decltype(concreteOperandTy)>(resultType)) {43                  return {concreteOperandTy.getElementType(),44                          concreteResultTy.getElementType()};45                }46                return {};47              })48          .Default([resultType](Type operandType) -> TypePair {49            return {operandType, resultType};50          });51 52  if (!operandElemTy || !resultElemTy)53    return op->emitOpError("incompatible operand and result types");54 55  unsigned operandTypeBitWidth = operandElemTy.getIntOrFloatBitWidth();56  unsigned resultTypeBitWidth = resultElemTy.getIntOrFloatBitWidth();57  bool isSameBitWidth = operandTypeBitWidth == resultTypeBitWidth;58 59  if (requireSameBitWidth) {60    if (!isSameBitWidth) {61      return op->emitOpError(62                 "expected the same bit widths for operand type and result "63                 "type, but provided ")64             << operandElemTy << " and " << resultElemTy;65    }66    return success();67  }68 69  if (isSameBitWidth) {70    return op->emitOpError(71               "expected the different bit widths for operand type and result "72               "type, but provided ")73           << operandElemTy << " and " << resultElemTy;74  }75  return success();76}77 78//===----------------------------------------------------------------------===//79// spirv.BitcastOp80//===----------------------------------------------------------------------===//81 82LogicalResult BitcastOp::verify() {83  // TODO: The SPIR-V spec validation rules are different for different84  // versions.85  auto operandType = getOperand().getType();86  auto resultType = getResult().getType();87  if (operandType == resultType) {88    return emitError("result type must be different from operand type");89  }90  if (llvm::isa<spirv::PointerType>(operandType) &&91      !llvm::isa<spirv::PointerType>(resultType)) {92    return emitError(93        "unhandled bit cast conversion from pointer type to non-pointer type");94  }95  if (!llvm::isa<spirv::PointerType>(operandType) &&96      llvm::isa<spirv::PointerType>(resultType)) {97    return emitError(98        "unhandled bit cast conversion from non-pointer type to pointer type");99  }100  auto operandBitWidth = getBitWidth(operandType);101  auto resultBitWidth = getBitWidth(resultType);102  if (operandBitWidth != resultBitWidth) {103    return emitOpError("mismatch in result type bitwidth ")104           << resultBitWidth << " and operand type bitwidth "105           << operandBitWidth;106  }107  return success();108}109 110//===----------------------------------------------------------------------===//111// spirv.ConvertPtrToUOp112//===----------------------------------------------------------------------===//113 114LogicalResult ConvertPtrToUOp::verify() {115  auto operandType = llvm::cast<spirv::PointerType>(getPointer().getType());116  auto resultType = llvm::cast<spirv::ScalarType>(getResult().getType());117  if (!resultType || !resultType.isSignlessInteger())118    return emitError("result must be a scalar type of unsigned integer");119  auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>();120  if (!spirvModule)121    return success();122  auto addressingModel = spirvModule.getAddressingModel();123  if ((addressingModel == spirv::AddressingModel::Logical) ||124      (addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64 &&125       operandType.getStorageClass() !=126           spirv::StorageClass::PhysicalStorageBuffer))127    return emitError("operand must be a physical pointer");128  return success();129}130 131//===----------------------------------------------------------------------===//132// spirv.ConvertUToPtrOp133//===----------------------------------------------------------------------===//134 135LogicalResult ConvertUToPtrOp::verify() {136  auto operandType = llvm::cast<spirv::ScalarType>(getOperand().getType());137  auto resultType = llvm::cast<spirv::PointerType>(getResult().getType());138  if (!operandType || !operandType.isSignlessInteger())139    return emitError("result must be a scalar type of unsigned integer");140  auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>();141  if (!spirvModule)142    return success();143  auto addressingModel = spirvModule.getAddressingModel();144  if ((addressingModel == spirv::AddressingModel::Logical) ||145      (addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64 &&146       resultType.getStorageClass() !=147           spirv::StorageClass::PhysicalStorageBuffer))148    return emitError("result must be a physical pointer");149  return success();150}151 152//===----------------------------------------------------------------------===//153// spirv.PtrCastToGenericOp154//===----------------------------------------------------------------------===//155 156LogicalResult PtrCastToGenericOp::verify() {157  auto operandType = llvm::cast<spirv::PointerType>(getPointer().getType());158  auto resultType = llvm::cast<spirv::PointerType>(getResult().getType());159 160  spirv::StorageClass operandStorage = operandType.getStorageClass();161  if (operandStorage != spirv::StorageClass::Workgroup &&162      operandStorage != spirv::StorageClass::CrossWorkgroup &&163      operandStorage != spirv::StorageClass::Function)164    return emitError("pointer must point to the Workgroup, CrossWorkgroup"165                     ", or Function Storage Class");166 167  spirv::StorageClass resultStorage = resultType.getStorageClass();168  if (resultStorage != spirv::StorageClass::Generic)169    return emitError("result type must be of storage class Generic");170 171  Type operandPointeeType = operandType.getPointeeType();172  Type resultPointeeType = resultType.getPointeeType();173  if (operandPointeeType != resultPointeeType)174    return emitOpError("pointer operand's pointee type must have the same "175                       "as the op result type, but found ")176           << operandPointeeType << " vs " << resultPointeeType;177  return success();178}179 180//===----------------------------------------------------------------------===//181// spirv.GenericCastToPtrOp182//===----------------------------------------------------------------------===//183 184LogicalResult GenericCastToPtrOp::verify() {185  auto operandType = llvm::cast<spirv::PointerType>(getPointer().getType());186  auto resultType = llvm::cast<spirv::PointerType>(getResult().getType());187 188  spirv::StorageClass operandStorage = operandType.getStorageClass();189  if (operandStorage != spirv::StorageClass::Generic)190    return emitError("pointer type must be of storage class Generic");191 192  spirv::StorageClass resultStorage = resultType.getStorageClass();193  if (resultStorage != spirv::StorageClass::Workgroup &&194      resultStorage != spirv::StorageClass::CrossWorkgroup &&195      resultStorage != spirv::StorageClass::Function)196    return emitError("result must point to the Workgroup, CrossWorkgroup, "197                     "or Function Storage Class");198 199  Type operandPointeeType = operandType.getPointeeType();200  Type resultPointeeType = resultType.getPointeeType();201  if (operandPointeeType != resultPointeeType)202    return emitOpError("pointer operand's pointee type must have the same "203                       "as the op result type, but found ")204           << operandPointeeType << " vs " << resultPointeeType;205  return success();206}207 208//===----------------------------------------------------------------------===//209// spirv.GenericCastToPtrExplicitOp210//===----------------------------------------------------------------------===//211 212LogicalResult GenericCastToPtrExplicitOp::verify() {213  auto operandType = llvm::cast<spirv::PointerType>(getPointer().getType());214  auto resultType = llvm::cast<spirv::PointerType>(getResult().getType());215 216  spirv::StorageClass operandStorage = operandType.getStorageClass();217  if (operandStorage != spirv::StorageClass::Generic)218    return emitError("pointer type must be of storage class Generic");219 220  spirv::StorageClass resultStorage = resultType.getStorageClass();221  if (resultStorage != spirv::StorageClass::Workgroup &&222      resultStorage != spirv::StorageClass::CrossWorkgroup &&223      resultStorage != spirv::StorageClass::Function)224    return emitError("result must point to the Workgroup, CrossWorkgroup, "225                     "or Function Storage Class");226 227  Type operandPointeeType = operandType.getPointeeType();228  Type resultPointeeType = resultType.getPointeeType();229  if (operandPointeeType != resultPointeeType)230    return emitOpError("pointer operand's pointee type must have the same "231                       "as the op result type, but found ")232           << operandPointeeType << " vs " << resultPointeeType;233  return success();234}235 236//===----------------------------------------------------------------------===//237// spirv.ConvertFToSOp238//===----------------------------------------------------------------------===//239 240LogicalResult ConvertFToSOp::verify() {241  return verifyCastOp(*this, /*requireSameBitWidth=*/false,242                      /*skipBitWidthCheck=*/true);243}244 245//===----------------------------------------------------------------------===//246// spirv.ConvertFToUOp247//===----------------------------------------------------------------------===//248 249LogicalResult ConvertFToUOp::verify() {250  return verifyCastOp(*this, /*requireSameBitWidth=*/false,251                      /*skipBitWidthCheck=*/true);252}253 254//===----------------------------------------------------------------------===//255// spirv.ConvertSToFOp256//===----------------------------------------------------------------------===//257 258LogicalResult ConvertSToFOp::verify() {259  return verifyCastOp(*this, /*requireSameBitWidth=*/false,260                      /*skipBitWidthCheck=*/true);261}262 263//===----------------------------------------------------------------------===//264// spirv.ConvertUToFOp265//===----------------------------------------------------------------------===//266 267LogicalResult ConvertUToFOp::verify() {268  return verifyCastOp(*this, /*requireSameBitWidth=*/false,269                      /*skipBitWidthCheck=*/true);270}271 272//===----------------------------------------------------------------------===//273// spirv.FConvertOp274//===----------------------------------------------------------------------===//275 276LogicalResult spirv::FConvertOp::verify() {277  return verifyCastOp(*this, /*requireSameBitWidth=*/false);278}279 280//===----------------------------------------------------------------------===//281// spirv.SConvertOp282//===----------------------------------------------------------------------===//283 284LogicalResult spirv::SConvertOp::verify() {285  return verifyCastOp(*this, /*requireSameBitWidth=*/false);286}287 288//===----------------------------------------------------------------------===//289// spirv.UConvertOp290//===----------------------------------------------------------------------===//291 292LogicalResult spirv::UConvertOp::verify() {293  return verifyCastOp(*this, /*requireSameBitWidth=*/false);294}295 296} // namespace mlir::spirv297