diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp index 12cb54a377583..a3728472809cd 100644 --- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp +++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp @@ -2312,6 +2312,19 @@ void LifetimeChecker::handleSelfInitUse(unsigned UseID) { } } +// In case of `var` initializations, SILGen creates a dynamic begin/end_access +// pair around the initialization store. If it's an initialization (and not +// a re-assign) it's guaranteed that it's an exclusive access and we can +// convert the access to an `[init] [static]` access. +static void setStaticInitAccess(SILValue memoryAddress) { + if (auto *ba = dyn_cast(memoryAddress)) { + if (ba->getEnforcement() == SILAccessEnforcement::Dynamic) { + ba->setEnforcement(SILAccessEnforcement::Static); + if (ba->getAccessKind() == SILAccessKind::Modify) + ba->setAccessKind(SILAccessKind::Init); + } + } +} /// updateInstructionForInitState - When an instruction being analyzed moves /// from being InitOrAssign to some concrete state, update it for that state. @@ -2336,6 +2349,8 @@ void LifetimeChecker::updateInstructionForInitState(unsigned UseID) { assert(!CA->isInitializationOfDest() && "should not modify copy_addr that already knows it is initialized"); CA->setIsInitializationOfDest(InitKind); + if (InitKind == IsInitialization) + setStaticInitAccess(CA->getDest()); return; } @@ -2382,6 +2397,7 @@ void LifetimeChecker::updateInstructionForInitState(unsigned UseID) { MarkMustCheckInst::CheckKind::InitableButNotConsumable); } } + setStaticInitAccess(AI->getDest()); } return; diff --git a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp index ce64569b4247d..03f3c88746186 100644 --- a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp @@ -280,6 +280,9 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts, if (isa(Inst)) return true; + if (isa(Inst) || isa(Inst)) + return true; + // If Inst does not read or write to memory, have side effects, and is not a // terminator, we can zap it. if (!Inst->mayHaveSideEffects() && !Inst->mayReadFromMemory() && diff --git a/test/Concurrency/default_actor_definit.swift b/test/Concurrency/default_actor_definit.swift index 229c7db8e52e8..e97966abfb395 100644 --- a/test/Concurrency/default_actor_definit.swift +++ b/test/Concurrency/default_actor_definit.swift @@ -40,7 +40,7 @@ actor C { // CHECK-LABEL: sil hidden @$s21default_actor_definit1CC1yACSgSi_tcfc // CHECK: builtin "initializeDefaultActor"(%1 : $C) // CHECK: [[X:%.*]] = ref_element_addr %1 : $C, #C.x -// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[X]] : $*String +// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [init] [static] [[X]] : $*String // CHECK-NEXT: store {{.*}} to [[ACCESS]] : $*String // CHECK-NEXT: end_access [[ACCESS]] : $*String // CHECK: cond_br {{%.*}}, bb1, bb2 diff --git a/test/SILOptimizer/dead_alloc_elim.sil b/test/SILOptimizer/dead_alloc_elim.sil index ef79c5fb69715..de4f3d66a8cff 100644 --- a/test/SILOptimizer/dead_alloc_elim.sil +++ b/test/SILOptimizer/dead_alloc_elim.sil @@ -127,7 +127,9 @@ sil @store_to_trivial_property : $@convention(thin) (Int) -> () { bb0(%0 : $Int): %20 = alloc_ref [stack] $NontrivialDestructor %21 = ref_element_addr %20 : $NontrivialDestructor, #NontrivialDestructor.i - store %0 to %21 : $*Int + %22 = begin_access [modify] [dynamic] %21 : $*Int + store %0 to %22 : $*Int + end_access %22 : $*Int set_deallocating %20 : $NontrivialDestructor dealloc_ref %20 : $NontrivialDestructor dealloc_stack_ref %20 : $NontrivialDestructor diff --git a/test/SILOptimizer/default-cmo.swift b/test/SILOptimizer/default-cmo.swift index 9f5f6301cc57a..bc603778696b8 100644 --- a/test/SILOptimizer/default-cmo.swift +++ b/test/SILOptimizer/default-cmo.swift @@ -80,9 +80,8 @@ public func getSubmoduleKlassMember() -> Int { } // CHECK-LABEL: sil @$s4Main26getSubmoduleKlassMemberTBDSiyF -// CHECK: [[F:%[0-9]+]] = function_ref @$s9ModuleTBD20submoduleKlassMemberSiyF -// CHECK: [[I:%[0-9]+]] = apply [[F]] -// CHECK: return [[I]] +// CHECK-NOT: function_ref +// CHECK-NOT: apply // CHECK: } // end sil function '$s4Main26getSubmoduleKlassMemberTBDSiyF' public func getSubmoduleKlassMemberTBD() -> Int { return ModuleTBD.submoduleKlassMember() diff --git a/test/SILOptimizer/definite_init_actor.swift b/test/SILOptimizer/definite_init_actor.swift index 1bd896baf5d96..c38418192749c 100644 --- a/test/SILOptimizer/definite_init_actor.swift +++ b/test/SILOptimizer/definite_init_actor.swift @@ -83,7 +83,7 @@ actor BoringActor { // CHECK-LABEL: sil hidden @$s4test14SingleVarActorC10iterationsACSi_tYacfc : $@convention(method) @async (Int, @owned SingleVarActor) -> @owned SingleVarActor { // CHECK: bb0({{%[0-9]+}} : $Int, [[SELF:%[0-9]+]] : $SingleVarActor): // CHECK: [[MYVAR_REF:%[0-9]+]] = ref_element_addr [[SELF]] : $SingleVarActor, #SingleVarActor.myVar - // CHECK: [[MYVAR:%[0-9]+]] = begin_access [modify] [dynamic] [[MYVAR_REF]] : $*Int + // CHECK: [[MYVAR:%[0-9]+]] = begin_access [init] [static] [[MYVAR_REF]] : $*Int // CHECK: store {{%[0-9]+}} to [[MYVAR]] : $*Int // CHECK-NEXT: end_access [[MYVAR]] // CHECK-NEXT: hop_to_executor [[SELF]] : $SingleVarActor @@ -196,7 +196,7 @@ actor MultiVarActor { // CHECK-LABEL: sil hidden @$s4test13MultiVarActorC10doNotThrowACSb_tYaKcfc : $@convention(method) @async (Bool, @owned MultiVarActor) -> (@owned MultiVarActor, @error any Error) { // CHECK: bb0({{%[0-9]+}} : $Bool, [[SELF:%[0-9]+]] : $MultiVarActor): // CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MultiVarActor, #MultiVarActor.firstVar - // CHECK: [[VAR:%[0-9]+]] = begin_access [modify] [dynamic] [[REF]] : $*Int + // CHECK: [[VAR:%[0-9]+]] = begin_access [init] [static] [[REF]] : $*Int // CHECK: store {{%[0-9]+}} to [[VAR]] : $*Int // CHECK-NEXT: end_access [[VAR]] // CHECK-NEXT: hop_to_executor %1 : $MultiVarActor diff --git a/test/SILOptimizer/definite_init_failable_initializers.swift b/test/SILOptimizer/definite_init_failable_initializers.swift index c67337128bcf4..f46bedebb8626 100644 --- a/test/SILOptimizer/definite_init_failable_initializers.swift +++ b/test/SILOptimizer/definite_init_failable_initializers.swift @@ -735,7 +735,7 @@ class FailableBaseClass { // CHECK: bb0(%0 : $FailableBaseClass): // CHECK: [[CANARY:%.*]] = apply // CHECK-NEXT: [[MEMBER_ADDR:%.*]] = ref_element_addr %0 -// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[MEMBER_ADDR]] : $*Canary +// CHECK-NEXT: [[WRITE:%.*]] = begin_access [init] [static] [[MEMBER_ADDR]] : $*Canary // CHECK-NEXT: store [[CANARY]] to [[WRITE]] // CHECK-NEXT: end_access [[WRITE]] : $*Canary // CHECK-NEXT: strong_release %0 @@ -849,7 +849,7 @@ class FailableDerivedClass : FailableBaseClass { // CHECK: [[CANARY_FUN:%.*]] = function_ref @$s35definite_init_failable_initializers6CanaryCACycfC : // CHECK: [[CANARY:%.*]] = apply [[CANARY_FUN]]( // CHECK-NEXT: [[MEMBER_ADDR:%.*]] = ref_element_addr [[SELF]] -// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[MEMBER_ADDR]] : $*Canary +// CHECK-NEXT: [[WRITE:%.*]] = begin_access [init] [static] [[MEMBER_ADDR]] : $*Canary // CHECK-NEXT: store [[CANARY]] to [[WRITE]] // CHECK-NEXT: end_access [[WRITE]] : $*Canary // CHECK-NEXT: strong_release [[SELF]] diff --git a/test/SILOptimizer/definite_init_markuninitialized_rootself.sil b/test/SILOptimizer/definite_init_markuninitialized_rootself.sil index 59b0497c3df12..887ee879647f5 100644 --- a/test/SILOptimizer/definite_init_markuninitialized_rootself.sil +++ b/test/SILOptimizer/definite_init_markuninitialized_rootself.sil @@ -21,6 +21,17 @@ class RootClassWithNontrivialStoredProperties { } class SomeClass {} + +final class IntClass { + var i: Int + init(_ i: Int) +} + +final class GenericClass { + var t: T + init(_ t: T) +} + sil @getSomeClass : $@convention(thin) () -> @owned SomeClass sil @getSomeOptionalClass : $@convention(thin) () -> Optional @@ -131,3 +142,45 @@ bb0(%0 : @owned $RootClassWithNontrivialStoredProperties): %13 = tuple () return %13 : $() } + +// CHECK-LABEL: sil [ossa] @init_IntClass : +// CHECK: [[ACCESS:%.*]] = begin_access [init] [static] +// CHECK: store %0 to [trivial] [[ACCESS]] +// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [dynamic] +// CHECK: store %0 to [trivial] [[ACCESS2]] +// CHECK: } // end sil function 'init_IntClass' +sil [ossa] @init_IntClass : $@convention(method) (Int, @owned IntClass) -> @owned IntClass { +bb0(%0 : $Int, %1 : @owned $IntClass): + %4 = mark_uninitialized [rootself] %1 : $IntClass + %5 = begin_borrow %4 : $IntClass + %6 = ref_element_addr %5 : $IntClass, #IntClass.i + %7 = begin_access [modify] [dynamic] %6 : $*Int + assign %0 to %7 : $*Int + end_access %7 : $*Int + %10 = begin_access [modify] [dynamic] %6 : $*Int + assign %0 to %10 : $*Int + end_access %10 : $*Int + end_borrow %5 : $IntClass + return %4 : $IntClass +} + +// CHECK-LABEL: sil [ossa] @init_GenericClass : +// CHECK: [[ACCESS:%.*]] = begin_access [init] [static] +// CHECK: copy_addr %0 to [init] [[ACCESS]] +// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [dynamic] +// CHECK: copy_addr [take] %0 to [[ACCESS2]] +// CHECK: } // end sil function 'init_GenericClass' +sil [ossa] @init_GenericClass : $@convention(method) (@in T, @owned GenericClass) -> @owned GenericClass { +bb0(%0 : $*T, %1 : @owned $GenericClass): + %4 = mark_uninitialized [rootself] %1 : $GenericClass + %5 = begin_borrow %4 : $GenericClass + %8 = ref_element_addr %5 : $GenericClass, #GenericClass.t + %9 = begin_access [modify] [dynamic] %8 : $*T + copy_addr %0 to %9 : $*T + end_access %9 : $*T + %12 = begin_access [modify] [dynamic] %8 : $*T + copy_addr [take] %0 to %12 : $*T + end_access %12 : $*T + end_borrow %5 : $GenericClass + return %4 : $GenericClass +} diff --git a/test/SILOptimizer/definite_init_root_class.swift b/test/SILOptimizer/definite_init_root_class.swift index 0e19405bd7868..75132ca6811ac 100644 --- a/test/SILOptimizer/definite_init_root_class.swift +++ b/test/SILOptimizer/definite_init_root_class.swift @@ -31,7 +31,7 @@ class FirstClass { // CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[X_ADDR:%.*]] = ref_element_addr %1 : $FirstClass, #FirstClass.x - // CHECK: [[X_ACCESS:%.*]] = begin_access [modify] [dynamic] %15 : $*OtherClass + // CHECK: [[X_ACCESS:%.*]] = begin_access [init] [static] %15 : $*OtherClass // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int1, -1 // CHECK: store [[ONE]] to [[CONTROL]] : $*Builtin.Int1 // CHECK: store [[OTHER]] to [[X_ACCESS]] : $*OtherClass @@ -115,7 +115,7 @@ class SecondClass { // CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[X_ADDR:%.*]] = ref_element_addr %1 : $SecondClass, #SecondClass.x - // CHECK: [[X_ACCESS:%.*]] = begin_access [modify] [dynamic] [[X_ADDR]] : $*OtherClass + // CHECK: [[X_ACCESS:%.*]] = begin_access [init] [static] [[X_ADDR]] : $*OtherClass // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int2, 1 // CHECK: store [[ONE]] to [[CONTROL]] : $*Builtin.Int2 // CHECK: store [[OTHER]] to [[X_ACCESS]] : $*OtherClass @@ -138,7 +138,7 @@ class SecondClass { // CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[Y_ADDR:%.*]] = ref_element_addr %1 : $SecondClass, #SecondClass.y - // CHECK: [[Y_ACCESS:%.*]] = begin_access [modify] [dynamic] [[Y_ADDR]] : $*OtherClass + // CHECK: [[Y_ACCESS:%.*]] = begin_access [init] [static] [[Y_ADDR]] : $*OtherClass // CHECK: [[THREE:%.*]] = integer_literal $Builtin.Int2, -1 // CHECK: store [[THREE]] to [[CONTROL]] : $*Builtin.Int2 // CHECK: store [[OTHER]] to [[Y_ACCESS]] : $*OtherClass diff --git a/test/SILOptimizer/devirt_speculative_init.swift b/test/SILOptimizer/devirt_speculative_init.swift index bf5034f37c843..f607a81a92251 100644 --- a/test/SILOptimizer/devirt_speculative_init.swift +++ b/test/SILOptimizer/devirt_speculative_init.swift @@ -20,17 +20,17 @@ public class BigCat : Cat { } } -public func make(type: Cat.Type, cats: Int) { - type.init(cats: cats) +public func make(type: Cat.Type, cats: Int) -> Cat { + return type.init(cats: cats) } -// CHECK-LABEL: sil @$s23devirt_speculative_init4make4type4catsyAA3CatCm_SitF : $@convention(thin) (@thick Cat.Type, Int) -> () +// CHECK-LABEL: sil @$s23devirt_speculative_init4make4type4catsAA3CatCAFm_SitF : $@convention(thin) (@thick Cat.Type, Int) -> @owned Cat { // CHECK: checked_cast_br [exact] %0 : $@thick Cat.Type to @thick Cat.Type, bb2, bb3 -// CHECK: bb1: +// CHECK: bb1{{.*}}: // CHECK: return // CHECK: bb2({{%.*}} : $@thick Cat.Type): -// CHECK: alloc_ref [stack] $Cat +// CHECK: alloc_ref $Cat // CHECK: br bb1 // CHECK: bb3: -// CHECK: alloc_ref [stack] $BigCat +// CHECK: alloc_ref $BigCat // CHECK: br bb1 diff --git a/test/SILOptimizer/merge_exclusivity.swift b/test/SILOptimizer/merge_exclusivity.swift index 2dbbaa50d31cc..95442cd3c6fa0 100644 --- a/test/SILOptimizer/merge_exclusivity.swift +++ b/test/SILOptimizer/merge_exclusivity.swift @@ -377,8 +377,7 @@ private struct EscapedTransform: WriteProt { // TESTSIL-LABEL: sil [noinline] @$s17merge_exclusivity14run_MergeTest9yySiF : $@convention(thin) // TESTSIL: [[REFADDR:%.*]] = ref_element_addr {{.*}} : $StreamClass, #StreamClass.buffer -// TESTSIL-NEXT: [[B1:%.*]] = begin_access [modify] [{{.*}}] [no_nested_conflict] [[REFADDR]] -// TESTSIL: end_access [[B1]] +// TESTSIL-NEXT: store {{.*}} to [[REFADDR]] // TESTSIL: [[BCONF:%.*]] = begin_access [modify] [{{.*}}] [[REFADDR]] // TESTSIL: end_access [[BCONF]] // TESTSIL: [[BCONF:%.*]] = begin_access [modify] [{{.*}}] [[REFADDR]] diff --git a/test/sil-func-extractor/basic.swift b/test/sil-func-extractor/basic.swift index e60a995da7b73..536a61cc0c13b 100644 --- a/test/sil-func-extractor/basic.swift +++ b/test/sil-func-extractor/basic.swift @@ -46,7 +46,7 @@ // EXTRACT-INIT-LABEL: sil @$s5basic7VehicleC1nACSi_tcfc : $@convention(method) (Int, @owned Vehicle) -> @owned Vehicle { // EXTRACT-INIT: bb0 // EXTRACT-INIT-NEXT: ref_element_addr -// EXTRACT-INIT-NEXT: begin_access [modify] [dynamic] +// EXTRACT-INIT-NEXT: begin_access [init] [static] // EXTRACT-INIT-NEXT: store // EXTRACT-INIT-NEXT: end_access // EXTRACT-INIT-NEXT: return