diff options
author | Hiroshi Yamauchi <yamauchi@google.com> | 2019-12-10 14:41:30 -0800 |
---|---|---|
committer | Hiroshi Yamauchi <yamauchi@google.com> | 2020-01-29 13:05:46 -0800 |
commit | 24962ced814123195be1a8cb41b615f255da824f (patch) | |
tree | eac36d178a3c764d1cc587da0ea2d57e4859fe04 /llvm/lib/Analysis/Loads.cpp | |
parent | 00c2249910a17eee9c5a23bc82f2d2f5e1b6c867 (diff) | |
download | llvm-24962ced814123195be1a8cb41b615f255da824f.zip llvm-24962ced814123195be1a8cb41b615f255da824f.tar.gz llvm-24962ced814123195be1a8cb41b615f255da824f.tar.bz2 |
[Loads] Handle simple cases with same base pointer with constant offsets in FindAvailableLoadedValue when AA is null.
Summary:
This will help with devirtualization (store forwarding with vtable pointers in
the presence of other stores into members in the constructor.) During inlining,
we don't have AA.
Reviewers: davidxl
Subscribers: mgorny, Prazek, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71307
Diffstat (limited to 'llvm/lib/Analysis/Loads.cpp')
-rw-r--r-- | llvm/lib/Analysis/Loads.cpp | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp index 218fc3e..c2e9b8b 100644 --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -381,6 +381,28 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, ScanFrom, MaxInstsToScan, AA, IsLoad, NumScanedInst); } +// Check if the load and the store have the same base, constant offsets and +// non-overlapping access ranges. +static bool AreNonOverlapSameBaseLoadAndStore( + Value *LoadPtr, Type *LoadTy, Value *StorePtr, Type *StoreTy, + const DataLayout &DL) { + APInt LoadOffset(DL.getTypeSizeInBits(LoadPtr->getType()), 0); + APInt StoreOffset(DL.getTypeSizeInBits(StorePtr->getType()), 0); + Value *LoadBase = LoadPtr->stripAndAccumulateConstantOffsets( + DL, LoadOffset, /* AllowNonInbounds */ false); + Value *StoreBase = StorePtr->stripAndAccumulateConstantOffsets( + DL, StoreOffset, /* AllowNonInbounds */ false); + if (LoadBase != StoreBase) + return false; + auto LoadAccessSize = LocationSize::precise(DL.getTypeStoreSize(LoadTy)); + auto StoreAccessSize = LocationSize::precise(DL.getTypeStoreSize(StoreTy)); + ConstantRange LoadRange(LoadOffset, + LoadOffset + LoadAccessSize.toRaw()); + ConstantRange StoreRange(StoreOffset, + StoreOffset + StoreAccessSize.toRaw()); + return LoadRange.intersectWith(StoreRange).isEmptySet(); +} + Value *llvm::FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, bool AtLeastAtomic, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, @@ -459,10 +481,21 @@ Value *llvm::FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, StrippedPtr != StorePtr) continue; - // If we have alias analysis and it says the store won't modify the loaded - // value, ignore the store. - if (AA && !isModSet(AA->getModRefInfo(SI, StrippedPtr, AccessSize))) - continue; + if (!AA) { + // When AA isn't available, but if the load and the store have the same + // base, constant offsets and non-overlapping access ranges, ignore the + // store. This is a simple form of alias analysis that is used by the + // inliner. FIXME: use BasicAA if possible. + if (AreNonOverlapSameBaseLoadAndStore( + Ptr, AccessTy, SI->getPointerOperand(), + SI->getValueOperand()->getType(), DL)) + continue; + } else { + // If we have alias analysis and it says the store won't modify the + // loaded value, ignore the store. + if (!isModSet(AA->getModRefInfo(SI, StrippedPtr, AccessSize))) + continue; + } // Otherwise the store that may or may not alias the pointer, bail out. ++ScanFrom; |