/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/XCore/XCoreInstrInfo.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- XCoreInstrInfo.cpp - XCore Instruction Information ----------------===// |
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-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file contains the XCore implementation of the TargetInstrInfo class. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "XCoreInstrInfo.h" |
14 | | #include "XCore.h" |
15 | | #include "XCoreMachineFunctionInfo.h" |
16 | | #include "llvm/ADT/STLExtras.h" |
17 | | #include "llvm/CodeGen/MachineConstantPool.h" |
18 | | #include "llvm/CodeGen/MachineFrameInfo.h" |
19 | | #include "llvm/CodeGen/MachineInstrBuilder.h" |
20 | | #include "llvm/CodeGen/MachineMemOperand.h" |
21 | | #include "llvm/IR/Constants.h" |
22 | | #include "llvm/IR/Function.h" |
23 | | #include "llvm/MC/MCContext.h" |
24 | | #include "llvm/Support/Debug.h" |
25 | | #include "llvm/Support/ErrorHandling.h" |
26 | | #include "llvm/Support/TargetRegistry.h" |
27 | | |
28 | | using namespace llvm; |
29 | | |
30 | | #define GET_INSTRINFO_CTOR_DTOR |
31 | | #include "XCoreGenInstrInfo.inc" |
32 | | |
33 | | namespace llvm { |
34 | | namespace XCore { |
35 | | |
36 | | // XCore Condition Codes |
37 | | enum CondCode { |
38 | | COND_TRUE, |
39 | | COND_FALSE, |
40 | | COND_INVALID |
41 | | }; |
42 | | } |
43 | | } |
44 | | |
45 | | // Pin the vtable to this file. |
46 | 0 | void XCoreInstrInfo::anchor() {} |
47 | | |
48 | | XCoreInstrInfo::XCoreInstrInfo() |
49 | | : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), |
50 | 81 | RI() { |
51 | 81 | } |
52 | | |
53 | 5 | static bool isZeroImm(const MachineOperand &op) { |
54 | 5 | return op.isImm() && op.getImm() == 0; |
55 | 5 | } |
56 | | |
57 | | /// isLoadFromStackSlot - If the specified machine instruction is a direct |
58 | | /// load from a stack slot, return the virtual or physical register number of |
59 | | /// the destination along with the FrameIndex of the loaded stack slot. If |
60 | | /// not, return 0. This predicate must return 0 if the instruction has |
61 | | /// any side effects other than loading from the stack slot. |
62 | | unsigned XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, |
63 | 76 | int &FrameIndex) const { |
64 | 76 | int Opcode = MI.getOpcode(); |
65 | 76 | if (Opcode == XCore::LDWFI) |
66 | 4 | { |
67 | 4 | if ((MI.getOperand(1).isFI()) && // is a stack slot |
68 | 4 | (MI.getOperand(2).isImm()) && // the imm is zero |
69 | 4 | (isZeroImm(MI.getOperand(2)))) { |
70 | 3 | FrameIndex = MI.getOperand(1).getIndex(); |
71 | 3 | return MI.getOperand(0).getReg(); |
72 | 3 | } |
73 | 73 | } |
74 | 73 | return 0; |
75 | 73 | } |
76 | | |
77 | | /// isStoreToStackSlot - If the specified machine instruction is a direct |
78 | | /// store to a stack slot, return the virtual or physical register number of |
79 | | /// the source reg along with the FrameIndex of the loaded stack slot. If |
80 | | /// not, return 0. This predicate must return 0 if the instruction has |
81 | | /// any side effects other than storing to the stack slot. |
82 | | unsigned XCoreInstrInfo::isStoreToStackSlot(const MachineInstr &MI, |
83 | 28 | int &FrameIndex) const { |
84 | 28 | int Opcode = MI.getOpcode(); |
85 | 28 | if (Opcode == XCore::STWFI) |
86 | 1 | { |
87 | 1 | if ((MI.getOperand(1).isFI()) && // is a stack slot |
88 | 1 | (MI.getOperand(2).isImm()) && // the imm is zero |
89 | 1 | (isZeroImm(MI.getOperand(2)))) { |
90 | 1 | FrameIndex = MI.getOperand(1).getIndex(); |
91 | 1 | return MI.getOperand(0).getReg(); |
92 | 1 | } |
93 | 27 | } |
94 | 27 | return 0; |
95 | 27 | } |
96 | | |
97 | | //===----------------------------------------------------------------------===// |
98 | | // Branch Analysis |
99 | | //===----------------------------------------------------------------------===// |
100 | | |
101 | 2.30k | static inline bool IsBRU(unsigned BrOpc) { |
102 | 2.30k | return BrOpc == XCore::BRFU_u6 |
103 | 2.30k | || BrOpc == XCore::BRFU_lu6 |
104 | 2.30k | || BrOpc == XCore::BRBU_u61.91k |
105 | 2.30k | || BrOpc == XCore::BRBU_lu61.91k ; |
106 | 2.30k | } |
107 | | |
108 | 1.99k | static inline bool IsBRT(unsigned BrOpc) { |
109 | 1.99k | return BrOpc == XCore::BRFT_ru6 |
110 | 1.99k | || BrOpc == XCore::BRFT_lru6 |
111 | 1.99k | || BrOpc == XCore::BRBT_ru61.87k |
112 | 1.99k | || BrOpc == XCore::BRBT_lru61.87k ; |
113 | 1.99k | } |
114 | | |
115 | 1.90k | static inline bool IsBRF(unsigned BrOpc) { |
116 | 1.90k | return BrOpc == XCore::BRFF_ru6 |
117 | 1.90k | || BrOpc == XCore::BRFF_lru6 |
118 | 1.90k | || BrOpc == XCore::BRBF_ru61.74k |
119 | 1.90k | || BrOpc == XCore::BRBF_lru61.74k ; |
120 | 1.90k | } |
121 | | |
122 | 100 | static inline bool IsCondBranch(unsigned BrOpc) { |
123 | 100 | return IsBRF(BrOpc) || IsBRT(BrOpc)79 ; |
124 | 100 | } |
125 | | |
126 | 0 | static inline bool IsBR_JT(unsigned BrOpc) { |
127 | 0 | return BrOpc == XCore::BR_JT |
128 | 0 | || BrOpc == XCore::BR_JT32; |
129 | 0 | } |
130 | | |
131 | | /// GetCondFromBranchOpc - Return the XCore CC that matches |
132 | | /// the correspondent Branch instruction opcode. |
133 | | static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc) |
134 | 1.91k | { |
135 | 1.91k | if (IsBRT(BrOpc)) { |
136 | 104 | return XCore::COND_TRUE; |
137 | 1.80k | } else if (IsBRF(BrOpc)) { |
138 | 145 | return XCore::COND_FALSE; |
139 | 1.66k | } else { |
140 | 1.66k | return XCore::COND_INVALID; |
141 | 1.66k | } |
142 | 1.91k | } |
143 | | |
144 | | /// GetCondBranchFromCond - Return the Branch instruction |
145 | | /// opcode that matches the cc. |
146 | | static inline unsigned GetCondBranchFromCond(XCore::CondCode CC) |
147 | 35 | { |
148 | 35 | switch (CC) { |
149 | 35 | default: 0 llvm_unreachable0 ("Illegal condition code!"); |
150 | 35 | case XCore::COND_TRUE : return XCore::BRFT_lru618 ; |
151 | 35 | case XCore::COND_FALSE : return XCore::BRFF_lru617 ; |
152 | 35 | } |
153 | 35 | } |
154 | | |
155 | | /// GetOppositeBranchCondition - Return the inverse of the specified |
156 | | /// condition, e.g. turning COND_E to COND_NE. |
157 | | static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC) |
158 | 24 | { |
159 | 24 | switch (CC) { |
160 | 24 | default: 0 llvm_unreachable0 ("Illegal condition code!"); |
161 | 24 | case XCore::COND_TRUE : return XCore::COND_FALSE10 ; |
162 | 24 | case XCore::COND_FALSE : return XCore::COND_TRUE14 ; |
163 | 24 | } |
164 | 24 | } |
165 | | |
166 | | /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning |
167 | | /// true if it cannot be understood (e.g. it's a switch dispatch or isn't |
168 | | /// implemented for a target). Upon success, this returns false and returns |
169 | | /// with the following information in various cases: |
170 | | /// |
171 | | /// 1. If this block ends with no branches (it just falls through to its succ) |
172 | | /// just return false, leaving TBB/FBB null. |
173 | | /// 2. If this block ends with only an unconditional branch, it sets TBB to be |
174 | | /// the destination block. |
175 | | /// 3. If this block ends with an conditional branch and it falls through to |
176 | | /// an successor block, it sets TBB to be the branch destination block and a |
177 | | /// list of operands that evaluate the condition. These |
178 | | /// operands can be passed to other TargetInstrInfo methods to create new |
179 | | /// branches. |
180 | | /// 4. If this block ends with an conditional branch and an unconditional |
181 | | /// block, it returns the 'true' destination in TBB, the 'false' destination |
182 | | /// in FBB, and a list of operands that evaluate the condition. These |
183 | | /// operands can be passed to other TargetInstrInfo methods to create new |
184 | | /// branches. |
185 | | /// |
186 | | /// Note that removeBranch and insertBranch must be implemented to support |
187 | | /// cases where this method returns success. |
188 | | /// |
189 | | bool XCoreInstrInfo::analyzeBranch(MachineBasicBlock &MBB, |
190 | | MachineBasicBlock *&TBB, |
191 | | MachineBasicBlock *&FBB, |
192 | | SmallVectorImpl<MachineOperand> &Cond, |
193 | 2.52k | bool AllowModify) const { |
194 | 2.52k | // If the block has no terminators, it just falls into the block after it. |
195 | 2.52k | MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); |
196 | 2.52k | if (I == MBB.end()) |
197 | 87 | return false; |
198 | 2.43k | |
199 | 2.43k | if (!isUnpredicatedTerminator(*I)) |
200 | 263 | return false; |
201 | 2.17k | |
202 | 2.17k | // Get the last instruction in the block. |
203 | 2.17k | MachineInstr *LastInst = &*I; |
204 | 2.17k | |
205 | 2.17k | // If there is only one terminator instruction, process it. |
206 | 2.17k | if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)1.93k ) { |
207 | 2.12k | if (IsBRU(LastInst->getOpcode())) { |
208 | 248 | TBB = LastInst->getOperand(0).getMBB(); |
209 | 248 | return false; |
210 | 248 | } |
211 | 1.87k | |
212 | 1.87k | XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode()); |
213 | 1.87k | if (BranchCode == XCore::COND_INVALID) |
214 | 1.66k | return true; // Can't handle indirect branch. |
215 | 211 | |
216 | 211 | // Conditional branch |
217 | 211 | // Block ends with fall-through condbranch. |
218 | 211 | |
219 | 211 | TBB = LastInst->getOperand(1).getMBB(); |
220 | 211 | Cond.push_back(MachineOperand::CreateImm(BranchCode)); |
221 | 211 | Cond.push_back(LastInst->getOperand(0)); |
222 | 211 | return false; |
223 | 211 | } |
224 | 51 | |
225 | 51 | // Get the instruction before it if it's a terminator. |
226 | 51 | MachineInstr *SecondLastInst = &*I; |
227 | 51 | |
228 | 51 | // If there are three terminators, we don't know what sort of block this is. |
229 | 51 | if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I)36 ) |
230 | 13 | return true; |
231 | 38 | |
232 | 38 | unsigned SecondLastOpc = SecondLastInst->getOpcode(); |
233 | 38 | XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc); |
234 | 38 | |
235 | 38 | // If the block ends with conditional branch followed by unconditional, |
236 | 38 | // handle it. |
237 | 38 | if (BranchCode != XCore::COND_INVALID |
238 | 38 | && IsBRU(LastInst->getOpcode())) { |
239 | 38 | |
240 | 38 | TBB = SecondLastInst->getOperand(1).getMBB(); |
241 | 38 | Cond.push_back(MachineOperand::CreateImm(BranchCode)); |
242 | 38 | Cond.push_back(SecondLastInst->getOperand(0)); |
243 | 38 | |
244 | 38 | FBB = LastInst->getOperand(0).getMBB(); |
245 | 38 | return false; |
246 | 38 | } |
247 | 0 | |
248 | 0 | // If the block ends with two unconditional branches, handle it. The second |
249 | 0 | // one is not executed, so remove it. |
250 | 0 | if (IsBRU(SecondLastInst->getOpcode()) && |
251 | 0 | IsBRU(LastInst->getOpcode())) { |
252 | 0 | TBB = SecondLastInst->getOperand(0).getMBB(); |
253 | 0 | I = LastInst; |
254 | 0 | if (AllowModify) |
255 | 0 | I->eraseFromParent(); |
256 | 0 | return false; |
257 | 0 | } |
258 | 0 |
|
259 | 0 | // Likewise if it ends with a branch table followed by an unconditional branch. |
260 | 0 | if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) { |
261 | 0 | I = LastInst; |
262 | 0 | if (AllowModify) |
263 | 0 | I->eraseFromParent(); |
264 | 0 | return true; |
265 | 0 | } |
266 | 0 |
|
267 | 0 | // Otherwise, can't handle this. |
268 | 0 | return true; |
269 | 0 | } |
270 | | |
271 | | unsigned XCoreInstrInfo::insertBranch(MachineBasicBlock &MBB, |
272 | | MachineBasicBlock *TBB, |
273 | | MachineBasicBlock *FBB, |
274 | | ArrayRef<MachineOperand> Cond, |
275 | | const DebugLoc &DL, |
276 | 123 | int *BytesAdded) const { |
277 | 123 | // Shouldn't be a fall through. |
278 | 123 | assert(TBB && "insertBranch must not be told to insert a fallthrough"); |
279 | 123 | assert((Cond.size() == 2 || Cond.size() == 0) && |
280 | 123 | "Unexpected number of components!"); |
281 | 123 | assert(!BytesAdded && "code size not handled"); |
282 | 123 | |
283 | 123 | if (!FBB) { // One way branch. |
284 | 122 | if (Cond.empty()) { |
285 | 88 | // Unconditional branch |
286 | 88 | BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB); |
287 | 88 | } else { |
288 | 34 | // Conditional branch. |
289 | 34 | unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm()); |
290 | 34 | BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()) |
291 | 34 | .addMBB(TBB); |
292 | 34 | } |
293 | 122 | return 1; |
294 | 122 | } |
295 | 1 | |
296 | 1 | // Two-way Conditional branch. |
297 | 1 | assert(Cond.size() == 2 && "Unexpected number of components!"); |
298 | 1 | unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm()); |
299 | 1 | BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()) |
300 | 1 | .addMBB(TBB); |
301 | 1 | BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB); |
302 | 1 | return 2; |
303 | 1 | } |
304 | | |
305 | | unsigned |
306 | 142 | XCoreInstrInfo::removeBranch(MachineBasicBlock &MBB, int *BytesRemoved) const { |
307 | 142 | assert(!BytesRemoved && "code size not handled"); |
308 | 142 | |
309 | 142 | MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); |
310 | 142 | if (I == MBB.end()) |
311 | 0 | return 0; |
312 | 142 | |
313 | 142 | if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode())36 ) |
314 | 14 | return 0; |
315 | 128 | |
316 | 128 | // Remove the branch. |
317 | 128 | I->eraseFromParent(); |
318 | 128 | |
319 | 128 | I = MBB.end(); |
320 | 128 | |
321 | 128 | if (I == MBB.begin()) return 164 ; |
322 | 64 | --I; |
323 | 64 | if (!IsCondBranch(I->getOpcode())) |
324 | 51 | return 1; |
325 | 13 | |
326 | 13 | // Remove the branch. |
327 | 13 | I->eraseFromParent(); |
328 | 13 | return 2; |
329 | 13 | } |
330 | | |
331 | | void XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB, |
332 | | MachineBasicBlock::iterator I, |
333 | | const DebugLoc &DL, unsigned DestReg, |
334 | 96 | unsigned SrcReg, bool KillSrc) const { |
335 | 96 | bool GRDest = XCore::GRRegsRegClass.contains(DestReg); |
336 | 96 | bool GRSrc = XCore::GRRegsRegClass.contains(SrcReg); |
337 | 96 | |
338 | 96 | if (GRDest && GRSrc93 ) { |
339 | 82 | BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg) |
340 | 82 | .addReg(SrcReg, getKillRegState(KillSrc)) |
341 | 82 | .addImm(0); |
342 | 82 | return; |
343 | 82 | } |
344 | 14 | |
345 | 14 | if (GRDest && SrcReg == XCore::SP11 ) { |
346 | 11 | BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0); |
347 | 11 | return; |
348 | 11 | } |
349 | 3 | |
350 | 3 | if (DestReg == XCore::SP && GRSrc) { |
351 | 3 | BuildMI(MBB, I, DL, get(XCore::SETSP_1r)) |
352 | 3 | .addReg(SrcReg, getKillRegState(KillSrc)); |
353 | 3 | return; |
354 | 3 | } |
355 | 0 | llvm_unreachable("Impossible reg-to-reg copy"); |
356 | 0 | } |
357 | | |
358 | | void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, |
359 | | MachineBasicBlock::iterator I, |
360 | | unsigned SrcReg, bool isKill, |
361 | | int FrameIndex, |
362 | | const TargetRegisterClass *RC, |
363 | | const TargetRegisterInfo *TRI) const |
364 | 83 | { |
365 | 83 | DebugLoc DL; |
366 | 83 | if (I != MBB.end() && !I->isDebugInstr()) |
367 | 83 | DL = I->getDebugLoc(); |
368 | 83 | MachineFunction *MF = MBB.getParent(); |
369 | 83 | const MachineFrameInfo &MFI = MF->getFrameInfo(); |
370 | 83 | MachineMemOperand *MMO = MF->getMachineMemOperand( |
371 | 83 | MachinePointerInfo::getFixedStack(*MF, FrameIndex), |
372 | 83 | MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex), |
373 | 83 | MFI.getObjectAlignment(FrameIndex)); |
374 | 83 | BuildMI(MBB, I, DL, get(XCore::STWFI)) |
375 | 83 | .addReg(SrcReg, getKillRegState(isKill)) |
376 | 83 | .addFrameIndex(FrameIndex) |
377 | 83 | .addImm(0) |
378 | 83 | .addMemOperand(MMO); |
379 | 83 | } |
380 | | |
381 | | void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, |
382 | | MachineBasicBlock::iterator I, |
383 | | unsigned DestReg, int FrameIndex, |
384 | | const TargetRegisterClass *RC, |
385 | | const TargetRegisterInfo *TRI) const |
386 | 96 | { |
387 | 96 | DebugLoc DL; |
388 | 96 | if (I != MBB.end() && !I->isDebugInstr()) |
389 | 96 | DL = I->getDebugLoc(); |
390 | 96 | MachineFunction *MF = MBB.getParent(); |
391 | 96 | const MachineFrameInfo &MFI = MF->getFrameInfo(); |
392 | 96 | MachineMemOperand *MMO = MF->getMachineMemOperand( |
393 | 96 | MachinePointerInfo::getFixedStack(*MF, FrameIndex), |
394 | 96 | MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex), |
395 | 96 | MFI.getObjectAlignment(FrameIndex)); |
396 | 96 | BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg) |
397 | 96 | .addFrameIndex(FrameIndex) |
398 | 96 | .addImm(0) |
399 | 96 | .addMemOperand(MMO); |
400 | 96 | } |
401 | | |
402 | | bool XCoreInstrInfo:: |
403 | 24 | reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { |
404 | 24 | assert((Cond.size() == 2) && |
405 | 24 | "Invalid XCore branch condition!"); |
406 | 24 | Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm())); |
407 | 24 | return false; |
408 | 24 | } |
409 | | |
410 | 27 | static inline bool isImmU6(unsigned val) { |
411 | 27 | return val < (1 << 6); |
412 | 27 | } |
413 | | |
414 | 39 | static inline bool isImmU16(unsigned val) { |
415 | 39 | return val < (1 << 16); |
416 | 39 | } |
417 | | |
418 | 40 | static bool isImmMskBitp(unsigned val) { |
419 | 40 | if (!isMask_32(val)) { |
420 | 38 | return false; |
421 | 38 | } |
422 | 2 | int N = Log2_32(val) + 1; |
423 | 2 | return (N >= 1 && N <= 8) || N == 161 || N == 241 || N == 321 ; |
424 | 2 | } |
425 | | |
426 | | MachineBasicBlock::iterator XCoreInstrInfo::loadImmediate( |
427 | | MachineBasicBlock &MBB, |
428 | | MachineBasicBlock::iterator MI, |
429 | 40 | unsigned Reg, uint64_t Value) const { |
430 | 40 | DebugLoc dl; |
431 | 40 | if (MI != MBB.end() && !MI->isDebugInstr()) |
432 | 40 | dl = MI->getDebugLoc(); |
433 | 40 | if (isImmMskBitp(Value)) { |
434 | 1 | int N = Log2_32(Value) + 1; |
435 | 1 | return BuildMI(MBB, MI, dl, get(XCore::MKMSK_rus), Reg) |
436 | 1 | .addImm(N) |
437 | 1 | .getInstr(); |
438 | 1 | } |
439 | 39 | if (isImmU16(Value)) { |
440 | 27 | int Opcode = isImmU6(Value) ? XCore::LDC_ru611 : XCore::LDC_lru616 ; |
441 | 27 | return BuildMI(MBB, MI, dl, get(Opcode), Reg).addImm(Value).getInstr(); |
442 | 27 | } |
443 | 12 | MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool(); |
444 | 12 | const Constant *C = ConstantInt::get( |
445 | 12 | Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Value); |
446 | 12 | unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); |
447 | 12 | return BuildMI(MBB, MI, dl, get(XCore::LDWCP_lru6), Reg) |
448 | 12 | .addConstantPoolIndex(Idx) |
449 | 12 | .getInstr(); |
450 | 12 | } |