Skip to content

Commit 9f12f65

Browse files
authored
[GVN] Drop Clobber dependency if store may overwrite only the same value (#68322)
In some cases clobbering store can be safely skipped if it can only must or no alias with memory location and it writes the same value. This patch supports simple case when the value from memory location was loaded in the same basic block before the store and there are no modifications between them.
1 parent 9ce8103 commit 9f12f65

File tree

2 files changed

+44
-13
lines changed

2 files changed

+44
-13
lines changed

llvm/lib/Analysis/MemoryDependenceAnalysis.cpp

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -360,11 +360,43 @@ MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
360360
return MemDepResult::getNonLocal();
361361
}
362362

363+
// Check if SI that may alias with MemLoc can be safely skipped. This is
364+
// possible in case if SI can only must alias or no alias with MemLoc (no
365+
// partial overlapping possible) and it writes the same value that MemLoc
366+
// contains now (it was loaded before this store and was not modified in
367+
// between).
368+
static bool canSkipClobberingStore(const StoreInst *SI,
369+
const MemoryLocation &MemLoc,
370+
Align MemLocAlign, BatchAAResults &BatchAA,
371+
unsigned ScanLimit) {
372+
if (!MemLoc.Size.hasValue())
373+
return false;
374+
if (MemoryLocation::get(SI).Size != MemLoc.Size)
375+
return false;
376+
if (std::min(MemLocAlign, SI->getAlign()).value() < MemLoc.Size.getValue())
377+
return false;
378+
379+
auto *LI = dyn_cast<LoadInst>(SI->getValueOperand());
380+
if (!LI || LI->getParent() != SI->getParent())
381+
return false;
382+
if (BatchAA.alias(MemoryLocation::get(LI), MemLoc) != AliasResult::MustAlias)
383+
return false;
384+
unsigned NumVisitedInsts = 0;
385+
for (const Instruction *I = LI; I != SI; I = I->getNextNonDebugInstruction())
386+
if (++NumVisitedInsts > ScanLimit ||
387+
isModSet(BatchAA.getModRefInfo(I, MemLoc)))
388+
return false;
389+
390+
return true;
391+
}
392+
363393
MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
364394
const MemoryLocation &MemLoc, bool isLoad, BasicBlock::iterator ScanIt,
365395
BasicBlock *BB, Instruction *QueryInst, unsigned *Limit,
366396
BatchAAResults &BatchAA) {
367397
bool isInvariantLoad = false;
398+
Align MemLocAlign =
399+
MemLoc.Ptr->getPointerAlignment(BB->getModule()->getDataLayout());
368400

369401
unsigned DefaultLimit = getDefaultBlockScanLimit();
370402
if (!Limit)
@@ -402,11 +434,12 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
402434
// do want to respect mustalias results since defs are useful for value
403435
// forwarding, but any mayalias write can be assumed to be noalias.
404436
// Arguably, this logic should be pushed inside AliasAnalysis itself.
405-
if (isLoad && QueryInst) {
406-
LoadInst *LI = dyn_cast<LoadInst>(QueryInst);
407-
if (LI && LI->hasMetadata(LLVMContext::MD_invariant_load))
408-
isInvariantLoad = true;
409-
}
437+
if (isLoad && QueryInst)
438+
if (LoadInst *LI = dyn_cast<LoadInst>(QueryInst)) {
439+
if (LI->hasMetadata(LLVMContext::MD_invariant_load))
440+
isInvariantLoad = true;
441+
MemLocAlign = LI->getAlign();
442+
}
410443

411444
// True for volatile instruction.
412445
// For Load/Store return true if atomic ordering is stronger than AO,
@@ -577,6 +610,8 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
577610
return MemDepResult::getDef(Inst);
578611
if (isInvariantLoad)
579612
continue;
613+
if (canSkipClobberingStore(SI, MemLoc, MemLocAlign, BatchAA, *Limit))
614+
continue;
580615
return MemDepResult::getClobber(Inst);
581616
}
582617

llvm/test/Transforms/GVN/rle-clobbering-store.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ define i1 @test_i1(ptr %a, ptr %b, ptr %c) {
77
; CHECK-NEXT: entry:
88
; CHECK-NEXT: [[TMP0:%.*]] = load i1, ptr [[A]], align 1
99
; CHECK-NEXT: store i1 [[TMP0]], ptr [[B]], align 1
10-
; CHECK-NEXT: [[TMP1:%.*]] = load i1, ptr [[A]], align 1
11-
; CHECK-NEXT: ret i1 [[TMP1]]
10+
; CHECK-NEXT: ret i1 [[TMP0]]
1211
;
1312
entry:
1413
%0 = load i1, ptr %a, align 1
@@ -23,8 +22,7 @@ define i8 @test_i8(ptr %a, ptr %b, ptr %c) {
2322
; CHECK-NEXT: entry:
2423
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[A]], align 1
2524
; CHECK-NEXT: store i8 [[TMP0]], ptr [[B]], align 1
26-
; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
27-
; CHECK-NEXT: ret i8 [[TMP1]]
25+
; CHECK-NEXT: ret i8 [[TMP0]]
2826
;
2927
entry:
3028
%0 = load i8, ptr %a, align 1
@@ -39,8 +37,7 @@ define i32 @test_i32(ptr %a, ptr %b, ptr %c) {
3937
; CHECK-NEXT: entry:
4038
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
4139
; CHECK-NEXT: store i32 [[TMP0]], ptr [[B]], align 4
42-
; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[A]], align 4
43-
; CHECK-NEXT: ret i32 [[TMP1]]
40+
; CHECK-NEXT: ret i32 [[TMP0]]
4441
;
4542
entry:
4643
%0 = load i32, ptr %a, align 4
@@ -55,8 +52,7 @@ define float @test_float(ptr %a, ptr %b, ptr %c) {
5552
; CHECK-NEXT: entry:
5653
; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[A]], align 4
5754
; CHECK-NEXT: store float [[TMP0]], ptr [[B]], align 4
58-
; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[A]], align 4
59-
; CHECK-NEXT: ret float [[TMP1]]
55+
; CHECK-NEXT: ret float [[TMP0]]
6056
;
6157
entry:
6258
%0 = load float, ptr %a, align 4

0 commit comments

Comments
 (0)