mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-18 12:29:27 +00:00
Significant improvement: GEP used by a load or store no longer generates
a separate ADD; instead just use the indexed load/store instruction! Also, a bug fix: folding a GEP with a leading non-zero index with its predecessor was incorrect: now it only happens if the predecessor is pointing to an indexable type (aka SequentialType). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4168 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8becaedfa8
commit
cf911de3c6
@ -154,14 +154,14 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
|
|||||||
assert((*firstIdx)->getType() == Type::LongTy &&
|
assert((*firstIdx)->getType() == Type::LongTy &&
|
||||||
"INTERNAL ERROR: Structure index for a pointer type!");
|
"INTERNAL ERROR: Structure index for a pointer type!");
|
||||||
|
|
||||||
// If the last instruction had a leading non-zero index,
|
// If the last instruction had a leading non-zero index, check if the
|
||||||
// check if the current one ends with an array index. If not,
|
// current one references a sequential (i.e., indexable) type.
|
||||||
// the code is not type-safe and we would create an illegal GEP
|
// If not, the code is not type-safe and we would create an illegal GEP
|
||||||
// by folding them, so don't fold any more instructions.
|
// by folding them, so don't fold any more instructions.
|
||||||
//
|
//
|
||||||
if (lastInstHasLeadingNonZero)
|
if (lastInstHasLeadingNonZero)
|
||||||
if (firstIdx != lastIdx && (*(lastIdx-1))->getType() != Type::LongTy)
|
if (! isa<SequentialType>(gepInst->getType()->getElementType()))
|
||||||
break; // cannot fold in any preceding getElementPtr instrs.
|
break; // cannot fold in any preceding getElementPtr instrs.
|
||||||
|
|
||||||
// Check that all offsets are constant for this instruction
|
// Check that all offsets are constant for this instruction
|
||||||
for (OI = firstIdx; allConstantOffsets && OI != lastIdx; ++OI)
|
for (OI = firstIdx; allConstantOffsets && OI != lastIdx; ++OI)
|
||||||
@ -197,6 +197,56 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Function: GetGEPInstArgs
|
||||||
|
//
|
||||||
|
// Purpose:
|
||||||
|
// Helper function for GetMemInstArgs that handles the final getElementPtr
|
||||||
|
// instruction used by (or same as) the memory operation.
|
||||||
|
// Extracts the indices of the current instruction and tries to fold in
|
||||||
|
// preceding ones if all indices of the current one are constant.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Value*
|
||||||
|
GetGEPInstArgs(InstructionNode* gepNode,
|
||||||
|
vector<Value*>& idxVec,
|
||||||
|
bool& allConstantIndices)
|
||||||
|
{
|
||||||
|
allConstantIndices = true;
|
||||||
|
GetElementPtrInst* gepI = cast<GetElementPtrInst>(gepNode->getInstruction());
|
||||||
|
|
||||||
|
// Default pointer is the one from the current instruction.
|
||||||
|
Value* ptrVal = gepI->getPointerOperand();
|
||||||
|
InstrTreeNode* ptrChild = gepNode->leftChild();
|
||||||
|
|
||||||
|
// Extract the index vector of the GEP instructin.
|
||||||
|
// If all indices are constant and first index is zero, try to fold
|
||||||
|
// in preceding GEPs with all constant indices.
|
||||||
|
for (User::op_iterator OI=gepI->idx_begin(), OE=gepI->idx_end();
|
||||||
|
allConstantIndices && OI != OE; ++OI)
|
||||||
|
if (! isa<Constant>(*OI))
|
||||||
|
allConstantIndices = false; // note: this also terminates loop!
|
||||||
|
|
||||||
|
// If we have only constant indices, fold chains of constant indices
|
||||||
|
// in this and any preceding GetElemPtr instructions.
|
||||||
|
bool foldedGEPs = false;
|
||||||
|
bool leadingNonZeroIdx = gepI && ! IsZero(*gepI->idx_begin());
|
||||||
|
if (allConstantIndices)
|
||||||
|
if (Value* newPtr = FoldGetElemChain(ptrChild, idxVec, leadingNonZeroIdx))
|
||||||
|
{
|
||||||
|
ptrVal = newPtr;
|
||||||
|
foldedGEPs = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the index vector of the current instruction.
|
||||||
|
// Skip the leading [0] index if preceding GEPs were folded into this.
|
||||||
|
idxVec.insert(idxVec.end(),
|
||||||
|
gepI->idx_begin() + (foldedGEPs && !leadingNonZeroIdx),
|
||||||
|
gepI->idx_end());
|
||||||
|
|
||||||
|
return ptrVal;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Function: GetMemInstArgs
|
// Function: GetMemInstArgs
|
||||||
//
|
//
|
||||||
@ -215,11 +265,11 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
Value*
|
Value*
|
||||||
GetMemInstArgs(const InstructionNode* memInstrNode,
|
GetMemInstArgs(InstructionNode* memInstrNode,
|
||||||
vector<Value*>& idxVec,
|
vector<Value*>& idxVec,
|
||||||
bool& allConstantIndices)
|
bool& allConstantIndices)
|
||||||
{
|
{
|
||||||
allConstantIndices = true;
|
allConstantIndices = false;
|
||||||
Instruction* memInst = memInstrNode->getInstruction();
|
Instruction* memInst = memInstrNode->getInstruction();
|
||||||
assert(idxVec.size() == 0 && "Need empty vector to return indices");
|
assert(idxVec.size() == 0 && "Need empty vector to return indices");
|
||||||
|
|
||||||
@ -229,41 +279,29 @@ GetMemInstArgs(const InstructionNode* memInstrNode,
|
|||||||
InstrTreeNode* ptrChild = (memInst->getOpcode() == Instruction::Store
|
InstrTreeNode* ptrChild = (memInst->getOpcode() == Instruction::Store
|
||||||
? memInstrNode->rightChild()
|
? memInstrNode->rightChild()
|
||||||
: memInstrNode->leftChild());
|
: memInstrNode->leftChild());
|
||||||
|
|
||||||
// Default pointer is the one from the current instruction.
|
// Default pointer is the one from the current instruction.
|
||||||
Value* ptrVal = ptrChild->getValue();
|
Value* ptrVal = ptrChild->getValue();
|
||||||
|
|
||||||
// GEP is the only indexed memory instruction. Extract its index vector.
|
// Find the "last" GetElemPtr instruction: this one or the immediate child.
|
||||||
// Also, if all indices are constant and first index is zero, try to fold
|
// There will be none if this is a load or a store from a scalar pointer.
|
||||||
// in preceding GEPs with all constant indices.
|
InstructionNode* gepNode = NULL;
|
||||||
GetElementPtrInst* gepI = dyn_cast<GetElementPtrInst>(memInst);
|
if (isa<GetElementPtrInst>(memInst))
|
||||||
if (gepI)
|
gepNode = memInstrNode;
|
||||||
for (User::op_iterator OI=gepI->idx_begin(), OE=gepI->idx_end();
|
else if (isa<InstructionNode>(ptrChild) && isa<GetElementPtrInst>(ptrVal))
|
||||||
allConstantIndices && OI != OE; ++OI)
|
{ // Child of load/store is a GEP and memInst is its only use.
|
||||||
if (! isa<Constant>(*OI))
|
// Use its indices and mark it as folded.
|
||||||
allConstantIndices = false; // note: this also terminates loop!
|
gepNode = cast<InstructionNode>(ptrChild);
|
||||||
|
gepNode->markFoldedIntoParent();
|
||||||
|
}
|
||||||
|
|
||||||
// If we have only constant indices, fold chains of constant indices
|
// If there are no indices, return the current pointer.
|
||||||
// in this and any preceding GetElemPtr instructions.
|
// Else extract the pointer from the GEP and fold the indices.
|
||||||
bool foldedGEPs = false;
|
return (gepNode)? GetGEPInstArgs(gepNode, idxVec, allConstantIndices)
|
||||||
bool leadingNonZeroIdx = gepI && ! IsZero(*gepI->idx_begin());
|
: ptrVal;
|
||||||
if (allConstantIndices)
|
|
||||||
if (Value* newPtr = FoldGetElemChain(ptrChild, idxVec, leadingNonZeroIdx))
|
|
||||||
{
|
|
||||||
ptrVal = newPtr;
|
|
||||||
foldedGEPs = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the index vector of the current instruction, if any.
|
|
||||||
// Skip the leading [0] index if preceding GEPs were folded into this.
|
|
||||||
if (gepI)
|
|
||||||
idxVec.insert(idxVec.end(),
|
|
||||||
gepI->idx_begin() + (foldedGEPs && !leadingNonZeroIdx),
|
|
||||||
gepI->idx_end());
|
|
||||||
|
|
||||||
return ptrVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Function Set2OperandsFromInstr
|
// Function Set2OperandsFromInstr
|
||||||
// Function Set3OperandsFromInstr
|
// Function Set3OperandsFromInstr
|
||||||
|
@ -154,14 +154,14 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
|
|||||||
assert((*firstIdx)->getType() == Type::LongTy &&
|
assert((*firstIdx)->getType() == Type::LongTy &&
|
||||||
"INTERNAL ERROR: Structure index for a pointer type!");
|
"INTERNAL ERROR: Structure index for a pointer type!");
|
||||||
|
|
||||||
// If the last instruction had a leading non-zero index,
|
// If the last instruction had a leading non-zero index, check if the
|
||||||
// check if the current one ends with an array index. If not,
|
// current one references a sequential (i.e., indexable) type.
|
||||||
// the code is not type-safe and we would create an illegal GEP
|
// If not, the code is not type-safe and we would create an illegal GEP
|
||||||
// by folding them, so don't fold any more instructions.
|
// by folding them, so don't fold any more instructions.
|
||||||
//
|
//
|
||||||
if (lastInstHasLeadingNonZero)
|
if (lastInstHasLeadingNonZero)
|
||||||
if (firstIdx != lastIdx && (*(lastIdx-1))->getType() != Type::LongTy)
|
if (! isa<SequentialType>(gepInst->getType()->getElementType()))
|
||||||
break; // cannot fold in any preceding getElementPtr instrs.
|
break; // cannot fold in any preceding getElementPtr instrs.
|
||||||
|
|
||||||
// Check that all offsets are constant for this instruction
|
// Check that all offsets are constant for this instruction
|
||||||
for (OI = firstIdx; allConstantOffsets && OI != lastIdx; ++OI)
|
for (OI = firstIdx; allConstantOffsets && OI != lastIdx; ++OI)
|
||||||
@ -197,6 +197,56 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Function: GetGEPInstArgs
|
||||||
|
//
|
||||||
|
// Purpose:
|
||||||
|
// Helper function for GetMemInstArgs that handles the final getElementPtr
|
||||||
|
// instruction used by (or same as) the memory operation.
|
||||||
|
// Extracts the indices of the current instruction and tries to fold in
|
||||||
|
// preceding ones if all indices of the current one are constant.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Value*
|
||||||
|
GetGEPInstArgs(InstructionNode* gepNode,
|
||||||
|
vector<Value*>& idxVec,
|
||||||
|
bool& allConstantIndices)
|
||||||
|
{
|
||||||
|
allConstantIndices = true;
|
||||||
|
GetElementPtrInst* gepI = cast<GetElementPtrInst>(gepNode->getInstruction());
|
||||||
|
|
||||||
|
// Default pointer is the one from the current instruction.
|
||||||
|
Value* ptrVal = gepI->getPointerOperand();
|
||||||
|
InstrTreeNode* ptrChild = gepNode->leftChild();
|
||||||
|
|
||||||
|
// Extract the index vector of the GEP instructin.
|
||||||
|
// If all indices are constant and first index is zero, try to fold
|
||||||
|
// in preceding GEPs with all constant indices.
|
||||||
|
for (User::op_iterator OI=gepI->idx_begin(), OE=gepI->idx_end();
|
||||||
|
allConstantIndices && OI != OE; ++OI)
|
||||||
|
if (! isa<Constant>(*OI))
|
||||||
|
allConstantIndices = false; // note: this also terminates loop!
|
||||||
|
|
||||||
|
// If we have only constant indices, fold chains of constant indices
|
||||||
|
// in this and any preceding GetElemPtr instructions.
|
||||||
|
bool foldedGEPs = false;
|
||||||
|
bool leadingNonZeroIdx = gepI && ! IsZero(*gepI->idx_begin());
|
||||||
|
if (allConstantIndices)
|
||||||
|
if (Value* newPtr = FoldGetElemChain(ptrChild, idxVec, leadingNonZeroIdx))
|
||||||
|
{
|
||||||
|
ptrVal = newPtr;
|
||||||
|
foldedGEPs = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the index vector of the current instruction.
|
||||||
|
// Skip the leading [0] index if preceding GEPs were folded into this.
|
||||||
|
idxVec.insert(idxVec.end(),
|
||||||
|
gepI->idx_begin() + (foldedGEPs && !leadingNonZeroIdx),
|
||||||
|
gepI->idx_end());
|
||||||
|
|
||||||
|
return ptrVal;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Function: GetMemInstArgs
|
// Function: GetMemInstArgs
|
||||||
//
|
//
|
||||||
@ -215,11 +265,11 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
Value*
|
Value*
|
||||||
GetMemInstArgs(const InstructionNode* memInstrNode,
|
GetMemInstArgs(InstructionNode* memInstrNode,
|
||||||
vector<Value*>& idxVec,
|
vector<Value*>& idxVec,
|
||||||
bool& allConstantIndices)
|
bool& allConstantIndices)
|
||||||
{
|
{
|
||||||
allConstantIndices = true;
|
allConstantIndices = false;
|
||||||
Instruction* memInst = memInstrNode->getInstruction();
|
Instruction* memInst = memInstrNode->getInstruction();
|
||||||
assert(idxVec.size() == 0 && "Need empty vector to return indices");
|
assert(idxVec.size() == 0 && "Need empty vector to return indices");
|
||||||
|
|
||||||
@ -229,41 +279,29 @@ GetMemInstArgs(const InstructionNode* memInstrNode,
|
|||||||
InstrTreeNode* ptrChild = (memInst->getOpcode() == Instruction::Store
|
InstrTreeNode* ptrChild = (memInst->getOpcode() == Instruction::Store
|
||||||
? memInstrNode->rightChild()
|
? memInstrNode->rightChild()
|
||||||
: memInstrNode->leftChild());
|
: memInstrNode->leftChild());
|
||||||
|
|
||||||
// Default pointer is the one from the current instruction.
|
// Default pointer is the one from the current instruction.
|
||||||
Value* ptrVal = ptrChild->getValue();
|
Value* ptrVal = ptrChild->getValue();
|
||||||
|
|
||||||
// GEP is the only indexed memory instruction. Extract its index vector.
|
// Find the "last" GetElemPtr instruction: this one or the immediate child.
|
||||||
// Also, if all indices are constant and first index is zero, try to fold
|
// There will be none if this is a load or a store from a scalar pointer.
|
||||||
// in preceding GEPs with all constant indices.
|
InstructionNode* gepNode = NULL;
|
||||||
GetElementPtrInst* gepI = dyn_cast<GetElementPtrInst>(memInst);
|
if (isa<GetElementPtrInst>(memInst))
|
||||||
if (gepI)
|
gepNode = memInstrNode;
|
||||||
for (User::op_iterator OI=gepI->idx_begin(), OE=gepI->idx_end();
|
else if (isa<InstructionNode>(ptrChild) && isa<GetElementPtrInst>(ptrVal))
|
||||||
allConstantIndices && OI != OE; ++OI)
|
{ // Child of load/store is a GEP and memInst is its only use.
|
||||||
if (! isa<Constant>(*OI))
|
// Use its indices and mark it as folded.
|
||||||
allConstantIndices = false; // note: this also terminates loop!
|
gepNode = cast<InstructionNode>(ptrChild);
|
||||||
|
gepNode->markFoldedIntoParent();
|
||||||
|
}
|
||||||
|
|
||||||
// If we have only constant indices, fold chains of constant indices
|
// If there are no indices, return the current pointer.
|
||||||
// in this and any preceding GetElemPtr instructions.
|
// Else extract the pointer from the GEP and fold the indices.
|
||||||
bool foldedGEPs = false;
|
return (gepNode)? GetGEPInstArgs(gepNode, idxVec, allConstantIndices)
|
||||||
bool leadingNonZeroIdx = gepI && ! IsZero(*gepI->idx_begin());
|
: ptrVal;
|
||||||
if (allConstantIndices)
|
|
||||||
if (Value* newPtr = FoldGetElemChain(ptrChild, idxVec, leadingNonZeroIdx))
|
|
||||||
{
|
|
||||||
ptrVal = newPtr;
|
|
||||||
foldedGEPs = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the index vector of the current instruction, if any.
|
|
||||||
// Skip the leading [0] index if preceding GEPs were folded into this.
|
|
||||||
if (gepI)
|
|
||||||
idxVec.insert(idxVec.end(),
|
|
||||||
gepI->idx_begin() + (foldedGEPs && !leadingNonZeroIdx),
|
|
||||||
gepI->idx_end());
|
|
||||||
|
|
||||||
return ptrVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Function Set2OperandsFromInstr
|
// Function Set2OperandsFromInstr
|
||||||
// Function Set3OperandsFromInstr
|
// Function Set3OperandsFromInstr
|
||||||
|
Loading…
Reference in New Issue
Block a user