diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift index c293c830654e5..fa478ddce641f 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift @@ -150,7 +150,6 @@ private func registerSwiftPasses() { registerPass(deadEndBlockDumper, { deadEndBlockDumper.run($0) }) registerPass(memBehaviorDumper, { memBehaviorDumper.run($0) }) registerPass(rangeDumper, { rangeDumper.run($0) }) - registerPass(runUnitTests, { runUnitTests.run($0) }) registerPass(testInstructionIteration, { testInstructionIteration.run($0) }) registerPass(updateBorrowedFromPass, { updateBorrowedFromPass.run($0) }) } diff --git a/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt b/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt index 45bfb439833ad..2aed2909f8708 100644 --- a/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt @@ -15,7 +15,6 @@ swift_compiler_sources(Optimizer MemBehaviorDumper.swift SILPrinter.swift RangeDumper.swift - RunUnitTests.swift UpdateBorrowedFrom.swift TestInstructionIteration.swift ) diff --git a/SwiftCompilerSources/Sources/Optimizer/TestPasses/RunUnitTests.swift b/SwiftCompilerSources/Sources/Optimizer/TestPasses/RunUnitTests.swift deleted file mode 100644 index 9e995aba5a300..0000000000000 --- a/SwiftCompilerSources/Sources/Optimizer/TestPasses/RunUnitTests.swift +++ /dev/null @@ -1,24 +0,0 @@ -//===--- UnitTests.swift - A pseudo pass for running the unit tests -------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -import SIL - -/// This pass should only be used by sil-opt to run all the unit tests. -/// -let runUnitTests = ModulePass(name: "run-unit-tests") { - (context: ModulePassContext) in - - print("--- Run unit tests ---") - - print("test ProjectionPath") - SmallProjectionPath.runUnitTests() -} diff --git a/SwiftCompilerSources/Sources/SIL/Utilities/SmallProjectionPath.swift b/SwiftCompilerSources/Sources/SIL/Utilities/SmallProjectionPath.swift index a6c9ed7156e39..0020e561ecd5a 100644 --- a/SwiftCompilerSources/Sources/SIL/Utilities/SmallProjectionPath.swift +++ b/SwiftCompilerSources/Sources/SIL/Utilities/SmallProjectionPath.swift @@ -680,308 +680,307 @@ extension StringParser { // Unit Tests //===----------------------------------------------------------------------===// -extension SmallProjectionPath { - public static func runUnitTests() { - - basicPushPop() - parsing() - merging() - subtracting() - matching() - overlapping() - predicates() - path2path() - indexedElements() - - func basicPushPop() { - let p1 = SmallProjectionPath(.structField, index: 3) - .push(.classField, index: 12345678) - let (k2, i2, p2) = p1.pop() - assert(k2 == .classField && i2 == 12345678) - let (k3, i3, p3) = p2.pop() - assert(k3 == .structField && i3 == 3) - assert(p3.isEmpty) - let (k4, i4, _) = p2.push(.enumCase, index: 876).pop() - assert(k4 == .enumCase && i4 == 876) - let p5 = SmallProjectionPath(.anything) - assert(p5.pop().path.isEmpty) - let p6 = SmallProjectionPath(.indexedElement, index: 1).push(.indexedElement, index: 2) - let (k6, i6, p7) = p6.pop() - assert(k6 == .indexedElement && i6 == 3 && p7.isEmpty) - let p8 = SmallProjectionPath(.indexedElement, index: 0) - assert(p8.isEmpty) - let p9 = SmallProjectionPath(.indexedElement, index: 1).push(.anyIndexedElement) - let (k9, i9, p10) = p9.pop() - assert(k9 == .anyIndexedElement && i9 == 0 && p10.isEmpty) - let p11 = SmallProjectionPath(.anyIndexedElement).push(.indexedElement, index: 1) - let (k11, i11, p12) = p11.pop() - assert(k11 == .anyIndexedElement && i11 == 0 && p12.isEmpty) - } - - func parsing() { - testParse("v**.c*", expect: SmallProjectionPath(.anyClassField) - .push(.anyValueFields)) - testParse("s3.c*.v**.s1", expect: SmallProjectionPath(.structField, index: 1) - .push(.anyValueFields) - .push(.anyClassField) - .push(.structField, index: 3)) - testParse("2.c*.e6.ct.**", expect: SmallProjectionPath(.anything) - .push(.tailElements) - .push(.enumCase, index: 6) - .push(.anyClassField) - .push(.tupleField, index: 2)) - testParse("i3.x.b.i*", expect: SmallProjectionPath(.anyIndexedElement) - .push(.vectorBase) - .push(.existential) - .push(.indexedElement, index: 3)) - - do { - var parser = StringParser("c*.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.**") - _ = try parser.parseProjectionPathFromSIL() - fatalError("too long path not detected") - } catch { - } - do { - var parser = StringParser("**.s0") - _ = try parser.parseProjectionPathFromSIL() - fatalError("wrong '**' not detected") - } catch { - } +let smallProjectionPathTest = Test("small_projection_path") { + function, arguments, context in + + basicPushPop() + parsing() + merging() + subtracting() + matching() + overlapping() + predicates() + path2path() + indexedElements() + + func basicPushPop() { + let p1 = SmallProjectionPath(.structField, index: 3) + .push(.classField, index: 12345678) + let (k2, i2, p2) = p1.pop() + assert(k2 == .classField && i2 == 12345678) + let (k3, i3, p3) = p2.pop() + assert(k3 == .structField && i3 == 3) + assert(p3.isEmpty) + let (k4, i4, _) = p2.push(.enumCase, index: 876).pop() + assert(k4 == .enumCase && i4 == 876) + let p5 = SmallProjectionPath(.anything) + assert(p5.pop().path.isEmpty) + let p6 = SmallProjectionPath(.indexedElement, index: 1).push(.indexedElement, index: 2) + let (k6, i6, p7) = p6.pop() + assert(k6 == .indexedElement && i6 == 3 && p7.isEmpty) + let p8 = SmallProjectionPath(.indexedElement, index: 0) + assert(p8.isEmpty) + let p9 = SmallProjectionPath(.indexedElement, index: 1).push(.anyIndexedElement) + let (k9, i9, p10) = p9.pop() + assert(k9 == .anyIndexedElement && i9 == 0 && p10.isEmpty) + let p11 = SmallProjectionPath(.anyIndexedElement).push(.indexedElement, index: 1) + let (k11, i11, p12) = p11.pop() + assert(k11 == .anyIndexedElement && i11 == 0 && p12.isEmpty) + } + + func parsing() { + testParse("v**.c*", expect: SmallProjectionPath(.anyClassField) + .push(.anyValueFields)) + testParse("s3.c*.v**.s1", expect: SmallProjectionPath(.structField, index: 1) + .push(.anyValueFields) + .push(.anyClassField) + .push(.structField, index: 3)) + testParse("2.c*.e6.ct.**", expect: SmallProjectionPath(.anything) + .push(.tailElements) + .push(.enumCase, index: 6) + .push(.anyClassField) + .push(.tupleField, index: 2)) + testParse("i3.x.b.i*", expect: SmallProjectionPath(.anyIndexedElement) + .push(.vectorBase) + .push(.existential) + .push(.indexedElement, index: 3)) + + do { + var parser = StringParser("c*.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.**") + _ = try parser.parseProjectionPathFromSIL() + fatalError("too long path not detected") + } catch { + } + do { + var parser = StringParser("**.s0") + _ = try parser.parseProjectionPathFromSIL() + fatalError("wrong '**' not detected") + } catch { } + } + + func testParse(_ pathStr: String, expect: SmallProjectionPath) { + var parser = StringParser(pathStr) + let path = try! parser.parseProjectionPathFromSIL() + assert(path == expect) + let str = path.description + assert(str == pathStr) + } + + func merging() { + testMerge("c1.c0", "c0", expect: "c*.**") + testMerge("c2.c1", "c2", expect: "c2.**") + testMerge("s3.c0", "v**.c0", expect: "v**.c0") + testMerge("c0", "s2.c1", expect: "v**.c*") + testMerge("s1.s1.c2", "s1.c2", expect: "s1.v**.c2") + testMerge("s1.s0", "s2.s0", expect: "v**") + testMerge("ct", "c2", expect: "c*") + testMerge("i1", "i2", expect: "i*") + testMerge("i*", "i2", expect: "i*") + testMerge("s0.i*.e3", "s0.e3", expect: "s0.i*.e3") + testMerge("i*", "v**", expect: "v**") + testMerge("s0.b.i1", "s0.b.i0", expect: "s0.b.i*") + testMerge("s0.b", "s0.1", expect: "s0.v**") + + testMerge("ct.s0.e0.v**.c0", "ct.s0.e0.v**.c0", expect: "ct.s0.e0.v**.c0") + testMerge("ct.s0.s0.c0", "ct.s0.e0.s0.c0", expect: "ct.s0.v**.c0") + } - func testParse(_ pathStr: String, expect: SmallProjectionPath) { - var parser = StringParser(pathStr) - let path = try! parser.parseProjectionPathFromSIL() - assert(path == expect) - let str = path.description - assert(str == pathStr) - } - - func merging() { - testMerge("c1.c0", "c0", expect: "c*.**") - testMerge("c2.c1", "c2", expect: "c2.**") - testMerge("s3.c0", "v**.c0", expect: "v**.c0") - testMerge("c0", "s2.c1", expect: "v**.c*") - testMerge("s1.s1.c2", "s1.c2", expect: "s1.v**.c2") - testMerge("s1.s0", "s2.s0", expect: "v**") - testMerge("ct", "c2", expect: "c*") - testMerge("i1", "i2", expect: "i*") - testMerge("i*", "i2", expect: "i*") - testMerge("s0.i*.e3", "s0.e3", expect: "s0.i*.e3") - testMerge("i*", "v**", expect: "v**") - testMerge("s0.b.i1", "s0.b.i0", expect: "s0.b.i*") - testMerge("s0.b", "s0.1", expect: "s0.v**") - - testMerge("ct.s0.e0.v**.c0", "ct.s0.e0.v**.c0", expect: "ct.s0.e0.v**.c0") - testMerge("ct.s0.s0.c0", "ct.s0.e0.s0.c0", expect: "ct.s0.v**.c0") - } - - func testMerge(_ lhsStr: String, _ rhsStr: String, - expect expectStr: String) { - var lhsParser = StringParser(lhsStr) - let lhs = try! lhsParser.parseProjectionPathFromSIL() - var rhsParser = StringParser(rhsStr) - let rhs = try! rhsParser.parseProjectionPathFromSIL() + func testMerge(_ lhsStr: String, _ rhsStr: String, + expect expectStr: String) { + var lhsParser = StringParser(lhsStr) + let lhs = try! lhsParser.parseProjectionPathFromSIL() + var rhsParser = StringParser(rhsStr) + let rhs = try! rhsParser.parseProjectionPathFromSIL() + var expectParser = StringParser(expectStr) + let expect = try! expectParser.parseProjectionPathFromSIL() + + let result = lhs.merge(with: rhs) + assert(result == expect) + let result2 = rhs.merge(with: lhs) + assert(result2 == expect) + } + + func subtracting() { + testSubtract("s0", "s0.s1", expect: "s1") + testSubtract("s0", "s1", expect: nil) + testSubtract("s0.s1", "s0.s1", expect: "") + testSubtract("i*.s1", "i*.s1", expect: nil) + testSubtract("ct.s1.0.i3.x", "ct.s1.0.i3.x", expect: "") + testSubtract("c0.s1.0.i3", "c0.s1.0.i3.x", expect: "x") + testSubtract("s1.0.i3.x", "s1.0.i3", expect: nil) + testSubtract("v**.s1", "v**.s1", expect: nil) + testSubtract("i*", "i*", expect: nil) + } + + func testSubtract(_ lhsStr: String, _ rhsStr: String, expect expectStr: String?) { + var lhsParser = StringParser(lhsStr) + let lhs = try! lhsParser.parseProjectionPathFromSIL() + var rhsParser = StringParser(rhsStr) + let rhs = try! rhsParser.parseProjectionPathFromSIL() + + let result = lhs.subtract(from: rhs) + + if let expectStr = expectStr { var expectParser = StringParser(expectStr) let expect = try! expectParser.parseProjectionPathFromSIL() - - let result = lhs.merge(with: rhs) - assert(result == expect) - let result2 = rhs.merge(with: lhs) - assert(result2 == expect) - } - - func subtracting() { - testSubtract("s0", "s0.s1", expect: "s1") - testSubtract("s0", "s1", expect: nil) - testSubtract("s0.s1", "s0.s1", expect: "") - testSubtract("i*.s1", "i*.s1", expect: nil) - testSubtract("ct.s1.0.i3.x", "ct.s1.0.i3.x", expect: "") - testSubtract("c0.s1.0.i3", "c0.s1.0.i3.x", expect: "x") - testSubtract("s1.0.i3.x", "s1.0.i3", expect: nil) - testSubtract("v**.s1", "v**.s1", expect: nil) - testSubtract("i*", "i*", expect: nil) - } - - func testSubtract(_ lhsStr: String, _ rhsStr: String, expect expectStr: String?) { - var lhsParser = StringParser(lhsStr) - let lhs = try! lhsParser.parseProjectionPathFromSIL() - var rhsParser = StringParser(rhsStr) - let rhs = try! rhsParser.parseProjectionPathFromSIL() - - let result = lhs.subtract(from: rhs) - - if let expectStr = expectStr { - var expectParser = StringParser(expectStr) - let expect = try! expectParser.parseProjectionPathFromSIL() - assert(result! == expect) - } else { - assert(result == nil) - } + assert(result! == expect) + } else { + assert(result == nil) } + } - func matching() { - testMatch("ct", "c*", expect: true) - testMatch("c1", "c*", expect: true) - testMatch("s2", "v**", expect: true) - testMatch("1", "v**", expect: true) - testMatch("e1", "v**", expect: true) - testMatch("c*", "c1", expect: false) - testMatch("c*", "ct", expect: false) - testMatch("v**", "s0", expect: false) - testMatch("i1", "i1", expect: true) - testMatch("i1", "i*", expect: true) - testMatch("i*", "i1", expect: false) - - testMatch("s0.s1", "s0.s1", expect: true) - testMatch("s0.s2", "s0.s1", expect: false) - testMatch("s0", "s0.v**", expect: true) - testMatch("s0.s1", "s0.v**", expect: true) - testMatch("s0.1.e2", "s0.v**", expect: true) - testMatch("s0.v**.x.e2", "v**", expect: true) - testMatch("s0.v**", "s0.s1", expect: false) - testMatch("s0.s1.c*", "s0.v**", expect: false) - testMatch("s0.v**", "s0.**", expect: true) - testMatch("s1.v**", "s0.**", expect: false) - testMatch("s0.**", "s0.v**", expect: false) - testMatch("s0.s1", "s0.i*.s1", expect: true) - testMatch("s0.b.s1", "s0.b.i*.s1", expect: true) - } - - func testMatch(_ lhsStr: String, _ rhsStr: String, expect: Bool) { - var lhsParser = StringParser(lhsStr) - let lhs = try! lhsParser.parseProjectionPathFromSIL() - var rhsParser = StringParser(rhsStr) - let rhs = try! rhsParser.parseProjectionPathFromSIL() - let result = lhs.matches(pattern: rhs) - assert(result == expect) - } - - func overlapping() { - testOverlap("s0.s1.s2", "s0.s1.s2", expect: true) - testOverlap("s0.s1.s2", "s0.s2.s2", expect: false) - testOverlap("s0.s1.s2", "s0.e1.s2", expect: false) - testOverlap("s0.s1.s2", "s0.s1", expect: true) - testOverlap("s0.s1.s2", "s1.s2", expect: false) - - testOverlap("s0.c*.s2", "s0.ct.s2", expect: true) - testOverlap("s0.c*.s2", "s0.c1.s2", expect: true) - testOverlap("s0.c*.s2", "s0.c1.c2.s2", expect: false) - testOverlap("s0.c*.s2", "s0.s2", expect: false) - - testOverlap("s0.v**.s2", "s0.s3.x", expect: true) - testOverlap("s0.v**.s2.c2", "s0.s3.c1", expect: false) - testOverlap("s0.v**.s2", "s1.s3", expect: false) - testOverlap("s0.v**.s2", "s0.v**.s3", expect: true) - - testOverlap("s0.**", "s0.s3.c1", expect: true) - testOverlap("**", "s0.s3.c1", expect: true) - - testOverlap("i1", "i*", expect: true) - testOverlap("i1", "v**", expect: true) - testOverlap("s0.i*.s1", "s0.s1", expect: true) - testOverlap("s0.b.s1", "s0.b.i*.s1", expect: true) - testOverlap("s0.b.i0.s1", "s0.b.i1.s1", expect: false) - testOverlap("s0.b.i2.s1", "s0.b.i1.s1", expect: false) - testOverlap("s0.b.s1", "s0.b.i0.s1", expect: true) - testOverlap("s0.b", "s0.b.i1", expect: false) - testOverlap("s0.b.i1", "s0.b", expect: false) - testOverlap("s0.b.i1", "s0", expect: true) - } - - func testOverlap(_ lhsStr: String, _ rhsStr: String, expect: Bool) { - var lhsParser = StringParser(lhsStr) - let lhs = try! lhsParser.parseProjectionPathFromSIL() - var rhsParser = StringParser(rhsStr) - let rhs = try! rhsParser.parseProjectionPathFromSIL() - let result = lhs.mayOverlap(with: rhs) - assert(result == expect) - let reversedResult = rhs.mayOverlap(with: lhs) - assert(reversedResult == expect) - } - - func predicates() { - testPredicate("v**", \.hasClassProjection, expect: false) - testPredicate("v**.c0.s1.v**", \.hasClassProjection, expect: true) - testPredicate("c0.**", \.hasClassProjection, expect: true) - testPredicate("c0.c1", \.hasClassProjection, expect: true) - testPredicate("ct", \.hasClassProjection, expect: true) - testPredicate("s0", \.hasClassProjection, expect: false) - - testPredicate("v**", \.mayHaveClassProjection, expect: false) - testPredicate("c0", \.mayHaveClassProjection, expect: true) - testPredicate("1", \.mayHaveClassProjection, expect: false) - testPredicate("**", \.mayHaveClassProjection, expect: true) - - testPredicate("v**", \.mayHaveTwoClassProjections, expect: false) - testPredicate("c0", \.mayHaveTwoClassProjections, expect: false) - testPredicate("**", \.mayHaveTwoClassProjections, expect: true) - testPredicate("v**.c*.s2.1.c0", \.mayHaveTwoClassProjections, expect: true) - testPredicate("c*.s2.1.c0.v**", \.mayHaveTwoClassProjections, expect: true) - testPredicate("v**.c*.**", \.mayHaveTwoClassProjections, expect: true) - } - - func testPredicate(_ pathStr: String, _ property: (SmallProjectionPath) -> Bool, expect: Bool) { - var parser = StringParser(pathStr) - let path = try! parser.parseProjectionPathFromSIL() - let result = property(path) - assert(result == expect) - } - - func path2path() { - testPath2Path("s0.b.e2.3.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1") - testPath2Path("v**.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1") - testPath2Path("**", { $0.popAllValueFields() }, expect: "**") - - testPath2Path("s0.e2.3.c4.s1.e2.v**.**", { $0.popLastClassAndValuesFromTail() }, expect: "s0.e2.3.c4.s1.e2.v**.**") - testPath2Path("s0.c2.3.c4.s1", { $0.popLastClassAndValuesFromTail() }, expect: "s0.c2.3") - testPath2Path("v**.c*.s1", { $0.popLastClassAndValuesFromTail() }, expect: "v**") - testPath2Path("s1.ct.v**", { $0.popLastClassAndValuesFromTail() }, expect: "s1") - testPath2Path("c0.c1.c2", { $0.popLastClassAndValuesFromTail() }, expect: "c0.c1") - testPath2Path("**", { $0.popLastClassAndValuesFromTail() }, expect: "**") - - testPath2Path("v**.c3", { $0.popIfMatches(.anyValueFields) }, expect: "v**.c3") - testPath2Path("**", { $0.popIfMatches(.anyValueFields) }, expect: "**") - testPath2Path("s0.c3", { $0.popIfMatches(.anyValueFields) }, expect: nil) - - testPath2Path("c0.s3", { $0.popIfMatches(.anyClassField) }, expect: nil) - testPath2Path("**", { $0.popIfMatches(.anyClassField) }, expect: "**") - testPath2Path("c*.e3", { $0.popIfMatches(.anyClassField) }, expect: "e3") - - testPath2Path("i*.e3.s0", { $0.popIfMatches(.enumCase, index: 3) }, expect: "s0") - testPath2Path("i1.e3.s0", { $0.popIfMatches(.enumCase, index: 3) }, expect: nil) - testPath2Path("i*.e3.s0", { $0.popIfMatches(.indexedElement, index: 0) }, expect: "i*.e3.s0") - } - - func testPath2Path(_ pathStr: String, _ transform: (SmallProjectionPath) -> SmallProjectionPath?, expect: String?) { - var parser = StringParser(pathStr) - let path = try! parser.parseProjectionPathFromSIL() - let result = transform(path) - if let expect = expect { - var expectParser = StringParser(expect) - let expectPath = try! expectParser.parseProjectionPathFromSIL() - assert(result == expectPath) - } else { - assert(result == nil) - } - } + func matching() { + testMatch("ct", "c*", expect: true) + testMatch("c1", "c*", expect: true) + testMatch("s2", "v**", expect: true) + testMatch("1", "v**", expect: true) + testMatch("e1", "v**", expect: true) + testMatch("c*", "c1", expect: false) + testMatch("c*", "ct", expect: false) + testMatch("v**", "s0", expect: false) + testMatch("i1", "i1", expect: true) + testMatch("i1", "i*", expect: true) + testMatch("i*", "i1", expect: false) + + testMatch("s0.s1", "s0.s1", expect: true) + testMatch("s0.s2", "s0.s1", expect: false) + testMatch("s0", "s0.v**", expect: true) + testMatch("s0.s1", "s0.v**", expect: true) + testMatch("s0.1.e2", "s0.v**", expect: true) + testMatch("s0.v**.x.e2", "v**", expect: true) + testMatch("s0.v**", "s0.s1", expect: false) + testMatch("s0.s1.c*", "s0.v**", expect: false) + testMatch("s0.v**", "s0.**", expect: true) + testMatch("s1.v**", "s0.**", expect: false) + testMatch("s0.**", "s0.v**", expect: false) + testMatch("s0.s1", "s0.i*.s1", expect: true) + testMatch("s0.b.s1", "s0.b.i*.s1", expect: true) + } + + func testMatch(_ lhsStr: String, _ rhsStr: String, expect: Bool) { + var lhsParser = StringParser(lhsStr) + let lhs = try! lhsParser.parseProjectionPathFromSIL() + var rhsParser = StringParser(rhsStr) + let rhs = try! rhsParser.parseProjectionPathFromSIL() + let result = lhs.matches(pattern: rhs) + assert(result == expect) + } + + func overlapping() { + testOverlap("s0.s1.s2", "s0.s1.s2", expect: true) + testOverlap("s0.s1.s2", "s0.s2.s2", expect: false) + testOverlap("s0.s1.s2", "s0.e1.s2", expect: false) + testOverlap("s0.s1.s2", "s0.s1", expect: true) + testOverlap("s0.s1.s2", "s1.s2", expect: false) + + testOverlap("s0.c*.s2", "s0.ct.s2", expect: true) + testOverlap("s0.c*.s2", "s0.c1.s2", expect: true) + testOverlap("s0.c*.s2", "s0.c1.c2.s2", expect: false) + testOverlap("s0.c*.s2", "s0.s2", expect: false) + + testOverlap("s0.v**.s2", "s0.s3.x", expect: true) + testOverlap("s0.v**.s2.c2", "s0.s3.c1", expect: false) + testOverlap("s0.v**.s2", "s1.s3", expect: false) + testOverlap("s0.v**.s2", "s0.v**.s3", expect: true) + + testOverlap("s0.**", "s0.s3.c1", expect: true) + testOverlap("**", "s0.s3.c1", expect: true) + + testOverlap("i1", "i*", expect: true) + testOverlap("i1", "v**", expect: true) + testOverlap("s0.i*.s1", "s0.s1", expect: true) + testOverlap("s0.b.s1", "s0.b.i*.s1", expect: true) + testOverlap("s0.b.i0.s1", "s0.b.i1.s1", expect: false) + testOverlap("s0.b.i2.s1", "s0.b.i1.s1", expect: false) + testOverlap("s0.b.s1", "s0.b.i0.s1", expect: true) + testOverlap("s0.b", "s0.b.i1", expect: false) + testOverlap("s0.b.i1", "s0.b", expect: false) + testOverlap("s0.b.i1", "s0", expect: true) + } - func indexedElements() { - let p1 = SmallProjectionPath(.indexedElement, index: 1) - let (k1, i1, s1) = p1.pop() - assert(k1 == .indexedElement && i1 == 1 && s1.isEmpty) + func testOverlap(_ lhsStr: String, _ rhsStr: String, expect: Bool) { + var lhsParser = StringParser(lhsStr) + let lhs = try! lhsParser.parseProjectionPathFromSIL() + var rhsParser = StringParser(rhsStr) + let rhs = try! rhsParser.parseProjectionPathFromSIL() + let result = lhs.mayOverlap(with: rhs) + assert(result == expect) + let reversedResult = rhs.mayOverlap(with: lhs) + assert(reversedResult == expect) + } + + func predicates() { + testPredicate("v**", \.hasClassProjection, expect: false) + testPredicate("v**.c0.s1.v**", \.hasClassProjection, expect: true) + testPredicate("c0.**", \.hasClassProjection, expect: true) + testPredicate("c0.c1", \.hasClassProjection, expect: true) + testPredicate("ct", \.hasClassProjection, expect: true) + testPredicate("s0", \.hasClassProjection, expect: false) + + testPredicate("v**", \.mayHaveClassProjection, expect: false) + testPredicate("c0", \.mayHaveClassProjection, expect: true) + testPredicate("1", \.mayHaveClassProjection, expect: false) + testPredicate("**", \.mayHaveClassProjection, expect: true) + + testPredicate("v**", \.mayHaveTwoClassProjections, expect: false) + testPredicate("c0", \.mayHaveTwoClassProjections, expect: false) + testPredicate("**", \.mayHaveTwoClassProjections, expect: true) + testPredicate("v**.c*.s2.1.c0", \.mayHaveTwoClassProjections, expect: true) + testPredicate("c*.s2.1.c0.v**", \.mayHaveTwoClassProjections, expect: true) + testPredicate("v**.c*.**", \.mayHaveTwoClassProjections, expect: true) + } - let p2 = SmallProjectionPath(.indexedElement, index: -1) - let (k2, _, s2) = p2.pop() - assert(k2 == .anything && s2.isEmpty) + func testPredicate(_ pathStr: String, _ property: (SmallProjectionPath) -> Bool, expect: Bool) { + var parser = StringParser(pathStr) + let path = try! parser.parseProjectionPathFromSIL() + let result = property(path) + assert(result == expect) + } - let p3 = SmallProjectionPath(.indexedElement, index: 0xfffffffffffff) - let (k3, i3, s3) = p3.pop() - assert(k3 == .indexedElement && i3 == 0xfffffffffffff && s3.isEmpty) + func path2path() { + testPath2Path("s0.b.e2.3.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1") + testPath2Path("v**.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1") + testPath2Path("**", { $0.popAllValueFields() }, expect: "**") + + testPath2Path("s0.e2.3.c4.s1.e2.v**.**", { $0.popLastClassAndValuesFromTail() }, expect: "s0.e2.3.c4.s1.e2.v**.**") + testPath2Path("s0.c2.3.c4.s1", { $0.popLastClassAndValuesFromTail() }, expect: "s0.c2.3") + testPath2Path("v**.c*.s1", { $0.popLastClassAndValuesFromTail() }, expect: "v**") + testPath2Path("s1.ct.v**", { $0.popLastClassAndValuesFromTail() }, expect: "s1") + testPath2Path("c0.c1.c2", { $0.popLastClassAndValuesFromTail() }, expect: "c0.c1") + testPath2Path("**", { $0.popLastClassAndValuesFromTail() }, expect: "**") + + testPath2Path("v**.c3", { $0.popIfMatches(.anyValueFields) }, expect: "v**.c3") + testPath2Path("**", { $0.popIfMatches(.anyValueFields) }, expect: "**") + testPath2Path("s0.c3", { $0.popIfMatches(.anyValueFields) }, expect: nil) + + testPath2Path("c0.s3", { $0.popIfMatches(.anyClassField) }, expect: nil) + testPath2Path("**", { $0.popIfMatches(.anyClassField) }, expect: "**") + testPath2Path("c*.e3", { $0.popIfMatches(.anyClassField) }, expect: "e3") + + testPath2Path("i*.e3.s0", { $0.popIfMatches(.enumCase, index: 3) }, expect: "s0") + testPath2Path("i1.e3.s0", { $0.popIfMatches(.enumCase, index: 3) }, expect: nil) + testPath2Path("i*.e3.s0", { $0.popIfMatches(.indexedElement, index: 0) }, expect: "i*.e3.s0") + } - let p4 = p3.push(.indexedElement, index: Int.max) - let (k4, _, s4) = p4.pop() - assert(k4 == .anyIndexedElement && s4.isEmpty) + func testPath2Path(_ pathStr: String, _ transform: (SmallProjectionPath) -> SmallProjectionPath?, expect: String?) { + var parser = StringParser(pathStr) + let path = try! parser.parseProjectionPathFromSIL() + let result = transform(path) + if let expect = expect { + var expectParser = StringParser(expect) + let expectPath = try! expectParser.parseProjectionPathFromSIL() + assert(result == expectPath) + } else { + assert(result == nil) } } + + func indexedElements() { + let p1 = SmallProjectionPath(.indexedElement, index: 1) + let (k1, i1, s1) = p1.pop() + assert(k1 == .indexedElement && i1 == 1 && s1.isEmpty) + + let p2 = SmallProjectionPath(.indexedElement, index: -1) + let (k2, _, s2) = p2.pop() + assert(k2 == .anything && s2.isEmpty) + + let p3 = SmallProjectionPath(.indexedElement, index: 0xfffffffffffff) + let (k3, i3, s3) = p3.pop() + assert(k3 == .indexedElement && i3 == 0xfffffffffffff && s3.isEmpty) + + let p4 = p3.push(.indexedElement, index: Int.max) + let (k4, _, s4) = p4.pop() + assert(k4 == .anyIndexedElement && s4.isEmpty) + } } diff --git a/SwiftCompilerSources/Sources/SIL/Utilities/Test.swift b/SwiftCompilerSources/Sources/SIL/Utilities/Test.swift index ffa25078207e7..8206f5b7b40f8 100644 --- a/SwiftCompilerSources/Sources/SIL/Utilities/Test.swift +++ b/SwiftCompilerSources/Sources/SIL/Utilities/Test.swift @@ -142,6 +142,7 @@ public func registerTests() { // Register each test. registerTests( parseTestSpecificationTest, + smallProjectionPathTest, getAccessBaseTest, borrowIntroducersTest, enclosingValuesTest, diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def index 77f9d1da55f0c..3e41897120d94 100644 --- a/include/swift/SILOptimizer/PassManager/Passes.def +++ b/include/swift/SILOptimizer/PassManager/Passes.def @@ -163,8 +163,6 @@ MODULE_PASS(MandatoryAllocBoxToStack, "mandatory-allocbox-to-stack", "Mandatory stack promotion of box objects") MODULE_PASS(AsyncDemotion, "async-demotion", "Convert async functions to be synchronous") -MODULE_PASS(RunUnitTests, "run-unit-tests", - "Runs the compiler internal unit tests") MODULE_PASS(FunctionUsesDumper, "dump-function-uses", "Dump the results of FunctionUses") MODULE_PASS(MandatoryPerformanceOptimizations, "mandatory-performance-optimizations", diff --git a/test/SILOptimizer/small_projection_path_unit.sil b/test/SILOptimizer/small_projection_path_unit.sil new file mode 100644 index 0000000000000..6cf3cdabd0994 --- /dev/null +++ b/test/SILOptimizer/small_projection_path_unit.sil @@ -0,0 +1,9 @@ +// RUN: %target-sil-opt -test-runner -sil-disable-input-verify %s -o /dev/null + +sil_stage raw + +sil @small_projection_path_unit_tests : $@convention(thin) () -> () { +bb0: + specify_test "small_projection_path" + unreachable +} diff --git a/test/SILOptimizer/swift-unit-tests.sil b/test/SILOptimizer/swift-unit-tests.sil deleted file mode 100644 index 9be5265eee382..0000000000000 --- a/test/SILOptimizer/swift-unit-tests.sil +++ /dev/null @@ -1,4 +0,0 @@ -// RUN: %target-sil-opt %s -run-unit-tests -o /dev/null - -// REQUIRES: swift_in_compiler -