mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-19 06:31:18 +00:00
Refactor operation equivalence checking in BBVectorize by extending Instruction::isSameOperationAs.
Maintaining this kind of checking in different places is dangerous, extending Instruction::isSameOperationAs consolidates this logic into one place. Here I've added an optional flags parameter and two flags that are important for vectorization: CompareIgnoringAlignment and CompareUsingScalarTypes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159329 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
97a759249d
commit
ec4e85e336
@ -281,6 +281,16 @@ public:
|
|||||||
/// ignores the SubclassOptionalData flags, which specify conditions
|
/// ignores the SubclassOptionalData flags, which specify conditions
|
||||||
/// under which the instruction's result is undefined.
|
/// under which the instruction's result is undefined.
|
||||||
bool isIdenticalToWhenDefined(const Instruction *I) const;
|
bool isIdenticalToWhenDefined(const Instruction *I) const;
|
||||||
|
|
||||||
|
/// When checking for operation equivalence (using isSameOperationAs) it is
|
||||||
|
/// sometimes useful to ignore certain attributes.
|
||||||
|
enum OperationEquivalenceFlags {
|
||||||
|
/// Check for equivalence ignoring load/store alignment.
|
||||||
|
CompareIgnoringAlignment = 1<<0,
|
||||||
|
/// Check for equivalence treating a type and a vector of that type
|
||||||
|
/// as equivalent.
|
||||||
|
CompareUsingScalarTypes = 1<<1
|
||||||
|
};
|
||||||
|
|
||||||
/// This function determines if the specified instruction executes the same
|
/// This function determines if the specified instruction executes the same
|
||||||
/// operation as the current one. This means that the opcodes, type, operand
|
/// operation as the current one. This means that the opcodes, type, operand
|
||||||
@ -290,7 +300,7 @@ public:
|
|||||||
/// @returns true if the specified instruction is the same operation as
|
/// @returns true if the specified instruction is the same operation as
|
||||||
/// the current one.
|
/// the current one.
|
||||||
/// @brief Determine if one instruction is the same operation as another.
|
/// @brief Determine if one instruction is the same operation as another.
|
||||||
bool isSameOperationAs(const Instruction *I) const;
|
bool isSameOperationAs(const Instruction *I, unsigned flags = 0) const;
|
||||||
|
|
||||||
/// isUsedOutsideOfBlock - Return true if there are any uses of this
|
/// isUsedOutsideOfBlock - Return true if there are any uses of this
|
||||||
/// instruction in blocks other than the specified block. Note that PHI nodes
|
/// instruction in blocks other than the specified block. Note that PHI nodes
|
||||||
|
@ -660,30 +660,9 @@ namespace {
|
|||||||
|
|
||||||
// Loads and stores can be merged if they have different alignments,
|
// Loads and stores can be merged if they have different alignments,
|
||||||
// but are otherwise the same.
|
// but are otherwise the same.
|
||||||
LoadInst *LI, *LJ;
|
if (!J->isSameOperationAs(I, Instruction::CompareIgnoringAlignment))
|
||||||
StoreInst *SI, *SJ;
|
|
||||||
if ((LI = dyn_cast<LoadInst>(I)) && (LJ = dyn_cast<LoadInst>(J))) {
|
|
||||||
if (I->getType() != J->getType())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (LI->getPointerOperand()->getType() !=
|
|
||||||
LJ->getPointerOperand()->getType() ||
|
|
||||||
LI->isVolatile() != LJ->isVolatile() ||
|
|
||||||
LI->getOrdering() != LJ->getOrdering() ||
|
|
||||||
LI->getSynchScope() != LJ->getSynchScope())
|
|
||||||
return false;
|
|
||||||
} else if ((SI = dyn_cast<StoreInst>(I)) && (SJ = dyn_cast<StoreInst>(J))) {
|
|
||||||
if (SI->getValueOperand()->getType() !=
|
|
||||||
SJ->getValueOperand()->getType() ||
|
|
||||||
SI->getPointerOperand()->getType() !=
|
|
||||||
SJ->getPointerOperand()->getType() ||
|
|
||||||
SI->isVolatile() != SJ->isVolatile() ||
|
|
||||||
SI->getOrdering() != SJ->getOrdering() ||
|
|
||||||
SI->getSynchScope() != SJ->getSynchScope())
|
|
||||||
return false;
|
|
||||||
} else if (!J->isSameOperationAs(I)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
// FIXME: handle addsub-type operations!
|
// FIXME: handle addsub-type operations!
|
||||||
|
|
||||||
if (IsSimpleLoadStore) {
|
if (IsSimpleLoadStore) {
|
||||||
|
@ -240,27 +240,38 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const {
|
|||||||
// isSameOperationAs
|
// isSameOperationAs
|
||||||
// This should be kept in sync with isEquivalentOperation in
|
// This should be kept in sync with isEquivalentOperation in
|
||||||
// lib/Transforms/IPO/MergeFunctions.cpp.
|
// lib/Transforms/IPO/MergeFunctions.cpp.
|
||||||
bool Instruction::isSameOperationAs(const Instruction *I) const {
|
bool Instruction::isSameOperationAs(const Instruction *I,
|
||||||
|
unsigned flags) const {
|
||||||
|
bool IgnoreAlignment = flags & CompareIgnoringAlignment;
|
||||||
|
bool UseScalarTypes = flags & CompareUsingScalarTypes;
|
||||||
|
|
||||||
if (getOpcode() != I->getOpcode() ||
|
if (getOpcode() != I->getOpcode() ||
|
||||||
getNumOperands() != I->getNumOperands() ||
|
getNumOperands() != I->getNumOperands() ||
|
||||||
getType() != I->getType())
|
(UseScalarTypes ?
|
||||||
|
getType()->getScalarType() != I->getType()->getScalarType() :
|
||||||
|
getType() != I->getType()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We have two instructions of identical opcode and #operands. Check to see
|
// We have two instructions of identical opcode and #operands. Check to see
|
||||||
// if all operands are the same type
|
// if all operands are the same type
|
||||||
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
|
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
|
||||||
if (getOperand(i)->getType() != I->getOperand(i)->getType())
|
if (UseScalarTypes ?
|
||||||
|
getOperand(i)->getType()->getScalarType() !=
|
||||||
|
I->getOperand(i)->getType()->getScalarType() :
|
||||||
|
getOperand(i)->getType() != I->getOperand(i)->getType())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check special state that is a part of some instructions.
|
// Check special state that is a part of some instructions.
|
||||||
if (const LoadInst *LI = dyn_cast<LoadInst>(this))
|
if (const LoadInst *LI = dyn_cast<LoadInst>(this))
|
||||||
return LI->isVolatile() == cast<LoadInst>(I)->isVolatile() &&
|
return LI->isVolatile() == cast<LoadInst>(I)->isVolatile() &&
|
||||||
LI->getAlignment() == cast<LoadInst>(I)->getAlignment() &&
|
(LI->getAlignment() == cast<LoadInst>(I)->getAlignment() ||
|
||||||
|
IgnoreAlignment) &&
|
||||||
LI->getOrdering() == cast<LoadInst>(I)->getOrdering() &&
|
LI->getOrdering() == cast<LoadInst>(I)->getOrdering() &&
|
||||||
LI->getSynchScope() == cast<LoadInst>(I)->getSynchScope();
|
LI->getSynchScope() == cast<LoadInst>(I)->getSynchScope();
|
||||||
if (const StoreInst *SI = dyn_cast<StoreInst>(this))
|
if (const StoreInst *SI = dyn_cast<StoreInst>(this))
|
||||||
return SI->isVolatile() == cast<StoreInst>(I)->isVolatile() &&
|
return SI->isVolatile() == cast<StoreInst>(I)->isVolatile() &&
|
||||||
SI->getAlignment() == cast<StoreInst>(I)->getAlignment() &&
|
(SI->getAlignment() == cast<StoreInst>(I)->getAlignment() ||
|
||||||
|
IgnoreAlignment) &&
|
||||||
SI->getOrdering() == cast<StoreInst>(I)->getOrdering() &&
|
SI->getOrdering() == cast<StoreInst>(I)->getOrdering() &&
|
||||||
SI->getSynchScope() == cast<StoreInst>(I)->getSynchScope();
|
SI->getSynchScope() == cast<StoreInst>(I)->getSynchScope();
|
||||||
if (const CmpInst *CI = dyn_cast<CmpInst>(this))
|
if (const CmpInst *CI = dyn_cast<CmpInst>(this))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user