Skip to content
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
38 changes: 22 additions & 16 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ static cl::opt<unsigned> DomConditionsMaxUses("dom-conditions-max-uses",

/// Maximum number of instructions to check between assume and context
/// instruction.
static constexpr unsigned MaxInstrsToCheckForFree = 16;
static constexpr unsigned MaxInstrsToCheckForFree = 32;

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

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

// Handle cross-block case: CtxI in a successor of Assume's block.
const BasicBlock *CtxBB = CtxI->getParent();
const BasicBlock *AssumeBB = Assume->getParent();
BasicBlock::const_iterator CtxIter = CtxI->getIterator();
if (CtxBB != AssumeBB) {
if (CtxBB->getSinglePredecessor() != AssumeBB)
if (CtxBB == AssumeBB) {
// Same block case: check that Assume comes before CtxI.
if (Assume != CtxI && !Assume->comesBefore(CtxI))
return false;
return hasNoFreeInRange(make_range(Assume->getIterator(), CtxIter));
}

// Handle chain of single-predecessor blocks.
const BasicBlock *CurBB = CtxBB;
while (true) {
if (CurBB == AssumeBB)
return hasNoFreeInRange(
make_range(Assume->getIterator(), AssumeBB->end()));

if (!hasNoFreeInRange(make_range(CtxBB->begin(), CtxIter)))
const BasicBlock *PredBB = CurBB->getSinglePredecessor();
if (!PredBB)
return false;

CtxIter = AssumeBB->end();
} else {
// Same block case: check that Assume comes before CtxI.
if (Assume != CtxI && !Assume->comesBefore(CtxI))
if (!hasNoFreeInRange(make_range(CurBB->begin(),
CurBB == CtxBB ? CtxIter : CurBB->end())))
return false;
CurBB = PredBB;
}

// Check if there are any calls between Assume and CtxIter that may free
// memory.
return hasNoFreeInRange(make_range(Assume->getIterator(), CtxIter));
}

// TODO: cmpExcludesZero misses many cases where `RHS` is non-constant but
Expand Down
1 change: 1 addition & 0 deletions llvm/test/Transforms/LICM/hoist-deref-load.ll
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=licm -verify-memoryssa < %s | FileCheck %s
; RUN: opt -S -passes=licm -verify-memoryssa -use-dereferenceable-at-point-semantics < %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(loop-simplifycfg,licm)' -verify-memoryssa -S < %s | FileCheck %s

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu -use-dereferenceable-at-point-semantics < %s | FileCheck %s

declare noalias ptr @malloc()

Expand Down
Loading