Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// | 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// |
| 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 const Inst *getProducerFor(const Operand *Opnd) const; | 144 const Inst *getProducerFor(const Operand *Opnd) const; |
| 145 void dump(const Cfg *Func) const; | 145 void dump(const Cfg *Func) const; |
| 146 | 146 |
| 147 private: | 147 private: |
| 148 /// Returns true if Producers contains a valid entry for the given VarNum. | 148 /// Returns true if Producers contains a valid entry for the given VarNum. |
| 149 bool containsValid(SizeT VarNum) const { | 149 bool containsValid(SizeT VarNum) const { |
| 150 auto Element = Producers.find(VarNum); | 150 auto Element = Producers.find(VarNum); |
| 151 return Element != Producers.end() && Element->second.Instr != nullptr; | 151 return Element != Producers.end() && Element->second.Instr != nullptr; |
| 152 } | 152 } |
| 153 void setInvalid(SizeT VarNum) { Producers[VarNum].Instr = nullptr; } | 153 void setInvalid(SizeT VarNum) { Producers[VarNum].Instr = nullptr; } |
| 154 void invalidateProducersOnStore(const Inst *Instr); | |
| 154 /// Producers maps Variable::Number to a BoolFoldingEntry. | 155 /// Producers maps Variable::Number to a BoolFoldingEntry. |
| 155 CfgUnorderedMap<SizeT, BoolFoldingEntry<Traits>> Producers; | 156 CfgUnorderedMap<SizeT, BoolFoldingEntry<Traits>> Producers; |
| 156 }; | 157 }; |
| 157 | 158 |
| 158 template <typename Traits> | 159 template <typename Traits> |
| 159 BoolFoldingEntry<Traits>::BoolFoldingEntry(Inst *I) | 160 BoolFoldingEntry<Traits>::BoolFoldingEntry(Inst *I) |
| 160 : Instr(I), IsComplex(BoolFolding<Traits>::hasComplexLowering(I)) {} | 161 : Instr(I), IsComplex(BoolFolding<Traits>::hasComplexLowering(I)) {} |
| 161 | 162 |
| 162 template <typename Traits> | 163 template <typename Traits> |
| 163 typename BoolFolding<Traits>::BoolFoldingProducerKind | 164 typename BoolFolding<Traits>::BoolFoldingProducerKind |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 case PK_Fcmp: | 246 case PK_Fcmp: |
| 246 return (ConsumerKind == CK_Br) || (ConsumerKind == CK_Select); | 247 return (ConsumerKind == CK_Br) || (ConsumerKind == CK_Select); |
| 247 case PK_Arith: | 248 case PK_Arith: |
| 248 return ConsumerKind == CK_Br; | 249 return ConsumerKind == CK_Br; |
| 249 } | 250 } |
| 250 } | 251 } |
| 251 | 252 |
| 252 template <typename Traits> void BoolFolding<Traits>::init(CfgNode *Node) { | 253 template <typename Traits> void BoolFolding<Traits>::init(CfgNode *Node) { |
| 253 Producers.clear(); | 254 Producers.clear(); |
| 254 for (Inst &Instr : Node->getInsts()) { | 255 for (Inst &Instr : Node->getInsts()) { |
| 256 if (Instr.isDeleted()) | |
|
Eric Holk
2016/04/21 22:09:43
As a future CL, it would probably be nice to add a
Jim Stichnoth
2016/04/21 22:50:29
That's a great idea.
| |
| 257 continue; | |
| 258 invalidateProducersOnStore(&Instr); | |
| 255 // Check whether Instr is a valid producer. | 259 // Check whether Instr is a valid producer. |
| 256 Variable *Var = Instr.getDest(); | 260 Variable *Var = Instr.getDest(); |
| 257 if (!Instr.isDeleted() // only consider non-deleted instructions | 261 if (Var // only consider instructions with an actual dest var |
| 258 && Var // only instructions with an actual dest var | |
| 259 && Var->getType() == IceType_i1 // only bool-type dest vars | 262 && Var->getType() == IceType_i1 // only bool-type dest vars |
| 260 && getProducerKind(&Instr) != PK_None) { // white-listed instructions | 263 && getProducerKind(&Instr) != PK_None) { // white-listed instructions |
| 261 Producers[Var->getIndex()] = BoolFoldingEntry<Traits>(&Instr); | 264 Producers[Var->getIndex()] = BoolFoldingEntry<Traits>(&Instr); |
| 262 } | 265 } |
| 263 // Check each src variable against the map. | 266 // Check each src variable against the map. |
| 264 FOREACH_VAR_IN_INST(Var, Instr) { | 267 FOREACH_VAR_IN_INST(Var, Instr) { |
| 265 SizeT VarNum = Var->getIndex(); | 268 SizeT VarNum = Var->getIndex(); |
| 266 if (!containsValid(VarNum)) | 269 if (!containsValid(VarNum)) |
| 267 continue; | 270 continue; |
| 268 // All valid consumers use Var as the first source operand | 271 // All valid consumers use Var as the first source operand |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 Ostream &Str = Func->getContext()->getStrDump(); | 334 Ostream &Str = Func->getContext()->getStrDump(); |
| 332 for (auto &I : Producers) { | 335 for (auto &I : Producers) { |
| 333 if (I.second.Instr == nullptr) | 336 if (I.second.Instr == nullptr) |
| 334 continue; | 337 continue; |
| 335 Str << "Found foldable producer:\n "; | 338 Str << "Found foldable producer:\n "; |
| 336 I.second.Instr->dump(Func); | 339 I.second.Instr->dump(Func); |
| 337 Str << "\n"; | 340 Str << "\n"; |
| 338 } | 341 } |
| 339 } | 342 } |
| 340 | 343 |
| 344 /// If the given instruction has potential memory side effects (e.g. store, rmw, | |
| 345 /// or a call instruction with potential memory side effects), then we must not | |
| 346 /// allow a pre-store Producer instruction with memory operands to be folded | |
| 347 /// into a post-store Consumer instruction. If this is detected, the Producer | |
| 348 /// is invalidated. | |
| 349 /// | |
| 350 /// We use the Producer's IsLiveOut field to determine whether any potential | |
| 351 /// Consumers come after this store instruction. If IsLiveOut has already been | |
| 352 /// set to false, then we know the folding is safe from the store instruction. | |
|
John
2016/04/21 22:50:02
"If IsLiveOut has already been set to false, then
Jim Stichnoth
2016/04/21 23:31:35
Done, hopefully it's more explanatory now.
| |
| 353 template <typename Traits> | |
| 354 void BoolFolding<Traits>::invalidateProducersOnStore(const Inst *Instr) { | |
| 355 if (!Instr->isMemoryWrite()) | |
| 356 return; | |
| 357 for (auto &ProducerPair : Producers) { | |
| 358 if (!ProducerPair.second.IsLiveOut) | |
| 359 continue; | |
| 360 Inst *PInst = ProducerPair.second.Instr; | |
| 361 if (PInst == nullptr) | |
| 362 continue; | |
| 363 bool HasMemOperand = false; | |
| 364 const SizeT SrcSize = PInst->getSrcSize(); | |
| 365 for (SizeT I = 0; !HasMemOperand && I < SrcSize; ++I) { | |
|
John
2016/04/21 22:50:02
why not breaking instead? I would expect llvm to e
Jim Stichnoth
2016/04/21 23:31:35
Done.
| |
| 366 if (llvm::isa<typename Traits::X86OperandMem>(PInst->getSrc(I))) { | |
| 367 HasMemOperand = true; | |
| 368 } | |
| 369 } | |
| 370 if (!HasMemOperand) | |
| 371 continue; | |
| 372 setInvalid(ProducerPair.first); | |
| 373 } | |
| 374 } | |
| 375 | |
| 341 template <typename TraitsType> | 376 template <typename TraitsType> |
| 342 void TargetX86Base<TraitsType>::initNodeForLowering(CfgNode *Node) { | 377 void TargetX86Base<TraitsType>::initNodeForLowering(CfgNode *Node) { |
| 343 FoldingInfo.init(Node); | 378 FoldingInfo.init(Node); |
| 344 FoldingInfo.dump(Func); | 379 FoldingInfo.dump(Func); |
| 345 } | 380 } |
| 346 | 381 |
| 347 template <typename TraitsType> | 382 template <typename TraitsType> |
| 348 TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func) | 383 TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func) |
| 349 : TargetLowering(Func), NeedSandboxing(SandboxingType == ST_NaCl) { | 384 : TargetLowering(Func), NeedSandboxing(SandboxingType == ST_NaCl) { |
| 350 static_assert( | 385 static_assert( |
| (...skipping 7088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7439 emitGlobal(*Var, SectionSuffix); | 7474 emitGlobal(*Var, SectionSuffix); |
| 7440 } | 7475 } |
| 7441 } | 7476 } |
| 7442 } break; | 7477 } break; |
| 7443 } | 7478 } |
| 7444 } | 7479 } |
| 7445 } // end of namespace X86NAMESPACE | 7480 } // end of namespace X86NAMESPACE |
| 7446 } // end of namespace Ice | 7481 } // end of namespace Ice |
| 7447 | 7482 |
| 7448 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 7483 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
| OLD | NEW |