| OLD | NEW | 
|    1 //===- subzero/src/IceInst.cpp - High-level instruction implementation ----===// |    1 //===- subzero/src/IceInst.cpp - High-level instruction implementation ----===// | 
|    2 // |    2 // | 
|    3 //                        The Subzero Code Generator |    3 //                        The Subzero Code Generator | 
|    4 // |    4 // | 
|    5 // This file is distributed under the University of Illinois Open Source |    5 // This file is distributed under the University of Illinois Open Source | 
|    6 // License. See LICENSE.TXT for details. |    6 // License. See LICENSE.TXT for details. | 
|    7 // |    7 // | 
|    8 //===----------------------------------------------------------------------===// |    8 //===----------------------------------------------------------------------===// | 
|    9 // |    9 // | 
|   10 // This file implements the Inst class, primarily the various |   10 // This file implements the Inst class, primarily the various | 
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  189             LiveEnd[VarNum] = InstNumber; |  189             LiveEnd[VarNum] = InstNumber; | 
|  190           } |  190           } | 
|  191         } |  191         } | 
|  192       } |  192       } | 
|  193     } |  193     } | 
|  194   } |  194   } | 
|  195 } |  195 } | 
|  196  |  196  | 
|  197 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, |  197 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, | 
|  198                        Variable *Dest) |  198                        Variable *Dest) | 
|  199     : Inst(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) { |  199     : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) { | 
|  200   // Verify AlignInBytes is 0 or a power of 2. |  200   // Verify AlignInBytes is 0 or a power of 2. | 
|  201   assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes)); |  201   assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes)); | 
|  202   addSource(ByteCount); |  202   addSource(ByteCount); | 
|  203 } |  203 } | 
|  204  |  204  | 
|  205 InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, |  205 InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, | 
|  206                                Operand *Source1, Operand *Source2) |  206                                Operand *Source1, Operand *Source2) | 
|  207     : Inst(Func, Inst::Arithmetic, 2, Dest), Op(Op) { |  207     : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) { | 
|  208   addSource(Source1); |  208   addSource(Source1); | 
|  209   addSource(Source2); |  209   addSource(Source2); | 
|  210 } |  210 } | 
|  211  |  211  | 
|  212 const char *InstArithmetic::getOpName(OpKind Op) { |  212 const char *InstArithmetic::getOpName(OpKind Op) { | 
|  213   size_t OpIndex = static_cast<size_t>(Op); |  213   size_t OpIndex = static_cast<size_t>(Op); | 
|  214   return OpIndex < InstArithmetic::_num |  214   return OpIndex < InstArithmetic::_num | 
|  215              ? InstArithmeticAttributes[OpIndex].DisplayString |  215              ? InstArithmeticAttributes[OpIndex].DisplayString | 
|  216              : "???"; |  216              : "???"; | 
|  217 } |  217 } | 
|  218  |  218  | 
|  219 bool InstArithmetic::isCommutative() const { |  219 bool InstArithmetic::isCommutative() const { | 
|  220   return InstArithmeticAttributes[getOp()].IsCommutative; |  220   return InstArithmeticAttributes[getOp()].IsCommutative; | 
|  221 } |  221 } | 
|  222  |  222  | 
|  223 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source) |  223 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source) | 
|  224     : Inst(Func, Inst::Assign, 1, Dest) { |  224     : InstHighLevel(Func, Inst::Assign, 1, Dest) { | 
|  225   addSource(Source); |  225   addSource(Source); | 
|  226 } |  226 } | 
|  227  |  227  | 
|  228 // If TargetTrue==TargetFalse, we turn it into an unconditional |  228 // If TargetTrue==TargetFalse, we turn it into an unconditional | 
|  229 // branch.  This ensures that, along with the 'switch' instruction |  229 // branch.  This ensures that, along with the 'switch' instruction | 
|  230 // semantics, there is at most one edge from one node to another. |  230 // semantics, there is at most one edge from one node to another. | 
|  231 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, |  231 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, | 
|  232                CfgNode *TargetFalse) |  232                CfgNode *TargetFalse) | 
|  233     : Inst(Func, Inst::Br, 1, NULL), TargetFalse(TargetFalse), |  233     : InstHighLevel(Func, Inst::Br, 1, NULL), TargetFalse(TargetFalse), | 
|  234       TargetTrue(TargetTrue) { |  234       TargetTrue(TargetTrue) { | 
|  235   if (TargetTrue == TargetFalse) { |  235   if (TargetTrue == TargetFalse) { | 
|  236     TargetTrue = NULL; // turn into unconditional version |  236     TargetTrue = NULL; // turn into unconditional version | 
|  237   } else { |  237   } else { | 
|  238     addSource(Source); |  238     addSource(Source); | 
|  239   } |  239   } | 
|  240 } |  240 } | 
|  241  |  241  | 
|  242 InstBr::InstBr(Cfg *Func, CfgNode *Target) |  242 InstBr::InstBr(Cfg *Func, CfgNode *Target) | 
|  243     : Inst(Func, Inst::Br, 0, NULL), TargetFalse(Target), TargetTrue(NULL) {} |  243     : InstHighLevel(Func, Inst::Br, 0, NULL), TargetFalse(Target), | 
 |  244       TargetTrue(NULL) {} | 
