mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
implement the logic for memset insertion and store deletion.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48679 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -13,7 +13,6 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#define DEBUG_TYPE "gvn"
|
#define DEBUG_TYPE "gvn"
|
||||||
|
|
||||||
#include "llvm/Transforms/Scalar.h"
|
#include "llvm/Transforms/Scalar.h"
|
||||||
#include "llvm/BasicBlock.h"
|
#include "llvm/BasicBlock.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
@@ -37,6 +36,11 @@
|
|||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
STATISTIC(NumGVNInstr, "Number of instructions deleted");
|
||||||
|
STATISTIC(NumGVNLoad, "Number of loads deleted");
|
||||||
|
STATISTIC(NumMemSetInfer, "Number of memsets inferred");
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ValueTable Class
|
// ValueTable Class
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@@ -695,9 +699,6 @@ FunctionPass *llvm::createGVNPass() { return new GVN(); }
|
|||||||
static RegisterPass<GVN> X("gvn",
|
static RegisterPass<GVN> X("gvn",
|
||||||
"Global Value Numbering");
|
"Global Value Numbering");
|
||||||
|
|
||||||
STATISTIC(NumGVNInstr, "Number of instructions deleted");
|
|
||||||
STATISTIC(NumGVNLoad, "Number of loads deleted");
|
|
||||||
|
|
||||||
/// find_leader - Given a set and a value number, return the first
|
/// find_leader - Given a set and a value number, return the first
|
||||||
/// element of the set with that value number, or 0 if no such element
|
/// element of the set with that value number, or 0 if no such element
|
||||||
/// is present
|
/// is present
|
||||||
@@ -1039,7 +1040,7 @@ static Value *isBytewiseValue(Value *V) {
|
|||||||
/// plus the specified constant offset. For example, Ptr1 might be &A[42], and
|
/// plus the specified constant offset. For example, Ptr1 might be &A[42], and
|
||||||
/// Ptr2 might be &A[40] and Offset might be 8.
|
/// Ptr2 might be &A[40] and Offset might be 8.
|
||||||
static bool IsPointerAtOffset(Value *Ptr1, Value *Ptr2, uint64_t Offset) {
|
static bool IsPointerAtOffset(Value *Ptr1, Value *Ptr2, uint64_t Offset) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1049,7 +1050,6 @@ static bool IsPointerAtOffset(Value *Ptr1, Value *Ptr2, uint64_t Offset) {
|
|||||||
/// (currently 4) it attempts to merge them together into a memcpy/memset.
|
/// (currently 4) it attempts to merge them together into a memcpy/memset.
|
||||||
bool GVN::processStore(StoreInst *SI, SmallVectorImpl<Instruction*> &toErase) {
|
bool GVN::processStore(StoreInst *SI, SmallVectorImpl<Instruction*> &toErase) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (SI->isVolatile()) return false;
|
if (SI->isVolatile()) return false;
|
||||||
|
|
||||||
// There are two cases that are interesting for this code to handle: memcpy
|
// There are two cases that are interesting for this code to handle: memcpy
|
||||||
@@ -1072,6 +1072,7 @@ bool GVN::processStore(StoreInst *SI, SmallVectorImpl<Instruction*> &toErase) {
|
|||||||
// in practice, right now we only worry about cases where stores are
|
// in practice, right now we only worry about cases where stores are
|
||||||
// consequtive in increasing or decreasing address order.
|
// consequtive in increasing or decreasing address order.
|
||||||
uint64_t BytesSoFar = TD.getTypeStoreSize(SI->getOperand(0)->getType());
|
uint64_t BytesSoFar = TD.getTypeStoreSize(SI->getOperand(0)->getType());
|
||||||
|
uint64_t BytesFromSI = 0;
|
||||||
unsigned StartAlign = SI->getAlignment();
|
unsigned StartAlign = SI->getAlignment();
|
||||||
Value *StartPtr = SI->getPointerOperand();
|
Value *StartPtr = SI->getPointerOperand();
|
||||||
SmallVector<StoreInst*, 16> Stores;
|
SmallVector<StoreInst*, 16> Stores;
|
||||||
@@ -1086,6 +1087,9 @@ bool GVN::processStore(StoreInst *SI, SmallVectorImpl<Instruction*> &toErase) {
|
|||||||
if (AA.getModRefBehavior(CallSite::get(BI)) ==
|
if (AA.getModRefBehavior(CallSite::get(BI)) ==
|
||||||
AliasAnalysis::DoesNotAccessMemory)
|
AliasAnalysis::DoesNotAccessMemory)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// TODO: If this is a memset, try to join it in.
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else if (isa<VAArgInst>(BI) || isa<LoadInst>(BI))
|
} else if (isa<VAArgInst>(BI) || isa<LoadInst>(BI))
|
||||||
break;
|
break;
|
||||||
@@ -1110,7 +1114,7 @@ bool GVN::processStore(StoreInst *SI, SmallVectorImpl<Instruction*> &toErase) {
|
|||||||
// Okay, this extends the stored area on the end, just add to the bytes
|
// Okay, this extends the stored area on the end, just add to the bytes
|
||||||
// so far and remember this store.
|
// so far and remember this store.
|
||||||
BytesSoFar += AccessSize;
|
BytesSoFar += AccessSize;
|
||||||
Stores.push_back(SI);
|
Stores.push_back(NextStore);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1118,7 +1122,8 @@ bool GVN::processStore(StoreInst *SI, SmallVectorImpl<Instruction*> &toErase) {
|
|||||||
// Okay, the store is before the current range. Reset our start pointer
|
// Okay, the store is before the current range. Reset our start pointer
|
||||||
// and get new alignment info etc.
|
// and get new alignment info etc.
|
||||||
BytesSoFar += AccessSize;
|
BytesSoFar += AccessSize;
|
||||||
Stores.push_back(SI);
|
BytesFromSI += AccessSize;
|
||||||
|
Stores.push_back(NextStore);
|
||||||
StartPtr = ThisPointer;
|
StartPtr = ThisPointer;
|
||||||
StartAlign = NextStore->getAlignment();
|
StartAlign = NextStore->getAlignment();
|
||||||
continue;
|
continue;
|
||||||
@@ -1133,9 +1138,42 @@ bool GVN::processStore(StoreInst *SI, SmallVectorImpl<Instruction*> &toErase) {
|
|||||||
if (Stores.size() < 4)
|
if (Stores.size() < 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Otherwise, we do want to transform this! But not yet. :)
|
// Otherwise, we do want to transform this! Create a new memset. We put the
|
||||||
|
// memset right after the first store that we found in this block. This
|
||||||
|
// ensures that the caller will increment the iterator to the memset before
|
||||||
|
// it deletes all the stores.
|
||||||
|
BasicBlock::iterator InsertPt = SI; ++InsertPt;
|
||||||
|
|
||||||
return false;
|
Function *F = Intrinsic::getDeclaration(SI->getParent()->getParent()
|
||||||
|
->getParent(), Intrinsic::memset_i64);
|
||||||
|
|
||||||
|
// StartPtr may not dominate the starting point. Instead of using it, base
|
||||||
|
// the destination pointer off the input to the first store in the block.
|
||||||
|
StartPtr = SI->getPointerOperand();
|
||||||
|
|
||||||
|
// Cast the start ptr to be i8* as memset requires.
|
||||||
|
const Type *i8Ptr = PointerType::getUnqual(Type::Int8Ty);
|
||||||
|
if (StartPtr->getType() != i8Ptr)
|
||||||
|
StartPtr = new BitCastInst(StartPtr, i8Ptr, StartPtr->getNameStart(),
|
||||||
|
InsertPt);
|
||||||
|
|
||||||
|
// Offset the pointer if needed.
|
||||||
|
if (BytesFromSI)
|
||||||
|
StartPtr = new GetElementPtrInst(StartPtr, ConstantInt::get(Type::Int64Ty,
|
||||||
|
-BytesFromSI),
|
||||||
|
"ptroffset", InsertPt);
|
||||||
|
|
||||||
|
Value *Ops[] = {
|
||||||
|
StartPtr, ByteVal, // Start, value
|
||||||
|
ConstantInt::get(Type::Int64Ty, BytesSoFar), // size
|
||||||
|
ConstantInt::get(Type::Int32Ty, StartAlign) // align
|
||||||
|
};
|
||||||
|
new CallInst(F, Ops, Ops+4, "", InsertPt);
|
||||||
|
|
||||||
|
toErase.append(Stores.begin(), Stores.end());
|
||||||
|
|
||||||
|
++NumMemSetInfer;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user