Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringMIPS32.cpp - MIPS32 lowering ----------===// | 1 //===- subzero/src/IceTargetLoweringMIPS32.cpp - MIPS32 lowering ----------===// |
| 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 |
| 11 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost | 11 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost |
| 12 /// entirely of the lowering sequence for each high-level instruction. | 12 /// entirely of the lowering sequence for each high-level instruction. |
| 13 /// | 13 /// |
| 14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
| 15 | 15 |
| 16 #include "IceTargetLoweringMIPS32.h" | 16 #include "IceTargetLoweringMIPS32.h" |
| 17 | 17 |
| 18 #include "IceCfg.h" | 18 #include "IceCfg.h" |
| 19 #include "IceCfgNode.h" | 19 #include "IceCfgNode.h" |
| 20 #include "IceClFlags.h" | 20 #include "IceClFlags.h" |
| 21 #include "IceDefs.h" | 21 #include "IceDefs.h" |
| 22 #include "IceELFObjectWriter.h" | 22 #include "IceELFObjectWriter.h" |
| 23 #include "IceGlobalInits.h" | 23 #include "IceGlobalInits.h" |
| 24 #include "IceInstMIPS32.h" | 24 #include "IceInstMIPS32.h" |
| 25 #include "IceInstVarIter.h" | |
| 25 #include "IceLiveness.h" | 26 #include "IceLiveness.h" |
| 26 #include "IceOperand.h" | 27 #include "IceOperand.h" |
| 27 #include "IcePhiLoweringImpl.h" | 28 #include "IcePhiLoweringImpl.h" |
| 28 #include "IceRegistersMIPS32.h" | 29 #include "IceRegistersMIPS32.h" |
| 29 #include "IceTargetLoweringMIPS32.def" | 30 #include "IceTargetLoweringMIPS32.def" |
| 30 #include "IceUtils.h" | 31 #include "IceUtils.h" |
| 31 #include "llvm/Support/MathExtras.h" | 32 #include "llvm/Support/MathExtras.h" |
| 32 | 33 |
| 33 namespace MIPS32 { | 34 namespace MIPS32 { |
| 34 std::unique_ptr<::Ice::TargetLowering> createTargetLowering(::Ice::Cfg *Func) { | 35 std::unique_ptr<::Ice::TargetLowering> createTargetLowering(::Ice::Cfg *Func) { |
| (...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 806 _mov(Dest, SrcR); | 807 _mov(Dest, SrcR); |
| 807 } | 808 } |
| 808 } | 809 } |
| 809 } | 810 } |
| 810 | 811 |
| 811 void TargetMIPS32::lowerBr(const InstBr *Instr) { | 812 void TargetMIPS32::lowerBr(const InstBr *Instr) { |
| 812 if (Instr->isUnconditional()) { | 813 if (Instr->isUnconditional()) { |
| 813 _br(Instr->getTargetUnconditional()); | 814 _br(Instr->getTargetUnconditional()); |
| 814 return; | 815 return; |
| 815 } | 816 } |
| 816 UnimplementedLoweringError(this, Instr); | 817 CfgNode *TargetTrue = Instr->getTargetTrue(); |
| 818 CfgNode *TargetFalse = Instr->getTargetFalse(); | |
| 819 Operand *Boolean = Instr->getCondition(); | |
| 820 const Inst *Producer = Computations.getProducerOf(Boolean); | |
| 821 assert(Producer != nullptr); | |
| 822 if (Producer->getKind() == Inst::Icmp) { | |
| 823 const InstIcmp *CompareInst = llvm::cast<InstIcmp>(Producer); | |
| 824 Operand *Src0 = CompareInst->getSrc(0); | |
| 825 Operand *Src1 = CompareInst->getSrc(1); | |
| 826 const Type Src0Ty = Src0->getType(); | |
| 827 const Type Src1Ty = Src1->getType(); | |
| 828 if (Src0Ty == IceType_i64 || Src1Ty == IceType_i64) { | |
|
Jim Stichnoth
2016/05/19 15:03:41
Instead of testing both types against i64, I sugge
sagar.thakur
2016/05/23 18:30:26
Done.
| |
| 829 UnimplementedLoweringError(this, Instr); | |
| 830 return; | |
| 831 } | |
| 832 auto *Src0R = legalizeToReg(Src0); | |
| 833 auto *Src1R = legalizeToReg(Src1); | |
| 834 auto *DestT = makeReg(Src0Ty); | |
| 835 switch (CompareInst->getCondition()) { | |
| 836 default: | |
| 837 break; | |
| 838 case InstIcmp::Eq: { | |
| 839 _br(TargetTrue, TargetFalse, Src0R, Src1R, CondMIPS32::Cond::NE); | |
| 840 break; | |
| 841 } | |
| 842 case InstIcmp::Ne: { | |
| 843 _br(TargetTrue, TargetFalse, Src0R, Src1R, CondMIPS32::Cond::EQ); | |
| 844 break; | |
| 845 } | |
| 846 case InstIcmp::Ugt: { | |
| 847 _sltu(DestT, Src1R, Src0R); | |
| 848 _br(TargetTrue, TargetFalse, DestT, NULL, CondMIPS32::Cond::EQZ); | |
|
Jim Stichnoth
2016/05/19 15:03:41
All the NULL should be nullptr.
sagar.thakur
2016/05/23 18:30:26
Done.
| |
| 849 break; | |
| 850 } | |
| 851 case InstIcmp::Uge: { | |
| 852 _sltu(DestT, Src0R, Src1R); | |
| 853 _br(TargetTrue, TargetFalse, DestT, NULL, CondMIPS32::Cond::NEZ); | |
| 854 break; | |
| 855 } | |
| 856 case InstIcmp::Ult: { | |
| 857 _sltu(DestT, Src0R, Src1R); | |
| 858 _br(TargetTrue, TargetFalse, DestT, NULL, CondMIPS32::Cond::EQZ); | |
| 859 break; | |
| 860 } | |
| 861 case InstIcmp::Ule: { | |
| 862 _sltu(DestT, Src1R, Src0R); | |
| 863 _br(TargetTrue, TargetFalse, DestT, NULL, CondMIPS32::Cond::NEZ); | |
| 864 break; | |
| 865 } | |
| 866 case InstIcmp::Sgt: { | |
| 867 _slt(DestT, Src1R, Src0R); | |
| 868 _br(TargetTrue, TargetFalse, DestT, NULL, CondMIPS32::Cond::EQZ); | |
| 869 break; | |
| 870 } | |
| 871 case InstIcmp::Sge: { | |
| 872 _slt(DestT, Src0R, Src1R); | |
| 873 _br(TargetTrue, TargetFalse, DestT, NULL, CondMIPS32::Cond::NEZ); | |
| 874 break; | |
| 875 } | |
| 876 case InstIcmp::Slt: { | |
| 877 _slt(DestT, Src0R, Src1R); | |
| 878 _br(TargetTrue, TargetFalse, DestT, NULL, CondMIPS32::Cond::EQZ); | |
| 879 break; | |
| 880 } | |
| 881 case InstIcmp::Sle: { | |
| 882 _slt(DestT, Src1R, Src0R); | |
| 883 _br(TargetTrue, TargetFalse, DestT, NULL, CondMIPS32::Cond::NEZ); | |
| 884 break; | |
| 885 } | |
| 886 } | |
| 887 } | |
| 888 return; | |
|
John
2016/05/19 14:59:59
no need to "return" here.
sagar.thakur
2016/05/23 18:30:26
Done.
| |
| 817 } | 889 } |
| 818 | 890 |
| 819 void TargetMIPS32::lowerCall(const InstCall *Instr) { | 891 void TargetMIPS32::lowerCall(const InstCall *Instr) { |
| 820 // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. | 892 // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. |
| 821 if (Instr->getNumArgs()) { | 893 if (Instr->getNumArgs()) { |
| 822 UnimplementedLoweringError(this, Instr); | 894 UnimplementedLoweringError(this, Instr); |
| 823 return; | 895 return; |
| 824 } | 896 } |
| 825 // Generate the call instruction. Assign its result to a temporary with high | 897 // Generate the call instruction. Assign its result to a temporary with high |
| 826 // register allocation weight. | 898 // register allocation weight. |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1403 // RegNum is required and Var->getRegNum() doesn't match. | 1475 // RegNum is required and Var->getRegNum() doesn't match. |
| 1404 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 1476 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
| 1405 (RegNum.hasValue() && RegNum != Var->getRegNum())) { | 1477 (RegNum.hasValue() && RegNum != Var->getRegNum())) { |
| 1406 From = copyToReg(From, RegNum); | 1478 From = copyToReg(From, RegNum); |
| 1407 } | 1479 } |
| 1408 return From; | 1480 return From; |
| 1409 } | 1481 } |
| 1410 return From; | 1482 return From; |
| 1411 } | 1483 } |
| 1412 | 1484 |
| 1485 namespace BoolFolding { | |
| 1486 // TODO(sagar.thakur): Add remaining instruction kinds to shouldTrackProducer() | |
| 1487 // and isValidConsumer() | |
| 1488 bool shouldTrackProducer(const Inst &Instr) { | |
| 1489 return Instr.getKind() == Inst::Icmp; | |
| 1490 } | |
| 1491 | |
| 1492 bool isValidConsumer(const Inst &Instr) { return Instr.getKind() == Inst::Br; } | |
| 1493 } // end of namespace BoolFolding | |
| 1494 | |
| 1495 void TargetMIPS32::ComputationTracker::recordProducers(CfgNode *Node) { | |
| 1496 for (Inst &Instr : Node->getInsts()) { | |
| 1497 // Check whether Instr is a valid producer. | |
| 1498 Variable *Dest = Instr.getDest(); | |
| 1499 if (!Instr.isDeleted() // only consider non-deleted instructions; and | |
|
Jim Stichnoth
2016/05/19 15:03:41
The isDeleted() check should be stronger. The who
sagar.thakur
2016/05/23 18:30:26
Done.
| |
| 1500 && Dest // only instructions with an actual dest var; and | |
| 1501 && Dest->getType() == IceType_i1 // only bool-type dest vars; and | |
| 1502 && BoolFolding::shouldTrackProducer(Instr)) { // white-listed instr. | |
| 1503 KnownComputations.emplace(Dest->getIndex(), | |
| 1504 ComputationEntry(&Instr, IceType_i1)); | |
| 1505 } | |
| 1506 // Check each src variable against the map. | |
| 1507 FOREACH_VAR_IN_INST(Var, Instr) { | |
| 1508 SizeT VarNum = Var->getIndex(); | |
| 1509 auto ComputationIter = KnownComputations.find(VarNum); | |
| 1510 if (ComputationIter == KnownComputations.end()) { | |
| 1511 continue; | |
| 1512 } | |
| 1513 | |
| 1514 ++ComputationIter->second.NumUses; | |
| 1515 switch (ComputationIter->second.ComputationType) { | |
| 1516 default: | |
| 1517 KnownComputations.erase(VarNum); | |
| 1518 continue; | |
| 1519 case IceType_i1: | |
| 1520 if (!BoolFolding::isValidConsumer(Instr)) { | |
| 1521 KnownComputations.erase(VarNum); | |
| 1522 continue; | |
| 1523 } | |
| 1524 break; | |
| 1525 } | |
| 1526 | |
| 1527 if (Instr.isLastUse(Var)) { | |
| 1528 ComputationIter->second.IsLiveOut = false; | |
| 1529 } | |
| 1530 } | |
| 1531 } | |
| 1532 | |
| 1533 for (auto Iter = KnownComputations.begin(), End = KnownComputations.end(); | |
| 1534 Iter != End;) { | |
| 1535 // Disable the folding if its dest may be live beyond this block. | |
| 1536 if (Iter->second.IsLiveOut || Iter->second.NumUses > 1) { | |
| 1537 Iter = KnownComputations.erase(Iter); | |
| 1538 continue; | |
| 1539 } | |
| 1540 | |
| 1541 // Mark as "dead" rather than outright deleting. This is so that other | |
| 1542 // peephole style optimizations during or before lowering have access to | |
| 1543 // this instruction in undeleted form. See for example | |
| 1544 // tryOptimizedCmpxchgCmpBr(). | |
| 1545 Iter->second.Instr->setDead(); | |
| 1546 ++Iter; | |
| 1547 } | |
| 1548 } | |
| 1549 | |
| 1413 TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx) | 1550 TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx) |
| 1414 : TargetHeaderLowering(Ctx) {} | 1551 : TargetHeaderLowering(Ctx) {} |
| 1415 | 1552 |
| 1416 void TargetHeaderMIPS32::lower() { | 1553 void TargetHeaderMIPS32::lower() { |
| 1417 OstreamLocker L(Ctx); | 1554 OstreamLocker L(Ctx); |
| 1418 Ostream &Str = Ctx->getStrEmit(); | 1555 Ostream &Str = Ctx->getStrEmit(); |
| 1419 Str << "\t.set\t" | 1556 Str << "\t.set\t" |
| 1420 << "nomicromips\n"; | 1557 << "nomicromips\n"; |
| 1421 Str << "\t.set\t" | 1558 Str << "\t.set\t" |
| 1422 << "nomips16\n"; | 1559 << "nomips16\n"; |
| 1423 } | 1560 } |
| 1424 | 1561 |
| 1425 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 1562 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
| 1426 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 1563 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
| 1427 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 1564 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
| 1428 | 1565 |
| 1429 } // end of namespace MIPS32 | 1566 } // end of namespace MIPS32 |
| 1430 } // end of namespace Ice | 1567 } // end of namespace Ice |
| OLD | NEW |