mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-12 13:38:21 +00:00
Eliminated the MemAccessInst class, folding contents into GEP class.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3487 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -127,70 +127,6 @@ struct FreeInst : public Instruction {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// MemAccessInst Class
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// MemAccessInst - Common base class of GetElementPtrInst...
|
|
||||||
//
|
|
||||||
class MemAccessInst : public Instruction {
|
|
||||||
protected:
|
|
||||||
inline MemAccessInst(const Type *Ty, unsigned Opcode,
|
|
||||||
const std::string &Nam = "")
|
|
||||||
: Instruction(Ty, Opcode, Nam) {}
|
|
||||||
public:
|
|
||||||
// getIndexedType - Returns the type of the element that would be loaded with
|
|
||||||
// a load instruction with the specified parameters.
|
|
||||||
//
|
|
||||||
// A null type is returned if the indices are invalid for the specified
|
|
||||||
// pointer type.
|
|
||||||
//
|
|
||||||
static const Type *getIndexedType(const Type *Ptr,
|
|
||||||
const std::vector<Value*> &Indices,
|
|
||||||
bool AllowStructLeaf = false);
|
|
||||||
|
|
||||||
inline op_iterator idx_begin() {
|
|
||||||
return op_begin()+getFirstIndexOperandNumber();
|
|
||||||
}
|
|
||||||
inline const_op_iterator idx_begin() const {
|
|
||||||
return op_begin()+getFirstIndexOperandNumber();
|
|
||||||
}
|
|
||||||
inline op_iterator idx_end() { return op_end(); }
|
|
||||||
inline const_op_iterator idx_end() const { return op_end(); }
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<Value*> copyIndices() const {
|
|
||||||
return std::vector<Value*>(idx_begin(), idx_end());
|
|
||||||
}
|
|
||||||
|
|
||||||
Value *getPointerOperand() {
|
|
||||||
return getOperand(getFirstIndexOperandNumber()-1);
|
|
||||||
}
|
|
||||||
const Value *getPointerOperand() const {
|
|
||||||
return getOperand(getFirstIndexOperandNumber()-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual unsigned getFirstIndexOperandNumber() const = 0;
|
|
||||||
|
|
||||||
inline unsigned getNumIndices() const { // Note: always non-negative
|
|
||||||
return (getNumOperands() - getFirstIndexOperandNumber());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool hasIndices() const {
|
|
||||||
return getNumIndices() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
||||||
static inline bool classof(const MemAccessInst *) { return true; }
|
|
||||||
static inline bool classof(const Instruction *I) {
|
|
||||||
return I->getOpcode() == GetElementPtr;
|
|
||||||
}
|
|
||||||
static inline bool classof(const Value *V) {
|
|
||||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// LoadInst Class
|
// LoadInst Class
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -253,9 +189,9 @@ public:
|
|||||||
// GetElementPtrInst Class
|
// GetElementPtrInst Class
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
class GetElementPtrInst : public MemAccessInst {
|
class GetElementPtrInst : public Instruction {
|
||||||
GetElementPtrInst(const GetElementPtrInst &EPI)
|
GetElementPtrInst(const GetElementPtrInst &EPI)
|
||||||
: MemAccessInst((Type*)EPI.getType(), GetElementPtr) {
|
: Instruction((Type*)EPI.getType(), GetElementPtr) {
|
||||||
Operands.reserve(EPI.Operands.size());
|
Operands.reserve(EPI.Operands.size());
|
||||||
for (unsigned i = 0, E = EPI.Operands.size(); i != E; ++i)
|
for (unsigned i = 0, E = EPI.Operands.size(); i != E; ++i)
|
||||||
Operands.push_back(Use(EPI.Operands[i], this));
|
Operands.push_back(Use(EPI.Operands[i], this));
|
||||||
@ -264,13 +200,46 @@ public:
|
|||||||
GetElementPtrInst(Value *Ptr, const std::vector<Value*> &Idx,
|
GetElementPtrInst(Value *Ptr, const std::vector<Value*> &Idx,
|
||||||
const std::string &Name = "");
|
const std::string &Name = "");
|
||||||
virtual Instruction *clone() const { return new GetElementPtrInst(*this); }
|
virtual Instruction *clone() const { return new GetElementPtrInst(*this); }
|
||||||
virtual unsigned getFirstIndexOperandNumber() const { return 1; }
|
|
||||||
|
|
||||||
// getType - Overload to return most specific pointer type...
|
// getType - Overload to return most specific pointer type...
|
||||||
inline const PointerType *getType() const {
|
inline const PointerType *getType() const {
|
||||||
return (PointerType*)Instruction::getType();
|
return (PointerType*)Instruction::getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getIndexedType - Returns the type of the element that would be loaded with
|
||||||
|
/// a load instruction with the specified parameters.
|
||||||
|
///
|
||||||
|
/// A null type is returned if the indices are invalid for the specified
|
||||||
|
/// pointer type.
|
||||||
|
///
|
||||||
|
static const Type *getIndexedType(const Type *Ptr,
|
||||||
|
const std::vector<Value*> &Indices,
|
||||||
|
bool AllowStructLeaf = false);
|
||||||
|
|
||||||
|
inline op_iterator idx_begin() {
|
||||||
|
return op_begin()+1;
|
||||||
|
}
|
||||||
|
inline const_op_iterator idx_begin() const {
|
||||||
|
return op_begin()+1;
|
||||||
|
}
|
||||||
|
inline op_iterator idx_end() { return op_end(); }
|
||||||
|
inline const_op_iterator idx_end() const { return op_end(); }
|
||||||
|
|
||||||
|
Value *getPointerOperand() {
|
||||||
|
return getOperand(0);
|
||||||
|
}
|
||||||
|
const Value *getPointerOperand() const {
|
||||||
|
return getOperand(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned getNumIndices() const { // Note: always non-negative
|
||||||
|
return getNumOperands() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool hasIndices() const {
|
||||||
|
return getNumOperands() > 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||||
static inline bool classof(const GetElementPtrInst *) { return true; }
|
static inline bool classof(const GetElementPtrInst *) { return true; }
|
||||||
static inline bool classof(const Instruction *I) {
|
static inline bool classof(const Instruction *I) {
|
||||||
|
@ -363,7 +363,7 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
|
|||||||
Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2));
|
Idx.push_back(V = getValue(TopTy->getIndexType(), Raw.Arg2));
|
||||||
if (!V) return true;
|
if (!V) return true;
|
||||||
|
|
||||||
const Type *ETy = MemAccessInst::getIndexedType(TopTy, Idx, true);
|
const Type *ETy = GetElementPtrInst::getIndexedType(TopTy, Idx, true);
|
||||||
const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy);
|
const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy);
|
||||||
if (!ElTy) return true;
|
if (!ElTy) return true;
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
|
|||||||
|
|
||||||
vector<unsigned> &args = *Raw.VarArgs;
|
vector<unsigned> &args = *Raw.VarArgs;
|
||||||
for (unsigned i = 0, E = args.size(); i != E; ++i) {
|
for (unsigned i = 0, E = args.size(); i != E; ++i) {
|
||||||
const Type *ETy = MemAccessInst::getIndexedType(Raw.Ty, Idx, true);
|
const Type *ETy = GetElementPtrInst::getIndexedType(Raw.Ty, Idx, true);
|
||||||
const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy);
|
const CompositeType *ElTy = dyn_cast_or_null<CompositeType>(ETy);
|
||||||
if (!ElTy) return true;
|
if (!ElTy) return true;
|
||||||
Idx.push_back(V = getValue(ElTy->getIndexType(), args[i]));
|
Idx.push_back(V = getValue(ElTy->getIndexType(), args[i]));
|
||||||
@ -393,7 +393,7 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
|
|||||||
if (!Idx.empty()) {
|
if (!Idx.empty()) {
|
||||||
cerr << "WARNING: Bytecode contains load instruction with indices. "
|
cerr << "WARNING: Bytecode contains load instruction with indices. "
|
||||||
<< "Replacing with getelementptr/load pair\n";
|
<< "Replacing with getelementptr/load pair\n";
|
||||||
assert(MemAccessInst::getIndexedType(Raw.Ty, Idx) &&
|
assert(GetElementPtrInst::getIndexedType(Raw.Ty, Idx) &&
|
||||||
"Bad indices for Load!");
|
"Bad indices for Load!");
|
||||||
Src = new GetElementPtrInst(Src, Idx);
|
Src = new GetElementPtrInst(Src, Idx);
|
||||||
// FIXME: Remove this compatibility code and the BB parameter to this
|
// FIXME: Remove this compatibility code and the BB parameter to this
|
||||||
@ -429,7 +429,7 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
|
|||||||
Idx.push_back(V = getValue(ElTy->getIndexType(), args[i]));
|
Idx.push_back(V = getValue(ElTy->getIndexType(), args[i]));
|
||||||
if (!V) return true;
|
if (!V) return true;
|
||||||
|
|
||||||
const Type *ETy = MemAccessInst::getIndexedType(Raw.Ty, Idx, true);
|
const Type *ETy = GetElementPtrInst::getIndexedType(Raw.Ty, Idx, true);
|
||||||
ElTy = dyn_cast_or_null<CompositeType>(ETy);
|
ElTy = dyn_cast_or_null<CompositeType>(ETy);
|
||||||
}
|
}
|
||||||
if (i != E)
|
if (i != E)
|
||||||
|
@ -67,11 +67,10 @@ InstructionNode::InstructionNode(Instruction* I)
|
|||||||
{
|
{
|
||||||
opLabel = AllocaN; // Alloca(ptr, N) operation
|
opLabel = AllocaN; // Alloca(ptr, N) operation
|
||||||
}
|
}
|
||||||
else if ((opLabel == Instruction::Load ||
|
else if (opLabel == Instruction::GetElementPtr &&
|
||||||
opLabel == Instruction::GetElementPtr) &&
|
cast<GetElementPtrInst>(I)->hasIndices())
|
||||||
cast<MemAccessInst>(I)->hasIndices())
|
|
||||||
{
|
{
|
||||||
opLabel = opLabel + 100; // load/getElem with index vector
|
opLabel = opLabel + 100; // getElem with index vector
|
||||||
}
|
}
|
||||||
else if (opLabel == Instruction::Xor &&
|
else if (opLabel == Instruction::Xor &&
|
||||||
BinaryOperator::isNot(I))
|
BinaryOperator::isNot(I))
|
||||||
|
@ -111,8 +111,8 @@ Value*
|
|||||||
FoldGetElemChain(const InstructionNode* getElemInstrNode,
|
FoldGetElemChain(const InstructionNode* getElemInstrNode,
|
||||||
vector<Value*>& chainIdxVec)
|
vector<Value*>& chainIdxVec)
|
||||||
{
|
{
|
||||||
MemAccessInst* getElemInst = (MemAccessInst*)
|
GetElementPtrInst* getElemInst =
|
||||||
getElemInstrNode->getInstruction();
|
cast<GetElementPtrInst>(getElemInstrNode->getInstruction());
|
||||||
|
|
||||||
// Return NULL if we don't fold any instructions in.
|
// Return NULL if we don't fold any instructions in.
|
||||||
Value* ptrVal = NULL;
|
Value* ptrVal = NULL;
|
||||||
@ -128,9 +128,9 @@ FoldGetElemChain(const InstructionNode* getElemInstrNode,
|
|||||||
ptrChild->getOpLabel() == GetElemPtrIdx)
|
ptrChild->getOpLabel() == GetElemPtrIdx)
|
||||||
{
|
{
|
||||||
// Child is a GetElemPtr instruction
|
// Child is a GetElemPtr instruction
|
||||||
getElemInst = cast<MemAccessInst>(ptrChild->getValue());
|
getElemInst = cast<GetElementPtrInst>(ptrChild->getValue());
|
||||||
MemAccessInst::op_iterator OI, firstIdx = getElemInst->idx_begin();
|
User::op_iterator OI, firstIdx = getElemInst->idx_begin();
|
||||||
MemAccessInst::op_iterator lastIdx = getElemInst->idx_end();
|
User::op_iterator lastIdx = getElemInst->idx_end();
|
||||||
bool allConstantOffsets = true;
|
bool allConstantOffsets = true;
|
||||||
|
|
||||||
// Check that all offsets are constant for this instruction
|
// Check that all offsets are constant for this instruction
|
||||||
|
@ -769,14 +769,14 @@ static void executeFreeInst(FreeInst &I, ExecutionContext &SF) {
|
|||||||
// the offset that arguments ArgOff+1 -> NumArgs specify for the pointer type
|
// the offset that arguments ArgOff+1 -> NumArgs specify for the pointer type
|
||||||
// specified by argument Arg.
|
// specified by argument Arg.
|
||||||
//
|
//
|
||||||
static PointerTy getElementOffset(MemAccessInst &I, ExecutionContext &SF) {
|
static PointerTy getElementOffset(GetElementPtrInst &I, ExecutionContext &SF) {
|
||||||
assert(isa<PointerType>(I.getPointerOperand()->getType()) &&
|
assert(isa<PointerType>(I.getPointerOperand()->getType()) &&
|
||||||
"Cannot getElementOffset of a nonpointer type!");
|
"Cannot getElementOffset of a nonpointer type!");
|
||||||
|
|
||||||
PointerTy Total = 0;
|
PointerTy Total = 0;
|
||||||
const Type *Ty = I.getPointerOperand()->getType();
|
const Type *Ty = I.getPointerOperand()->getType();
|
||||||
|
|
||||||
unsigned ArgOff = I.getFirstIndexOperandNumber();
|
unsigned ArgOff = 1;
|
||||||
while (ArgOff < I.getNumOperands()) {
|
while (ArgOff < I.getNumOperands()) {
|
||||||
if (const StructType *STy = dyn_cast<StructType>(Ty)) {
|
if (const StructType *STy = dyn_cast<StructType>(Ty)) {
|
||||||
const StructLayout *SLO = TD.getStructLayout(STy);
|
const StructLayout *SLO = TD.getStructLayout(STy);
|
||||||
@ -806,8 +806,7 @@ static PointerTy getElementOffset(MemAccessInst &I, ExecutionContext &SF) {
|
|||||||
if (Idx >= AT->getNumElements() && ArrayChecksEnabled) {
|
if (Idx >= AT->getNumElements() && ArrayChecksEnabled) {
|
||||||
cerr << "Out of range memory access to element #" << Idx
|
cerr << "Out of range memory access to element #" << Idx
|
||||||
<< " of a " << AT->getNumElements() << " element array."
|
<< " of a " << AT->getNumElements() << " element array."
|
||||||
<< " Subscript #" << (ArgOff-I.getFirstIndexOperandNumber())
|
<< " Subscript #" << (ArgOff-1) << "\n";
|
||||||
<< "\n";
|
|
||||||
// Get outta here!!!
|
// Get outta here!!!
|
||||||
siglongjmp(SignalRecoverBuffer, SIGTRAP);
|
siglongjmp(SignalRecoverBuffer, SIGTRAP);
|
||||||
}
|
}
|
||||||
|
@ -67,11 +67,10 @@ InstructionNode::InstructionNode(Instruction* I)
|
|||||||
{
|
{
|
||||||
opLabel = AllocaN; // Alloca(ptr, N) operation
|
opLabel = AllocaN; // Alloca(ptr, N) operation
|
||||||
}
|
}
|
||||||
else if ((opLabel == Instruction::Load ||
|
else if (opLabel == Instruction::GetElementPtr &&
|
||||||
opLabel == Instruction::GetElementPtr) &&
|
cast<GetElementPtrInst>(I)->hasIndices())
|
||||||
cast<MemAccessInst>(I)->hasIndices())
|
|
||||||
{
|
{
|
||||||
opLabel = opLabel + 100; // load/getElem with index vector
|
opLabel = opLabel + 100; // getElem with index vector
|
||||||
}
|
}
|
||||||
else if (opLabel == Instruction::Xor &&
|
else if (opLabel == Instruction::Xor &&
|
||||||
BinaryOperator::isNot(I))
|
BinaryOperator::isNot(I))
|
||||||
|
@ -111,8 +111,8 @@ Value*
|
|||||||
FoldGetElemChain(const InstructionNode* getElemInstrNode,
|
FoldGetElemChain(const InstructionNode* getElemInstrNode,
|
||||||
vector<Value*>& chainIdxVec)
|
vector<Value*>& chainIdxVec)
|
||||||
{
|
{
|
||||||
MemAccessInst* getElemInst = (MemAccessInst*)
|
GetElementPtrInst* getElemInst =
|
||||||
getElemInstrNode->getInstruction();
|
cast<GetElementPtrInst>(getElemInstrNode->getInstruction());
|
||||||
|
|
||||||
// Return NULL if we don't fold any instructions in.
|
// Return NULL if we don't fold any instructions in.
|
||||||
Value* ptrVal = NULL;
|
Value* ptrVal = NULL;
|
||||||
@ -128,9 +128,9 @@ FoldGetElemChain(const InstructionNode* getElemInstrNode,
|
|||||||
ptrChild->getOpLabel() == GetElemPtrIdx)
|
ptrChild->getOpLabel() == GetElemPtrIdx)
|
||||||
{
|
{
|
||||||
// Child is a GetElemPtr instruction
|
// Child is a GetElemPtr instruction
|
||||||
getElemInst = cast<MemAccessInst>(ptrChild->getValue());
|
getElemInst = cast<GetElementPtrInst>(ptrChild->getValue());
|
||||||
MemAccessInst::op_iterator OI, firstIdx = getElemInst->idx_begin();
|
User::op_iterator OI, firstIdx = getElemInst->idx_begin();
|
||||||
MemAccessInst::op_iterator lastIdx = getElemInst->idx_end();
|
User::op_iterator lastIdx = getElemInst->idx_end();
|
||||||
bool allConstantOffsets = true;
|
bool allConstantOffsets = true;
|
||||||
|
|
||||||
// Check that all offsets are constant for this instruction
|
// Check that all offsets are constant for this instruction
|
||||||
|
@ -24,19 +24,6 @@ static bool OperandConvertableToType(User *U, Value *V, const Type *Ty,
|
|||||||
static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
||||||
ValueMapCache &VMC);
|
ValueMapCache &VMC);
|
||||||
|
|
||||||
// AllIndicesZero - Return true if all of the indices of the specified memory
|
|
||||||
// access instruction are zero, indicating an effectively nil offset to the
|
|
||||||
// pointer value.
|
|
||||||
//
|
|
||||||
static bool AllIndicesZero(const MemAccessInst *MAI) {
|
|
||||||
for (User::const_op_iterator S = MAI->idx_begin(), E = MAI->idx_end();
|
|
||||||
S != E; ++S)
|
|
||||||
if (!isa<Constant>(S->get()) || !cast<Constant>(S->get())->isNullValue())
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Peephole Malloc instructions: we take a look at the use chain of the
|
// Peephole Malloc instructions: we take a look at the use chain of the
|
||||||
// malloc instruction, and try to find out if the following conditions hold:
|
// malloc instruction, and try to find out if the following conditions hold:
|
||||||
// 1. The malloc is of the form: 'malloc [sbyte], uint <constant>'
|
// 1. The malloc is of the form: 'malloc [sbyte], uint <constant>'
|
||||||
@ -253,7 +240,7 @@ bool ExpressionConvertableToType(Value *V, const Type *Ty,
|
|||||||
// index array. If there are, check to see if removing them causes us to
|
// index array. If there are, check to see if removing them causes us to
|
||||||
// get to the right type...
|
// get to the right type...
|
||||||
//
|
//
|
||||||
std::vector<Value*> Indices = GEP->copyIndices();
|
std::vector<Value*> Indices(GEP->idx_begin(), GEP->idx_end());
|
||||||
const Type *BaseType = GEP->getPointerOperand()->getType();
|
const Type *BaseType = GEP->getPointerOperand()->getType();
|
||||||
const Type *ElTy = 0;
|
const Type *ElTy = 0;
|
||||||
|
|
||||||
@ -446,7 +433,7 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
|||||||
// index array. If there are, check to see if removing them causes us to
|
// index array. If there are, check to see if removing them causes us to
|
||||||
// get to the right type...
|
// get to the right type...
|
||||||
//
|
//
|
||||||
std::vector<Value*> Indices = GEP->copyIndices();
|
std::vector<Value*> Indices(GEP->idx_begin(), GEP->idx_end());
|
||||||
const Type *BaseType = GEP->getPointerOperand()->getType();
|
const Type *BaseType = GEP->getPointerOperand()->getType();
|
||||||
const Type *PVTy = cast<PointerType>(Ty)->getElementType();
|
const Type *PVTy = cast<PointerType>(Ty)->getElementType();
|
||||||
Res = 0;
|
Res = 0;
|
||||||
@ -497,8 +484,9 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
|||||||
//
|
//
|
||||||
if (Res == 0) {
|
if (Res == 0) {
|
||||||
const PointerType *NewSrcTy = PointerType::get(PVTy);
|
const PointerType *NewSrcTy = PointerType::get(PVTy);
|
||||||
|
std::vector<Value*> Indices(GEP->idx_begin(), GEP->idx_end());
|
||||||
Res = new GetElementPtrInst(Constant::getNullValue(NewSrcTy),
|
Res = new GetElementPtrInst(Constant::getNullValue(NewSrcTy),
|
||||||
GEP->copyIndices(), Name);
|
Indices, Name);
|
||||||
VMC.ExprMap[I] = Res;
|
VMC.ExprMap[I] = Res;
|
||||||
Res->setOperand(0, ConvertExpressionToType(I->getOperand(0),
|
Res->setOperand(0, ConvertExpressionToType(I->getOperand(0),
|
||||||
NewSrcTy, VMC));
|
NewSrcTy, VMC));
|
||||||
@ -1108,9 +1096,9 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
|||||||
// to getelementptr long * %reg123, uint %N
|
// to getelementptr long * %reg123, uint %N
|
||||||
// ... where the type must simply stay the same size...
|
// ... where the type must simply stay the same size...
|
||||||
//
|
//
|
||||||
Res = new GetElementPtrInst(NewVal,
|
GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
|
||||||
cast<GetElementPtrInst>(I)->copyIndices(),
|
std::vector<Value*> Indices(GEP->idx_begin(), GEP->idx_end());
|
||||||
Name);
|
Res = new GetElementPtrInst(NewVal, Indices, Name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
@ -47,8 +47,8 @@ DecomposePass::runOnBasicBlock(BasicBlock &BB)
|
|||||||
{
|
{
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
for (BasicBlock::iterator II = BB.begin(); II != BB.end(); ) {
|
for (BasicBlock::iterator II = BB.begin(); II != BB.end(); ) {
|
||||||
if (MemAccessInst *MAI = dyn_cast<MemAccessInst>(&*II))
|
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&*II))
|
||||||
if (MAI->getNumIndices() >= 2) {
|
if (GEP->getNumIndices() >= 2) {
|
||||||
Changed |= decomposeArrayRef(II); // always modifies II
|
Changed |= decomposeArrayRef(II); // always modifies II
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ IsZero(Value* idx)
|
|||||||
return (isa<ConstantInt>(idx) && cast<ConstantInt>(idx)->isNullValue());
|
return (isa<ConstantInt>(idx) && cast<ConstantInt>(idx)->isNullValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// For any MemAccessInst with 2 or more array and structure indices:
|
// For any GetElementPtrInst with 2 or more array and structure indices:
|
||||||
//
|
//
|
||||||
// opCode CompositeType* P, [uint|ubyte] idx1, ..., [uint|ubyte] idxN
|
// opCode CompositeType* P, [uint|ubyte] idx1, ..., [uint|ubyte] idxN
|
||||||
//
|
//
|
||||||
@ -88,9 +88,9 @@ IsZero(Value* idx)
|
|||||||
bool
|
bool
|
||||||
DecomposePass::decomposeArrayRef(BasicBlock::iterator &BBI)
|
DecomposePass::decomposeArrayRef(BasicBlock::iterator &BBI)
|
||||||
{
|
{
|
||||||
MemAccessInst &MAI = cast<MemAccessInst>(*BBI);
|
GetElementPtrInst &GEP = cast<GetElementPtrInst>(*BBI);
|
||||||
BasicBlock *BB = MAI.getParent();
|
BasicBlock *BB = GEP.getParent();
|
||||||
Value *LastPtr = MAI.getPointerOperand();
|
Value *LastPtr = GEP.getPointerOperand();
|
||||||
|
|
||||||
// Remove the instruction from the stream
|
// Remove the instruction from the stream
|
||||||
BB->getInstList().remove(BBI);
|
BB->getInstList().remove(BBI);
|
||||||
@ -99,12 +99,12 @@ DecomposePass::decomposeArrayRef(BasicBlock::iterator &BBI)
|
|||||||
std::vector<Instruction*> NewInsts;
|
std::vector<Instruction*> NewInsts;
|
||||||
|
|
||||||
// Process each index except the last one.
|
// Process each index except the last one.
|
||||||
User::const_op_iterator OI = MAI.idx_begin(), OE = MAI.idx_end();
|
User::const_op_iterator OI = GEP.idx_begin(), OE = GEP.idx_end();
|
||||||
for (; OI+1 != OE; ++OI) {
|
for (; OI+1 != OE; ++OI) {
|
||||||
std::vector<Value*> Indices;
|
std::vector<Value*> Indices;
|
||||||
|
|
||||||
// If this is the first index and is 0, skip it and move on!
|
// If this is the first index and is 0, skip it and move on!
|
||||||
if (OI == MAI.idx_begin()) {
|
if (OI == GEP.idx_begin()) {
|
||||||
if (IsZero(*OI)) continue;
|
if (IsZero(*OI)) continue;
|
||||||
} else
|
} else
|
||||||
// Not the first index: include initial [0] to deref the last ptr
|
// Not the first index: include initial [0] to deref the last ptr
|
||||||
@ -127,21 +127,14 @@ DecomposePass::decomposeArrayRef(BasicBlock::iterator &BBI)
|
|||||||
Indices.push_back(Constant::getNullValue(Type::UIntTy));
|
Indices.push_back(Constant::getNullValue(Type::UIntTy));
|
||||||
Indices.push_back(*OI);
|
Indices.push_back(*OI);
|
||||||
|
|
||||||
Instruction *NewI = 0;
|
Instruction *NewI = new GetElementPtrInst(LastPtr, Indices, GEP.getName());
|
||||||
switch(MAI.getOpcode()) {
|
|
||||||
case Instruction::GetElementPtr:
|
|
||||||
NewI = new GetElementPtrInst(LastPtr, Indices, MAI.getName());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0 && "Unrecognized memory access instruction");
|
|
||||||
}
|
|
||||||
NewInsts.push_back(NewI);
|
NewInsts.push_back(NewI);
|
||||||
|
|
||||||
// Replace all uses of the old instruction with the new
|
// Replace all uses of the old instruction with the new
|
||||||
MAI.replaceAllUsesWith(NewI);
|
GEP.replaceAllUsesWith(NewI);
|
||||||
|
|
||||||
// Now delete the old instruction...
|
// Now delete the old instruction...
|
||||||
delete &MAI;
|
delete &GEP;
|
||||||
|
|
||||||
// Insert all of the new instructions...
|
// Insert all of the new instructions...
|
||||||
BB->getInstList().insert(BBI, NewInsts.begin(), NewInsts.end());
|
BB->getInstList().insert(BBI, NewInsts.begin(), NewInsts.end());
|
||||||
|
@ -183,7 +183,8 @@ private:
|
|||||||
|
|
||||||
// Instructions that cannot be folded away...
|
// Instructions that cannot be folded away...
|
||||||
void visitStoreInst (Instruction &I) { /*returns void*/ }
|
void visitStoreInst (Instruction &I) { /*returns void*/ }
|
||||||
void visitMemAccessInst (Instruction &I) { markOverdefined(&I); }
|
void visitLoadInst (Instruction &I) { markOverdefined(&I); }
|
||||||
|
void visitGetElementPtrInst(Instruction &I) { markOverdefined(&I); } // FIXME
|
||||||
void visitCallInst (Instruction &I) { markOverdefined(&I); }
|
void visitCallInst (Instruction &I) { markOverdefined(&I); }
|
||||||
void visitInvokeInst (Instruction &I) { markOverdefined(&I); }
|
void visitInvokeInst (Instruction &I) { markOverdefined(&I); }
|
||||||
void visitAllocationInst(Instruction &I) { markOverdefined(&I); }
|
void visitAllocationInst(Instruction &I) { markOverdefined(&I); }
|
||||||
|
@ -76,25 +76,11 @@ namespace {
|
|||||||
static inline bool isSafeAlloca(const AllocaInst *AI) {
|
static inline bool isSafeAlloca(const AllocaInst *AI) {
|
||||||
if (AI->isArrayAllocation()) return false;
|
if (AI->isArrayAllocation()) return false;
|
||||||
|
|
||||||
|
// Only allow direct loads and stores...
|
||||||
for (Value::use_const_iterator UI = AI->use_begin(), UE = AI->use_end();
|
for (Value::use_const_iterator UI = AI->use_begin(), UE = AI->use_end();
|
||||||
UI != UE; ++UI) { // Loop over all of the uses of the alloca
|
UI != UE; ++UI) // Loop over all of the uses of the alloca
|
||||||
|
if (!isa<LoadInst>(*UI) && !isa<StoreInst>(*UI))
|
||||||
// Only allow nonindexed memory access instructions...
|
|
||||||
if (MemAccessInst *MAI = dyn_cast<MemAccessInst>(*UI)) {
|
|
||||||
if (MAI->getPointerOperand() != (Value*)AI)
|
|
||||||
return false; // Reject stores of alloca pointer into some other loc.
|
|
||||||
|
|
||||||
if (MAI->hasIndices()) { // indexed?
|
|
||||||
// Allow the access if there is only one index and the index is
|
|
||||||
// zero.
|
|
||||||
if (*MAI->idx_begin() != Constant::getNullValue(Type::UIntTy) ||
|
|
||||||
MAI->idx_begin()+1 != MAI->idx_end())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false; // Not a load or store?
|
return false; // Not a load or store?
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -321,8 +321,9 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
||||||
const Type *ElTy = MemAccessInst::getIndexedType(GEP.getOperand(0)->getType(),
|
const Type *ElTy =
|
||||||
GEP.copyIndices(), true);
|
GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(),
|
||||||
|
std::vector<Value*>(GEP.idx_begin(), GEP.idx_end()), true);
|
||||||
Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP);
|
Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP);
|
||||||
Assert2(PointerType::get(ElTy) == GEP.getType(),
|
Assert2(PointerType::get(ElTy) == GEP.getType(),
|
||||||
"GEP is not of right type for indices!", &GEP, ElTy);
|
"GEP is not of right type for indices!", &GEP, ElTy);
|
||||||
|
@ -38,39 +38,6 @@ const Type *AllocationInst::getAllocatedType() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// MemAccessInst Implementation
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// getIndexedType - Returns the type of the element that would be loaded with
|
|
||||||
// a load instruction with the specified parameters.
|
|
||||||
//
|
|
||||||
// A null type is returned if the indices are invalid for the specified
|
|
||||||
// pointer type.
|
|
||||||
//
|
|
||||||
const Type* MemAccessInst::getIndexedType(const Type *Ptr,
|
|
||||||
const std::vector<Value*> &Idx,
|
|
||||||
bool AllowCompositeLeaf) {
|
|
||||||
if (!isa<PointerType>(Ptr)) return 0; // Type isn't a pointer type!
|
|
||||||
|
|
||||||
// Handle the special case of the empty set index set...
|
|
||||||
if (Idx.empty()) return cast<PointerType>(Ptr)->getElementType();
|
|
||||||
|
|
||||||
unsigned CurIDX = 0;
|
|
||||||
while (const CompositeType *CT = dyn_cast<CompositeType>(Ptr)) {
|
|
||||||
if (Idx.size() == CurIDX) {
|
|
||||||
if (AllowCompositeLeaf || CT->isFirstClassType()) return Ptr;
|
|
||||||
return 0; // Can't load a whole structure or array!?!?
|
|
||||||
}
|
|
||||||
|
|
||||||
Value *Index = Idx[CurIDX++];
|
|
||||||
if (!CT->indexValid(Index)) return 0;
|
|
||||||
Ptr = CT->getTypeAtIndex(Index);
|
|
||||||
}
|
|
||||||
return CurIDX == Idx.size() ? Ptr : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// LoadInst Implementation
|
// LoadInst Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -102,7 +69,7 @@ StoreInst::StoreInst(Value *Val, Value *Ptr)
|
|||||||
|
|
||||||
GetElementPtrInst::GetElementPtrInst(Value *Ptr, const std::vector<Value*> &Idx,
|
GetElementPtrInst::GetElementPtrInst(Value *Ptr, const std::vector<Value*> &Idx,
|
||||||
const std::string &Name)
|
const std::string &Name)
|
||||||
: MemAccessInst(PointerType::get(checkType(getIndexedType(Ptr->getType(),
|
: Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),
|
||||||
Idx, true))),
|
Idx, true))),
|
||||||
GetElementPtr, Name) {
|
GetElementPtr, Name) {
|
||||||
assert(getIndexedType(Ptr->getType(), Idx, true) && "gep operands invalid!");
|
assert(getIndexedType(Ptr->getType(), Idx, true) && "gep operands invalid!");
|
||||||
@ -113,6 +80,34 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, const std::vector<Value*> &Idx,
|
|||||||
Operands.push_back(Use(Idx[i], this));
|
Operands.push_back(Use(Idx[i], this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getIndexedType - Returns the type of the element that would be loaded with
|
||||||
|
// a load instruction with the specified parameters.
|
||||||
|
//
|
||||||
|
// A null type is returned if the indices are invalid for the specified
|
||||||
|
// pointer type.
|
||||||
|
//
|
||||||
|
const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
|
||||||
|
const std::vector<Value*> &Idx,
|
||||||
|
bool AllowCompositeLeaf) {
|
||||||
|
if (!isa<PointerType>(Ptr)) return 0; // Type isn't a pointer type!
|
||||||
|
|
||||||
|
// Handle the special case of the empty set index set...
|
||||||
|
if (Idx.empty()) return cast<PointerType>(Ptr)->getElementType();
|
||||||
|
|
||||||
|
unsigned CurIDX = 0;
|
||||||
|
while (const CompositeType *CT = dyn_cast<CompositeType>(Ptr)) {
|
||||||
|
if (Idx.size() == CurIDX) {
|
||||||
|
if (AllowCompositeLeaf || CT->isFirstClassType()) return Ptr;
|
||||||
|
return 0; // Can't load a whole structure or array!?!?
|
||||||
|
}
|
||||||
|
|
||||||
|
Value *Index = Idx[CurIDX++];
|
||||||
|
if (!CT->indexValid(Index)) return 0;
|
||||||
|
Ptr = CT->getTypeAtIndex(Index);
|
||||||
|
}
|
||||||
|
return CurIDX == Idx.size() ? Ptr : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// FreeInst Implementation
|
// FreeInst Implementation
|
||||||
|
Reference in New Issue
Block a user