mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
implement the "no aliasing accesses in loop" safety check. This pass
should be correct now. llvm-svn: 122659
This commit is contained in:
parent
e223c0aa14
commit
4651f8b037
@ -180,6 +180,9 @@ bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) {
|
|||||||
// know that every byte is touched in the loop.
|
// know that every byte is touched in the loop.
|
||||||
unsigned StoreSize = (unsigned)SizeInBits >> 3;
|
unsigned StoreSize = (unsigned)SizeInBits >> 3;
|
||||||
const SCEVConstant *Stride = dyn_cast<SCEVConstant>(Ev->getOperand(1));
|
const SCEVConstant *Stride = dyn_cast<SCEVConstant>(Ev->getOperand(1));
|
||||||
|
|
||||||
|
// TODO: Could also handle negative stride here someday, that will require the
|
||||||
|
// validity check in mayLoopModRefLocation to be updated though.
|
||||||
if (Stride == 0 || StoreSize != Stride->getValue()->getValue())
|
if (Stride == 0 || StoreSize != Stride->getValue()->getValue())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -196,22 +199,46 @@ bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// mayLoopModRefLocation - Return true if the specified loop might do a load or
|
||||||
|
/// store to the same location that the specified store could store to, which is
|
||||||
|
/// a loop-strided access.
|
||||||
|
static bool mayLoopModRefLocation(StoreInst *SI, Loop *L, AliasAnalysis &AA) {
|
||||||
|
// Get the location that may be stored across the loop. Since the access is
|
||||||
|
// strided positively through memory, we say that the modified location starts
|
||||||
|
// at the pointer and has infinite size.
|
||||||
|
// TODO: Could improve this for constant trip-count loops.
|
||||||
|
AliasAnalysis::Location StoreLoc =
|
||||||
|
AliasAnalysis::Location(SI->getPointerOperand());
|
||||||
|
|
||||||
|
for (Loop::block_iterator BI = L->block_begin(), E = L->block_end(); BI != E;
|
||||||
|
++BI)
|
||||||
|
for (BasicBlock::iterator I = (*BI)->begin(), E = (*BI)->end(); I != E; ++I)
|
||||||
|
if (AA.getModRefInfo(I, StoreLoc) != AliasAnalysis::NoModRef)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// processLoopStoreOfSplatValue - We see a strided store of a memsetable value.
|
/// processLoopStoreOfSplatValue - We see a strided store of a memsetable value.
|
||||||
/// If we can transform this into a memset in the loop preheader, do so.
|
/// If we can transform this into a memset in the loop preheader, do so.
|
||||||
bool LoopIdiomRecognize::
|
bool LoopIdiomRecognize::
|
||||||
processLoopStoreOfSplatValue(StoreInst *SI, unsigned StoreSize,
|
processLoopStoreOfSplatValue(StoreInst *SI, unsigned StoreSize,
|
||||||
Value *SplatValue,
|
Value *SplatValue,
|
||||||
const SCEVAddRecExpr *Ev, const SCEV *BECount) {
|
const SCEVAddRecExpr *Ev, const SCEV *BECount) {
|
||||||
|
// Temporarily remove the store from the loop, to avoid the mod/ref query from
|
||||||
|
// seeing it.
|
||||||
|
Instruction *InstAfterStore = ++BasicBlock::iterator(SI);
|
||||||
|
SI->removeFromParent();
|
||||||
|
|
||||||
// Okay, we have a strided store "p[i]" of a splattable value. We can turn
|
// Okay, we have a strided store "p[i]" of a splattable value. We can turn
|
||||||
// this into a memset in the loop preheader now if we want. However, this
|
// this into a memset in the loop preheader now if we want. However, this
|
||||||
// would be unsafe to do if there is anything else in the loop that may read
|
// would be unsafe to do if there is anything else in the loop that may read
|
||||||
// or write to the aliased location. Check for an alias.
|
// or write to the aliased location. Check for an alias.
|
||||||
|
bool Unsafe=mayLoopModRefLocation(SI, CurLoop, getAnalysis<AliasAnalysis>());
|
||||||
|
|
||||||
// FIXME: Need to get a base pointer that is valid.
|
SI->insertBefore(InstAfterStore);
|
||||||
// if (LoopCanModRefLocation(SI->getPointerOperand())
|
|
||||||
|
|
||||||
|
if (Unsafe) return false;
|
||||||
// FIXME: TODO safety check.
|
|
||||||
|
|
||||||
// Okay, everything looks good, insert the memset.
|
// Okay, everything looks good, insert the memset.
|
||||||
BasicBlock *Preheader = CurLoop->getLoopPreheader();
|
BasicBlock *Preheader = CurLoop->getLoopPreheader();
|
||||||
|
@ -42,3 +42,26 @@ for.end: ; preds = %for.body, %entry
|
|||||||
; CHECK: call void @llvm.memset.p0i8.i64(i8* %Base1, i8 1, i64 %tmp, i32 4, i1 false)
|
; CHECK: call void @llvm.memset.p0i8.i64(i8* %Base1, i8 1, i64 %tmp, i32 4, i1 false)
|
||||||
; CHECK-NOT: store
|
; CHECK-NOT: store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; This is a case where there is an extra may-aliased store in the loop, we can't
|
||||||
|
; promote the memset.
|
||||||
|
define void @test3(i32* %Base, i64 %Size, i8 *%MayAlias) nounwind ssp {
|
||||||
|
entry:
|
||||||
|
br label %for.body
|
||||||
|
|
||||||
|
for.body: ; preds = %entry, %for.body
|
||||||
|
%i.011 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
|
||||||
|
%add.ptr.i = getelementptr i32* %Base, i64 %i.011
|
||||||
|
store i32 16843009, i32* %add.ptr.i, align 4
|
||||||
|
|
||||||
|
store i8 42, i8* %MayAlias
|
||||||
|
%inc = add nsw i64 %i.011, 1
|
||||||
|
%exitcond = icmp eq i64 %inc, %Size
|
||||||
|
br i1 %exitcond, label %for.end, label %for.body
|
||||||
|
|
||||||
|
for.end: ; preds = %entry
|
||||||
|
ret void
|
||||||
|
; CHECK: @test3
|
||||||
|
; CHECK-NOT: memset
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user