Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===// | 1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===// |
| 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 if (!Insts.empty()) { | 44 if (!Insts.empty()) { |
| 45 Func->setError("Phi instruction added to the middle of a block"); | 45 Func->setError("Phi instruction added to the middle of a block"); |
| 46 return; | 46 return; |
| 47 } | 47 } |
| 48 Phis.push_back(Phi); | 48 Phis.push_back(Phi); |
| 49 } else { | 49 } else { |
| 50 Insts.push_back(Instr); | 50 Insts.push_back(Instr); |
| 51 } | 51 } |
| 52 } | 52 } |
| 53 | 53 |
| 54 void CfgNode::replaceInEdge(CfgNode *Old, CfgNode *New) { | |
| 55 for (SizeT i = 0; i < InEdges.size(); ++i) { | |
| 56 if (InEdges[i] == Old) { | |
| 57 InEdges[i] = New; | |
| 58 } | |
| 59 } | |
| 60 for (auto &Inst : getPhis()) { | |
| 61 InstPhi &Phi = llvm::cast<InstPhi>(Inst); | |
|
Jim Stichnoth
2016/06/27 19:44:41
auto &
| |
| 62 for (SizeT i = 0; i < Phi.getSrcSize(); ++i) { | |
| 63 if (Phi.getLabel(i) == Old) { | |
| 64 Phi.setLabel(i, New); | |
| 65 } | |
| 66 } | |
| 67 } | |
| 68 } | |
| 69 | |
| 54 namespace { | 70 namespace { |
| 55 template <typename List> void removeDeletedAndRenumber(List *L, Cfg *Func) { | 71 template <typename List> void removeDeletedAndRenumber(List *L, Cfg *Func) { |
| 56 const bool DoDelete = | 72 const bool DoDelete = |
| 57 BuildDefs::minimal() || !getFlags().getKeepDeletedInsts(); | 73 BuildDefs::minimal() || !getFlags().getKeepDeletedInsts(); |
| 58 auto I = L->begin(), E = L->end(), Next = I; | 74 auto I = L->begin(), E = L->end(), Next = I; |
| 59 for (++Next; I != E; I = Next++) { | 75 for (++Next; I != E; I = Next++) { |
| 60 if (DoDelete && I->isDeleted()) { | 76 if (DoDelete && I->isDeleted()) { |
| 61 L->erase(I); | 77 L->erase(I); |
| 62 } else { | 78 } else { |
| 63 I->renumber(Func); | 79 I->renumber(Func); |
| (...skipping 1401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1465 | 1481 |
| 1466 auto *Instr = InstIntrinsicCall::create( | 1482 auto *Instr = InstIntrinsicCall::create( |
| 1467 Func, 5, Func->makeVariable(IceType_i64), RMWI64Name, Info->Info); | 1483 Func, 5, Func->makeVariable(IceType_i64), RMWI64Name, Info->Info); |
| 1468 Instr->addArg(AtomicRMWOp); | 1484 Instr->addArg(AtomicRMWOp); |
| 1469 Instr->addArg(Counter); | 1485 Instr->addArg(Counter); |
| 1470 Instr->addArg(One); | 1486 Instr->addArg(One); |
| 1471 Instr->addArg(OrderAcquireRelease); | 1487 Instr->addArg(OrderAcquireRelease); |
| 1472 Insts.push_front(Instr); | 1488 Insts.push_front(Instr); |
| 1473 } | 1489 } |
| 1474 | 1490 |
| 1491 void CfgNode::removeInEdge(CfgNode *In) { | |
| 1492 InEdges.erase(std::find(InEdges.begin(), InEdges.end(), In)); | |
| 1493 } | |
| 1494 | |
| 1495 CfgNode *CfgNode::shortCircuit() { | |
| 1496 auto *Func = getCfg(); | |
| 1497 auto *Last = &getInsts().back(); | |
| 1498 Variable *Condition = nullptr; | |
| 1499 InstBr *Br = nullptr; | |
| 1500 if ((Br = llvm::dyn_cast<InstBr>(Last))) { | |
| 1501 if (!Br->isUnconditional()) { | |
| 1502 Condition = llvm::dyn_cast<Variable>(Br->getCondition()); | |
| 1503 } | |
| 1504 } | |
| 1505 if (Condition == nullptr) | |
| 1506 return nullptr; | |
| 1507 | |
| 1508 auto *JumpOnTrue = Br->getTargetTrue(); | |
| 1509 auto *JumpOnFalse = Br->getTargetFalse(); | |
| 1510 | |
| 1511 bool FoundOr = false; | |
| 1512 bool FoundAnd = false; | |
| 1513 | |
| 1514 InstArithmetic *TopLevelBoolOp = nullptr; | |
| 1515 | |
| 1516 for (auto &Inst : reverse_range(getInsts())) { | |
| 1517 if (Inst.isDeleted()) | |
| 1518 continue; | |
| 1519 if (Inst.getDest() == Condition) { | |
| 1520 if (auto *Arith = llvm::dyn_cast<InstArithmetic>(&Inst)) { | |
| 1521 | |
| 1522 FoundOr = (Arith->getOp() == InstArithmetic::OpKind::Or); | |
| 1523 FoundAnd = (Arith->getOp() == InstArithmetic::OpKind::And); | |
| 1524 | |
| 1525 if (FoundOr || FoundAnd) { | |
| 1526 TopLevelBoolOp = Arith; | |
| 1527 break; | |
| 1528 } | |
| 1529 } | |
| 1530 } | |
| 1531 } | |
| 1532 | |
| 1533 if (!TopLevelBoolOp) | |
| 1534 return nullptr; | |
| 1535 | |
| 1536 auto IsOperand = [](Inst *Instr, Operand *Opr) -> bool { | |
| 1537 for (SizeT i = 0; i < Instr->getSrcSize(); ++i) { | |
| 1538 if (Instr->getSrc(i) == Opr) | |
| 1539 return true; | |
| 1540 } | |
| 1541 return false; | |
| 1542 }; | |
| 1543 Inst *FirstOperandDef = nullptr; | |
| 1544 for (auto &Inst : getInsts()) { | |
| 1545 if (IsOperand(TopLevelBoolOp, Inst.getDest())) { | |
| 1546 FirstOperandDef = &Inst; | |
| 1547 break; | |
| 1548 } | |
| 1549 } | |
| 1550 | |
| 1551 if (FirstOperandDef == nullptr) { | |
| 1552 return nullptr; | |
| 1553 } | |
| 1554 | |
| 1555 // Check for side effects | |
| 1556 auto It = Ice::instToIterator(FirstOperandDef); | |
| 1557 while (It != getInsts().end()) { | |
| 1558 if (It->isDeleted()) { | |
| 1559 It++; | |
| 1560 continue; | |
| 1561 } | |
| 1562 if (llvm::isa<InstBr>(It) || llvm::isa<InstRet>(It)) { | |
| 1563 break; | |
| 1564 } | |
| 1565 auto *Dest = It->getDest(); | |
| 1566 if (It->getDest() == nullptr || It->hasSideEffects() || | |
| 1567 !Func->getVMetadata()->isSingleBlock(Dest)) { | |
| 1568 // Relying on short cicuit eval here. | |
| 1569 // getVMetadata()->isSingleBlock(Dest) | |
| 1570 // will segfault if It->getDest() == nullptr | |
| 1571 return nullptr; | |
| 1572 } | |
| 1573 It++; | |
| 1574 } | |
| 1575 | |
| 1576 auto *NewNode = Func->makeNode(); | |
| 1577 NewNode->setLoopNestDepth(getLoopNestDepth()); | |
| 1578 It = Ice::instToIterator(FirstOperandDef); | |
| 1579 It++; // Have to split after the def | |
|
Jim Stichnoth
2016/06/27 19:44:41
++It
may be more efficient
manasijm
2016/06/27 22:00:40
Done.
| |
| 1580 | |
| 1581 NewNode->getInsts().splice(NewNode->getInsts().begin(), getInsts(), It, | |
| 1582 getInsts().end()); | |
| 1583 | |
| 1584 | |
| 1585 NewNode->setName(getName().append("_2")); | |
|
Jim Stichnoth
2016/06/27 19:44:41
Wrap all the name management inside:
if (BuildDe
manasijm
2016/06/27 22:00:40
Done.
| |
| 1586 setName(getName().append("_1")); | |
| 1587 | |
| 1588 // Point edges properly | |
| 1589 NewNode->addInEdge(this); | |
| 1590 for (auto *Out : getOutEdges()) { | |
| 1591 NewNode->addOutEdge(Out); | |
| 1592 Out->addInEdge(NewNode); | |
| 1593 } | |
| 1594 removeAllOutEdges(); | |
| 1595 addOutEdge(NewNode); | |
| 1596 | |
| 1597 //Manage Phi instructions of successors | |
| 1598 for (auto *Succ : NewNode->getOutEdges()) { | |
| 1599 for (auto &Inst : Succ->getPhis()) { | |
| 1600 auto *Phi = llvm::dyn_cast<InstPhi>(&Inst); | |
|
Jim Stichnoth
2016/06/27 19:44:41
llvm::cast<>
manasijm
2016/06/27 22:00:40
Done.
| |
| 1601 for (SizeT i = 0; i < Phi->getSrcSize(); ++i) { | |
| 1602 if (Phi->getLabel(i) == this) { | |
| 1603 Phi->addArgument(Phi->getSrc(i), NewNode); | |
| 1604 } | |
| 1605 } | |
| 1606 } | |
| 1607 } | |
| 1608 | |
| 1609 //Create new Br instruction | |
| 1610 InstBr *NewInst = nullptr; | |
| 1611 if (FoundOr) { | |
| 1612 addOutEdge(JumpOnTrue); | |
| 1613 JumpOnFalse->removeInEdge(this); | |
| 1614 NewInst = | |
| 1615 InstBr::create(Func, FirstOperandDef->getDest(), JumpOnTrue, NewNode); | |
| 1616 } else if (FoundAnd) { | |
| 1617 addOutEdge(JumpOnFalse); | |
| 1618 JumpOnTrue->removeInEdge(this); | |
| 1619 NewInst = | |
| 1620 InstBr::create(Func, FirstOperandDef->getDest(), NewNode, JumpOnFalse); | |
| 1621 } | |
| 1622 appendInst(NewInst); | |
|
Jim Stichnoth
2016/06/27 19:44:41
Naively, it looks like there could be a path where
manasijm
2016/06/27 22:00:40
Done.
| |
| 1623 | |
| 1624 Operand *UnusedOperand = nullptr; | |
| 1625 assert(TopLevelBoolOp->getSrcSize() == 2); | |
| 1626 if (TopLevelBoolOp->getSrc(0) == FirstOperandDef->getDest()) | |
| 1627 UnusedOperand = TopLevelBoolOp->getSrc(1); | |
| 1628 else if (TopLevelBoolOp->getSrc(1) == FirstOperandDef->getDest()) | |
| 1629 UnusedOperand = TopLevelBoolOp->getSrc(0); | |
| 1630 assert(UnusedOperand); | |
| 1631 | |
| 1632 Br->replaceSource(0, UnusedOperand); // Index 0 has the condition of the Br | |
| 1633 | |
| 1634 TopLevelBoolOp->setDeleted(); | |
| 1635 return NewNode; | |
| 1636 } | |
| 1637 | |
| 1475 } // end of namespace Ice | 1638 } // end of namespace Ice |
| OLD | NEW |