mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-30 02:25:19 +00:00
Vectorizer: refactor the memory checks to a new function. No functionality change.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166366 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -202,6 +202,12 @@ private:
|
|||||||
/// and we only need to check individual instructions.
|
/// and we only need to check individual instructions.
|
||||||
bool canVectorizeBlock(BasicBlock &BB);
|
bool canVectorizeBlock(BasicBlock &BB);
|
||||||
|
|
||||||
|
/// When we vectorize loops we may change the order in which
|
||||||
|
/// we read and write from memory. This method checks if it is
|
||||||
|
/// legal to vectorize the code, considering only memory constrains.
|
||||||
|
/// Returns true if BB is vectorizable
|
||||||
|
bool canVectorizeMemory(BasicBlock &BB;)
|
||||||
|
|
||||||
// Check if a pointer value is known to be disjoint.
|
// Check if a pointer value is known to be disjoint.
|
||||||
// Example: Alloca, Global, NoAlias.
|
// Example: Alloca, Global, NoAlias.
|
||||||
bool isIdentifiedSafeObject(Value* Val);
|
bool isIdentifiedSafeObject(Value* Val);
|
||||||
@@ -908,11 +914,7 @@ unsigned LoopVectorizationLegality::getLoopMaxVF() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool LoopVectorizationLegality::canVectorizeBlock(BasicBlock &BB) {
|
bool LoopVectorizationLegality::canVectorizeBlock(BasicBlock &BB) {
|
||||||
// Holds the read and write pointers that we find.
|
// Scan the instructions in the block and look for hazards.
|
||||||
typedef SmallVector<Value*, 10> ValueVector;
|
|
||||||
ValueVector Reads;
|
|
||||||
ValueVector Writes;
|
|
||||||
|
|
||||||
for (BasicBlock::iterator it = BB.begin(), e = BB.end(); it != e; ++it) {
|
for (BasicBlock::iterator it = BB.begin(), e = BB.end(); it != e; ++it) {
|
||||||
Instruction *I = it;
|
Instruction *I = it;
|
||||||
|
|
||||||
@@ -960,34 +962,6 @@ bool LoopVectorizationLegality::canVectorizeBlock(BasicBlock &BB) {
|
|||||||
}
|
}
|
||||||
}// end of PHI handling
|
}// end of PHI handling
|
||||||
|
|
||||||
// If this is a load, record its pointer. If it is not a load, abort.
|
|
||||||
// Notice that we don't handle function calls that read or write.
|
|
||||||
if (I->mayReadFromMemory()) {
|
|
||||||
LoadInst *Ld = dyn_cast<LoadInst>(I);
|
|
||||||
if (!Ld) return false;
|
|
||||||
if (!Ld->isSimple()) {
|
|
||||||
DEBUG(dbgs() << "LV: Found a non-simple load.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* Ptr = Ld->getPointerOperand();
|
|
||||||
GetUnderlyingObjects(Ptr, Reads, DL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record store pointers. Abort on all other instructions that write to
|
|
||||||
// memory.
|
|
||||||
if (I->mayWriteToMemory()) {
|
|
||||||
StoreInst *St = dyn_cast<StoreInst>(I);
|
|
||||||
if (!St) return false;
|
|
||||||
if (!St->isSimple()) {
|
|
||||||
DEBUG(dbgs() << "LV: Found a non-simple store.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* Ptr = St->getPointerOperand();
|
|
||||||
GetUnderlyingObjects(Ptr, Writes, DL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We still don't handle functions.
|
// We still don't handle functions.
|
||||||
CallInst *CI = dyn_cast<CallInst>(I);
|
CallInst *CI = dyn_cast<CallInst>(I);
|
||||||
if (CI) {
|
if (CI) {
|
||||||
@@ -1024,6 +998,50 @@ bool LoopVectorizationLegality::canVectorizeBlock(BasicBlock &BB) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the memory dependencies do not prevent us from
|
||||||
|
// vectorizing, then vectorize.
|
||||||
|
return canVectorizeMemory(BB);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoopVectorizationLegality::canVectorizeMemory(BasicBlock &BB) {
|
||||||
|
// Holds the read and write pointers that we find.
|
||||||
|
typedef SmallVector<Value*, 10> ValueVector;
|
||||||
|
ValueVector Reads;
|
||||||
|
ValueVector Writes;
|
||||||
|
|
||||||
|
for (BasicBlock::iterator it = BB.begin(), e = BB.end(); it != e; ++it) {
|
||||||
|
Instruction *I = it;
|
||||||
|
|
||||||
|
// If this is a load, record its pointer. If it is not a load, abort.
|
||||||
|
// Notice that we don't handle function calls that read or write.
|
||||||
|
if (I->mayReadFromMemory()) {
|
||||||
|
LoadInst *Ld = dyn_cast<LoadInst>(I);
|
||||||
|
if (!Ld) return false;
|
||||||
|
if (!Ld->isSimple()) {
|
||||||
|
DEBUG(dbgs() << "LV: Found a non-simple load.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* Ptr = Ld->getPointerOperand();
|
||||||
|
GetUnderlyingObjects(Ptr, Reads, DL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record store pointers. Abort on all other instructions that write to
|
||||||
|
// memory.
|
||||||
|
if (I->mayWriteToMemory()) {
|
||||||
|
StoreInst *St = dyn_cast<StoreInst>(I);
|
||||||
|
if (!St) return false;
|
||||||
|
if (!St->isSimple()) {
|
||||||
|
DEBUG(dbgs() << "LV: Found a non-simple store.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* Ptr = St->getPointerOperand();
|
||||||
|
GetUnderlyingObjects(Ptr, Writes, DL);
|
||||||
|
}
|
||||||
|
} // next instr.
|
||||||
|
|
||||||
|
|
||||||
// Check that the underlying objects of the reads and writes are either
|
// Check that the underlying objects of the reads and writes are either
|
||||||
// disjoint memory locations, or that they are no-alias arguments.
|
// disjoint memory locations, or that they are no-alias arguments.
|
||||||
ValueVector::iterator r, re, w, we;
|
ValueVector::iterator r, re, w, we;
|
||||||
|
Reference in New Issue
Block a user