Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===// | 1 //===- subzero/src/IceTargetLoweringARM32.h - ARM32 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 // The target lowering logic for ARM32. | 51 // The target lowering logic for ARM32. |
| 52 class TargetARM32 : public TargetLowering { | 52 class TargetARM32 : public TargetLowering { |
| 53 TargetARM32() = delete; | 53 TargetARM32() = delete; |
| 54 TargetARM32(const TargetARM32 &) = delete; | 54 TargetARM32(const TargetARM32 &) = delete; |
| 55 TargetARM32 &operator=(const TargetARM32 &) = delete; | 55 TargetARM32 &operator=(const TargetARM32 &) = delete; |
| 56 | 56 |
| 57 public: | 57 public: |
| 58 // TODO(jvoung): return a unique_ptr. | 58 // TODO(jvoung): return a unique_ptr. |
| 59 static TargetARM32 *create(Cfg *Func) { return new TargetARM32(Func); } | 59 static TargetARM32 *create(Cfg *Func) { return new TargetARM32(Func); } |
| 60 | 60 |
| 61 void initNodeForLowering(CfgNode *Node) override { | |
| 62 BoolComputations.forgetProducers(); | |
| 63 BoolComputations.recordProducers(Node); | |
| 64 BoolComputations.dump(Func); | |
| 65 } | |
| 66 | |
| 61 void translateOm1() override; | 67 void translateOm1() override; |
| 62 void translateO2() override; | 68 void translateO2() override; |
| 63 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override; | 69 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override; |
| 64 | 70 |
| 65 SizeT getNumRegisters() const override { return RegARM32::Reg_NUM; } | 71 SizeT getNumRegisters() const override { return RegARM32::Reg_NUM; } |
| 66 Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override; | 72 Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override; |
| 67 IceString getRegName(SizeT RegNum, Type Ty) const override; | 73 IceString getRegName(SizeT RegNum, Type Ty) const override; |
| 68 llvm::SmallBitVector getRegisterSet(RegSetMask Include, | 74 llvm::SmallBitVector getRegisterSet(RegSetMask Include, |
| 69 RegSetMask Exclude) const override; | 75 RegSetMask Exclude) const override; |
| 70 const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override { | 76 const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 | 129 |
| 124 void postLower() override; | 130 void postLower() override; |
| 125 | 131 |
| 126 void lowerAlloca(const InstAlloca *Inst) override; | 132 void lowerAlloca(const InstAlloca *Inst) override; |
| 127 void lowerArithmetic(const InstArithmetic *Inst) override; | 133 void lowerArithmetic(const InstArithmetic *Inst) override; |
| 128 void lowerAssign(const InstAssign *Inst) override; | 134 void lowerAssign(const InstAssign *Inst) override; |
| 129 void lowerBr(const InstBr *Inst) override; | 135 void lowerBr(const InstBr *Inst) override; |
| 130 void lowerCall(const InstCall *Inst) override; | 136 void lowerCall(const InstCall *Inst) override; |
| 131 void lowerCast(const InstCast *Inst) override; | 137 void lowerCast(const InstCast *Inst) override; |
| 132 void lowerExtractElement(const InstExtractElement *Inst) override; | 138 void lowerExtractElement(const InstExtractElement *Inst) override; |
| 133 void lowerFcmp(const InstFcmp *Inst) override; | 139 void lowerFcmpCond(const InstFcmp *Instr, CondARM32::Cond *CondIfTrue0, |
| 134 void lowerIcmp(const InstIcmp *Inst) override; | 140 CondARM32::Cond *CondIfTrue1, |
| 141 CondARM32::Cond *CondIfFalse); | |
| 142 void lowerFcmp(const InstFcmp *Instr) override; | |
| 143 void lowerIcmpCond(const InstIcmp *Instr, CondARM32::Cond *CondIfTrue, | |
| 144 CondARM32::Cond *CondIfFalse); | |
| 145 void lowerIcmp(const InstIcmp *Instr) override; | |
| 135 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, | 146 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, |
| 136 Operand *Val); | 147 Operand *Val); |
| 137 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override; | 148 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override; |
| 138 void lowerInsertElement(const InstInsertElement *Inst) override; | 149 void lowerInsertElement(const InstInsertElement *Inst) override; |
| 139 void lowerLoad(const InstLoad *Inst) override; | 150 void lowerLoad(const InstLoad *Inst) override; |
| 140 void lowerPhi(const InstPhi *Inst) override; | 151 void lowerPhi(const InstPhi *Inst) override; |
| 141 void lowerRet(const InstRet *Inst) override; | 152 void lowerRet(const InstRet *Inst) override; |
| 142 void lowerSelect(const InstSelect *Inst) override; | 153 void lowerSelect(const InstSelect *Inst) override; |
| 143 void lowerStore(const InstStore *Inst) override; | 154 void lowerStore(const InstStore *Inst) override; |
| 144 void lowerSwitch(const InstSwitch *Inst) override; | 155 void lowerSwitch(const InstSwitch *Inst) override; |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 auto *Instr = InstARM32Mov::create(Func, Dest, Src0, Pred); | 320 auto *Instr = InstARM32Mov::create(Func, Dest, Src0, Pred); |
| 310 Instr->setDestRedefined(); | 321 Instr->setDestRedefined(); |
| 311 Context.insert(Instr); | 322 Context.insert(Instr); |
| 312 if (Instr->isMultiDest()) { | 323 if (Instr->isMultiDest()) { |
| 313 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a | 324 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a |
| 314 // fake-def for Instr.DestHi here. | 325 // fake-def for Instr.DestHi here. |
| 315 assert(llvm::isa<Variable64On32>(Dest)); | 326 assert(llvm::isa<Variable64On32>(Dest)); |
| 316 Context.insert(InstFakeDef::create(Func, Instr->getDestHi())); | 327 Context.insert(InstFakeDef::create(Func, Instr->getDestHi())); |
| 317 } | 328 } |
| 318 } | 329 } |
| 330 | |
| 331 // _mov_i1_to_flags is used for bool folding. If "Boolean" is fold, this | |
|
Jim Stichnoth
2015/11/03 20:04:28
There are a few places in comments where I think "
John
2015/11/05 20:25:39
Done.
| |
| 332 // method returns true, and sets "CondIfTrue0" and "CondIfTrue1" to the | |
| 333 // appropriate ARM condition codes. If "Boolean" is not to be fold, then this | |
| 334 // method returns false. | |
| 335 bool _mov_i1_to_flags(Operand *Boolean, CondARM32::Cond *CondIfTrue0, | |
| 336 CondARM32::Cond *CondIfTrue1, | |
| 337 CondARM32::Cond *CondIfFalse); | |
| 338 | |
| 339 // _cmov is a pseudo instruction that is used fol boolean folding. It emits | |
|
Jim Stichnoth
2015/11/03 20:04:28
for
John
2015/11/05 20:25:39
Done.
| |
| 340 // code that moves "SrcIfTrue" to dest if either "CondIfTrue0" or | |
| 341 // "CondIfTrue1" holds, and "SrcIfFalse", if "CondIfFalse" holds. It requires | |
| 342 // "Dest" to be an infinite-weight temporary. | |
| 343 void _cmov(Variable *Dest, Operand *SrcIfTrue, CondARM32::Cond CondIfTrue0, | |
| 344 CondARM32::Cond CondIfTrue1, Operand *SrcIfFalse, | |
| 345 CondARM32::Cond CondIfFalse) { | |
| 346 assert(Dest->mustHaveReg()); | |
| 347 | |
| 348 if (CondIfFalse == CondARM32::kNone) { | |
| 349 assert(CondIfTrue0 == CondARM32::AL); | |
| 350 assert(CondIfTrue1 == CondARM32::kNone); | |
| 351 } | |
| 352 | |
| 353 if (CondIfTrue0 == CondARM32::kNone) { | |
| 354 assert(CondIfFalse == CondARM32::AL); | |
| 355 assert(CondIfTrue1 == CondARM32::kNone); | |
| 356 } | |
| 357 | |
| 358 if (CondIfTrue1 != CondARM32::kNone) { | |
| 359 assert(CondIfFalse == CondARM32::AL); | |
| 360 assert(CondIfTrue1 != CondARM32::kNone); | |
| 361 } | |
| 362 | |
| 363 bool RedefineT = false; | |
| 364 if (CondIfFalse != CondARM32::kNone) { | |
| 365 _mov(Dest, SrcIfFalse, CondIfFalse); | |
| 366 RedefineT = true; | |
| 367 } | |
| 368 | |
| 369 if (CondIfTrue0 != CondARM32::kNone) { | |
| 370 if (RedefineT) { | |
| 371 _mov_redefined(Dest, SrcIfTrue, CondIfTrue0); | |
| 372 } else { | |
| 373 _mov(Dest, SrcIfTrue, CondIfTrue0); | |
| 374 } | |
| 375 RedefineT = true; | |
| 376 } | |
| 377 | |
| 378 if (CondIfTrue1 != CondARM32::kNone) { | |
| 379 assert(RedefineT); | |
| 380 _mov_redefined(Dest, SrcIfTrue, CondIfTrue1); | |
| 381 } | |
| 382 } | |
| 383 | |
| 319 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with | 384 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with |
| 320 /// an upper16 relocation). | 385 /// an upper16 relocation). |
| 321 void _movt(Variable *Dest, Operand *Src0, | 386 void _movt(Variable *Dest, Operand *Src0, |
| 322 CondARM32::Cond Pred = CondARM32::AL) { | 387 CondARM32::Cond Pred = CondARM32::AL) { |
| 323 Context.insert(InstARM32Movt::create(Func, Dest, Src0, Pred)); | 388 Context.insert(InstARM32Movt::create(Func, Dest, Src0, Pred)); |
| 324 } | 389 } |
| 325 void _movw(Variable *Dest, Operand *Src0, | 390 void _movw(Variable *Dest, Operand *Src0, |
| 326 CondARM32::Cond Pred = CondARM32::AL) { | 391 CondARM32::Cond Pred = CondARM32::AL) { |
| 327 Context.insert(InstARM32Movw::create(Func, Dest, Src0, Pred)); | 392 Context.insert(InstARM32Movw::create(Func, Dest, Src0, Pred)); |
| 328 } | 393 } |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 | 600 |
| 536 private: | 601 private: |
| 537 uint32_t NumGPRRegsUsed = 0; | 602 uint32_t NumGPRRegsUsed = 0; |
| 538 llvm::SmallBitVector VFPRegsFree; | 603 llvm::SmallBitVector VFPRegsFree; |
| 539 llvm::SmallBitVector ValidF64Regs; | 604 llvm::SmallBitVector ValidF64Regs; |
| 540 llvm::SmallBitVector ValidV128Regs; | 605 llvm::SmallBitVector ValidV128Regs; |
| 541 }; | 606 }; |
| 542 | 607 |
| 543 private: | 608 private: |
| 544 ~TargetARM32() override = default; | 609 ~TargetARM32() override = default; |
| 610 | |
| 611 void lowerTruncToFlags(Operand *Src, CondARM32::Cond *CondIfTrue, | |
| 612 CondARM32::Cond *CondIfFalse); | |
| 613 class BoolComputationTracker { | |
| 614 public: | |
| 615 BoolComputationTracker() = default; | |
| 616 ~BoolComputationTracker() = default; | |
| 617 | |
| 618 void forgetProducers() { KnownComputations.clear(); } | |
| 619 void recordProducers(CfgNode *Node); | |
| 620 | |
| 621 const Inst *getProducerOf(const Operand *Opnd) const { | |
| 622 auto *Var = llvm::dyn_cast<Variable>(Opnd); | |
| 623 if (Var == nullptr) { | |
| 624 return nullptr; | |
| 625 } | |
| 626 | |
| 627 auto Iter = KnownComputations.find(Var->getIndex()); | |
| 628 if (Iter == KnownComputations.end()) { | |
| 629 return nullptr; | |
| 630 } | |
| 631 | |
| 632 return Iter->second.Instr; | |
| 633 } | |
| 634 | |
| 635 void dump(const Cfg *Func) const { | |
| 636 if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding)) | |
| 637 return; | |
| 638 OstreamLocker L(Func->getContext()); | |
| 639 Ostream &Str = Func->getContext()->getStrDump(); | |
| 640 Str << "foldable producer:\n "; | |
| 641 for (const auto &Computation : KnownComputations) { | |
| 642 Str << " "; | |
| 643 Computation.second.Instr->dump(Func); | |
| 644 Str << "\n"; | |
| 645 } | |
| 646 Str << "\n"; | |
| 647 } | |
| 648 | |
| 649 private: | |
| 650 struct BoolComputationEntry { | |
|
Jim Stichnoth
2015/11/03 20:04:28
Make this class instead of struct?
I'm not sure w
John
2015/11/05 20:25:39
I tend to think of classes as "data with behavior,
| |
| 651 explicit BoolComputationEntry(Inst *I) : Instr(I) {} | |
| 652 Inst *Instr; | |
|
Jim Stichnoth
2015/11/03 20:04:28
How about
Inst *const Instr;
?
John
2015/11/05 20:25:39
Done.
| |
| 653 // Boolean folding is disabled for variables whose live range is multi | |
| 654 // block. We conservatively initialize IsLiveOut to true, and set it to | |
| 655 // false once we find the end of the live range for the variable defined | |
| 656 // by this instruction. If liveness analysis is not performed (e.g., in | |
| 657 // Om1 mode) IsLiveOut will never be set to false, and folding will be | |
| 658 // disabled. | |
| 659 bool IsLiveOut = true; | |
| 660 }; | |
| 661 | |
| 662 using BoolComputationMap = std::unordered_map<SizeT, BoolComputationEntry>; | |
| 663 BoolComputationMap KnownComputations; | |
| 664 }; | |
| 665 | |
| 666 BoolComputationTracker BoolComputations; | |
| 545 }; | 667 }; |
| 546 | 668 |
| 547 class TargetDataARM32 final : public TargetDataLowering { | 669 class TargetDataARM32 final : public TargetDataLowering { |
| 548 TargetDataARM32() = delete; | 670 TargetDataARM32() = delete; |
| 549 TargetDataARM32(const TargetDataARM32 &) = delete; | 671 TargetDataARM32(const TargetDataARM32 &) = delete; |
| 550 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete; | 672 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete; |
| 551 | 673 |
| 552 public: | 674 public: |
| 553 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { | 675 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { |
| 554 return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx)); | 676 return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx)); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 583 | 705 |
| 584 private: | 706 private: |
| 585 ~TargetHeaderARM32() = default; | 707 ~TargetHeaderARM32() = default; |
| 586 | 708 |
| 587 TargetARM32Features CPUFeatures; | 709 TargetARM32Features CPUFeatures; |
| 588 }; | 710 }; |
| 589 | 711 |
| 590 } // end of namespace Ice | 712 } // end of namespace Ice |
| 591 | 713 |
| 592 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H | 714 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H |
| OLD | NEW |