mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
It eliminates dead access scopes if they are not conflicting with other scopes. Removes: ``` %2 = begin_access [modify] [dynamic] %1 ... // no uses of %2 end_access %2 ``` However, dead _conflicting_ access scopes are not removed. If a conflicting scope becomes dead because an optimization e.g. removed a load, it is still important to get an access violation at runtime. Even a propagated value of a redundant load from a conflicting scope is undefined. ``` %2 = begin_access [modify] [dynamic] %1 store %x to %2 %3 = begin_access [read] [dynamic] %1 // conflicting with %2! %y = load %3 end_access %3 end_access %2 use(%y) ``` After redundant-load-elimination: ``` %2 = begin_access [modify] [dynamic] %1 store %x to %2 %3 = begin_access [read] [dynamic] %1 // now dead, but still conflicting with %2 end_access %3 end_access %2 use(%x) // propagated from the store, but undefined here! ``` In this case the scope `%3` is not removed because it's important to get an access violation error at runtime before the undefined value `%x` is used. This pass considers potential conflicting access scopes in called functions. But it does not consider potential conflicting access in callers (because it can't!). However, optimizations, like redundant-load-elimination, can only do such transformations if the outer access scope is within the function, e.g. ``` bb0(%0 : $*T): // an inout from a conflicting scope in the caller store %x to %0 %3 = begin_access [read] [dynamic] %1 %y = load %3 // cannot be propagated because it cannot be proved that %1 is the same address as %0 end_access %3 ``` All those checks are only done for dynamic access scopes, because they matter for runtime exclusivity checking. Dead static scopes are removed unconditionally.
9.7 KiB
9.7 KiB