Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: src/IceInst.cpp

Issue 1234803007: Introduction of improved switch lowering. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 /// \file 10 /// \file
11 /// This file implements the Inst class, primarily the various 11 /// This file implements the Inst class, primarily the various
12 /// subclass constructors and dump routines. 12 /// subclass constructors and dump routines.
13 /// 13 ///
14 //===----------------------------------------------------------------------===// 14 //===----------------------------------------------------------------------===//
15 15
16 #include "IceInst.h" 16 #include "IceInst.h"
17 17
18 #include "IceCfg.h" 18 #include "IceCfg.h"
19 #include "IceCfgNode.h" 19 #include "IceCfgNode.h"
20 #include "IceLiveness.h" 20 #include "IceLiveness.h"
21 #include "IceOperand.h" 21 #include "IceOperand.h"
22 #include "IceTargetLowering.h"
22 23
23 namespace Ice { 24 namespace Ice {
24 25
25 namespace { 26 namespace {
26 27
27 // Using non-anonymous struct so that array_lengthof works. 28 // Using non-anonymous struct so that array_lengthof works.
28 const struct InstArithmeticAttributes_ { 29 const struct InstArithmeticAttributes_ {
29 const char *DisplayString; 30 const char *DisplayString;
30 bool IsCommutative; 31 bool IsCommutative;
31 } InstArithmeticAttributes[] = { 32 } InstArithmeticAttributes[] = {
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 289
289 NodeList InstBr::getTerminatorEdges() const { 290 NodeList InstBr::getTerminatorEdges() const {
290 NodeList OutEdges; 291 NodeList OutEdges;
291 OutEdges.reserve(TargetTrue ? 2 : 1); 292 OutEdges.reserve(TargetTrue ? 2 : 1);
292 OutEdges.push_back(TargetFalse); 293 OutEdges.push_back(TargetFalse);
293 if (TargetTrue) 294 if (TargetTrue)
294 OutEdges.push_back(TargetTrue); 295 OutEdges.push_back(TargetTrue);
295 return OutEdges; 296 return OutEdges;
296 } 297 }
297 298
298 bool InstBr::repointEdge(CfgNode *OldNode, CfgNode *NewNode) { 299 bool InstBr::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
300 bool Found = false;
299 if (TargetFalse == OldNode) { 301 if (TargetFalse == OldNode) {
300 TargetFalse = NewNode; 302 TargetFalse = NewNode;
301 return true; 303 Found = true;
302 } else if (TargetTrue == OldNode) { 304 }
305 if (TargetTrue == OldNode) {
303 TargetTrue = NewNode; 306 TargetTrue = NewNode;
304 return true; 307 Found = true;
305 } 308 }
306 return false; 309 return Found;
307 } 310 }
308 311
309 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source) 312 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source)
310 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) { 313 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) {
311 addSource(Source); 314 addSource(Source);
312 } 315 }
313 316
314 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest, 317 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest,
315 Operand *Source1, Operand *Source2) 318 Operand *Source1, Operand *Source2)
316 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) { 319 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 Labels[CaseIndex] = Label; 457 Labels[CaseIndex] = Label;
455 } 458 }
456 459
457 NodeList InstSwitch::getTerminatorEdges() const { 460 NodeList InstSwitch::getTerminatorEdges() const {
458 NodeList OutEdges; 461 NodeList OutEdges;
459 OutEdges.reserve(NumCases + 1); 462 OutEdges.reserve(NumCases + 1);
460 OutEdges.push_back(LabelDefault); 463 OutEdges.push_back(LabelDefault);
461 for (SizeT I = 0; I < NumCases; ++I) { 464 for (SizeT I = 0; I < NumCases; ++I) {
462 OutEdges.push_back(Labels[I]); 465 OutEdges.push_back(Labels[I]);
463 } 466 }
467 std::sort(OutEdges.begin(), OutEdges.end());
Jim Stichnoth 2015/07/15 19:17:42 What is the comparison function here? It needs to
ascull 2015/07/16 19:38:45 Done.
468 auto last = std::unique(OutEdges.begin(), OutEdges.end());
Jim Stichnoth 2015/07/15 19:17:42 capitalize Last per LLVM convention
ascull 2015/07/16 19:38:45 Done.
469 OutEdges.erase(last, OutEdges.end());
464 return OutEdges; 470 return OutEdges;
465 } 471 }
466 472
467 bool InstSwitch::repointEdge(CfgNode *OldNode, CfgNode *NewNode) { 473 bool InstSwitch::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
474 bool Found = false;
468 if (LabelDefault == OldNode) { 475 if (LabelDefault == OldNode) {
469 LabelDefault = NewNode; 476 LabelDefault = NewNode;
470 return true; 477 Found = true;
471 } 478 }
472 for (SizeT I = 0; I < NumCases; ++I) { 479 for (SizeT I = 0; I < NumCases; ++I) {
473 if (Labels[I] == OldNode) { 480 if (Labels[I] == OldNode) {
474 Labels[I] = NewNode; 481 Labels[I] = NewNode;
475 return true; 482 Found = true;
476 } 483 }
477 } 484 }
478 return false; 485 return Found;
479 } 486 }
480 487
481 InstUnreachable::InstUnreachable(Cfg *Func) 488 InstUnreachable::InstUnreachable(Cfg *Func)
482 : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {} 489 : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {}
483 490
484 InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption) 491 InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption)
485 : InstHighLevel(Func, Inst::BundleLock, 0, nullptr), 492 : InstHighLevel(Func, Inst::BundleLock, 0, nullptr),
486 BundleOption(BundleOption) {} 493 BundleOption(BundleOption) {}
487 494
488 InstBundleUnlock::InstBundleUnlock(Cfg *Func) 495 InstBundleUnlock::InstBundleUnlock(Cfg *Func)
489 : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {} 496 : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {}
490 497
491 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) 498 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
492 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { 499 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
493 assert(Dest); 500 assert(Dest);
494 if (Src) 501 if (Src)
495 addSource(Src); 502 addSource(Src);
496 } 503 }
497 504
498 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) 505 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src)
499 : InstHighLevel(Func, Inst::FakeUse, 1, nullptr) { 506 : InstHighLevel(Func, Inst::FakeUse, 1, nullptr) {
500 assert(Src); 507 assert(Src);
501 addSource(Src); 508 addSource(Src);
502 } 509 }
503 510
504 InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked) 511 InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
505 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {} 512 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
506 513
514 InstJumpTable::InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default)
515 : InstHighLevel(Func, Inst::JumpTable, 1, nullptr),
516 Number(Func->getTarget()->makeNextLabelNumber()), NumTargets(NumTargets) {
517 Targets = Func->allocateArrayOf<CfgNode *>(NumTargets);
518 for (SizeT I = 0; I < NumTargets; ++I)
519 Targets[I] = Default;
Jim Stichnoth 2015/07/15 19:17:42 For safety, maybe all of these could be initialize
ascull 2015/07/16 19:38:45 Every element of the jump table can be jumped to s
520 }
521
522 bool InstJumpTable::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
523 bool Found = false;
524 for (SizeT I = 0; I < NumTargets; ++I) {
525 if (Targets[I] == OldNode) {
526 Targets[I] = NewNode;
527 Found = true;
528 }
529 }
530 return Found;
531 }
532
533 IceString InstJumpTable::getName(const Cfg *Func) const {
534 return ".L" + Func->getFunctionName()
535 + "$jumptable$__" + std::to_string(Number);
536 }
537
507 Type InstCall::getReturnType() const { 538 Type InstCall::getReturnType() const {
508 if (Dest == nullptr) 539 if (Dest == nullptr)
509 return IceType_void; 540 return IceType_void;
510 return Dest->getType(); 541 return Dest->getType();
511 } 542 }
512 543
513 // ======================== Dump routines ======================== // 544 // ======================== Dump routines ======================== //
514 545
515 void Inst::dumpDecorated(const Cfg *Func) const { 546 void Inst::dumpDecorated(const Cfg *Func) const {
516 if (!BuildDefs::dump()) 547 if (!BuildDefs::dump())
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 941
911 void InstFakeKill::dump(const Cfg *Func) const { 942 void InstFakeKill::dump(const Cfg *Func) const {
912 if (!BuildDefs::dump()) 943 if (!BuildDefs::dump())
913 return; 944 return;
914 Ostream &Str = Func->getContext()->getStrDump(); 945 Ostream &Str = Func->getContext()->getStrDump();
915 if (Linked->isDeleted()) 946 if (Linked->isDeleted())
916 Str << "// "; 947 Str << "// ";
917 Str << "kill.pseudo scratch_regs"; 948 Str << "kill.pseudo scratch_regs";
918 } 949 }
919 950
951 void InstJumpTable::emit(const Cfg *Func) const {
Jim Stichnoth 2015/07/15 19:17:42 This should be tied in to the target data lowering
ascull 2015/07/16 19:38:45 I'm going to be doing this for emitIAS which is st
Jim Stichnoth 2015/07/17 15:33:47 TODO is fine for now, thanks.
952 // TODO(ascull): should this be a target specific lowering (with access built
953 // in?) and just have InstJumpTable as a high level, similar to br? or should
954 // this follow the same path as emitIAS i.e. put it in global context and
955 // produce this code later?
956 if (!BuildDefs::dump())
957 return;
958 Ostream &Str = Func->getContext()->getStrEmit();
959 // TODO(ascull): softcode pointer size of 4
960 // TODO(ascull): is .long portable?
961 Str << "\n\t.section\t.rodata."
962 << Func->getFunctionName() << "$jumptable,\"a\",@progbits\n"
963 << "\t.align 4\n"
964 << getName(Func) << ":";
965 for (SizeT I = 0; I < NumTargets; ++I)
966 Str << "\n\t.long\t" << Targets[I]->getAsmName();
967 Str << "\n\n\t.text";
968 }
969 void InstJumpTable::emitIAS(const Cfg *Func) const {
jvoung (off chromium) 2015/07/15 18:32:01 add a newline between functions
ascull 2015/07/16 19:38:45 Done.
970 // TODO(ascull): put jump table in the global context for emision later
jvoung (off chromium) 2015/07/15 18:32:01 emision -> emission
ascull 2015/07/16 19:38:45 Done.
971 (void)Func;
972 }
973
974 void InstJumpTable::dump(const Cfg *Func) const {
975 if (!BuildDefs::dump())
976 return;
977 Ostream &Str = Func->getContext()->getStrDump();
978 Str << "jump table [";
979 for (SizeT I = 0; I < NumTargets; ++I)
980 Str << "\n " << Targets[I]->getName();
981 Str << "\n ]";
982 }
983
920 void InstTarget::dump(const Cfg *Func) const { 984 void InstTarget::dump(const Cfg *Func) const {
921 if (!BuildDefs::dump()) 985 if (!BuildDefs::dump())
922 return; 986 return;
923 Ostream &Str = Func->getContext()->getStrDump(); 987 Ostream &Str = Func->getContext()->getStrDump();
924 Str << "[TARGET] "; 988 Str << "[TARGET] ";
925 Inst::dump(Func); 989 Inst::dump(Func);
926 } 990 }
927 991
928 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { 992 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
929 const auto SrcVar = llvm::dyn_cast<const Variable>(Source); 993 const auto SrcVar = llvm::dyn_cast<const Variable>(Source);
930 if (!SrcVar) 994 if (!SrcVar)
931 return false; 995 return false;
932 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) { 996 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) {
933 // TODO: On x86-64, instructions like "mov eax, eax" are used to 997 // TODO: On x86-64, instructions like "mov eax, eax" are used to
934 // clear the upper 32 bits of rax. We need to recognize and 998 // clear the upper 32 bits of rax. We need to recognize and
935 // preserve these. 999 // preserve these.
936 return true; 1000 return true;
937 } 1001 }
938 if (!Dest->hasReg() && !SrcVar->hasReg() && 1002 if (!Dest->hasReg() && !SrcVar->hasReg() &&
939 Dest->getStackOffset() == SrcVar->getStackOffset()) 1003 Dest->getStackOffset() == SrcVar->getStackOffset())
940 return true; 1004 return true;
941 return false; 1005 return false;
942 } 1006 }
943 1007
944 } // end of namespace Ice 1008 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698