Skip to content

Commit 1e6edcb

Browse files
committed
[sil-combine] Fix a couple of oversights in the propagation of concrete types of existentials
- Do not try to make a lookup type of a witness_method more concrete if it not an opened existential. - Replace witness_method instruction by a new one with a more concrete type only in the specific apply instruction instead of doing it everywhere. This allows for more optimization opportunities if the same witness_method is used by multiple apply instructions.
1 parent a4d7b37 commit 1e6edcb

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -871,12 +871,17 @@ SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite AI,
871871
return nullptr;
872872
}
873873

874-
// Obtain the protocol whose which should be used by the conformance.
874+
// The lookup type is not a opened existential type,
875+
// thus it cannot be made more concrete.
876+
if (!WMI->getLookupType()->isOpenedExistential())
877+
return nullptr;
878+
879+
// Obtain the protocol which should be used by the conformance.
875880
auto *PD = WMI->getLookupProtocol();
876881

877882
// Propagate the concrete type into a callee-operand, which is a
878883
// witness_method instruction.
879-
auto PropagateIntoOperand = [this, &WMI](CanType ConcreteType,
884+
auto PropagateIntoOperand = [this, &WMI, &AI](CanType ConcreteType,
880885
ProtocolConformanceRef Conformance) {
881886
// Keep around the dependence on the open instruction unless we've
882887
// actually eliminated the use.
@@ -885,8 +890,15 @@ SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite AI,
885890
Conformance, WMI->getMember(),
886891
WMI->getType(),
887892
WMI->isVolatile());
888-
replaceInstUsesWith(*WMI, NewWMI);
889-
eraseInstFromFunction(*WMI);
893+
// Replace only uses of the witness_method in the apply that is going to
894+
// be changed.
895+
MutableArrayRef<Operand> Operands = AI.getInstruction()->getAllOperands();
896+
for (auto &Op : Operands) {
897+
if (Op.get() == WMI)
898+
Op.set(NewWMI);
899+
}
900+
if (WMI->use_empty())
901+
eraseInstFromFunction(*WMI);
890902
};
891903

892904
// Try to perform the propagation.

test/SILOptimizer/sil_combine.sil

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3038,6 +3038,31 @@ bb0(%0 : $BBB):
30383038
return %11 : $()
30393039
}
30403040

3041+
// Check that both applies can be devirtualized by means of propagating the concrete
3042+
// type of the existential into witness_method and apply instructions.
3043+
// CHECK-LABEL: sil @silcombine_devirt_both_applies_of_witness_method
3044+
// CHECK-NOT: open_existential_ref
3045+
// CHECK-NOT: witness_method
3046+
// CHECK: [[FR1:%.*]] = function_ref @_TTWC4nix23XXXS_3PPPS_FS1_3foofT_T_
3047+
// CHECK: apply [[FR1]](%0)
3048+
// CHECK: [[FR2:%.*]] = function_ref @_TTWC4nix23XXXS_3PPPS_FS1_3foofT_T_
3049+
// CHECK: apply [[FR2]](%0)
3050+
// CHECK: return
3051+
sil @silcombine_devirt_both_applies_of_witness_method : $@convention(thin) (@owned XXX) -> () {
3052+
bb0(%0 : $XXX):
3053+
strong_retain %0 : $XXX
3054+
%3 = init_existential_ref %0 : $XXX : $XXX, $PPP
3055+
%5 = open_existential_ref %3 : $PPP to $@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP
3056+
%6 = witness_method $@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP, #PPP.foo!1, %5 : $@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
3057+
%7 = apply %6<@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP>(%5) : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
3058+
%8 = apply %6<@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP>(%5) : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
3059+
strong_release %3 : $PPP
3060+
%9 = tuple ()
3061+
strong_release %0 : $XXX
3062+
%11 = tuple ()
3063+
return %11 : $()
3064+
}
3065+
30413066
sil @_TTWC4nix23XXXS_3PPPS_FS1_3foofT_T_ : $@convention(witness_method) (@guaranteed XXX) -> ()
30423067

30433068
sil_witness_table XXX: PPP module nix2 {

0 commit comments

Comments
 (0)