Skip to content

Commit d958f3c

Browse files
authored
Merge pull request #42247 from meg-gupta/opaquevaluework
[SIL Opaque Value] Add support for open_existential_box_value in AddressLowering
2 parents 87cfabc + d50005b commit d958f3c

File tree

4 files changed

+112
-21
lines changed

4 files changed

+112
-21
lines changed

include/swift/SIL/SILValue.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class DeadEndBlocks;
4444
class ValueBaseUseIterator;
4545
class ConsumingUseIterator;
4646
class NonConsumingUseIterator;
47+
class TypeDependentUseIterator;
4748
class NonTypeDependentUseIterator;
4849
class SILValue;
4950
class SILModuleConventions;
@@ -376,6 +377,8 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
376377
/// same type as the result of this instruction.
377378
void replaceAllUsesWithUndef();
378379

380+
void replaceAllTypeDependentUsesWith(ValueBase *RHS);
381+
379382
/// Is this value a direct result of the given instruction?
380383
bool isResultOf(SILInstruction *I) const;
381384

@@ -390,6 +393,8 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
390393
using consuming_use_range = iterator_range<consuming_use_iterator>;
391394
using non_consuming_use_iterator = NonConsumingUseIterator;
392395
using non_consuming_use_range = iterator_range<non_consuming_use_iterator>;
396+
using typedependent_use_iterator = TypeDependentUseIterator;
397+
using typedependent_use_range = iterator_range<typedependent_use_iterator>;
393398
using non_typedependent_use_iterator = NonTypeDependentUseIterator;
394399
using non_typedependent_use_range =
395400
iterator_range<non_typedependent_use_iterator>;
@@ -403,6 +408,9 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
403408
inline non_consuming_use_iterator non_consuming_use_begin() const;
404409
inline non_consuming_use_iterator non_consuming_use_end() const;
405410

411+
inline typedependent_use_iterator typedependent_use_begin() const;
412+
inline typedependent_use_iterator typedependent_use_end() const;
413+
406414
inline non_typedependent_use_iterator non_typedependent_use_begin() const;
407415
inline non_typedependent_use_iterator non_typedependent_use_end() const;
408416

@@ -430,6 +438,10 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
430438
/// Returns a range of all non consuming uses
431439
inline non_consuming_use_range getNonConsumingUses() const;
432440

