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 folded, this |
| 332 // method returns true, and sets "CondIfTrue0" and "CondIfTrue1" to the |
| 333 // appropriate ARM condition codes. If "Boolean" is not to be folded, then thi
s |
| 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 for boolean folding. It emits |
| 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 class BoolComputationEntry { |
| 651 public: |
| 652 explicit BoolComputationEntry(Inst *I) : Instr(I) {} |
| 653 Inst *const Instr; |
| 654 // Boolean folding is disabled for variables whose live range is multi |
| 655 // block. We conservatively initialize IsLiveOut to true, and set it to |
| 656 // false once we find the end of the live range for the variable defined |
| 657 // by this instruction. If liveness analysis is not performed (e.g., in |
| 658 // Om1 mode) IsLiveOut will never be set to false, and folding will be |
| 659 // disabled. |
| 660 bool IsLiveOut = true; |
| 661 }; |
| 662 |
| 663 using BoolComputationMap = std::unordered_map<SizeT, BoolComputationEntry>; |
| 664 BoolComputationMap KnownComputations; |
| 665 }; |
| 666 |
| 667 BoolComputationTracker BoolComputations; |
545 }; | 668 }; |
546 | 669 |
547 class TargetDataARM32 final : public TargetDataLowering { | 670 class TargetDataARM32 final : public TargetDataLowering { |
548 TargetDataARM32() = delete; | 671 TargetDataARM32() = delete; |
549 TargetDataARM32(const TargetDataARM32 &) = delete; | 672 TargetDataARM32(const TargetDataARM32 &) = delete; |
550 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete; | 673 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete; |
551 | 674 |
552 public: | 675 public: |
553 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { | 676 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { |
554 return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx)); | 677 return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx)); |
(...skipping 28 matching lines...) Expand all Loading... |
583 | 706 |
584 private: | 707 private: |
585 ~TargetHeaderARM32() = default; | 708 ~TargetHeaderARM32() = default; |
586 | 709 |
587 TargetARM32Features CPUFeatures; | 710 TargetARM32Features CPUFeatures; |
588 }; | 711 }; |
589 | 712 |
590 } // end of namespace Ice | 713 } // end of namespace Ice |
591 | 714 |
592 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H | 715 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H |
OLD | NEW |