aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@apple.com>2010-01-30 04:42:39 +0000
committerBob Wilson <bob.wilson@apple.com>2010-01-30 04:42:39 +0000
commit49db68fba01722ca032dc5170f8248a9d25f0199 (patch)
tree575e1422b433c1028bda1df8331249b35730b54d /lib/Transforms
parenta6bff982c10f6f19c0a9ba20a6300201449c5f39 (diff)
downloadexternal_llvm-49db68fba01722ca032dc5170f8248a9d25f0199.zip
external_llvm-49db68fba01722ca032dc5170f8248a9d25f0199.tar.gz
external_llvm-49db68fba01722ca032dc5170f8248a9d25f0199.tar.bz2
Check alignment of loads when deciding whether it is safe to execute them
unconditionally. Besides checking the offset, also check that the underlying object is aligned as much as the load itself. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94875 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp13
-rw-r--r--lib/Transforms/Scalar/GVN.cpp3
-rw-r--r--lib/Transforms/Scalar/TailRecursionElimination.cpp3
-rw-r--r--lib/Transforms/Utils/Local.cpp21
4 files changed, 25 insertions, 15 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index 422ffd0..2d13298 100644
--- a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -200,14 +200,15 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) {
//
if (SelectInst *SI = dyn_cast<SelectInst>(Op)) {
// load (select (Cond, &V1, &V2)) --> select(Cond, load &V1, load &V2).
- if (isSafeToLoadUnconditionally(SI->getOperand(1), SI, TD) &&
- isSafeToLoadUnconditionally(SI->getOperand(2), SI, TD)) {
+ unsigned Align = LI.getAlignment();
+ if (isSafeToLoadUnconditionally(SI->getOperand(1), SI, Align, TD) &&
+ isSafeToLoadUnconditionally(SI->getOperand(2), SI, Align, TD)) {
LoadInst *V1 = Builder->CreateLoad(SI->getOperand(1),
- SI->getOperand(1)->getName()+".val");
+ SI->getOperand(1)->getName()+".val");
LoadInst *V2 = Builder->CreateLoad(SI->getOperand(2),
- SI->getOperand(2)->getName()+".val");
- V1->setAlignment(LI.getAlignment());
- V2->setAlignment(LI.getAlignment());
+ SI->getOperand(2)->getName()+".val");
+ V1->setAlignment(Align);
+ V2->setAlignment(Align);
return SelectInst::Create(SI->getCondition(), V1, V2);
}
diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp
index 9c18452..6e70952 100644
--- a/lib/Transforms/Scalar/GVN.cpp
+++ b/lib/Transforms/Scalar/GVN.cpp
@@ -1651,7 +1651,8 @@ bool GVN::processNonLocalLoad(LoadInst *LI,
if (!allSingleSucc &&
// FIXME: REEVALUTE THIS.
!isSafeToLoadUnconditionally(LoadPtr,
- UnavailablePred->getTerminator(), TD)) {
+ UnavailablePred->getTerminator(),
+ LI->getAlignment(), TD)) {
assert(NewInsts.empty() && "Should not have inserted instructions");
return false;
}
diff --git a/lib/Transforms/Scalar/TailRecursionElimination.cpp b/lib/Transforms/Scalar/TailRecursionElimination.cpp
index 4119cb9..162d902 100644
--- a/lib/Transforms/Scalar/TailRecursionElimination.cpp
+++ b/lib/Transforms/Scalar/TailRecursionElimination.cpp
@@ -211,7 +211,8 @@ bool TailCallElim::CanMoveAboveCall(Instruction *I, CallInst *CI) {
// FIXME: Writes to memory only matter if they may alias the pointer
// being loaded from.
if (CI->mayWriteToMemory() ||
- !isSafeToLoadUnconditionally(L->getPointerOperand(), L))
+ !isSafeToLoadUnconditionally(L->getPointerOperand(), L,
+ L->getAlignment()))
return false;
}
}
diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp
index 425f557..62c0ae0 100644
--- a/lib/Transforms/Utils/Local.cpp
+++ b/lib/Transforms/Utils/Local.cpp
@@ -75,31 +75,38 @@ static Value *getUnderlyingObjectWithOffset(Value *V, const TargetData *TD,
/// specified pointer, we do a quick local scan of the basic block containing
/// ScanFrom, to determine if the address is already accessed.
bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
- const TargetData *TD) {
+ unsigned Align, const TargetData *TD) {
uint64_t ByteOffset = 0;
Value *Base = V;
if (TD)
Base = getUnderlyingObjectWithOffset(V, TD, ByteOffset);
const Type *BaseType = 0;
- if (const AllocaInst *AI = dyn_cast<AllocaInst>(Base))
- // If it is an alloca it is always safe to load from.
+ unsigned BaseAlign = 0;
+ if (const AllocaInst *AI = dyn_cast<AllocaInst>(Base)) {
+ // An alloca is safe to load from as load as it is suitably aligned.
BaseType = AI->getAllocatedType();
- else if (const GlobalValue *GV = dyn_cast<GlobalValue>(Base)) {
+ BaseAlign = AI->getAlignment();
+ } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(Base)) {
// Global variables are safe to load from but their size cannot be
// guaranteed if they are overridden.
- if (!isa<GlobalAlias>(GV) && !GV->mayBeOverridden())
+ if (!isa<GlobalAlias>(GV) && !GV->mayBeOverridden()) {
BaseType = GV->getType()->getElementType();
+ BaseAlign = GV->getAlignment();
+ }
}
+ if (TD && BaseType && BaseAlign == 0)
+ BaseAlign = TD->getPrefTypeAlignment(BaseType);
- if (BaseType) {
+ if (BaseType && Align <= BaseAlign) {
if (!TD)
return true; // Loading directly from an alloca or global is OK.
if (BaseType->isSized()) {
// Check if the load is within the bounds of the underlying object.
const PointerType *AddrTy = cast<PointerType>(V->getType());
uint64_t LoadSize = TD->getTypeStoreSize(AddrTy->getElementType());
- if (ByteOffset + LoadSize <= TD->getTypeAllocSize(BaseType))
+ if (ByteOffset + LoadSize <= TD->getTypeAllocSize(BaseType) &&
+ (Align == 0 || (ByteOffset % Align) == 0))
return true;
}
}