• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
SPIRVInstruction(unsigned TheWordCount,Op TheOC,SPIRVType * TheType,SPIRVId TheId,SPIRVBasicBlock * TheBB)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 
SPIRVInstruction(unsigned TheWordCount,Op TheOC,SPIRVType * TheType,SPIRVId TheId,SPIRVBasicBlock * TheBB,SPIRVModule * TheBM)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
SPIRVInstruction(unsigned TheWordCount,Op TheOC,SPIRVId TheId,SPIRVBasicBlock * TheBB)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
SPIRVInstruction(unsigned TheWordCount,Op TheOC,SPIRVBasicBlock * TheBB)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
SPIRVInstruction(unsigned TheWordCount,Op TheOC,SPIRVType * TheType,SPIRVBasicBlock * TheBB)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
setParent(SPIRVBasicBlock * TheBB)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
setScope(SPIRVEntry * Scope)91 SPIRVInstruction::setScope(SPIRVEntry *Scope) {
92   assert(Scope && Scope->getOpCode() == OpLabel && "Invalid scope");
93   setParent(static_cast<SPIRVBasicBlock*>(Scope));
94 }
95 
SPIRVFunctionCall(SPIRVId TheId,SPIRVFunction * TheFunction,const std::vector<SPIRVWord> & TheArgs,SPIRVBasicBlock * BB)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
validate() const105 SPIRVFunctionCall::validate()const {
106   SPIRVFunctionCallGeneric::validate();
107 }
108 
109 // ToDo: Each instruction should implement this function
110 std::vector<SPIRVValue *>
getOperands()111 SPIRVInstruction::getOperands() {
112   std::vector<SPIRVValue *> Empty;
113   assert(0 && "not supported");
114   return Empty;
115 }
116 
117 std::vector<SPIRVType*>
getOperandTypes(const std::vector<SPIRVValue * > & Ops)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*>
getOperandTypes()133 SPIRVInstruction::getOperandTypes() {
134   return getOperandTypes(getOperands());
135 }
136 
137 bool
isSpecConstantOpAllowedOp(Op OC)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 *
createSpecConstantOpInst(SPIRVInstruction * Inst)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 *
createInstFromSpecConstantOp(SPIRVSpecConstantOp * Inst)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