Skip to content

Commit cfe1e7e

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 08e9a11 + 66e07f0 commit cfe1e7e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+566
-103
lines changed

SwiftCompilerSources/Sources/AST/Type.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ public struct Type: TypeProperties, CustomStringConvertible, NoReflectionChildre
6161

6262
public var builtinVectorElementType: Type { Type(bridged: bridged.getBuiltinVectorElementType()) }
6363

64+
public var builtinFixedArrayElementType: Type { Type(bridged: bridged.getBuiltinFixedArrayElementType()) }
65+
6466
public func subst(with substitutionMap: SubstitutionMap) -> Type {
6567
return Type(bridged: bridged.subst(substitutionMap.bridged))
6668
}
@@ -81,6 +83,8 @@ public struct CanonicalType: TypeProperties, CustomStringConvertible, NoReflecti
8183

8284
public var builtinVectorElementType: CanonicalType { rawType.builtinVectorElementType.canonical }
8385

86+
public var builtinFixedArrayElementType: CanonicalType { rawType.builtinFixedArrayElementType.canonical }
87+
8488
public func subst(with substitutionMap: SubstitutionMap) -> CanonicalType {
8589
return rawType.subst(with: substitutionMap).canonical
8690
}
@@ -106,6 +110,7 @@ extension TypeProperties {
106110

107111
public var isBuiltinFloat: Bool { rawType.bridged.isBuiltinFloat() }
108112
public var isBuiltinVector: Bool { rawType.bridged.isBuiltinVector() }
113+
public var isBuiltinFixedArray: Bool { rawType.bridged.isBuiltinFixedArray() }
109114

110115
public var isClass: Bool {
111116
if let nominal = nominal, nominal is ClassDecl {

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/InitializeStaticGlobals.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ private func lowerInlineArray(array: InlineArray, _ context: FunctionPassContext
175175
///
176176
private func getInlineArrayInfo(of allocStack: AllocStackInst) -> InlineArray? {
177177
var arrayLoad: LoadInst? = nil
178-
var elementStorage: UncheckedAddrCastInst? = nil
178+
var elementStorage: VectorBaseAddrInst? = nil
179179

180180
for use in allocStack.uses {
181181
switch use.instruction {
@@ -188,11 +188,11 @@ private func getInlineArrayInfo(of allocStack: AllocStackInst) -> InlineArray? {
188188
arrayLoad = load
189189
case is DeallocStackInst:
190190
break
191-
case let addrCastToElement as UncheckedAddrCastInst:
191+
case let baseAddr as VectorBaseAddrInst:
192192
if elementStorage != nil {
193193
return nil
194194
}
195-
elementStorage = addrCastToElement
195+
elementStorage = baseAddr
196196
default:
197197
return nil
198198
}

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ swift_compiler_sources(Optimizer
3939
SimplifySwitchEnum.swift
4040
SimplifyTuple.swift
4141
SimplifyTupleExtract.swift
42+
SimplifyUncheckedAddrCast.swift
4243
SimplifyUncheckedEnumData.swift
4344
SimplifyValueToBridgeObject.swift
4445
SimplifyWitnessMethod.swift)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//===--- SimplifyUncheckedAddrCast.swift ----------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SIL
14+
15+
extension UncheckedAddrCastInst : OnoneSimplifiable, SILCombineSimplifiable {
16+
17+
func simplify(_ context: SimplifyContext) {
18+
// ```
19+
// %1 = unchecked_addr_cast %0 : $*T to $*T
20+
// ```
21+
// ->
22+
// replace %1 with %0
23+
//
24+
if optimizeSameTypeCast(context) {
25+
return
26+
}
27+
28+
// ```
29+
// %1 = unchecked_addr_cast %0 : $*U to $*V
30+
// %2 = unchecked_addr_cast %1 : $*V to $*T
31+
// ```
32+
// ->
33+
// ```
34+
// %2 = unchecked_addr_cast %0: $*U to $*T
35+
// ```
36+
if optimizeDoubleCast(context) {
37+
return
38+
}
39+
40+
// ```
41+
// %1 = unchecked_addr_cast %0 : $*Builtin.FixedArray<N, Element> to $*Element
42+
// ```
43+
// ->
44+
// ```
45+
// %1 = vector_base_addr %0 : $*Builtin.FixedArray<N, Element>
46+
// ```
47+
_ = optimizeVectorBaseCast(context)
48+
}
49+
}
50+
51+
private extension UncheckedAddrCastInst {
52+
func optimizeSameTypeCast(_ context: SimplifyContext) -> Bool {
53+
if fromAddress.type == type {
54+
self.replace(with: fromAddress, context)
55+
return true
56+
}
57+
return false
58+
}
59+
60+
func optimizeDoubleCast(_ context: SimplifyContext) -> Bool {
61+
if let firstCast = fromAddress as? UncheckedAddrCastInst {
62+
let builder = Builder(before: self, context)
63+
let newCast = builder.createUncheckedAddrCast(from: firstCast.fromAddress, to: type)
64+
self.replace(with: newCast, context)
65+
return true
66+
}
67+
return false
68+
}
69+
70+
func optimizeVectorBaseCast(_ context: SimplifyContext) -> Bool {
71+
if fromAddress.type.isBuiltinFixedArray,
72+
fromAddress.type.builtinFixedArrayElementType(in: parentFunction, maximallyAbstracted: true).addressType == type
73+
{
74+
let builder = Builder(before: self, context)
75+
let vectorBase = builder.createVectorBaseAddr(vector: fromAddress)
76+
self.replace(with: vectorBase, context)
77+
return true
78+
}
79+
return false
80+
}
81+
}

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ private func registerSwiftPasses() {
125125
registerForSILCombine(PointerToAddressInst.self, { run(PointerToAddressInst.self, $0) })
126126
registerForSILCombine(UncheckedEnumDataInst.self, { run(UncheckedEnumDataInst.self, $0) })
127127
registerForSILCombine(WitnessMethodInst.self, { run(WitnessMethodInst.self, $0) })
128+
registerForSILCombine(UncheckedAddrCastInst.self, { run(UncheckedAddrCastInst.self, $0) })
128129
registerForSILCombine(UnconditionalCheckedCastInst.self, { run(UnconditionalCheckedCastInst.self, $0) })
129130
registerForSILCombine(AllocStackInst.self, { run(AllocStackInst.self, $0) })
130131
registerForSILCombine(ApplyInst.self, { run(ApplyInst.self, $0) })

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ extension Instruction {
387387
case let bi as BuiltinInst:
388388
switch bi.id {
389389
case .ZeroInitializer:
390-
let type = bi.type.isBuiltinVector ? bi.type.builtinVectorElementType : bi.type
390+
let type = bi.type.isBuiltinVector ? bi.type.builtinVectorElementType(in: parentFunction) : bi.type
391391
return type.isBuiltinInteger || type.isBuiltinFloat
392392
case .PtrToInt:
393393
return bi.operands[0].value is StringLiteralInst

SwiftCompilerSources/Sources/Optimizer/Utilities/Verifier.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ extension LoadBorrowInst : VerifiableInstruction {
148148
}
149149
}
150150

151+
extension VectorBaseAddrInst : VerifiableInstruction {
152+
func verify(_ context: FunctionPassContext) {
153+
require(vector.type.isBuiltinFixedArray,
154+
"vector operand of vector_element_addr must be a Builtin.FixedArray")
155+
require(type == vector.type.builtinFixedArrayElementType(in: parentFunction,
156+
maximallyAbstracted: true).addressType,
157+
"result of vector_element_addr has wrong type")
158+
}
159+
}
160+
151161
// Used to check if any instruction is mutating the memory location within the liverange of a `load_borrow`.
152162
// Note that it is not checking if an instruction _may_ mutate the memory, but it's checking if any instruction
153163
// _definitely_ will mutate the memory.

SwiftCompilerSources/Sources/SIL/Builder.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,10 @@ public struct Builder {
487487
return notifyNew(vectorInst.getAs(VectorInst.self))
488488
}
489489

490+
public func createVectorBaseAddr(vector: Value) -> VectorBaseAddrInst {
491+
return notifyNew(bridged.createVectorBaseAddr(vector.bridged).getAs(VectorBaseAddrInst.self))
492+
}
493+
490494
public func createGlobalAddr(global: GlobalVariable, dependencyToken: Value?) -> GlobalAddrInst {
491495
return notifyNew(bridged.createGlobalAddr(global.bridged, dependencyToken.bridged).getAs(GlobalAddrInst.self))
492496
}

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,10 @@ final public class ObjectInst : SingleValueInstruction {
13501350
final public class VectorInst : SingleValueInstruction {
13511351
}
13521352

1353+
final public class VectorBaseAddrInst : SingleValueInstruction, UnaryInstruction {
1354+
public var vector: Value { operand.value }
1355+
}
1356+
13531357
final public class DifferentiableFunctionInst: SingleValueInstruction {}
13541358

13551359
final public class LinearFunctionInst: SingleValueInstruction {}

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public func registerSILClasses() {
118118
register(MoveOnlyWrapperToCopyableAddrInst.self)
119119
register(ObjectInst.self)
120120
register(VectorInst.self)
121+
register(VectorBaseAddrInst.self)
121122
register(TuplePackExtractInst.self)
122123
register(TuplePackElementAddrInst.self)
123124
register(PackElementGetInst.self)

SwiftCompilerSources/Sources/SIL/Type.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,13 @@ public struct Type : TypeProperties, CustomStringConvertible, NoReflectionChildr
8080
!isNoEscapeFunction && isEscapable(in: function)
8181
}
8282

83-
public var builtinVectorElementType: Type { canonicalType.builtinVectorElementType.silType! }
83+
public func builtinVectorElementType(in function: Function) -> Type {
84+
canonicalType.builtinVectorElementType.loweredType(in: function)
85+
}
86+
87+
public func builtinFixedArrayElementType(in function: Function, maximallyAbstracted: Bool = false) -> Type {
88+
canonicalType.builtinFixedArrayElementType.loweredType(in: function, maximallyAbstracted: maximallyAbstracted)
89+
}
8490

8591
public var superClassType: Type? { canonicalType.superClassType?.silType }
8692

SwiftCompilerSources/Sources/SIL/Utilities/AccessUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ public struct AccessPath : CustomStringConvertible, Hashable {
431431

432432
private func canBeOperandOfIndexAddr(_ value: Value) -> Bool {
433433
switch value {
434-
case is IndexAddrInst, is RefTailAddrInst, is PointerToAddressInst:
434+
case is IndexAddrInst, is RefTailAddrInst, is PointerToAddressInst, is VectorBaseAddrInst:
435435
return true
436436
default:
437437
return false

SwiftCompilerSources/Sources/SIL/Utilities/SmallProjectionPath.swift

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,17 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
8383
// This and all following kinds (we'll add in the future) cannot have a field index.
8484
case tailElements = 0x07 // (0 << 3) | 0x7 A tail allocated element of a class: syntax `ct`
8585
case existential = 0x0f // (1 << 3) | 0x7 A concrete value projected out of an existential: synatx 'x'
86-
case anyClassField = 0x17 // (2 << 3) | 0x7 Any class field, including tail elements: syntax `c*`
87-
case anyIndexedElement = 0x1f // (3 << 3) | 0x7 An unknown offset into an array of elements.
86+
case vectorBase = 0x17 // (2 << 3) | 0x7 The base element of a vector: synatx 'b'
87+
case anyClassField = 0x1f // (3 << 3) | 0x7 Any class field, including tail elements: syntax `c*`
88+
case anyIndexedElement = 0x27 // (4 << 3) | 0x7 An unknown offset into an array of elements.
8889
// There must not be two successive element indices in the path.
89-
case anyValueFields = 0x27 // (4 << 3) | 0x7 Any number of any value fields (struct, tuple, enum): syntax `v**`
90-
case anything = 0x2f // (5 << 3) | 0x7 Any number of any fields: syntax `**`
90+
case anyValueFields = 0x2f // (5 << 3) | 0x7 Any number of any value fields (struct, tuple, enum): syntax `v**`
91+
case anything = 0x37 // (6 << 3) | 0x7 Any number of any fields: syntax `**`
9192

9293
public var isValueField: Bool {
9394
switch self {
94-
case .anyValueFields, .structField, .tupleField, .enumCase, .indexedElement, .anyIndexedElement, .existential:
95+
case .structField, .tupleField, .enumCase, .indexedElement, .existential, .vectorBase,
96+
.anyValueFields, .anyIndexedElement:
9597
return true
9698
case .root, .anything, .anyClassField, .classField, .tailElements:
9799
return false
@@ -102,7 +104,8 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
102104
switch self {
103105
case .anyClassField, .classField, .tailElements:
104106
return true
105-
case .root, .anything, .anyValueFields, .structField, .tupleField, .enumCase, .indexedElement, .anyIndexedElement, .existential:
107+
case .root, .anything, .anyValueFields, .structField, .tupleField, .enumCase, .indexedElement,
108+
.anyIndexedElement, .existential, .vectorBase:
106109
return false
107110
}
108111
}
@@ -140,6 +143,7 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
140143
case .classField: s = "c\(idx)"
141144
case .tailElements: s = "ct"
142145
case .existential: s = "x"
146+
case .vectorBase: s = "b"
143147
case .indexedElement: s = "i\(idx)"
144148
case .anyIndexedElement: s = "i*"
145149
case .anything: s = "**"
@@ -398,7 +402,7 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
398402
return subPath.matches(pattern: subPattern)
399403
case .anyIndexedElement:
400404
return popIndexedElements().matches(pattern: subPattern)
401-
case .structField, .tupleField, .enumCase, .classField, .tailElements, .indexedElement, .existential:
405+
case .structField, .tupleField, .enumCase, .classField, .tailElements, .indexedElement, .existential, .vectorBase:
402406
let (kind, index, subPath) = pop()
403407
if kind != patternKind || index != patternIdx { return false }
404408
return subPath.matches(pattern: subPattern)
@@ -478,8 +482,18 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
478482
}
479483
if (lhsKind == rhsKind && lhsIdx == rhsIdx) ||
480484
(lhsKind == .anyClassField && rhsKind.isClassField) ||
481-
(lhsKind.isClassField && rhsKind == .anyClassField) {
482-
return pop(numBits: lhsBits).mayOverlap(with: rhs.pop(numBits: rhsBits))
485+
(lhsKind.isClassField && rhsKind == .anyClassField)
486+
{
487+
let poppedPath = pop(numBits: lhsBits)
488+
let rhsPoppedPath = rhs.pop(numBits: rhsBits)
489+
// Check for the case of overlapping the first element of a vector with another element.
490+
// Note that the index of `.indexedElement` cannot be 0.
491+
if (poppedPath.isEmpty && rhsPoppedPath.pop().kind == .indexedElement) ||
492+
(rhsPoppedPath.isEmpty && poppedPath.pop().kind == .indexedElement)
493+
{
494+
return false
495+
}
496+
return poppedPath.mayOverlap(with: rhsPoppedPath)
483497
}
484498
return false
485499
}
@@ -496,7 +510,7 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
496510
switch lhsKind {
497511
case .root:
498512
return rhs
499-
case .classField, .tailElements, .structField, .tupleField, .enumCase, .existential, .indexedElement:
513+
case .classField, .tailElements, .structField, .tupleField, .enumCase, .existential, .indexedElement, .vectorBase:
500514
let (rhsKind, rhsIdx, rhsBits) = rhs.top
501515
if lhsKind == rhsKind && lhsIdx == rhsIdx {
502516
return pop(numBits: lhsBits).subtract(from: rhs.pop(numBits: rhsBits))
@@ -601,6 +615,8 @@ extension StringParser {
601615
entries.append((.tailElements, 0))
602616
} else if consume("x") {
603617
entries.append((.existential, 0))
618+
} else if consume("b") {
619+
entries.append((.vectorBase, 0))
604620
} else if consume("c") {
605621
guard let idx = consumeInt(withWhiteSpace: false) else {
606622
try throwError("expected class field index")
@@ -701,7 +717,8 @@ extension SmallProjectionPath {
701717
.push(.enumCase, index: 6)
702718
.push(.anyClassField)
703719
.push(.tupleField, index: 2))
704-
testParse("i3.x.i*", expect: SmallProjectionPath(.anyIndexedElement)
720+
testParse("i3.x.b.i*", expect: SmallProjectionPath(.anyIndexedElement)
721+
.push(.vectorBase)
705722
.push(.existential)
706723
.push(.indexedElement, index: 3))
707724

@@ -739,6 +756,8 @@ extension SmallProjectionPath {
739756
testMerge("i*", "i2", expect: "i*")
740757
testMerge("s0.i*.e3", "s0.e3", expect: "s0.i*.e3")
741758
testMerge("i*", "v**", expect: "v**")
759+
testMerge("s0.b.i1", "s0.b.i0", expect: "s0.b.i*")
760+
testMerge("s0.b", "s0.1", expect: "s0.v**")
742761

743762
testMerge("ct.s0.e0.v**.c0", "ct.s0.e0.v**.c0", expect: "ct.s0.e0.v**.c0")
744763
testMerge("ct.s0.s0.c0", "ct.s0.e0.s0.c0", expect: "ct.s0.v**.c0")
@@ -813,6 +832,7 @@ extension SmallProjectionPath {
813832
testMatch("s1.v**", "s0.**", expect: false)
814833
testMatch("s0.**", "s0.v**", expect: false)
815834
testMatch("s0.s1", "s0.i*.s1", expect: true)
835+
testMatch("s0.b.s1", "s0.b.i*.s1", expect: true)
816836
}
817837

818838
func testMatch(_ lhsStr: String, _ rhsStr: String, expect: Bool) {
@@ -847,6 +867,13 @@ extension SmallProjectionPath {
847867
testOverlap("i1", "i*", expect: true)
848868
testOverlap("i1", "v**", expect: true)
849869
testOverlap("s0.i*.s1", "s0.s1", expect: true)
870+
testOverlap("s0.b.s1", "s0.b.i*.s1", expect: true)
871+
testOverlap("s0.b.i0.s1", "s0.b.i1.s1", expect: false)
872+
testOverlap("s0.b.i2.s1", "s0.b.i1.s1", expect: false)
873+
testOverlap("s0.b.s1", "s0.b.i0.s1", expect: true)
874+
testOverlap("s0.b", "s0.b.i1", expect: false)
875+
testOverlap("s0.b.i1", "s0.b", expect: false)
876+
testOverlap("s0.b.i1", "s0", expect: true)
850877
}
851878

852879
func testOverlap(_ lhsStr: String, _ rhsStr: String, expect: Bool) {
@@ -889,7 +916,7 @@ extension SmallProjectionPath {
889916
}
890917

891918
func path2path() {
892-
testPath2Path("s0.e2.3.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1")
919+
testPath2Path("s0.b.e2.3.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1")
893920
testPath2Path("v**.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1")
894921
testPath2Path("**", { $0.popAllValueFields() }, expect: "**")
895922

SwiftCompilerSources/Sources/SIL/Utilities/WalkUtils.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,12 @@ extension AddressDefUseWalker {
509509
} else {
510510
return unmatchedPath(address: operand, path: path)
511511
}
512+
case let vba as VectorBaseAddrInst:
513+
if let path = path.popIfMatches(.vectorBase, index: 0) {
514+
return walkDownUses(ofAddress: vba, path: path)
515+
} else {
516+
return unmatchedPath(address: operand, path: path)
517+
}
512518
case is InitEnumDataAddrInst, is UncheckedTakeEnumDataAddrInst:
513519
let ei = instruction as! SingleValueInstruction
514520
if let path = path.popIfMatches(.enumCase, index: (instruction as! EnumInstruction).caseIndex) {
@@ -814,6 +820,8 @@ extension AddressUseDefWalker {
814820
return walkUp(address: sea.struct, path: path.push(.structField, index: sea.fieldIndex))
815821
case let tea as TupleElementAddrInst:
816822
return walkUp(address: tea.tuple, path: path.push(.tupleField, index: tea.fieldIndex))
823+
case let vba as VectorBaseAddrInst:
824+
return walkUp(address: vba.vector, path: path.push(.vectorBase, index: 0))
817825
case let ida as InitEnumDataAddrInst:
818826
return walkUp(address: ida.operand.value, path: path.push(.enumCase, index: ida.caseIndex))
819827
case let uteda as UncheckedTakeEnumDataAddrInst:

0 commit comments

Comments
 (0)