OLD | NEW |
1 //===- subzero/src/IceTargetLowering.cpp - Basic lowering implementation --===// | 1 //===- subzero/src/IceTargetLowering.cpp - Basic lowering 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 // } | 49 // } |
50 #define SUBZERO_TARGET(X) \ | 50 #define SUBZERO_TARGET(X) \ |
51 namespace X { \ | 51 namespace X { \ |
52 std::unique_ptr<::Ice::TargetLowering> \ | 52 std::unique_ptr<::Ice::TargetLowering> \ |
53 createTargetLowering(::Ice::Cfg *Func); \ | 53 createTargetLowering(::Ice::Cfg *Func); \ |
54 std::unique_ptr<::Ice::TargetDataLowering> \ | 54 std::unique_ptr<::Ice::TargetDataLowering> \ |
55 createTargetDataLowering(::Ice::GlobalContext *Ctx); \ | 55 createTargetDataLowering(::Ice::GlobalContext *Ctx); \ |
56 std::unique_ptr<::Ice::TargetHeaderLowering> \ | 56 std::unique_ptr<::Ice::TargetHeaderLowering> \ |
57 createTargetHeaderLowering(::Ice::GlobalContext *Ctx); \ | 57 createTargetHeaderLowering(::Ice::GlobalContext *Ctx); \ |
58 void staticInit(::Ice::GlobalContext *Ctx); \ | 58 void staticInit(::Ice::GlobalContext *Ctx); \ |
| 59 bool shouldBePooled(const ::Ice::Constant *C); \ |
59 } // end of namespace X | 60 } // end of namespace X |
60 #include "SZTargets.def" | 61 #include "SZTargets.def" |
61 #undef SUBZERO_TARGET | 62 #undef SUBZERO_TARGET |
62 | 63 |
63 namespace Ice { | 64 namespace Ice { |
64 void LoweringContext::init(CfgNode *N) { | 65 void LoweringContext::init(CfgNode *N) { |
65 Node = N; | 66 Node = N; |
66 End = getNode()->getInsts().end(); | 67 End = getNode()->getInsts().end(); |
67 rewind(); | 68 rewind(); |
68 advanceForward(Next); | 69 advanceForward(Next); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 Variable *LoweringContext::availabilityGet(Operand *Src) const { | 119 Variable *LoweringContext::availabilityGet(Operand *Src) const { |
119 assert(Src); | 120 assert(Src); |
120 if (Src == LastDest) | 121 if (Src == LastDest) |
121 return LastSrc; | 122 return LastSrc; |
122 return nullptr; | 123 return nullptr; |
123 } | 124 } |
124 | 125 |
125 namespace { | 126 namespace { |
126 | 127 |
127 void printRegisterSet(Ostream &Str, const SmallBitVector &Bitset, | 128 void printRegisterSet(Ostream &Str, const SmallBitVector &Bitset, |
128 std::function<IceString(RegNumT)> getRegName, | 129 std::function<std::string(RegNumT)> getRegName, |
129 const IceString &LineIndentString) { | 130 const std::string &LineIndentString) { |
130 constexpr size_t RegistersPerLine = 16; | 131 constexpr size_t RegistersPerLine = 16; |
131 size_t Count = 0; | 132 size_t Count = 0; |
132 for (RegNumT RegNum : RegNumBVIter(Bitset)) { | 133 for (RegNumT RegNum : RegNumBVIter(Bitset)) { |
133 if (Count == 0) { | 134 if (Count == 0) { |
134 Str << LineIndentString; | 135 Str << LineIndentString; |
135 } else { | 136 } else { |
136 Str << ","; | 137 Str << ","; |
137 } | 138 } |
138 if (Count > 0 && Count % RegistersPerLine == 0) | 139 if (Count > 0 && Count % RegistersPerLine == 0) |
139 Str << "\n" << LineIndentString; | 140 Str << "\n" << LineIndentString; |
140 ++Count; | 141 ++Count; |
141 Str << getRegName(RegNum); | 142 Str << getRegName(RegNum); |
142 } | 143 } |
143 if (Count) | 144 if (Count) |
144 Str << "\n"; | 145 Str << "\n"; |
145 } | 146 } |
146 | 147 |
147 // Splits "<class>:<reg>" into "<class>" plus "<reg>". If there is no <class> | 148 // Splits "<class>:<reg>" into "<class>" plus "<reg>". If there is no <class> |
148 // component, the result is "" plus "<reg>". | 149 // component, the result is "" plus "<reg>". |
149 void splitToClassAndName(const IceString &RegName, IceString *SplitRegClass, | 150 void splitToClassAndName(const std::string &RegName, std::string *SplitRegClass, |
150 IceString *SplitRegName) { | 151 std::string *SplitRegName) { |
151 constexpr const char Separator[] = ":"; | 152 constexpr const char Separator[] = ":"; |
152 constexpr size_t SeparatorWidth = llvm::array_lengthof(Separator) - 1; | 153 constexpr size_t SeparatorWidth = llvm::array_lengthof(Separator) - 1; |
153 size_t Pos = RegName.find(Separator); | 154 size_t Pos = RegName.find(Separator); |
154 if (Pos == std::string::npos) { | 155 if (Pos == std::string::npos) { |
155 *SplitRegClass = ""; | 156 *SplitRegClass = ""; |
156 *SplitRegName = RegName; | 157 *SplitRegName = RegName; |
157 } else { | 158 } else { |
158 *SplitRegClass = RegName.substr(0, Pos); | 159 *SplitRegClass = RegName.substr(0, Pos); |
159 *SplitRegName = RegName.substr(Pos + SeparatorWidth); | 160 *SplitRegName = RegName.substr(Pos + SeparatorWidth); |
160 } | 161 } |
161 } | 162 } |
162 | 163 |
163 LLVM_ATTRIBUTE_NORETURN void badTargetFatalError(TargetArch Target) { | 164 LLVM_ATTRIBUTE_NORETURN void badTargetFatalError(TargetArch Target) { |
164 llvm::report_fatal_error("Unsupported target: " + | 165 llvm::report_fatal_error("Unsupported target: " + |
165 std::string(targetArchString(Target))); | 166 std::string(targetArchString(Target))); |
166 } | 167 } |
167 | 168 |
168 } // end of anonymous namespace | 169 } // end of anonymous namespace |
169 | 170 |
170 void TargetLowering::filterTypeToRegisterSet( | 171 void TargetLowering::filterTypeToRegisterSet( |
171 GlobalContext *Ctx, int32_t NumRegs, SmallBitVector TypeToRegisterSet[], | 172 GlobalContext *Ctx, int32_t NumRegs, SmallBitVector TypeToRegisterSet[], |
172 size_t TypeToRegisterSetSize, std::function<IceString(RegNumT)> getRegName, | 173 size_t TypeToRegisterSetSize, |
173 std::function<IceString(RegClass)> getRegClassName) { | 174 std::function<std::string(RegNumT)> getRegName, |
| 175 std::function<const char *(RegClass)> getRegClassName) { |
174 std::vector<SmallBitVector> UseSet(TypeToRegisterSetSize, | 176 std::vector<SmallBitVector> UseSet(TypeToRegisterSetSize, |
175 SmallBitVector(NumRegs)); | 177 SmallBitVector(NumRegs)); |
176 std::vector<SmallBitVector> ExcludeSet(TypeToRegisterSetSize, | 178 std::vector<SmallBitVector> ExcludeSet(TypeToRegisterSetSize, |
177 SmallBitVector(NumRegs)); | 179 SmallBitVector(NumRegs)); |
178 | 180 |
179 std::unordered_map<IceString, RegNumT> RegNameToIndex; | 181 std::unordered_map<std::string, RegNumT> RegNameToIndex; |
180 for (int32_t RegIndex = 0; RegIndex < NumRegs; ++RegIndex) { | 182 for (int32_t RegIndex = 0; RegIndex < NumRegs; ++RegIndex) { |
181 const auto RegNum = RegNumT::fromInt(RegIndex); | 183 const auto RegNum = RegNumT::fromInt(RegIndex); |
182 RegNameToIndex[getRegName(RegNum)] = RegNum; | 184 RegNameToIndex[getRegName(RegNum)] = RegNum; |
183 } | 185 } |
184 | 186 |
185 std::vector<std::string> BadRegNames; | 187 std::vector<std::string> BadRegNames; |
186 | 188 |
187 // The processRegList function iterates across the RegNames vector. Each | 189 // The processRegList function iterates across the RegNames vector. Each |
188 // entry in the vector is a string of the form "<reg>" or "<class>:<reg>". | 190 // entry in the vector is a string of the form "<reg>" or "<class>:<reg>". |
189 // The register class and register number are computed, and the corresponding | 191 // The register class and register number are computed, and the corresponding |
190 // bit is set in RegSet[][]. If "<class>:" is missing, then the bit is set | 192 // bit is set in RegSet[][]. If "<class>:" is missing, then the bit is set |
191 // for all classes. | 193 // for all classes. |
192 auto processRegList = [&](const std::vector<std::string> &RegNames, | 194 auto processRegList = [&](const std::vector<std::string> &RegNames, |
193 std::vector<SmallBitVector> &RegSet) { | 195 std::vector<SmallBitVector> &RegSet) { |
194 for (const IceString &RegClassAndName : RegNames) { | 196 for (const std::string &RegClassAndName : RegNames) { |
195 IceString RClass; | 197 std::string RClass; |
196 IceString RName; | 198 std::string RName; |
197 splitToClassAndName(RegClassAndName, &RClass, &RName); | 199 splitToClassAndName(RegClassAndName, &RClass, &RName); |
198 if (!RegNameToIndex.count(RName)) { | 200 if (!RegNameToIndex.count(RName)) { |
199 BadRegNames.push_back(RName); | 201 BadRegNames.push_back(RName); |
200 continue; | 202 continue; |
201 } | 203 } |
202 const int32_t RegIndex = RegNameToIndex.at(RName); | 204 const int32_t RegIndex = RegNameToIndex.at(RName); |
203 for (SizeT TypeIndex = 0; TypeIndex < TypeToRegisterSetSize; | 205 for (SizeT TypeIndex = 0; TypeIndex < TypeToRegisterSetSize; |
204 ++TypeIndex) { | 206 ++TypeIndex) { |
205 if (RClass.empty() || | 207 if (RClass.empty() || |
206 RClass == getRegClassName(static_cast<RegClass>(TypeIndex))) { | 208 RClass == getRegClassName(static_cast<RegClass>(TypeIndex))) { |
(...skipping 22 matching lines...) Expand all Loading... |
229 SmallBitVector *ExcludeBitSet = &ExcludeSet[TypeIndex]; | 231 SmallBitVector *ExcludeBitSet = &ExcludeSet[TypeIndex]; |
230 if (UseBitSet->any()) | 232 if (UseBitSet->any()) |
231 *TypeBitSet = *UseBitSet; | 233 *TypeBitSet = *UseBitSet; |
232 (*TypeBitSet).reset(*ExcludeBitSet); | 234 (*TypeBitSet).reset(*ExcludeBitSet); |
233 } | 235 } |
234 | 236 |
235 // Display filtered register sets, if requested. | 237 // Display filtered register sets, if requested. |
236 if (BuildDefs::dump() && NumRegs && | 238 if (BuildDefs::dump() && NumRegs && |
237 (Ctx->getFlags().getVerbose() & IceV_AvailableRegs)) { | 239 (Ctx->getFlags().getVerbose() & IceV_AvailableRegs)) { |
238 Ostream &Str = Ctx->getStrDump(); | 240 Ostream &Str = Ctx->getStrDump(); |
239 const IceString Indent = " "; | 241 const std::string Indent = " "; |
240 const IceString IndentTwice = Indent + Indent; | 242 const std::string IndentTwice = Indent + Indent; |
241 Str << "Registers available for register allocation:\n"; | 243 Str << "Registers available for register allocation:\n"; |
242 for (size_t TypeIndex = 0; TypeIndex < TypeToRegisterSetSize; ++TypeIndex) { | 244 for (size_t TypeIndex = 0; TypeIndex < TypeToRegisterSetSize; ++TypeIndex) { |
243 Str << Indent << getRegClassName(static_cast<RegClass>(TypeIndex)) | 245 Str << Indent << getRegClassName(static_cast<RegClass>(TypeIndex)) |
244 << ":\n"; | 246 << ":\n"; |
245 printRegisterSet(Str, TypeToRegisterSet[TypeIndex], getRegName, | 247 printRegisterSet(Str, TypeToRegisterSet[TypeIndex], getRegName, |
246 IndentTwice); | 248 IndentTwice); |
247 } | 249 } |
248 Str << "\n"; | 250 Str << "\n"; |
249 } | 251 } |
250 } | 252 } |
(...skipping 24 matching lines...) Expand all Loading... |
275 return; \ | 277 return; \ |
276 } \ | 278 } \ |
277 InitGuard##X = true; \ | 279 InitGuard##X = true; \ |
278 ::X::staticInit(Ctx); \ | 280 ::X::staticInit(Ctx); \ |
279 } break; | 281 } break; |
280 #include "SZTargets.def" | 282 #include "SZTargets.def" |
281 #undef SUBZERO_TARGET | 283 #undef SUBZERO_TARGET |
282 } | 284 } |
283 } | 285 } |
284 | 286 |
| 287 bool TargetLowering::shouldBePooled(const Constant *C) { |
| 288 const TargetArch Target = GlobalContext::getFlags().getTargetArch(); |
| 289 switch (Target) { |
| 290 default: |
| 291 return false; |
| 292 #define SUBZERO_TARGET(X) \ |
| 293 case TARGET_LOWERING_CLASS_FOR(X): \ |
| 294 return ::X::shouldBePooled(C); |
| 295 #include "SZTargets.def" |
| 296 #undef SUBZERO_TARGET |
| 297 } |
| 298 } |
| 299 |
285 TargetLowering::SandboxType | 300 TargetLowering::SandboxType |
286 TargetLowering::determineSandboxTypeFromFlags(const ClFlags &Flags) { | 301 TargetLowering::determineSandboxTypeFromFlags(const ClFlags &Flags) { |
287 assert(!Flags.getUseSandboxing() || !Flags.getUseNonsfi()); | 302 assert(!Flags.getUseSandboxing() || !Flags.getUseNonsfi()); |
288 if (Flags.getUseNonsfi()) { | 303 if (Flags.getUseNonsfi()) { |
289 return TargetLowering::ST_Nonsfi; | 304 return TargetLowering::ST_Nonsfi; |
290 } | 305 } |
291 if (Flags.getUseSandboxing()) { | 306 if (Flags.getUseSandboxing()) { |
292 return TargetLowering::ST_NaCl; | 307 return TargetLowering::ST_NaCl; |
293 } | 308 } |
294 return TargetLowering::ST_None; | 309 return TargetLowering::ST_None; |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 Dest, [this, Kind](Variable *Dest, Operand *Src0, Operand *Src1) { | 736 Dest, [this, Kind](Variable *Dest, Operand *Src0, Operand *Src1) { |
722 return Context.insert<InstArithmetic>(Kind, Dest, Src0, Src1); | 737 return Context.insert<InstArithmetic>(Kind, Dest, Src0, Src1); |
723 }, Src0, Src1); | 738 }, Src0, Src1); |
724 } | 739 } |
725 | 740 |
726 void TargetLowering::emitWithoutPrefix(const ConstantRelocatable *C, | 741 void TargetLowering::emitWithoutPrefix(const ConstantRelocatable *C, |
727 const char *Suffix) const { | 742 const char *Suffix) const { |
728 if (!BuildDefs::dump()) | 743 if (!BuildDefs::dump()) |
729 return; | 744 return; |
730 Ostream &Str = Ctx->getStrEmit(); | 745 Ostream &Str = Ctx->getStrEmit(); |
731 const IceString &EmitStr = C->getEmitString(); | 746 const std::string &EmitStr = C->getEmitString(); |
732 if (!EmitStr.empty()) { | 747 if (!EmitStr.empty()) { |
733 // C has a custom emit string, so we use it instead of the canonical | 748 // C has a custom emit string, so we use it instead of the canonical |
734 // Name + Offset form. | 749 // Name + Offset form. |
735 Str << EmitStr; | 750 Str << EmitStr; |
736 return; | 751 return; |
737 } | 752 } |
738 Str << C->getName() << Suffix; | 753 Str << C->getName() << Suffix; |
739 RelocOffsetT Offset = C->getOffset(); | 754 RelocOffsetT Offset = C->getOffset(); |
740 if (Offset) { | 755 if (Offset) { |
741 if (Offset > 0) | 756 if (Offset > 0) |
(...skipping 16 matching lines...) Expand all Loading... |
758 } | 773 } |
759 } | 774 } |
760 | 775 |
761 TargetDataLowering::~TargetDataLowering() = default; | 776 TargetDataLowering::~TargetDataLowering() = default; |
762 | 777 |
763 namespace { | 778 namespace { |
764 | 779 |
765 // dataSectionSuffix decides whether to use SectionSuffix or VarName as data | 780 // dataSectionSuffix decides whether to use SectionSuffix or VarName as data |
766 // section suffix. Essentially, when using separate data sections for globals | 781 // section suffix. Essentially, when using separate data sections for globals |
767 // SectionSuffix is not necessary. | 782 // SectionSuffix is not necessary. |
768 IceString dataSectionSuffix(const IceString &SectionSuffix, | 783 std::string dataSectionSuffix(const std::string &SectionSuffix, |
769 const IceString &VarName, const bool DataSections) { | 784 const std::string &VarName, |
| 785 const bool DataSections) { |
770 if (SectionSuffix.empty() && !DataSections) { | 786 if (SectionSuffix.empty() && !DataSections) { |
771 return ""; | 787 return ""; |
772 } | 788 } |
773 | 789 |
774 if (DataSections) { | 790 if (DataSections) { |
775 // With data sections we don't need to use the SectionSuffix. | 791 // With data sections we don't need to use the SectionSuffix. |
776 return "." + VarName; | 792 return "." + VarName; |
777 } | 793 } |
778 | 794 |
779 assert(!SectionSuffix.empty()); | 795 assert(!SectionSuffix.empty()); |
780 return "." + SectionSuffix; | 796 return "." + SectionSuffix; |
781 } | 797 } |
782 | 798 |
783 } // end of anonymous namespace | 799 } // end of anonymous namespace |
784 | 800 |
785 void TargetDataLowering::emitGlobal(const VariableDeclaration &Var, | 801 void TargetDataLowering::emitGlobal(const VariableDeclaration &Var, |
786 const IceString &SectionSuffix) { | 802 const std::string &SectionSuffix) { |
787 if (!BuildDefs::dump()) | 803 if (!BuildDefs::dump()) |
788 return; | 804 return; |
789 | 805 |
790 // If external and not initialized, this must be a cross test. Don't generate | 806 // If external and not initialized, this must be a cross test. Don't generate |
791 // a declaration for such cases. | 807 // a declaration for such cases. |
792 const bool IsExternal = | 808 const bool IsExternal = |
793 Var.isExternal() || Ctx->getFlags().getDisableInternal(); | 809 Var.isExternal() || Ctx->getFlags().getDisableInternal(); |
794 if (IsExternal && !Var.hasInitializer()) | 810 if (IsExternal && !Var.hasInitializer()) |
795 return; | 811 return; |
796 | 812 |
797 Ostream &Str = Ctx->getStrEmit(); | 813 Ostream &Str = Ctx->getStrEmit(); |
798 const bool HasNonzeroInitializer = Var.hasNonzeroInitializer(); | 814 const bool HasNonzeroInitializer = Var.hasNonzeroInitializer(); |
799 const bool IsConstant = Var.getIsConstant(); | 815 const bool IsConstant = Var.getIsConstant(); |
800 const SizeT Size = Var.getNumBytes(); | 816 const SizeT Size = Var.getNumBytes(); |
801 const IceString &Name = Var.getName(); | 817 const std::string Name = Var.getName().toString(); |
802 | 818 |
803 Str << "\t.type\t" << Name << ",%object\n"; | 819 Str << "\t.type\t" << Name << ",%object\n"; |
804 | 820 |
805 const bool UseDataSections = Ctx->getFlags().getDataSections(); | 821 const bool UseDataSections = Ctx->getFlags().getDataSections(); |
806 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); | 822 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); |
807 const IceString Suffix = | 823 const std::string Suffix = |
808 dataSectionSuffix(SectionSuffix, Name, UseDataSections); | 824 dataSectionSuffix(SectionSuffix, Name, UseDataSections); |
809 if (IsConstant && UseNonsfi) | 825 if (IsConstant && UseNonsfi) |
810 Str << "\t.section\t.data.rel.ro" << Suffix << ",\"aw\",%progbits\n"; | 826 Str << "\t.section\t.data.rel.ro" << Suffix << ",\"aw\",%progbits\n"; |
811 else if (IsConstant) | 827 else if (IsConstant) |
812 Str << "\t.section\t.rodata" << Suffix << ",\"a\",%progbits\n"; | 828 Str << "\t.section\t.rodata" << Suffix << ",\"a\",%progbits\n"; |
813 else if (HasNonzeroInitializer) | 829 else if (HasNonzeroInitializer) |
814 Str << "\t.section\t.data" << Suffix << ",\"aw\",%progbits\n"; | 830 Str << "\t.section\t.data" << Suffix << ",\"aw\",%progbits\n"; |
815 else | 831 else |
816 Str << "\t.section\t.bss" << Suffix << ",\"aw\",%nobits\n"; | 832 Str << "\t.section\t.bss" << Suffix << ",\"aw\",%nobits\n"; |
817 | 833 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 case TARGET_LOWERING_CLASS_FOR(X): \ | 900 case TARGET_LOWERING_CLASS_FOR(X): \ |
885 return ::X::createTargetHeaderLowering(Ctx); | 901 return ::X::createTargetHeaderLowering(Ctx); |
886 #include "SZTargets.def" | 902 #include "SZTargets.def" |
887 #undef SUBZERO_TARGET | 903 #undef SUBZERO_TARGET |
888 } | 904 } |
889 } | 905 } |
890 | 906 |
891 TargetHeaderLowering::~TargetHeaderLowering() = default; | 907 TargetHeaderLowering::~TargetHeaderLowering() = default; |
892 | 908 |
893 } // end of namespace Ice | 909 } // end of namespace Ice |
OLD | NEW |