GVN: Enable value forwarding for calloc

Enable value forwarding for loads from `calloc()` without an intervening
store.

This change extends GVN to handle the following case:

    %1 = tail call noalias i8* @calloc(i64 1, i64 4)
    %2 = bitcast i8* %1 to i32*
    ; This load is trivially constant zero
    %3 = load i32* %2, align 4

This is analogous to the handling for `malloc()` in the same places.
`malloc()` returns `undef`; `calloc()` returns a zero value.  Note that
it is correct to return zero even for out of bounds GEPs since the
result of such a GEP would be undefined.

Patch by Philip Reames!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210828 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan P. N. Exon Smith
2014-06-12 21:16:19 +00:00
parent 00c3986254
commit 3fdfffbfa3
2 changed files with 41 additions and 0 deletions

View File

@@ -1464,6 +1464,13 @@ void GVN::AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps,
continue;
}
// Loading from calloc (which zero initializes memory) -> zero
if (isCallocLikeFn(DepInst, TLI)) {
ValuesPerBlock.push_back(AvailableValueInBlock::get(
DepBB, Constant::getNullValue(LI->getType())));
continue;
}
if (StoreInst *S = dyn_cast<StoreInst>(DepInst)) {
// Reject loads and stores that are to the same address but are of
// different types if we have to.
@@ -1988,6 +1995,15 @@ bool GVN::processLoad(LoadInst *L) {
}
}
// If this load follows a calloc (which zero initializes memory),
// then the loaded value is zero
if (isCallocLikeFn(DepInst, TLI)) {
L->replaceAllUsesWith(Constant::getNullValue(L->getType()));
markInstructionForDeletion(L);
++NumGVNLoad;
return true;
}
return false;
}