Skip to content

Commit 0eed6ec

Browse files
committed
[InstCombine] Support offsets in memset to load forwarding
Adds support for load offsets when performing `memset` to load forwarding.
1 parent 5f56ddb commit 0eed6ec

File tree

3 files changed

+13
-25
lines changed

3 files changed

+13
-25
lines changed

llvm/lib/Analysis/Loads.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -631,9 +631,13 @@ static Value *getAvailableLoadStore(Instruction *Inst, const Value *Ptr,
631631
if (!Val || !Len)
632632
return nullptr;
633633

634-
// TODO: Handle offsets.
635-
Value *Dst = MSI->getDest();
636-
if (!AreEquivalentAddressValues(Dst, Ptr))
634+
// Handle offsets.
635+
int64_t StoreOffset = 0, LoadOffset = 0;
636+
const Value *StoreBase =
637+
GetPointerBaseWithConstantOffset(MSI->getDest(), StoreOffset, DL);
638+
const Value *LoadBase =
639+
GetPointerBaseWithConstantOffset(Ptr, LoadOffset, DL);
640+
if (StoreBase != LoadBase || LoadOffset < StoreOffset)
637641
return nullptr;
638642

639643
if (IsLoadCSE)
@@ -645,7 +649,7 @@ static Value *getAvailableLoadStore(Instruction *Inst, const Value *Ptr,
645649

646650
// Make sure the read bytes are contained in the memset.
647651
uint64_t LoadSize = LoadTypeSize.getFixedValue();
648-
if ((Len->getValue() * 8).ult(LoadSize))
652+
if ((Len->getValue() * 8).ult(LoadSize + (LoadOffset - StoreOffset) * 8))
649653
return nullptr;
650654

651655
APInt Splat = LoadSize >= 8 ? APInt::getSplat(LoadSize, Val->getValue())

llvm/test/Analysis/GlobalsModRef/memset-escape.ll

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,14 @@ target triple = "x86_64-apple-macosx10.10.0"
77
@a = internal global [3 x i32] zeroinitializer, align 4
88
@b = common global i32 0, align 4
99

10-
; The important thing we're checking for here is the reload of (some element of)
11-
; @a after the memset.
10+
; The important thing we're checking here is that the value from the memset
11+
; rather than the preceding store is forwarded.
1212

1313
define i32 @main() {
1414
; CHECK-LABEL: define noundef i32 @main(
1515
; CHECK-SAME: ) local_unnamed_addr #[[ATTR0:[0-9]+]] {
1616
; CHECK-NEXT: [[ENTRY:.*:]]
17-
; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @a, i64 8), align 4
18-
; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 4 dereferenceable(12) @a, i8 0, i64 12, i1 false)
1917
; CHECK-NEXT: store i32 3, ptr @b, align 4
20-
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @a, i64 8), align 4
21-
; CHECK-NEXT: [[CMP1_NOT:%.*]] = icmp eq i32 [[TMP0]], 0
22-
; CHECK-NEXT: br i1 [[CMP1_NOT]], label %[[IF_END:.*]], label %[[IF_THEN:.*]]
23-
; CHECK: [[IF_THEN]]:
24-
; CHECK-NEXT: tail call void @abort()
25-
; CHECK-NEXT: unreachable
26-
; CHECK: [[IF_END]]:
2718
; CHECK-NEXT: ret i32 0
2819
;
2920
entry:

llvm/test/Transforms/InstCombine/load-store-forward.ll

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -365,13 +365,10 @@ define i32 @load_after_memset_unknown(ptr %a, i8 %byte) {
365365
ret i32 %v
366366
}
367367

368-
; TODO: Handle load at offset.
369368
define i32 @load_after_memset_0_offset(ptr %a) {
370369
; CHECK-LABEL: @load_after_memset_0_offset(
371370
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(16) [[A:%.*]], i8 0, i64 16, i1 false)
372-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 4
373-
; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[GEP]], align 4
374-
; CHECK-NEXT: ret i32 [[V]]
371+
; CHECK-NEXT: ret i32 0
375372
;
376373
call void @llvm.memset.p0.i64(ptr %a, i8 0, i64 16, i1 false)
377374
%gep = getelementptr i8, ptr %a, i64 4
@@ -382,9 +379,7 @@ define i32 @load_after_memset_0_offset(ptr %a) {
382379
define i32 @load_after_memset_1_offset(ptr %a) {
383380
; CHECK-LABEL: @load_after_memset_1_offset(
384381
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(16) [[A:%.*]], i8 1, i64 16, i1 false)
385-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 4
386-
; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[GEP]], align 4
387-
; CHECK-NEXT: ret i32 [[V]]
382+
; CHECK-NEXT: ret i32 16843009
388383
;
389384
call void @llvm.memset.p0.i64(ptr %a, i8 1, i64 16, i1 false)
390385
%gep = getelementptr i8, ptr %a, i64 4
@@ -395,9 +390,7 @@ define i32 @load_after_memset_1_offset(ptr %a) {
395390
define i1 @load_after_memset_0_offset_i1(ptr %a) {
396391
; CHECK-LABEL: @load_after_memset_0_offset_i1(
397392
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(16) [[A:%.*]], i8 0, i64 16, i1 false)
398-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 12
399-
; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[GEP]], align 1
400-
; CHECK-NEXT: ret i1 [[V]]
393+
; CHECK-NEXT: ret i1 false
401394
;
402395
call void @llvm.memset.p0.i64(ptr %a, i8 0, i64 16, i1 false)
403396
%gep = getelementptr i1, ptr %a, i64 12

0 commit comments

Comments
 (0)