OLD | NEW |
1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// | 1 //===- subzero/src/IceCfg.cpp - Control flow graph 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 |
(...skipping 13 matching lines...) Loading... |
24 #include "IceInst.h" | 24 #include "IceInst.h" |
25 #include "IceInstVarIter.h" | 25 #include "IceInstVarIter.h" |
26 #include "IceLiveness.h" | 26 #include "IceLiveness.h" |
27 #include "IceLoopAnalyzer.h" | 27 #include "IceLoopAnalyzer.h" |
28 #include "IceOperand.h" | 28 #include "IceOperand.h" |
29 #include "IceTargetLowering.h" | 29 #include "IceTargetLowering.h" |
30 | 30 |
31 namespace Ice { | 31 namespace Ice { |
32 | 32 |
33 Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber) | 33 Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber) |
34 : Ctx(Ctx), SequenceNumber(SequenceNumber), | 34 : Ctx(Ctx), SequenceNumber(SequenceNumber), VMask(getFlags().getVerbose()), |
35 VMask(Ctx->getFlags().getVerbose()), FunctionName(), | 35 FunctionName(), NextInstNumber(Inst::NumberInitial), Live(nullptr) { |
36 NextInstNumber(Inst::NumberInitial), Live(nullptr) { | |
37 Allocator.reset(new ArenaAllocator()); | 36 Allocator.reset(new ArenaAllocator()); |
38 NodeStrings.reset(new StringPool); | 37 NodeStrings.reset(new StringPool); |
39 VarStrings.reset(new StringPool); | 38 VarStrings.reset(new StringPool); |
40 CfgLocalAllocatorScope _(this); | 39 CfgLocalAllocatorScope _(this); |
41 Target = | 40 Target = TargetLowering::createLowering(getFlags().getTargetArch(), this); |
42 TargetLowering::createLowering(Ctx->getFlags().getTargetArch(), this); | |
43 VMetadata.reset(new VariablesMetadata(this)); | 41 VMetadata.reset(new VariablesMetadata(this)); |
44 TargetAssembler = Target->createAssembler(); | 42 TargetAssembler = Target->createAssembler(); |
45 | 43 |
46 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Randomize) { | 44 if (getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Randomize) { |
47 // If -randomize-pool-immediates=randomize, create a random number | 45 // If -randomize-pool-immediates=randomize, create a random number |
48 // generator to generate a cookie for constant blinding. | 46 // generator to generate a cookie for constant blinding. |
49 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), | 47 RandomNumberGenerator RNG(getFlags().getRandomSeed(), RPE_ConstantBlinding, |
50 RPE_ConstantBlinding, this->SequenceNumber); | 48 this->SequenceNumber); |
51 ConstantBlindingCookie = | 49 ConstantBlindingCookie = |
52 (uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max() + 1); | 50 (uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max() + 1); |
53 } | 51 } |
54 } | 52 } |
55 | 53 |
56 Cfg::~Cfg() { | 54 Cfg::~Cfg() { |
57 assert(CfgAllocatorTraits::current() == nullptr); | 55 assert(CfgAllocatorTraits::current() == nullptr); |
58 if (GlobalContext::getFlags().getDumpStrings()) { | 56 if (getFlags().getDumpStrings()) { |
59 OstreamLocker _(Ctx); | 57 OstreamLocker _(Ctx); |
60 Ostream &Str = Ctx->getStrDump(); | 58 Ostream &Str = Ctx->getStrDump(); |
61 getNodeStrings()->dump(Str); | 59 getNodeStrings()->dump(Str); |
62 getVarStrings()->dump(Str); | 60 getVarStrings()->dump(Str); |
63 } | 61 } |
64 } | 62 } |
65 | 63 |
66 /// Create a string like "foo(i=123:b=9)" indicating the function name, number | 64 /// Create a string like "foo(i=123:b=9)" indicating the function name, number |
67 /// of high-level instructions, and number of basic blocks. This string is only | 65 /// of high-level instructions, and number of basic blocks. This string is only |
68 /// used for dumping and other diagnostics, and the idea is that given a set of | 66 /// used for dumping and other diagnostics, and the idea is that given a set of |
(...skipping 121 matching lines...) Loading... |
190 constexpr bool HasTailCall = false; | 188 constexpr bool HasTailCall = false; |
191 auto *Call = | 189 auto *Call = |
192 InstCall::create(this, NumArgs, Void, ProfileSummarySym, HasTailCall); | 190 InstCall::create(this, NumArgs, Void, ProfileSummarySym, HasTailCall); |
193 getEntryNode()->getInsts().push_front(Call); | 191 getEntryNode()->getInsts().push_front(Call); |
194 } | 192 } |
195 | 193 |
196 void Cfg::translate() { | 194 void Cfg::translate() { |
197 if (hasError()) | 195 if (hasError()) |
198 return; | 196 return; |
199 if (BuildDefs::dump()) { | 197 if (BuildDefs::dump()) { |
200 const std::string TimingFocusOn = | 198 const std::string TimingFocusOn = getFlags().getTimingFocusOn(); |
201 getContext()->getFlags().getTimingFocusOn(); | |
202 const std::string Name = getFunctionName().toString(); | 199 const std::string Name = getFunctionName().toString(); |
203 if (TimingFocusOn == "*" || TimingFocusOn == Name) { | 200 if (TimingFocusOn == "*" || TimingFocusOn == Name) { |
204 setFocusedTiming(); | 201 setFocusedTiming(); |
205 getContext()->resetTimer(GlobalContext::TSK_Default); | 202 getContext()->resetTimer(GlobalContext::TSK_Default); |
206 getContext()->setTimerName(GlobalContext::TSK_Default, Name); | 203 getContext()->setTimerName(GlobalContext::TSK_Default, Name); |
207 } | 204 } |
208 if (isVerbose(IceV_Status)) { | 205 if (isVerbose(IceV_Status)) { |
209 getContext()->getStrDump() << ">>>Translating " | 206 getContext()->getStrDump() << ">>>Translating " |
210 << getFunctionNameAndSize() << "\n"; | 207 << getFunctionNameAndSize() << "\n"; |
211 } | 208 } |
212 } | 209 } |
213 TimerMarker T_func(getContext(), getFunctionName().toStringOrEmpty()); | 210 TimerMarker T_func(getContext(), getFunctionName().toStringOrEmpty()); |
214 TimerMarker T(TimerStack::TT_translate, this); | 211 TimerMarker T(TimerStack::TT_translate, this); |
215 | 212 |
216 dump("Initial CFG"); | 213 dump("Initial CFG"); |
217 | 214 |
218 if (getContext()->getFlags().getEnableBlockProfile()) { | 215 if (getFlags().getEnableBlockProfile()) { |
219 profileBlocks(); | 216 profileBlocks(); |
220 // TODO(jpp): this is fragile, at best. Figure out a better way of | 217 // TODO(jpp): this is fragile, at best. Figure out a better way of |
221 // detecting exit functions. | 218 // detecting exit functions. |
222 if (GlobalContext::matchSymbolName(getFunctionName(), "exit")) { | 219 if (GlobalContext::matchSymbolName(getFunctionName(), "exit")) { |
223 addCallToProfileSummary(); | 220 addCallToProfileSummary(); |
224 } | 221 } |
225 dump("Profiled CFG"); | 222 dump("Profiled CFG"); |
226 } | 223 } |
227 | 224 |
228 // Create the Hi and Lo variables where a split was needed | 225 // Create the Hi and Lo variables where a split was needed |
(...skipping 217 matching lines...) Loading... |
446 [RNG](int N) { return RNG->next(N); }); | 443 [RNG](int N) { return RNG->next(N); }); |
447 for (CfgNode *Next : Outs) { | 444 for (CfgNode *Next : Outs) { |
448 if (ToVisit[Next->getIndex()]) | 445 if (ToVisit[Next->getIndex()]) |
449 getRandomPostOrder(Next, ToVisit, PostOrder, RNG); | 446 getRandomPostOrder(Next, ToVisit, PostOrder, RNG); |
450 } | 447 } |
451 PostOrder.push_back(Node); | 448 PostOrder.push_back(Node); |
452 } | 449 } |
453 } // end of anonymous namespace | 450 } // end of anonymous namespace |
454 | 451 |
455 void Cfg::shuffleNodes() { | 452 void Cfg::shuffleNodes() { |
456 if (!Ctx->getFlags().getReorderBasicBlocks()) | 453 if (!getFlags().getReorderBasicBlocks()) |
457 return; | 454 return; |
458 | 455 |
459 NodeList ReversedReachable; | 456 NodeList ReversedReachable; |
460 NodeList Unreachable; | 457 NodeList Unreachable; |
461 BitVector ToVisit(Nodes.size(), true); | 458 BitVector ToVisit(Nodes.size(), true); |
462 // Create Random number generator for function reordering | 459 // Create Random number generator for function reordering |
463 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), | 460 RandomNumberGenerator RNG(getFlags().getRandomSeed(), |
464 RPE_BasicBlockReordering, SequenceNumber); | 461 RPE_BasicBlockReordering, SequenceNumber); |
465 // Traverse from entry node. | 462 // Traverse from entry node. |
466 getRandomPostOrder(getEntryNode(), ToVisit, ReversedReachable, &RNG); | 463 getRandomPostOrder(getEntryNode(), ToVisit, ReversedReachable, &RNG); |
467 // Collect the unreachable nodes. | 464 // Collect the unreachable nodes. |
468 for (CfgNode *Node : Nodes) | 465 for (CfgNode *Node : Nodes) |
469 if (ToVisit[Node->getIndex()]) | 466 if (ToVisit[Node->getIndex()]) |
470 Unreachable.push_back(Node); | 467 Unreachable.push_back(Node); |
471 // Copy the layout list to the Nodes. | 468 // Copy the layout list to the Nodes. |
472 NodeList Shuffled; | 469 NodeList Shuffled; |
473 Shuffled.reserve(ReversedReachable.size() + Unreachable.size()); | 470 Shuffled.reserve(ReversedReachable.size() + Unreachable.size()); |
(...skipping 295 matching lines...) Loading... |
769 } while (FoundNewAssignment); | 766 } while (FoundNewAssignment); |
770 } | 767 } |
771 | 768 |
772 void Cfg::doAddressOpt() { | 769 void Cfg::doAddressOpt() { |
773 TimerMarker T(TimerStack::TT_doAddressOpt, this); | 770 TimerMarker T(TimerStack::TT_doAddressOpt, this); |
774 for (CfgNode *Node : Nodes) | 771 for (CfgNode *Node : Nodes) |
775 Node->doAddressOpt(); | 772 Node->doAddressOpt(); |
776 } | 773 } |
777 | 774 |
778 void Cfg::doNopInsertion() { | 775 void Cfg::doNopInsertion() { |
779 if (!Ctx->getFlags().getShouldDoNopInsertion()) | 776 if (!getFlags().getShouldDoNopInsertion()) |
780 return; | 777 return; |
781 TimerMarker T(TimerStack::TT_doNopInsertion, this); | 778 TimerMarker T(TimerStack::TT_doNopInsertion, this); |
782 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), RPE_NopInsertion, | 779 RandomNumberGenerator RNG(getFlags().getRandomSeed(), RPE_NopInsertion, |
783 SequenceNumber); | 780 SequenceNumber); |
784 for (CfgNode *Node : Nodes) | 781 for (CfgNode *Node : Nodes) |
785 Node->doNopInsertion(RNG); | 782 Node->doNopInsertion(RNG); |
786 } | 783 } |
787 | 784 |
788 void Cfg::genCode() { | 785 void Cfg::genCode() { |
789 TimerMarker T(TimerStack::TT_genCode, this); | 786 TimerMarker T(TimerStack::TT_genCode, this); |
790 for (CfgNode *Node : Nodes) | 787 for (CfgNode *Node : Nodes) |
791 Node->genCode(); | 788 Node->genCode(); |
792 } | 789 } |
(...skipping 152 matching lines...) Loading... |
945 } | 942 } |
946 return Valid; | 943 return Valid; |
947 } | 944 } |
948 | 945 |
949 void Cfg::contractEmptyNodes() { | 946 void Cfg::contractEmptyNodes() { |
950 // If we're decorating the asm output with register liveness info, this | 947 // If we're decorating the asm output with register liveness info, this |
951 // information may become corrupted or incorrect after contracting nodes that | 948 // information may become corrupted or incorrect after contracting nodes that |
952 // contain only redundant assignments. As such, we disable this pass when | 949 // contain only redundant assignments. As such, we disable this pass when |
953 // DecorateAsm is specified. This may make the resulting code look more | 950 // DecorateAsm is specified. This may make the resulting code look more |
954 // branchy, but it should have no effect on the register assignments. | 951 // branchy, but it should have no effect on the register assignments. |
955 if (Ctx->getFlags().getDecorateAsm()) | 952 if (getFlags().getDecorateAsm()) |
956 return; | 953 return; |
957 for (CfgNode *Node : Nodes) { | 954 for (CfgNode *Node : Nodes) { |
958 Node->contractIfEmpty(); | 955 Node->contractIfEmpty(); |
959 } | 956 } |
960 } | 957 } |
961 | 958 |
962 void Cfg::doBranchOpt() { | 959 void Cfg::doBranchOpt() { |
963 TimerMarker T(TimerStack::TT_doBranchOpt, this); | 960 TimerMarker T(TimerStack::TT_doBranchOpt, this); |
964 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 961 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
965 auto NextNode = I + 1; | 962 auto NextNode = I + 1; |
(...skipping 11 matching lines...) Loading... |
977 | 974 |
978 // emitTextHeader() is not target-specific (apart from what is abstracted by | 975 // emitTextHeader() is not target-specific (apart from what is abstracted by |
979 // the Assembler), so it is defined here rather than in the target lowering | 976 // the Assembler), so it is defined here rather than in the target lowering |
980 // class. | 977 // class. |
981 void Cfg::emitTextHeader(GlobalString Name, GlobalContext *Ctx, | 978 void Cfg::emitTextHeader(GlobalString Name, GlobalContext *Ctx, |
982 const Assembler *Asm) { | 979 const Assembler *Asm) { |
983 if (!BuildDefs::dump()) | 980 if (!BuildDefs::dump()) |
984 return; | 981 return; |
985 Ostream &Str = Ctx->getStrEmit(); | 982 Ostream &Str = Ctx->getStrEmit(); |
986 Str << "\t.text\n"; | 983 Str << "\t.text\n"; |
987 if (Ctx->getFlags().getFunctionSections()) | 984 if (getFlags().getFunctionSections()) |
988 Str << "\t.section\t.text." << Name << ",\"ax\",%progbits\n"; | 985 Str << "\t.section\t.text." << Name << ",\"ax\",%progbits\n"; |
989 if (!Asm->getInternal() || Ctx->getFlags().getDisableInternal()) { | 986 if (!Asm->getInternal() || getFlags().getDisableInternal()) { |
990 Str << "\t.globl\t" << Name << "\n"; | 987 Str << "\t.globl\t" << Name << "\n"; |
991 Str << "\t.type\t" << Name << ",%function\n"; | 988 Str << "\t.type\t" << Name << ",%function\n"; |
992 } | 989 } |
993 Str << "\t" << Asm->getAlignDirective() << " " | 990 Str << "\t" << Asm->getAlignDirective() << " " |
994 << Asm->getBundleAlignLog2Bytes() << ",0x"; | 991 << Asm->getBundleAlignLog2Bytes() << ",0x"; |
995 for (uint8_t I : Asm->getNonExecBundlePadding()) | 992 for (uint8_t I : Asm->getNonExecBundlePadding()) |
996 Str.write_hex(I); | 993 Str.write_hex(I); |
997 Str << "\n"; | 994 Str << "\n"; |
998 Str << Name << ":\n"; | 995 Str << Name << ":\n"; |
999 } | 996 } |
1000 | 997 |
1001 void Cfg::deleteJumpTableInsts() { | 998 void Cfg::deleteJumpTableInsts() { |
1002 for (InstJumpTable *JumpTable : JumpTables) | 999 for (InstJumpTable *JumpTable : JumpTables) |
1003 JumpTable->setDeleted(); | 1000 JumpTable->setDeleted(); |
1004 } | 1001 } |
1005 | 1002 |
1006 void Cfg::emitJumpTables() { | 1003 void Cfg::emitJumpTables() { |
1007 switch (Ctx->getFlags().getOutFileType()) { | 1004 switch (getFlags().getOutFileType()) { |
1008 case FT_Elf: | 1005 case FT_Elf: |
1009 case FT_Iasm: { | 1006 case FT_Iasm: { |
1010 // The emission needs to be delayed until the after the text section so | 1007 // The emission needs to be delayed until the after the text section so |
1011 // save the offsets in the global context. | 1008 // save the offsets in the global context. |
1012 for (const InstJumpTable *JumpTable : JumpTables) { | 1009 for (const InstJumpTable *JumpTable : JumpTables) { |
1013 SizeT NumTargets = JumpTable->getNumTargets(); | 1010 SizeT NumTargets = JumpTable->getNumTargets(); |
1014 JumpTableData::TargetList TargetList; | 1011 JumpTableData::TargetList TargetList; |
1015 for (SizeT I = 0; I < NumTargets; ++I) { | 1012 for (SizeT I = 0; I < NumTargets; ++I) { |
1016 SizeT Index = JumpTable->getTarget(I)->getIndex(); | 1013 SizeT Index = JumpTable->getTarget(I)->getIndex(); |
1017 TargetList.emplace_back( | 1014 TargetList.emplace_back( |
1018 getAssembler()->getCfgNodeLabel(Index)->getPosition()); | 1015 getAssembler()->getCfgNodeLabel(Index)->getPosition()); |
1019 } | 1016 } |
1020 Ctx->addJumpTable(FunctionName, JumpTable->getId(), TargetList); | 1017 Ctx->addJumpTable(FunctionName, JumpTable->getId(), TargetList); |
1021 } | 1018 } |
1022 } break; | 1019 } break; |
1023 case FT_Asm: { | 1020 case FT_Asm: { |
1024 // Emit the assembly directly so we don't need to hang on to all the names | 1021 // Emit the assembly directly so we don't need to hang on to all the names |
1025 for (const InstJumpTable *JumpTable : JumpTables) | 1022 for (const InstJumpTable *JumpTable : JumpTables) |
1026 getTarget()->emitJumpTable(this, JumpTable); | 1023 getTarget()->emitJumpTable(this, JumpTable); |
1027 } break; | 1024 } break; |
1028 } | 1025 } |
1029 } | 1026 } |
1030 | 1027 |
1031 void Cfg::emit() { | 1028 void Cfg::emit() { |
1032 if (!BuildDefs::dump()) | 1029 if (!BuildDefs::dump()) |
1033 return; | 1030 return; |
1034 TimerMarker T(TimerStack::TT_emitAsm, this); | 1031 TimerMarker T(TimerStack::TT_emitAsm, this); |
1035 if (Ctx->getFlags().getDecorateAsm()) { | 1032 if (getFlags().getDecorateAsm()) { |
1036 renumberInstructions(); | 1033 renumberInstructions(); |
1037 getVMetadata()->init(VMK_Uses); | 1034 getVMetadata()->init(VMK_Uses); |
1038 liveness(Liveness_Basic); | 1035 liveness(Liveness_Basic); |
1039 dump("After recomputing liveness for -decorate-asm"); | 1036 dump("After recomputing liveness for -decorate-asm"); |
1040 } | 1037 } |
1041 OstreamLocker L(Ctx); | 1038 OstreamLocker L(Ctx); |
1042 Ostream &Str = Ctx->getStrEmit(); | 1039 Ostream &Str = Ctx->getStrEmit(); |
1043 const Assembler *Asm = getAssembler<>(); | 1040 const Assembler *Asm = getAssembler<>(); |
1044 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 1041 const bool NeedSandboxing = getFlags().getUseSandboxing(); |
1045 | 1042 |
1046 emitTextHeader(FunctionName, Ctx, Asm); | 1043 emitTextHeader(FunctionName, Ctx, Asm); |
1047 deleteJumpTableInsts(); | 1044 deleteJumpTableInsts(); |
1048 if (Ctx->getFlags().getDecorateAsm()) { | 1045 if (getFlags().getDecorateAsm()) { |
1049 for (Variable *Var : getVariables()) { | 1046 for (Variable *Var : getVariables()) { |
1050 if (Var->getStackOffset() && !Var->isRematerializable()) { | 1047 if (Var->getStackOffset() && !Var->isRematerializable()) { |
1051 Str << "\t" << Var->getSymbolicStackOffset(this) << " = " | 1048 Str << "\t" << Var->getSymbolicStackOffset(this) << " = " |
1052 << Var->getStackOffset() << "\n"; | 1049 << Var->getStackOffset() << "\n"; |
1053 } | 1050 } |
1054 } | 1051 } |
1055 } | 1052 } |
1056 for (CfgNode *Node : Nodes) { | 1053 for (CfgNode *Node : Nodes) { |
1057 if (NeedSandboxing && Node->needsAlignment()) { | 1054 if (NeedSandboxing && Node->needsAlignment()) { |
1058 Str << "\t" << Asm->getAlignDirective() << " " | 1055 Str << "\t" << Asm->getAlignDirective() << " " |
1059 << Asm->getBundleAlignLog2Bytes() << "\n"; | 1056 << Asm->getBundleAlignLog2Bytes() << "\n"; |
1060 } | 1057 } |
1061 Node->emit(this); | 1058 Node->emit(this); |
1062 } | 1059 } |
1063 emitJumpTables(); | 1060 emitJumpTables(); |
1064 Str << "\n"; | 1061 Str << "\n"; |
1065 } | 1062 } |
1066 | 1063 |
1067 void Cfg::emitIAS() { | 1064 void Cfg::emitIAS() { |
1068 TimerMarker T(TimerStack::TT_emitAsm, this); | 1065 TimerMarker T(TimerStack::TT_emitAsm, this); |
1069 // The emitIAS() routines emit into the internal assembler buffer, so there's | 1066 // The emitIAS() routines emit into the internal assembler buffer, so there's |
1070 // no need to lock the streams. | 1067 // no need to lock the streams. |
1071 deleteJumpTableInsts(); | 1068 deleteJumpTableInsts(); |
1072 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 1069 const bool NeedSandboxing = getFlags().getUseSandboxing(); |
1073 for (CfgNode *Node : Nodes) { | 1070 for (CfgNode *Node : Nodes) { |
1074 if (NeedSandboxing && Node->needsAlignment()) | 1071 if (NeedSandboxing && Node->needsAlignment()) |
1075 getAssembler()->alignCfgNode(); | 1072 getAssembler()->alignCfgNode(); |
1076 Node->emitIAS(this); | 1073 Node->emitIAS(this); |
1077 } | 1074 } |
1078 emitJumpTables(); | 1075 emitJumpTables(); |
1079 } | 1076 } |
1080 | 1077 |
1081 size_t Cfg::getTotalMemoryMB() { | 1078 size_t Cfg::getTotalMemoryMB() { |
1082 constexpr size_t OneMB = 1024 * 1024; | 1079 constexpr size_t OneMB = 1024 * 1024; |
(...skipping 13 matching lines...) Loading... |
1096 Ostream &Str = Ctx->getStrDump(); | 1093 Ostream &Str = Ctx->getStrDump(); |
1097 if (Message[0]) | 1094 if (Message[0]) |
1098 Str << "================ " << Message << " ================\n"; | 1095 Str << "================ " << Message << " ================\n"; |
1099 if (isVerbose(IceV_Mem)) { | 1096 if (isVerbose(IceV_Mem)) { |
1100 Str << "Memory size = " << getTotalMemoryMB() << " MB\n"; | 1097 Str << "Memory size = " << getTotalMemoryMB() << " MB\n"; |
1101 } | 1098 } |
1102 setCurrentNode(getEntryNode()); | 1099 setCurrentNode(getEntryNode()); |
1103 // Print function name+args | 1100 // Print function name+args |
1104 if (isVerbose(IceV_Instructions)) { | 1101 if (isVerbose(IceV_Instructions)) { |
1105 Str << "define "; | 1102 Str << "define "; |
1106 if (getInternal() && !Ctx->getFlags().getDisableInternal()) | 1103 if (getInternal() && !getFlags().getDisableInternal()) |
1107 Str << "internal "; | 1104 Str << "internal "; |
1108 Str << ReturnType << " @" << getFunctionName() << "("; | 1105 Str << ReturnType << " @" << getFunctionName() << "("; |
1109 for (SizeT i = 0; i < Args.size(); ++i) { | 1106 for (SizeT i = 0; i < Args.size(); ++i) { |
1110 if (i > 0) | 1107 if (i > 0) |
1111 Str << ", "; | 1108 Str << ", "; |
1112 Str << Args[i]->getType() << " "; | 1109 Str << Args[i]->getType() << " "; |
1113 Args[i]->dump(this); | 1110 Args[i]->dump(this); |
1114 } | 1111 } |
1115 // Append an extra copy of the function name here, in order to print its | 1112 // Append an extra copy of the function name here, in order to print its |
1116 // size stats but not mess up lit tests. | 1113 // size stats but not mess up lit tests. |
(...skipping 30 matching lines...) Loading... |
1147 } | 1144 } |
1148 } | 1145 } |
1149 // Print each basic block | 1146 // Print each basic block |
1150 for (CfgNode *Node : Nodes) | 1147 for (CfgNode *Node : Nodes) |
1151 Node->dump(this); | 1148 Node->dump(this); |
1152 if (isVerbose(IceV_Instructions)) | 1149 if (isVerbose(IceV_Instructions)) |
1153 Str << "}\n"; | 1150 Str << "}\n"; |
1154 } | 1151 } |
1155 | 1152 |
1156 } // end of namespace Ice | 1153 } // end of namespace Ice |
OLD | NEW |