441+
/// Returns a range of uses that are classified as a type dependent
442+
/// operand of the user.
443+
inline typedependent_use_range getTypeDependentUses() const;
444+
433445
/// Returns a range of uses that are not classified as a type dependent
434446
/// operand of the user.
435447
inline non_typedependent_use_range getNonTypeDependentUses() const;
@@ -1104,6 +1116,7 @@ class Operand {
11041116
friend class ValueBaseUseIterator;
11051117
friend class ConsumingUseIterator;
11061118
friend class NonConsumingUseIterator;
1119+
friend class TypeDependentUseIterator;
11071120
friend class NonTypeDependentUseIterator;
11081121
template <unsigned N> friend class FixedOperandList;
11091122
friend class TrailingOperandsList;
@@ -1231,6 +1244,39 @@ ValueBase::non_consuming_use_end() const {
12311244
return ValueBase::non_consuming_use_iterator(nullptr);
12321245
}
12331246

1247+
class TypeDependentUseIterator : public ValueBaseUseIterator {
1248+
public:
1249+
explicit TypeDependentUseIterator(Operand *cur) : ValueBaseUseIterator(cur) {}
1250+
TypeDependentUseIterator &operator++() {
1251+
assert(Cur && "incrementing past end()!");
1252+
while ((Cur = Cur->NextUse)) {
1253+
if (Cur->isTypeDependent())
1254+
break;
1255+
}
1256+
return *this;
1257+
}
1258+
1259+
TypeDependentUseIterator operator++(int unused) {
1260+
TypeDependentUseIterator copy = *this;
1261+
++*this;
1262+
return copy;
1263+
}
1264+
};
1265+
1266+
inline ValueBase::typedependent_use_iterator
1267+
ValueBase::typedependent_use_begin() const {
1268+
auto cur = FirstUse;
1269+
while (cur && !cur->isTypeDependent()) {
1270+
cur = cur->NextUse;
1271+
}
1272+
return ValueBase::typedependent_use_iterator(cur);
1273+
}
1274+
1275+
inline ValueBase::typedependent_use_iterator
1276+
ValueBase::typedependent_use_end() const {
1277+
return ValueBase::typedependent_use_iterator(nullptr);
1278+
}
1279+
12341280
class NonTypeDependentUseIterator : public ValueBaseUseIterator {
12351281
public:
12361282
explicit NonTypeDependentUseIterator(Operand *cur)
@@ -1311,6 +1357,11 @@ ValueBase::getNonConsumingUses() const {
13111357
return {non_consuming_use_begin(), non_consuming_use_end()};
13121358
}
13131359

1360+
inline ValueBase::typedependent_use_range
1361+
ValueBase::getTypeDependentUses() const {
1362+
return {typedependent_use_begin(), typedependent_use_end()};
1363+
}
1364+
13141365
inline ValueBase::non_typedependent_use_range
13151366
ValueBase::getNonTypeDependentUses() const {
13161367
return {non_typedependent_use_begin(), non_typedependent_use_end()};

lib/SIL/IR/SILValue.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ void ValueBase::replaceAllUsesWithUndef() {
6565
}
6666
}
6767

68+
void ValueBase::replaceAllTypeDependentUsesWith(ValueBase *RHS) {
69+
SmallVector<Operand *, 4> typeUses(getTypeDependentUses());
70+
for (Operand *use : typeUses) {
71+
use->set(RHS);
72+
}
73+
}
74+
6875
SILInstruction *ValueBase::getDefiningInstruction() {
6976
if (auto *inst = dyn_cast<SingleValueInstruction>(this))
7077
return inst;

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
///
3838
/// 1. Reused-storage: Some operations are guaranteed to reuse their operand's
3939
/// storage. This includes extracting an enum payload and opening an existential
40-
/// value. This is required avoid introducing new copies or moves.
40+
/// value. This is required to avoid introducing new copies or moves.
4141
///
4242
/// // %data's storage must reuse storage allocated for %enum
4343
/// %data = unchecked_enum_data %enum : $Optional<T>, #Optional.some!enumelt
@@ -2503,12 +2503,6 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
25032503
// types.
25042504
void visitOpenExistentialValueInst(OpenExistentialValueInst *openExistential);
25052505

2506-
void visitOpenExistentialBoxValueInst(
2507-
OpenExistentialBoxValueInst *openExistentialBox) {
2508-
// FIXME: Unimplemented
2509-
llvm::report_fatal_error("Unimplemented OpenExistentialBox use.");
2510-
}
2511-
25122506
void visitReturnInst(ReturnInst *returnInst) {
25132507
// Returns are rewritten for any function with indirect results after
25142508
// opaque value rewriting.
@@ -2625,15 +2619,7 @@ void UseRewriter::visitOpenExistentialValueInst(
26252619
openExistential->getType().getAddressType(),
26262620
OpenedExistentialAccess::Immutable);
26272621

2628-
SmallVector<Operand *, 4> typeUses;
2629-
for (Operand *use : openExistential->getUses()) {
2630-
if (use->isTypeDependent()) {
2631-
typeUses.push_back(use);
2632-
}
2633-
}
2634-
for (Operand *use : typeUses) {
2635-
use->set(openAddr);
2636-
}
2622+
openExistential->replaceAllTypeDependentUsesWith(openAddr);
26372623
markRewritten(openExistential, openAddr);
26382624
}
26392625

@@ -2939,11 +2925,18 @@ class DefRewriter : SILInstructionVisitor<DefRewriter> {
29392925
addrMat.initializeComposingUse(&initExistentialValue->getOperandRef());
29402926
}
29412927

2942-
// Project an opaque value out of a box-type existential.
29432928
void visitOpenExistentialBoxValueInst(
2944-
OpenExistentialBoxValueInst *openExistentialBox) {
2945-
// FIXME: Unimplemented
2946-
llvm::report_fatal_error("Unimplemented OpenExistentialBoxValue def.");
2929+
OpenExistentialBoxValueInst *openExistentialBoxValue) {
2930+
// Replace the module's openedArchetypesDef
2931+
pass.getModule()->willDeleteInstruction(openExistentialBoxValue);
2932+
2933+
auto *openAddr = builder.createOpenExistentialBox(
2934+
openExistentialBoxValue->getLoc(),
2935+
openExistentialBoxValue->getOperand(),
2936+
openExistentialBoxValue->getType().getAddressType());
2937+
2938+
openExistentialBoxValue->replaceAllTypeDependentUsesWith(openAddr);
2939+
setStorageAddress(openExistentialBoxValue, openAddr);
29472940
}
29482941

29492942
// Load an opaque value.
@@ -2978,6 +2971,14 @@ class DefRewriter : SILInstructionVisitor<DefRewriter> {
29782971
for (Operand &operand : tupleInst->getAllOperands())
29792972
addrMat.initializeComposingUse(&operand);
29802973
}
2974+
2975+
void setStorageAddress(SILValue oldValue, SILValue addr) {
2976+
auto &storage = pass.valueStorageMap.getStorage(oldValue);
2977+
// getReusedStorageOperand() ensures that oldValue does not already have
2978+
// separate storage. So there's no need to delete its alloc_stack.
2979+
assert(!storage.storageAddress || storage.storageAddress == addr);
2980+
storage.storageAddress = addr;
2981+
}
29812982
};
29822983
} // end anonymous namespace
29832984

@@ -3132,7 +3133,8 @@ static void deleteRewrittenInstructions(AddressLoweringState &pass) {
31323133
}
31333134
}
31343135
LLVM_DEBUG(llvm::dbgs() << "DEAD "; deadInst->dump());
3135-
if (!isa<OpenExistentialValueInst>(deadInst)) {
3136+
if (!isa<OpenExistentialValueInst>(deadInst) &&
3137+
!isa<OpenExistentialBoxValueInst>(deadInst)) {
31363138
pass.deleter.forceDeleteWithUsers(deadInst);
31373139
continue;
31383140
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-sil-opt -address-lowering -enable-sil-opaque-values -sil-verify-all %s | %FileCheck %s
2+
//
3+
import Builtin
4+
import Swift
5+
6+
sil_stage raw
7+
8+
// CHECK-LABEL: sil [ossa] @test_open_existential_box_value : $@convention(thin) (@in Error) -> () {
9+
// CHECK: [[ALLOC:%.*]] = alloc_stack $Any
10+
// CHECK: [[VAL:%.*]] = load [take] %0 : $*Error
11+
// CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [[VAL]] : $Error
12+
// CHECK: [[OPENADDR:%.*]] = open_existential_box [[BORROW]] : $Error to $*@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error
13+
// CHECK: [[INIT:%.*]] = init_existential_addr [[ALLOC]] : $*Any, $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error
14+
// CHECK: copy_addr [[OPENADDR]] to [initialization] [[INIT]] : $*@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error
15+
// CHECK: destroy_addr [[ALLOC]] : $*Any
16+
// CHECK: end_borrow [[BORROW]] : $Error
17+
// CHECK: destroy_value [[VAL]] : $Error
18+
// CHECK: dealloc_stack [[ALLOC]] : $*Any
19+
// CHECK-LABEL: } // end sil function 'test_open_existential_box_value'
20+
sil [ossa] @test_open_existential_box_value : $@convention(thin) (@in Error) -> () {
21+
bb0(%0 : @owned $Error):
22+
%1 = begin_borrow [lexical] %0 : $Error
23+
%2 = open_existential_box_value %1 : $Error to $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error
24+
%3 = copy_value %2 : $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error
25+
%4 = init_existential_value %3 : $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error, $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error, $Any
26+
destroy_value %4 : $Any
27+
end_borrow %1 : $Error
28+
destroy_value %0 : $Error
29+
%ret = tuple ()
30+
return %ret : $()
31+
}

0 commit comments

Comments
 (0)