Skip to content

Commit a964cc0

Browse files
authored
Merge pull request swiftlang#77590 from eeckstein/fix-enum-data-simplification
Optimizer: fix simplification of unchecked_enum_data
2 parents 6b43670 + 99ef6f7 commit a964cc0

File tree

11 files changed

+106
-49
lines changed

11 files changed

+106
-49
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyUncheckedEnumData.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import SIL
1414

15-
extension UncheckedEnumDataInst : OnoneSimplifyable {
15+
extension UncheckedEnumDataInst : OnoneSimplifyable, SILCombineSimplifyable {
1616
func simplify(_ context: SimplifyContext) {
1717
guard let enumInst = self.enum as? EnumInst else {
1818
return

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ private func registerSwiftPasses() {
113113
registerForSILCombine(DestructureTupleInst.self, { run(DestructureTupleInst.self, $0) })
114114
registerForSILCombine(TypeValueInst.self, { run(TypeValueInst.self, $0) })
115115
registerForSILCombine(ClassifyBridgeObjectInst.self, { run(ClassifyBridgeObjectInst.self, $0) })
116+
registerForSILCombine(UncheckedEnumDataInst.self, { run(UncheckedEnumDataInst.self, $0) })
116117

117118
// Test passes
118119
registerPass(aliasInfoDumper, { aliasInfoDumper.run($0) })

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,9 +576,18 @@ extension SimplifyContext {
576576
let singleUse = preserveDebugInfo ? first.uses.singleUse : first.uses.ignoreDebugUses.singleUse
577577
let canEraseFirst = singleUse?.instruction == second
578578

579-
if !canEraseFirst && first.parentFunction.hasOwnership && replacement.ownership == .owned {
580-
// We cannot add more uses to `replacement` without inserting a copy.
581-
return
579+
if !canEraseFirst && first.parentFunction.hasOwnership {
580+
if replacement.ownership == .owned {
581+
// We cannot add more uses to `replacement` without inserting a copy.
582+
return
583+
}
584+
if first.ownership == .owned {
585+
// We have to insert a compensating destroy because we are deleting the second instruction but
586+
// not the first one. This can happen if the first instruction is an `enum` which constructs a
587+
// non-trivial enum from a trivial payload.
588+
let builder = Builder(before: second, self)
589+
builder.createDestroyValue(operand: first)
590+
}
582591
}
583592

584593
second.uses.replaceAll(with: replacement, self)

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ SWIFT_SILCOMBINE_PASS(DestroyValueInst)
531531
SWIFT_SILCOMBINE_PASS(DestructureStructInst)
532532
SWIFT_SILCOMBINE_PASS(DestructureTupleInst)
533533
SWIFT_SILCOMBINE_PASS(TypeValueInst)
534+
SWIFT_SILCOMBINE_PASS(UncheckedEnumDataInst)
534535

535536
#undef IRGEN_PASS
536537
#undef SWIFT_MODULE_PASS

lib/SILOptimizer/Analysis/SimplifyInstruction.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ namespace {
4747
SILValue visitStructExtractInst(StructExtractInst *SEI);
4848
SILValue visitEnumInst(EnumInst *EI);
4949
SILValue visitSelectEnumInst(SelectEnumInst *SEI);
50-
SILValue visitUncheckedEnumDataInst(UncheckedEnumDataInst *UEDI);
5150
SILValue visitAddressToPointerInst(AddressToPointerInst *ATPI);
5251
SILValue visitPointerToAddressInst(PointerToAddressInst *PTAI);
5352
SILValue visitRefToRawPointerInst(RefToRawPointerInst *RRPI);
@@ -171,24 +170,6 @@ SILValue InstSimplifier::visitStructExtractInst(StructExtractInst *sei) {
171170
return SILValue();
172171
}
173172

174-
SILValue
175-
InstSimplifier::visitUncheckedEnumDataInst(UncheckedEnumDataInst *uedi) {
176-
if (uedi->getOperand()->getType().isValueTypeWithDeinit())
177-
return SILValue();
178-
// (unchecked_enum_data (enum payload)) -> payload
179-
auto opt = lookThroughOwnershipInsts(uedi->getOperand());
180-
if (auto *ei = dyn_cast<EnumInst>(opt)) {
181-
if (ei->getElement() != uedi->getElement())
182-
return SILValue();
183-
184-
assert(ei->hasOperand() &&
185-
"Should only get data from an enum with payload.");
186-
return lookThroughOwnershipInsts(ei->getOperand());
187-
}
188-
189-
return SILValue();
190-
}
191-
192173
// Simplify:
193174
// %1 = unchecked_enum_data %0 : $Optional<C>, #Optional.Some!enumelt
194175
// %2 = enum $Optional<C>, #Optional.Some!enumelt, %1 : $C

test/SILOptimizer/sil_combine_enums_ossa.sil

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ enum Numerals {
1818
case Four
1919
}
2020

21+
enum E2 {
22+
case int(Int)
23+
case str(String)
24+
}
25+
2126
sil [ossa] @external_func: $@convention(thin) () -> ()
27+
sil @useit : $@convention(thin) (@owned E2) -> ()
2228

2329
// CHECK-LABEL: sil [ossa] @eliminate_sw_enum_addr : $@convention(thin) () -> Int {
2430
// CHECK-NOT: switch_enum_addr
@@ -679,3 +685,33 @@ bb0(%0 : $*Optional<NC>):
679685
return %1 : $Optional<NC>
680686
}
681687

688+
// CHECK-LABEL: sil [ossa] @trivial_replacement
689+
// CHECK: bb1({{.*}}:
690+
// CHECK-NEXT: end_borrow
691+
// CHECK-NEXT: destroy_value %2
692+
// CHECK: apply {{%[0-9]+}}(%1)
693+
// CHECK: } // end sil function 'trivial_replacement'
694+
sil [ossa] @trivial_replacement : $@convention(thin) (Int) -> () {
695+
bb0(%0 : $Int):
696+
%1 = enum $E2, #E2.int!enumelt, %0 : $Int
697+
%2 = enum $Optional<E2>, #Optional.some!enumelt, %1 : $E2, forwarding: @owned
698+
%3 = begin_borrow %2 : $Optional<E2>
699+
switch_enum %3 : $Optional<E2>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
700+
701+
bb1(%5 : @guaranteed $E2):
702+
end_borrow %3 : $Optional<E2>
703+
%7 = unchecked_enum_data %2 : $Optional<E2>, #Optional.some!enumelt
704+
%8 = function_ref @useit : $@convention(thin) (@owned E2) -> ()
705+
%9 = apply %8(%7) : $@convention(thin) (@owned E2) -> ()
706+
br bb3
707+
708+
bb2:
709+
end_borrow %3 : $Optional<E2>
710+
destroy_value %2 : $Optional<E2>
711+
br bb3
712+
713+
bb3:
714+
%r = tuple ()
715+
return %r : $()
716+
}
717+

test/SILOptimizer/sil_combine_ossa.sil

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5202,25 +5202,6 @@ bb0(%0 : @guaranteed $Function):
52025202
return %13 : $Double
52035203
}
52045204

5205-
// CHECK-LABEL: sil [ossa] @test_borrow_unchecked_enum_data : $@convention(thin) (@guaranteed Function) -> Double {
5206-
// CHECK-NOT: unchecked_enum_data
5207-
// CHECK: } // end sil function 'test_borrow_unchecked_enum_data'
5208-
sil [ossa] @test_borrow_unchecked_enum_data : $@convention(thin) (@guaranteed Function) -> Double {
5209-
bb0(%0 : @guaranteed $Function):
5210-
%3 = function_ref @negateFunction : $@convention(thin) (MyInt, @guaranteed Function) -> Double
5211-
%4 = copy_value %0 : $Function
5212-
%5 = partial_apply [callee_guaranteed] %3(%4) : $@convention(thin) (MyInt, @guaranteed Function) -> Double
5213-
%7 = integer_literal $Builtin.Int32, 0
5214-
%8 = struct $MyInt (%7 : $Builtin.Int32)
5215-
%6 = enum $Optional<@callee_guaranteed (MyInt) -> Double>, #Optional.some!enumelt, %5 : $@callee_guaranteed (MyInt) -> Double
5216-
%9 = begin_borrow %6 : $Optional<@callee_guaranteed (MyInt) -> Double>
5217-
%12 = unchecked_enum_data %9 : $Optional<@callee_guaranteed (MyInt) -> Double>, #Optional.some!enumelt
5218-
%13 = apply %12(%8) : $@callee_guaranteed (MyInt) -> Double
5219-
end_borrow %9 : $Optional<@callee_guaranteed (MyInt) -> Double>
5220-
destroy_value %6 : $Optional<@callee_guaranteed (MyInt) -> Double>
5221-
return %13 : $Double
5222-
}
5223-
52245205
sil [reabstraction_thunk] @thunk : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> ()
52255206

52265207
// CHECK-LABEL: sil [ossa] @test_partial_apply_apply_opt1 :

test/SILOptimizer/simplify_cfg_args.sil

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,15 @@ enum X {
121121
case C(Int32)
122122
}
123123

124-
// CHECK-LABEL: simplify_switch_include_args
124+
// CHECK-LABEL: sil @simplify_switch_include_args :
125+
// CHECK: tuple
126+
// CHECK-NEXT: enum $X
127+
// CHECK-NEXT: unchecked_enum_data
128+
// CHECK-NEXT: tuple_extract
129+
// CHECK-NEXT: return
130+
// CHECK: } // end sil function 'simplify_switch_include_args'
125131
sil @simplify_switch_include_args : $@convention(thin) (Int32, Int32) -> Int32 {
126132
bb0(%0 : $Int32, %1 : $Int32):
127-
// CHECK: return %0 : $Int32
128133
%2 = tuple (%0 : $Int32, %1 : $Int32)
129134
%3 = enum $X, #X.B!enumelt, %2 : $(Int32, Int32)
130135
switch_enum %3 : $X, case #X.A!enumelt: bb1, case #X.B!enumelt: bb3, case #X.C!enumelt: bb5

test/SILOptimizer/simplify_cfg_args_ossa.sil

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,15 @@ enum X {
9393
case C(Int32)
9494
}
9595

96-
// CHECK-LABEL: simplify_switch_include_args
96+
// CHECK-LABEL: sil [ossa] @simplify_switch_include_args :
97+
// CHECK: tuple
98+
// CHECK-NEXT: enum $X
99+
// CHECK-NEXT: unchecked_enum_data
100+
// CHECK-NEXT: tuple_extract
101+
// CHECK-NEXT: return
102+
// CHECK: } // end sil function 'simplify_switch_include_args'
97103
sil [ossa] @simplify_switch_include_args : $@convention(thin) (Int32, Int32) -> Int32 {
98104
bb0(%0 : $Int32, %1 : $Int32):
99-
// CHECK: return %0 : $Int32
100105
%2 = tuple (%0 : $Int32, %1 : $Int32)
101106
%3 = enum $X, #X.B!enumelt, %2 : $(Int32, Int32)
102107
switch_enum %3 : $X, case #X.A!enumelt: bb1, case #X.B!enumelt: bb3, case #X.C!enumelt: bb5

test/SILOptimizer/simplify_cfg_ossa_dom_jumpthread.sil

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -511,11 +511,12 @@ bb7(%r : $Builtin.Int32, %carg2 : $Builtin.Int32):
511511

512512
// CHECK-LABEL: sil [ossa] @jumpthread_switch_enum5
513513
// CHECK: bb0:
514-
// CHECK: br bb2
514+
// CHECK: br bb1
515515
// CHECK: bb1:
516-
// CHECK-NEXT: br bb2
516+
// CHECK-NEXT: cond_br undef, bb2, bb3
517517
// CHECK: bb2:
518-
// CHECK: cond_br undef, bb1, bb3
518+
// CHECK-NEXT: unchecked_enum_data
519+
// CHECK-NEXT: br bb1
519520
// CHECK: bb3:
520521
// CHECK-NEXT: tuple
521522
// CHECK-NEXT: return

0 commit comments

Comments
 (0)