Skip to content

Commit 0786344

Browse files
committed
Introduce ForwardingOperation wrapper type
APIs on ForwardingInstruction should be written as static taking in a SILInstruction as a parameter making it awkward. Introduce a ForwardingOperation wrapper type and move the apis from the old "mixin" class to the wrapper type. Add new api getForwardedOperands()
1 parent c2312a4 commit 0786344

File tree

10 files changed

+212
-159
lines changed

10 files changed

+212
-159
lines changed

include/swift/SIL/InstWrappers.h

+84
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,90 @@ class SelectEnumOperation {
237237
}
238238
};
239239

240+
class ForwardingOperation {
241+
SILInstruction *forwardingInst = nullptr;
242+
243+
public:
244+
explicit ForwardingOperation(SILInstruction *inst);
245+
246+
operator bool() const { return bool(forwardingInst); }
247+
const SILInstruction *operator->() const { return forwardingInst; }
248+
SILInstruction *operator->() { return forwardingInst; }
249+
const SILInstruction *operator*() const { return forwardingInst; }
250+
SILInstruction *operator*() { return forwardingInst; }
251+
252+
ValueOwnershipKind getForwardingOwnershipKind();
253+
bool preservesOwnership();
254+
255+
// FIXME: Find a better name. Even unary instructions like struct_extract
256+
// forward "all" operands.
257+
bool canForwardAllOperands() const {
258+
switch (forwardingInst->getKind()) {
259+
case SILInstructionKind::StructInst:
260+
case SILInstructionKind::TupleInst:
261+
case SILInstructionKind::LinearFunctionInst:
262+
case SILInstructionKind::DifferentiableFunctionInst:
263+
return true;
264+
default:
265+
return false;
266+
}
267+
}
268+
269+
// FIXME: Find a better name. Even instructions that forward all operands can
270+
// forward the first operand.
271+
bool canForwardFirstOperandOnly() const {
272+
return !canForwardAllOperands() && forwardingInst->getNumRealOperands() > 0;
273+
}
274+
275+
ArrayRef<Operand> getForwardedOperands() const {
276+
if (canForwardAllOperands()) {
277+
return forwardingInst->getAllOperands();
278+
}
279+
if (canForwardFirstOperandOnly()) {
280+
return forwardingInst->getOperandRef(0);
281+
}
282+
return {};
283+
}
284+
285+
MutableArrayRef<Operand> getForwardedOperands() {
286+
if (canForwardAllOperands()) {
287+
return forwardingInst->getAllOperands();
288+
}
289+
if (canForwardFirstOperandOnly()) {
290+
return forwardingInst->getOperandRef(0);
291+
}
292+
return {};
293+
}
294+
295+
bool canForwardOwnedCompatibleValuesOnly() {
296+
switch (forwardingInst->getKind()) {
297+
case SILInstructionKind::MarkUninitializedInst:
298+
return true;
299+
default:
300+
return false;
301+
}
302+
}
303+
304+
bool canForwardGuaranteedCompatibleValuesOnly() {
305+
switch (forwardingInst->getKind()) {
306+
case SILInstructionKind::TupleExtractInst:
307+
case SILInstructionKind::StructExtractInst:
308+
case SILInstructionKind::DifferentiableFunctionExtractInst:
309+
case SILInstructionKind::LinearFunctionExtractInst:
310+
return true;
311+
default:
312+
return false;
313+
}
314+
}
315+
316+
/// Return true if the forwarded value has the same representation. If true,
317+
/// then the result can be mapped to the same storage without a move or copy.
318+
bool hasSameRepresentation() const;
319+
320+
/// Return true if the forwarded value is address-only either before or after
321+
/// forwarding.
322+
bool isAddressOnly() const;
323+
};
240324
} // end namespace swift
241325

242326
#endif

include/swift/SIL/SILInstruction.h

-52
Original file line numberDiff line numberDiff line change
@@ -1239,46 +1239,6 @@ class ForwardingInstruction {
12391239
ownershipKind = newKind;
12401240
}
12411241