|  244  |  245  | 
|  245 NodeList InstBr::getTerminatorEdges() const { |  246 NodeList InstBr::getTerminatorEdges() const { | 
|  246   NodeList OutEdges; |  247   NodeList OutEdges; | 
|  247   OutEdges.push_back(TargetFalse); |  248   OutEdges.push_back(TargetFalse); | 
|  248   if (TargetTrue) |  249   if (TargetTrue) | 
|  249     OutEdges.push_back(TargetTrue); |  250     OutEdges.push_back(TargetTrue); | 
|  250   return OutEdges; |  251   return OutEdges; | 
|  251 } |  252 } | 
|  252  |  253  | 
|  253 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source) |  254 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source) | 
|  254     : Inst(Func, Inst::Cast, 1, Dest), CastKind(CastKind) { |  255     : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) { | 
|  255   addSource(Source); |  256   addSource(Source); | 
|  256 } |  257 } | 
|  257  |  258  | 
|  258 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest, |  259 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest, | 
|  259                                        Operand *Source1, Operand *Source2) |  260                                        Operand *Source1, Operand *Source2) | 
|  260     : Inst(Func, Inst::ExtractElement, 2, Dest) { |  261     : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) { | 
|  261   addSource(Source1); |  262   addSource(Source1); | 
|  262   addSource(Source2); |  263   addSource(Source2); | 
|  263 } |  264 } | 
|  264  |  265  | 
|  265 InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, |  266 InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 
|  266                    Operand *Source2) |  267                    Operand *Source2) | 
|  267     : Inst(Func, Inst::Fcmp, 2, Dest), Condition(Condition) { |  268     : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) { | 
|  268   addSource(Source1); |  269   addSource(Source1); | 
|  269   addSource(Source2); |  270   addSource(Source2); | 
|  270 } |  271 } | 
|  271  |  272  | 
|  272 InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, |  273 InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, | 
|  273                    Operand *Source2) |  274                    Operand *Source2) | 
|  274     : Inst(Func, Inst::Icmp, 2, Dest), Condition(Condition) { |  275     : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) { | 
|  275   addSource(Source1); |  276   addSource(Source1); | 
|  276   addSource(Source2); |  277   addSource(Source2); | 
|  277 } |  278 } | 
|  278  |  279  | 
|  279 InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest, |  280 InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest, | 
|  280                                      Operand *Source1, Operand *Source2, |  281                                      Operand *Source1, Operand *Source2, | 
|  281                                      Operand *Source3) |  282                                      Operand *Source3) | 
|  282     : Inst(Func, Inst::InsertElement, 3, Dest) { |  283     : InstHighLevel(Func, Inst::InsertElement, 3, Dest) { | 
|  283   addSource(Source1); |  284   addSource(Source1); | 
|  284   addSource(Source2); |  285   addSource(Source2); | 
|  285   addSource(Source3); |  286   addSource(Source3); | 
|  286 } |  287 } | 
|  287  |  288  | 
|  288 InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr) |  289 InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr) | 
|  289     : Inst(Func, Inst::Load, 1, Dest) { |  290     : InstHighLevel(Func, Inst::Load, 1, Dest) { | 
|  290   addSource(SourceAddr); |  291   addSource(SourceAddr); | 
|  291 } |  292 } | 
|  292  |  293  | 
|  293 InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest) |  294 InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest) | 
|  294     : Inst(Func, Phi, MaxSrcs, Dest) { |  295     : InstHighLevel(Func, Phi, MaxSrcs, Dest) { | 
|  295   Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs); |  296   Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs); | 
|  296 } |  297 } | 
|  297  |  298  | 
|  298 // TODO: A Switch instruction (and maybe others) can add duplicate |  299 // TODO: A Switch instruction (and maybe others) can add duplicate | 
|  299 // edges.  We may want to de-dup Phis and validate consistency (i.e., |  300 // edges.  We may want to de-dup Phis and validate consistency (i.e., | 
|  300 // the source operands are the same for duplicate edges), though it |  301 // the source operands are the same for duplicate edges), though it | 
|  301 // seems the current lowering code is OK with this situation. |  302 // seems the current lowering code is OK with this situation. | 
|  302 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { |  303 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { | 
|  303   Labels[getSrcSize()] = Label; |  304   Labels[getSrcSize()] = Label; | 
|  304   addSource(Source); |  305   addSource(Source); | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  343 Inst *InstPhi::lower(Cfg *Func) { |  344 Inst *InstPhi::lower(Cfg *Func) { | 
|  344   Variable *Dest = getDest(); |  345   Variable *Dest = getDest(); | 
|  345   assert(Dest); |  346   assert(Dest); | 
|  346   IceString PhiName = Dest->getName() + "_phi"; |  347   IceString PhiName = Dest->getName() + "_phi"; | 
|  347   Variable *NewSrc = Func->makeVariable(Dest->getType(), PhiName); |  348   Variable *NewSrc = Func->makeVariable(Dest->getType(), PhiName); | 
|  348   this->Dest = NewSrc; |  349   this->Dest = NewSrc; | 
|  349   return InstAssign::create(Func, Dest, NewSrc); |  350   return InstAssign::create(Func, Dest, NewSrc); | 
|  350 } |  351 } | 
|  351  |  352  | 
|  352 InstRet::InstRet(Cfg *Func, Operand *RetValue) |  353 InstRet::InstRet(Cfg *Func, Operand *RetValue) | 
|  353     : Inst(Func, Ret, RetValue ? 1 : 0, NULL) { |  354     : InstHighLevel(Func, Ret, RetValue ? 1 : 0, NULL) { | 
|  354   if (RetValue) |  355   if (RetValue) | 
|  355     addSource(RetValue); |  356     addSource(RetValue); | 
|  356 } |  357 } | 
|  357  |  358  | 
|  358 InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, |  359 InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, | 
|  359                        Operand *SourceTrue, Operand *SourceFalse) |  360                        Operand *SourceTrue, Operand *SourceFalse) | 
|  360     : Inst(Func, Inst::Select, 3, Dest) { |  361     : InstHighLevel(Func, Inst::Select, 3, Dest) { | 
|  361   assert(typeElementType(Condition->getType()) == IceType_i1); |  362   assert(typeElementType(Condition->getType()) == IceType_i1); | 
|  362   addSource(Condition); |  363   addSource(Condition); | 
|  363   addSource(SourceTrue); |  364   addSource(SourceTrue); | 
|  364   addSource(SourceFalse); |  365   addSource(SourceFalse); | 
|  365 } |  366 } | 
|  366  |  367  | 
|  367 InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr) |  368 InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr) | 
|  368     : Inst(Func, Inst::Store, 2, NULL) { |  369     : InstHighLevel(Func, Inst::Store, 2, NULL) { | 
|  369   addSource(Data); |  370   addSource(Data); | 
|  370   addSource(Addr); |  371   addSource(Addr); | 
|  371 } |  372 } | 
|  372  |  373  | 
|  373 InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, |  374 InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, | 
|  374                        CfgNode *LabelDefault) |  375                        CfgNode *LabelDefault) | 
|  375     : Inst(Func, Inst::Switch, 1, NULL), LabelDefault(LabelDefault), |  376     : InstHighLevel(Func, Inst::Switch, 1, NULL), LabelDefault(LabelDefault), | 
|  376       NumCases(NumCases) { |  377       NumCases(NumCases) { | 
|  377   addSource(Source); |  378   addSource(Source); | 
|  378   Values = Func->allocateArrayOf<uint64_t>(NumCases); |  379   Values = Func->allocateArrayOf<uint64_t>(NumCases); | 
|  379   Labels = Func->allocateArrayOf<CfgNode *>(NumCases); |  380   Labels = Func->allocateArrayOf<CfgNode *>(NumCases); | 
|  380   // Initialize in case buggy code doesn't set all entries |  381   // Initialize in case buggy code doesn't set all entries | 
|  381   for (SizeT I = 0; I < NumCases; ++I) { |  382   for (SizeT I = 0; I < NumCases; ++I) { | 
|  382     Values[I] = 0; |  383     Values[I] = 0; | 
|  383     Labels[I] = NULL; |  384     Labels[I] = NULL; | 
|  384   } |  385   } | 
|  385 } |  386 } | 
|  386  |  387  | 
|  387 void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) { |  388 void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) { | 
|  388   assert(CaseIndex < NumCases); |  389   assert(CaseIndex < NumCases); | 
|  389   Values[CaseIndex] = Value; |  390   Values[CaseIndex] = Value; | 
|  390   Labels[CaseIndex] = Label; |  391   Labels[CaseIndex] = Label; | 
|  391 } |  392 } | 
|  392  |  393  | 
|  393 NodeList InstSwitch::getTerminatorEdges() const { |  394 NodeList InstSwitch::getTerminatorEdges() const { | 
|  394   NodeList OutEdges; |  395   NodeList OutEdges; | 
|  395   OutEdges.push_back(LabelDefault); |  396   OutEdges.push_back(LabelDefault); | 
|  396   for (SizeT I = 0; I < NumCases; ++I) { |  397   for (SizeT I = 0; I < NumCases; ++I) { | 
|  397     OutEdges.push_back(Labels[I]); |  398     OutEdges.push_back(Labels[I]); | 
|  398   } |  399   } | 
|  399   return OutEdges; |  400   return OutEdges; | 
|  400 } |  401 } | 
|  401  |  402  | 
|  402 InstUnreachable::InstUnreachable(Cfg *Func) |  403 InstUnreachable::InstUnreachable(Cfg *Func) | 
|  403     : Inst(Func, Inst::Unreachable, 0, NULL) {} |  404     : InstHighLevel(Func, Inst::Unreachable, 0, NULL) {} | 
|  404  |  405  | 
|  405 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) |  406 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) | 
|  406     : Inst(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { |  407     : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { | 
|  407   assert(Dest); |  408   assert(Dest); | 
|  408   if (Src) |  409   if (Src) | 
|  409     addSource(Src); |  410     addSource(Src); | 
|  410 } |  411 } | 
|  411  |  412  | 
|  412 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) |  413 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) | 
|  413     : Inst(Func, Inst::FakeUse, 1, NULL) { |  414     : InstHighLevel(Func, Inst::FakeUse, 1, NULL) { | 
|  414   assert(Src); |  415   assert(Src); | 
|  415   addSource(Src); |  416   addSource(Src); | 
|  416 } |  417 } | 
|  417  |  418  | 
|  418 InstFakeKill::InstFakeKill(Cfg *Func, const VarList &KilledRegs, |  419 InstFakeKill::InstFakeKill(Cfg *Func, const VarList &KilledRegs, | 
|  419                            const Inst *Linked) |  420                            const Inst *Linked) | 
|  420     : Inst(Func, Inst::FakeKill, KilledRegs.size(), NULL), Linked(Linked) { |  421     : InstHighLevel(Func, Inst::FakeKill, KilledRegs.size(), NULL), | 
 |  422       Linked(Linked) { | 
|  421   for (VarList::const_iterator I = KilledRegs.begin(), E = KilledRegs.end(); |  423   for (VarList::const_iterator I = KilledRegs.begin(), E = KilledRegs.end(); | 
|  422        I != E; ++I) { |  424        I != E; ++I) { | 
|  423     Variable *Var = *I; |  425     Variable *Var = *I; | 
|  424     addSource(Var); |  426     addSource(Var); | 
|  425   } |  427   } | 
|  426 } |  428 } | 
|  427  |  429  | 
|  428 // ======================== Dump routines ======================== // |  430 // ======================== Dump routines ======================== // | 
|  429  |  431  | 
|  430 void Inst::dumpDecorated(const Cfg *Func) const { |  432 void Inst::dumpDecorated(const Cfg *Func) const { | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|  442     Str << buf; |  444     Str << buf; | 
|  443   } |  445   } | 
|  444   Str << "  "; |  446   Str << "  "; | 
|  445   if (isDeleted()) |  447   if (isDeleted()) | 
|  446     Str << "  //"; |  448     Str << "  //"; | 
|  447   dump(Func); |  449   dump(Func); | 
|  448   dumpExtras(Func); |  450   dumpExtras(Func); | 
|  449   Str << "\n"; |  451   Str << "\n"; | 
|  450 } |  452 } | 
|  451  |  453  | 
|  452 void Inst::emit(const Cfg * /*Func*/) const { |  | 
|  453   llvm_unreachable("emit() called on a non-lowered instruction"); |  | 
|  454 } |  | 
|  455  |  | 
|  456 void Inst::emitIAS(const Cfg *Func) const { emit(Func); } |  | 
|  457  |  | 
|  458 void Inst::dump(const Cfg *Func) const { |  454 void Inst::dump(const Cfg *Func) const { | 
|  459   Ostream &Str = Func->getContext()->getStrDump(); |  455   Ostream &Str = Func->getContext()->getStrDump(); | 
|  460   dumpDest(Func); |  456   dumpDest(Func); | 
|  461   Str << " =~ "; |  457   Str << " =~ "; | 
|  462   dumpSources(Func); |  458   dumpSources(Func); | 
|  463 } |  459 } | 
|  464  |  460  | 
|  465 void Inst::dumpExtras(const Cfg *Func) const { |  461 void Inst::dumpExtras(const Cfg *Func) const { | 
|  466   Ostream &Str = Func->getContext()->getStrDump(); |  462   Ostream &Str = Func->getContext()->getStrDump(); | 
|  467   bool First = true; |  463   bool First = true; | 
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  747   Str << "kill.pseudo "; |  743   Str << "kill.pseudo "; | 
|  748   dumpSources(Func); |  744   dumpSources(Func); | 
|  749 } |  745 } | 
|  750  |  746  | 
|  751 void InstTarget::dump(const Cfg *Func) const { |  747 void InstTarget::dump(const Cfg *Func) const { | 
|  752   Ostream &Str = Func->getContext()->getStrDump(); |  748   Ostream &Str = Func->getContext()->getStrDump(); | 
|  753   Str << "[TARGET] "; |  749   Str << "[TARGET] "; | 
|  754   Inst::dump(Func); |  750   Inst::dump(Func); | 
|  755 } |  751 } | 
|  756  |  752  | 
|  757 void InstTarget::dumpExtras(const Cfg *Func) const { Inst::dumpExtras(Func); } |  | 
|  758  |  | 
|  759 } // end of namespace Ice |  753 } // end of namespace Ice | 
| OLD | NEW |