From be72ad726aab58ae31be9c88ec984a3b00aa9dd5 Mon Sep 17 00:00:00 2001 From: Jakub Florek Date: Tue, 9 Sep 2025 17:02:29 +0100 Subject: [PATCH] Fix licm not projecting load path before load splitting. --- .../LoopInvariantCodeMotion.swift | 3 +- test/SILOptimizer/licm.sil | 41 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LoopInvariantCodeMotion.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LoopInvariantCodeMotion.swift index c250890da4080..04306c9dcedb3 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LoopInvariantCodeMotion.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LoopInvariantCodeMotion.swift @@ -587,7 +587,8 @@ private extension AnalyzedInstructions { continue } - guard let splitLoads = loadInst.trySplit(alongPath: accessPath.projectionPath, context) else { + guard let projectionPath = loadInst.operand.value.accessPath.getProjection(to: accessPath), + let splitLoads = loadInst.trySplit(alongPath: projectionPath, context) else { newLoads.push(loadInst) return false } diff --git a/test/SILOptimizer/licm.sil b/test/SILOptimizer/licm.sil index 73c581511fa46..e456cefed10b5 100644 --- a/test/SILOptimizer/licm.sil +++ b/test/SILOptimizer/licm.sil @@ -1514,6 +1514,47 @@ bb2: return %r1 : $() } +struct Outer { + var interactions: Inner +} + +public struct Inner { + public let x: Int + var storage: ContiguousArray +} + +sil @$get_array_from_inner : $@convention(method) (Inner) -> (ContiguousArray) + +// Make sure we project load access path to matching store access path. +// Otherwise the pass could crash. +// +// CHECK-LABEL: sil @project_load_path_before_splitting_crash : +// CHECK: load +// CHECK: bb1(%8 : $ContiguousArray): +// CHECK: bb3: +// CHECK: store +// CHECK: } // end sil function 'project_load_path_before_splitting_crash' +sil @project_load_path_before_splitting_crash : $@convention(thin) (@inout Outer) -> () { +bb0(%0 : $*Outer): + %1 = struct_element_addr %0, #Outer.interactions + %2 = struct_element_addr %1, #Inner.storage + br bb1 + +bb1: + %4 = load %1 + %5 = function_ref @$get_array_from_inner : $@convention(method) (Inner) -> ContiguousArray + %6 = apply %5(%4) : $@convention(method) (Inner) -> ContiguousArray + store %6 to %2 + cond_br undef, bb2, bb3 + +bb2: + br bb1 + +bb3: + %10 = tuple () + return %10 +} + // CHECK-LABEL: sil @dont_hoist_builtin_once_memory_conflict : // CHECK: function_ref // CHECK: br bb1