1242-
static bool canForwardAllOperands(SILInstruction *inst) {
1243-
switch (inst->getKind()) {
1244-
case SILInstructionKind::StructInst:
1245-
case SILInstructionKind::TupleInst:
1246-
case SILInstructionKind::LinearFunctionInst:
1247-
case SILInstructionKind::DifferentiableFunctionInst:
1248-
return true;
1249-
default:
1250-
return false;
1251-
}
1252-
}
1253-
1254-
static bool canForwardFirstOperandOnly(SILInstruction *inst) {
1255-
if (!ForwardingInstruction::isa(inst)) {
1256-
return false;
1257-
}
1258-
return !canForwardAllOperands(inst);
1259-
}
1260-
1261-
static bool canForwardOwnedCompatibleValuesOnly(SILInstruction *inst) {
1262-
switch (inst->getKind()) {
1263-
case SILInstructionKind::MarkUninitializedInst:
1264-
return true;
1265-
default:
1266-
return false;
1267-
}
1268-
}
1269-
1270-
static bool canForwardGuaranteedCompatibleValuesOnly(SILInstruction *inst) {
1271-
switch (inst->getKind()) {
1272-
case SILInstructionKind::TupleExtractInst:
1273-
case SILInstructionKind::StructExtractInst:
1274-
case SILInstructionKind::DifferentiableFunctionExtractInst:
1275-
case SILInstructionKind::LinearFunctionExtractInst:
1276-
return true;
1277-
default:
1278-
return false;
1279-
}
1280-
}
1281-
12821242
/// Defined inline below due to forward declaration issues.
12831243
static ForwardingInstruction *get(SILInstruction *inst);
12841244
static bool isa(SILInstructionKind kind);
@@ -1288,18 +1248,6 @@ class ForwardingInstruction {
12881248
return isa(i);
12891249
return false;
12901250
}
1291-
1292-
/// Return true if the forwarded value has the same representation. If true,
1293-
/// then the result can be mapped to the same storage without a move or copy.
1294-
///
1295-
/// \p inst is an ForwardingInstruction
1296-
static bool hasSameRepresentation(SILInstruction *inst);
1297-
1298-
/// Return true if the forwarded value is address-only either before or after
1299-
/// forwarding.
1300-
///
1301-
/// \p inst is an ForwardingInstruction
1302-
static bool isAddressOnly(SILInstruction *inst);
13031251
};
13041252

13051253
/// A single value inst that forwards a static ownership from its first operand.

lib/SIL/IR/SILInstructions.cpp

-41
Original file line numberDiff line numberDiff line change
@@ -3141,47 +3141,6 @@ ReturnInst::ReturnInst(SILFunction &func, SILDebugLocation debugLoc,
31413141
"result info?!");
31423142
}
31433143

3144-
bool ForwardingInstruction::hasSameRepresentation(SILInstruction *inst) {
3145-
switch (inst->getKind()) {
3146-
// Explicitly list instructions which definitely involve a representation
3147-
// change.
3148-
case SILInstructionKind::SwitchEnumInst:
3149-
default:
3150-
// Conservatively assume that a conversion changes representation.
3151-
// Operations can be added as needed to participate in SIL opaque values.
3152-
assert(ForwardingInstruction::isa(inst));
3153-
return false;
3154-
3155-
case SILInstructionKind::ConvertFunctionInst:
3156-
case SILInstructionKind::DestructureTupleInst:
3157-
case SILInstructionKind::DestructureStructInst:
3158-
case SILInstructionKind::InitExistentialRefInst:
3159-
case SILInstructionKind::ObjectInst:
3160-
case SILInstructionKind::OpenExistentialBoxValueInst:
3161-
case SILInstructionKind::OpenExistentialRefInst:
3162-
case SILInstructionKind::OpenExistentialValueInst:
3163-
case SILInstructionKind::MarkMustCheckInst:
3164-
case SILInstructionKind::MarkUninitializedInst:
3165-
case SILInstructionKind::SelectEnumInst:
3166-
case SILInstructionKind::StructExtractInst:
3167-
case SILInstructionKind::TupleExtractInst:
3168-
return true;
3169-
}
3170-
}
3171-
3172-
bool ForwardingInstruction::isAddressOnly(SILInstruction *inst) {
3173-
if (canForwardAllOperands(inst)) {
3174-
// All ForwardingInstructions that forward all operands are currently a
3175-
// single value instruction.
3176-
auto *aggregate = cast<OwnershipForwardingSingleValueInstruction>(inst);
3177-
// If any of the operands are address-only, then the aggregate must be.
3178-
return aggregate->getType().isAddressOnly(*inst->getFunction());
3179-
}
3180-
// All other forwarding instructions must forward their first operand.
3181-
assert(canForwardFirstOperandOnly(inst));
3182-
return inst->getOperand(0)->getType().isAddressOnly(*inst->getFunction());
3183-
}
3184-
31853144
// This may be called in an invalid SIL state. SILCombine creates new
31863145
// terminators in non-terminator position and defers deleting the original
31873146
// terminator until after all modification.

