| 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   if (Producer == nullptr) { | 
|  | 822     // Since we don't know the producer of this boolean we will assume its | 
|  | 823     // producer will keep it in positive logic and just emit beqz with this | 
|  | 824     // Boolean as an operand. | 
|  | 825     auto *BooleanR = legalizeToReg(Boolean); | 
|  | 826     _br(TargetTrue, TargetFalse, BooleanR, CondMIPS32::Cond::EQZ); | 
|  | 827     return; | 
|  | 828   } | 
|  | 829   if (Producer->getKind() == Inst::Icmp) { | 
|  | 830     const InstIcmp *CompareInst = llvm::cast<InstIcmp>(Producer); | 
|  | 831     Operand *Src0 = CompareInst->getSrc(0); | 
|  | 832     Operand *Src1 = CompareInst->getSrc(1); | 
|  | 833     const Type Src0Ty = Src0->getType(); | 
|  | 834     assert(Src0Ty == Src1->getType()); | 
|  | 835     if (Src0Ty == IceType_i64) { | 
|  | 836       UnimplementedLoweringError(this, Instr); | 
|  | 837       return; | 
|  | 838     } | 
|  | 839     auto *Src0R = legalizeToReg(Src0); | 
|  | 840     auto *Src1R = legalizeToReg(Src1); | 
|  | 841     auto *DestT = makeReg(Src0Ty); | 
|  | 842     switch (CompareInst->getCondition()) { | 
|  | 843     default: | 
|  | 844       break; | 
|  | 845     case InstIcmp::Eq: { | 
|  | 846       _br(TargetTrue, TargetFalse, Src0R, Src1R, CondMIPS32::Cond::NE); | 
|  | 847       break; | 
|  | 848     } | 
|  | 849     case InstIcmp::Ne: { | 
|  | 850       _br(TargetTrue, TargetFalse, Src0R, Src1R, CondMIPS32::Cond::EQ); | 
|  | 851       break; | 
|  | 852     } | 
|  | 853     case InstIcmp::Ugt: { | 
|  | 854       _sltu(DestT, Src1R, Src0R); | 
|  | 855       _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ); | 
|  | 856       break; | 
|  | 857     } | 
|  | 858     case InstIcmp::Uge: { | 
|  | 859       _sltu(DestT, Src0R, Src1R); | 
|  | 860       _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); | 
|  | 861       break; | 
|  | 862     } | 
|  | 863     case InstIcmp::Ult: { | 
|  | 864       _sltu(DestT, Src0R, Src1R); | 
|  | 865       _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ); | 
|  | 866       break; | 
|  | 867     } | 
|  | 868     case InstIcmp::Ule: { | 
|  | 869       _sltu(DestT, Src1R, Src0R); | 
|  | 870       _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); | 
|  | 871       break; | 
|  | 872     } | 
|  | 873     case InstIcmp::Sgt: { | 
|  | 874       _slt(DestT, Src1R, Src0R); | 
|  | 875       _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ); | 
|  | 876       break; | 
|  | 877     } | 
|  | 878     case InstIcmp::Sge: { | 
|  | 879       _slt(DestT, Src0R, Src1R); | 
|  | 880       _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); | 
|  | 881       break; | 
|  | 882     } | 
|  | 883     case InstIcmp::Slt: { | 
|  | 884       _slt(DestT, Src0R, Src1R); | 
|  | 885       _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ); | 
|  | 886       break; | 
|  | 887     } | 
|  | 888     case InstIcmp::Sle: { | 
|  | 889       _slt(DestT, Src1R, Src0R); | 
|  | 890       _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); | 
|  | 891       break; | 
|  | 892     } | 
|  | 893     } | 
|  | 894   } | 
| 817 } | 895 } | 
| 818 | 896 | 
| 819 void TargetMIPS32::lowerCall(const InstCall *Instr) { | 897 void TargetMIPS32::lowerCall(const InstCall *Instr) { | 
| 820   // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. | 898   // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. | 
| 821   if (Instr->getNumArgs()) { | 899   if (Instr->getNumArgs()) { | 
| 822     UnimplementedLoweringError(this, Instr); | 900     UnimplementedLoweringError(this, Instr); | 
| 823     return; | 901     return; | 
| 824   } | 902   } | 
| 825   // Generate the call instruction.  Assign its result to a temporary with high | 903   // Generate the call instruction.  Assign its result to a temporary with high | 
| 826   // register allocation weight. | 904   // register allocation weight. | 
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1024   } | 1102   } | 
| 1025   case InstIcmp::Sgt: { | 1103   case InstIcmp::Sgt: { | 
| 1026     auto *DestT = I32Reg(); | 1104     auto *DestT = I32Reg(); | 
| 1027     _slt(DestT, Src1R, Src0R); | 1105     _slt(DestT, Src1R, Src0R); | 
| 1028     _mov(Dest, DestT); | 1106     _mov(Dest, DestT); | 
| 1029     return; | 1107     return; | 
| 1030   } | 1108   } | 
| 1031   case InstIcmp::Sge: { | 1109   case InstIcmp::Sge: { | 
| 1032     auto *DestT = I32Reg(); | 1110     auto *DestT = I32Reg(); | 
| 1033     auto *T = I32Reg(); | 1111     auto *T = I32Reg(); | 
| 1034     _slt(T, Src1R, Src0R); | 1112     _slt(T, Src0R, Src1R); | 
| 1035     _xori(DestT, T, 1); | 1113     _xori(DestT, T, 1); | 
| 1036     _mov(Dest, DestT); | 1114     _mov(Dest, DestT); | 
| 1037     return; | 1115     return; | 
| 1038   } | 1116   } | 
| 1039   case InstIcmp::Slt: { | 1117   case InstIcmp::Slt: { | 
| 1040     auto *DestT = I32Reg(); | 1118     auto *DestT = I32Reg(); | 
| 1041     _slt(DestT, Src0R, Src1R); | 1119     _slt(DestT, Src0R, Src1R); | 
| 1042     _mov(Dest, DestT); | 1120     _mov(Dest, DestT); | 
| 1043     return; | 1121     return; | 
| 1044   } | 1122   } | 
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1403     //   RegNum is required and Var->getRegNum() doesn't match. | 1481     //   RegNum is required and Var->getRegNum() doesn't match. | 
| 1404     if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 1482     if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 
| 1405         (RegNum.hasValue() && RegNum != Var->getRegNum())) { | 1483         (RegNum.hasValue() && RegNum != Var->getRegNum())) { | 
| 1406       From = copyToReg(From, RegNum); | 1484       From = copyToReg(From, RegNum); | 
| 1407     } | 1485     } | 
| 1408     return From; | 1486     return From; | 
| 1409   } | 1487   } | 
| 1410   return From; | 1488   return From; | 
| 1411 } | 1489 } | 
| 1412 | 1490 | 
|  | 1491 namespace BoolFolding { | 
|  | 1492 // TODO(sagar.thakur): Add remaining instruction kinds to shouldTrackProducer() | 
|  | 1493 // and isValidConsumer() | 
|  | 1494 bool shouldTrackProducer(const Inst &Instr) { | 
|  | 1495   return Instr.getKind() == Inst::Icmp; | 
|  | 1496 } | 
|  | 1497 | 
|  | 1498 bool isValidConsumer(const Inst &Instr) { return Instr.getKind() == Inst::Br; } | 
|  | 1499 } // end of namespace BoolFolding | 
|  | 1500 | 
|  | 1501 void TargetMIPS32::ComputationTracker::recordProducers(CfgNode *Node) { | 
|  | 1502   for (Inst &Instr : Node->getInsts()) { | 
|  | 1503     if (Instr.isDeleted()) | 
|  | 1504       continue; | 
|  | 1505     // Check whether Instr is a valid producer. | 
|  | 1506     Variable *Dest = Instr.getDest(); | 
|  | 1507     if (Dest // only consider instructions with an actual dest var; and | 
|  | 1508         && Dest->getType() == IceType_i1 // only bool-type dest vars; and | 
|  | 1509         && BoolFolding::shouldTrackProducer(Instr)) { // white-listed instr. | 
|  | 1510       KnownComputations.emplace(Dest->getIndex(), | 
|  | 1511                                 ComputationEntry(&Instr, IceType_i1)); | 
|  | 1512     } | 
|  | 1513     // Check each src variable against the map. | 
|  | 1514     FOREACH_VAR_IN_INST(Var, Instr) { | 
|  | 1515       SizeT VarNum = Var->getIndex(); | 
|  | 1516       auto ComputationIter = KnownComputations.find(VarNum); | 
|  | 1517       if (ComputationIter == KnownComputations.end()) { | 
|  | 1518         continue; | 
|  | 1519       } | 
|  | 1520 | 
|  | 1521       ++ComputationIter->second.NumUses; | 
|  | 1522       switch (ComputationIter->second.ComputationType) { | 
|  | 1523       default: | 
|  | 1524         KnownComputations.erase(VarNum); | 
|  | 1525         continue; | 
|  | 1526       case IceType_i1: | 
|  | 1527         if (!BoolFolding::isValidConsumer(Instr)) { | 
|  | 1528           KnownComputations.erase(VarNum); | 
|  | 1529           continue; | 
|  | 1530         } | 
|  | 1531         break; | 
|  | 1532       } | 
|  | 1533 | 
|  | 1534       if (Instr.isLastUse(Var)) { | 
|  | 1535         ComputationIter->second.IsLiveOut = false; | 
|  | 1536       } | 
|  | 1537     } | 
|  | 1538   } | 
|  | 1539 | 
|  | 1540   for (auto Iter = KnownComputations.begin(), End = KnownComputations.end(); | 
|  | 1541        Iter != End;) { | 
|  | 1542     // Disable the folding if its dest may be live beyond this block. | 
|  | 1543     if (Iter->second.IsLiveOut || Iter->second.NumUses > 1) { | 
|  | 1544       Iter = KnownComputations.erase(Iter); | 
|  | 1545       continue; | 
|  | 1546     } | 
|  | 1547 | 
|  | 1548     // Mark as "dead" rather than outright deleting. This is so that other | 
|  | 1549     // peephole style optimizations during or before lowering have access to | 
|  | 1550     // this instruction in undeleted form. See for example | 
|  | 1551     // tryOptimizedCmpxchgCmpBr(). | 
|  | 1552     Iter->second.Instr->setDead(); | 
|  | 1553     ++Iter; | 
|  | 1554   } | 
|  | 1555 } | 
|  | 1556 | 
| 1413 TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx) | 1557 TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx) | 
| 1414     : TargetHeaderLowering(Ctx) {} | 1558     : TargetHeaderLowering(Ctx) {} | 
| 1415 | 1559 | 
| 1416 void TargetHeaderMIPS32::lower() { | 1560 void TargetHeaderMIPS32::lower() { | 
| 1417   OstreamLocker L(Ctx); | 1561   OstreamLocker L(Ctx); | 
| 1418   Ostream &Str = Ctx->getStrEmit(); | 1562   Ostream &Str = Ctx->getStrEmit(); | 
| 1419   Str << "\t.set\t" | 1563   Str << "\t.set\t" | 
| 1420       << "nomicromips\n"; | 1564       << "nomicromips\n"; | 
| 1421   Str << "\t.set\t" | 1565   Str << "\t.set\t" | 
| 1422       << "nomips16\n"; | 1566       << "nomips16\n"; | 
| 1423 } | 1567 } | 
| 1424 | 1568 | 
| 1425 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 1569 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 
| 1426 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 1570 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 
| 1427 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 1571 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 
| 1428 | 1572 | 
| 1429 } // end of namespace MIPS32 | 1573 } // end of namespace MIPS32 | 
| 1430 } // end of namespace Ice | 1574 } // end of namespace Ice | 
| OLD | NEW | 
|---|