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