[llvm] [MemCpyOpt] Continue merging memset with unrelated clobber (PR #89550)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 23 00:07:23 PDT 2024
https://github.com/XChy updated https://github.com/llvm/llvm-project/pull/89550
>From 18e8374820a5b51c297ae3b011593c2860ec3cd8 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Mon, 22 Apr 2024 00:46:18 +0800
Subject: [PATCH 1/3] [MemCpyOpt] Precommit tests for merging into memset (NFC)
---
.../Transforms/MemCpyOpt/merge-into-memset.ll | 153 +++++++++++++++++-
1 file changed, 151 insertions(+), 2 deletions(-)
diff --git a/llvm/test/Transforms/MemCpyOpt/merge-into-memset.ll b/llvm/test/Transforms/MemCpyOpt/merge-into-memset.ll
index 78aa769982404a..a24696063e4d39 100644
--- a/llvm/test/Transforms/MemCpyOpt/merge-into-memset.ll
+++ b/llvm/test/Transforms/MemCpyOpt/merge-into-memset.ll
@@ -36,5 +36,154 @@ exit:
ret void
}
-declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
-declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)
+define void @memset_clobber_no_alias(ptr %p) {
+; CHECK-LABEL: @memset_clobber_no_alias(
+; CHECK-NEXT: [[STACK:%.*]] = alloca <256 x i8>, align 8
+; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 8
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 0, i64 16, i1 false)
+; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: ret void
+;
+ %stack = alloca <256 x i8>, align 8
+ %stack1 = getelementptr inbounds i8, ptr %stack, i64 8
+ call void @llvm.memset.p0.i64(ptr %stack1, i8 0, i64 136, i1 false)
+ call void @llvm.memset.p0.i64(ptr %p, i8 0, i64 16, i1 false)
+ %stack2 = getelementptr inbounds i8, ptr %stack, i64 24
+ call void @llvm.memset.p0.i64(ptr %stack2, i8 0, i64 24, i1 false)
+ ret void
+}
+
+define void @store_clobber_no_alias1(i64 %a, ptr %p) {
+; CHECK-LABEL: @store_clobber_no_alias1(
+; CHECK-NEXT: [[STACK:%.*]] = alloca <256 x i8>, align 8
+; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 8
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
+; CHECK-NEXT: store i64 [[A:%.*]], ptr [[P:%.*]], align 8
+; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: ret void
+;
+ %stack = alloca <256 x i8>, align 8
+ %stack1 = getelementptr inbounds i8, ptr %stack, i64 8
+ call void @llvm.memset.p0.i64(ptr %stack1, i8 0, i64 136, i1 false)
+ store i64 %a, ptr %p, align 8
+ %stack2 = getelementptr inbounds i8, ptr %stack, i64 24
+ call void @llvm.memset.p0.i64(ptr %stack2, i8 0, i64 24, i1 false)
+ ret void
+}
+
+define void @store_clobber_no_alias2(i64 %a, ptr %p) {
+; CHECK-LABEL: @store_clobber_no_alias2(
+; CHECK-NEXT: [[STACK:%.*]] = alloca <256 x i8>, align 8
+; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 8
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
+; CHECK-NEXT: store i64 [[A:%.*]], ptr [[P:%.*]], align 8
+; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: ret void
+;
+ %stack = alloca <256 x i8>, align 8
+ %stack1 = getelementptr inbounds i8, ptr %stack, i64 8
+ call void @llvm.memset.p0.i64(ptr %stack1, i8 0, i64 136, i1 false)
+ store i64 %a, ptr %p, align 8
+ %stack2 = getelementptr inbounds i8, ptr %stack, i64 24
+ call void @llvm.memset.p0.i64(ptr %stack2, i8 0, i64 24, i1 false)
+ ret void
+}
+
+define void @store_clobber_no_alias_precise_fail(i64 %a) {
+; CHECK-LABEL: @store_clobber_no_alias_precise_fail(
+; CHECK-NEXT: [[STACK:%.*]] = alloca <256 x i8>, align 8
+; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 8
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
+; CHECK-NEXT: store i64 [[A:%.*]], ptr [[STACK]], align 8
+; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: ret void
+;
+ %stack = alloca <256 x i8>, align 8
+ %stack1 = getelementptr inbounds i8, ptr %stack, i64 8
+ call void @llvm.memset.p0.i64(ptr %stack1, i8 0, i64 136, i1 false)
+ store i64 %a, ptr %stack, align 8
+ %stack2 = getelementptr inbounds i8, ptr %stack, i64 24
+ call void @llvm.memset.p0.i64(ptr %stack2, i8 0, i64 24, i1 false)
+ ret void
+}
+
+define void @store_clobber_may_alias_fail(ptr %p, ptr %p1) {
+; CHECK-LABEL: @store_clobber_may_alias_fail(
+; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK:%.*]], i64 8
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
+; CHECK-NEXT: store i64 0, ptr [[P1:%.*]], align 8
+; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: ret void
+;
+ %stack1 = getelementptr inbounds i8, ptr %p, i64 8
+ call void @llvm.memset.p0.i64(ptr %stack1, i8 0, i64 136, i1 false)
+ store i64 0, ptr %p1, align 8
+ %stack2 = getelementptr inbounds i8, ptr %p, i64 24
+ call void @llvm.memset.p0.i64(ptr %stack2, i8 0, i64 24, i1 false)
+ ret void
+}
+
+define void @load_clobber_fail(ptr %p, ptr %p1) {
+; CHECK-LABEL: @load_clobber_fail(
+; CHECK-NEXT: [[STACK:%.*]] = alloca <256 x i8>, align 8
+; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 8
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
+; CHECK-NEXT: [[A:%.*]] = load i64, ptr [[P:%.*]], align 8
+; CHECK-NEXT: store i64 [[A]], ptr [[P1:%.*]], align 8
+; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: ret void
+;
+ %stack = alloca <256 x i8>, align 8
+ %stack1 = getelementptr inbounds i8, ptr %stack, i64 8
+ call void @llvm.memset.p0.i64(ptr %stack1, i8 0, i64 136, i1 false)
+ %a = load i64, ptr %p, align 8
+ store i64 %a, ptr %p1, align 8
+ %stack2 = getelementptr inbounds i8, ptr %stack, i64 24
+ call void @llvm.memset.p0.i64(ptr %stack2, i8 0, i64 24, i1 false)
+ ret void
+}
+
+define void @memset_volatile_fail(ptr %p) {
+; CHECK-LABEL: @memset_volatile_fail(
+; CHECK-NEXT: [[STACK:%.*]] = alloca <256 x i8>, align 8
+; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 8
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 0, i64 16, i1 true)
+; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: ret void
+;
+ %stack = alloca <256 x i8>, align 8
+ %stack1 = getelementptr inbounds i8, ptr %stack, i64 8
+ call void @llvm.memset.p0.i64(ptr %stack1, i8 0, i64 136, i1 false)
+ call void @llvm.memset.p0.i64(ptr %p, i8 0, i64 16, i1 true)
+ %stack2 = getelementptr inbounds i8, ptr %stack, i64 24
+ call void @llvm.memset.p0.i64(ptr %stack2, i8 0, i64 24, i1 false)
+ ret void
+}
+
+define void @store_volatile_fail(i64 %a, ptr %p) {
+; CHECK-LABEL: @store_volatile_fail(
+; CHECK-NEXT: [[STACK:%.*]] = alloca <256 x i8>, align 8
+; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 8
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
+; CHECK-NEXT: store volatile i64 [[A:%.*]], ptr [[P:%.*]], align 8
+; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: ret void
+;
+ %stack = alloca <256 x i8>, align 8
+ %stack1 = getelementptr inbounds i8, ptr %stack, i64 8
+ call void @llvm.memset.p0.i64(ptr %stack1, i8 0, i64 136, i1 false)
+ store volatile i64 %a, ptr %p
+ %stack2 = getelementptr inbounds i8, ptr %stack, i64 24
+ call void @llvm.memset.p0.i64(ptr %stack2, i8 0, i64 24, i1 false)
+ ret void
+}
>From 6da7237c2d7b5c18a68ef61e8a0605516ff07f64 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Mon, 22 Apr 2024 00:29:53 +0800
Subject: [PATCH 2/3] [MemCpyOpt] Continue merge memset with unrelated clobber
---
llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp | 14 ++++++++++++--
llvm/test/Transforms/MemCpyOpt/form-memset.ll | 4 ++--
.../test/Transforms/MemCpyOpt/merge-into-memset.ll | 9 +++------
3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 1036b8ae963a24..9cf31de95ca3b1 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -399,6 +399,9 @@ Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,
// If this is a store, see if we can merge it in.
if (!NextStore->isSimple()) break;
+ if (AA->isNoAlias(NextStore->getPointerOperand(), StartPtr))
+ continue;
+
Value *StoredVal = NextStore->getValueOperand();
// Don't convert stores of non-integral pointer types to memsets (which
@@ -420,6 +423,7 @@ Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,
// Check to see if this store is to a constant offset from the start ptr.
std::optional<int64_t> Offset =
NextStore->getPointerOperand()->getPointerOffsetFrom(StartPtr, DL);
+
if (!Offset)
break;
@@ -427,13 +431,19 @@ Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,
} else {
auto *MSI = cast<MemSetInst>(BI);
- if (MSI->isVolatile() || ByteVal != MSI->getValue() ||
- !isa<ConstantInt>(MSI->getLength()))
+ if (MSI->isVolatile())
+ break;
+
+ if (AA->isNoAlias(MSI->getDest(), StartPtr))
+ continue;
+
+ if (ByteVal != MSI->getValue() || !isa<ConstantInt>(MSI->getLength()))
break;
// Check to see if this store is to a constant offset from the start ptr.
std::optional<int64_t> Offset =
MSI->getDest()->getPointerOffsetFrom(StartPtr, DL);
+
if (!Offset)
break;
diff --git a/llvm/test/Transforms/MemCpyOpt/form-memset.ll b/llvm/test/Transforms/MemCpyOpt/form-memset.ll
index 020a72183e9ea1..edcf27e48f3bda 100644
--- a/llvm/test/Transforms/MemCpyOpt/form-memset.ll
+++ b/llvm/test/Transforms/MemCpyOpt/form-memset.ll
@@ -97,7 +97,6 @@ define void @test2() nounwind {
; CHECK-NEXT: [[TMP38:%.*]] = getelementptr [8 x i8], ptr [[REF_IDX]], i32 0, i32 1
; CHECK-NEXT: [[TMP41:%.*]] = getelementptr [8 x i8], ptr [[REF_IDX]], i32 0, i32 0
; CHECK-NEXT: [[TMP43:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 7, i32 0
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP41]], i8 -1, i64 8, i1 false)
; CHECK-NEXT: [[TMP46:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 7, i32 1
; CHECK-NEXT: [[TMP57:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 6, i32 0
; CHECK-NEXT: [[TMP60:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 6, i32 1
@@ -114,7 +113,6 @@ define void @test2() nounwind {
; CHECK-NEXT: [[TMP141:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 0, i32 0
; CHECK-NEXT: [[TMP144:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 0, i32 1
; CHECK-NEXT: [[TMP148:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 7, i32 0
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP141]], i8 0, i64 32, i1 false)
; CHECK-NEXT: [[TMP151:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 7, i32 1
; CHECK-NEXT: [[TMP162:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 6, i32 0
; CHECK-NEXT: [[TMP165:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 6, i32 1
@@ -132,6 +130,8 @@ define void @test2() nounwind {
; CHECK-NEXT: [[TMP249:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 0, i32 1
; CHECK-NEXT: [[UP_MVD252:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 0
; CHECK-NEXT: [[LEFT_MVD253:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 0
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP41]], i8 -1, i64 8, i1 false)
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP141]], i8 0, i64 32, i1 false)
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP246]], i8 0, i64 32, i1 false)
; CHECK-NEXT: call void @foo(ptr [[UP_MVD252]], ptr [[LEFT_MVD253]], ptr [[TMP41]]) #[[ATTR0]]
; CHECK-NEXT: ret void
diff --git a/llvm/test/Transforms/MemCpyOpt/merge-into-memset.ll b/llvm/test/Transforms/MemCpyOpt/merge-into-memset.ll
index a24696063e4d39..8015b21023995e 100644
--- a/llvm/test/Transforms/MemCpyOpt/merge-into-memset.ll
+++ b/llvm/test/Transforms/MemCpyOpt/merge-into-memset.ll
@@ -40,10 +40,9 @@ define void @memset_clobber_no_alias(ptr %p) {
; CHECK-LABEL: @memset_clobber_no_alias(
; CHECK-NEXT: [[STACK:%.*]] = alloca <256 x i8>, align 8
; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 8
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 0, i64 16, i1 false)
; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
; CHECK-NEXT: ret void
;
%stack = alloca <256 x i8>, align 8
@@ -59,10 +58,9 @@ define void @store_clobber_no_alias1(i64 %a, ptr %p) {
; CHECK-LABEL: @store_clobber_no_alias1(
; CHECK-NEXT: [[STACK:%.*]] = alloca <256 x i8>, align 8
; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 8
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
; CHECK-NEXT: store i64 [[A:%.*]], ptr [[P:%.*]], align 8
; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
; CHECK-NEXT: ret void
;
%stack = alloca <256 x i8>, align 8
@@ -78,10 +76,9 @@ define void @store_clobber_no_alias2(i64 %a, ptr %p) {
; CHECK-LABEL: @store_clobber_no_alias2(
; CHECK-NEXT: [[STACK:%.*]] = alloca <256 x i8>, align 8
; CHECK-NEXT: [[STACK1:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 8
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
; CHECK-NEXT: store i64 [[A:%.*]], ptr [[P:%.*]], align 8
; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[STACK]], i64 24
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK2]], i8 0, i64 24, i1 false)
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[STACK1]], i8 0, i64 136, i1 false)
; CHECK-NEXT: ret void
;
%stack = alloca <256 x i8>, align 8
>From dd84a531f55f46f9ac7a5d87c69ab4c178323581 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 23 Apr 2024 15:07:00 +0800
Subject: [PATCH 3/3] [MemCpyOpt] Use BatchAA
---
.../lib/Transforms/Scalar/MemCpyOptimizer.cpp | 39 +++++++++----------
1 file changed, 19 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 9cf31de95ca3b1..e335926c1aa84c 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -373,6 +373,9 @@ Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,
// the new memset. The new MemoryDef for the inserted memsets will be inserted
// after MemInsertPoint.
MemoryUseOrDef *MemInsertPoint = nullptr;
+ MemoryLocation StartPtrLocation = MemoryLocation::getBeforeOrAfter(StartPtr);
+ BatchAAResults BAA(*AA);
+
for (++BI; !BI->isTerminator(); ++BI) {
auto *CurrentAcc = cast_or_null<MemoryUseOrDef>(
MSSAU->getMemorySSA()->getMemoryAccess(&*BI));
@@ -386,22 +389,26 @@ Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,
continue;
}
- if (!isa<StoreInst>(BI) && !isa<MemSetInst>(BI)) {
- // If the instruction is readnone, ignore it, otherwise bail out. We
- // don't even allow readonly here because we don't want something like:
- // A[1] = 2; strlen(A); A[2] = 2; -> memcpy(A, ...); strlen(A).
- if (BI->mayWriteToMemory() || BI->mayReadFromMemory())
+ if (BI->isVolatile() || BI->isAtomic())
+ break;
+
+ // If the instruction reads something, bail out. We
+ // don't even allow readonly here because we don't want something like:
+ // A[1] = 2; strlen(A); A[2] = 2; -> memcpy(A, ...); strlen(A).
+ if (BI->mayReadFromMemory())
+ break;
+
+ if (BI->mayWriteToMemory()) {
+ // Skip unrelated write clobbers.
+ if (isNoModRef(BAA.getModRefInfo(&*BI, StartPtrLocation)))
+ continue;
+ // Bail out if an unmergable write clobbers.
+ if (!isa<StoreInst>(BI) && !isa<MemSetInst>(BI))
break;
- continue;
}
if (auto *NextStore = dyn_cast<StoreInst>(BI)) {
// If this is a store, see if we can merge it in.
- if (!NextStore->isSimple()) break;
-
- if (AA->isNoAlias(NextStore->getPointerOperand(), StartPtr))
- continue;
-
Value *StoredVal = NextStore->getValueOperand();
// Don't convert stores of non-integral pointer types to memsets (which
@@ -428,15 +435,7 @@ Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,
break;
Ranges.addStore(*Offset, NextStore);
- } else {
- auto *MSI = cast<MemSetInst>(BI);
-
- if (MSI->isVolatile())
- break;
-
- if (AA->isNoAlias(MSI->getDest(), StartPtr))
- continue;
-
+ } else if (auto *MSI = dyn_cast<MemSetInst>(BI)) {
if (ByteVal != MSI->getValue() || !isa<ConstantInt>(MSI->getLength()))
break;
More information about the llvm-commits
mailing list