| 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 |