@@ -486,13 +486,23 @@ private extension Instruction {
486486 if !atp. needsStackProtection {
487487 return nil
488488 }
489+ var hasNoStores = NoStores ( )
490+ if hasNoStores. walkDownUses ( ofValue: atp, path: SmallProjectionPath ( ) ) == . continueWalk {
491+ return nil
492+ }
493+
489494 // The result of an `address_to_pointer` may be used in any unsafe way, e.g.
490495 // passed to a C function.
491496 baseAddr = atp. operand
492497 case let ia as IndexAddrInst :
493498 if !ia. needsStackProtection {
494499 return nil
495500 }
501+ var hasNoStores = NoStores ( )
502+ if hasNoStores. walkDownUses ( ofAddress: ia, path: SmallProjectionPath ( ) ) == . continueWalk {
503+ return nil
504+ }
505+
496506 // `index_addr` is unsafe if not used for tail-allocated elements (e.g. in Array).
497507 baseAddr = ia. base
498508 default :
@@ -509,6 +519,29 @@ private extension Instruction {
509519 }
510520}
511521
522+ /// Checks if there are no stores to an address or raw pointer.
523+ private struct NoStores : ValueDefUseWalker , AddressDefUseWalker {
524+ var walkDownCache = WalkerCache < SmallProjectionPath > ( )
525+
526+ mutating func leafUse( value: Operand , path: SmallProjectionPath ) -> WalkResult {
527+ if let ptai = value. instruction as? PointerToAddressInst {
528+ return walkDownUses ( ofAddress: ptai, path: path)
529+ }
530+ return . abortWalk
531+ }
532+
533+ mutating func leafUse( address: Operand , path: SmallProjectionPath ) -> WalkResult {
534+ switch address. instruction {
535+ case is LoadInst :
536+ return . continueWalk
537+ case let cai as CopyAddrInst :
538+ return address == cai. sourceOperand ? . continueWalk : . abortWalk
539+ default :
540+ return . abortWalk
541+ }
542+ }
543+ }
544+
512545private extension Function {
513546 func setNeedsStackProtection( _ context: FunctionPassContext ) {
514547 if !needsStackProtection {
0 commit comments