Files
swift-mirror/test/SILOptimizer/string_optimization.sil
T
Erik Eckstein c20593cd58 Optimizer: better support of OSSA in various optimizations
Mainly:
* look through ownership instructions in more places
* support `load_borrow` and `store_borrow` where `load` and `store`s are expected
* support `destructure_struct` where `struct_extract` is expected
* enable inout-keypath optimization for OSSA
* OSSA support in StringOptimization
2026-03-10 07:56:51 +01:00

267 lines
15 KiB
Plaintext

// RUN: %target-sil-opt %s -parse-serialized-sil -string-optimization -sil-combine | %FileCheck %s
sil_stage canonical
import Builtin
import Swift
import SwiftShims
sil [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
sil [readonly] [_semantics "string.init_empty"] @empty_string : $@convention(method) (@thin String.Type) -> @owned String
sil [_semantics "string.init_empty"] @empty_string_with_capacity : $@convention(method) (Int, @thin String.Type) -> @owned String
sil [_semantics "string.append"] @string_append : $@convention(method) (@guaranteed String, @inout String) -> ()
sil [_semantics "string.concat"] @string_concat : $@convention(method) (@guaranteed String, @guaranteed String, @thin String.Type) -> @owned String
sil [readonly] [_semantics "string.getUTF8CString"] @string_getUTF8CString : $@convention(method) (@guaranteed String) -> @owned ContiguousArray<Int8>
// CHECK-LABEL: sil [ossa] @ossa_append_to_empty_string
// CHECK: [[S:%[0-9]+]] = alloc_stack $String
// CHECK: [[F:%[0-9]+]] = function_ref @empty_string
// CHECK: [[A:%[0-9]+]] = apply [[F]]
// CHECK-NEXT: store [[A]] to [init] [[S]]
// CHECK-NEXT: [[COPY:%[0-9]+]] = copy_value %0
// CHECK-NEXT: store [[COPY]] to [assign] [[S]]
// CHECK-NEXT: [[L:%[0-9]+]] = load [take] [[S]]
// CHECK: return [[L]]
// CHECK: } // end sil function 'ossa_append_to_empty_string'
sil [ossa] @ossa_append_to_empty_string : $@convention(thin) (@guaranteed String) -> @owned String {
bb0(%0 : @guaranteed $String):
%2 = alloc_stack $String
%5 = metatype $@thin String.Type
%6 = function_ref @empty_string : $@convention(method) (@thin String.Type) -> @owned String
%7 = apply %6(%5) : $@convention(method) (@thin String.Type) -> @owned String
store %7 to [init] %2 : $*String
%14 = function_ref @string_append : $@convention(method) (@guaranteed String, @inout String) -> ()
%15 = apply %14(%0, %2) : $@convention(method) (@guaranteed String, @inout String) -> ()
%28 = load [take] %2 : $*String
dealloc_stack %2 : $*String
return %28 : $String
}
// CHECK-LABEL: sil [ossa] @append_empty_string
// CHECK: [[S:%[0-9]+]] = alloc_stack $String
// CHECK-NEXT: store %0 to [init] [[S]]
// CHECK-NEXT: [[L:%[0-9]+]] = load [take] [[S]]
// CHECK: return [[L]]
// CHECK: } // end sil function 'append_empty_string'
sil [ossa] @append_empty_string : $@convention(thin) (@owned String) -> @owned String {
bb0(%0 : @owned $String):
%2 = alloc_stack $String
store %0 to [init] %2 : $*String
%5 = metatype $@thin String.Type
%6 = function_ref @empty_string : $@convention(method) (@thin String.Type) -> @owned String
%7 = apply %6(%5) : $@convention(method) (@thin String.Type) -> @owned String
%14 = function_ref @string_append : $@convention(method) (@guaranteed String, @inout String) -> ()
%15 = apply %14(%7, %2) : $@convention(method) (@guaranteed String, @inout String) -> ()
destroy_value %7 : $String
%28 = load [take] %2 : $*String
dealloc_stack %2 : $*String
return %28 : $String
}
// CHECK-LABEL: sil [ossa] @append_constant_strings
// CHECK: [[S:%[0-9]+]] = alloc_stack $String
// CHECK: [[STR:%[0-9]+]] = string_literal utf8 "a🙂"
// CHECK: [[LENGTH:%[0-9]+]] = integer_literal $Builtin.Word, 5
// CHECK: [[ASCII:%[0-9]+]] = integer_literal $Builtin.Int1, 0
// CHECK: [[MT:%[0-9]+]] = metatype $@thin String.Type
// CHECK: [[F:%[0-9]+]] = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC
// CHECK: [[A:%[0-9]+]] = apply [[F]]([[STR]], [[LENGTH]], [[ASCII]], [[MT]])
// CHECK-NEXT: store [[A]] to [assign] [[S]]
// CHECK-NEXT: [[L:%[0-9]+]] = load [take] [[S]]
// CHECK: return [[L]]
// CHECK: } // end sil function 'append_constant_strings'
sil [ossa] @append_constant_strings : $@convention(thin) (@guaranteed String) -> @owned String {
bb0(%0 : @guaranteed $String):
%2 = alloc_stack $String
%3 = string_literal utf8 "a"
%4 = integer_literal $Builtin.Word, 1
%5 = integer_literal $Builtin.Int1, -1
%6 = metatype $@thin String.Type
%7 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%8 = apply %7(%3, %4, %5, %6) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%9 = string_literal utf8 "🙂"
%10 = integer_literal $Builtin.Word, 4
%11 = apply %7(%9, %10, %5, %6) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
store %8 to [init] %2 : $*String
%14 = function_ref @string_append : $@convention(method) (@guaranteed String, @inout String) -> ()
%15 = apply %14(%11, %2) : $@convention(method) (@guaranteed String, @inout String) -> ()
destroy_value %11 : $String
%28 = load [take] %2 : $*String
dealloc_stack %2 : $*String
return %28 : $String
}
// CHECK-LABEL: sil [ossa] @dont_concat_non_const_strings
// CHECK: [[S:%[0-9]+]] = alloc_stack $String
// CHECK-DAG: [[APPEND:%[0-9]+]] = function_ref @string_append
// CHECK: [[A_STR:%[0-9]+]] = apply {{.*}} : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
// CHECK: apply [[APPEND]]([[A_STR]], [[S]])
// CHECK: [[L:%[0-9]+]] = load [take] [[S]]
// CHECK: return [[L]]
// CHECK: } // end sil function 'dont_concat_non_const_strings'
sil [ossa] @dont_concat_non_const_strings : $@convention(thin) (@guaranteed String) -> @owned String {
bb0(%0 : @guaranteed $String):
%2 = alloc_stack $String
%5 = metatype $@thin String.Type
%6 = function_ref @empty_string : $@convention(method) (@thin String.Type) -> @owned String
%7 = apply %6(%5) : $@convention(method) (@thin String.Type) -> @owned String
store %7 to [init] %2 : $*String
%10 = function_ref @string_append : $@convention(method) (@guaranteed String, @inout String) -> ()
%11 = apply %10(%0, %2) : $@convention(method) (@guaranteed String, @inout String) -> ()
%12 = string_literal utf8 "a"
%13 = integer_literal $Builtin.Word, 1
%14 = integer_literal $Builtin.Int1, -1
%15 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%16 = apply %15(%12, %13, %14, %5) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%17 = apply %10(%16, %2) : $@convention(method) (@guaranteed String, @inout String) -> ()
destroy_value %16 : $String
%28 = load [take] %2 : $*String
dealloc_stack %2 : $*String
return %28 : $String
}
sil @unknown_modify : $@convention(thin) (@inout String) -> ()
// CHECK-LABEL: sil [ossa] @dont_optimize_modified_string
// CHECK: [[INIT:%[0-9]+]] = function_ref @empty_string
// CHECK: apply [[INIT]]
// CHECK: [[UNKNOWN:%[0-9]+]] = function_ref @unknown_modify
// CHECK: apply [[UNKNOWN]]
// CHECK: [[APPEND:%[0-9]+]] = function_ref @string_append
// CHECK: apply [[APPEND]]
// CHECK: } // end sil function 'dont_optimize_modified_string'
sil [ossa] @dont_optimize_modified_string : $@convention(thin) (@guaranteed String) -> @owned String {
bb0(%0 : @guaranteed $String):
%2 = alloc_stack $String
%5 = metatype $@thin String.Type
%6 = function_ref @empty_string : $@convention(method) (@thin String.Type) -> @owned String
%7 = apply %6(%5) : $@convention(method) (@thin String.Type) -> @owned String
store %7 to [init] %2 : $*String
%8 = function_ref @unknown_modify : $@convention(thin) (@inout String) -> ()
%9 = apply %8(%2) : $@convention(thin) (@inout String) -> ()
%14 = function_ref @string_append : $@convention(method) (@guaranteed String, @inout String) -> ()
%15 = apply %14(%0, %2) : $@convention(method) (@guaranteed String, @inout String) -> ()
%28 = load [take] %2 : $*String
dealloc_stack %2 : $*String
return %28 : $String
}
// CHECK-LABEL: sil [ossa] @concat_to_empty_string
// CHECK: bb0(%0 : @guaranteed $String):
// CHECK-NEXT: %1 = copy_value %0
// CHECK-NEXT: return %1
// CHECK: } // end sil function 'concat_to_empty_string'
sil [ossa] @concat_to_empty_string : $@convention(thin) (@guaranteed String) -> @owned String {
bb0(%0 : @guaranteed $String):
%5 = metatype $@thin String.Type
%6 = function_ref @empty_string : $@convention(method) (@thin String.Type) -> @owned String
%7 = apply %6(%5) : $@convention(method) (@thin String.Type) -> @owned String
%8 = function_ref @string_concat : $@convention(method) (@guaranteed String, @guaranteed String, @thin String.Type) -> @owned String
%9 = apply %8(%7, %0, %5) : $@convention(method) (@guaranteed String, @guaranteed String, @thin String.Type) -> @owned String
destroy_value %7
return %9 : $String
}
// CHECK-LABEL: sil [ossa] @concat_empty_string
// CHECK: bb0(%0 : @owned $String):
// CHECK-NEXT: return %0
// CHECK: } // end sil function 'concat_empty_string'
sil [ossa] @concat_empty_string : $@convention(thin) (@owned String) -> @owned String {
bb0(%0 : @owned $String):
%5 = metatype $@thin String.Type
%6 = function_ref @empty_string : $@convention(method) (@thin String.Type) -> @owned String
%7 = apply %6(%5) : $@convention(method) (@thin String.Type) -> @owned String
%8 = function_ref @string_concat : $@convention(method) (@guaranteed String, @guaranteed String, @thin String.Type) -> @owned String
%9 = apply %8(%0, %7, %5) : $@convention(method) (@guaranteed String, @guaranteed String, @thin String.Type) -> @owned String
destroy_value %7
destroy_value %0
return %9 : $String
}
// CHECK-LABEL: sil [ossa] @concat_constant_strings
// CHECK: [[STR:%[0-9]+]] = string_literal utf8 "a🙂"
// CHECK: [[LENGTH:%[0-9]+]] = integer_literal $Builtin.Word, 5
// CHECK: [[ASCII:%[0-9]+]] = integer_literal $Builtin.Int1, 0
// CHECK: [[MT:%[0-9]+]] = metatype $@thin String.Type
// CHECK: [[F:%[0-9]+]] = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC
// CHECK: [[A:%[0-9]+]] = apply [[F]]([[STR]], [[LENGTH]], [[ASCII]], [[MT]])
// CHECK: return [[A]]
// CHECK: } // end sil function 'concat_constant_strings'
sil [ossa] @concat_constant_strings : $@convention(thin) (@guaranteed String) -> @owned String {
bb0(%0 : @guaranteed $String):
%3 = string_literal utf8 "a"
%4 = integer_literal $Builtin.Word, 1
%5 = integer_literal $Builtin.Int1, -1
%6 = metatype $@thin String.Type
%7 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%8 = apply %7(%3, %4, %5, %6) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%9 = string_literal utf8 "🙂"
%10 = integer_literal $Builtin.Word, 4
%11 = apply %7(%9, %10, %5, %6) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%12 = function_ref @string_concat : $@convention(method) (@guaranteed String, @guaranteed String, @thin String.Type) -> @owned String
%13 = apply %12(%8, %11, %6) : $@convention(method) (@guaranteed String, @guaranteed String, @thin String.Type) -> @owned String
destroy_value %8
destroy_value %11
return %13 : $String
}
// CHECK-LABEL: sil @test_cstring
// CHECK: %0 = string_literal utf8 "a"
// CHECK: return %0
// CHECK: } // end sil function 'test_cstring'
sil @test_cstring : $@convention(thin) () -> Builtin.RawPointer {
bb0:
%3 = string_literal utf8 "a"
%4 = integer_literal $Builtin.Word, 1
%5 = integer_literal $Builtin.Int1, -1
%6 = metatype $@thin String.Type
%7 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%8 = apply %7(%3, %4, %5, %6) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%d = struct $DefaultStringInterpolation (%8 : $String)
%e = struct_extract %d : $DefaultStringInterpolation, #DefaultStringInterpolation._storage
%9 = function_ref @string_getUTF8CString : $@convention(method) (@guaranteed String) -> @owned ContiguousArray<Int8>
%10 = apply %9(%e) : $@convention(method) (@guaranteed String) -> @owned ContiguousArray<Int8>
%11 = struct_extract %10 : $ContiguousArray<Int8>, #ContiguousArray._buffer
%12 = struct_extract %11 : $_ContiguousArrayBuffer<Int8>, #_ContiguousArrayBuffer._storage
%13 = ref_tail_addr %12 : $__ContiguousArrayStorageBase, $Int8
%14 = address_to_pointer %13 : $*Int8 to $Builtin.RawPointer
return %14 : $Builtin.RawPointer
}
// CHECK-LABEL: sil @test_interpolated_cstring
// CHECK: apply
// CHECK: [[S:%[0-9]+]] = string_literal utf8 "a"
// CHECK: return [[S]]
// CHECK: } // end sil function 'test_interpolated_cstring'
sil @test_interpolated_cstring : $@convention(thin) () -> Builtin.RawPointer {
bb0:
%3 = string_literal utf8 "a"
%4 = integer_literal $Builtin.Word, 1
%5 = integer_literal $Builtin.Int1, -1
%6 = metatype $@thin String.Type
%7 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%8 = apply %7(%3, %4, %5, %6) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
%d = struct $DefaultStringInterpolation (%8 : $String)
%f = function_ref @$sSS19stringInterpolationSSs013DefaultStringB0V_tcfC : $@convention(method) (@owned DefaultStringInterpolation, @thin String.Type) -> @owned String
%a = apply %f(%d, %6) : $@convention(method) (@owned DefaultStringInterpolation, @thin String.Type) -> @owned String
%9 = function_ref @string_getUTF8CString : $@convention(method) (@guaranteed String) -> @owned ContiguousArray<Int8>
%10 = apply %9(%a) : $@convention(method) (@guaranteed String) -> @owned ContiguousArray<Int8>
%11 = struct_extract %10 : $ContiguousArray<Int8>, #ContiguousArray._buffer
%12 = struct_extract %11 : $_ContiguousArrayBuffer<Int8>, #_ContiguousArrayBuffer._storage
%13 = ref_tail_addr %12 : $__ContiguousArrayStorageBase, $Int8
%14 = address_to_pointer %13 : $*Int8 to $Builtin.RawPointer
return %14 : $Builtin.RawPointer
}
sil public_external [readonly] [ossa] @$sSS19stringInterpolationSSs013DefaultStringB0V_tcfC : $@convention(method) (@owned DefaultStringInterpolation, @thin String.Type) -> @owned String {
bb0(%0 : @owned $DefaultStringInterpolation, %1 : $@thin String.Type):
%2 = destructure_struct %0
return %2 : $String
}