Skip to content

Commit c04c945

Browse files
authored
[ValueTracking] Handle chain of single-pred blocks in willNotFreeBetween() (#202308)
willNotFreeBetween() currently handles the case where both instructions are in the same block, or one is in the single predecessor of the other. This patch extends this to handle a chain of single predecessor blocks. The budget now applies to all checked instructions, rather than per block. Also increase the budget by a factor of two (which means that new budget interpretation should never regress relative to the previous).
1 parent 69215c5 commit c04c945

3 files changed

Lines changed: 24 additions & 16 deletions

File tree

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ static cl::opt<unsigned> DomConditionsMaxUses("dom-conditions-max-uses",
9494

9595
/// Maximum number of instructions to check between assume and context
9696
/// instruction.
97-
static constexpr unsigned MaxInstrsToCheckForFree = 16;
97+
static constexpr unsigned MaxInstrsToCheckForFree = 32;
9898

9999
/// Returns the bitwidth of the given scalar or pointer type. For vector types,
100100
/// returns the element type's bitwidth.
@@ -705,9 +705,10 @@ bool llvm::isValidAssumeForContext(const Instruction *Inv,
705705
bool llvm::willNotFreeBetween(const Instruction *Assume,
706706
const Instruction *CtxI) {
707707
// Helper to check if there are any calls in the range that may free memory.
708-
auto hasNoFreeInRange = [](auto Range) {
709-
for (const auto &[Idx, I] : enumerate(Range)) {
710-
if (Idx > MaxInstrsToCheckForFree)
708+
unsigned NumChecked = 0;
709+
auto hasNoFreeInRange = [&NumChecked](auto Range) {
710+
for (const Instruction &I : Range) {
711+
if (NumChecked++ > MaxInstrsToCheckForFree)
711712
return false;
712713

713714
if (auto *CB = dyn_cast<CallBase>(&I)) {
@@ -719,27 +720,32 @@ bool llvm::willNotFreeBetween(const Instruction *Assume,
719720
return true;
720721
};
721722

722-
// Handle cross-block case: CtxI in a successor of Assume's block.
723723
const BasicBlock *CtxBB = CtxI->getParent();
724724
const BasicBlock *AssumeBB = Assume->getParent();
725725
BasicBlock::const_iterator CtxIter = CtxI->getIterator();
726-
if (CtxBB != AssumeBB) {
727-
if (CtxBB->getSinglePredecessor() != AssumeBB)
726+
if (CtxBB == AssumeBB) {
727+
// Same block case: check that Assume comes before CtxI.
728+
if (Assume != CtxI && !Assume->comesBefore(CtxI))
728729
return false;
730+
return hasNoFreeInRange(make_range(Assume->getIterator(), CtxIter));
731+
}
732+
733+
// Handle chain of single-predecessor blocks.
734+
const BasicBlock *CurBB = CtxBB;
735+
while (true) {
736+
if (CurBB == AssumeBB)
737+
return hasNoFreeInRange(
738+
make_range(Assume->getIterator(), AssumeBB->end()));
729739

730-
if (!hasNoFreeInRange(make_range(CtxBB->begin(), CtxIter)))
740+
const BasicBlock *PredBB = CurBB->getSinglePredecessor();
741+
if (!PredBB)
731742
return false;
732743

733-
CtxIter = AssumeBB->end();
734-
} else {
735-
// Same block case: check that Assume comes before CtxI.
736-
if (Assume != CtxI && !Assume->comesBefore(CtxI))
744+
if (!hasNoFreeInRange(make_range(CurBB->begin(),
745+
CurBB == CtxBB ? CtxIter : CurBB->end())))
737746
return false;
747+
CurBB = PredBB;
738748
}
739-
740-
// Check if there are any calls between Assume and CtxIter that may free
741-
// memory.
742-
return hasNoFreeInRange(make_range(Assume->getIterator(), CtxIter));
743749
}
744750

745751
// TODO: cmpExcludesZero misses many cases where `RHS` is non-constant but

llvm/test/Transforms/LICM/hoist-deref-load.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
22
; RUN: opt -S -passes=licm -verify-memoryssa < %s | FileCheck %s
3+
; RUN: opt -S -passes=licm -verify-memoryssa -use-dereferenceable-at-point-semantics < %s | FileCheck %s
34
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(loop-simplifycfg,licm)' -verify-memoryssa -S < %s | FileCheck %s
45

56
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

llvm/test/Transforms/SLPVectorizer/AArch64/masked-loads-side-effects-after-vec.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
22
; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
3+
; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu -use-dereferenceable-at-point-semantics < %s | FileCheck %s
34

45
declare noalias ptr @malloc()
56

0 commit comments

Comments
 (0)