Skip to content

Commit 2abd7e8

Browse files
committed
[sil-combine] Update unchecked_bitwise_cast canonicalizations for ownership.
The only interesting thing that I did in this commit is I added a parameter to OwnershipRAUWHelper::perform that lets one pass in a transformed version of newValue. The assumption is that the transformation if it is done is done at the location of oldValue.
1 parent 44fdc74 commit 2abd7e8

File tree

3 files changed

+76
-33
lines changed

3 files changed

+76
-33
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -739,9 +739,6 @@ visitUncheckedTrivialBitCastInst(UncheckedTrivialBitCastInst *UTBCI) {
739739
SILInstruction *
740740
SILCombiner::
741741
visitUncheckedBitwiseCastInst(UncheckedBitwiseCastInst *UBCI) {
742-
if (UBCI->getFunction()->hasOwnership())
743-
return nullptr;
744-
745742
// (unchecked_bitwise_cast Y->Z (unchecked_bitwise_cast X->Y x))
746743
// OR (unchecked_trivial_cast Y->Z (unchecked_bitwise_cast X->Y x))
747744
// ->
@@ -750,20 +747,55 @@ visitUncheckedBitwiseCastInst(UncheckedBitwiseCastInst *UBCI) {
750747
if (match(UBCI->getOperand(),
751748
m_CombineOr(m_UncheckedBitwiseCastInst(m_SILValue(Oper)),
752749
m_UncheckedTrivialBitCastInst(m_SILValue(Oper))))) {
753-
return Builder.createUncheckedBitwiseCast(UBCI->getLoc(), Oper,
754-
UBCI->getType());
750+
if (!Builder.hasOwnership()) {
751+
return Builder.createUncheckedBitwiseCast(UBCI->getLoc(), Oper,
752+
UBCI->getType());
753+
}
754+
755+
OwnershipRAUWHelper helper(ownershipFixupContext, UBCI, Oper);
756+
if (helper) {
757+
auto *transformedOper = Builder.createUncheckedBitwiseCast(
758+
UBCI->getLoc(), Oper, UBCI->getType());
759+
helper.perform(transformedOper);
760+
return nullptr;
761+
}
762+
}
763+
764+
if (UBCI->getType().isTrivial(*UBCI->getFunction())) {
765+
// If our result is trivial, we can always just RAUW.
766+
return Builder.createUncheckedTrivialBitCast(
767+
UBCI->getLoc(), UBCI->getOperand(), UBCI->getType());
755768
}
756-
if (UBCI->getType().isTrivial(*UBCI->getFunction()))
757-
return Builder.createUncheckedTrivialBitCast(UBCI->getLoc(),
758-
UBCI->getOperand(),
759-
UBCI->getType());
760769

761770
if (!SILType::canRefCast(UBCI->getOperand()->getType(), UBCI->getType(),
762771
Builder.getModule()))
763772
return nullptr;
764773

765-
return Builder.createUncheckedRefCast(UBCI->getLoc(), UBCI->getOperand(),
766-
UBCI->getType());
774+
if (!Builder.hasOwnership()) {
775+
return Builder.createUncheckedRefCast(UBCI->getLoc(), UBCI->getOperand(),
776+
UBCI->getType());
777+
}
778+
779+
{
780+
OwnershipRAUWHelper helper(ownershipFixupContext, UBCI, UBCI->getOperand());
781+
if (helper) {
782+
auto *newInst = Builder.createUncheckedRefCast(UBCI->getLoc(), UBCI->getOperand(),
783+
UBCI->getType());
784+
// If we have an operand with owned ownership, we change our
785+
// unchecked_ref_cast to explicitly pass the owned operand as an unowned
786+
// value. This is because otherwise, we would consume the owned value
787+
// creating breaking OSSA. In contrast, if we have a guaranteed value, we
788+
// are going to be replacing an UnownedInstantaneousUse with an
789+
// InstantaneousUse which is always safe for a guaranteed value.
790+
if (newInst->getOwnershipKind() == OwnershipKind::Owned) {
791+
newInst->setOwnershipKind(OwnershipKind::Unowned);
792+
}
793+
helper.perform(newInst);
794+
return nullptr;
795+
}
796+
}
797+
798+
return nullptr;
767799
}
768800

769801
SILInstruction *

test/SILOptimizer/sil_combine.sil

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4075,16 +4075,3 @@ bb0:
40754075
%1 = load %0 : $*Int64
40764076
return %1 : $Int64
40774077
}
4078-
4079-
// Check for disabled optimization of unchecked_bitwise_cast to unchecked_ref_cast in ossa
4080-
// This test can be optimized when ossa is supported in the SILCombine for unchecked_bitwise_cast
4081-
// CHECK-LABEL: sil [ossa] @refcast :
4082-
// CHECK: unchecked_bitwise_cast
4083-
// CHECK-LABEL: } // end sil function 'refcast'
4084-
sil [ossa] @refcast : $@convention(thin) (@owned Klass) -> @owned Optional<Klass> {
4085-
bb0(%0 : @owned $Klass):
4086-
%1 = unchecked_bitwise_cast %0 : $Klass to $Optional<Klass>
4087-
%2 = copy_value %1 : $Optional<Klass>
4088-
destroy_value %0 : $Klass
4089-
return %2 : $Optional<Klass>
4090-
}

test/SILOptimizer/sil_combine_ossa.sil

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,14 +2018,14 @@ bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.RawPointer):
20182018
return %6 : $(B, Optional<Builtin.Word>)
20192019
}
20202020

