summaryrefslogtreecommitdiff
path: root/lib/Analysis/MemoryDependenceAnalysis.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2011-04-26 22:42:01 +0000
committerChris Lattner <sabre@nondot.org>2011-04-26 22:42:01 +0000
commitcb5fd743a95898ddefd75b6d104f5e91c0d50b23 (patch)
tree77e606ba67cec80a4d3015c2f4cb86bad93eccdc /lib/Analysis/MemoryDependenceAnalysis.cpp
parent9f4b893b84d9c2b56aa2abc3c96ce1e5ccc465e5 (diff)
downloadllvm-cb5fd743a95898ddefd75b6d104f5e91c0d50b23.tar.gz
llvm-cb5fd743a95898ddefd75b6d104f5e91c0d50b23.tar.bz2
llvm-cb5fd743a95898ddefd75b6d104f5e91c0d50b23.tar.xz
Enhance memdep to return clobber relation between noalias loads when
an earlier load could be widened to encompass a later load. For example, if we see: X = load i8* P, align 4 Y = load i8* (P+3), align 1 and we have a 32-bit native integer type, we can widen the former load to i32 which then makes the second load redundant. GVN can't actually do anything with this load/load relation yet, so this isn't testable, but it is the next step to resolving PR6627, and a fairly general class of "merge neighboring loads" missed optimizations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130250 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/MemoryDependenceAnalysis.cpp')
-rw-r--r--lib/Analysis/MemoryDependenceAnalysis.cpp98
1 files changed, 95 insertions, 3 deletions
diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp
index f52b945204..582ae0a614 100644
--- a/lib/Analysis/MemoryDependenceAnalysis.cpp
+++ b/lib/Analysis/MemoryDependenceAnalysis.cpp
@@ -16,6 +16,7 @@
#define DEBUG_TYPE "memdep"
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
+#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Function.h"
@@ -221,6 +222,75 @@ getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall,
return MemDepResult::getClobber(ScanIt);
}
+/// isLoadLoadClobberIfExtendedToFullWidth - Return true if LI is a load that
+/// would fully overlap MemLoc if done as a wider legal integer load.
+///
+/// MemLocBase, MemLocOffset are lazily computed here the first time the
+/// base/offs of memloc is needed.
+static bool
+isLoadLoadClobberIfExtendedToFullWidth(const AliasAnalysis::Location &MemLoc,
+ const Value *&MemLocBase,
+ int64_t &MemLocOffs,
+ const LoadInst *LI, TargetData *TD) {
+ // If we have no target data, we can't do this.
+ if (TD == 0) return false;
+
+ // If we haven't already computed the base/offset of MemLoc, do so now.
+ if (MemLocBase == 0)
+ MemLocBase = GetPointerBaseWithConstantOffset(MemLoc.Ptr, MemLocOffs, *TD);
+
+ // Get the base of this load.
+ int64_t LIOffs = 0;
+ const Value *LIBase =
+ GetPointerBaseWithConstantOffset(LI->getPointerOperand(), LIOffs, *TD);
+
+ // If the two pointers are not based on the same pointer, we can't tell that
+ // they are related.
+ if (LIBase != MemLocBase) return false;
+
+ // Okay, the two values are based on the same pointer, but returned as
+ // no-alias. This happens when we have things like two byte loads at "P+1"
+ // and "P+3". Check to see if increasing the size of the "LI" load up to its
+ // alignment (or the largest native integer type) will allow us to load all
+ // the bits required by MemLoc.
+
+ // If MemLoc is before LI, then no widening of LI will help us out.
+ if (MemLocOffs < LIOffs) return false;
+
+ // Get the alignment of the load in bytes. We assume that it is safe to load
+ // any legal integer up to this size without a problem. For example, if we're
+ // looking at an i8 load on x86-32 that is known 1024 byte aligned, we can
+ // widen it up to an i32 load. If it is known 2-byte aligned, we can widen it
+ // to i16.
+ unsigned LoadAlign = LI->getAlignment();
+
+ int64_t MemLocEnd = MemLocOffs+MemLoc.Size;
+
+ // If no amount of rounding up will let MemLoc fit into LI, then bail out.
+ if (LIOffs+LoadAlign < MemLocEnd) return false;
+
+ // This is the size of the load to try. Start with the next larger power of
+ // two.
+ unsigned NewLoadByteSize = LI->getType()->getPrimitiveSizeInBits()/8U;
+ NewLoadByteSize = NextPowerOf2(NewLoadByteSize);
+
+ while (1) {
+ // If this load size is bigger than our known alignment or would not fit
+ // into a native integer register, then we fail.
+ if (NewLoadByteSize > LoadAlign ||
+ !TD->fitsInLegalInteger(NewLoadByteSize*8))
+ return false;
+
+ // If a load of this width would include all of MemLoc, then we succeed.
+ if (LIOffs+NewLoadByteSize >= MemLocEnd)
+ return true;
+
+ NewLoadByteSize <<= 1;
+ }
+
+ return false;
+}
+
/// getPointerDependencyFrom - Return the instruction on which a memory
/// location depends. If isLoad is true, this routine ignores may-aliases with
/// read-only operations. If isLoad is false, this routine ignores may-aliases
@@ -229,6 +299,9 @@ MemDepResult MemoryDependenceAnalysis::
getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad,
BasicBlock::iterator ScanIt, BasicBlock *BB) {
+ const Value *MemLocBase = 0;
+ int64_t MemLocOffset = 0;
+
// Walk backwards through the basic block, looking for dependencies.
while (ScanIt != BB->begin()) {
Instruction *Inst = --ScanIt;
@@ -242,7 +315,8 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad,
if (II->getIntrinsicID() == Intrinsic::lifetime_start) {
// FIXME: This only considers queries directly on the invariant-tagged
// pointer, not on query pointers that are indexed off of them. It'd
- // be nice to handle that at some point.
+ // be nice to handle that at some point (the right approach is to use
+ // GetPointerBaseWithConstantOffset).
if (AA->isMustAlias(AliasAnalysis::Location(II->getArgOperand(1)),
MemLoc))
return MemDepResult::getDef(II);
@@ -257,10 +331,24 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad,
// If we found a pointer, check if it could be the same as our pointer.
AliasAnalysis::AliasResult R = AA->alias(LoadLoc, MemLoc);
- if (R == AliasAnalysis::NoAlias)
- continue;
if (isLoad) {
+ if (R == AliasAnalysis::NoAlias) {
+ // If this is an over-aligned integer load (for example,
+ // "load i8* %P, align 4") see if it would obviously overlap with the
+ // queried location if widened to a larger load (e.g. if the queried
+ // location is 1 byte at P+1). If so, return it as a load/load
+ // clobber result, allowing the client to decide to widen the load if
+ // it wants to.
+ if (const IntegerType *ITy = dyn_cast<IntegerType>(LI->getType()))
+ if (LI->getAlignment()*8 > ITy->getPrimitiveSizeInBits() &&
+ isLoadLoadClobberIfExtendedToFullWidth(MemLoc, MemLocBase,
+ MemLocOffset, LI, TD))
+ return MemDepResult::getClobber(Inst);
+
+ continue;
+ }
+
// Must aliased loads are defs of each other.
if (R == AliasAnalysis::MustAlias)
return MemDepResult::getDef(Inst);
@@ -275,6 +363,10 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad,
continue;
}
+ // Stores don't depend on other no-aliased accesses.
+ if (R == AliasAnalysis::NoAlias)
+ continue;
+
// Stores don't alias loads from read-only memory.
if (AA->pointsToConstantMemory(LoadLoc))
continue;