mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-23 05:29:23 +00:00
MergeFunctions Pass, introduced total ordering among operations.
Patch replaces old isEquivalentOperation implementation, and changes type of comparison result from bool (equal or not) to {-1, 0, 1} (less, equal, greater). This patch belongs to patch series that improves MergeFunctions performance time from O(N*N) to O(N*log(N)). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208973 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e4dfc196e4
commit
0885a28635
@ -307,8 +307,32 @@ private:
|
|||||||
/// Compare two Instructions for equivalence, similar to
|
/// Compare two Instructions for equivalence, similar to
|
||||||
/// Instruction::isSameOperationAs but with modifications to the type
|
/// Instruction::isSameOperationAs but with modifications to the type
|
||||||
/// comparison.
|
/// comparison.
|
||||||
|
/// Stages are listed in "most significant stage first" order:
|
||||||
|
/// On each stage below, we do comparison between some left and right
|
||||||
|
/// operation parts. If parts are non-equal, we assign parts comparison
|
||||||
|
/// result to the operation comparison result and exit from method.
|
||||||
|
/// Otherwise we proceed to the next stage.
|
||||||
|
/// Stages:
|
||||||
|
/// 1. Operations opcodes. Compared as numbers.
|
||||||
|
/// 2. Number of operands.
|
||||||
|
/// 3. Operation types. Compared with cmpType method.
|
||||||
|
/// 4. Compare operation subclass optional data as stream of bytes:
|
||||||
|
/// just convert it to integers and call cmpNumbers.
|
||||||
|
/// 5. Compare in operation operand types with cmpType in
|
||||||
|
/// most significant operand first order.
|
||||||
|
/// 6. Last stage. Check operations for some specific attributes.
|
||||||
|
/// For example, for Load it would be:
|
||||||
|
/// 6.1.Load: volatile (as boolean flag)
|
||||||
|
/// 6.2.Load: alignment (as integer numbers)
|
||||||
|
/// 6.3.Load: synch-scope (as integer numbers)
|
||||||
|
/// On this stage its better to see the code, since its not more than 10-15
|
||||||
|
/// strings for particular instruction, and could change sometimes.
|
||||||
|
int cmpOperation(const Instruction *L, const Instruction *R) const;
|
||||||
|
|
||||||
bool isEquivalentOperation(const Instruction *I1,
|
bool isEquivalentOperation(const Instruction *I1,
|
||||||
const Instruction *I2) const;
|
const Instruction *I2) const {
|
||||||
|
return cmpOperation(I1, I2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// Compare two GEPs for equivalent pointer arithmetic.
|
/// Compare two GEPs for equivalent pointer arithmetic.
|
||||||
bool isEquivalentGEP(const GEPOperator *GEP1, const GEPOperator *GEP2);
|
bool isEquivalentGEP(const GEPOperator *GEP1, const GEPOperator *GEP2);
|
||||||
@ -711,65 +735,126 @@ int FunctionComparator::cmpType(Type *TyL, Type *TyR) const {
|
|||||||
// Determine whether the two operations are the same except that pointer-to-A
|
// Determine whether the two operations are the same except that pointer-to-A
|
||||||
// and pointer-to-B are equivalent. This should be kept in sync with
|
// and pointer-to-B are equivalent. This should be kept in sync with
|
||||||
// Instruction::isSameOperationAs.
|
// Instruction::isSameOperationAs.
|
||||||
bool FunctionComparator::isEquivalentOperation(const Instruction *I1,
|
// Read method declaration comments for more details.
|
||||||
const Instruction *I2) const {
|
int FunctionComparator::cmpOperation(const Instruction *L,
|
||||||
|
const Instruction *R) const {
|
||||||
// Differences from Instruction::isSameOperationAs:
|
// Differences from Instruction::isSameOperationAs:
|
||||||
// * replace type comparison with calls to isEquivalentType.
|
// * replace type comparison with calls to isEquivalentType.
|
||||||
// * we test for I->hasSameSubclassOptionalData (nuw/nsw/tail) at the top
|
// * we test for I->hasSameSubclassOptionalData (nuw/nsw/tail) at the top
|
||||||
// * because of the above, we don't test for the tail bit on calls later on
|
// * because of the above, we don't test for the tail bit on calls later on
|
||||||
if (I1->getOpcode() != I2->getOpcode() ||
|
if (int Res = cmpNumbers(L->getOpcode(), R->getOpcode()))
|
||||||
I1->getNumOperands() != I2->getNumOperands() ||
|
return Res;
|
||||||
!isEquivalentType(I1->getType(), I2->getType()) ||
|
|
||||||
!I1->hasSameSubclassOptionalData(I2))
|
if (int Res = cmpNumbers(L->getNumOperands(), R->getNumOperands()))
|
||||||
return false;
|
return Res;
|
||||||
|
|
||||||
|
if (int Res = cmpType(L->getType(), R->getType()))
|
||||||
|
return Res;
|
||||||
|
|
||||||
|
if (int Res = cmpNumbers(L->getRawSubclassOptionalData(),
|
||||||
|
R->getRawSubclassOptionalData()))
|
||||||
|
return Res;
|
||||||
|
|
||||||
// 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 = I1->getNumOperands(); i != e; ++i)
|
for (unsigned i = 0, e = L->getNumOperands(); i != e; ++i) {
|
||||||
if (!isEquivalentType(I1->getOperand(i)->getType(),
|
if (int Res =
|
||||||
I2->getOperand(i)->getType()))
|
cmpType(L->getOperand(i)->getType(), R->getOperand(i)->getType()))
|
||||||
return false;
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
// 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>(I1))
|
if (const LoadInst *LI = dyn_cast<LoadInst>(L)) {
|
||||||
return LI->isVolatile() == cast<LoadInst>(I2)->isVolatile() &&
|
if (int Res = cmpNumbers(LI->isVolatile(), cast<LoadInst>(R)->isVolatile()))
|
||||||
LI->getAlignment() == cast<LoadInst>(I2)->getAlignment() &&
|
return Res;
|
||||||
LI->getOrdering() == cast<LoadInst>(I2)->getOrdering() &&
|
if (int Res =
|
||||||
LI->getSynchScope() == cast<LoadInst>(I2)->getSynchScope();
|
cmpNumbers(LI->getAlignment(), cast<LoadInst>(R)->getAlignment()))
|
||||||
if (const StoreInst *SI = dyn_cast<StoreInst>(I1))
|
return Res;
|
||||||
return SI->isVolatile() == cast<StoreInst>(I2)->isVolatile() &&
|
if (int Res =
|
||||||
SI->getAlignment() == cast<StoreInst>(I2)->getAlignment() &&
|
cmpNumbers(LI->getOrdering(), cast<LoadInst>(R)->getOrdering()))
|
||||||
SI->getOrdering() == cast<StoreInst>(I2)->getOrdering() &&
|
return Res;
|
||||||
SI->getSynchScope() == cast<StoreInst>(I2)->getSynchScope();
|
return cmpNumbers(LI->getSynchScope(), cast<LoadInst>(R)->getSynchScope());
|
||||||
if (const CmpInst *CI = dyn_cast<CmpInst>(I1))
|
}
|
||||||
return CI->getPredicate() == cast<CmpInst>(I2)->getPredicate();
|
if (const StoreInst *SI = dyn_cast<StoreInst>(L)) {
|
||||||
if (const CallInst *CI = dyn_cast<CallInst>(I1))
|
if (int Res =
|
||||||
return CI->getCallingConv() == cast<CallInst>(I2)->getCallingConv() &&
|
cmpNumbers(SI->isVolatile(), cast<StoreInst>(R)->isVolatile()))
|
||||||
CI->getAttributes() == cast<CallInst>(I2)->getAttributes();
|
return Res;
|
||||||
if (const InvokeInst *CI = dyn_cast<InvokeInst>(I1))
|
if (int Res =
|
||||||
return CI->getCallingConv() == cast<InvokeInst>(I2)->getCallingConv() &&
|
cmpNumbers(SI->getAlignment(), cast<StoreInst>(R)->getAlignment()))
|
||||||
CI->getAttributes() == cast<InvokeInst>(I2)->getAttributes();
|
return Res;
|
||||||
if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(I1))
|
if (int Res =
|
||||||
return IVI->getIndices() == cast<InsertValueInst>(I2)->getIndices();
|
cmpNumbers(SI->getOrdering(), cast<StoreInst>(R)->getOrdering()))
|
||||||
if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(I1))
|
return Res;
|
||||||
return EVI->getIndices() == cast<ExtractValueInst>(I2)->getIndices();
|
return cmpNumbers(SI->getSynchScope(), cast<StoreInst>(R)->getSynchScope());
|
||||||
if (const FenceInst *FI = dyn_cast<FenceInst>(I1))
|
}
|
||||||
return FI->getOrdering() == cast<FenceInst>(I2)->getOrdering() &&
|
if (const CmpInst *CI = dyn_cast<CmpInst>(L))
|
||||||
FI->getSynchScope() == cast<FenceInst>(I2)->getSynchScope();
|
return cmpNumbers(CI->getPredicate(), cast<CmpInst>(R)->getPredicate());
|
||||||
if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(I1))
|
if (const CallInst *CI = dyn_cast<CallInst>(L)) {
|
||||||
return CXI->isVolatile() == cast<AtomicCmpXchgInst>(I2)->isVolatile() &&
|
if (int Res = cmpNumbers(CI->getCallingConv(),
|
||||||
CXI->getSuccessOrdering() ==
|
cast<CallInst>(R)->getCallingConv()))
|
||||||
cast<AtomicCmpXchgInst>(I2)->getSuccessOrdering() &&
|
return Res;
|
||||||
CXI->getFailureOrdering() ==
|
return cmpAttrs(CI->getAttributes(), cast<CallInst>(R)->getAttributes());
|
||||||
cast<AtomicCmpXchgInst>(I2)->getFailureOrdering() &&
|
}
|
||||||
CXI->getSynchScope() == cast<AtomicCmpXchgInst>(I2)->getSynchScope();
|
if (const InvokeInst *CI = dyn_cast<InvokeInst>(L)) {
|
||||||
if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I1))
|
if (int Res = cmpNumbers(CI->getCallingConv(),
|
||||||
return RMWI->getOperation() == cast<AtomicRMWInst>(I2)->getOperation() &&
|
cast<InvokeInst>(R)->getCallingConv()))
|
||||||
RMWI->isVolatile() == cast<AtomicRMWInst>(I2)->isVolatile() &&
|
return Res;
|
||||||
RMWI->getOrdering() == cast<AtomicRMWInst>(I2)->getOrdering() &&
|
return cmpAttrs(CI->getAttributes(), cast<InvokeInst>(R)->getAttributes());
|
||||||
RMWI->getSynchScope() == cast<AtomicRMWInst>(I2)->getSynchScope();
|
}
|
||||||
|
if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(L)) {
|
||||||
|
ArrayRef<unsigned> LIndices = IVI->getIndices();
|
||||||
|
ArrayRef<unsigned> RIndices = cast<InsertValueInst>(R)->getIndices();
|
||||||
|
if (int Res = cmpNumbers(LIndices.size(), RIndices.size()))
|
||||||
|
return Res;
|
||||||
|
for (size_t i = 0, e = LIndices.size(); i != e; ++i) {
|
||||||
|
if (int Res = cmpNumbers(LIndices[i], RIndices[i]))
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(L)) {
|
||||||
|
ArrayRef<unsigned> LIndices = EVI->getIndices();
|
||||||
|
ArrayRef<unsigned> RIndices = cast<ExtractValueInst>(R)->getIndices();
|
||||||
|
if (int Res = cmpNumbers(LIndices.size(), RIndices.size()))
|
||||||
|
return Res;
|
||||||
|
for (size_t i = 0, e = LIndices.size(); i != e; ++i) {
|
||||||
|
if (int Res = cmpNumbers(LIndices[i], RIndices[i]))
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (const FenceInst *FI = dyn_cast<FenceInst>(L)) {
|
||||||
|
if (int Res =
|
||||||
|
cmpNumbers(FI->getOrdering(), cast<FenceInst>(R)->getOrdering()))
|
||||||
|
return Res;
|
||||||
|
return cmpNumbers(FI->getSynchScope(), cast<FenceInst>(R)->getSynchScope());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(L)) {
|
||||||
|
if (int Res = cmpNumbers(CXI->isVolatile(),
|
||||||
|
cast<AtomicCmpXchgInst>(R)->isVolatile()))
|
||||||
|
return Res;
|
||||||
|
if (int Res = cmpNumbers(CXI->getSuccessOrdering(),
|
||||||
|
cast<AtomicCmpXchgInst>(R)->getSuccessOrdering()))
|
||||||
|
return Res;
|
||||||
|
if (int Res = cmpNumbers(CXI->getFailureOrdering(),
|
||||||
|
cast<AtomicCmpXchgInst>(R)->getFailureOrdering()))
|
||||||
|
return Res;
|
||||||
|
return cmpNumbers(CXI->getSynchScope(),
|
||||||
|
cast<AtomicCmpXchgInst>(R)->getSynchScope());
|
||||||
|
}
|
||||||
|
if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(L)) {
|
||||||
|
if (int Res = cmpNumbers(RMWI->getOperation(),
|
||||||
|
cast<AtomicRMWInst>(R)->getOperation()))
|
||||||
|
return Res;
|
||||||
|
if (int Res = cmpNumbers(RMWI->isVolatile(),
|
||||||
|
cast<AtomicRMWInst>(R)->isVolatile()))
|
||||||
|
return Res;
|
||||||
|
if (int Res = cmpNumbers(RMWI->getOrdering(),
|
||||||
|
cast<AtomicRMWInst>(R)->getOrdering()))
|
||||||
|
return Res;
|
||||||
|
return cmpNumbers(RMWI->getSynchScope(),
|
||||||
|
cast<AtomicRMWInst>(R)->getSynchScope());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine whether two GEP operations perform the same underlying arithmetic.
|
// Determine whether two GEP operations perform the same underlying arithmetic.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user