mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
* access * accessed * accesses * accessor * acquiring * across * activated * additive * address * addresses' * aggregated * analysis * and * appropriately * archetype * argument * associated * availability * barriers * because * been * beginning * belongs * beneficial * blocks * borrow * builtin * cannot * canonical * canonicalize * clazz * cleanup * coalesceable * coalesced * comparisons * completely * component * computed * concrete * conjunction * conservatively * constituent * construct * consuming * containing * covered * creates * critical * dataflow * declaration * defined * defining * definition * deinitialization * deliberately * dependencies * dependent * deserialized * destroy * deterministic * deterministically * devirtualizes * diagnostic * diagnostics * differentiation * disable * discipline * dominate * dominates * don't * element * eliminate * eliminating * elimination * embedded * encounter * epilogue * epsilon * escape * escaping * essential * evaluating * evaluation * evaluator * executing * existential * existentials * explicit * expression * extended * extension * extract * for * from * function * generic * guarantee * guaranteed * happened * heuristic * however * identifiable * immediately * implementation * improper * include * infinite * initialize * initialized * initializer * inside * instruction * interference * interferes * interleaved * internal * intersection * intractable * intrinsic * invalidates * irreducible * irrelevant * language * lifetime * literal * looks * materialize * meaning * mergeable * might * mimics * modification * modifies * multiple * mutating * necessarily * necessary * needsmultiplecopies * nonetheless * nothing * occurred * occurs * optimization * optimizing * original * outside * overflow * overlapping * overridden * owned * ownership * parallel * parameter * paths * patterns * pipeline * plottable * possible * potentially * practically * preamble * precede * preceding * predecessor * preferable * preparation * probably * projection * properties * property * protocol * reabstraction * reachable * recognized * recursive * recursively * redundant * reentrancy * referenced * registry * reinitialization * reload * represent * requires * response * responsible * retrieving * returned * returning * returns * rewriting * rewritten * sample * scenarios * scope * should * sideeffects * similar * simplify * simplifycfg * somewhat * spaghetti * specialization * specializations * specialized * specially * statistically * substitute * substitution * succeeds * successful * successfully * successor * superfluous * surprisingly * suspension * swift * targeted * that * that our * the * therefore * this * those * threshold * through * transform * transformation * truncated * ultimate * unchecked * uninitialized * unlikely * unmanaged * unoptimized key * updataflow * usefulness * utilities * villain * whenever * writes Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
112 lines
4.9 KiB
Plaintext
112 lines
4.9 KiB
Plaintext
// RUN: %target-sil-opt -access-enforcement-opts -debug-only=access-enforcement-opts -verify %s -o /dev/null 2>&1 | %FileCheck %s
|
|
//
|
|
// REQUIRES: asserts
|
|
//
|
|
// This tests four kinds of AccessEnforcementOpts fast paths:
|
|
//
|
|
// 1. During identifyAccess, determine if there are either any
|
|
// identical accesses or an accesses that aren't already marked
|
|
// no_nested_storage. If there are neither, then skip the subsequent
|
|
// data flow analysis.
|
|
//
|
|
// 2. In StorageSet, indicate whether identical storage was seen
|
|
// elsewhere in the function. During dataflow, only add an access to
|
|
// the out-of-scope access set if was marked as having identical
|
|
// storage with another access.
|
|
//
|
|
// 3. If no access pairs can be merged, avoid analyzing SCC regions in
|
|
// the control flow graph.
|
|
//
|
|
// 4. During data flow, don't track in scope conflicts for
|
|
// instructions already marked [no_nested_conflict].
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
import SwiftShims
|
|
|
|
public class TestEarlyBail {
|
|
@_hasStorage var prop1: Int { get set }
|
|
@_hasStorage var prop2: Int { get set }
|
|
}
|
|
|
|
// All accesses are no_nested_conflict, and none are identical. Bail.
|
|
// (1) Skipping AccessConflictAndMergeAnalysis...
|
|
//
|
|
// CHECK-LABEL: Running local AccessEnforcementOpts on testEarlyBail
|
|
// CHECK-NOT: Processing
|
|
// CHECK-NOT: No conflict on one path
|
|
// CHECK-NOT: Folding
|
|
// CHECK-NOT: Merging
|
|
// CHECK: Skipping AccessConflictAndMergeAnalysis...
|
|
sil @testEarlyBail : $@convention(method) (@owned TestEarlyBail) -> @owned TestEarlyBail {
|
|
bb0(%0 : $TestEarlyBail):
|
|
%adr1 = ref_element_addr %0 : $TestEarlyBail, #TestEarlyBail.prop1
|
|
%a1 = begin_access [modify] [dynamic] [no_nested_conflict] %adr1 : $*Int
|
|
%v1 = load %a1 : $*Int
|
|
end_access %a1 : $*Int
|
|
%adr2 = ref_element_addr %0 : $TestEarlyBail, #TestEarlyBail.prop2
|
|
%a2 = begin_access [modify] [dynamic] [no_nested_conflict] %adr2 : $*Int
|
|
%v2 = load %a2 : $*Int
|
|
end_access %a2 : $*Int
|
|
return %0 : $TestEarlyBail
|
|
}
|
|
|
|
// An access is not marked no_nested_conflict. Need to run analysis.
|
|
// NOT (1) Skipping AccessConflictAndMergeAnalysis...
|
|
// (2) Ignoring unique access...
|
|
// (3) Skipping SCC analysis...
|
|
//
|
|
// CHECK-LABEL: Running local AccessEnforcementOpts on testEarlyBailNeedsFolding
|
|
// CHECK: Processing Function: testEarlyBailNeedsFolding
|
|
// CHECK: No conflict on one path from [[ACCESS:%.*]] = begin_access [modify] [dynamic] %{{.*}} : $*Int
|
|
// CHECK-NEXT: to end_access [[ACCESS]] : $*Int
|
|
// CHECK: Ignoring unmergeable access: [[ACCESS]] = begin_access [modify] [dynamic] %{{.*}} : $*Int
|
|
// CHECK: Folding [[ACCESS]] = begin_access [modify] [dynamic] [no_nested_conflict] %{{.*}} : $*Int
|
|
// CHECK: Skipping SCC Analysis...
|
|
sil @testEarlyBailNeedsFolding : $@convention(method) (@owned TestEarlyBail) -> @owned TestEarlyBail {
|
|
bb0(%0 : $TestEarlyBail):
|
|
%adr1 = ref_element_addr %0 : $TestEarlyBail, #TestEarlyBail.prop1
|
|
%a1 = begin_access [modify] [dynamic] %adr1 : $*Int
|
|
%v1 = load %a1 : $*Int
|
|
end_access %a1 : $*Int
|
|
return %0 : $TestEarlyBail
|
|
}
|
|
|
|
// Two accesses have the same storage. Need to run analysis.
|
|
// NOT (1) Skipping AccessConflictAndMergeAnalysis...
|
|
// NOT (2) Ignoring unique access...
|
|
// (4) No Conflict On Path
|
|
// (4) NOT No Conflict On Path
|
|
// NOT (3) Skipping SCC analysis...
|
|
//
|
|
// CHECK-LABEL: Running local AccessEnforcementOpts on testEarlyBailMayMerge
|
|
// CHECK: Processing Function: testEarlyBailMayMerge
|
|
// CHECK: No conflict on one path from [[ACCESS1:%.*]] = begin_access [modify] [dynamic] %{{.*}} : $*Int
|
|
// CHECK: to end_access [[ACCESS1]] : $*Int
|
|
// CHECK: Found mergeable pair: [[ACCESS1]] = begin_access [modify] [dynamic] %{{.*}} : $*Int
|
|
// CHECK-NEXT: with [[ACCESS2:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] %{{.*}} : $*Int
|
|
// CHECK-NOT: No conflict on one path from [[ACCESS2]]
|
|
// CHECK: Ignoring unmergeable access: [[ACCESS2]] = begin_access [modify] [dynamic] [no_nested_conflict] %{{.*}} : $*Int
|
|
// CHECK-NOT: No conflict on one path from [[ACCESS2]]
|
|
//
|
|
// Note: The order that accesses with no nested conflicts are "Folded" is nondeterministic.
|
|
// CHECK-DAG: Folding [[ACCESS1]] = begin_access [modify] [dynamic] [no_nested_conflict] %{{.*}} : $*Int
|
|
// CHECK-DAG: Folding [[ACCESS2]] = begin_access [modify] [dynamic] [no_nested_conflict] %{{.*}} : $*Int
|
|
// CHECK: Merging [[ACCESS2]] = begin_access [modify] [dynamic] [no_nested_conflict] %{{.*}} : $*Int
|
|
// CHECK-NEXT: into [[ACCESS1]] = begin_access [modify] [dynamic] [no_nested_conflict] %{{.*}} : $*Int
|
|
// CHECK-NOT: Skipping SCC Analysis...
|
|
sil @testEarlyBailMayMerge : $@convention(method) (@owned TestEarlyBail) -> @owned TestEarlyBail {
|
|
bb0(%0 : $TestEarlyBail):
|
|
%adr1 = ref_element_addr %0 : $TestEarlyBail, #TestEarlyBail.prop1
|
|
%a1 = begin_access [modify] [dynamic] %adr1 : $*Int
|
|
%v1 = load %a1 : $*Int
|
|
end_access %a1 : $*Int
|
|
%adr2 = ref_element_addr %0 : $TestEarlyBail, #TestEarlyBail.prop1
|
|
%a2 = begin_access [modify] [dynamic] [no_nested_conflict] %adr2 : $*Int
|
|
%v2 = load %a2 : $*Int
|
|
end_access %a2 : $*Int
|
|
return %0 : $TestEarlyBail
|
|
}
|