@@ -37,13 +37,15 @@ let stripObjectHeadersPass = FunctionPass(name: "strip-object-headers") {
37
37
38
38
private extension Value {
39
39
func needObjectHeader( ) -> Bool {
40
- var walker = IsBareObjectWalker ( )
40
+ var walker = IsBareObjectWalker ( rootDef : self )
41
41
return walker. walkDownUses ( ofValue: self , path: SmallProjectionPath ( ) ) == . abortWalk
42
42
}
43
43
}
44
44
45
- private struct IsBareObjectWalker : ValueDefUseWalker {
45
+ private struct IsBareObjectWalker : ValueDefUseWalker , ValueUseDefWalker {
46
+ var walkUpCache = WalkerCache < SmallProjectionPath > ( )
46
47
var walkDownCache = WalkerCache < SmallProjectionPath > ( )
48
+ let rootDef : Value
47
49
48
50
mutating func walkDown( value operand: Operand , path: Path ) -> WalkResult {
49
51
switch operand. instruction {
@@ -67,11 +69,20 @@ private struct IsBareObjectWalker : ValueDefUseWalker {
67
69
switch operand. instruction {
68
70
// White-list all instructions which don't use the object header.
69
71
case is RefElementAddrInst , is RefTailAddrInst ,
70
- is DeallocRefInst , is DeallocStackRefInst ,
72
+ is DeallocStackRefInst ,
71
73
is DebugValueInst , is FixLifetimeInst :
72
74
return . continueWalk
75
+ case let deallocRef as DeallocRefInst :
76
+ // Check if the final dealloc_ref comes from the single `rootDef`.
77
+ // In case of phi-arguments it might come from multiple root definitions.
78
+ return walkUp ( value: deallocRef. operand. value, path: path)
73
79
default :
74
80
return . abortWalk
75
81
}
76
82
}
83
+
84
+ mutating func rootDef( value: Value , path: SmallProjectionPath ) -> WalkResult {
85
+ return value == rootDef ? . continueWalk : . abortWalk
86
+ }
87
+
77
88
}
0 commit comments