1 //===- SPIRVInstruction.cpp -Class to represent SPIR-V instruction - C++ -*-===// 2 // 3 // The LLVM/SPIRV Translator 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 // 10 // Permission is hereby granted, free of charge, to any person obtaining a 11 // copy of this software and associated documentation files (the "Software"), 12 // to deal with the Software without restriction, including without limitation 13 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 // and/or sell copies of the Software, and to permit persons to whom the 15 // Software is furnished to do so, subject to the following conditions: 16 // 17 // Redistributions of source code must retain the above copyright notice, 18 // this list of conditions and the following disclaimers. 19 // Redistributions in binary form must reproduce the above copyright notice, 20 // this list of conditions and the following disclaimers in the documentation 21 // and/or other materials provided with the distribution. 22 // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 // contributors may be used to endorse or promote products derived from this 24 // Software without specific prior written permission. 25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 // THE SOFTWARE. 32 // 33 //===----------------------------------------------------------------------===// 34 /// \file 35 /// 36 /// This file implements SPIR-V instructions. 37 /// 38 //===----------------------------------------------------------------------===// 39 40 #include "SPIRVInstruction.h" 41 #include "SPIRVBasicBlock.h" 42 #include "SPIRVFunction.h" 43 44 #include <unordered_set> 45 46 namespace SPIRV { 47 48 // Complete constructor for instruction with type and id 49 SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, 50 SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB) 51 :SPIRVValue(TheBB->getModule(), TheWordCount, TheOC, TheType, TheId), 52 BB(TheBB){ 53 validate(); 54 } 55 56 SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, 57 SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB, SPIRVModule *TheBM) 58 : SPIRVValue(TheBM, TheWordCount, TheOC, TheType, TheId), BB(TheBB){ 59 validate(); 60 } 61 62 // Complete constructor for instruction with id but no type 63 SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, 64 SPIRVId TheId, SPIRVBasicBlock *TheBB) 65 :SPIRVValue(TheBB->getModule(), TheWordCount, TheOC, TheId), BB(TheBB){ 66 validate(); 67 } 68 // Complete constructor for instruction without type and id 69 SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, 70 SPIRVBasicBlock *TheBB) 71 :SPIRVValue(TheBB->getModule(), TheWordCount, TheOC), BB(TheBB){ 72 validate(); 73 } 74 // Complete constructor for instruction with type but no id 75 SPIRVInstruction::SPIRVInstruction(unsigned TheWordCount, Op TheOC, 76 SPIRVType *TheType, SPIRVBasicBlock *TheBB) 77 :SPIRVValue(TheBB->getModule(), TheWordCount, TheOC, TheType), BB(TheBB){ 78 validate(); 79 } 80 81 void 82 SPIRVInstruction::setParent(SPIRVBasicBlock *TheBB) { 83 assert(TheBB && "Invalid BB"); 84 if (BB == TheBB) 85 return; 86 assert(BB == NULL && "BB cannot change parent"); 87 BB = TheBB; 88 } 89 90 void 91 SPIRVInstruction::setScope(SPIRVEntry *Scope) { 92 assert(Scope && Scope->getOpCode() == OpLabel && "Invalid scope"); 93 setParent(static_cast<SPIRVBasicBlock*>(Scope)); 94 } 95 96 SPIRVFunctionCall::SPIRVFunctionCall(SPIRVId TheId, SPIRVFunction *TheFunction, 97 const std::vector<SPIRVWord> &TheArgs, SPIRVBasicBlock *BB) 98 :SPIRVFunctionCallGeneric( 99 TheFunction->getFunctionType()->getReturnType(), 100 TheId, TheArgs, BB), FunctionId(TheFunction->getId()){ 101 validate(); 102 } 103 104 void 105 SPIRVFunctionCall::validate()const { 106 SPIRVFunctionCallGeneric::validate(); 107 } 108 109 // ToDo: Each instruction should implement this function 110 std::vector<SPIRVValue *> 111 SPIRVInstruction::getOperands() { 112 std::vector<SPIRVValue *> Empty; 113 assert(0 && "not supported"); 114 return Empty; 115 } 116 117 std::vector<SPIRVType*> 118 SPIRVInstruction::getOperandTypes(const std::vector<SPIRVValue *> &Ops) { 119 std::vector<SPIRVType*> Tys; 120 for (auto& I : Ops) { 121 SPIRVType* Ty = nullptr; 122 if (I->getOpCode() == OpFunction) 123 Ty = reinterpret_cast<SPIRVFunction*>(I)->getFunctionType(); 124 else 125 Ty = I->getType(); 126 127 Tys.push_back(Ty); 128 } 129 return Tys; 130 } 131 132 std::vector<SPIRVType*> 133 SPIRVInstruction::getOperandTypes() { 134 return getOperandTypes(getOperands()); 135 } 136 137 bool 138 isSpecConstantOpAllowedOp(Op OC) { 139 static SPIRVWord Table[] = 140 { 141 OpSConvert, 142 OpFConvert, 143 OpConvertFToS, 144 OpConvertSToF, 145 OpConvertFToU, 146 OpConvertUToF, 147 OpUConvert, 148 OpConvertPtrToU, 149 OpConvertUToPtr, 150 OpGenericCastToPtr, 151 OpPtrCastToGeneric, 152 OpBitcast, 153 OpQuantizeToF16, 154 OpSNegate, 155 OpNot, 156 OpIAdd, 157 OpISub, 158 OpIMul, 159 OpUDiv, 160 OpSDiv, 161 OpUMod, 162 OpSRem, 163 OpSMod, 164 OpShiftRightLogical, 165 OpShiftRightArithmetic, 166 OpShiftLeftLogical, 167 OpBitwiseOr, 168 OpBitwiseXor, 169 OpBitwiseAnd, 170 OpFNegate, 171 OpFAdd, 172 OpFSub, 173 OpFMul, 174 OpFDiv, 175 OpFRem, 176 OpFMod, 177 OpVectorShuffle, 178 OpCompositeExtract, 179 OpCompositeInsert, 180 OpLogicalOr, 181 OpLogicalAnd, 182 OpLogicalNot, 183 OpLogicalEqual, 184 OpLogicalNotEqual, 185 OpSelect, 186 OpIEqual, 187 OpULessThan, 188 OpSLessThan, 189 OpUGreaterThan, 190 OpSGreaterThan, 191 OpULessThanEqual, 192 OpSLessThanEqual, 193 OpUGreaterThanEqual, 194 OpSGreaterThanEqual, 195 OpAccessChain, 196 OpInBoundsAccessChain, 197 OpPtrAccessChain, 198 OpInBoundsPtrAccessChain, 199 }; 200 static std::unordered_set<SPIRVWord> 201 Allow(std::begin(Table), std::end(Table)); 202 return Allow.count(OC); 203 } 204 205 SPIRVSpecConstantOp * 206 createSpecConstantOpInst(SPIRVInstruction *Inst) { 207 auto OC = Inst->getOpCode(); 208 assert (isSpecConstantOpAllowedOp(OC) && 209 "Op code not allowed for OpSpecConstantOp"); 210 auto Ops = Inst->getIds(Inst->getOperands()); 211 Ops.insert(Ops.begin(), OC); 212 return static_cast<SPIRVSpecConstantOp *>( 213 SPIRVSpecConstantOp::create(OpSpecConstantOp, Inst->getType(), 214 Inst->getId(), Ops, nullptr, Inst->getModule())); 215 } 216 217 SPIRVInstruction * 218 createInstFromSpecConstantOp(SPIRVSpecConstantOp *Inst) { 219 assert(Inst->getOpCode() == OpSpecConstantOp && 220 "Not OpSpecConstantOp"); 221 auto Ops = Inst->getOpWords(); 222 auto OC = static_cast<Op>(Ops[0]); 223 assert (isSpecConstantOpAllowedOp(OC) && 224 "Op code not allowed for OpSpecConstantOp"); 225 Ops.erase(Ops.begin(), Ops.begin() + 1); 226 return SPIRVInstTemplateBase::create(OC, Inst->getType(), 227 Inst->getId(), Ops, nullptr, Inst->getModule()); 228 } 229 230 } 231 232 233