Skip to content

Commit 5c97397

Browse files
authored
[SROA] Support load-only promotion with dynamic offset loads (#135609)
If we do load-only promotion, it is okay if we leave some loads alone. We only need to know all stores that affect a specific location. As such, we can handle loads with unknown offset via the "escaped read-only" code path. This is something we already support in LICM load-only promotion, but doing this in SROA is much better from a phase ordering perspective. Fixes #134513.
1 parent 1588aab commit 5c97397

File tree

2 files changed

+9
-3
lines changed

2 files changed

+9
-3
lines changed

llvm/lib/Transforms/Scalar/SROA.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1114,8 +1114,10 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
11141114
assert((!LI.isSimple() || LI.getType()->isSingleValueType()) &&
11151115
"All simple FCA loads should have been pre-split");
11161116

1117+
// If there is a load with an unknown offset, we can still perform store
1118+
// to load forwarding for other known-offset loads.
11171119
if (!IsOffsetKnown)
1118-
return PI.setAborted(&LI);
1120+
return PI.setEscapedReadOnly(&LI);
11191121

11201122
TypeSize Size = DL.getTypeStoreSize(LI.getType());
11211123
if (Size.isScalable())

llvm/test/Transforms/SROA/readonlynocapture.ll

+6-2
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@ define i32 @twoalloc_with_lifetimes() {
501501

502502
declare void @use.i32(i32)
503503

504+
; We can promote the %i load, even though there is an unknown offset load
505+
; in the loop. It is sufficient that we know all stores.
504506
define void @load_dyn_offset(ptr %ary) {
505507
; CHECK-LABEL: @load_dyn_offset(
506508
; CHECK-NEXT: [[A:%.*]] = alloca { i64, [4 x i32] }, align 8
@@ -509,8 +511,8 @@ define void @load_dyn_offset(ptr %ary) {
509511
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[GEP]], ptr [[ARY:%.*]], i64 16, i1 false)
510512
; CHECK-NEXT: br label [[LOOP:%.*]]
511513
; CHECK: loop:
512-
; CHECK-NEXT: [[I:%.*]] = load i64, ptr [[A]], align 4
513-
; CHECK-NEXT: [[I_NEXT:%.*]] = add i64 [[I]], 1
514+
; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[TMP0:%.*]] ]
515+
; CHECK-NEXT: [[I_NEXT]] = add i64 [[I]], 1
514516
; CHECK-NEXT: store i64 [[I_NEXT]], ptr [[A]], align 4
515517
; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr i32, ptr [[GEP]], i64 [[I]]
516518
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[GEP_I]], align 4
@@ -540,6 +542,8 @@ exit:
540542
ret void
541543
}
542544

545+
; Same as previous test, but with an unknown-offset store. We can't promote in
546+
; that case.
543547
define void @store_dyn_offset(ptr %ary) {
544548
; CHECK-LABEL: @store_dyn_offset(
545549
; CHECK-NEXT: [[A:%.*]] = alloca { i64, [4 x i32] }, align 8

0 commit comments

Comments
 (0)