Skip to content

Commit dca0209

Browse files
authored
Merge pull request #31807 from eeckstein/licm-improvement
LICM: enable more stores to moved out of a loop
2 parents 0c403fe + ba4da8e commit dca0209

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

lib/SILOptimizer/LoopTransforms/LICM.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,41 @@ static bool storesCommonlyDominateLoopExits(SILValue addr, SILLoop *loop,
963963
if (stores.count(header) != 0)
964964
return true;
965965

966+
// Also a store in the pre-header dominates all exists. Although the situation
967+
// is a bit different here: the store in the pre-header remains - it's not
968+
// (re)moved by the LICM transformation.
969+
// But even if the loop-stores are not dominating the loop exits, it
970+
// makes sense to move them out of the loop if this case. When this is done,
971+
// dead-store-elimination can then most likely eliminate the store in the
972+
// pre-header.
973+
//
974+
// pre_header:
975+
// store %v1 to %addr
976+
// header:
977+
// cond_br %cond, then, tail
978+
// then:
979+
// store %v2 to %addr // a conditional store in the loop
980+
// br tail
981+
// tail:
982+
// cond_br %loop_cond, header, exit
983+
// exit:
984+
//
985+
// will be transformed to
986+
//
987+
// pre_header:
988+
// store %v1 to %addr // <- can be removed by DSE afterwards
989+
// header:
990+
// cond_br %cond, then, tail
991+
// then:
992+
// br tail
993+
// tail(%phi):
994+
// cond_br %loop_cond, header, exit
995+
// exit:
996+
// store %phi to %addr
997+
//
998+
if (stores.count(loop->getLoopPreheader()) != 0)
999+
return true;
1000+
9661001
// Propagate the store-is-not-alive flag through the control flow in the loop,
9671002
// starting at the header.
9681003
SmallPtrSet<SILBasicBlock *, 16> storesNotAlive;

test/SILOptimizer/licm.sil

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,47 @@ bb6:
502502
return %12 : $()
503503
}
504504

505+
// CHECK-LABEL: sil @hoist_when_store_is_in_preheader
506+
// CHECK: bb0(%0 : $*Int32, %1 : $Int32):
507+
// CHECK: store
508+
// CHECK: load
509+
// CHECK: bb1(%{{[0-9]+}} : $Int32):
510+
// CHECK-NOT: load
511+
// CHECK-NOT: store
512+
// CHECK: bb4([[P:%[0-9]+]] : $Int32):
513+
// CHECK: bb6:
514+
// CHECK: store [[P]] to %0
515+
// CHECK: } // end sil function 'hoist_when_store_is_in_preheader'
516+
sil @hoist_when_store_is_in_preheader : $@convention(thin) (@inout Int32, Int32) -> () {
517+
bb0(%0 : $*Int32, %1 : $Int32):
518+
%8 = struct_element_addr %0 : $*Int32, #Int32._value
519+
%9 = struct_extract %1 : $Int32, #Int32._value
520+
%10 = integer_literal $Builtin.Int1, 0
521+
store %1 to %0 : $*Int32
522+
br bb1
523+
524+
bb1:
525+
%17 = load %8 : $*Builtin.Int32
526+
%18 = builtin "sadd_with_overflow_Int64"(%17 : $Builtin.Int32, %9 : $Builtin.Int32, %10 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
527+
%19 = tuple_extract %18 : $(Builtin.Int32, Builtin.Int1), 0
528+
%20 = struct $Int32 (%19 : $Builtin.Int32)
529+
cond_br undef, bb2, bb3
530+
bb2:
531+
br bb4
532+
bb3:
533+
store %20 to %0 : $*Int32
534+
br bb4
535+
bb4:
536+
cond_br undef, bb5, bb6
537+
538+
bb5:
539+
br bb1
540+
541+
bb6:
542+
%12 = tuple ()
543+
return %12 : $()
544+
}
545+
505546
// CHECK-LABEL: sil @hoist_loads_and_stores_multiple_exits
506547
// CHECK: [[V1:%[0-9]+]] = load %0
507548
// CHECK: br bb1([[V1]] : $Int32)

0 commit comments

Comments
 (0)