mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
181 lines
4.8 KiB
C++
181 lines
4.8 KiB
C++
//===--- InstructionUtils.cpp - Utilities for SIL instructions ------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "sil-inst-utils"
|
|
#include "swift/SIL/InstructionUtils.h"
|
|
#include "swift/SIL/SILArgument.h"
|
|
#include "swift/SIL/SILBasicBlock.h"
|
|
#include "swift/SIL/Projection.h"
|
|
|
|
using namespace swift;
|
|
|
|
/// Strip off casts/indexing insts/address projections from V until there is
|
|
/// nothing left to strip.
|
|
/// FIXME: Why don't we strip projections after stripping indexes?
|
|
SILValue swift::getUnderlyingObject(SILValue V) {
|
|
while (true) {
|
|
SILValue V2 = stripIndexingInsts(stripAddressProjections(stripCasts(V)));
|
|
if (V2 == V)
|
|
return V2;
|
|
V = V2;
|
|
}
|
|
}
|
|
|
|
static bool isRCIdentityPreservingCast(ValueKind Kind) {
|
|
switch (Kind) {
|
|
case ValueKind::UpcastInst:
|
|
case ValueKind::UncheckedRefCastInst:
|
|
case ValueKind::UncheckedRefCastAddrInst:
|
|
case ValueKind::UnconditionalCheckedCastInst:
|
|
case ValueKind::RefToBridgeObjectInst:
|
|
case ValueKind::BridgeObjectToRefInst:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Return the underlying SILValue after stripping off identity SILArguments if
|
|
/// we belong to a BB with one predecessor.
|
|
SILValue swift::stripSinglePredecessorArgs(SILValue V) {
|
|
while (true) {
|
|
auto *A = dyn_cast<SILArgument>(V);
|
|
if (!A)
|
|
return V;
|
|
|
|
SILBasicBlock *BB = A->getParent();
|
|
|
|
// First try and grab the single predecessor of our parent BB. If we don't
|
|
// have one, bail.
|
|
SILBasicBlock *Pred = BB->getSinglePredecessor();
|
|
if (!Pred)
|
|
return V;
|
|
|
|
// Then grab the terminator of Pred...
|
|
TermInst *PredTI = Pred->getTerminator();
|
|
|
|
// And attempt to find our matching argument.
|
|
//
|
|
// *NOTE* We can only strip things here if we know that there is no semantic
|
|
// change in terms of upcasts/downcasts/enum extraction since this is used
|
|
// by other routines here. This means that we can only look through
|
|
// cond_br/br.
|
|
//
|
|
// For instance, routines that use stripUpcasts() do not want to strip off a
|
|
// downcast that results from checked_cast_br.
|
|
if (auto *BI = dyn_cast<BranchInst>(PredTI)) {
|
|
V = BI->getArg(A->getIndex());
|
|
continue;
|
|
}
|
|
|
|
if (auto *CBI = dyn_cast<CondBranchInst>(PredTI)) {
|
|
if (SILValue Arg = CBI->getArgForDestBB(BB, A)) {
|
|
V = Arg;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return V;
|
|
}
|
|
}
|
|
|
|
SILValue swift::stripCasts(SILValue V) {
|
|
while (true) {
|
|
V = stripSinglePredecessorArgs(V);
|
|
|
|
auto K = V->getKind();
|
|
if (isRCIdentityPreservingCast(K)
|
|
|| K == ValueKind::UncheckedTrivialBitCastInst
|
|
|| K == ValueKind::MarkDependenceInst) {
|
|
V = cast<SILInstruction>(V)->getOperand(0);
|
|
continue;
|
|
}
|
|
|
|
return V;
|
|
}
|
|
}
|
|
|
|
SILValue swift::stripUpCasts(SILValue V) {
|
|
assert(V->getType().isClassOrClassMetatype() &&
|
|
"Expected class or class metatype!");
|
|
|
|
V = stripSinglePredecessorArgs(V);
|
|
|
|
while (isa<UpcastInst>(V))
|
|
V = stripSinglePredecessorArgs(cast<UpcastInst>(V)->getOperand());
|
|
|
|
return V;
|
|
}
|
|
|
|
SILValue swift::stripClassCasts(SILValue V) {
|
|
while (true) {
|
|
if (auto *UI = dyn_cast<UpcastInst>(V)) {
|
|
V = UI->getOperand();
|
|
continue;
|
|
}
|
|
|
|
if (auto *UCCI = dyn_cast<UnconditionalCheckedCastInst>(V)) {
|
|
V = UCCI->getOperand();
|
|
continue;
|
|
}
|
|
|
|
return V;
|
|
}
|
|
}
|
|
|
|
SILValue swift::stripAddressProjections(SILValue V) {
|
|
while (true) {
|
|
V = stripSinglePredecessorArgs(V);
|
|
if (!Projection::isAddressProjection(V))
|
|
return V;
|
|
V = cast<SILInstruction>(V)->getOperand(0);
|
|
}
|
|
}
|
|
|
|
SILValue swift::stripUnaryAddressProjections(SILValue V) {
|
|
while (true) {
|
|
V = stripSinglePredecessorArgs(V);
|
|
if (!Projection::isAddressProjection(V))
|
|
return V;
|
|
auto *Inst = cast<SILInstruction>(V);
|
|
if (Inst->getNumOperands() > 1)
|
|
return V;
|
|
V = Inst->getOperand(0);
|
|
}
|
|
}
|
|
|
|
SILValue swift::stripValueProjections(SILValue V) {
|
|
while (true) {
|
|
V = stripSinglePredecessorArgs(V);
|
|
if (!Projection::isObjectProjection(V))
|
|
return V;
|
|
V = cast<SILInstruction>(V)->getOperand(0);
|
|
}
|
|
}
|
|
|
|
SILValue swift::stripIndexingInsts(SILValue V) {
|
|
while (true) {
|
|
if (!isa<IndexingInst>(V))
|
|
return V;
|
|
V = cast<IndexingInst>(V)->getBase();
|
|
}
|
|
}
|
|
|
|
SILValue swift::stripExpectIntrinsic(SILValue V) {
|
|
auto *BI = dyn_cast<BuiltinInst>(V);
|
|
if (!BI)
|
|
return V;
|
|
if (BI->getIntrinsicInfo().ID != llvm::Intrinsic::expect)
|
|
return V;
|
|
return BI->getArguments()[0];
|
|
}
|