2021-
// We do not suport the non-trivial version of this in OSSA today due to issues around unowned ownership.
2022-
//
2023-
// CHECK-LABEL: sil [ossa] @bitwise_combines : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
2024-
// XHECK: bb0(
2025-
// XHECK-NEXT: unchecked_bitwise_cast
2026-
// XHECK-NEXT: unchecked_trivial_bit_cast
2027-
// XHECK-NEXT: unchecked_bitwise_cast
2028-
sil [ossa] @bitwise_combines : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
2021+
// CHECK-LABEL: sil [ossa] @bitwise_combines_owned : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
2022+
// CHECK: bb0(
2023+
// CHECK-NEXT: unchecked_bitwise_cast
2024+
// CHECK-NEXT: unchecked_trivial_bit_cast
2025+
// CHECK-NEXT: unchecked_ref_cast
2026+
// CHECK-NOT: unchecked_bitwise_cast
2027+
// CHECK: } // end sil function 'bitwise_combines_owned'
2028+
sil [ossa] @bitwise_combines_owned : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
20292029
bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.RawPointer):
20302030
// combine
20312031
%2 = unchecked_bitwise_cast %1 : $Builtin.RawPointer to $Builtin.Word
@@ -2044,6 +2044,30 @@ bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.RawPointer):
20442044
return %6a : $(Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>)
20452045
}
20462046

2047+
// CHECK-LABEL: sil [ossa] @bitwise_combines_guaranteed : $@convention(thin) (@guaranteed Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
2048+
// CHECK: bb0(
2049+
// CHECK-NEXT: unchecked_bitwise_cast
2050+
// CHECK-NEXT: unchecked_trivial_bit_cast
2051+
// CHECK-NEXT: unchecked_ref_cast
2052+
// CHECK-NOT: unchecked_bitwise_cast
2053+
// CHECK: } // end sil function 'bitwise_combines_guaranteed'
2054+
sil [ossa] @bitwise_combines_guaranteed : $@convention(thin) (@guaranteed Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
2055+
bb0(%0 : @guaranteed $Builtin.NativeObject, %1 : $Builtin.RawPointer):
2056+
// combine
2057+
%2 = unchecked_bitwise_cast %1 : $Builtin.RawPointer to $Builtin.Word
2058+
%3 = unchecked_bitwise_cast %2 : $Builtin.Word to $Optional<Builtin.NativeObject>
2059+
2060+
// promote trivial
2061+
%4 = unchecked_bitwise_cast %0 : $Builtin.NativeObject to $Builtin.RawPointer
2062+
2063+
// promote ref
2064+
%5 = unchecked_bitwise_cast %0 : $Builtin.NativeObject to $Optional<Builtin.NativeObject>
2065+
2066+
%6 = tuple(%3 : $Optional<Builtin.NativeObject>, %4 : $Builtin.RawPointer, %5 : $Optional<Builtin.NativeObject>)
2067+
%6a = copy_value %6 : $(Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>)
2068+
return %6a : $(Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>)
2069+
}
2070+
20472071
// CHECK-LABEL: @remove_pointer_compare_to_zero :
20482072
// CHECK-NOT: apply
20492073
// CHECK-NOT: cond_fail
@@ -4519,4 +4543,4 @@ bb1(%2 : @owned $FakeOptional<Builtin.NativeObject>):
45194543
destroy_value %2 : $FakeOptional<Builtin.NativeObject>
45204544
%9999 = tuple()
45214545
return %9999 : $()
4522-
}
4546+
}

0 commit comments

Comments
 (0)