From 89b0de3563cf34d99acfad53ed68c44f9de20087 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 14 Jul 2023 19:37:34 +0200 Subject: [PATCH] StackPromotion: fix a crash due to a problem in liferange evaluation The analysis to check if an alloc_ref outlives it's "inner" liferange had a bug which resulted in a crash in the StackPromotion pass rdar://112275272 --- .../FunctionPasses/StackPromotion.swift | 5 ++-- test/SILOptimizer/stack_promotion.sil | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift index 4c3c9bedb7201..10c606fe7954a 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift @@ -289,14 +289,13 @@ private extension BasicBlockRange { /// Returns true if there is a direct edge connecting this range with the `otherRange`. func hasControlFlowEdge(to otherRange: BasicBlockRange) -> Bool { func isOnlyInOtherRange(_ block: BasicBlock) -> Bool { - return !inclusiveRangeContains(block) && - otherRange.inclusiveRangeContains(block) && block != otherRange.begin + return !inclusiveRangeContains(block) && otherRange.inclusiveRangeContains(block) } for lifeBlock in inclusiveRange { assert(otherRange.inclusiveRangeContains(lifeBlock), "range must be a subset of other range") for succ in lifeBlock.successors { - if isOnlyInOtherRange(succ) { + if isOnlyInOtherRange(succ) && succ != otherRange.begin { return true } // The entry of the begin-block is conceptually not part of the range. We can check if diff --git a/test/SILOptimizer/stack_promotion.sil b/test/SILOptimizer/stack_promotion.sil index 805f940a494f3..ea2d6f7c96f37 100644 --- a/test/SILOptimizer/stack_promotion.sil +++ b/test/SILOptimizer/stack_promotion.sil @@ -1209,3 +1209,27 @@ bb3: br bb3 } +// CHECK-LABEL: sil @inner_liferange_jumps_to_outer_in_header_block +// CHECK: alloc_ref $XX +// CHECK-LABEL: } // end sil function 'inner_liferange_jumps_to_outer_in_header_block' +sil @inner_liferange_jumps_to_outer_in_header_block : $@convention(thin) (@owned XX) -> () { +bb0(%0 : $XX): + %1 = alloc_stack $XX + br bb1(%0 : $XX) + +bb1(%2 : $XX): + strong_release %2 : $XX + %4 = alloc_ref $XX + store %4 to %1 : $*XX + cond_br undef, bb2, bb3 + +bb2: + br bb1(%4 : $XX) + +bb3: + strong_release %4 : $XX + dealloc_stack %1 : $*XX + %r = tuple () + return %r : $() +} +