|
19 | 19 | #include "swift/Demangling/Demangle.h"
|
20 | 20 | #include "../../IRGen/IRGenModule.h"
|
21 | 21 | #include "swift/SIL/ApplySite.h"
|
| 22 | +#include "swift/SIL/SILCloner.h" |
22 | 23 | #include "swift/SIL/SILFunction.h"
|
23 | 24 | #include "swift/SIL/SILModule.h"
|
24 | 25 | #include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
|
25 | 26 | #include "swift/SILOptimizer/Analysis/FunctionOrder.h"
|
| 27 | +#include "swift/SILOptimizer/OptimizerBridging.h" |
26 | 28 | #include "swift/SILOptimizer/PassManager/PrettyStackTrace.h"
|
27 | 29 | #include "swift/SILOptimizer/PassManager/Transforms.h"
|
| 30 | +#include "swift/SILOptimizer/Utils/Devirtualize.h" |
| 31 | +#include "swift/SILOptimizer/Utils/ConstantFolding.h" |
28 | 32 | #include "swift/SILOptimizer/Utils/OptimizerStatsUtils.h"
|
29 | 33 | #include "swift/SILOptimizer/Utils/SILInliner.h"
|
30 | 34 | #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
|
| 35 | +#include "swift/SILOptimizer/Utils/SpecializationMangler.h" |
| 36 | +#include "swift/SILOptimizer/Utils/StackNesting.h" |
31 | 37 | #include "llvm/ADT/DenseMap.h"
|
32 | 38 | #include "llvm/ADT/Statistic.h"
|
33 | 39 | #include "llvm/ADT/StringSwitch.h"
|
@@ -1423,3 +1429,314 @@ SwiftPassInvocation::~SwiftPassInvocation() {
|
1423 | 1429 | irgen = nullptr;
|
1424 | 1430 | }
|
1425 | 1431 | }
|
| 1432 | + |
| 1433 | +//===----------------------------------------------------------------------===// |
| 1434 | +// OptimizerBridging |
| 1435 | +//===----------------------------------------------------------------------===// |
| 1436 | + |
| 1437 | +llvm::cl::list<std::string> |
| 1438 | + SimplifyInstructionTest("simplify-instruction", llvm::cl::CommaSeparated, |
| 1439 | + llvm::cl::desc("Simplify instruction of specified kind(s)")); |
| 1440 | + |
| 1441 | +#ifdef PURE_BRIDGING_MODE |
| 1442 | +// In PURE_BRIDGING_MODE, briding functions are not inlined and therefore inluded in the cpp file. |
| 1443 | +#include "swift/SILOptimizer/OptimizerBridgingImpl.h" |
| 1444 | +#endif |
| 1445 | + |
| 1446 | +void BridgedChangeNotificationHandler::notifyChanges(Kind changeKind) const { |
| 1447 | + switch (changeKind) { |
| 1448 | + case Kind::instructionsChanged: |
| 1449 | + invocation->notifyChanges(SILAnalysis::InvalidationKind::Instructions); |
| 1450 | + break; |
| 1451 | + case Kind::callsChanged: |
| 1452 | + invocation->notifyChanges(SILAnalysis::InvalidationKind::CallsAndInstructions); |
| 1453 | + break; |
| 1454 | + case Kind::branchesChanged: |
| 1455 | + invocation->notifyChanges(SILAnalysis::InvalidationKind::BranchesAndInstructions); |
| 1456 | + break; |
| 1457 | + case Kind::effectsChanged: |
| 1458 | + invocation->notifyChanges(SILAnalysis::InvalidationKind::Effects); |
| 1459 | + break; |
| 1460 | + } |
| 1461 | +} |
| 1462 | + |
| 1463 | +BridgedOwnedString BridgedPassContext::getModuleDescription() const { |
| 1464 | + std::string str; |
| 1465 | + llvm::raw_string_ostream os(str); |
| 1466 | + invocation->getPassManager()->getModule()->print(os); |
| 1467 | + str.pop_back(); // Remove trailing newline. |
| 1468 | + return str; |
| 1469 | +} |
| 1470 | + |
| 1471 | +bool BridgedPassContext::tryOptimizeApplyOfPartialApply(BridgedInstruction closure) const { |
| 1472 | + auto *pa = closure.getAs<PartialApplyInst>(); |
| 1473 | + SILBuilder builder(pa); |
| 1474 | + return ::tryOptimizeApplyOfPartialApply(pa, builder.getBuilderContext(), InstModCallbacks()); |
| 1475 | +} |
| 1476 | + |
| 1477 | +bool BridgedPassContext::tryDeleteDeadClosure(BridgedInstruction closure, bool needKeepArgsAlive) const { |
| 1478 | + return ::tryDeleteDeadClosure(closure.getAs<SingleValueInstruction>(), InstModCallbacks(), needKeepArgsAlive); |
| 1479 | +} |
| 1480 | + |
| 1481 | +BridgedPassContext::DevirtResult BridgedPassContext::tryDevirtualizeApply(BridgedInstruction apply, |
| 1482 | + bool isMandatory) const { |
| 1483 | + auto cha = invocation->getPassManager()->getAnalysis<ClassHierarchyAnalysis>(); |
| 1484 | + auto result = ::tryDevirtualizeApply(ApplySite(apply.get()), cha, nullptr, isMandatory); |
| 1485 | + if (result.first) { |
| 1486 | + OptionalBridgedInstruction newApply(result.first.getInstruction()->asSILNode()); |
| 1487 | + return {newApply, result.second}; |
| 1488 | + } |
| 1489 | + return {{nullptr}, false}; |
| 1490 | +} |
| 1491 | + |
| 1492 | +OptionalBridgedValue BridgedPassContext::constantFoldBuiltin(BridgedInstruction builtin) const { |
| 1493 | + auto bi = builtin.getAs<BuiltinInst>(); |
| 1494 | + llvm::Optional<bool> resultsInError; |
| 1495 | + return {::constantFoldBuiltin(bi, resultsInError)}; |
| 1496 | +} |
| 1497 | + |
| 1498 | +void BridgedPassContext::inlineFunction(BridgedInstruction apply, bool mandatoryInline) const { |
| 1499 | + SILOptFunctionBuilder funcBuilder(*invocation->getTransform()); |
| 1500 | + InstructionDeleter deleter; |
| 1501 | + SILInliner::inlineFullApply(FullApplySite(apply.get()), |
| 1502 | + mandatoryInline ? SILInliner::InlineKind::MandatoryInline |
| 1503 | + : SILInliner::InlineKind::PerformanceInline, |
| 1504 | + funcBuilder, |
| 1505 | + deleter); |
| 1506 | +} |
| 1507 | + |
| 1508 | +static const irgen::TypeInfo &getTypeInfoOfBuiltin(swift::SILType type, irgen::IRGenModule &IGM) { |
| 1509 | + SILType lowered = IGM.getLoweredType(swift::Lowering::AbstractionPattern::getOpaque(), type.getASTType()); |
| 1510 | + return IGM.getTypeInfo(lowered); |
| 1511 | +} |
| 1512 | + |
| 1513 | +static SwiftInt integerValueFromConstant(llvm::Constant *c, SwiftInt add = 0) { |
| 1514 | + auto *intConst = dyn_cast_or_null<llvm::ConstantInt>(c); |
| 1515 | + if (!intConst) |
| 1516 | + return -1; |
| 1517 | + APInt value = intConst->getValue(); |
| 1518 | + return value.getLimitedValue() + add; |
| 1519 | +} |
| 1520 | + |
| 1521 | +SwiftInt BridgedPassContext::getStaticSize(BridgedType type) const { |
| 1522 | + irgen::IRGenModule *IGM = invocation->getIRGenModule(); |
| 1523 | + if (!IGM) |
| 1524 | + return -1; |
| 1525 | + auto &ti = getTypeInfoOfBuiltin(type.get(), *IGM); |
| 1526 | + llvm::Constant *c = ti.getStaticSize(*IGM); |
| 1527 | + return integerValueFromConstant(c); |
| 1528 | +} |
| 1529 | + |
| 1530 | +SwiftInt BridgedPassContext::getStaticAlignment(BridgedType type) const { |
| 1531 | + irgen::IRGenModule *IGM = invocation->getIRGenModule(); |
| 1532 | + if (!IGM) |
| 1533 | + return -1; |
| 1534 | + auto &ti = getTypeInfoOfBuiltin(type.get(), *IGM); |
| 1535 | + llvm::Constant *c = ti.getStaticAlignmentMask(*IGM); |
| 1536 | + return integerValueFromConstant(c, 1); |
| 1537 | +} |
| 1538 | + |
| 1539 | +SwiftInt BridgedPassContext::getStaticStride(BridgedType type) const { |
| 1540 | + irgen::IRGenModule *IGM = invocation->getIRGenModule(); |
| 1541 | + if (!IGM) |
| 1542 | + return -1; |
| 1543 | + auto &ti = getTypeInfoOfBuiltin(type.get(), *IGM); |
| 1544 | + llvm::Constant *c = ti.getStaticStride(*IGM); |
| 1545 | + return integerValueFromConstant(c); |
| 1546 | +} |
| 1547 | + |
| 1548 | +swift::SILVTable * BridgedPassContext::specializeVTableForType(BridgedType type, BridgedFunction function) const { |
| 1549 | + return ::specializeVTableForType(type.get(), function.getFunction()->getModule(), invocation->getTransform()); |
| 1550 | +} |
| 1551 | + |
| 1552 | +bool BridgedPassContext::specializeClassMethodInst(BridgedInstruction cm) const { |
| 1553 | + return ::specializeClassMethodInst(cm.getAs<ClassMethodInst>()); |
| 1554 | +} |
| 1555 | + |
| 1556 | +bool BridgedPassContext::specializeAppliesInFunction(BridgedFunction function, bool isMandatory) const { |
| 1557 | + return ::specializeAppliesInFunction(*function.getFunction(), invocation->getTransform(), isMandatory); |
| 1558 | +} |
| 1559 | + |
| 1560 | +namespace { |
| 1561 | +class GlobalVariableMangler : public Mangle::ASTMangler { |
| 1562 | +public: |
| 1563 | + std::string mangleOutlinedVariable(SILFunction *F, int &uniqueIdx) { |
| 1564 | + std::string GlobName; |
| 1565 | + do { |
| 1566 | + beginManglingWithoutPrefix(); |
| 1567 | + appendOperator(F->getName()); |
| 1568 | + appendOperator("Tv", Index(uniqueIdx++)); |
| 1569 | + GlobName = finalize(); |
| 1570 | + } while (F->getModule().lookUpGlobalVariable(GlobName)); |
| 1571 | + |
| 1572 | + return GlobName; |
| 1573 | + } |
| 1574 | +}; |
| 1575 | +} // namespace |
| 1576 | + |
| 1577 | +BridgedOwnedString BridgedPassContext::mangleOutlinedVariable(BridgedFunction function) const { |
| 1578 | + int idx = 0; |
| 1579 | + SILFunction *f = function.getFunction(); |
| 1580 | + SILModule &mod = f->getModule(); |
| 1581 | + while (true) { |
| 1582 | + GlobalVariableMangler mangler; |
| 1583 | + std::string name = mangler.mangleOutlinedVariable(f, idx); |
| 1584 | + if (!mod.lookUpGlobalVariable(name)) |
| 1585 | + return name; |
| 1586 | + idx++; |
| 1587 | + } |
| 1588 | +} |
| 1589 | + |
| 1590 | +BridgedOwnedString BridgedPassContext::mangleAsyncRemoved(BridgedFunction function) const { |
| 1591 | + SILFunction *F = function.getFunction(); |
| 1592 | + |
| 1593 | + // FIXME: hard assumption on what pass is requesting this. |
| 1594 | + auto P = Demangle::SpecializationPass::AsyncDemotion; |
| 1595 | + |
| 1596 | + Mangle::FunctionSignatureSpecializationMangler Mangler(P, F->isSerialized(), |
| 1597 | + F); |
| 1598 | + Mangler.setRemovedEffect(EffectKind::Async); |
| 1599 | + return Mangler.mangle(); |
| 1600 | +} |
| 1601 | + |
| 1602 | +BridgedGlobalVar BridgedPassContext::createGlobalVariable(BridgedStringRef name, BridgedType type, bool isPrivate) const { |
| 1603 | + return {SILGlobalVariable::create(*invocation->getPassManager()->getModule(), |
| 1604 | + isPrivate ? SILLinkage::Private : SILLinkage::Public, |
| 1605 | + IsNotSerialized, |
| 1606 | + name.get(), type.get())}; |
| 1607 | +} |
| 1608 | + |
| 1609 | +void BridgedPassContext::fixStackNesting(BridgedFunction function) const { |
| 1610 | + switch (StackNesting::fixNesting(function.getFunction())) { |
| 1611 | + case StackNesting::Changes::None: |
| 1612 | + break; |
| 1613 | + case StackNesting::Changes::Instructions: |
| 1614 | + invocation->notifyChanges(SILAnalysis::InvalidationKind::Instructions); |
| 1615 | + break; |
| 1616 | + case StackNesting::Changes::CFG: |
| 1617 | + invocation->notifyChanges(SILAnalysis::InvalidationKind::BranchesAndInstructions); |
| 1618 | + break; |
| 1619 | + } |
| 1620 | + invocation->setNeedFixStackNesting(false); |
| 1621 | +} |
| 1622 | + |
| 1623 | +OptionalBridgedFunction BridgedPassContext::lookupStdlibFunction(BridgedStringRef name) const { |
| 1624 | + swift::SILModule *mod = invocation->getPassManager()->getModule(); |
| 1625 | + SmallVector<ValueDecl *, 1> results; |
| 1626 | + mod->getASTContext().lookupInSwiftModule(name.get(), results); |
| 1627 | + if (results.size() != 1) |
| 1628 | + return {nullptr}; |
| 1629 | + |
| 1630 | + auto *decl = dyn_cast<FuncDecl>(results.front()); |
| 1631 | + if (!decl) |
| 1632 | + return {nullptr}; |
| 1633 | + |
| 1634 | + SILDeclRef declRef(decl, SILDeclRef::Kind::Func); |
| 1635 | + SILOptFunctionBuilder funcBuilder(*invocation->getTransform()); |
| 1636 | + return {funcBuilder.getOrCreateFunction(SILLocation(decl), declRef, NotForDefinition)}; |
| 1637 | +} |
| 1638 | + |
| 1639 | +bool BridgedPassContext::enableSimplificationFor(BridgedInstruction inst) const { |
| 1640 | + // Fast-path check. |
| 1641 | + if (SimplifyInstructionTest.empty() && SILDisablePass.empty()) |
| 1642 | + return true; |
| 1643 | + |
| 1644 | + StringRef instName = getSILInstructionName(inst.get()->getKind()); |
| 1645 | + |
| 1646 | + if (SILPassManager::isInstructionPassDisabled(instName)) |
| 1647 | + return false; |
| 1648 | + |
| 1649 | + if (SimplifyInstructionTest.empty()) |
| 1650 | + return true; |
| 1651 | + |
| 1652 | + for (const std::string &testName : SimplifyInstructionTest) { |
| 1653 | + if (testName == instName) |
| 1654 | + return true; |
| 1655 | + } |
| 1656 | + return false; |
| 1657 | +} |
| 1658 | + |
| 1659 | +bool FullApplySite_canInline(BridgedInstruction apply) { |
| 1660 | + return swift::SILInliner::canInlineApplySite(swift::FullApplySite(apply.get())); |
| 1661 | +} |
| 1662 | + |
| 1663 | +// TODO: can't be inlined to work around https://github.com/apple/swift/issues/64502 |
| 1664 | +BridgedCalleeAnalysis::CalleeList BridgedCalleeAnalysis::getCallees(BridgedValue callee) const { |
| 1665 | + return ca->getCalleeListOfValue(callee.getSILValue()); |
| 1666 | +} |
| 1667 | + |
| 1668 | +// TODO: can't be inlined to work around https://github.com/apple/swift/issues/64502 |
| 1669 | +BridgedCalleeAnalysis::CalleeList BridgedCalleeAnalysis::getDestructors(BridgedType type, bool isExactType) const { |
| 1670 | + return ca->getDestructors(type.get(), isExactType); |
| 1671 | +} |
| 1672 | + |
| 1673 | +// Need to put ClonerWithFixedLocation into namespace swift to forward reference |
| 1674 | +// it in OptimizerBridging.h. |
| 1675 | +namespace swift { |
| 1676 | + |
| 1677 | +class ClonerWithFixedLocation : public SILCloner<ClonerWithFixedLocation> { |
| 1678 | + friend class SILInstructionVisitor<ClonerWithFixedLocation>; |
| 1679 | + friend class SILCloner<ClonerWithFixedLocation>; |
| 1680 | + |
| 1681 | + SILDebugLocation insertLoc; |
| 1682 | + |
| 1683 | +public: |
| 1684 | + ClonerWithFixedLocation(SILGlobalVariable *gVar) |
| 1685 | + : SILCloner<ClonerWithFixedLocation>(gVar), |
| 1686 | + insertLoc(ArtificialUnreachableLocation(), nullptr) {} |
| 1687 | + |
| 1688 | + ClonerWithFixedLocation(SILInstruction *insertionPoint) |
| 1689 | + : SILCloner<ClonerWithFixedLocation>(*insertionPoint->getFunction()), |
| 1690 | + insertLoc(insertionPoint->getDebugLocation()) { |
| 1691 | + Builder.setInsertionPoint(insertionPoint); |
| 1692 | + } |
| 1693 | + |
| 1694 | + SILValue getClonedValue(SILValue v) { |
| 1695 | + return getMappedValue(v); |
| 1696 | + } |
| 1697 | + |
| 1698 | + void cloneInst(SILInstruction *inst) { |
| 1699 | + visit(inst); |
| 1700 | + } |
| 1701 | + |
| 1702 | +protected: |
| 1703 | + |
| 1704 | + SILLocation remapLocation(SILLocation loc) { |
| 1705 | + return insertLoc.getLocation(); |
| 1706 | + } |
| 1707 | + |
| 1708 | + const SILDebugScope *remapScope(const SILDebugScope *DS) { |
| 1709 | + return insertLoc.getScope(); |
| 1710 | + } |
| 1711 | +}; |
| 1712 | + |
| 1713 | +} // namespace swift |
| 1714 | + |
| 1715 | +BridgedCloner::BridgedCloner(BridgedGlobalVar var, BridgedPassContext context) |
| 1716 | + : cloner(new ClonerWithFixedLocation(var.getGlobal())) { |
| 1717 | + context.invocation->notifyNewCloner(); |
| 1718 | +} |
| 1719 | + |
| 1720 | +BridgedCloner::BridgedCloner(BridgedInstruction inst, BridgedPassContext context) |
| 1721 | + : cloner(new ClonerWithFixedLocation(inst.get())) { |
| 1722 | + context.invocation->notifyNewCloner(); |
| 1723 | +} |
| 1724 | + |
| 1725 | +void BridgedCloner::destroy(BridgedPassContext context) { |
| 1726 | + delete cloner; |
| 1727 | + cloner = nullptr; |
| 1728 | + context.invocation->notifyClonerDestroyed(); |
| 1729 | +} |
| 1730 | + |
| 1731 | +BridgedValue BridgedCloner::getClonedValue(BridgedValue v) { |
| 1732 | + return {cloner->getClonedValue(v.getSILValue())}; |
| 1733 | +} |
| 1734 | + |
| 1735 | +bool BridgedCloner::isValueCloned(BridgedValue v) const { |
| 1736 | + return cloner->isValueCloned(v.getSILValue()); |
| 1737 | +} |
| 1738 | + |
| 1739 | +void BridgedCloner::clone(BridgedInstruction inst) { |
| 1740 | + cloner->cloneInst(inst.get()); |
| 1741 | +} |
| 1742 | + |
0 commit comments