Skip to content

Commit f043b36

Browse files
committed
RedundantLoadElimination: insert mark_dependence instructions for a removed load
If the memory location depends on something, insert a dependency for the loaded value: ``` %2 = mark_dependence %1 on %0 %3 = load %2 ``` -> ``` %2 = mark_dependence %1 on %0 // not needed anymore, can be removed eventually %3 = load %2 %4 = mark_dependence %3 on %0 // replace %3 with %4 ```
1 parent 63961e9 commit f043b36

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RedundantLoadElimination.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,10 @@ private func replace(load: LoadInst, with availableValues: [AvailableValue], _ c
279279
//
280280
newValue = ssaUpdater.getValue(inMiddleOf: load.parentBlock)
281281
}
282+
283+
// Make sure to keep dependencies valid after replacing the load
284+
insertMarkDependencies(for: load, context)
285+
282286
load.replace(with: newValue, context)
283287
}
284288

@@ -306,6 +310,39 @@ private func provideValue(
306310
}
307311
}
308312

313+
/// If the memory location depends on something, insert a dependency for the loaded value:
314+
///
315+
/// %2 = mark_dependence %1 on %0
316+
/// %3 = load %2
317+
/// ->
318+
/// %2 = mark_dependence %1 on %0 // not needed anymore, can be removed eventually
319+
/// %3 = load %2
320+
/// %4 = mark_dependence %3 on %0
321+
/// // replace %3 with %4
322+
///
323+
private func insertMarkDependencies(for load: LoadInst, _ context: FunctionPassContext) {
324+
var inserter = MarkDependenceInserter(load: load, context: context)
325+
_ = inserter.walkUp(address: load.address, path: UnusedWalkingPath())
326+
}
327+
328+
private struct MarkDependenceInserter : AddressUseDefWalker {
329+
let load: LoadInst
330+
let context: FunctionPassContext
331+
332+
mutating func walkUp(address: Value, path: UnusedWalkingPath) -> WalkResult {
333+
if let mdi = address as? MarkDependenceInst {
334+
let builder = Builder(after: load, context)
335+
let newMdi = builder.createMarkDependence(value: load, base: mdi.base, kind: mdi.dependenceKind)
336+
load.uses.ignore(user: newMdi).replaceAll(with: newMdi, context)
337+
}
338+
return walkUpDefault(address: address, path: path)
339+
}
340+
341+
mutating func rootDef(address: Value, path: UnusedWalkingPath) -> WalkResult {
342+
return .continueWalk
343+
}
344+
}
345+
309346
/// In case of a `load [take]` shrink lifetime of the value in memory back to the `availableValue`
310347
/// and return the (possibly projected) available value. For example:
311348
///

test/SILOptimizer/redundant_load_elim_ossa.sil

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,6 +1271,39 @@ bb0(%0 : $*Builtin.Int64, %1 : @guaranteed $Builtin.NativeObject):
12711271
return %6 : $(Builtin.Int64, Builtin.Int64)
12721272
}
12731273

1274+
// CHECK-LABEL: sil [ossa] @insert_mark_dependence :
1275+
// CHECK: mark_dependence
1276+
// CHECK: [[MD:%.*]] = mark_dependence %0 : $B on %1
1277+
// CHECK: return [[MD]]
1278+
// CHECK-LABEL: } // end sil function 'insert_mark_dependence'
1279+
sil [ossa] @insert_mark_dependence : $@convention(thin) (@owned B, @guaranteed B) -> @owned B {
1280+
bb0(%0 : @owned $B, %1 : @guaranteed $B):
1281+
%2 = alloc_stack $B
1282+
store %0 to [init] %2
1283+
%4 = mark_dependence %2 on %1
1284+
%5 = load [take] %4
1285+
dealloc_stack %2
1286+
return %5
1287+
}
1288+
1289+
// CHECK-LABEL: sil [ossa] @insert_two_mark_dependences :
1290+
// CHECK: mark_dependence
1291+
// CHECK: mark_dependence
1292+
// CHECK: [[MD1:%.*]] = mark_dependence %0 : $B on %1
1293+
// CHECK: [[MD2:%.*]] = mark_dependence [[MD1]] : $B on %2
1294+
// CHECK: return [[MD2]]
1295+
// CHECK-LABEL: } // end sil function 'insert_two_mark_dependences'
1296+
sil [ossa] @insert_two_mark_dependences : $@convention(thin) (@owned B, @guaranteed B, @guaranteed B) -> @owned B {
1297+
bb0(%0 : @owned $B, %1 : @guaranteed $B, %2 : @guaranteed $B):
1298+
%3 = alloc_stack $B
1299+
store %0 to [init] %3
1300+
%5 = mark_dependence %3 on %1
1301+
%6 = mark_dependence %5 on %2
1302+
%7 = load [take] %6
1303+
dealloc_stack %3
1304+
return %7
1305+
}
1306+
12741307
// CHECK-LABEL: sil [ossa] @dont_crash_on_index_addr_projection :
12751308
// CHECK-LABEL: } // end sil function 'dont_crash_on_index_addr_projection'
12761309
sil [ossa] @dont_crash_on_index_addr_projection : $@convention(thin) (Builtin.RawPointer) -> (Int, Int, Int, Int) {

0 commit comments

Comments
 (0)