1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
//===--- OwnershipConversionElimination.cpp -------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "SemanticARC/SemanticARCOpts.h"
#include "SemanticARCOptVisitor.h"
#include "swift/SIL/LinearLifetimeChecker.h"
using namespace swift;
using namespace semanticarc;
//===----------------------------------------------------------------------===//
// Top Level Entrypoint
//===----------------------------------------------------------------------===//
bool SemanticARCOptVisitor::visitUncheckedOwnershipConversionInst(
UncheckedOwnershipConversionInst *uoci) {
// Return false if we are supposed to only be running guaranteed opts.
if (ctx.onlyMandatoryOpts)
return false;
// Then check if we are running tests and shouldn't perform this optimization
// since we are testing something else.
if (!ctx.shouldPerform(ARCTransformKind::OwnershipConversionElimPeephole))
return false;
// Otherwise, shrink our state space so that we only consider conversions from
// owned or guaranteed to unowned. These are always legal and it is sometimes
// convenient to insert them to avoid forwarding issues when RAUWing
// values. So we eliminate them here.
if (uoci->getConversionOwnershipKind() != OwnershipKind::Unowned)
return false;
auto op = uoci->getOperand();
auto opKind = op->getOwnershipKind();
if (opKind != OwnershipKind::Owned && opKind != OwnershipKind::Guaranteed)
return false;
// Ok, we can perform our optimization. First go through all of the uses of
// uoci and see if they can accept our operand without any changes and that
// they do not consume values.
SmallVector<Operand *, 8> newUses;
for (auto *use : uoci->getUses()) {
if (use->isLifetimeEnding() || !use->canAcceptKind(opKind))
return false;
newUses.push_back(use);
}
// Ok, now we need to perform our lifetime check.
SmallVector<Operand *, 8> consumingUses(op->getConsumingUses());
LinearLifetimeChecker checker(&ctx.getDeadEndBlocks());
if (!checker.validateLifetime(op, consumingUses, newUses))
return false;
// Otherwise, we can perform our rauw.
eraseAndRAUWSingleValueInstruction(uoci, op);
return true;
}
|