Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: src/IceTargetLoweringMIPS32.cpp

Issue 1993773004: [Subzero][MIPS32] Addition of bool folding machinery and implementation of conditional branches (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addressed review comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 we the producer of this boolean we will assume
Jim Stichnoth 2016/05/23 19:53:05 "we don't we" is wrong Also, can you reflow the c
sagar.thakur 2016/05/24 05:44:36 Done.
823 // its producer will keep it in positive logic and just emit beqz
824 // with this 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
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
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 instructions with an actual dest var; and
Jim Stichnoth 2016/05/23 19:53:05 I would start this comment as "only consider instr
sagar.thakur 2016/05/24 05:44:36 Done.
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698