blob: 21319e3505fbf303cba647aa0f8715cc928994f8 [file] [log] [blame]
//===--- 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.onlyGuaranteedOpts)
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());
SmallPtrSet<SILBasicBlock *, 8> visitedBlocks;
LinearLifetimeChecker checker(visitedBlocks, ctx.getDeadEndBlocks());
if (!checker.validateLifetime(op, consumingUses, newUses))
return false;
// Otherwise, we can perform our rauw.
eraseAndRAUWSingleValueInstruction(uoci, op);
return true;
}