lib/SIL/Utils/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ target_sources(swiftSIL PRIVATE
88
FieldSensitivePrunedLiveness.cpp
99
GenericSpecializationMangler.cpp
1010
InstructionUtils.cpp
11+
InstWrappers.cpp
1112
LoopInfo.cpp
1213
MemAccessUtils.cpp
1314
MemoryLocations.cpp
@@ -22,4 +23,5 @@ target_sources(swiftSIL PRIVATE
2223
SILBridging.cpp
2324
SILInstructionWorklist.cpp
2425
SILRemarkStreamer.cpp
25-
ValueUtils.cpp)
26+
ValueUtils.cpp
27+
)

lib/SIL/Utils/InstWrappers.cpp

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//===--- InstWrappers.cpp ------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/SIL/InstWrappers.h"
14+
#include "swift/SIL/SILFunction.h"
15+
16+
using namespace swift;
17+
18+
ForwardingOperation::ForwardingOperation(SILInstruction *inst) {
19+
if (ForwardingInstruction::isa(inst)) {
20+
this->forwardingInst = inst;
21+
return;
22+
}
23+
}
24+
25+
ValueOwnershipKind ForwardingOperation::getForwardingOwnershipKind() {
26+
return ForwardingInstruction::get(forwardingInst)
27+
->getForwardingOwnershipKind();
28+
}
29+
30+
bool ForwardingOperation::preservesOwnership() {
31+
return ForwardingInstruction::get(forwardingInst)->preservesOwnership();
32+
}
33+
34+
bool ForwardingOperation::hasSameRepresentation() const {
35+
switch (forwardingInst->getKind()) {
36+
// Explicitly list instructions which definitely involve a representation
37+
// change.
38+
case SILInstructionKind::SwitchEnumInst:
39+
default:
40+
// Conservatively assume that a conversion changes representation.
41+
// Operations can be added as needed to participate in SIL opaque values.
42+
return false;
43+
44+
case SILInstructionKind::ConvertFunctionInst:
45+
case SILInstructionKind::DestructureTupleInst:
46+
case SILInstructionKind::DestructureStructInst:
47+
case SILInstructionKind::InitExistentialRefInst:
48+
case SILInstructionKind::ObjectInst:
49+
case SILInstructionKind::OpenExistentialBoxValueInst:
50+
case SILInstructionKind::OpenExistentialRefInst:
51+
case SILInstructionKind::OpenExistentialValueInst:
52+
case SILInstructionKind::MarkMustCheckInst:
53+
case SILInstructionKind::MarkUninitializedInst:
54+
case SILInstructionKind::SelectEnumInst:
55+
case SILInstructionKind::StructExtractInst:
56+
case SILInstructionKind::TupleExtractInst:
57+
return true;
58+
}
59+
}
60+
61+
bool ForwardingOperation::isAddressOnly() const {
62+
if (canForwardAllOperands()) {
63+
// All ForwardingInstructions that forward all operands are currently a
64+
// single value instruction.
65+
auto *aggregate =
66+
cast<OwnershipForwardingSingleValueInstruction>(forwardingInst);
67+
// If any of the operands are address-only, then the aggregate must be.
68+
return aggregate->getType().isAddressOnly(*forwardingInst->getFunction());
69+
}
70+
return forwardingInst->getOperand(0)->getType().isAddressOnly(
71+
*forwardingInst->getFunction());
72+
}

lib/SIL/Utils/MemAccessUtils.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -900,13 +900,15 @@ SILValue swift::findOwnershipReferenceAggregate(SILValue ref) {
900900
return root;
901901

902902
if (auto *inst = root->getDefiningInstruction()) {
903-
if (ForwardingInstruction::canForwardFirstOperandOnly(inst)) {
904-
// The `enum` instruction can have no operand.
905-
if (inst->getNumOperands() == 0)
906-
return root;
903+
if (auto fwdOp = ForwardingOperation(inst)) {
904+
if (fwdOp.canForwardFirstOperandOnly()) {
905+
// The `enum` instruction can have no operand.
906+
if (inst->getNumOperands() == 0)
907+
return root;
907908

908-
root = inst->getOperand(0);
909-
continue;
909+
root = inst->getOperand(0);
910+
continue;
911+
}
910912
}
911913
}
912914
if (auto *termResult = SILArgument::isTerminatorResult(root)) {

0 commit comments

Comments
 (0)