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

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: Safer check for 0 size type 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
« no previous file with comments | « src/IceInst.h ('k') | src/IceInstARM32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(),
468 [](const CfgNode *x, const CfgNode *y) {
469 return x->getIndex() < y->getIndex();
470 });
471 auto Last = std::unique(OutEdges.begin(), OutEdges.end());
472 OutEdges.erase(Last, OutEdges.end());
464 return OutEdges; 473 return OutEdges;
465 } 474 }
466 475
467 bool InstSwitch::repointEdge(CfgNode *OldNode, CfgNode *NewNode) { 476 bool InstSwitch::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
477 bool Found = false;
468 if (LabelDefault == OldNode) { 478 if (LabelDefault == OldNode) {
469 LabelDefault = NewNode; 479 LabelDefault = NewNode;
470 return true; 480 Found = true;
471 } 481 }
472 for (SizeT I = 0; I < NumCases; ++I) { 482 for (SizeT I = 0; I < NumCases; ++I) {
473 if (Labels[I] == OldNode) { 483 if (Labels[I] == OldNode) {
474 Labels[I] = NewNode; 484 Labels[I] = NewNode;
475 return true; 485 Found = true;
476 } 486 }
477 } 487 }
478 return false; 488 return Found;
479 } 489 }
480 490
481 InstUnreachable::InstUnreachable(Cfg *Func) 491 InstUnreachable::InstUnreachable(Cfg *Func)
482 : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {} 492 : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {}
483 493
484 InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption) 494 InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption)
485 : InstHighLevel(Func, Inst::BundleLock, 0, nullptr), 495 : InstHighLevel(Func, Inst::BundleLock, 0, nullptr),
486 BundleOption(BundleOption) {} 496 BundleOption(BundleOption) {}
487 497
488 InstBundleUnlock::InstBundleUnlock(Cfg *Func) 498 InstBundleUnlock::InstBundleUnlock(Cfg *Func)
489 : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {} 499 : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {}
490 500
491 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) 501 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
492 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { 502 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
493 assert(Dest); 503 assert(Dest);
494 if (Src) 504 if (Src)
495 addSource(Src); 505 addSource(Src);
496 } 506 }
497 507
498 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) 508 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src)
499 : InstHighLevel(Func, Inst::FakeUse, 1, nullptr) { 509 : InstHighLevel(Func, Inst::FakeUse, 1, nullptr) {
500 assert(Src); 510 assert(Src);
501 addSource(Src); 511 addSource(Src);
502 } 512 }
503 513
504 InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked) 514 InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
505 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {} 515 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
506 516
517 InstJumpTable::InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default)
518 : InstHighLevel(Func, Inst::JumpTable, 1, nullptr),
519 LabelNumber(Func->getTarget()->makeNextLabelNumber()),
520 NumTargets(NumTargets) {
521 Targets = Func->allocateArrayOf<CfgNode *>(NumTargets);
522 for (SizeT I = 0; I < NumTargets; ++I)
523 Targets[I] = Default;
524 }
525
526 bool InstJumpTable::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
527 bool Found = false;
528 for (SizeT I = 0; I < NumTargets; ++I) {
529 if (Targets[I] == OldNode) {
530 Targets[I] = NewNode;
531 Found = true;
532 }
533 }
534 return Found;
535 }
536
537 IceString InstJumpTable::getName(const Cfg *Func) const {
538 return ".L" + Func->getFunctionName() + "$jumptable$__" +
539 std::to_string(LabelNumber);
540 }
541
507 Type InstCall::getReturnType() const { 542 Type InstCall::getReturnType() const {
508 if (Dest == nullptr) 543 if (Dest == nullptr)
509 return IceType_void; 544 return IceType_void;
510 return Dest->getType(); 545 return Dest->getType();
511 } 546 }
512 547
513 // ======================== Dump routines ======================== // 548 // ======================== Dump routines ======================== //
514 549
515 void Inst::dumpDecorated(const Cfg *Func) const { 550 void Inst::dumpDecorated(const Cfg *Func) const {
516 if (!BuildDefs::dump()) 551 if (!BuildDefs::dump())
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 945
911 void InstFakeKill::dump(const Cfg *Func) const { 946 void InstFakeKill::dump(const Cfg *Func) const {
912 if (!BuildDefs::dump()) 947 if (!BuildDefs::dump())
913 return; 948 return;
914 Ostream &Str = Func->getContext()->getStrDump(); 949 Ostream &Str = Func->getContext()->getStrDump();
915 if (Linked->isDeleted()) 950 if (Linked->isDeleted())
916 Str << "// "; 951 Str << "// ";
917 Str << "kill.pseudo scratch_regs"; 952 Str << "kill.pseudo scratch_regs";
918 } 953 }
919 954
955 void InstJumpTable::emit(const Cfg *Func) const {
956 // TODO(ascull): should this be a target specific lowering (with access built
957 // in?) and just have InstJumpTable as a high level, similar to br? or should
958 // this follow the same path as emitIAS i.e. put it in global context and
959 // produce this code later?
960 if (!BuildDefs::dump())
961 return;
962 Ostream &Str = Func->getContext()->getStrEmit();
963 // TODO(ascull): softcode pointer size of 4
964 // TODO(ascull): is .long portable?
965 Str << "\n\t.section\t.rodata." << Func->getFunctionName()
966 << "$jumptable,\"a\",@progbits\n"
967 << "\t.align 4\n" << getName(Func) << ":";
968 for (SizeT I = 0; I < NumTargets; ++I)
969 Str << "\n\t.long\t" << Targets[I]->getAsmName();
970 Str << "\n\n\t.text";
971 }
972
973 void InstJumpTable::emitIAS(const Cfg *Func) const {
974 // TODO(ascull): put jump table in the global context for emission later
975 (void)Func;
976 }
977
978 void InstJumpTable::dump(const Cfg *Func) const {
979 if (!BuildDefs::dump())
980 return;
981 Ostream &Str = Func->getContext()->getStrDump();
982 Str << "jump table [";
983 for (SizeT I = 0; I < NumTargets; ++I)
984 Str << "\n " << Targets[I]->getName();
985 Str << "\n ]";
986 }
987
920 void InstTarget::dump(const Cfg *Func) const { 988 void InstTarget::dump(const Cfg *Func) const {
921 if (!BuildDefs::dump()) 989 if (!BuildDefs::dump())
922 return; 990 return;
923 Ostream &Str = Func->getContext()->getStrDump(); 991 Ostream &Str = Func->getContext()->getStrDump();
924 Str << "[TARGET] "; 992 Str << "[TARGET] ";
925 Inst::dump(Func); 993 Inst::dump(Func);
926 } 994 }
927 995
928 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { 996 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
929 const auto SrcVar = llvm::dyn_cast<const Variable>(Source); 997 const auto SrcVar = llvm::dyn_cast<const Variable>(Source);
930 if (!SrcVar) 998 if (!SrcVar)
931 return false; 999 return false;
932 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) { 1000 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) {
933 // TODO: On x86-64, instructions like "mov eax, eax" are used to 1001 // 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 1002 // clear the upper 32 bits of rax. We need to recognize and
935 // preserve these. 1003 // preserve these.
936 return true; 1004 return true;
937 } 1005 }
938 if (!Dest->hasReg() && !SrcVar->hasReg() && 1006 if (!Dest->hasReg() && !SrcVar->hasReg() &&
939 Dest->getStackOffset() == SrcVar->getStackOffset()) 1007 Dest->getStackOffset() == SrcVar->getStackOffset())
940 return true; 1008 return true;
941 return false; 1009 return false;
942 } 1010 }
943 1011
944 } // end of namespace Ice 1012 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceInst.h ('k') | src/IceInstARM32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698