| 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...) Expand all 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand all 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...) Expand all 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...) Expand all 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 |