Restrict sin/cos optimization to 64-bit only for now. 32-bit is a bit messy and less...
[oota-llvm.git] / lib / Target / R600 / AMDILISelDAGToDAG.cpp
1 //===-- AMDILISelDAGToDAG.cpp - A dag to dag inst selector for AMDIL ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //==-----------------------------------------------------------------------===//
9 //
10 /// \file
11 /// \brief Defines an instruction selector for the AMDGPU target.
12 //
13 //===----------------------------------------------------------------------===//
14 #include "AMDGPUInstrInfo.h"
15 #include "AMDGPUISelLowering.h" // For AMDGPUISD
16 #include "AMDGPURegisterInfo.h"
17 #include "AMDILDevices.h"
18 #include "R600InstrInfo.h"
19 #include "llvm/ADT/ValueMap.h"
20 #include "llvm/CodeGen/PseudoSourceValue.h"
21 #include "llvm/CodeGen/SelectionDAGISel.h"
22 #include "llvm/Support/Compiler.h"
23 #include "llvm/CodeGen/SelectionDAG.h"
24 #include <list>
25 #include <queue>
26
27 using namespace llvm;
28
29 //===----------------------------------------------------------------------===//
30 // Instruction Selector Implementation
31 //===----------------------------------------------------------------------===//
32
33 namespace {
34 /// AMDGPU specific code to select AMDGPU machine instructions for
35 /// SelectionDAG operations.
36 class AMDGPUDAGToDAGISel : public SelectionDAGISel {
37   // Subtarget - Keep a pointer to the AMDGPU Subtarget around so that we can
38   // make the right decision when generating code for different targets.
39   const AMDGPUSubtarget &Subtarget;
40 public:
41   AMDGPUDAGToDAGISel(TargetMachine &TM);
42   virtual ~AMDGPUDAGToDAGISel();
43
44   SDNode *Select(SDNode *N);
45   virtual const char *getPassName() const;
46
47 private:
48   inline SDValue getSmallIPtrImm(unsigned Imm);
49   bool FoldOperands(unsigned, const R600InstrInfo *, std::vector<SDValue> &);
50
51   // Complex pattern selectors
52   bool SelectADDRParam(SDValue Addr, SDValue& R1, SDValue& R2);
53   bool SelectADDR(SDValue N, SDValue &R1, SDValue &R2);
54   bool SelectADDR64(SDValue N, SDValue &R1, SDValue &R2);
55
56   static bool checkType(const Value *ptr, unsigned int addrspace);
57   static const Value *getBasePointerValue(const Value *V);
58
59   static bool isGlobalStore(const StoreSDNode *N);
60   static bool isPrivateStore(const StoreSDNode *N);
61   static bool isLocalStore(const StoreSDNode *N);
62   static bool isRegionStore(const StoreSDNode *N);
63
64   static bool isCPLoad(const LoadSDNode *N);
65   static bool isConstantLoad(const LoadSDNode *N, int cbID);
66   static bool isGlobalLoad(const LoadSDNode *N);
67   static bool isParamLoad(const LoadSDNode *N);
68   static bool isPrivateLoad(const LoadSDNode *N);
69   static bool isLocalLoad(const LoadSDNode *N);
70   static bool isRegionLoad(const LoadSDNode *N);
71
72   bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue& IntPtr);
73   bool SelectGlobalValueVariableOffset(SDValue Addr,
74       SDValue &BaseReg, SDValue& Offset);
75   bool SelectADDR8BitOffset(SDValue Addr, SDValue& Base, SDValue& Offset);
76   bool SelectADDRReg(SDValue Addr, SDValue& Base, SDValue& Offset);
77   bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset);
78
79   // Include the pieces autogenerated from the target description.
80 #include "AMDGPUGenDAGISel.inc"
81 };
82 }  // end anonymous namespace
83
84 /// \brief This pass converts a legalized DAG into a AMDGPU-specific
85 // DAG, ready for instruction scheduling.
86 FunctionPass *llvm::createAMDGPUISelDag(TargetMachine &TM
87                                        ) {
88   return new AMDGPUDAGToDAGISel(TM);
89 }
90
91 AMDGPUDAGToDAGISel::AMDGPUDAGToDAGISel(TargetMachine &TM
92                                      )
93   : SelectionDAGISel(TM), Subtarget(TM.getSubtarget<AMDGPUSubtarget>()) {
94 }
95
96 AMDGPUDAGToDAGISel::~AMDGPUDAGToDAGISel() {
97 }
98
99 SDValue AMDGPUDAGToDAGISel::getSmallIPtrImm(unsigned int Imm) {
100   return CurDAG->getTargetConstant(Imm, MVT::i32);
101 }
102
103 bool AMDGPUDAGToDAGISel::SelectADDRParam(
104     SDValue Addr, SDValue& R1, SDValue& R2) {
105
106   if (Addr.getOpcode() == ISD::FrameIndex) {
107     if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
108       R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
109       R2 = CurDAG->getTargetConstant(0, MVT::i32);
110     } else {
111       R1 = Addr;
112       R2 = CurDAG->getTargetConstant(0, MVT::i32);
113     }
114   } else if (Addr.getOpcode() == ISD::ADD) {
115     R1 = Addr.getOperand(0);
116     R2 = Addr.getOperand(1);
117   } else {
118     R1 = Addr;
119     R2 = CurDAG->getTargetConstant(0, MVT::i32);
120   }
121   return true;
122 }
123
124 bool AMDGPUDAGToDAGISel::SelectADDR(SDValue Addr, SDValue& R1, SDValue& R2) {
125   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
126       Addr.getOpcode() == ISD::TargetGlobalAddress) {
127     return false;
128   }
129   return SelectADDRParam(Addr, R1, R2);
130 }
131
132
133 bool AMDGPUDAGToDAGISel::SelectADDR64(SDValue Addr, SDValue& R1, SDValue& R2) {
134   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
135       Addr.getOpcode() == ISD::TargetGlobalAddress) {
136     return false;
137   }
138
139   if (Addr.getOpcode() == ISD::FrameIndex) {
140     if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
141       R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
142       R2 = CurDAG->getTargetConstant(0, MVT::i64);
143     } else {
144       R1 = Addr;
145       R2 = CurDAG->getTargetConstant(0, MVT::i64);
146     }
147   } else if (Addr.getOpcode() == ISD::ADD) {
148     R1 = Addr.getOperand(0);
149     R2 = Addr.getOperand(1);
150   } else {
151     R1 = Addr;
152     R2 = CurDAG->getTargetConstant(0, MVT::i64);
153   }
154   return true;
155 }
156
157 SDNode *AMDGPUDAGToDAGISel::Select(SDNode *N) {
158   unsigned int Opc = N->getOpcode();
159   if (N->isMachineOpcode()) {
160     return NULL;   // Already selected.
161   }
162   switch (Opc) {
163   default: break;
164   case ISD::FrameIndex: {
165     if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
166       unsigned int FI = FIN->getIndex();
167       EVT OpVT = N->getValueType(0);
168       unsigned int NewOpc = AMDGPU::COPY;
169       SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
170       return CurDAG->SelectNodeTo(N, NewOpc, OpVT, TFI);
171     }
172     break;
173   }
174   case ISD::ConstantFP:
175   case ISD::Constant: {
176     const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>();
177     // XXX: Custom immediate lowering not implemented yet.  Instead we use
178     // pseudo instructions defined in SIInstructions.td
179     if (ST.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
180       break;
181     }
182     const R600InstrInfo *TII = static_cast<const R600InstrInfo*>(TM.getInstrInfo());
183
184     uint64_t ImmValue = 0;
185     unsigned ImmReg = AMDGPU::ALU_LITERAL_X;
186
187     if (N->getOpcode() == ISD::ConstantFP) {
188       // XXX: 64-bit Immediates not supported yet
189       assert(N->getValueType(0) != MVT::f64);
190
191       ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N);
192       APFloat Value = C->getValueAPF();
193       float FloatValue = Value.convertToFloat();
194       if (FloatValue == 0.0) {
195         ImmReg = AMDGPU::ZERO;
196       } else if (FloatValue == 0.5) {
197         ImmReg = AMDGPU::HALF;
198       } else if (FloatValue == 1.0) {
199         ImmReg = AMDGPU::ONE;
200       } else {
201         ImmValue = Value.bitcastToAPInt().getZExtValue();
202       }
203     } else {
204       // XXX: 64-bit Immediates not supported yet
205       assert(N->getValueType(0) != MVT::i64);
206
207       ConstantSDNode *C = dyn_cast<ConstantSDNode>(N);
208       if (C->getZExtValue() == 0) {
209         ImmReg = AMDGPU::ZERO;
210       } else if (C->getZExtValue() == 1) {
211         ImmReg = AMDGPU::ONE_INT;
212       } else {
213         ImmValue = C->getZExtValue();
214       }
215     }
216
217     for (SDNode::use_iterator Use = N->use_begin(), Next = llvm::next(Use);
218                               Use != SDNode::use_end(); Use = Next) {
219       Next = llvm::next(Use);
220       std::vector<SDValue> Ops;
221       for (unsigned i = 0; i < Use->getNumOperands(); ++i) {
222         Ops.push_back(Use->getOperand(i));
223       }
224
225       if (!Use->isMachineOpcode()) {
226           if (ImmReg == AMDGPU::ALU_LITERAL_X) {
227             // We can only use literal constants (e.g. AMDGPU::ZERO,
228             // AMDGPU::ONE, etc) in machine opcodes.
229             continue;
230           }
231       } else {
232         if (!TII->isALUInstr(Use->getMachineOpcode())) {
233           continue;
234         }
235
236         int ImmIdx = TII->getOperandIdx(Use->getMachineOpcode(), R600Operands::IMM);
237         assert(ImmIdx != -1);
238
239         // subtract one from ImmIdx, because the DST operand is usually index
240         // 0 for MachineInstrs, but we have no DST in the Ops vector.
241         ImmIdx--;
242
243         // Check that we aren't already using an immediate.
244         // XXX: It's possible for an instruction to have more than one
245         // immediate operand, but this is not supported yet.
246         if (ImmReg == AMDGPU::ALU_LITERAL_X) {
247           ConstantSDNode *C = dyn_cast<ConstantSDNode>(Use->getOperand(ImmIdx));
248           assert(C);
249
250           if (C->getZExtValue() != 0) {
251             // This instruction is already using an immediate.
252             continue;
253           }
254
255           // Set the immediate value
256           Ops[ImmIdx] = CurDAG->getTargetConstant(ImmValue, MVT::i32);
257         }
258       }
259       // Set the immediate register
260       Ops[Use.getOperandNo()] = CurDAG->getRegister(ImmReg, MVT::i32);
261
262       CurDAG->UpdateNodeOperands(*Use, Ops.data(), Use->getNumOperands());
263     }
264     break;
265   }
266   }
267   SDNode *Result = SelectCode(N);
268
269   // Fold operands of selected node
270
271   const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>();
272   if (ST.device()->getGeneration() <= AMDGPUDeviceInfo::HD6XXX) {
273     const R600InstrInfo *TII =
274         static_cast<const R600InstrInfo*>(TM.getInstrInfo());
275     if (Result && TII->isALUInstr(Result->getMachineOpcode())) {
276       bool IsModified = false;
277       do {
278         std::vector<SDValue> Ops;
279         for(SDNode::op_iterator I = Result->op_begin(), E = Result->op_end();
280             I != E; ++I)
281           Ops.push_back(*I);
282         IsModified = FoldOperands(Result->getMachineOpcode(), TII, Ops);
283         if (IsModified) {
284           Result = CurDAG->MorphNodeTo(Result, Result->getOpcode(),
285               Result->getVTList(), Ops.data(), Ops.size());
286         }
287       } while (IsModified);
288     }
289   }
290
291   return Result;
292 }
293
294 bool AMDGPUDAGToDAGISel::FoldOperands(unsigned Opcode,
295     const R600InstrInfo *TII, std::vector<SDValue> &Ops) {
296   int OperandIdx[] = {
297     TII->getOperandIdx(Opcode, R600Operands::SRC0),
298     TII->getOperandIdx(Opcode, R600Operands::SRC1),
299     TII->getOperandIdx(Opcode, R600Operands::SRC2)
300   };
301   int SelIdx[] = {
302     TII->getOperandIdx(Opcode, R600Operands::SRC0_SEL),
303     TII->getOperandIdx(Opcode, R600Operands::SRC1_SEL),
304     TII->getOperandIdx(Opcode, R600Operands::SRC2_SEL)
305   };
306   for (unsigned i = 0; i < 3; i++) {
307     if (OperandIdx[i] < 0)
308       return false;
309     SDValue Operand = Ops[OperandIdx[i] - 1];
310     switch (Operand.getOpcode()) {
311     case AMDGPUISD::CONST_ADDRESS: {
312       SDValue CstOffset;
313       if (!Operand.getValueType().isVector() &&
314           SelectGlobalValueConstantOffset(Operand.getOperand(0), CstOffset)) {
315         Ops[OperandIdx[i] - 1] = CurDAG->getRegister(AMDGPU::ALU_CONST, MVT::f32);
316         Ops[SelIdx[i] - 1] = CstOffset;
317         return true;
318       }
319       }
320       break;
321     default:
322       break;
323     }
324   }
325   return false;
326 }
327
328 bool AMDGPUDAGToDAGISel::checkType(const Value *ptr, unsigned int addrspace) {
329   if (!ptr) {
330     return false;
331   }
332   Type *ptrType = ptr->getType();
333   return dyn_cast<PointerType>(ptrType)->getAddressSpace() == addrspace;
334 }
335
336 const Value * AMDGPUDAGToDAGISel::getBasePointerValue(const Value *V) {
337   if (!V) {
338     return NULL;
339   }
340   const Value *ret = NULL;
341   ValueMap<const Value *, bool> ValueBitMap;
342   std::queue<const Value *, std::list<const Value *> > ValueQueue;
343   ValueQueue.push(V);
344   while (!ValueQueue.empty()) {
345     V = ValueQueue.front();
346     if (ValueBitMap.find(V) == ValueBitMap.end()) {
347       ValueBitMap[V] = true;
348       if (dyn_cast<Argument>(V) && dyn_cast<PointerType>(V->getType())) {
349         ret = V;
350         break;
351       } else if (dyn_cast<GlobalVariable>(V)) {
352         ret = V;
353         break;
354       } else if (dyn_cast<Constant>(V)) {
355         const ConstantExpr *CE = dyn_cast<ConstantExpr>(V);
356         if (CE) {
357           ValueQueue.push(CE->getOperand(0));
358         }
359       } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
360         ret = AI;
361         break;
362       } else if (const Instruction *I = dyn_cast<Instruction>(V)) {
363         uint32_t numOps = I->getNumOperands();
364         for (uint32_t x = 0; x < numOps; ++x) {
365           ValueQueue.push(I->getOperand(x));
366         }
367       } else {
368         assert(!"Found a Value that we didn't know how to handle!");
369       }
370     }
371     ValueQueue.pop();
372   }
373   return ret;
374 }
375
376 bool AMDGPUDAGToDAGISel::isGlobalStore(const StoreSDNode *N) {
377   return checkType(N->getSrcValue(), AMDGPUAS::GLOBAL_ADDRESS);
378 }
379
380 bool AMDGPUDAGToDAGISel::isPrivateStore(const StoreSDNode *N) {
381   return (!checkType(N->getSrcValue(), AMDGPUAS::LOCAL_ADDRESS)
382           && !checkType(N->getSrcValue(), AMDGPUAS::GLOBAL_ADDRESS)
383           && !checkType(N->getSrcValue(), AMDGPUAS::REGION_ADDRESS));
384 }
385
386 bool AMDGPUDAGToDAGISel::isLocalStore(const StoreSDNode *N) {
387   return checkType(N->getSrcValue(), AMDGPUAS::LOCAL_ADDRESS);
388 }
389
390 bool AMDGPUDAGToDAGISel::isRegionStore(const StoreSDNode *N) {
391   return checkType(N->getSrcValue(), AMDGPUAS::REGION_ADDRESS);
392 }
393
394 bool AMDGPUDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int cbID) {
395   if (checkType(N->getSrcValue(), AMDGPUAS::CONSTANT_ADDRESS)) {
396     return true;
397   }
398   MachineMemOperand *MMO = N->getMemOperand();
399   const Value *V = MMO->getValue();
400   const Value *BV = getBasePointerValue(V);
401   if (MMO
402       && MMO->getValue()
403       && ((V && dyn_cast<GlobalValue>(V))
404           || (BV && dyn_cast<GlobalValue>(
405                         getBasePointerValue(MMO->getValue()))))) {
406     return checkType(N->getSrcValue(), AMDGPUAS::PRIVATE_ADDRESS);
407   } else {
408     return false;
409   }
410 }
411
412 bool AMDGPUDAGToDAGISel::isGlobalLoad(const LoadSDNode *N) {
413   return checkType(N->getSrcValue(), AMDGPUAS::GLOBAL_ADDRESS);
414 }
415
416 bool AMDGPUDAGToDAGISel::isParamLoad(const LoadSDNode *N) {
417   return checkType(N->getSrcValue(), AMDGPUAS::PARAM_I_ADDRESS);
418 }
419
420 bool AMDGPUDAGToDAGISel::isLocalLoad(const  LoadSDNode *N) {
421   return checkType(N->getSrcValue(), AMDGPUAS::LOCAL_ADDRESS);
422 }
423
424 bool AMDGPUDAGToDAGISel::isRegionLoad(const  LoadSDNode *N) {
425   return checkType(N->getSrcValue(), AMDGPUAS::REGION_ADDRESS);
426 }
427
428 bool AMDGPUDAGToDAGISel::isCPLoad(const LoadSDNode *N) {
429   MachineMemOperand *MMO = N->getMemOperand();
430   if (checkType(N->getSrcValue(), AMDGPUAS::PRIVATE_ADDRESS)) {
431     if (MMO) {
432       const Value *V = MMO->getValue();
433       const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V);
434       if (PSV && PSV == PseudoSourceValue::getConstantPool()) {
435         return true;
436       }
437     }
438   }
439   return false;
440 }
441
442 bool AMDGPUDAGToDAGISel::isPrivateLoad(const LoadSDNode *N) {
443   if (checkType(N->getSrcValue(), AMDGPUAS::PRIVATE_ADDRESS)) {
444     // Check to make sure we are not a constant pool load or a constant load
445     // that is marked as a private load
446     if (isCPLoad(N) || isConstantLoad(N, -1)) {
447       return false;
448     }
449   }
450   if (!checkType(N->getSrcValue(), AMDGPUAS::LOCAL_ADDRESS)
451       && !checkType(N->getSrcValue(), AMDGPUAS::GLOBAL_ADDRESS)
452       && !checkType(N->getSrcValue(), AMDGPUAS::REGION_ADDRESS)
453       && !checkType(N->getSrcValue(), AMDGPUAS::CONSTANT_ADDRESS)
454       && !checkType(N->getSrcValue(), AMDGPUAS::PARAM_D_ADDRESS)
455       && !checkType(N->getSrcValue(), AMDGPUAS::PARAM_I_ADDRESS)) {
456     return true;
457   }
458   return false;
459 }
460
461 const char *AMDGPUDAGToDAGISel::getPassName() const {
462   return "AMDGPU DAG->DAG Pattern Instruction Selection";
463 }
464
465 #ifdef DEBUGTMP
466 #undef INT64_C
467 #endif
468 #undef DEBUGTMP
469
470 ///==== AMDGPU Functions ====///
471
472 bool AMDGPUDAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr,
473     SDValue& IntPtr) {
474   if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Addr)) {
475     IntPtr = CurDAG->getIntPtrConstant(Cst->getZExtValue() / 4, true);
476     return true;
477   }
478   return false;
479 }
480
481 bool AMDGPUDAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr,
482     SDValue& BaseReg, SDValue &Offset) {
483   if (!dyn_cast<ConstantSDNode>(Addr)) {
484     BaseReg = Addr;
485     Offset = CurDAG->getIntPtrConstant(0, true);
486     return true;
487   }
488   return false;
489 }
490
491 bool AMDGPUDAGToDAGISel::SelectADDR8BitOffset(SDValue Addr, SDValue& Base,
492                                              SDValue& Offset) {
493   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
494       Addr.getOpcode() == ISD::TargetGlobalAddress) {
495     return false;
496   }
497
498
499   if (Addr.getOpcode() == ISD::ADD) {
500     bool Match = false;
501
502     // Find the base ptr and the offset
503     for (unsigned i = 0; i < Addr.getNumOperands(); i++) {
504       SDValue Arg = Addr.getOperand(i);
505       ConstantSDNode * OffsetNode = dyn_cast<ConstantSDNode>(Arg);
506       // This arg isn't a constant so it must be the base PTR.
507       if (!OffsetNode) {
508         Base = Addr.getOperand(i);
509         continue;
510       }
511       // Check if the constant argument fits in 8-bits.  The offset is in bytes
512       // so we need to convert it to dwords.
513       if (isUInt<8>(OffsetNode->getZExtValue() >> 2)) {
514         Match = true;
515         Offset = CurDAG->getTargetConstant(OffsetNode->getZExtValue() >> 2,
516                                            MVT::i32);
517       }
518     }
519     return Match;
520   }
521
522   // Default case, no offset
523   Base = Addr;
524   Offset = CurDAG->getTargetConstant(0, MVT::i32);
525   return true;
526 }
527
528 bool AMDGPUDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
529                                            SDValue &Offset) {
530   ConstantSDNode * IMMOffset;
531
532   if (Addr.getOpcode() == ISD::ADD
533       && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
534       && isInt<16>(IMMOffset->getZExtValue())) {
535
536       Base = Addr.getOperand(0);
537       Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
538       return true;
539   // If the pointer address is constant, we can move it to the offset field.
540   } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr))
541              && isInt<16>(IMMOffset->getZExtValue())) {
542     Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
543                                   CurDAG->getEntryNode().getDebugLoc(),
544                                   AMDGPU::ZERO, MVT::i32);
545     Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
546     return true;
547   }
548
549   // Default case, no offset
550   Base = Addr;
551   Offset = CurDAG->getTargetConstant(0, MVT::i32);
552   return true;
553 }
554
555 bool AMDGPUDAGToDAGISel::SelectADDRReg(SDValue Addr, SDValue& Base,
556                                       SDValue& Offset) {
557   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
558       Addr.getOpcode() == ISD::TargetGlobalAddress  ||
559       Addr.getOpcode() != ISD::ADD) {
560     return false;
561   }
562
563   Base = Addr.getOperand(0);
564   Offset = Addr.getOperand(1);
565
566   return true;
567 }