Skip to content

[GVN] Drop Clobber dependency if store may overwrite only the same value #68322

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 40 additions & 5 deletions llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,43 @@ MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
return MemDepResult::getNonLocal();
}

// Check if SI that may alias with MemLoc can be safely skipped. This is
// possible in case if SI can only must alias or no alias with MemLoc (no
// partial overlapping possible) and it writes the same value that MemLoc
// contains now (it was loaded before this store and was not modified in
// between).
static bool canSkipClobberingStore(const StoreInst *SI,
const MemoryLocation &MemLoc,
Align MemLocAlign, BatchAAResults &BatchAA,
unsigned ScanLimit) {
if (!MemLoc.Size.hasValue())
return false;
if (MemoryLocation::get(SI).Size != MemLoc.Size)
return false;
if (std::min(MemLocAlign, SI->getAlign()).value() < MemLoc.Size.getValue())
return false;

auto *LI = dyn_cast<LoadInst>(SI->getValueOperand());
if (!LI || LI->getParent() != SI->getParent())
return false;
if (BatchAA.alias(MemoryLocation::get(LI), MemLoc) != AliasResult::MustAlias)
return false;
unsigned NumVisitedInsts = 0;
for (const Instruction *I = LI; I != SI; I = I->getNextNonDebugInstruction())
if (++NumVisitedInsts > ScanLimit ||
isModSet(BatchAA.getModRefInfo(I, MemLoc)))
return false;

return true;
}

MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
const MemoryLocation &MemLoc, bool isLoad, BasicBlock::iterator ScanIt,
BasicBlock *BB, Instruction *QueryInst, unsigned *Limit,
BatchAAResults &BatchAA) {
bool isInvariantLoad = false;
Align MemLocAlign =
MemLoc.Ptr->getPointerAlignment(BB->getModule()->getDataLayout());

unsigned DefaultLimit = getDefaultBlockScanLimit();
if (!Limit)
Expand Down Expand Up @@ -402,11 +434,12 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
// do want to respect mustalias results since defs are useful for value
// forwarding, but any mayalias write can be assumed to be noalias.
// Arguably, this logic should be pushed inside AliasAnalysis itself.
if (isLoad && QueryInst) {
LoadInst *LI = dyn_cast<LoadInst>(QueryInst);
if (LI && LI->hasMetadata(LLVMContext::MD_invariant_load))
isInvariantLoad = true;
}
if (isLoad && QueryInst)
if (LoadInst *LI = dyn_cast<LoadInst>(QueryInst)) {
if (LI->hasMetadata(LLVMContext::MD_invariant_load))
isInvariantLoad = true;
MemLocAlign = LI->getAlign();
}

// True for volatile instruction.
// For Load/Store return true if atomic ordering is stronger than AO,
Expand Down Expand Up @@ -577,6 +610,8 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
return MemDepResult::getDef(Inst);
if (isInvariantLoad)
continue;
if (canSkipClobberingStore(SI, MemLoc, MemLocAlign, BatchAA, *Limit))
continue;
return MemDepResult::getClobber(Inst);
}

Expand Down
12 changes: 4 additions & 8 deletions llvm/test/Transforms/GVN/rle-clobbering-store.ll
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ define i1 @test_i1(ptr %a, ptr %b, ptr %c) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i1, ptr [[A]], align 1
; CHECK-NEXT: store i1 [[TMP0]], ptr [[B]], align 1
; CHECK-NEXT: [[TMP1:%.*]] = load i1, ptr [[A]], align 1
; CHECK-NEXT: ret i1 [[TMP1]]
; CHECK-NEXT: ret i1 [[TMP0]]
;
entry:
%0 = load i1, ptr %a, align 1
Expand All @@ -23,8 +22,7 @@ define i8 @test_i8(ptr %a, ptr %b, ptr %c) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[A]], align 1
; CHECK-NEXT: store i8 [[TMP0]], ptr [[B]], align 1
; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
; CHECK-NEXT: ret i8 [[TMP1]]
; CHECK-NEXT: ret i8 [[TMP0]]
;
entry:
%0 = load i8, ptr %a, align 1
Expand All @@ -39,8 +37,7 @@ define i32 @test_i32(ptr %a, ptr %b, ptr %c) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
; CHECK-NEXT: store i32 [[TMP0]], ptr [[B]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[A]], align 4
; CHECK-NEXT: ret i32 [[TMP1]]
; CHECK-NEXT: ret i32 [[TMP0]]
;
entry:
%0 = load i32, ptr %a, align 4
Expand All @@ -55,8 +52,7 @@ define float @test_float(ptr %a, ptr %b, ptr %c) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[A]], align 4
; CHECK-NEXT: store float [[TMP0]], ptr [[B]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[A]], align 4
; CHECK-NEXT: ret float [[TMP1]]
; CHECK-NEXT: ret float [[TMP0]]
;
entry:
%0 = load float, ptr %a, align 4
Expand Down