Skip to content

Enable ArrayCountPropagation on OSSA #35191

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions lib/SILOptimizer/Transforms/ArrayCountPropagation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ bool ArrayAllocation::recursivelyCollectUses(ValueBase *Def) {
for (auto *Opd : Def->getUses()) {
auto *User = Opd->getUser();
// Ignore reference counting and debug instructions.
if (isa<RefCountingInst>(User) ||
if (isa<RefCountingInst>(User) || isa<DestroyValueInst>(User) ||
isa<DebugValueInst>(User))
continue;

Expand Down Expand Up @@ -195,11 +195,6 @@ class ArrayCountPropagation : public SILFunctionTransform {

void run() override {
auto &Fn = *getFunction();

// FIXME: Add ownership support.
if (Fn.hasOwnership())
return;

bool Changed = false;
SmallVector<ApplyInst *, 16> DeadArrayCountCalls;
// Propagate the count of array allocations to array.count users.
Expand Down
184 changes: 184 additions & 0 deletions test/SILOptimizer/array_count_propagation_ossa.sil
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// RUN: %target-sil-opt -enable-sil-verify-all -array-count-propagation %s | %FileCheck %s

sil_stage canonical

import Builtin
import Swift

struct MyInt {
@_hasStorage var _value: Builtin.Int64
}

struct MyBool {}

struct _MyBridgeStorage {
@_hasStorage var rawValue : Builtin.BridgeObject
}

struct _MyArrayBuffer<T> {
@_hasStorage var _storage : _MyBridgeStorage
}

struct MyArray<T> {
@_hasStorage var _buffer : _MyArrayBuffer<T>
}

class Klass {
}

sil [ossa] @swift_bufferAllocate : $@convention(thin)() -> @owned AnyObject
sil [ossa] [_semantics "array.uninitialized"] @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
sil [ossa] [_semantics "array.get_count"] @getCount : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
sil [ossa] [_semantics "array.get_element"] @getElement : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> @out MyInt
sil [ossa] [_semantics "array.uninitialized"] @allocateUninitialized : $@convention(thin) (MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
sil [ossa] [_semantics "array.finalize_intrinsic"] @finalize : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
sil [ossa] [_semantics "array.init"] @initRepeatedValueCount : $@convention(thin) (@in MyInt, MyInt, @thin MyArray<MyInt>.Type) -> @owned MyArray<MyInt>
sil [ossa] [_semantics "array.init"] @initEmpty : $@convention(thin) (@thin MyArray<MyInt>.Type) -> @owned MyArray<MyInt>

// CHECK-LABEL: sil [ossa] @test_adoptStorage1 :
// CHECK: [[COUNTVAL:%.*]] = integer_literal $Builtin.Int64, 3
// CHECK: [[COUNT:%.*]] = struct $MyInt ([[COUNTVAL]]
// CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount
// CHECK-NOT: apply [[GETCOUNTFUN]]
// CHECK-LABEL: } // end sil function 'test_adoptStorage1'
sil [ossa] @test_adoptStorage1 : $@convention(thin) () -> MyInt {
bb0:
%0 = integer_literal $Builtin.Int64, 3
%1 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject
%2 = apply %1() : $@convention(thin) () -> @owned AnyObject
%3 = struct $MyInt(%0 : $Builtin.Int64)
%4 = metatype $@thin MyArray<MyInt>.Type
%5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
%6 = apply %5(%2, %3, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
(%7, %8) = destructure_tuple %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
debug_value %7 : $MyArray<MyInt>
%f = function_ref @finalize : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
%a = apply %f(%7) : $@convention(thin) (@owned MyArray<MyInt>) -> @owned MyArray<MyInt>
%9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
%10 = apply %9(%a) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
destroy_value %a : $MyArray<MyInt>
return %10 : $MyInt
}

// CHECK-LABEL: sil [ossa] @test_allocateUninitialized :
// CHECK: [[COUNTVAL:%.*]] = integer_literal $Builtin.Int64, 3
// CHECK: [[COUNT:%.*]] = struct $MyInt ([[COUNTVAL]]
// CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount
// CHECK-NOT: apply [[GETCOUNTFUN]]
// CHECK-LABEL: } // end sil function 'test_allocateUninitialized'
sil [ossa] @test_allocateUninitialized : $@convention(thin) () -> MyInt {
bb0:
%0 = integer_literal $Builtin.Int64, 3
%3 = struct $MyInt(%0 : $Builtin.Int64)
%4 = metatype $@thin MyArray<MyInt>.Type
%5 = function_ref @allocateUninitialized : $@convention(thin) (MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
%6 = apply %5(%3, %4) : $@convention(thin) (MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
(%7, %8) = destructure_tuple %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
debug_value %7 : $MyArray<MyInt>
%9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
%10 = apply %9(%7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
%15 = function_ref @getElement : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> @out MyInt
%16 = alloc_stack $MyInt
%17 = struct $MyBool()
%18 = apply %15(%16, %3, %17, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> @out MyInt
destroy_value %7 : $MyArray<MyInt>
dealloc_stack %16 : $*MyInt
return %10 : $MyInt
}

// CHECK-LABEL: sil [ossa] @test_initRepeatedValueCount :
// CHECK: [[COUNTVAL:%.*]] = integer_literal $Builtin.Int64, 3
// CHECK: [[COUNT:%.*]] = struct $MyInt ([[COUNTVAL]]
// CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount
// CHECK-NOT: apply [[GETCOUNTFUN]]
// CHECK-LABEL: } // end sil function 'test_initRepeatedValueCount'
sil [ossa] @test_initRepeatedValueCount : $@convention(thin) () -> MyInt {
bb0:
%0 = integer_literal $Builtin.Int64, 3
%1 = alloc_stack $MyInt
%3 = struct $MyInt(%0 : $Builtin.Int64)
store %3 to [trivial] %1: $*MyInt
%4 = metatype $@thin MyArray<MyInt>.Type
%5 = function_ref @initRepeatedValueCount : $@convention(thin) (@in MyInt, MyInt, @thin MyArray<MyInt>.Type) -> @owned MyArray<MyInt>
%6 = apply %5(%1, %3, %4) : $@convention(thin) (@in MyInt, MyInt, @thin MyArray<MyInt>.Type) -> @owned MyArray<MyInt>
debug_value %6 : $MyArray<MyInt>
%9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
%10 = apply %9(%6) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
%15 = function_ref @getElement : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> @out MyInt
%16 = alloc_stack $MyInt
%17 = struct $MyBool()
%18 = apply %15(%16, %3, %17, %6) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> @out MyInt
destroy_value %6 : $MyArray<MyInt>
dealloc_stack %16 : $*MyInt
dealloc_stack %1 : $*MyInt
return %10 : $MyInt
}

// CHECK-LABEL: sil [ossa] @test_escape :
// CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount
// CHECK: [[RESULT:%.*]] = apply [[GETCOUNTFUN]]
// CHECK-LABEL: } // end sil function 'test_escape'
sil [ossa] @test_escape : $@convention(thin) () -> MyInt {
bb0:
%0 = integer_literal $Builtin.Int64, 3
%15 = alloc_stack $MyArray<MyInt>
%1 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject
%2 = apply %1() : $@convention(thin) () -> @owned AnyObject
%3 = struct $MyInt(%0 : $Builtin.Int64)
%4 = metatype $@thin MyArray<MyInt>.Type
%5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
%6 = apply %5(%2, %3, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
(%7, %8) = destructure_tuple %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
%copy7 = copy_value %7 : $MyArray<MyInt>
debug_value %7 : $MyArray<MyInt>
store %7 to [init] %15 : $*MyArray<MyInt>
%9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
%10 = apply %9(%copy7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
destroy_value %copy7 : $MyArray<MyInt>
destroy_addr %15 : $*MyArray<MyInt>
dealloc_stack %15 : $*MyArray<MyInt>
return %10 : $MyInt
}

sil [ossa] @mayWrite : $@convention(thin) (@guaranteed MyArray<MyInt>) -> ()

// CHECK-LABEL: sil [ossa] @test_mayWrite :
// CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount
// CHECK: [[RESULT:%.*]] = apply [[GETCOUNTFUN]]
// CHECK-LABEL: } // end sil function 'test_mayWrite'
sil [ossa] @test_mayWrite : $@convention(thin) () -> MyInt {
bb0:
%0 = integer_literal $Builtin.Int64, 3
%1 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject
%2 = apply %1() : $@convention(thin) () -> @owned AnyObject
%3 = struct $MyInt(%0 : $Builtin.Int64)
%4 = metatype $@thin MyArray<MyInt>.Type
%5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
%6 = apply %5(%2, %3, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
(%7, %8) = destructure_tuple %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
debug_value %7 : $MyArray<MyInt>
%15 = function_ref @mayWrite : $@convention(thin) (@guaranteed MyArray<MyInt>) -> ()
%16 = apply %15(%7) : $@convention(thin) (@guaranteed MyArray<MyInt>) -> ()
%9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
%10 = apply %9(%7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
destroy_value %7 : $MyArray<MyInt>
return %10 : $MyInt
}

// We don't handle empty array allocations yet.
// CHECK-LABEL: sil [ossa] @test_initEmpty :
// CHECK: [[GETCOUNTFUN:%.*]] = function_ref @getCount
// CHECK: [[RESULT:%.*]] = apply [[GETCOUNTFUN]]
// CHECK-LABEL: } // end sil function 'test_initEmpty'
sil [ossa] @test_initEmpty : $@convention(thin) () -> MyInt {
bb0:
%4 = metatype $@thin MyArray<MyInt>.Type
%5 = function_ref @initEmpty : $@convention(thin) (@thin MyArray<MyInt>.Type) -> @owned MyArray<MyInt>
%6 = apply %5(%4) : $@convention(thin) (@thin MyArray<MyInt>.Type) -> @owned MyArray<MyInt>
debug_value %6 : $MyArray<MyInt>
%9 = function_ref @getCount : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
%10 = apply %9(%6) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyInt
destroy_value %6 : $MyArray<MyInt>
return %10 : $MyInt
}