brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.9 KiB · 461d037 Raw
364 lines · cpp
1//===- GroupOps.cpp - MLIR SPIR-V Group 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 group operations in the SPIR-V dialect.10//11//===----------------------------------------------------------------------===//12 13#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"14#include "mlir/Dialect/SPIRV/IR/TargetAndABI.h"15 16#include "SPIRVOpUtils.h"17#include "SPIRVParsingUtils.h"18 19using namespace mlir::spirv::AttrNames;20 21namespace mlir::spirv {22 23template <typename OpTy>24static LogicalResult verifyGroupNonUniformArithmeticOp(Operation *groupOp) {25  spirv::Scope scope =26      groupOp27          ->getAttrOfType<spirv::ScopeAttr>(28              OpTy::getExecutionScopeAttrName(groupOp->getName()))29          .getValue();30  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)31    return groupOp->emitOpError(32        "execution scope must be 'Workgroup' or 'Subgroup'");33 34  GroupOperation operation =35      groupOp36          ->getAttrOfType<GroupOperationAttr>(37              OpTy::getGroupOperationAttrName(groupOp->getName()))38          .getValue();39  if (operation == GroupOperation::ClusteredReduce &&40      groupOp->getNumOperands() == 1)41    return groupOp->emitOpError("cluster size operand must be provided for "42                                "'ClusteredReduce' group operation");43  if (groupOp->getNumOperands() > 1) {44    Operation *sizeOp = groupOp->getOperand(1).getDefiningOp();45    int32_t clusterSize = 0;46 47    // TODO: support specialization constant here.48    if (failed(extractValueFromConstOp(sizeOp, clusterSize)))49      return groupOp->emitOpError(50          "cluster size operand must come from a constant op");51 52    if (!llvm::isPowerOf2_32(clusterSize))53      return groupOp->emitOpError(54          "cluster size operand must be a power of two");55  }56  return success();57}58 59//===----------------------------------------------------------------------===//60// spirv.GroupBroadcast61//===----------------------------------------------------------------------===//62 63LogicalResult GroupBroadcastOp::verify() {64  spirv::Scope scope = getExecutionScope();65  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)66    return emitOpError("execution scope must be 'Workgroup' or 'Subgroup'");67 68  if (auto localIdTy = llvm::dyn_cast<VectorType>(getLocalid().getType()))69    if (localIdTy.getNumElements() != 2 && localIdTy.getNumElements() != 3)70      return emitOpError("localid is a vector and can be with only "71                         " 2 or 3 components, actual number is ")72             << localIdTy.getNumElements();73 74  return success();75}76 77//===----------------------------------------------------------------------===//78// spirv.GroupNonUniformBallotOp79//===----------------------------------------------------------------------===//80 81LogicalResult GroupNonUniformBallotOp::verify() {82  spirv::Scope scope = getExecutionScope();83  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)84    return emitOpError("execution scope must be 'Workgroup' or 'Subgroup'");85 86  return success();87}88 89//===----------------------------------------------------------------------===//90// spirv.GroupNonUniformBallotFindLSBOp91//===----------------------------------------------------------------------===//92 93LogicalResult GroupNonUniformBallotFindLSBOp::verify() {94  spirv::Scope scope = getExecutionScope();95  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)96    return emitOpError("execution scope must be 'Workgroup' or 'Subgroup'");97 98  return success();99}100 101//===----------------------------------------------------------------------===//102// spirv.GroupNonUniformBallotFindLSBOp103//===----------------------------------------------------------------------===//104 105LogicalResult GroupNonUniformBallotFindMSBOp::verify() {106  spirv::Scope scope = getExecutionScope();107  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)108    return emitOpError("execution scope must be 'Workgroup' or 'Subgroup'");109 110  return success();111}112 113//===----------------------------------------------------------------------===//114// spirv.GroupNonUniformBroadcast115//===----------------------------------------------------------------------===//116 117LogicalResult GroupNonUniformBroadcastOp::verify() {118  spirv::Scope scope = getExecutionScope();119  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)120    return emitOpError("execution scope must be 'Workgroup' or 'Subgroup'");121 122  // SPIR-V spec: "Before version 1.5, Id must come from a123  // constant instruction.124  auto targetEnv = spirv::getDefaultTargetEnv(getContext());125  if (auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>())126    targetEnv = spirv::lookupTargetEnvOrDefault(spirvModule);127 128  if (targetEnv.getVersion() < spirv::Version::V_1_5) {129    auto *idOp = getId().getDefiningOp();130    if (!idOp || !isa<spirv::ConstantOp,           // for normal constant131                      spirv::ReferenceOfOp>(idOp)) // for spec constant132      return emitOpError("id must be the result of a constant op");133  }134 135  return success();136}137 138//===----------------------------------------------------------------------===//139// spirv.GroupNonUniformShuffle*140//===----------------------------------------------------------------------===//141 142template <typename OpTy>143static LogicalResult verifyGroupNonUniformShuffleOp(OpTy op) {144  spirv::Scope scope = op.getExecutionScope();145  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)146    return op.emitOpError("execution scope must be 'Workgroup' or 'Subgroup'");147 148  if (op.getOperands().back().getType().isSignedInteger())149    return op.emitOpError("second operand must be a singless/unsigned integer");150 151  return success();152}153 154LogicalResult GroupNonUniformShuffleOp::verify() {155  return verifyGroupNonUniformShuffleOp(*this);156}157LogicalResult GroupNonUniformShuffleDownOp::verify() {158  return verifyGroupNonUniformShuffleOp(*this);159}160LogicalResult GroupNonUniformShuffleUpOp::verify() {161  return verifyGroupNonUniformShuffleOp(*this);162}163LogicalResult GroupNonUniformShuffleXorOp::verify() {164  return verifyGroupNonUniformShuffleOp(*this);165}166 167//===----------------------------------------------------------------------===//168// spirv.GroupNonUniformElectOp169//===----------------------------------------------------------------------===//170 171LogicalResult GroupNonUniformElectOp::verify() {172  spirv::Scope scope = getExecutionScope();173  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)174    return emitOpError("execution scope must be 'Workgroup' or 'Subgroup'");175 176  return success();177}178 179//===----------------------------------------------------------------------===//180// spirv.GroupNonUniformFAddOp181//===----------------------------------------------------------------------===//182 183LogicalResult GroupNonUniformFAddOp::verify() {184  return verifyGroupNonUniformArithmeticOp<GroupNonUniformFAddOp>(*this);185}186 187//===----------------------------------------------------------------------===//188// spirv.GroupNonUniformFMaxOp189//===----------------------------------------------------------------------===//190 191LogicalResult GroupNonUniformFMaxOp::verify() {192  return verifyGroupNonUniformArithmeticOp<GroupNonUniformFMaxOp>(*this);193}194 195//===----------------------------------------------------------------------===//196// spirv.GroupNonUniformFMinOp197//===----------------------------------------------------------------------===//198 199LogicalResult GroupNonUniformFMinOp::verify() {200  return verifyGroupNonUniformArithmeticOp<GroupNonUniformFMinOp>(*this);201}202 203//===----------------------------------------------------------------------===//204// spirv.GroupNonUniformFMulOp205//===----------------------------------------------------------------------===//206 207LogicalResult GroupNonUniformFMulOp::verify() {208  return verifyGroupNonUniformArithmeticOp<GroupNonUniformFMulOp>(*this);209}210 211//===----------------------------------------------------------------------===//212// spirv.GroupNonUniformIAddOp213//===----------------------------------------------------------------------===//214 215LogicalResult GroupNonUniformIAddOp::verify() {216  return verifyGroupNonUniformArithmeticOp<GroupNonUniformIAddOp>(*this);217}218 219//===----------------------------------------------------------------------===//220// spirv.GroupNonUniformIMulOp221//===----------------------------------------------------------------------===//222 223LogicalResult GroupNonUniformIMulOp::verify() {224  return verifyGroupNonUniformArithmeticOp<GroupNonUniformIMulOp>(*this);225}226 227//===----------------------------------------------------------------------===//228// spirv.GroupNonUniformSMaxOp229//===----------------------------------------------------------------------===//230 231LogicalResult GroupNonUniformSMaxOp::verify() {232  return verifyGroupNonUniformArithmeticOp<GroupNonUniformSMaxOp>(*this);233}234 235//===----------------------------------------------------------------------===//236// spirv.GroupNonUniformSMinOp237//===----------------------------------------------------------------------===//238 239LogicalResult GroupNonUniformSMinOp::verify() {240  return verifyGroupNonUniformArithmeticOp<GroupNonUniformSMinOp>(*this);241}242 243//===----------------------------------------------------------------------===//244// spirv.GroupNonUniformUMaxOp245//===----------------------------------------------------------------------===//246 247LogicalResult GroupNonUniformUMaxOp::verify() {248  return verifyGroupNonUniformArithmeticOp<GroupNonUniformUMaxOp>(*this);249}250 251//===----------------------------------------------------------------------===//252// spirv.GroupNonUniformUMinOp253//===----------------------------------------------------------------------===//254 255LogicalResult GroupNonUniformUMinOp::verify() {256  return verifyGroupNonUniformArithmeticOp<GroupNonUniformUMinOp>(*this);257}258 259//===----------------------------------------------------------------------===//260// spirv.GroupNonUniformBitwiseAnd261//===----------------------------------------------------------------------===//262 263LogicalResult GroupNonUniformBitwiseAndOp::verify() {264  return verifyGroupNonUniformArithmeticOp<GroupNonUniformBitwiseAndOp>(*this);265}266 267//===----------------------------------------------------------------------===//268// spirv.GroupNonUniformBitwiseOr269//===----------------------------------------------------------------------===//270 271LogicalResult GroupNonUniformBitwiseOrOp::verify() {272  return verifyGroupNonUniformArithmeticOp<GroupNonUniformBitwiseOrOp>(*this);273}274 275//===----------------------------------------------------------------------===//276// spirv.GroupNonUniformBitwiseXor277//===----------------------------------------------------------------------===//278 279LogicalResult GroupNonUniformBitwiseXorOp::verify() {280  return verifyGroupNonUniformArithmeticOp<GroupNonUniformBitwiseXorOp>(*this);281}282 283//===----------------------------------------------------------------------===//284// spirv.GroupNonUniformLogicalAnd285//===----------------------------------------------------------------------===//286 287LogicalResult GroupNonUniformLogicalAndOp::verify() {288  return verifyGroupNonUniformArithmeticOp<GroupNonUniformLogicalAndOp>(*this);289}290 291//===----------------------------------------------------------------------===//292// spirv.GroupNonUniformLogicalOr293//===----------------------------------------------------------------------===//294 295LogicalResult GroupNonUniformLogicalOrOp::verify() {296  return verifyGroupNonUniformArithmeticOp<GroupNonUniformLogicalOrOp>(*this);297}298 299//===----------------------------------------------------------------------===//300// spirv.GroupNonUniformLogicalXor301//===----------------------------------------------------------------------===//302 303LogicalResult GroupNonUniformLogicalXorOp::verify() {304  return verifyGroupNonUniformArithmeticOp<GroupNonUniformLogicalXorOp>(*this);305}306 307//===----------------------------------------------------------------------===//308// spirv.GroupNonUniformRotateKHR309//===----------------------------------------------------------------------===//310 311LogicalResult GroupNonUniformRotateKHROp::verify() {312  spirv::Scope scope = getExecutionScope();313  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)314    return emitOpError("execution scope must be 'Workgroup' or 'Subgroup'");315 316  if (Value clusterSizeVal = getClusterSize()) {317    mlir::Operation *defOp = clusterSizeVal.getDefiningOp();318    int32_t clusterSize = 0;319 320    if (failed(extractValueFromConstOp(defOp, clusterSize)))321      return emitOpError("cluster size operand must come from a constant op");322 323    if (!llvm::isPowerOf2_32(clusterSize))324      return emitOpError("cluster size operand must be a power of two");325  }326 327  return success();328}329 330//===----------------------------------------------------------------------===//331// Group op verification332//===----------------------------------------------------------------------===//333 334template <typename Op>335static LogicalResult verifyGroupOp(Op op) {336  spirv::Scope scope = op.getExecutionScope();337  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)338    return op.emitOpError("execution scope must be 'Workgroup' or 'Subgroup'");339 340  return success();341}342 343LogicalResult GroupIAddOp::verify() { return verifyGroupOp(*this); }344 345LogicalResult GroupFAddOp::verify() { return verifyGroupOp(*this); }346 347LogicalResult GroupFMinOp::verify() { return verifyGroupOp(*this); }348 349LogicalResult GroupUMinOp::verify() { return verifyGroupOp(*this); }350 351LogicalResult GroupSMinOp::verify() { return verifyGroupOp(*this); }352 353LogicalResult GroupFMaxOp::verify() { return verifyGroupOp(*this); }354 355LogicalResult GroupUMaxOp::verify() { return verifyGroupOp(*this); }356 357LogicalResult GroupSMaxOp::verify() { return verifyGroupOp(*this); }358 359LogicalResult GroupIMulKHROp::verify() { return verifyGroupOp(*this); }360 361LogicalResult GroupFMulKHROp::verify() { return verifyGroupOp(*this); }362 363} // namespace mlir::spirv364