Skip to content

Commit abc40b3

Browse files
committed
Optimizer: convert the EscapeInfoDumper from a pass to a test
1 parent 828813c commit abc40b3

File tree

9 files changed

+259
-170
lines changed

9 files changed

+259
-170
lines changed

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,6 @@ private func registerSwiftPasses() {
151151
registerPass(aliasInfoDumper, { aliasInfoDumper.run($0) })
152152
registerPass(functionUsesDumper, { functionUsesDumper.run($0) })
153153
registerPass(silPrinterPass, { silPrinterPass.run($0) })
154-
registerPass(escapeInfoDumper, { escapeInfoDumper.run($0) })
155-
registerPass(addressEscapeInfoDumper, { addressEscapeInfoDumper.run($0) })
156154
registerPass(accessDumper, { accessDumper.run($0) })
157155
registerPass(deadEndBlockDumper, { deadEndBlockDumper.run($0) })
158156
registerPass(memBehaviorDumper, { memBehaviorDumper.run($0) })

SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ swift_compiler_sources(Optimizer
1111
AccessDumper.swift
1212
AliasInfoDumper.swift
1313
DeadEndBlockDumper.swift
14-
EscapeInfoDumper.swift
1514
MemBehaviorDumper.swift
1615
SILPrinter.swift
1716
RangeDumper.swift

SwiftCompilerSources/Sources/Optimizer/TestPasses/EscapeInfoDumper.swift

Lines changed: 0 additions & 159 deletions
This file was deleted.

SwiftCompilerSources/Sources/Optimizer/Utilities/EscapeUtils.swift

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,3 +990,146 @@ private extension PartialApplyInst {
990990
}
991991
}
992992
}
993+
994+
//===--------------------------------------------------------------------===//
995+
// Tests
996+
//===--------------------------------------------------------------------===//
997+
998+
let escapeInfoTest = FunctionTest("escape_info") {
999+
function, arguments, context in
1000+
1001+
print("Escape information for \(function.name):")
1002+
1003+
struct Visitor : EscapeVisitorWithResult {
1004+
var result: Set<String> = Set()
1005+
1006+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
1007+
if operand.instruction is ReturnInstruction {
1008+
result.insert("return[\(path.projectionPath)]")
1009+
return .ignore
1010+
}
1011+
return .continueWalk
1012+
}
1013+
1014+
mutating func visitDef(def: Value, path: EscapePath) -> DefResult {
1015+
guard let arg = def as? FunctionArgument else {
1016+
return .continueWalkUp
1017+
}
1018+
result.insert("arg\(arg.index)[\(path.projectionPath)]")
1019+
return .walkDown
1020+
}
1021+
}
1022+
1023+
// Dump the EscapeInfo query results for all `alloc_ref` instructions in the function.
1024+
//
1025+
for inst in function.instructions {
1026+
if let allocRef = inst as? AllocRefInst {
1027+
1028+
let resultStr: String
1029+
if let result = allocRef.visit(using: Visitor(), context) {
1030+
if result.isEmpty {
1031+
resultStr = " - "
1032+
} else {
1033+
resultStr = Array(result).sorted().joined(separator: ",")
1034+
}
1035+
} else {
1036+
resultStr = "global"
1037+
}
1038+
print("\(resultStr): \(allocRef)")
1039+
}
1040+
}
1041+
print("End function \(function.name)\n")
1042+
}
1043+
1044+
let addressEscapeInfoTest = FunctionTest("address_escape_info") {
1045+
function, arguments, context in
1046+
1047+
// Dumps the EscapeInfo query results for addresses escaping to function calls.
1048+
// The `fix_lifetime` instruction is used as marker for addresses and values to query.
1049+
1050+
print("Address escape information for \(function.name):")
1051+
1052+
var valuesToCheck = [Value]()
1053+
var applies = [Instruction]()
1054+
1055+
for inst in function.instructions {
1056+
switch inst {
1057+
case let fli as FixLifetimeInst:
1058+
valuesToCheck.append(fli.operand.value)
1059+
case is FullApplySite:
1060+
applies.append(inst)
1061+
default:
1062+
break
1063+
}
1064+
}
1065+
1066+
struct Visitor : EscapeVisitor {
1067+
let apply: Instruction
1068+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
1069+
let user = operand.instruction
1070+
if user == apply {
1071+
return .abort
1072+
}
1073+
if user is ReturnInstruction {
1074+
// Anything which is returned cannot escape to an instruction inside the function.
1075+
return .ignore
1076+
}
1077+
return .continueWalk
1078+
}
1079+
1080+
var followTrivialTypes: Bool { true }
1081+
var followLoads: Bool { false }
1082+
}
1083+
1084+
// test `isEscaping(addressesOf:)`
1085+
for value in valuesToCheck {
1086+
print("value:\(value)")
1087+
for apply in applies {
1088+
if value.allContainedAddresses.isEscaping(using: Visitor(apply: apply), context) {
1089+
print(" ==> \(apply)")
1090+
} else {
1091+
print(" - \(apply)")
1092+
}
1093+
}
1094+
}
1095+
1096+
// test `canReferenceSameField` for each pair of `fix_lifetime`.
1097+
if !valuesToCheck.isEmpty {
1098+
for lhsIdx in 0..<(valuesToCheck.count - 1) {
1099+
for rhsIdx in (lhsIdx + 1) ..< valuesToCheck.count {
1100+
print("pair \(lhsIdx) - \(rhsIdx)")
1101+
let lhs = valuesToCheck[lhsIdx]
1102+
let rhs = valuesToCheck[rhsIdx]
1103+
print(lhs)
1104+
print(rhs)
1105+
1106+
let projLhs = lhs.allContainedAddresses
1107+
let projRhs = rhs.allContainedAddresses
1108+
let mayAlias = projLhs.canAddressAlias(with: projRhs, context)
1109+
if mayAlias != projRhs.canAddressAlias(with: projLhs, context) {
1110+
fatalError("canAddressAlias(with:) must be symmetric")
1111+
}
1112+
1113+
let addrReachable: Bool
1114+
if lhs.type.isAddress && !rhs.type.isAddress {
1115+
let anythingReachableFromRhs = rhs.at(SmallProjectionPath(.anything))
1116+
addrReachable = projLhs.canAddressAlias(with: anythingReachableFromRhs, context)
1117+
if mayAlias && !addrReachable {
1118+
fatalError("mayAlias implies addrReachable")
1119+
}
1120+
} else {
1121+
addrReachable = false
1122+
}
1123+
if mayAlias {
1124+
print("may alias")
1125+
} else if addrReachable {
1126+
print("address reachable but no alias")
1127+
} else {
1128+
print("no alias")
1129+
}
1130+
}
1131+
}
1132+
}
1133+
1134+
print("End function \(function.name)\n")
1135+
}

SwiftCompilerSources/Sources/Optimizer/Utilities/FunctionTest.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ public func registerOptimizerTests() {
5252
localVariableReachingAssignmentsTest,
5353
rangeOverlapsPathTest,
5454
variableIntroducerTest,
55-
destroyBarrierTest
55+
destroyBarrierTest,
56+
escapeInfoTest,
57+
addressEscapeInfoTest
5658
)
5759

5860
// Finally register the thunk they all call through.

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,6 @@ PASS(DeadEndBlockDumper, "dump-deadendblocks",
7777
"Tests the DeadEndBlocks utility")
7878
PASS(EmbeddedWitnessCallSpecialization, "embedded-witness-call-specialization",
7979
"Mandatory witness method call specialization")
80-
PASS(EscapeInfoDumper, "dump-escape-info",
81-
"Dumps escape information")
82-
PASS(AddressEscapeInfoDumper, "dump-addr-escape-info",
83-
"Dumps address escape information")
8480
PASS(AccessDumper, "dump-access",
8581
"Dump access information")
8682
PASS(ConstantCapturePropagation, "constant-capture-propagation",

0 commit comments

Comments
 (0)