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 |